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.core.avltree;
21
22
23 import java.io.IOException;
24
25 import org.apache.directory.api.ldap.model.constants.Loggers;
26 import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
27 import org.apache.directory.api.ldap.model.cursor.CursorException;
28 import org.apache.directory.api.ldap.model.cursor.InvalidCursorPositionException;
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 public class AvlTreeCursor<E> extends AbstractCursor<E>
40 {
41
42 private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
43
44
45 private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
46
47
48 private AvlTree<E> tree;
49
50
51 private LinkedAvlNode<E> node;
52
53
54 private Position position = Position.BEFORE_FIRST;
55
56
57 public AvlTreeCursor( AvlTree<E> tree )
58 {
59 if ( IS_DEBUG )
60 {
61 LOG_CURSOR.debug( "Creating AvlTreeCursor {}", this );
62 }
63
64 this.tree = tree;
65 }
66
67
68
69
70
71 public void after( E element ) throws LdapException, CursorException
72 {
73 checkNotClosed();
74
75 if ( element == null )
76 {
77 afterLast();
78 return;
79 }
80
81 node = tree.findGreater( element );
82
83 if ( node == null )
84 {
85 position = Position.AFTER_LAST;
86 }
87 else
88 {
89
90
91
92 position = Position.BEFORE_NODE;
93 }
94 }
95
96
97
98
99
100 public void afterLast() throws LdapException, CursorException
101 {
102 checkNotClosed();
103 node = null;
104 position = Position.AFTER_LAST;
105 }
106
107
108 public boolean available()
109 {
110 return position == Position.ON_NODE;
111 }
112
113
114
115
116
117 public void before( E element ) throws LdapException, CursorException
118 {
119 checkNotClosed();
120
121 if ( element == null )
122 {
123 beforeFirst();
124 return;
125 }
126
127 node = tree.findLess( element );
128
129 if ( node == null )
130 {
131 position = Position.BEFORE_FIRST;
132 }
133 else
134 {
135
136
137
138 position = Position.AFTER_NODE;
139 }
140 }
141
142
143
144
145
146 public void beforeFirst() throws LdapException, CursorException
147 {
148 checkNotClosed();
149 node = null;
150 position = Position.BEFORE_FIRST;
151 }
152
153
154
155
156
157 public boolean first() throws LdapException, CursorException
158 {
159 checkNotClosed();
160
161 node = tree.getFirst();
162
163 if ( node == null )
164 {
165 position = Position.BEFORE_FIRST;
166 return false;
167 }
168 else
169 {
170 position = Position.ON_NODE;
171 return true;
172 }
173 }
174
175
176
177
178
179 public E get() throws CursorException
180 {
181 checkNotClosed();
182
183 if ( position == Position.ON_NODE )
184 {
185 return node.getKey();
186 }
187
188 throw new InvalidCursorPositionException();
189 }
190
191
192
193
194
195 public boolean last() throws LdapException, CursorException
196 {
197 checkNotClosed();
198
199 node = tree.getLast();
200
201 if ( node == null )
202 {
203 position = Position.AFTER_LAST;
204 return false;
205 }
206 else
207 {
208 position = Position.ON_NODE;
209 return true;
210 }
211 }
212
213
214
215
216
217 public boolean next() throws LdapException, CursorException
218 {
219 checkNotClosed();
220
221 switch ( position )
222 {
223 case BEFORE_FIRST:
224 return first();
225
226 case BEFORE_NODE:
227 position = Position.ON_NODE;
228 return true;
229
230 case ON_NODE:
231 case AFTER_NODE:
232 node = node.next;
233 if ( node == null )
234 {
235 afterLast();
236 return false;
237 }
238 else
239 {
240 position = Position.ON_NODE;
241 return true;
242 }
243
244 case AFTER_LAST:
245 return false;
246
247 default:
248 throw new IllegalStateException( "Unexpected position " + position );
249 }
250 }
251
252
253
254
255
256 public boolean previous() throws LdapException, CursorException
257 {
258 checkNotClosed();
259
260 switch ( position )
261 {
262 case BEFORE_FIRST:
263 return false;
264
265 case BEFORE_NODE:
266 case ON_NODE:
267 node = node.previous;
268 if ( node == null )
269 {
270 beforeFirst();
271 return false;
272 }
273 else
274 {
275 position = Position.ON_NODE;
276 return true;
277 }
278
279 case AFTER_NODE:
280 position = Position.ON_NODE;
281 return true;
282
283 case AFTER_LAST:
284 return last();
285
286 default:
287 throw new IllegalStateException( "Unexpected position " + position );
288 }
289 }
290
291
292
293
294
295 @Override
296 public void close() throws IOException
297 {
298 if ( IS_DEBUG )
299 {
300 LOG_CURSOR.debug( "Closing AvlTreeCursor {}", this );
301 }
302
303 super.close();
304 }
305
306
307
308
309
310 @Override
311 public void close( Exception reason ) throws IOException
312 {
313 if ( IS_DEBUG )
314 {
315 LOG_CURSOR.debug( "Closing AvlTreeCursor {}", this );
316 }
317
318 super.close( reason );
319 }
320 }