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