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