1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2012 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.history.util;
\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
23 * Stream iterator iterates sample entries in an array.
\r
25 * Is scans the next sample and knows its time stamp.
\r
27 * @author toni.kalajainen
\r
29 public class StreamIterator {
\r
32 RecordBinding sampleBinding;
\r
38 // From and end times of the whole stream
\r
41 // Current and next sample
\r
42 Object current, next;
\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
52 public StreamIterator(ArrayAccessor aa) throws HistoryException {
\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
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
68 } catch (BindingException e) {
\r
69 throw new HistoryException( e );
\r
70 } catch (AccessorException e) {
\r
71 throw new HistoryException( e );
\r
76 * Go to time using random access
\r
78 * @return true if sample was found
\r
79 * @throws HistoryException
\r
81 public boolean gotoTime(double time) throws HistoryException {
\r
83 if ( time<from || time>end ) {
\r
88 // Already at cursor
\r
89 if ( time>=startTime && time<endTime ) return hasValue();
\r
90 int i = stream.binarySearch(Bindings.DOUBLE, time);
\r
94 int insertPos = -i-2;
\r
95 if ( insertPos<0 || insertPos>=size ) {
\r
98 gotoIndex( insertPos );
\r
99 if ( endTime<time ) index = -1;
\r
103 return hasValue();
\r
107 * Proceed to time using sequential seek.
\r
110 * @return true if sample was found
\r
111 * @throws HistoryException
\r
113 public boolean proceedToTime(double time) throws HistoryException {
\r
115 if ( time<from || time>end ) {
\r
120 // No position, or going to past
\r
121 if (index<0 || startTime>time) {
\r
126 // Proceed until end hit
\r
127 while (time>=endTime && hasNext()) gotoIndex(index+1);
\r
132 * Go to index. If element does not exist, index is set to -1;
\r
134 * @throws HistoryException
\r
136 public void gotoIndex(int pos) throws HistoryException {
\r
137 if (pos == index) return;
\r
139 if (pos<0 || pos>=size) {
\r
145 // Read current value
\r
146 if (pos == index+1 && index>=0) {
\r
147 sampleBinding.readFrom(sampleBinding, next, current);
\r
149 aa.get(pos, sampleBinding, current);
\r
151 startTime = valueBand.getTimeDouble();
\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
159 endTime = valueBand.hasEndTime() ? valueBand.getEndTimeDouble() : valueBand.getTimeDouble();
\r
164 } catch (AccessorException e) {
\r
165 throw new HistoryException( e );
\r
166 } catch (BindingException e) {
\r
167 throw new HistoryException( e );
\r
172 public boolean hasNext() {
\r
173 return index<size-1;
\r
176 public void next() throws HistoryException {
\r
178 gotoIndex( index+1 );
\r
181 public ValueBand getValueBand() {
\r
185 public Object getValue(Binding binding) throws HistoryException {
\r
186 return valueBand.getValue(binding);
\r
189 public Object getSample() {
\r
193 public RecordBinding getSampleBinding() {
\r
194 return sampleBinding;
\r
197 public boolean hasValue() {
\r
201 public boolean hasValidValue() throws HistoryException {
\r
202 return index!=-1 && !valueBand.isNanSample() && !valueBand.isNullValue();
\r
205 * Get the start time. The value is valid if index != -1
\r
206 * @return start time
\r
208 public double getStartTime() {
\r
213 * Get end time, the value is valid if index != -1
\r
216 public double getEndTime() {
\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
226 public Double getNextTime( double currentTime ) throws HistoryException {
\r
227 if ( size==0 ) return null;
\r
228 if ( index==-1 ) return from;
\r
230 if ( valueBand.hasEndTime() ) {
\r
231 Double endTime = (Double) valueBand.getEndTime(Bindings.DOUBLE);
\r
232 if ( endTime>currentTime ) return endTime;
\r
235 double nextTime = (Double) nextValueBand.getTime(Bindings.DOUBLE);
\r
242 * get index of the cursor
\r
243 * @return index or -1
\r
245 public int getIndex() {
\r
250 public String toString() {
\r
251 Binding valueBinding = valueBand.getValueBinding();
\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
260 if ( hasValue() ) {
\r
261 return "i="+index+", time=["+startTime+"-"+endTime+"], value="+valueStr;
\r
263 return "<no value>";
\r
268 * Get start time of the first sample.
\r
271 public double getFirstTime() {
\r
276 * Get end time of the last sample.
\r
279 public double getLastTime() {
\r
283 public int size() {
\r
287 public boolean isEmpty() {
\r