1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.directory.api.ldap.model.cursor;
20
21
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.List;
25
26 import org.apache.directory.api.i18n.I18n;
27 import org.apache.directory.api.ldap.model.constants.Loggers;
28 import org.apache.directory.api.ldap.model.exception.LdapException;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32
33
34
35
36
37
38
39
40 public class ListCursor<E> extends AbstractCursor<E>
41 {
42
43 private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
44
45
46 private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
47
48
49 private final List<E> list;
50
51
52 private final Comparator<E> comparator;
53
54
55 private final int start;
56
57
58 private final int end;
59
60
61 private int index = -1;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 public ListCursor( Comparator<E> comparator, int start, List<E> list, int end )
78 {
79 if ( list == null )
80 {
81 list = Collections.emptyList();
82 }
83
84 if ( ( start < 0 ) || ( start > list.size() ) )
85 {
86 throw new IllegalArgumentException( I18n.err( I18n.ERR_02005_START_INDEX_OUT_OF_RANGE, start ) );
87 }
88
89 if ( ( end < 0 ) || ( end > list.size() ) )
90 {
91 throw new IllegalArgumentException( I18n.err( I18n.ERR_02006_END_INDEX_OUT_OF_RANGE, end ) );
92 }
93
94
95
96 if ( ( list.size() > 0 ) && ( start >= end ) )
97 {
98 throw new IllegalArgumentException( I18n.err( I18n.ERR_02007_START_INDEX_ABOVE_END_INDEX, start, end ) );
99 }
100
101 if ( IS_DEBUG )
102 {
103 LOG_CURSOR.debug( "Creating ListCursor {}", this );
104 }
105
106 this.comparator = comparator;
107 this.list = list;
108 this.start = start;
109 this.end = end;
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 public ListCursor( int start, List<E> list, int end )
126 {
127 this( null, start, list, end );
128 }
129
130
131
132
133
134
135
136
137
138
139 public ListCursor( List<E> list, int end )
140 {
141 this( null, 0, list, end );
142 }
143
144
145
146
147
148
149
150
151
152
153
154 public ListCursor( Comparator<E> comparator, List<E> list, int end )
155 {
156 this( comparator, 0, list, end );
157 }
158
159
160
161
162
163
164
165
166
167
168 public ListCursor( int start, List<E> list )
169 {
170 this( null, start, list, list.size() );
171 }
172
173
174
175
176
177
178
179
180
181
182
183 public ListCursor( Comparator<E> comparator, int start, List<E> list )
184 {
185 this( comparator, start, list, list.size() );
186 }
187
188
189
190
191
192
193
194
195 public ListCursor( List<E> list )
196 {
197 this( null, 0, list, list.size() );
198 }
199
200
201
202
203
204
205
206
207
208 public ListCursor( Comparator<E> comparator, List<E> list )
209 {
210 this( comparator, 0, list, list.size() );
211 }
212
213
214
215
216
217 @SuppressWarnings("unchecked")
218 public ListCursor()
219 {
220 this( null, 0, Collections.EMPTY_LIST, 0 );
221 }
222
223
224
225
226
227
228
229
230 @SuppressWarnings("unchecked")
231 public ListCursor( Comparator<E> comparator )
232 {
233 this( comparator, 0, Collections.EMPTY_LIST, 0 );
234 }
235
236
237
238
239
240 public boolean available()
241 {
242 return index >= 0 && index < end;
243 }
244
245
246
247
248
249 public void before( E element ) throws LdapException, CursorException
250 {
251 checkNotClosed( "before()" );
252
253 if ( comparator == null )
254 {
255 throw new IllegalStateException();
256 }
257
258
259 if ( list.size() == 0 )
260 {
261 return;
262 }
263 else if ( list.size() == 1 )
264 {
265 if ( comparator.compare( element, list.get( 0 ) ) <= 0 )
266 {
267 beforeFirst();
268 }
269 else
270 {
271 afterLast();
272 }
273 }
274
275 throw new UnsupportedOperationException( I18n.err( I18n.ERR_02008_LIST_MAY_BE_SORTED ) );
276 }
277
278
279
280
281
282 public void after( E element ) throws LdapException, CursorException
283 {
284 checkNotClosed( "after()" );
285
286 if ( comparator == null )
287 {
288 throw new IllegalStateException();
289 }
290
291
292 if ( list.size() == 0 )
293 {
294 return;
295 }
296 else if ( list.size() == 1 )
297 {
298 if ( comparator.compare( element, list.get( 0 ) ) >= 0 )
299 {
300 afterLast();
301 }
302 else
303 {
304 beforeFirst();
305 }
306 }
307
308 throw new UnsupportedOperationException( I18n.err( I18n.ERR_02008_LIST_MAY_BE_SORTED ) );
309 }
310
311
312
313
314
315 public void beforeFirst() throws LdapException, CursorException
316 {
317 checkNotClosed( "beforeFirst()" );
318 this.index = -1;
319 }
320
321
322
323
324
325 public void afterLast() throws LdapException, CursorException
326 {
327 checkNotClosed( "afterLast()" );
328 this.index = end;
329 }
330
331
332
333
334
335 public boolean first() throws LdapException, CursorException
336 {
337 checkNotClosed( "first()" );
338
339 if ( list.size() > 0 )
340 {
341 index = start;
342
343 return true;
344 }
345
346 return false;
347 }
348
349
350
351
352
353 public boolean last() throws LdapException, CursorException
354 {
355 checkNotClosed( "last()" );
356
357 if ( list.size() > 0 )
358 {
359 index = end - 1;
360
361 return true;
362 }
363
364 return false;
365 }
366
367
368
369
370
371 @Override
372 public boolean isFirst()
373 {
374 return list.size() > 0 && index == start;
375 }
376
377
378
379
380
381 @Override
382 public boolean isLast()
383 {
384 return list.size() > 0 && index == end - 1;
385 }
386
387
388
389
390
391 @Override
392 public boolean isAfterLast()
393 {
394 return index == end;
395 }
396
397
398
399
400
401 @Override
402 public boolean isBeforeFirst()
403 {
404 return index == -1;
405 }
406
407
408
409
410
411 public boolean previous() throws LdapException, CursorException
412 {
413 checkNotClosed( "previous()" );
414
415
416 if ( index == -1 )
417 {
418 return false;
419 }
420
421
422 if ( index - 1 >= start )
423 {
424 index--;
425
426 return true;
427 }
428
429
430 if ( index <= start )
431 {
432 index = -1;
433
434 return false;
435 }
436
437 if ( list.size() <= 0 )
438 {
439 index = -1;
440 }
441
442 return false;
443 }
444
445
446
447
448
449 public boolean next() throws LdapException, CursorException
450 {
451 checkNotClosed( "next()" );
452
453
454 if ( ( list.size() > 0 ) && ( index == -1 ) )
455 {
456 index = start;
457
458 return true;
459 }
460
461
462 if ( ( list.size() > 0 ) && ( index + 1 < end ) )
463 {
464 index++;
465
466 return true;
467 }
468
469
470 if ( ( list.size() > 0 ) && ( index + 1 == end ) )
471 {
472 index++;
473
474 return false;
475 }
476
477 if ( list.size() <= 0 )
478 {
479 index = end;
480 }
481
482 return false;
483 }
484
485
486
487
488
489 public E get() throws CursorException
490 {
491 checkNotClosed( "get()" );
492
493 if ( ( index < start ) || ( index >= end ) )
494 {
495 throw new CursorException( I18n.err( I18n.ERR_02009_CURSOR_NOT_POSITIONED ) );
496 }
497
498 return list.get( index );
499 }
500
501
502
503
504
505 @Override
506 public void close()
507 {
508 if ( IS_DEBUG )
509 {
510 LOG_CURSOR.debug( "Closing ListCursor {}", this );
511 }
512
513 super.close();
514 }
515
516
517
518
519
520 @Override
521 public void close( Exception cause )
522 {
523 if ( IS_DEBUG )
524 {
525 LOG_CURSOR.debug( "Closing ListCursor {}", this );
526 }
527
528 super.close( cause );
529 }
530 }