X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.history%2Fsrc%2Forg%2Fsimantics%2Fhistory%2Futil%2FStream.java;h=3366a1c26858751ef8017644b98efc28239847cc;hb=c943961e15c1022e1f9165e683995240abb5d97f;hp=9ffd048d4ce0e016ef707b2a11c1d30799b7148f;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.history/src/org/simantics/history/util/Stream.java b/bundles/org.simantics.history/src/org/simantics/history/util/Stream.java
index 9ffd048d4..3366a1c26 100644
--- a/bundles/org.simantics.history/src/org/simantics/history/util/Stream.java
+++ b/bundles/org.simantics.history/src/org/simantics/history/util/Stream.java
@@ -1,524 +1,533 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
- * Industry THTH ry.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * VTT Technical Research Centre of Finland - initial API and implementation
- *******************************************************************************/
-package org.simantics.history.util;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.databoard.accessor.ArrayAccessor;
-import org.simantics.databoard.accessor.CloseableAccessor;
-import org.simantics.databoard.accessor.StreamAccessor;
-import org.simantics.databoard.accessor.error.AccessorException;
-import org.simantics.databoard.adapter.AdaptException;
-import org.simantics.databoard.binding.Binding;
-import org.simantics.databoard.binding.NumberBinding;
-import org.simantics.databoard.binding.RecordBinding;
-import org.simantics.databoard.binding.error.BindingException;
-import org.simantics.databoard.type.Datatype;
-import org.simantics.databoard.type.NumberType;
-import org.simantics.databoard.type.RecordType;
-import org.simantics.history.HistoryException;
-
-/**
- * This utility adds random access (time) to array accessor.
- *
- * @author toni.kalajainen
- */
-public class Stream {
-
- public ArrayAccessor accessor;
- public RecordType sampleType;
- public RecordBinding sampleBinding;
-
- public int timeIndex;
- public Datatype timeType;
- public Binding timeBinding;
-
- public int endTimeIndex;
- public Datatype endTimeType;
- public Binding endTimeBinding;
-
- public int valueIndex;
- public Datatype valueType;
- public Binding valueBinding;
-
- public int qualityIndex=-1;
- public NumberType qualityType;
- public NumberBinding qualityBinding;
-
- /**
- * Construct stream
- *
- * @param accessor
- */
- public Stream(ArrayAccessor accessor)
- {
- this.accessor = accessor;
- this.sampleType = (RecordType) accessor.type().componentType();
- this.sampleBinding = (RecordBinding) Bindings.getBeanBinding( sampleType );
-
- this.valueIndex = sampleType.getComponentIndex2("value");
- if (valueIndex<0) throw new IllegalArgumentException("Array is not a sample array, value field is missing");
- this.valueType = sampleType.getComponentType(valueIndex);
- this.valueBinding = this.sampleBinding.getComponentBinding(valueIndex);
-
- this.timeIndex = sampleType.getComponentIndex2("time");
- if (timeIndex<0) throw new IllegalArgumentException("Array is not a sample array, time field is missing");
- this.timeType = sampleType.getComponentType(timeIndex);
- this.timeBinding = this.sampleBinding.getComponentBinding(timeIndex);
-
- this.endTimeIndex = sampleType.getComponentIndex2("endTime");
-
- this.qualityIndex = sampleType.getComponentIndex2("quality");
- this.qualityType = qualityIndex>=0?(NumberType)sampleType.getComponentType(qualityIndex):null;
- this.qualityBinding = qualityType!=null?(NumberBinding)this.sampleBinding.getComponentBinding(qualityIndex):null;
- }
-
- /**
- * Construct stream
- *
- * @param accessor
- */
- public Stream(ArrayAccessor accessor, RecordBinding recordBinding)
- {
- this.accessor = accessor;
- this.sampleType = (RecordType) accessor.type().componentType();
- if (!this.sampleType.equals(recordBinding.type())) throw new IllegalArgumentException("Wrong binding. Got " + recordBinding.type() + ", expected " + this.sampleType);
- this.sampleBinding = recordBinding;
-
- this.valueIndex = sampleType.getComponentIndex2("value");
- this.timeIndex = sampleType.getComponentIndex2("time");
- this.endTimeIndex = sampleType.getComponentIndex2("endTime");
-
- if (valueIndex<0) throw new IllegalArgumentException("Array is not a sample array, value field is missing");
- if (timeIndex<0) throw new IllegalArgumentException("Array is not a sample array, time field is missing");
- //if (endTimeIndex<0) throw new IllegalArgumentException("Array is not a sample array, time field is missing");
-
- this.valueType = sampleType.getComponentType(valueIndex);
- this.timeType = sampleType.getComponentType(timeIndex);
- this.endTimeType = endTimeIndex>=0 ? sampleType.getComponentType(endTimeIndex) : null;
-
- this.valueBinding = this.sampleBinding.getComponentBinding("value");
- this.timeBinding = this.sampleBinding.getComponentBinding("time");
- this.endTimeBinding = endTimeIndex>=0 ? this.sampleBinding.getComponentBinding("endTime") : null;
- }
-
- public void close() {
- if (accessor instanceof CloseableAccessor) {
- CloseableAccessor ca = (CloseableAccessor) accessor;
- try {
- ca.close();
- } catch (AccessorException e) {
- }
- }
- }
-
- public void reset() {
- if (accessor instanceof StreamAccessor) {
- StreamAccessor sa = (StreamAccessor) accessor;
- try {
- sa.reset();
- } catch (AccessorException e) {
- }
- }
- }
-
- /**
- * Make a binary search to stream data
- *
- * @param array
- * @param timeBinding
- * @param time
- * @return index of the search key, if it is contained in the array
- * within the specified range;
- * otherwise, (-(insertion point) - 1). The
- * insertion point is defined as the point at which the
- * key would be inserted into the array: the index of the first
- * element in the range greater than the key,
- * or toIndex if all
- * elements in the range are less than the specified key. Note
- * that this guarantees that the return value will be >= 0 if
- * and only if the key is found.
- * @throws HistoryException
- */
- public int binarySearch(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- Object time_ = Bindings.adapt(time, timeBinding, this.timeBinding);
-
- int fromIndex = 0;
- int toIndex = accessor.size();
-
- int ix = binarySearch0(fromIndex, toIndex, time_);
- return ix;
- } catch (AccessorException e) {
- throw new HistoryException(e);
- } catch (BindingException e) {
- throw new HistoryException(e);
- } catch (AdaptException e) {
- throw new HistoryException(e);
- }
- }
-
- // Like public version, but without range checks.
- private int binarySearch0(int fromIndex, int toIndex, Object key) throws AccessorException, BindingException {
- int low = fromIndex;
- int high = toIndex - 1;
- Binding timeBinding = sampleBinding.getComponentBinding(timeIndex);
-
- while (low <= high) {
- int mid = (low + high) >>> 1;
- Object midSam = accessor.get(mid, sampleBinding);
- Object midVal = sampleBinding.getComponent(midSam, timeIndex);
- int cmp = timeBinding.compare(midVal, key);
- if (cmp < 0)
- low = mid + 1;
- else if (cmp > 0)
- high = mid - 1;
- else
- return mid; // key found
- }
- return -(low + 1); // key not found.
- }
-
- public Object getLowerSample(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int index = binarySearch(timeBinding, time);
- // Exact match
- if (index==0) return null;
- if (index>0) {
- return accessor.get(index-1, sampleBinding);
- }
- index = -index-2;
- if (index<0) return null;
- if (index>=accessor.size()) return null;
- return accessor.get(index, sampleBinding);
- } catch (AccessorException e) {
- throw new HistoryException( e );
- }
- }
-
-
- public Object getFloorSample(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int index = binarySearch(timeBinding, time);
- // Exact match
- if (index>=0) {
- return accessor.get(index, sampleBinding);
- }
- // The position where the sample would be inserted
- index = -index-2;
- if (index<0) return null;
- if (index>=accessor.size()) return null;
- return accessor.get(index, sampleBinding);
- } catch (AccessorException e) {
- throw new HistoryException( e );
- }
- }
-
- public Object getSample(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int pos = binarySearch(timeBinding, time);
- if (pos>=0) {
- return accessor.get(pos, sampleBinding);
- }
- return null;
- } catch (AccessorException e) {
- throw new HistoryException(e);
- }
- }
-
- public boolean getSample(Binding timeBinding, Object time, Object sample) throws HistoryException
- {
- try {
- int pos = binarySearch(timeBinding, time);
- if (pos>=0) {
- accessor.get(pos, sampleBinding, sample);
- return true;
- }
- return false;
- } catch (AccessorException e) {
- throw new HistoryException(e);
- }
- }
-
- public Object getCeilingSample(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int index = binarySearch(timeBinding, time);
- // Exact match
- if (index>=0) {
- return accessor.get(index, sampleBinding);
- }
- // The position where the sample would be inserted
- index = -index-1;
- if (index<0) return null;
- if (index>=accessor.size()) return null;
- return accessor.get(index, sampleBinding);
- } catch (AccessorException e) {
- throw new HistoryException( e );
- }
- }
-
- public Object getHigherSample(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int index = binarySearch(timeBinding, time);
- // Exact match
- int count = accessor.size();
- if (index>=0) {
- index++; // exact match, -> next
- } else {
- // The position where the sample would be inserted
- index = -index-1;
- }
- if (index<0 || index>=count) return null;
- return accessor.get(index, sampleBinding);
- } catch (AccessorException e) {
- throw new HistoryException( e );
- }
- }
-
- private Object _getTime(Object sample, Binding timeBinding) throws HistoryException
- {
- try {
- Object time__ = sampleBinding.getComponent( sample, timeIndex );
- return Bindings.adapt(time__, this.timeBinding, timeBinding);
- } catch (AdaptException e) {
- throw new HistoryException(e);
- } catch (BindingException e) {
- throw new HistoryException(e);
- }
- }
-
- public Object getLowerTime(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int index = binarySearch(timeBinding, time);
- // Exact match
- if (index==0) return null;
- if (index>0) {
- return time;
- }
- index = -index-2;
- if (index<0) return null;
- if (index>=accessor.size()) return null;
- return _getTime(accessor.get(index, sampleBinding), timeBinding);
- } catch (AccessorException e) {
- throw new HistoryException( e );
- }
- }
-
-
- public Object getFloorTime(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int index = binarySearch(timeBinding, time);
- // Exact match
- if (index>=0) {
- return time;
- }
- // The position where the sample would be inserted
- index = -index-2;
- if (index<0) return null;
- if (index>=accessor.size()) return null;
- return _getTime( accessor.get(index, sampleBinding), timeBinding );
- } catch (AccessorException e) {
- throw new HistoryException( e );
- }
- }
-
- public Object getCeilingTime(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int index = binarySearch(timeBinding, time);
- // Exact match
- if (index>=0) {
- return time;
- }
- // The position where the sample would be inserted
- index = -index-1;
- if (index<0) return null;
- if (index>=accessor.size()) return null;
- return _getTime( accessor.get(index, sampleBinding), timeBinding );
- } catch (AccessorException e) {
- throw new HistoryException( e );
- }
- }
-
- public Object getHigherTime(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int index = binarySearch(timeBinding, time);
-
- // Exact match
- int count = accessor.size();
- if (index>=0) {
- index++; // exact match, -> next
- } else {
- // The position where the sample would be inserted
- index = -index-1;
- }
- if (index<0 || index>=count) return null;
- return _getTime( accessor.get(index, sampleBinding), timeBinding );
- } catch (AccessorException e) {
- throw new HistoryException( e );
- }
- }
-
-
- public Object getValue(Binding timeBinding, Object time, Binding valueBinding) throws HistoryException
- {
- try {
- int pos = binarySearch(timeBinding, time);
- if (pos>=0) {
- Object sample = accessor.get(pos, sampleBinding);
- Object value = sampleBinding.getComponent(sample, valueIndex);
-
- if (valueBinding != this.valueBinding) {
- value = Bindings.adapt(value, this.valueBinding, valueBinding);
- }
- return value;
- }
- return null;
- } catch (AccessorException e) {
- throw new HistoryException(e);
- } catch (BindingException e) {
- throw new HistoryException(e);
- } catch (AdaptException e) {
- throw new HistoryException(e);
- }
- }
-
- public Object getValue(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int pos = binarySearch(timeBinding, time);
- if (pos>=0) {
- Object sample = accessor.get(pos, sampleBinding);
- Object value = sampleBinding.getComponent(sample, valueIndex);
- return value;
- }
- return null;
- } catch (AccessorException e) {
- throw new HistoryException(e);
- } catch (BindingException e) {
- throw new HistoryException(e);
- }
- }
-
- public Object getQuality(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int pos = binarySearch(timeBinding, time);
- if (pos>=0) {
- Object sample = accessor.get(pos, sampleBinding);
- Object value = sampleBinding.getComponent(sample, qualityIndex);
- return value;
- }
- return null;
- } catch (AccessorException e) {
- throw new HistoryException(e);
- } catch (BindingException e) {
- throw new HistoryException(e);
- }
- }
-
- /**
- * Get value if exists, otherwise null
- * @param timeBinding
- * @param time
- * @return value or null
- * @throws HistoryException
- */
- public Object getPossibleValue(Binding timeBinding, Object time) throws HistoryException
- {
- try {
- int pos = binarySearch(timeBinding, time);
- if (pos>=0) {
- Object sample = accessor.get(pos, sampleBinding);
- if (qualityBinding != null) {
- Object quality = sampleBinding.getComponent(sample, qualityIndex);
- if ( !qualityBinding.getValue(quality).equals( ValueBand.QUALITY_GOOD ) ) return null;
- }
- Object value = sampleBinding.getComponent(sample, valueIndex);
- return value;
- }
- return null;
- } catch (AccessorException e) {
- throw new HistoryException(e);
- } catch (BindingException e) {
- throw new HistoryException(e);
- }
- }
-
- public int count() throws HistoryException {
- try {
- return accessor.size();
- } catch (AccessorException e) {
- throw new HistoryException(e);
- }
- }
-
- public Object getFirstTime(Binding binding) throws HistoryException {
- try {
- if (accessor.size()==0) {
- return null;
- }
- Object sample = accessor.get(0, sampleBinding);
- Object time = sampleBinding.getComponent(sample, timeIndex);
- if (timeBinding!=binding) time = Bindings.adapt(time, timeBinding, binding);
- return time;
- } catch (BindingException e) {
- throw new HistoryException(e);
- } catch (AccessorException e) {
- throw new HistoryException(e);
- } catch (AdaptException e) {
- throw new HistoryException(e);
- }
- }
-
- public Object getEndTime(Binding binding) throws HistoryException {
- try {
- if (accessor.size()==0) {
- return null;
- }
- Object sample = accessor.get(0, sampleBinding);
-
- if (endTimeIndex>=0) {
- Object endtime = sampleBinding.getComponent(sample, endTimeIndex);
- if (endTimeBinding!=binding) endtime = Bindings.adapt(endtime, endTimeBinding, binding);
- return endtime;
- } else {
- Object time = sampleBinding.getComponent(sample, timeIndex);
- if (timeBinding!=binding) time = Bindings.adapt(time, timeBinding, binding);
- return time;
- }
- } catch (BindingException e) {
- throw new HistoryException(e);
- } catch (AccessorException e) {
- throw new HistoryException(e);
- } catch (AdaptException e) {
- throw new HistoryException(e);
- }
- }
-
- public boolean isEmpty() throws HistoryException {
- try {
- return accessor.size() == 0;
- } catch (AccessorException e) {
- throw new HistoryException(e);
- }
- }
-
-}
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.history.util;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.accessor.ArrayAccessor;
+import org.simantics.databoard.accessor.CloseableAccessor;
+import org.simantics.databoard.accessor.StreamAccessor;
+import org.simantics.databoard.accessor.error.AccessorException;
+import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.NumberBinding;
+import org.simantics.databoard.binding.RecordBinding;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.type.NumberType;
+import org.simantics.databoard.type.RecordType;
+import org.simantics.history.HistoryException;
+
+/**
+ * This utility adds random access (time) to array accessor.
+ *
+ * @author toni.kalajainen
+ */
+public class Stream {
+
+ public ArrayAccessor accessor;
+ public RecordType sampleType;
+ public RecordBinding sampleBinding;
+
+ public int timeIndex;
+ public Datatype timeType;
+ public Binding timeBinding;
+
+ public int endTimeIndex;
+ public Datatype endTimeType;
+ public Binding endTimeBinding;
+
+ public int valueIndex;
+ public Datatype valueType;
+ public Binding valueBinding;
+
+ public int qualityIndex=-1;
+ public NumberType qualityType;
+ public NumberBinding qualityBinding;
+
+ /**
+ * Construct stream
+ *
+ * @param accessor
+ */
+ public Stream(ArrayAccessor accessor)
+ {
+ this.accessor = accessor;
+ this.sampleType = (RecordType) accessor.type().componentType();
+ this.sampleBinding = (RecordBinding) Bindings.getBeanBinding( sampleType );
+
+ this.valueIndex = sampleType.getComponentIndex2("value");
+ if (valueIndex<0) throw new IllegalArgumentException("Array is not a sample array, value field is missing");
+ this.valueType = sampleType.getComponentType(valueIndex);
+ this.valueBinding = this.sampleBinding.getComponentBinding(valueIndex);
+
+ this.timeIndex = sampleType.getComponentIndex2("time");
+ if (timeIndex<0) throw new IllegalArgumentException("Array is not a sample array, time field is missing");
+ this.timeType = sampleType.getComponentType(timeIndex);
+ this.timeBinding = this.sampleBinding.getComponentBinding(timeIndex);
+
+ this.endTimeIndex = sampleType.getComponentIndex2("endTime");
+
+ this.qualityIndex = sampleType.getComponentIndex2("quality");
+ this.qualityType = qualityIndex>=0?(NumberType)sampleType.getComponentType(qualityIndex):null;
+ this.qualityBinding = qualityType!=null?(NumberBinding)this.sampleBinding.getComponentBinding(qualityIndex):null;
+ }
+
+ /**
+ * Construct stream
+ *
+ * @param accessor
+ */
+ public Stream(ArrayAccessor accessor, RecordBinding recordBinding)
+ {
+ this.accessor = accessor;
+ this.sampleType = (RecordType) accessor.type().componentType();
+ if (!this.sampleType.equals(recordBinding.type())) throw new IllegalArgumentException("Wrong binding. Got " + recordBinding.type() + ", expected " + this.sampleType);
+ this.sampleBinding = recordBinding;
+
+ this.valueIndex = sampleType.getComponentIndex2("value");
+ this.timeIndex = sampleType.getComponentIndex2("time");
+ this.endTimeIndex = sampleType.getComponentIndex2("endTime");
+
+ if (valueIndex<0) throw new IllegalArgumentException("Array is not a sample array, value field is missing");
+ if (timeIndex<0) throw new IllegalArgumentException("Array is not a sample array, time field is missing");
+ //if (endTimeIndex<0) throw new IllegalArgumentException("Array is not a sample array, time field is missing");
+
+ this.valueType = sampleType.getComponentType(valueIndex);
+ this.timeType = sampleType.getComponentType(timeIndex);
+ this.endTimeType = endTimeIndex>=0 ? sampleType.getComponentType(endTimeIndex) : null;
+
+ this.valueBinding = this.sampleBinding.getComponentBinding("value");
+ this.timeBinding = this.sampleBinding.getComponentBinding("time");
+ this.endTimeBinding = endTimeIndex>=0 ? this.sampleBinding.getComponentBinding("endTime") : null;
+ }
+
+ public void close() {
+ if (accessor instanceof CloseableAccessor) {
+ CloseableAccessor ca = (CloseableAccessor) accessor;
+ try {
+ ca.close();
+ } catch (AccessorException e) {
+ }
+ }
+ }
+
+ public void reset() {
+ if (accessor instanceof StreamAccessor) {
+ StreamAccessor sa = (StreamAccessor) accessor;
+ try {
+ sa.reset();
+ } catch (AccessorException e) {
+ }
+ }
+ }
+
+ /**
+ * Make a binary search to stream data
+ *
+ * @param array
+ * @param timeBinding
+ * @param time
+ * @return index of the search key, if it is contained in the array
+ * within the specified range;
+ * otherwise, (-(insertion point) - 1). The
+ * insertion point is defined as the point at which the
+ * key would be inserted into the array: the index of the first
+ * element in the range greater than the key,
+ * or toIndex if all
+ * elements in the range are less than the specified key. Note
+ * that this guarantees that the return value will be >= 0 if
+ * and only if the key is found.
+ * @throws HistoryException
+ */
+ public int binarySearch(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ Object time_ = Bindings.adapt(time, timeBinding, this.timeBinding);
+
+ int fromIndex = 0;
+ int toIndex = accessor.size();
+
+ int ix = binarySearch0(fromIndex, toIndex, time_);
+ return ix;
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ } catch (BindingException e) {
+ throw new HistoryException(e);
+ } catch (AdaptException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ // Like public version, but without range checks.
+ private int binarySearch0(int fromIndex, int toIndex, Object key) throws AccessorException, BindingException {
+ int low = fromIndex;
+ int high = toIndex - 1;
+ Binding timeBinding = sampleBinding.getComponentBinding(timeIndex);
+
+ while (low <= high) {
+ int mid = (low + high) >>> 1;
+ Object midSam = accessor.get(mid, sampleBinding);
+ Object midVal = sampleBinding.getComponent(midSam, timeIndex);
+ int cmp = timeBinding.compare(midVal, key);
+ if (cmp < 0)
+ low = mid + 1;
+ else if (cmp > 0)
+ high = mid - 1;
+ else
+ return mid; // key found
+ }
+ return -(low + 1); // key not found.
+ }
+
+ public Object getLowerSample(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int index = binarySearch(timeBinding, time);
+ // Exact match
+ if (index==0) return null;
+ if (index>0) {
+ return accessor.get(index-1, sampleBinding);
+ }
+ index = -index-2;
+ if (index<0) return null;
+ if (index>=accessor.size()) return null;
+ return accessor.get(index, sampleBinding);
+ } catch (AccessorException e) {
+ throw new HistoryException( e );
+ }
+ }
+
+
+ public Object getFloorSample(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int index = binarySearch(timeBinding, time);
+ // Exact match
+ if (index>=0) {
+ return accessor.get(index, sampleBinding);
+ }
+ // The position where the sample would be inserted
+ index = -index-2;
+ if (index<0) return null;
+ if (index>=accessor.size()) return null;
+ return accessor.get(index, sampleBinding);
+ } catch (AccessorException e) {
+ throw new HistoryException( e );
+ }
+ }
+
+ public Object getSample(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int pos = binarySearch(timeBinding, time);
+ if (pos>=0) {
+ return accessor.get(pos, sampleBinding);
+ }
+ return null;
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ public boolean getSample(Binding timeBinding, Object time, Object sample) throws HistoryException
+ {
+ try {
+ int pos = binarySearch(timeBinding, time);
+ if (pos>=0) {
+ accessor.get(pos, sampleBinding, sample);
+ return true;
+ }
+ return false;
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ public Object getCeilingSample(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int index = binarySearch(timeBinding, time);
+ // Exact match
+ if (index>=0) {
+ return accessor.get(index, sampleBinding);
+ }
+ // The position where the sample would be inserted
+ index = -index-1;
+ if (index<0) return null;
+ if (index>=accessor.size()) return null;
+ return accessor.get(index, sampleBinding);
+ } catch (AccessorException e) {
+ throw new HistoryException( e );
+ }
+ }
+
+ public Object getHigherSample(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int index = binarySearch(timeBinding, time);
+ // Exact match
+ int count = accessor.size();
+ if (index>=0) {
+ index++; // exact match, -> next
+ } else {
+ // The position where the sample would be inserted
+ index = -index-1;
+ }
+ if (index<0 || index>=count) return null;
+ return accessor.get(index, sampleBinding);
+ } catch (AccessorException e) {
+ throw new HistoryException( e );
+ }
+ }
+
+ private Object _getTime(Object sample, Binding timeBinding) throws HistoryException
+ {
+ try {
+ Object time__ = sampleBinding.getComponent( sample, timeIndex );
+ return Bindings.adapt(time__, this.timeBinding, timeBinding);
+ } catch (AdaptException e) {
+ throw new HistoryException(e);
+ } catch (BindingException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ public Object getItemTime(Binding timeBinding, int index) throws HistoryException
+ {
+ try {
+ return _getTime( accessor.get(index, sampleBinding), timeBinding );
+ } catch (AccessorException e) {
+ throw new HistoryException( e );
+ }
+ }
+
+ public Object getLowerTime(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int index = binarySearch(timeBinding, time);
+ // Exact match
+ if (index==0) return null;
+ if (index>0) {
+ return time;
+ }
+ index = -index-2;
+ if (index<0) return null;
+ if (index>=accessor.size()) return null;
+ return _getTime(accessor.get(index, sampleBinding), timeBinding);
+ } catch (AccessorException e) {
+ throw new HistoryException( e );
+ }
+ }
+
+
+ public Object getFloorTime(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int index = binarySearch(timeBinding, time);
+ // Exact match
+ if (index>=0) {
+ return time;
+ }
+ // The position where the sample would be inserted
+ index = -index-2;
+ if (index<0) return null;
+ if (index>=accessor.size()) return null;
+ return _getTime( accessor.get(index, sampleBinding), timeBinding );
+ } catch (AccessorException e) {
+ throw new HistoryException( e );
+ }
+ }
+
+ public Object getCeilingTime(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int index = binarySearch(timeBinding, time);
+ // Exact match
+ if (index>=0) {
+ return time;
+ }
+ // The position where the sample would be inserted
+ index = -index-1;
+ if (index<0) return null;
+ if (index>=accessor.size()) return null;
+ return _getTime( accessor.get(index, sampleBinding), timeBinding );
+ } catch (AccessorException e) {
+ throw new HistoryException( e );
+ }
+ }
+
+ public Object getHigherTime(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int index = binarySearch(timeBinding, time);
+
+ // Exact match
+ int count = accessor.size();
+ if (index>=0) {
+ index++; // exact match, -> next
+ } else {
+ // The position where the sample would be inserted
+ index = -index-1;
+ }
+ if (index<0 || index>=count) return null;
+ return _getTime( accessor.get(index, sampleBinding), timeBinding );
+ } catch (AccessorException e) {
+ throw new HistoryException( e );
+ }
+ }
+
+
+ public Object getValue(Binding timeBinding, Object time, Binding valueBinding) throws HistoryException
+ {
+ try {
+ int pos = binarySearch(timeBinding, time);
+ if (pos>=0) {
+ Object sample = accessor.get(pos, sampleBinding);
+ Object value = sampleBinding.getComponent(sample, valueIndex);
+
+ if (valueBinding != this.valueBinding) {
+ value = Bindings.adapt(value, this.valueBinding, valueBinding);
+ }
+ return value;
+ }
+ return null;
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ } catch (BindingException e) {
+ throw new HistoryException(e);
+ } catch (AdaptException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ public Object getValue(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int pos = binarySearch(timeBinding, time);
+ if (pos>=0) {
+ Object sample = accessor.get(pos, sampleBinding);
+ Object value = sampleBinding.getComponent(sample, valueIndex);
+ return value;
+ }
+ return null;
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ } catch (BindingException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ public Object getQuality(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int pos = binarySearch(timeBinding, time);
+ if (pos>=0) {
+ Object sample = accessor.get(pos, sampleBinding);
+ Object value = sampleBinding.getComponent(sample, qualityIndex);
+ return value;
+ }
+ return null;
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ } catch (BindingException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ /**
+ * Get value if exists, otherwise null
+ * @param timeBinding
+ * @param time
+ * @return value or null
+ * @throws HistoryException
+ */
+ public Object getPossibleValue(Binding timeBinding, Object time) throws HistoryException
+ {
+ try {
+ int pos = binarySearch(timeBinding, time);
+ if (pos>=0) {
+ Object sample = accessor.get(pos, sampleBinding);
+ if (qualityBinding != null) {
+ Object quality = sampleBinding.getComponent(sample, qualityIndex);
+ if ( !qualityBinding.getValue(quality).equals( ValueBand.QUALITY_GOOD ) ) return null;
+ }
+ Object value = sampleBinding.getComponent(sample, valueIndex);
+ return value;
+ }
+ return null;
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ } catch (BindingException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ public int count() throws HistoryException {
+ try {
+ return accessor.size();
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ public Object getFirstTime(Binding binding) throws HistoryException {
+ try {
+ if (accessor.size()==0) {
+ return null;
+ }
+ Object sample = accessor.get(0, sampleBinding);
+ Object time = sampleBinding.getComponent(sample, timeIndex);
+ if (timeBinding!=binding) time = Bindings.adapt(time, timeBinding, binding);
+ return time;
+ } catch (BindingException e) {
+ throw new HistoryException(e);
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ } catch (AdaptException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ public Object getEndTime(Binding binding) throws HistoryException {
+ try {
+ if (accessor.size()==0) {
+ return null;
+ }
+ Object sample = accessor.get(0, sampleBinding);
+
+ if (endTimeIndex>=0) {
+ Object endtime = sampleBinding.getComponent(sample, endTimeIndex);
+ if (endTimeBinding!=binding) endtime = Bindings.adapt(endtime, endTimeBinding, binding);
+ return endtime;
+ } else {
+ Object time = sampleBinding.getComponent(sample, timeIndex);
+ if (timeBinding!=binding) time = Bindings.adapt(time, timeBinding, binding);
+ return time;
+ }
+ } catch (BindingException e) {
+ throw new HistoryException(e);
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ } catch (AdaptException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+ public boolean isEmpty() throws HistoryException {
+ try {
+ return accessor.size() == 0;
+ } catch (AccessorException e) {
+ throw new HistoryException(e);
+ }
+ }
+
+}