View Javadoc

1   /*
2    * Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
3    * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
4    *
5    * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
6    * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
7    * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
8    * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
9    * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
10   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
11   * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
12   * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
13   * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
14   * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
15   * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
16   * OR MODIFICATIONS.
17   * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
18   * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
19   * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
20   * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
21   */
22  
23  package de.desy.acop.transport.adapters;
24  
25  import java.beans.PropertyVetoException;
26  import java.util.ArrayList;
27  import java.util.LinkedHashMap;
28  import java.util.Map;
29  
30  import com.cosylab.gui.adapters.DataSourceJoint;
31  import com.cosylab.gui.displayers.DataConsumer;
32  import com.cosylab.gui.displayers.DataSource;
33  import com.cosylab.gui.displayers.DataState;
34  import com.cosylab.gui.displayers.DoubleSeqConsumer;
35  import com.cosylab.util.CommonException;
36  
37  /**
38   * <code>AcopDataSourceJoint</code> is an implementation of <code>DataSourceJoint</code>
39   * which combines several <code>AcopTransportDataSource</code>. DataSources are
40   * combined in the manner prescribed by the DataSourceJoint API. 
41   * <p>
42   * AcopDataSourceJoint supports only <code>com.cosylabu.gui.displayers.DoubleSeqConsumer</code>
43   * </p>
44   * @author Jaka Bobnar, Cosylab
45   *
46   */
47  public class AcopDataSourceJoint extends AcopTransportDataSource implements DataSourceJoint<AcopTransportDataSource>{
48  	
49  	private static final long serialVersionUID = 1099113487965270874L;
50  
51  	protected class DataSourceWrapper {
52  		
53  		protected AcopTransportDataSource dataSource;
54  		protected String identifier;
55  		protected double[] lastValue = null;
56  		public DataSourceWrapper(AcopTransportDataSource source, String identifier) throws PropertyVetoException {
57  			this.dataSource = source;
58  			this.identifier = identifier;
59  			source.addConsumer(new DoubleSeqConsumer() {
60  
61  				public void updateValue(long timestamp, double[] value) throws CommonException {
62  					DataSourceWrapper.this.lastValue = new double[value.length];
63  					System.arraycopy(value, 0, lastValue, 0, value.length);	
64  					updateConsumers(timestamp);
65  					
66  				}
67  
68  				@SuppressWarnings("unchecked")
69  				public DataConsumer getDataConsumer(Class type) {
70  					if (type.isAssignableFrom(DoubleSeqConsumer.class)) {
71  						return this;
72  					} 
73  					return null;
74  					
75  				}
76  
77  				public DataConsumer getDefaultDataConsumer() {
78  					// TODO Auto-generated method stub
79  					return this;
80  				}
81  
82  				public String getName() {
83  					// TODO Auto-generated method stub
84  					return null;
85  				}
86  
87  				public String[] getSupportedCharacteristics() {
88  					// TODO Auto-generated method stub
89  					return null;
90  				}
91  
92  				@SuppressWarnings("unchecked")
93  				public Class<DataConsumer>[] getSupportedConsumerTypes() {
94  					return new Class[]{DoubleSeqConsumer.class};
95  				}
96  
97  				@SuppressWarnings("unchecked")
98  				public void setCharacteristics(Map characteristics) {
99  					// TODO Auto-generated method stub
100 					
101 				}
102 
103 				public void updateDataState(DataState state) {
104 					// TODO Auto-generated method stub
105 					
106 				}
107 				
108 			});
109 		}
110 		
111 	}
112 	
113 	protected ArrayList<DataSourceWrapper> dataSources;
114 	
115 	/**
116 	 * Constructs a new AcopDataSOurceJoint object.
117 	 *
118 	 */
119 	public AcopDataSourceJoint() {
120 		super();
121 		dataSources = new ArrayList<DataSourceWrapper>();
122 	}
123 	
124 	/*
125 	 * (non-Javadoc)
126 	 * @see com.cosylab.gui.adapters.DataSourceJoint#getDataSources()
127 	 */
128 	public Map<AcopTransportDataSource, String> getDataSources() {
129 		LinkedHashMap<AcopTransportDataSource, String> map = new LinkedHashMap<AcopTransportDataSource, String>();
130 		for (DataSourceWrapper w : dataSources) {
131 			map.put(w.dataSource,w.identifier);
132 		}
133 		
134 		return map;
135 	}
136 
137 	/*
138 	 * (non-Javadoc)
139 	 * @see com.cosylab.gui.adapters.DataSourceJoint#removeDataSource(com.cosylab.gui.displayers.DataSource)
140 	 */
141 	public String removeDataSource(AcopTransportDataSource dataSource) {
142 		for (DataSourceWrapper w: dataSources) {
143 			if (w.dataSource.equals(dataSource)) {
144 				return w.identifier;
145 			}
146 		}
147 		return null;
148 	}
149 	
150 	/*
151 	 * (non-Javadoc)
152 	 * @see com.cosylab.gui.adapters.DataSourceJoint#addDataSource(com.cosylab.gui.displayers.DataSource, java.lang.String)
153 	 */
154 	public void addDataSource(AcopTransportDataSource dataSource, String operation) throws PropertyVetoException {
155 		addDataSource(dataSource, operation, dataSources.size());		
156 	}
157 	
158 	private boolean isDataSourceAccepted(AcopTransportDataSource dataSource) {
159 		Class<?>[] supported = dataSource.getAcceptableConsumerTypes();
160 		Class<?>[] existing = getAcceptableConsumerTypes();
161 		for (Class<?> ex : existing) {
162 			boolean exist = false;
163 			for (Class<?> sup : supported) {
164 				if (ex.equals(sup)) {
165 					exist = true;
166 					break;
167 				}
168 			}
169 			if (!exist) return false;
170 		}
171 		
172 		return true;
173 	}
174 
175 	/*
176 	 * (non-Javadoc)
177 	 * @see com.cosylab.gui.adapters.DataSourceJoint#addDataSource(com.cosylab.gui.displayers.DataSource, java.lang.String, int)
178 	 */
179 	public void addDataSource(AcopTransportDataSource dataSource, String operation, int index) throws PropertyVetoException {
180 		if (index > dataSources.size()) 
181 			throw new IllegalArgumentException("Invalid index. It should be less or equal " +
182 					"to " + dataSources.size() + ".");
183 		if (!isDataSourceAccepted(dataSource))
184 			throw new IllegalArgumentException("Given DataSource does not support all " +
185 					"characteristics supported by this class.");
186 		
187 		if (index == 0 || operation == null || (operation.equals(FIRST_IN_A_ROW) && index != 0)) {
188 			operation = FIRST_IN_A_ROW;
189 			if (dataSources.size() > 0)
190 				dataSources.remove(0);
191 			dataSources.add(0, new DataSourceWrapper(dataSource, operation));
192 			return;
193 		}
194 		
195 		DataSourceWrapper wrapper = new DataSourceWrapper(dataSource, operation);
196 		dataSources.add(index, wrapper);
197 	}
198 	
199 	private void updateConsumers(long timestamp) {
200 		if (dataSources.get(0).lastValue == null) return;
201 		double[] d = new double[dataSources.get(0).lastValue.length];
202 		System.arraycopy(dataSources.get(0).lastValue, 0, d, 0, d.length);
203 
204 		for (int i = 1; i < dataSources.size(); i++) {
205 			if (dataSources.get(i).lastValue == null) return;
206 			operate(d, dataSources.get(i).lastValue, dataSources.get(i).identifier);
207 		}
208 		
209 		DoubleSeqConsumer[] dsc= (DoubleSeqConsumer[])dcon.toArray();
210     	for (int i = 0; i < dsc.length; i++) {
211 			try {
212 				//System.out.println(dsc[i]);
213 				dsc[i].updateValue(timestamp,d);
214 			} catch (Exception e) {
215 				e.printStackTrace();
216 			}
217 		}
218 	}
219 	
220 	private void operate(double[] higherChain, double[] values, String operation) {
221 		if (higherChain.length != values.length) 
222 			throw new IllegalArgumentException("Array length does not match");
223 		if (operation.equals(ADD)) {
224 			for (int i = 0; i < higherChain.length; i++) {
225 				higherChain[i] += values[i];
226 			}
227 		} else if (operation.equals(SUBSTRACT)) {
228 			for (int i = 0; i < higherChain.length; i++) {
229 				higherChain[i] -= values[i];
230 			}
231 		} else if (operation.equals(MULTIPLY)) {
232 			for (int i = 0; i < higherChain.length; i++) {
233 				higherChain[i] *= values[i];
234 			}
235 		} else if (operation.equals(DIVIDE)) {
236 			for (int i = 0; i < higherChain.length; i++) {
237 				if (values[i] == 0)
238 					higherChain[i] = higherChain[i] > 0 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
239 				else if (Double.isInfinite(values[i]))
240 					higherChain[i] = 0;
241 				else if (Double.isNaN(values[i]))
242 					higherChain[i] = Double.NaN;
243 				else
244 					higherChain[i] /= values[i];				
245 			}
246 		} 
247 	}
248 	
249 	/*
250 	 * (non-Javadoc)
251 	 * @see de.desy.acop.transport.adapters.AcopTransportDataSource#addConsumer(com.cosylab.gui.displayers.DataConsumer)
252 	 */
253 	public void addConsumer(DataConsumer consumer) throws PropertyVetoException {
254 		super.addConsumer(consumer);
255 		//do not allow setting
256 		if (consumer instanceof DataSource) {
257 			((DataSource)consumer).removeConsumer(getReverseConsumer());
258 		}
259 		
260 	}	
261 }