]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/accessor/impl/MapAccessorIterator.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / accessor / impl / MapAccessorIterator.java
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
7  *\r
8  * Contributors:\r
9  *     VTT Technical Research Centre of Finland - initial API and implementation\r
10  *******************************************************************************/\r
11 package org.simantics.databoard.accessor.impl;\r
12 \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
30 \r
31 /**\r
32  * This helper class creates an iterator to MapAccessor\r
33  *\r
34  * @param <K> key class\r
35  * @param <V> value class\r
36  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
37  */\r
38 public class MapAccessorIterator<K, V> {\r
39         \r
40         MapAccessor map;\r
41         Binding keyBinding;\r
42         Binding valueBinding;\r
43         \r
44         Object from;\r
45         boolean fromInclusive;\r
46         \r
47         Object end;\r
48         boolean endInclusive;\r
49 \r
50         ArrayBinding keyCacheBinding;\r
51         Object keyCache;\r
52         \r
53         ArrayBinding valueCacheBinding;\r
54         Object valueCache;\r
55         \r
56         // Entry index, i.e. the number of entries read starting from 0\r
57         int index = -1;\r
58         \r
59         // The number of samples written to cache\r
60         int samplesInCache = 0;\r
61         \r
62         // The index in cache\r
63         int cacheIndex = -1;\r
64         \r
65         /**\r
66          * Initialize iterator with a cache. The cache should already be allocated with some empty elements.\r
67          * @param map\r
68          * @param keyBinding\r
69          * @param from\r
70          * @param fromInclusive\r
71          * @param end\r
72          * @param endInclusive\r
73          * @param keyCacheBinding\r
74          * @param keyCache\r
75          * @param valueCacheBinding\r
76          * @param valueCache\r
77          */\r
78         public MapAccessorIterator(\r
79                         MapAccessor map, \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
83                 this.map = map;\r
84                 this.keyBinding = keyBinding;\r
85                 this.from = from;\r
86                 this.fromInclusive = fromInclusive;\r
87                 this.end = end;\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
94         }\r
95 \r
96         /**\r
97          * Initialize map accessor iterator with a default cache\r
98          * @param map\r
99          * @param keyBinding\r
100          * @param from\r
101          * @param fromInclusive\r
102          * @param end\r
103          * @param endInclusive\r
104          * @param valueBinding\r
105          * @param cacheSize\r
106          * @throws BindingException \r
107          * @throws AccessorException \r
108          */\r
109         public MapAccessorIterator(\r
110                         MapAccessor map, \r
111                         Binding keyBinding, Object from, boolean fromInclusive, Object end, boolean endInclusive,\r
112                         Binding valueBinding,\r
113                         int cacheSize) throws BindingException, AccessorException {\r
114                 this.map = map;\r
115                 this.keyBinding = keyBinding;\r
116                 this.from = from;\r
117                 this.fromInclusive = fromInclusive;\r
118                 this.end = end;\r
119                 this.endInclusive = endInclusive;\r
120                 this.valueBinding = valueBinding;\r
121                 \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
130         }\r
131 \r
132     /**\r
133          * Reads data to cache.\r
134          * \r
135          * Updates from and fromInclusive fields for next read.\r
136          * Updates samplesInCache field.\r
137          * Sets cacheIndex to 0.\r
138          * \r
139          * @throws AccessorException\r
140          */\r
141         private void fillCache() throws AccessorException {\r
142                 try {\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
145                         \r
146                         cacheIndex = -1;\r
147                         \r
148                         if (from==null) {\r
149                                 samplesInCache = 0;\r
150                                 return;\r
151                         }\r
152                 \r
153                         samplesInCache = map.getEntries(\r
154                                 keyBinding, from, fromInclusive, \r
155                                 end, endInclusive, \r
156                                 keyCacheBinding, keyCache, \r
157                                 valueCacheBinding, valueCache, \r
158                                 limit);\r
159                         \r
160                         if (samplesInCache==0) {\r
161                                 from = null;\r
162                                 return;\r
163                         }\r
164                         \r
165                         from = keyCacheBinding.get(keyCache, samplesInCache-1);\r
166                         fromInclusive = false;\r
167                 } catch (BindingException e) {\r
168                         throw new AccessorException(e);\r
169                 }\r
170         }\r
171         \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
177         }\r
178         \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
183                 cacheIndex++;\r
184                 index++;\r
185                 return true;\r
186         }\r
187 \r
188         @SuppressWarnings("unchecked")\r
189         public K key() throws AccessorException {\r
190                 try {\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
196                 }\r
197         }\r
198         \r
199         @SuppressWarnings("unchecked")\r
200         public V value() throws AccessorException {\r
201                 try {\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
207                 }\r
208         }\r
209         \r
210         public double keyDouble() throws AccessorException {\r
211                 try {\r
212                         if (keyCacheBinding instanceof FloatArrayBinding) {\r
213                                 return ((float[]) keyCache)[cacheIndex];\r
214                         }\r
215                         if (keyCacheBinding instanceof DoubleArrayBinding) {\r
216                                 return ((double[]) keyCache)[cacheIndex];\r
217                         }\r
218                         if (keyCacheBinding instanceof ByteArrayBinding) {\r
219                                 return ((byte[]) keyCache)[cacheIndex];\r
220                         }\r
221                         if (keyCacheBinding instanceof IntArrayBinding) {\r
222                                 return ((int[]) keyCache)[cacheIndex];\r
223                         }\r
224                         if (keyCacheBinding instanceof LongArrayBinding) {\r
225                                 return ((long[]) keyCache)[cacheIndex];\r
226                         }\r
227                         if (keyCacheBinding instanceof BooleanArrayBinding) {\r
228                                 return ((boolean[]) keyCache)[cacheIndex] ? 1.0 : 0.0;\r
229                         }\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
240                 }\r
241         }\r
242         \r
243         public double valueDouble() throws AccessorException {\r
244                 try {\r
245                         if (valueCacheBinding instanceof FloatArrayBinding) {\r
246                                 return ((float[]) valueCache)[cacheIndex];\r
247                         }\r
248                         if (valueCacheBinding instanceof DoubleArrayBinding) {\r
249                                 return ((double[]) valueCache)[cacheIndex];\r
250                         }\r
251                         if (valueCacheBinding instanceof ByteArrayBinding) {\r
252                                 return ((byte[]) valueCache)[cacheIndex];\r
253                         }\r
254                         if (valueCacheBinding instanceof IntArrayBinding) {\r
255                                 return ((int[]) valueCache)[cacheIndex];\r
256                         }\r
257                         if (valueCacheBinding instanceof LongArrayBinding) {\r
258                                 return ((long[]) valueCache)[cacheIndex];\r
259                         }\r
260                         if (valueCacheBinding instanceof BooleanArrayBinding) {\r
261                                 return ((boolean[]) valueCache)[cacheIndex] ? 1.0 : 0.0;\r
262                         }\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
273                 }\r
274         }\r
275         \r
276         public int index() {\r
277                 return index;\r
278         }\r
279 \r
280 }\r
281 \r