1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.xdbm.impl.avl;
21
22
23 import java.util.Comparator;
24
25 import org.apache.directory.api.ldap.model.cursor.Cursor;
26 import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
27 import org.apache.directory.api.ldap.model.cursor.SingletonCursor;
28 import org.apache.directory.api.ldap.model.cursor.Tuple;
29 import org.apache.directory.api.ldap.model.exception.LdapException;
30 import org.apache.directory.server.core.api.partition.PartitionTxn;
31 import org.apache.directory.server.core.avltree.AvlSingletonOrOrderedSetCursor;
32 import org.apache.directory.server.core.avltree.AvlTree;
33 import org.apache.directory.server.core.avltree.AvlTreeCursor;
34 import org.apache.directory.server.core.avltree.AvlTreeMap;
35 import org.apache.directory.server.core.avltree.AvlTreeMapImpl;
36 import org.apache.directory.server.core.avltree.AvlTreeMapNoDupsWrapperCursor;
37 import org.apache.directory.server.core.avltree.KeyTupleAvlCursor;
38 import org.apache.directory.server.core.avltree.LinkedAvlMapNode;
39 import org.apache.directory.server.core.avltree.SingletonOrOrderedSet;
40 import org.apache.directory.server.xdbm.AbstractTable;
41
42
43
44
45
46
47
48 public class AvlTable<K, V> extends AbstractTable<K, V>
49 {
50 private final AvlTreeMap<K, V> avl;
51 private final Comparator<Tuple<K, V>> keyOnlytupleComparator;
52
53
54 public AvlTable( String name, final Comparator<K> keyComparator, final Comparator<V> valueComparator,
55 boolean dupsEnabled )
56 {
57 super( null, name, keyComparator, valueComparator );
58 this.avl = new AvlTreeMapImpl<>( keyComparator, valueComparator, dupsEnabled );
59 allowsDuplicates = this.avl.isDupsAllowed();
60 this.keyOnlytupleComparator = new Comparator<Tuple<K, V>>()
61 {
62 public int compare( Tuple<K, V> t0, Tuple<K, V> t1 )
63 {
64 return keyComparator.compare( t0.getKey(), t1.getKey() );
65 }
66 };
67 }
68
69
70
71
72
73 @Override
74 public void close( PartitionTxn transaction ) throws LdapException
75 {
76 ( ( AvlTreeMapImpl<K, V> ) avl ).removeAll();
77 }
78
79
80
81
82
83 @Override
84 public long count( PartitionTxn transaction, K key ) throws LdapException
85 {
86 if ( key == null )
87 {
88 return 0L;
89 }
90
91 LinkedAvlMapNode<K, V> node = avl.find( key );
92
93 if ( node == null )
94 {
95 return 0L;
96 }
97
98 SingletonOrOrderedSet<V> val = node.getValue();
99
100 if ( val.isOrderedSet() )
101 {
102 return val.getOrderedSet().getSize();
103 }
104
105 return 1L;
106 }
107
108
109
110
111
112 @Override
113 public V get( PartitionTxn transaction, K key ) throws LdapException
114 {
115 if ( key == null )
116 {
117 return null;
118 }
119
120 LinkedAvlMapNode<K, V> node = avl.find( key );
121
122 if ( node == null )
123 {
124 return null;
125 }
126
127 SingletonOrOrderedSet<V> val = node.getValue();
128
129 if ( val.isOrderedSet() )
130 {
131 return val.getOrderedSet().getFirst().getKey();
132 }
133
134 return val.getSingleton();
135 }
136
137
138
139
140
141 @Override
142 public long greaterThanCount( PartitionTxn transaction, K key ) throws LdapException
143 {
144 return avl.getSize();
145 }
146
147
148
149
150
151 @Override
152 public boolean has( PartitionTxn transaction, K key ) throws LdapException
153 {
154 if ( key == null )
155 {
156 return false;
157 }
158
159 return avl.find( key ) != null;
160 }
161
162
163
164
165
166 @Override
167 public boolean has( PartitionTxn transaction, K key, V value ) throws LdapException
168 {
169 if ( key == null )
170 {
171 return false;
172 }
173
174 return avl.find( key, value ) != null;
175 }
176
177
178
179
180
181 @Override
182 public boolean hasGreaterOrEqual( PartitionTxn transaction, K key ) throws LdapException
183 {
184 if ( key == null )
185 {
186 return false;
187 }
188
189 return avl.findGreaterOrEqual( key ) != null;
190 }
191
192
193
194
195
196 @Override
197 public boolean hasGreaterOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
198 {
199 if ( key == null )
200 {
201 return false;
202 }
203
204 LinkedAvlMapNode<K, V> node = avl.findGreaterOrEqual( key );
205
206 if ( node == null )
207 {
208 return false;
209 }
210
211 if ( node.getValue().isOrderedSet() )
212 {
213 AvlTree<V> values = node.getValue().getOrderedSet();
214 return values.findGreaterOrEqual( val ) != null;
215 }
216
217 return valueComparator.compare( node.getValue().getSingleton(), val ) >= 0;
218 }
219
220
221
222
223
224 @Override
225 public boolean hasLessOrEqual( PartitionTxn transaction, K key ) throws LdapException
226 {
227 if ( key == null )
228 {
229 return false;
230 }
231
232 return avl.findLessOrEqual( key ) != null;
233 }
234
235
236
237
238
239 @Override
240 public boolean hasLessOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
241 {
242 if ( key == null )
243 {
244 return false;
245 }
246
247 LinkedAvlMapNode<K, V> node = avl.findLessOrEqual( key );
248
249 if ( node == null )
250 {
251 return false;
252 }
253
254 if ( node.getValue().isOrderedSet() )
255 {
256 AvlTree<V> values = node.getValue().getOrderedSet();
257 return values.findLessOrEqual( val ) != null;
258 }
259
260 return valueComparator.compare( node.getValue().getSingleton(), val ) <= 0;
261 }
262
263
264
265
266
267 @Override
268 public long lessThanCount( PartitionTxn transaction, K key ) throws LdapException
269 {
270 return count;
271 }
272
273
274
275
276
277 @Override
278 public void put( PartitionTxn partitionTxn, K key, V value ) throws LdapException
279 {
280 if ( ( key == null ) || ( value == null ) )
281 {
282 return;
283 }
284
285 if ( avl.insert( key, value ) == null )
286 {
287 count++;
288 }
289 }
290
291
292
293
294
295 @Override
296 public void remove( PartitionTxn partitionTxn, K key ) throws LdapException
297 {
298 if ( key == null )
299 {
300 return;
301 }
302
303 SingletonOrOrderedSet<V> value = avl.remove( key );
304
305 if ( value == null )
306 {
307 return;
308 }
309
310 if ( value.isOrderedSet() )
311 {
312 count -= value.getOrderedSet().getSize();
313 }
314 else
315 {
316 count--;
317 }
318 }
319
320
321
322
323
324 @Override
325 public void remove( PartitionTxn partitionTxn, K key, V value ) throws LdapException
326 {
327 if ( avl.remove( key, value ) != null )
328 {
329 count--;
330 }
331 }
332
333
334
335
336
337 @Override
338 public Cursor<Tuple<K, V>> cursor()
339 {
340 if ( !allowsDuplicates )
341 {
342 return new AvlTreeMapNoDupsWrapperCursor<>(
343 new AvlSingletonOrOrderedSetCursor<K, V>( avl ) );
344 }
345
346 return new AvlTableDupsCursor<>( this );
347 }
348
349
350
351
352
353 @Override
354 public Cursor<Tuple<K, V>> cursor( PartitionTxn partitionTxn, K key ) throws LdapException
355 {
356 if ( key == null )
357 {
358 return new EmptyCursor<>();
359 }
360
361 LinkedAvlMapNode<K, V> node = avl.find( key );
362
363 if ( node == null )
364 {
365 return new EmptyCursor<>();
366 }
367
368 if ( node.getValue().isOrderedSet() )
369 {
370 return new KeyTupleAvlCursor<>( node.getValue().getOrderedSet(), key );
371 }
372
373 return new SingletonCursor<>( new Tuple<K, V>( key, node.getValue().getSingleton() ),
374 keyOnlytupleComparator );
375 }
376
377
378
379
380
381 @Override
382 public Cursor<V> valueCursor( PartitionTxn transaction, K key ) throws LdapException
383 {
384 if ( key == null )
385 {
386 return new EmptyCursor<>();
387 }
388
389 LinkedAvlMapNode<K, V> node = avl.find( key );
390
391 if ( node == null )
392 {
393 return new EmptyCursor<>();
394 }
395
396 if ( node.getValue().isOrderedSet() )
397 {
398 return new AvlTreeCursor<>( node.getValue().getOrderedSet() );
399 }
400
401 return new SingletonCursor<>( node.getValue().getSingleton(), valueComparator );
402 }
403
404
405
406
407
408
409
410
411 AvlTreeMap<K, V> getAvlTreeMap()
412 {
413 return avl;
414 }
415 }