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