1 /*******************************************************************************
\r
2 * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package org.simantics.databoard.accessor.impl;
\r
13 import org.simantics.databoard.Bindings;
\r
14 import org.simantics.databoard.accessor.MapAccessor;
\r
15 import org.simantics.databoard.accessor.error.AccessorException;
\r
16 import org.simantics.databoard.binding.ArrayBinding;
\r
17 import org.simantics.databoard.binding.Binding;
\r
18 import org.simantics.databoard.binding.BooleanBinding;
\r
19 import org.simantics.databoard.binding.NumberBinding;
\r
20 import org.simantics.databoard.binding.error.BindingException;
\r
21 import org.simantics.databoard.binding.impl.BooleanArrayBinding;
\r
22 import org.simantics.databoard.binding.impl.ByteArrayBinding;
\r
23 import org.simantics.databoard.binding.impl.DoubleArrayBinding;
\r
24 import org.simantics.databoard.binding.impl.FloatArrayBinding;
\r
25 import org.simantics.databoard.binding.impl.IntArrayBinding;
\r
26 import org.simantics.databoard.binding.impl.LongArrayBinding;
\r
27 import org.simantics.databoard.type.ArrayType;
\r
28 import org.simantics.databoard.util.Limit;
\r
29 import org.simantics.databoard.util.Range;
\r
32 * This helper class creates an iterator to MapAccessor
\r
34 * @param <K> key class
\r
35 * @param <V> value class
\r
36 * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
\r
38 public class MapAccessorIterator<K, V> {
\r
42 Binding valueBinding;
\r
45 boolean fromInclusive;
\r
48 boolean endInclusive;
\r
50 ArrayBinding keyCacheBinding;
\r
53 ArrayBinding valueCacheBinding;
\r
56 // Entry index, i.e. the number of entries read starting from 0
\r
59 // The number of samples written to cache
\r
60 int samplesInCache = 0;
\r
62 // The index in cache
\r
63 int cacheIndex = -1;
\r
66 * Initialize iterator with a cache. The cache should already be allocated with some empty elements.
\r
70 * @param fromInclusive
\r
72 * @param endInclusive
\r
73 * @param keyCacheBinding
\r
75 * @param valueCacheBinding
\r
78 public MapAccessorIterator(
\r
80 Binding keyBinding, Object from, boolean fromInclusive, Object end, boolean endInclusive,
\r
81 ArrayBinding keyCacheBinding, Object keyCache,
\r
82 ArrayBinding valueCacheBinding, Object valueCache) {
\r
84 this.keyBinding = keyBinding;
\r
86 this.fromInclusive = fromInclusive;
\r
88 this.endInclusive = endInclusive;
\r
89 this.valueBinding = valueCacheBinding.getComponentBinding();
\r
90 this.keyCacheBinding = keyCacheBinding;
\r
91 this.keyCache = keyCache;
\r
92 this.valueCacheBinding = valueCacheBinding;
\r
93 this.valueCache = valueCache;
\r
97 * Initialize map accessor iterator with a default cache
\r
101 * @param fromInclusive
\r
103 * @param endInclusive
\r
104 * @param valueBinding
\r
106 * @throws BindingException
\r
107 * @throws AccessorException
\r
109 public MapAccessorIterator(
\r
111 Binding keyBinding, Object from, boolean fromInclusive, Object end, boolean endInclusive,
\r
112 Binding valueBinding,
\r
113 int cacheSize) throws BindingException, AccessorException {
\r
115 this.keyBinding = keyBinding;
\r
117 this.fromInclusive = fromInclusive;
\r
119 this.endInclusive = endInclusive;
\r
120 this.valueBinding = valueBinding;
\r
122 // TODO calc num of elements if source
\r
123 // int count = map.count(keyBinding, from, fromInclusive, end, endInclusive);
\r
124 // int len = Math.min(count, 256);
\r
125 Range range = new Range(Limit.inclusive(cacheSize), Limit.nolimit());
\r
126 this.keyCacheBinding = Bindings.getBinding( new ArrayType(keyBinding.type(), range) );
\r
127 this.keyCache = keyCacheBinding.createDefault();
\r
128 this.valueCacheBinding = Bindings.getBinding( new ArrayType(valueBinding.type(), range) );
\r
129 this.valueCache = valueCacheBinding.createDefault();
\r
133 * Reads data to cache.
\r
135 * Updates from and fromInclusive fields for next read.
\r
136 * Updates samplesInCache field.
\r
137 * Sets cacheIndex to 0.
\r
139 * @throws AccessorException
\r
141 private void fillCache() throws AccessorException {
\r
143 int limit = Math.min(keyCacheBinding.size(keyCache), valueCacheBinding.size(valueCache));
\r
144 if (limit==0) throw new AccessorException("You should have some entries in the cache");
\r
149 samplesInCache = 0;
\r
153 samplesInCache = map.getEntries(
\r
154 keyBinding, from, fromInclusive,
\r
155 end, endInclusive,
\r
156 keyCacheBinding, keyCache,
\r
157 valueCacheBinding, valueCache,
\r
160 if (samplesInCache==0) {
\r
165 from = keyCacheBinding.get(keyCache, samplesInCache-1);
\r
166 fromInclusive = false;
\r
167 } catch (BindingException e) {
\r
168 throw new AccessorException(e);
\r
172 public boolean hasNext() throws AccessorException {
\r
173 if (from==null) return false;
\r
174 if (cacheIndex>=samplesInCache-1) fillCache();
\r
175 if (cacheIndex>=samplesInCache-1) return false;
\r
176 return cacheIndex+1<samplesInCache;
\r
179 public boolean next() throws AccessorException {
\r
180 if (from==null) return false;
\r
181 if (cacheIndex>=samplesInCache-1) fillCache();
\r
182 if (cacheIndex>=samplesInCache-1) return false;
\r
188 @SuppressWarnings("unchecked")
\r
189 public K key() throws AccessorException {
\r
191 return (K) keyCacheBinding.get(keyCache, cacheIndex);
\r
192 } catch (IndexOutOfBoundsException e) {
\r
193 throw new AccessorException(e);
\r
194 } catch (BindingException e) {
\r
195 throw new AccessorException(e);
\r
199 @SuppressWarnings("unchecked")
\r
200 public V value() throws AccessorException {
\r
202 return (V) valueCacheBinding.get(valueCache, cacheIndex);
\r
203 } catch (IndexOutOfBoundsException e) {
\r
204 throw new AccessorException(e);
\r
205 } catch (BindingException e) {
\r
206 throw new AccessorException(e);
\r
210 public double keyDouble() throws AccessorException {
\r
212 if (keyCacheBinding instanceof FloatArrayBinding) {
\r
213 return ((float[]) keyCache)[cacheIndex];
\r
215 if (keyCacheBinding instanceof DoubleArrayBinding) {
\r
216 return ((double[]) keyCache)[cacheIndex];
\r
218 if (keyCacheBinding instanceof ByteArrayBinding) {
\r
219 return ((byte[]) keyCache)[cacheIndex];
\r
221 if (keyCacheBinding instanceof IntArrayBinding) {
\r
222 return ((int[]) keyCache)[cacheIndex];
\r
224 if (keyCacheBinding instanceof LongArrayBinding) {
\r
225 return ((long[]) keyCache)[cacheIndex];
\r
227 if (keyCacheBinding instanceof BooleanArrayBinding) {
\r
228 return ((boolean[]) keyCache)[cacheIndex] ? 1.0 : 0.0;
\r
230 Object o = keyCacheBinding.get(keyCache, cacheIndex);
\r
231 Binding b = keyCacheBinding.getComponentBinding();
\r
232 if (b instanceof BooleanBinding)
\r
233 return ((BooleanBinding)b).getValue(o) ? 1.0 : 0.0;
\r
234 NumberBinding nb = (NumberBinding) b;
\r
235 return nb.getValue(o).doubleValue();
\r
236 } catch (IndexOutOfBoundsException e) {
\r
237 throw new AccessorException(e);
\r
238 } catch (BindingException e) {
\r
239 throw new AccessorException(e);
\r
243 public double valueDouble() throws AccessorException {
\r
245 if (valueCacheBinding instanceof FloatArrayBinding) {
\r
246 return ((float[]) valueCache)[cacheIndex];
\r
248 if (valueCacheBinding instanceof DoubleArrayBinding) {
\r
249 return ((double[]) valueCache)[cacheIndex];
\r
251 if (valueCacheBinding instanceof ByteArrayBinding) {
\r
252 return ((byte[]) valueCache)[cacheIndex];
\r
254 if (valueCacheBinding instanceof IntArrayBinding) {
\r
255 return ((int[]) valueCache)[cacheIndex];
\r
257 if (valueCacheBinding instanceof LongArrayBinding) {
\r
258 return ((long[]) valueCache)[cacheIndex];
\r
260 if (valueCacheBinding instanceof BooleanArrayBinding) {
\r
261 return ((boolean[]) valueCache)[cacheIndex] ? 1.0 : 0.0;
\r
263 Object o = valueCacheBinding.get(valueCache, cacheIndex);
\r
264 Binding b = valueCacheBinding.getComponentBinding();
\r
265 if (b instanceof BooleanBinding)
\r
266 return ((BooleanBinding)b).getValue(o) ? 1.0 : 0.0;
\r
267 NumberBinding nb = (NumberBinding) b;
\r
268 return nb.getValue(o).doubleValue();
\r
269 } catch (IndexOutOfBoundsException e) {
\r
270 throw new AccessorException(e);
\r
271 } catch (BindingException e) {
\r
272 throw new AccessorException(e);
\r
276 public int index() {
\r