1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.mavibot.btree;
21
22
23 import java.io.IOException;
24 import java.lang.reflect.Array;
25 import java.util.Comparator;
26
27 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
28 import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
29
30
31
32
33
34
35
36
37 abstract class AbstractValueHolder<V> implements ValueHolder<V>
38 {
39
40 protected BTree<V, V> valueBtree;
41
42
43 protected V[] valueArray;
44
45
46 protected ElementSerializer<V> valueSerializer;
47
48
49 protected int valueThresholdUp = 1;
50 protected int valueThresholdLow = 1;
51
52 protected int nbArrayElems;
53
54
55
56
57
58 public boolean isSubBtree()
59 {
60 return valueBtree != null;
61 }
62
63
64
65
66
67 public ValueHolder<V> clone() throws CloneNotSupportedException
68 {
69 ValueHolder<V> copy = ( ValueHolder<V> ) super.clone();
70
71 return copy;
72 }
73
74
75
76
77
78 public ValueCursor<V> getCursor()
79 {
80 if ( valueBtree != null )
81 {
82 return new ValueBTreeCursor<V>( valueBtree );
83 }
84 else
85 {
86 return new ValueArrayCursor<V>( valueArray );
87 }
88 }
89
90
91
92
93
94
95
96
97
98
99 private int findPos( V value )
100 {
101 if ( valueArray.length == 0 )
102 {
103 return -1;
104 }
105
106
107 int pivot = valueArray.length / 2;
108 int low = 0;
109 int high = valueArray.length - 1;
110 Comparator<V> comparator = valueSerializer.getComparator();
111
112 while ( high > low )
113 {
114 switch ( high - low )
115 {
116 case 1:
117
118 int result = comparator.compare( value, valueArray[pivot] );
119
120 if ( result == 0 )
121 {
122 return pivot;
123 }
124
125 if ( result < 0 )
126 {
127 if ( pivot == low )
128 {
129 return -( low + 1 );
130 }
131 else
132 {
133 result = comparator.compare( value, valueArray[low] );
134
135 if ( result == 0 )
136 {
137 return low;
138 }
139
140 if ( result < 0 )
141 {
142 return -( low + 1 );
143 }
144 else
145 {
146 return -( low + 2 );
147 }
148 }
149 }
150 else
151 {
152 if ( pivot == high )
153 {
154 return -( high + 2 );
155 }
156 else
157 {
158 result = comparator.compare( value, valueArray[high] );
159
160 if ( result == 0 )
161 {
162 return high;
163 }
164
165 if ( result < 0 )
166 {
167 return -( high + 1 );
168 }
169 else
170 {
171 return -( high + 2 );
172 }
173 }
174 }
175
176 default:
177
178 result = comparator.compare( value, valueArray[pivot] );
179
180 if ( result == 0 )
181 {
182 return pivot;
183 }
184
185 if ( result < 0 )
186 {
187 high = pivot - 1;
188 }
189 else
190 {
191 low = pivot + 1;
192 }
193
194 pivot = ( high + low ) / 2;
195
196 continue;
197 }
198 }
199
200 int result = comparator.compare( value, valueArray[pivot] );
201
202 if ( result == 0 )
203 {
204 return pivot;
205 }
206
207 if ( result < 0 )
208 {
209 return -( pivot + 1 );
210 }
211 else
212 {
213 return -( pivot + 2 );
214 }
215 }
216
217
218
219
220
221 private boolean arrayContains( V value )
222 {
223 if ( valueArray.length == 0 )
224 {
225 return false;
226 }
227
228
229 return findPos( value ) >= 0;
230 }
231
232
233
234
235
236 protected boolean btreeContains( V value )
237 {
238 try
239 {
240 return valueBtree.hasKey( value );
241 }
242 catch ( IOException e )
243 {
244
245 e.printStackTrace();
246 return false;
247 }
248 catch ( KeyNotFoundException knfe )
249 {
250 knfe.printStackTrace();return false;
251 }
252 }
253
254
255
256
257
258 public boolean contains( V checkedValue )
259 {
260 if ( valueArray == null )
261 {
262 return btreeContains( checkedValue );
263 }
264 else
265 {
266 return arrayContains( checkedValue );
267 }
268 }
269
270
271
272
273
274 protected abstract void createSubTree();
275
276
277
278
279
280 private void addInArray( V value )
281 {
282
283 if ( size() >= valueThresholdUp )
284 {
285
286 createSubTree();
287
288 try
289 {
290 for ( V val : valueArray )
291 {
292
293
294 valueBtree.insert( val, null );
295 }
296
297
298 nbArrayElems = 0;
299 valueArray = null;
300
301
302 valueBtree.insert( value, null );
303 }
304 catch ( IOException e )
305 {
306
307 e.printStackTrace();
308 }
309 }
310 else
311 {
312
313 if ( valueArray == null )
314 {
315 valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), 1 );
316 nbArrayElems = 1;
317 valueArray[0] = value;
318 }
319 else
320 {
321
322 int pos = findPos( value );
323
324 if ( pos >= 0 )
325 {
326
327 return;
328 }
329
330
331
332 pos = -( pos + 1 );
333
334 V[] newValueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), valueArray.length + 1 );
335
336 System.arraycopy( valueArray, 0, newValueArray, 0, pos );
337 newValueArray[pos] = value;
338 System.arraycopy( valueArray, pos, newValueArray, pos + 1, valueArray.length - pos );
339
340
341 valueArray = newValueArray;
342 }
343 }
344 }
345
346
347
348
349
350 private void addInBtree( V value )
351 {
352 try
353 {
354 valueBtree.insert( value, null );
355 }
356 catch ( IOException e )
357 {
358
359 e.printStackTrace();
360 }
361 }
362
363
364
365
366
367 public void add( V value )
368 {
369 if ( valueBtree == null )
370 {
371 addInArray( value );
372 }
373 else
374 {
375 addInBtree( value );
376 }
377 }
378 }