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.search.impl;
21
22
23 import org.apache.directory.server.xdbm.*;
24 import org.apache.directory.server.core.cursor.InvalidCursorPositionException;
25 import org.apache.directory.server.core.entry.ServerEntry;
26
27
28
29
30
31
32
33
34
35
36
37
38 public class LessEqCursor<V> extends AbstractIndexCursor<V, ServerEntry>
39 {
40 private static final String UNSUPPORTED_MSG =
41 "LessEqCursors only support positioning by element when a user index exists on the asserted attribute.";
42
43
44 private final LessEqEvaluator lessEqEvaluator;
45
46
47 private final IndexCursor<V,ServerEntry> userIdxCursor;
48
49
50 private final IndexCursor<V,ServerEntry> ndnIdxCursor;
51
52
53
54
55
56
57 IndexEntry<V, ServerEntry> ndnCandidate;
58
59
60 private boolean available = false;
61
62
63 @SuppressWarnings("unchecked")
64 public LessEqCursor( Store<ServerEntry> db, LessEqEvaluator lessEqEvaluator ) throws Exception
65 {
66 this.lessEqEvaluator = lessEqEvaluator;
67
68 String attribute = lessEqEvaluator.getExpression().getAttribute();
69 if ( db.hasUserIndexOn( attribute ) )
70 {
71 userIdxCursor = ( ( Index<V,ServerEntry> ) db.getUserIndex( attribute ) ).forwardCursor();
72 ndnIdxCursor = null;
73 }
74 else
75 {
76 ndnIdxCursor = ( IndexCursor<V,ServerEntry> ) db.getNdnIndex().forwardCursor();
77 userIdxCursor = null;
78 }
79 }
80
81
82 public boolean available()
83 {
84 return available;
85 }
86
87
88 public void beforeValue( Long id, V value ) throws Exception
89 {
90 checkNotClosed( "beforeValue()" );
91 if ( userIdxCursor != null )
92 {
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 int compareValue = lessEqEvaluator.getComparator().compare( value,
108 lessEqEvaluator.getExpression().getValue().get() );
109
110 if ( compareValue > 0 )
111 {
112 afterLast();
113 return;
114 }
115 else if ( compareValue == 0 )
116 {
117 last();
118 previous();
119 available = false;
120 return;
121 }
122
123 userIdxCursor.beforeValue( id, value );
124 available = false;
125 }
126 else
127 {
128 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
129 }
130 }
131
132
133 @SuppressWarnings("unchecked")
134 public void before( IndexEntry<V, ServerEntry> element ) throws Exception
135 {
136 checkNotClosed( "before()" );
137 if ( userIdxCursor != null )
138 {
139
140
141
142
143
144
145
146
147
148
149
150
151
152 int compareValue = lessEqEvaluator.getComparator().compare( element.getValue(),
153 lessEqEvaluator.getExpression().getValue().get() );
154
155 if ( compareValue > 0 )
156 {
157 afterLast();
158 return;
159 }
160 else if ( compareValue == 0 )
161 {
162 last();
163 previous();
164 available = false;
165 return;
166 }
167
168 userIdxCursor.before( element );
169 available = false;
170 }
171 else
172 {
173 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
174 }
175 }
176
177
178 @SuppressWarnings("unchecked")
179 public void afterValue( Long id, V value ) throws Exception
180 {
181 checkNotClosed( "afterValue()" );
182 if ( userIdxCursor != null )
183 {
184 int comparedValue = lessEqEvaluator.getComparator().compare( value,
185 lessEqEvaluator.getExpression().getValue().get() );
186
187
188
189
190
191
192
193
194
195
196
197
198 if ( comparedValue >= 0 )
199 {
200 afterLast();
201 return;
202 }
203
204
205 userIdxCursor.afterValue( id, value );
206 available = false;
207 }
208 else
209 {
210 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
211 }
212 }
213
214
215 @SuppressWarnings("unchecked")
216 public void after( IndexEntry<V, ServerEntry> element ) throws Exception
217 {
218 checkNotClosed( "after()" );
219 if ( userIdxCursor != null )
220 {
221 int comparedValue = lessEqEvaluator.getComparator().compare( element.getValue(),
222 lessEqEvaluator.getExpression().getValue().get() );
223
224
225
226
227
228
229
230
231
232
233
234
235 if ( comparedValue >= 0 )
236 {
237 afterLast();
238 return;
239 }
240
241
242 userIdxCursor.after( element );
243 available = false;
244 }
245 else
246 {
247 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
248 }
249 }
250
251
252 public void beforeFirst() throws Exception
253 {
254 checkNotClosed( "beforeFirst()" );
255 if ( userIdxCursor != null )
256 {
257 userIdxCursor.beforeFirst();
258 }
259 else
260 {
261 ndnIdxCursor.beforeFirst();
262 ndnCandidate = null;
263 }
264
265 available = false;
266 }
267
268
269 public void afterLast() throws Exception
270 {
271 checkNotClosed( "afterLast()" );
272 if ( userIdxCursor != null )
273 {
274 IndexEntry<V,ServerEntry> advanceTo = new ForwardIndexEntry<V,ServerEntry>();
275
276 advanceTo.setValue( ( V ) lessEqEvaluator.getExpression().getValue().get() );
277 userIdxCursor.after( advanceTo );
278 }
279 else
280 {
281 ndnIdxCursor.afterLast();
282 ndnCandidate = null;
283 }
284
285 available = false;
286 }
287
288
289 public boolean first() throws Exception
290 {
291 beforeFirst();
292 return next();
293 }
294
295
296 public boolean last() throws Exception
297 {
298 afterLast();
299 return previous();
300 }
301
302
303 public boolean previous() throws Exception
304 {
305 checkNotClosed( "previous()" );
306
307 if ( userIdxCursor != null )
308 {
309
310
311
312
313
314 return available = userIdxCursor.previous();
315 }
316
317 while( ndnIdxCursor.previous() )
318 {
319 checkNotClosed( "previous()" );
320 ndnCandidate = ndnIdxCursor.get();
321 if ( lessEqEvaluator.evaluate( ndnCandidate ) )
322 {
323 return available = true;
324 }
325 else
326 {
327 ndnCandidate = null;
328 }
329 }
330
331 return available = false;
332 }
333
334
335 @SuppressWarnings("unchecked")
336 public boolean next() throws Exception
337 {
338 checkNotClosed( "next()" );
339 if ( userIdxCursor != null )
340 {
341
342
343
344
345
346
347 while ( userIdxCursor.next() )
348 {
349 checkNotClosed( "next()" );
350 IndexEntry<?,ServerEntry> candidate = userIdxCursor.get();
351 if ( lessEqEvaluator.getComparator().compare( candidate.getValue(),
352 lessEqEvaluator.getExpression().getValue().get() ) <= 0 )
353 {
354 return available = true;
355 }
356 }
357
358 return available = false;
359 }
360
361 while( ndnIdxCursor.next() )
362 {
363 checkNotClosed( "next()" );
364 ndnCandidate = ndnIdxCursor.get();
365 if ( lessEqEvaluator.evaluate( ndnCandidate ) )
366 {
367 return available = true;
368 }
369 else
370 {
371 ndnCandidate = null;
372 }
373 }
374
375 return available = false;
376 }
377
378
379 public IndexEntry<V, ServerEntry> get() throws Exception
380 {
381 checkNotClosed( "get()" );
382 if ( userIdxCursor != null )
383 {
384 if ( available )
385 {
386 return userIdxCursor.get();
387 }
388
389 throw new InvalidCursorPositionException( "Cursor has not been positioned yet." );
390 }
391
392 if ( available )
393 {
394 return ndnCandidate;
395 }
396
397 throw new InvalidCursorPositionException( "Cursor has not been positioned yet." );
398 }
399
400
401 public boolean isElementReused()
402 {
403 if ( userIdxCursor != null )
404 {
405 return userIdxCursor.isElementReused();
406 }
407
408 return ndnIdxCursor.isElementReused();
409 }
410
411
412 public void close() throws Exception
413 {
414 super.close();
415
416 if ( userIdxCursor != null )
417 {
418 userIdxCursor.close();
419 }
420 else
421 {
422 ndnIdxCursor.close();
423 ndnCandidate = null;
424 }
425 }
426 }