View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of CosyBeans.
5    *
6    * CosyBeans is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * CosyBeans is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with CosyBeans.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.gui.adapters;
21  
22  import java.util.Map;
23  
24  import com.cosylab.gui.displayers.DataConsumer;
25  import com.cosylab.gui.displayers.DataState;
26  import com.cosylab.gui.displayers.DoubleConsumer;
27  import com.cosylab.util.CommonException;
28  
29  
30  /**
31   * <code>DataInterceptor</code> filters data that belongs to DoubleConsumer.
32   * <code>DataInterceptor</code> saves a certain amount of data (defined with
33   * timeInterval in constructor). After that time elapses average value and
34   * standard deviation are calculated. Interceptor than  updates consumer with
35   * four values: average value at the begining and end of the interval that all
36   * data belongs too, min and max value on this interval.
37   * 
38   * <p>
39   * <code>DataInterceptor</code> can be used with chart consumers when great
40   * ammount of data needs to be displayed. 
41   * </p> 
42   *
43   * @author <a href="mailto:jaka.bobnar@cosylab.com">Jaka Bobnar</a>
44   * @version $Id: DataInterceptor.java,v 1.6 2008-04-22 12:31:02 jbobnar Exp $
45   *
46   * @since VERSION
47   */
48  public class DataInterceptor implements DoubleConsumer
49  {
50  	/**
51  	 * <code>Value</code> represents a single point for the consumer. It holds
52  	 * timestamp and value of the point.
53  	 *
54  	 * @author <a href="mailto:jaka.bobnar@cosylab.com">Jaka Bobnar</a>
55  	 * @version $Id: DataInterceptor.java,v 1.6 2008-04-22 12:31:02 jbobnar Exp $
56  	 *
57  	 * @since VERSION
58  	 */
59  	class Value
60  	{
61  		double value;
62  		long timestamp;
63  
64  		/**
65  		 * Creates a new Value object.
66  		 *
67  		 * @param timestamp timestamp of the point
68  		 * @param value value of the point
69  		 */
70  		public Value(long timestamp, double value)
71  		{
72  			this.value = value;
73  			this.timestamp = timestamp;
74  		}
75  	}
76  
77  	/** Consumer that communicates with displayer. */
78  	private DoubleConsumer consumer;
79  
80  	/** Time interval that average and deviation are calculated in. */
81  	private long timeInterval;
82  	private double deviation;
83  	private double average;
84  	private int numberOfValues;
85  	private double sum;
86  	private double sumSquare;
87  	private long startTime;
88  	private long lastTime;
89  	private Value maxValue;
90  	private Value minValue;
91  	private DataState state;
92  
93  	/**
94  	 * Default constructor.
95  	 */
96  	public DataInterceptor()
97  	{
98  		this.timeInterval = 0;
99  		reset();
100 	}
101 
102 	/**
103 	 * Constructor.
104 	 *
105 	 * @param consumer consumers that sends data to displayer
106 	 * @param timeInterval time interval in millis
107 	 */
108 	public DataInterceptor(DoubleConsumer consumer, long timeInterval)
109 	{
110 		this.consumer = consumer;
111 		this.timeInterval = timeInterval;
112 		reset();
113 	}
114 
115 	/**
116 	 * Sets the time interval for calculating average and deviation.
117 	 *
118 	 * @param timeInterval
119 	 */
120 	public void setTimeInterval(long timeInterval)
121 	{
122 		this.timeInterval = timeInterval;
123 		reset();
124 	}
125 
126 	/**
127 	 * Returns the time interval set for this interceptor.
128 	 *
129 	 * @return time interval
130 	 */
131 	public long getTimeInterval()
132 	{
133 		return timeInterval;
134 	}
135 
136 	/**
137 	 * Returns the value of standard deviation for the last dispatched data.
138 	 *
139 	 * @return standard deviation
140 	 */
141 	public double getDeviation()
142 	{
143 		return deviation;
144 	}
145 
146 	/**
147 	 * Returns the average value on the interval of the last dispatched data.
148 	 *
149 	 * @return average
150 	 */
151 	public double getAverage()
152 	{
153 		return average;
154 	}
155 
156 	/* (non-Javadoc)
157 	 * @see com.cosylab.gui.displayers.DoubleConsumer#updateValue(long, double)
158 	 */
159 	public void updateValue(long timestamp, double value)
160 		throws CommonException
161 	{
162 		if (numberOfValues == 0) {
163 			startTime = timestamp;
164 			maxValue = new Value(timestamp, value);
165 			minValue = new Value(timestamp, value);
166 		}
167 
168 		sumSquare += value*value;
169 		sum += value;
170 		numberOfValues++;
171 
172 		if (timestamp > startTime + timeInterval) {
173 			lastTime = timestamp;
174 			dispatch();
175 		}
176 	}
177 
178 	private void dispatch() throws CommonException
179 	{
180 		average = sum / numberOfValues;
181 		// calculate deviation on the interval
182 		deviation = Math.sqrt(sumSquare/numberOfValues - average*average);
183 
184 		// update consumer
185 		consumer.updateValue(startTime, average);
186 		if (maxValue.timestamp <= minValue.timestamp) {
187 		    consumer.updateValue(maxValue.timestamp, maxValue.value);
188 		    consumer.updateValue(minValue.timestamp, minValue.value);
189 		} else {
190 		    consumer.updateValue(minValue.timestamp, minValue.value);
191 		    consumer.updateValue(maxValue.timestamp, maxValue.value);
192 		}
193 		consumer.updateValue(lastTime, average);
194 		
195 		reset();
196 	}
197 
198 	private void reset()
199 	{
200 		sum = 0;
201 		numberOfValues = 0;
202 		sumSquare = 0;
203 		maxValue = null;
204 		minValue = null;
205 	}
206 
207 	/**
208 	 * Sets consumer of which this <code>DataInterceptor</code> intercepts
209 	 * data.
210 	 *
211 	 * @param newConsumer
212 	 */
213 	public void setConsumer(DoubleConsumer newConsumer)
214 	{
215 		this.consumer = newConsumer;
216 		reset();
217 	}
218 
219 	/* (non-Javadoc)
220 	 * @see com.cosylab.gui.displayers.DataConsumer#getDataConsumer(java.lang.Class)
221 	 */
222 	public DataConsumer getDataConsumer(Class type)
223 	{
224 		if (type.isAssignableFrom(this.getClass())) {
225 			return this;
226 		}
227 
228 		return null;
229 	}
230 
231 	/* (non-Javadoc)
232 	 * @see com.cosylab.gui.displayers.DataConsumer#getDefaultDataConsumer()
233 	 */
234 	public DataConsumer getDefaultDataConsumer()
235 	{
236 		return this;
237 	}
238 
239 	/* (non-Javadoc)
240 	 * @see com.cosylab.gui.displayers.DataConsumer#updateDataState(com.cosylab.gui.displayers.DataState)
241 	 */
242 	public void updateDataState(DataState datastate)
243 	{
244 		this.state = datastate;
245 	}
246 
247 	/* (non-Javadoc)
248 	 * @see com.cosylab.gui.displayers.DataConsumer#setCharacteristics(java.util.Map)
249 	 */
250 	public void setCharacteristics(Map characteristics)
251 	{
252 		consumer.setCharacteristics(characteristics);
253 	}
254 
255 	/* (non-Javadoc)
256 	 * @see com.cosylab.gui.displayers.DataConsumer#getName()
257 	 */
258 	public String getName()
259 	{
260 		return consumer.getName();
261 	}
262 
263 	/* (non-Javadoc)
264 	 * @see com.cosylab.gui.displayers.DataConsumer#getSupportedCharacteristics()
265 	 */
266 	public String[] getSupportedCharacteristics()
267 	{
268 		return consumer.getSupportedCharacteristics();
269 	}
270 
271 	/* (non-Javadoc)
272 	 * @see com.cosylab.gui.displayers.DataConsumer#getSupportedConsumerTypes()
273 	 */
274 	public Class[] getSupportedConsumerTypes()
275 	{
276 		return new Class[]{ DoubleConsumer.class };
277 	}
278 }
279 
280 /* __oOo__ */