/******************************************************************************* * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. * 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.databoard.accessor.impl; import org.simantics.databoard.Bindings; import org.simantics.databoard.accessor.MapAccessor; import org.simantics.databoard.accessor.error.AccessorException; import org.simantics.databoard.binding.ArrayBinding; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.BooleanBinding; import org.simantics.databoard.binding.NumberBinding; import org.simantics.databoard.binding.error.BindingException; import org.simantics.databoard.binding.impl.BooleanArrayBinding; import org.simantics.databoard.binding.impl.ByteArrayBinding; import org.simantics.databoard.binding.impl.DoubleArrayBinding; import org.simantics.databoard.binding.impl.FloatArrayBinding; import org.simantics.databoard.binding.impl.IntArrayBinding; import org.simantics.databoard.binding.impl.LongArrayBinding; import org.simantics.databoard.type.ArrayType; import org.simantics.databoard.util.Limit; import org.simantics.databoard.util.Range; /** * This helper class creates an iterator to MapAccessor * * @param key class * @param value class * @author Toni Kalajainen */ public class MapAccessorIterator { MapAccessor map; Binding keyBinding; Binding valueBinding; Object from; boolean fromInclusive; Object end; boolean endInclusive; ArrayBinding keyCacheBinding; Object keyCache; ArrayBinding valueCacheBinding; Object valueCache; // Entry index, i.e. the number of entries read starting from 0 int index = -1; // The number of samples written to cache int samplesInCache = 0; // The index in cache int cacheIndex = -1; /** * Initialize iterator with a cache. The cache should already be allocated with some empty elements. * @param map * @param keyBinding * @param from * @param fromInclusive * @param end * @param endInclusive * @param keyCacheBinding * @param keyCache * @param valueCacheBinding * @param valueCache */ public MapAccessorIterator( MapAccessor map, Binding keyBinding, Object from, boolean fromInclusive, Object end, boolean endInclusive, ArrayBinding keyCacheBinding, Object keyCache, ArrayBinding valueCacheBinding, Object valueCache) { this.map = map; this.keyBinding = keyBinding; this.from = from; this.fromInclusive = fromInclusive; this.end = end; this.endInclusive = endInclusive; this.valueBinding = valueCacheBinding.getComponentBinding(); this.keyCacheBinding = keyCacheBinding; this.keyCache = keyCache; this.valueCacheBinding = valueCacheBinding; this.valueCache = valueCache; } /** * Initialize map accessor iterator with a default cache * @param map * @param keyBinding * @param from * @param fromInclusive * @param end * @param endInclusive * @param valueBinding * @param cacheSize * @throws BindingException * @throws AccessorException */ public MapAccessorIterator( MapAccessor map, Binding keyBinding, Object from, boolean fromInclusive, Object end, boolean endInclusive, Binding valueBinding, int cacheSize) throws BindingException, AccessorException { this.map = map; this.keyBinding = keyBinding; this.from = from; this.fromInclusive = fromInclusive; this.end = end; this.endInclusive = endInclusive; this.valueBinding = valueBinding; // TODO calc num of elements if source // int count = map.count(keyBinding, from, fromInclusive, end, endInclusive); // int len = Math.min(count, 256); Range range = new Range(Limit.inclusive(cacheSize), Limit.nolimit()); this.keyCacheBinding = Bindings.getBinding( new ArrayType(keyBinding.type(), range) ); this.keyCache = keyCacheBinding.createDefault(); this.valueCacheBinding = Bindings.getBinding( new ArrayType(valueBinding.type(), range) ); this.valueCache = valueCacheBinding.createDefault(); } /** * Reads data to cache. * * Updates from and fromInclusive fields for next read. * Updates samplesInCache field. * Sets cacheIndex to 0. * * @throws AccessorException */ private void fillCache() throws AccessorException { try { int limit = Math.min(keyCacheBinding.size(keyCache), valueCacheBinding.size(valueCache)); if (limit==0) throw new AccessorException("You should have some entries in the cache"); cacheIndex = -1; if (from==null) { samplesInCache = 0; return; } samplesInCache = map.getEntries( keyBinding, from, fromInclusive, end, endInclusive, keyCacheBinding, keyCache, valueCacheBinding, valueCache, limit); if (samplesInCache==0) { from = null; return; } from = keyCacheBinding.get(keyCache, samplesInCache-1); fromInclusive = false; } catch (BindingException e) { throw new AccessorException(e); } } public boolean hasNext() throws AccessorException { if (from==null) return false; if (cacheIndex>=samplesInCache-1) fillCache(); if (cacheIndex>=samplesInCache-1) return false; return cacheIndex+1=samplesInCache-1) fillCache(); if (cacheIndex>=samplesInCache-1) return false; cacheIndex++; index++; return true; } @SuppressWarnings("unchecked") public K key() throws AccessorException { try { return (K) keyCacheBinding.get(keyCache, cacheIndex); } catch (IndexOutOfBoundsException e) { throw new AccessorException(e); } catch (BindingException e) { throw new AccessorException(e); } } @SuppressWarnings("unchecked") public V value() throws AccessorException { try { return (V) valueCacheBinding.get(valueCache, cacheIndex); } catch (IndexOutOfBoundsException e) { throw new AccessorException(e); } catch (BindingException e) { throw new AccessorException(e); } } public double keyDouble() throws AccessorException { try { if (keyCacheBinding instanceof FloatArrayBinding) { return ((float[]) keyCache)[cacheIndex]; } if (keyCacheBinding instanceof DoubleArrayBinding) { return ((double[]) keyCache)[cacheIndex]; } if (keyCacheBinding instanceof ByteArrayBinding) { return ((byte[]) keyCache)[cacheIndex]; } if (keyCacheBinding instanceof IntArrayBinding) { return ((int[]) keyCache)[cacheIndex]; } if (keyCacheBinding instanceof LongArrayBinding) { return ((long[]) keyCache)[cacheIndex]; } if (keyCacheBinding instanceof BooleanArrayBinding) { return ((boolean[]) keyCache)[cacheIndex] ? 1.0 : 0.0; } Object o = keyCacheBinding.get(keyCache, cacheIndex); Binding b = keyCacheBinding.getComponentBinding(); if (b instanceof BooleanBinding) return ((BooleanBinding)b).getValue(o) ? 1.0 : 0.0; NumberBinding nb = (NumberBinding) b; return nb.getValue(o).doubleValue(); } catch (IndexOutOfBoundsException e) { throw new AccessorException(e); } catch (BindingException e) { throw new AccessorException(e); } } public double valueDouble() throws AccessorException { try { if (valueCacheBinding instanceof FloatArrayBinding) { return ((float[]) valueCache)[cacheIndex]; } if (valueCacheBinding instanceof DoubleArrayBinding) { return ((double[]) valueCache)[cacheIndex]; } if (valueCacheBinding instanceof ByteArrayBinding) { return ((byte[]) valueCache)[cacheIndex]; } if (valueCacheBinding instanceof IntArrayBinding) { return ((int[]) valueCache)[cacheIndex]; } if (valueCacheBinding instanceof LongArrayBinding) { return ((long[]) valueCache)[cacheIndex]; } if (valueCacheBinding instanceof BooleanArrayBinding) { return ((boolean[]) valueCache)[cacheIndex] ? 1.0 : 0.0; } Object o = valueCacheBinding.get(valueCache, cacheIndex); Binding b = valueCacheBinding.getComponentBinding(); if (b instanceof BooleanBinding) return ((BooleanBinding)b).getValue(o) ? 1.0 : 0.0; NumberBinding nb = (NumberBinding) b; return nb.getValue(o).doubleValue(); } catch (IndexOutOfBoundsException e) { throw new AccessorException(e); } catch (BindingException e) { throw new AccessorException(e); } } public int index() { return index; } }