]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.history/src/org/simantics/history/util/StreamIterator.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.history / src / org / simantics / history / util / StreamIterator.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2012 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.history.util;\r
13 \r
14 import org.simantics.databoard.Bindings;\r
15 import org.simantics.databoard.accessor.ArrayAccessor;\r
16 import org.simantics.databoard.accessor.error.AccessorException;\r
17 import org.simantics.databoard.binding.Binding;\r
18 import org.simantics.databoard.binding.RecordBinding;\r
19 import org.simantics.databoard.binding.error.BindingException;\r
20 import org.simantics.history.HistoryException;\r
21 \r
22 /**\r
23  * Stream iterator iterates sample entries in an array.\r
24  * \r
25  * Is scans the next sample and knows its time stamp.\r
26  * \r
27  * @author toni.kalajainen\r
28  */\r
29 public class StreamIterator {\r
30 \r
31         // Sample binding\r
32         RecordBinding sampleBinding;\r
33         \r
34         // Array accessor\r
35         ArrayAccessor aa;\r
36         // Array stream\r
37         Stream stream;\r
38         // From and end times of the whole stream\r
39         double from, end;\r
40         \r
41         // Current and next sample\r
42         Object current, next;\r
43 \r
44         // Utility for reading sample\r
45         ValueBand valueBand, nextValueBand;\r
46         // Start and end time of current sample\r
47         double startTime, endTime;\r
48         \r
49         int index = -1;\r
50         int size;\r
51         \r
52         public StreamIterator(ArrayAccessor aa) throws HistoryException {\r
53                 try {\r
54                         this.aa = aa;\r
55                         sampleBinding = (RecordBinding) Bindings.getBeanBinding( aa.type().componentType );\r
56                         current = sampleBinding.createDefault();\r
57                         next = sampleBinding.createDefault();\r
58                         valueBand = new ValueBand(sampleBinding, current);\r
59                         nextValueBand = new ValueBand(sampleBinding, next);\r
60                         stream = new Stream( aa, sampleBinding );\r
61                         size = aa.size();\r
62                         if ( size>0 ) {\r
63                         aa.get(0, sampleBinding, current);\r
64                                 from = valueBand.getTimeDouble();\r
65                         aa.get(size-1, sampleBinding, current);\r
66                                 end = valueBand.hasEndTime() ? valueBand.getEndTimeDouble() : valueBand.getTimeDouble();\r
67                         }\r
68                 } catch (BindingException e) {\r
69                         throw new HistoryException( e );\r
70                 } catch (AccessorException e) {\r
71                         throw new HistoryException( e );\r
72                 } \r
73         }\r
74         \r
75         /**\r
76          * Go to time using random access\r
77          * @param time\r
78          * @return true if sample was found\r
79          * @throws HistoryException \r
80          */\r
81         public boolean gotoTime(double time) throws HistoryException {\r
82                 // Outside range\r
83                 if ( time<from || time>end ) {\r
84                         index = -1;\r
85                         return false;\r
86                 }\r
87                 \r
88                 // Already at cursor\r
89                 if ( time>=startTime && time<endTime ) return hasValue();\r
90                 int i = stream.binarySearch(Bindings.DOUBLE, time);\r
91                 if (i>=0) {\r
92                         gotoIndex( i );\r
93                 } else {\r
94                         int insertPos = -i-2;\r
95                         if ( insertPos<0 || insertPos>=size ) {\r
96                                 index = -1;\r
97                         } else {\r
98                                 gotoIndex( insertPos );\r
99                                 if ( endTime<time ) index = -1;\r
100                         }\r
101                 }\r
102                 \r
103                 return hasValue();              \r
104         }\r
105         \r
106         /**\r
107          * Proceed to time using sequential seek.\r
108          * \r
109          * @param time\r
110          * @return true if sample was found\r
111          * @throws HistoryException \r
112          */\r
113         public boolean proceedToTime(double time) throws HistoryException {\r
114                 // Outside range\r
115                 if ( time<from || time>end ) {\r
116                         index = -1;\r
117                         return false;\r
118                 }\r
119 \r
120                 // No position, or going to past\r
121                 if (index<0 || startTime>time) {\r
122                         gotoTime(time);\r
123                         return hasValue();\r
124                 }\r
125                 \r
126                 // Proceed until end hit\r
127                 while (time>=endTime && hasNext()) gotoIndex(index+1);\r
128                 return hasValue();\r
129         }\r
130         \r
131         /**\r
132          * Go to index. If element does not exist, index is set to -1;\r
133          * @param pos\r
134          * @throws HistoryException\r
135          */\r
136         public void gotoIndex(int pos) throws HistoryException {\r
137                 if (pos == index) return;\r
138                 \r
139                 if (pos<0 || pos>=size) {\r
140                         index = -1;\r
141                         return;\r
142                 }\r
143 \r
144                 try {\r
145                         // Read current value\r
146                         if (pos == index+1 && index>=0) {\r
147                                 sampleBinding.readFrom(sampleBinding, next, current);\r
148                         } else {\r
149                                 aa.get(pos, sampleBinding, current);\r
150                         }\r
151                         startTime = valueBand.getTimeDouble();\r
152                         \r
153                         // Read next value\r
154                         if (pos+1<size) {\r
155                                 aa.get(pos+1, sampleBinding, next);\r
156                                 //endTime = valueBand.isValidValue() ? nextValueBand.getTimeDouble() : ( nextValueBand.isValidValue() ? nextValueBand.getTimeDouble() : nextValueBand.getTimeDouble() );\r
157                                 endTime = nextValueBand.getTimeDouble();\r
158                         } else {                                \r
159                                 endTime = valueBand.hasEndTime() ? valueBand.getEndTimeDouble() : valueBand.getTimeDouble();\r
160                         }\r
161                         \r
162                         // \r
163                         index = pos;\r
164                 } catch (AccessorException e) {\r
165                         throw new HistoryException( e );\r
166                 } catch (BindingException e) {\r
167                         throw new HistoryException( e );\r
168                 }\r
169         }\r
170 \r
171         \r
172         public boolean hasNext() {\r
173                 return index<size-1;\r
174         }\r
175 \r
176         public void next() throws HistoryException {\r
177                 //if (index>=0) \r
178                 gotoIndex( index+1 );\r
179         }\r
180         \r
181         public ValueBand getValueBand() {\r
182                 return valueBand;\r
183         }\r
184         \r
185         public Object getValue(Binding binding) throws HistoryException {\r
186                 return valueBand.getValue(binding);\r
187         }\r
188         \r
189         public Object getSample() {\r
190                 return current;\r
191         }\r
192         \r
193         public RecordBinding getSampleBinding() {\r
194                 return sampleBinding;\r
195         }\r
196         \r
197         public boolean hasValue() {\r
198                 return index!=-1;\r
199         }\r
200         \r
201         public boolean hasValidValue() throws HistoryException {\r
202                 return index!=-1 && !valueBand.isNanSample() && !valueBand.isNullValue();\r
203         }\r
204         /**\r
205          * Get the start time. The value is valid if index != -1\r
206          * @return start time\r
207          */\r
208         public double getStartTime() {\r
209                 return startTime;\r
210         }\r
211         \r
212         /**\r
213          * Get end time, the value is valid if index != -1\r
214          * @return end time\r
215          */\r
216         public double getEndTime() {\r
217                 return endTime;\r
218         }\r
219         \r
220         public Double getNextTime() throws HistoryException {\r
221                 if ( size==0 ) return null;\r
222                 if ( index==-1 ) return from;\r
223                 return (Double) nextValueBand.getTime(Bindings.DOUBLE);\r
224         }\r
225         \r
226         public Double getNextTime( double currentTime ) throws HistoryException {\r
227                 if ( size==0 ) return null;\r
228                 if ( index==-1 ) return from;\r
229                 \r
230                 if ( valueBand.hasEndTime() ) {\r
231                         Double endTime = (Double) valueBand.getEndTime(Bindings.DOUBLE);\r
232                         if ( endTime>currentTime ) return endTime;\r
233                 }\r
234                 \r
235                 double nextTime = (Double) nextValueBand.getTime(Bindings.DOUBLE);\r
236                 return nextTime;\r
237         }\r
238         \r
239         \r
240         \r
241         /**\r
242          * get index of the cursor\r
243          * @return index or -1\r
244          */\r
245         public int getIndex() {\r
246                 return index;\r
247         }\r
248         \r
249         @Override\r
250         public String toString() {\r
251                 Binding valueBinding = valueBand.getValueBinding();\r
252                 String valueStr;\r
253                 try {\r
254                         valueStr = valueBinding.toString( valueBand.getValue() );\r
255                 } catch (BindingException e) {\r
256                         valueStr = e.toString();\r
257                 } catch (HistoryException e) {\r
258                         valueStr = e.toString();\r
259                 }\r
260                 if ( hasValue() ) {\r
261                         return "i="+index+", time=["+startTime+"-"+endTime+"], value="+valueStr;\r
262                 } else {\r
263                         return "<no value>";\r
264                 }\r
265         }\r
266         \r
267         /**\r
268          * Get start time of the first sample.\r
269          * @return time\r
270          */\r
271         public double getFirstTime() {\r
272                 return from;\r
273         }\r
274         \r
275         /**\r
276          * Get end time of the last sample.\r
277          * @return time\r
278          */\r
279         public double getLastTime() {\r
280                 return end;\r
281         }\r
282         \r
283         public int size() {\r
284                 return size;\r
285         }\r
286         \r
287         public boolean isEmpty() {\r
288                 return size==0;\r
289         }\r
290         \r
291 }\r