1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.directory.server.core.partition.impl.btree.jdbm;
20
21
22 import java.io.IOException;
23 import java.util.Comparator;
24
25 import jdbm.btree.BTree;
26 import jdbm.helper.Tuple;
27 import jdbm.helper.TupleBrowser;
28
29 import org.apache.directory.api.ldap.model.constants.Loggers;
30 import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
31 import org.apache.directory.api.ldap.model.cursor.CursorException;
32 import org.apache.directory.api.ldap.model.cursor.InvalidCursorPositionException;
33 import org.apache.directory.api.ldap.model.exception.LdapException;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38
39
40
41
42
43
44 public class KeyBTreeCursor<E> extends AbstractCursor<E>
45 {
46
47 private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
48
49
50 private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
51
52 private final Tuple tuple = new Tuple();
53
54 private final BTree btree;
55 private final Comparator<E> comparator;
56 private boolean valueAvailable;
57 private TupleBrowser browser;
58
59
60
61
62
63
64
65
66 public KeyBTreeCursor( BTree btree, Comparator<E> comparator )
67 {
68 if ( IS_DEBUG )
69 {
70 LOG_CURSOR.debug( "Creating KeyBTreeCursor {}", this );
71 }
72
73 this.btree = btree;
74 this.comparator = comparator;
75 }
76
77
78 private void clearValue()
79 {
80 tuple.setKey( null );
81 tuple.setValue( null );
82 valueAvailable = false;
83 }
84
85
86 public boolean available()
87 {
88 return valueAvailable;
89 }
90
91
92
93
94
95 public void before( E element ) throws LdapException, CursorException
96 {
97 checkNotClosed();
98 try
99 {
100 browser = btree.browse( element );
101 }
102 catch ( IOException e )
103 {
104 throw new CursorException( e );
105 }
106 clearValue();
107 }
108
109
110
111
112
113 @SuppressWarnings("unchecked")
114 public void after( E element ) throws LdapException, CursorException
115 {
116 try
117 {
118 browser = btree.browse( element );
119
120
121
122
123
124
125
126
127 while ( browser.getNext( tuple ) )
128 {
129 checkNotClosed();
130 E next = ( E ) tuple.getKey();
131 int nextCompared = comparator.compare( next, element );
132
133 if ( nextCompared > 0 )
134 {
135
136
137
138
139
140
141 browser.getPrevious( tuple );
142 clearValue();
143 return;
144 }
145 }
146
147 clearValue();
148
149 }
150 catch ( IOException e )
151 {
152 throw new CursorException( e );
153 }
154 }
155
156
157
158
159
160 public void beforeFirst() throws LdapException, CursorException
161 {
162 checkNotClosed();
163 try
164 {
165 browser = btree.browse();
166 clearValue();
167 }
168 catch ( IOException e )
169 {
170 throw new CursorException( e );
171 }
172 }
173
174
175
176
177
178 public void afterLast() throws LdapException, CursorException
179 {
180 checkNotClosed();
181 try
182 {
183 browser = btree.browse( null );
184 }
185 catch ( IOException e )
186 {
187 throw new CursorException( e );
188 }
189 }
190
191
192
193
194
195 public boolean first() throws LdapException, CursorException
196 {
197 beforeFirst();
198 return next();
199 }
200
201
202
203
204
205 public boolean last() throws LdapException, CursorException
206 {
207 afterLast();
208 return previous();
209 }
210
211
212
213
214
215 public boolean previous() throws LdapException, CursorException
216 {
217 checkNotClosed();
218
219 try
220 {
221 if ( browser == null )
222 {
223 browser = btree.browse( null );
224 }
225
226 if ( browser.getPrevious( tuple ) )
227 {
228 valueAvailable = true;
229 return true;
230 }
231 else
232 {
233 clearValue();
234 return false;
235 }
236 }
237 catch ( IOException e )
238 {
239 throw new CursorException( e );
240 }
241 }
242
243
244
245
246
247 public boolean next() throws LdapException, CursorException
248 {
249 checkNotClosed();
250
251 try
252 {
253 if ( browser == null )
254 {
255 browser = btree.browse();
256 }
257
258 if ( browser.getNext( tuple ) )
259 {
260 valueAvailable = true;
261 return true;
262 }
263 else
264 {
265 clearValue();
266
267 return false;
268 }
269 }
270 catch ( IOException e )
271 {
272 throw new CursorException( e );
273 }
274 }
275
276
277
278
279
280 public E get() throws CursorException
281 {
282 checkNotClosed();
283
284 if ( valueAvailable )
285 {
286 return ( E ) tuple.getKey();
287 }
288
289 throw new InvalidCursorPositionException();
290 }
291
292
293
294
295
296 @Override
297 public void close() throws IOException
298 {
299 if ( IS_DEBUG )
300 {
301 LOG_CURSOR.debug( "Closing KeyBTreeCursor {}", this );
302 }
303
304 super.close();
305 }
306
307
308
309
310
311 @Override
312 public void close( Exception cause ) throws IOException
313 {
314 if ( IS_DEBUG )
315 {
316 LOG_CURSOR.debug( "Closing KeyBTreeCursor {}", this );
317 }
318
319 super.close( cause );
320 }
321 }