1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.directory.server.xdbm;
20
21
22 import java.io.IOException;
23
24 import org.apache.directory.api.ldap.model.constants.Loggers;
25 import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
26 import org.apache.directory.api.ldap.model.cursor.CursorException;
27 import org.apache.directory.api.ldap.model.cursor.InvalidCursorPositionException;
28 import org.apache.directory.api.ldap.model.cursor.Tuple;
29 import org.apache.directory.api.ldap.model.exception.LdapException;
30 import org.apache.directory.server.core.avltree.ArrayTree;
31 import org.apache.directory.server.core.avltree.ArrayTreeCursor;
32 import org.apache.directory.server.i18n.I18n;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36
37
38
39
40
41
42
43
44 public class KeyTupleArrayCursor<K, V> extends AbstractCursor<Tuple<K, V>>
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 ArrayTreeCursor<V> wrapped;
53 private final K key;
54
55 private Tuple<K, V> returnedTuple = new Tuple<>();
56 private boolean valueAvailable;
57
58
59
60
61
62
63
64
65 public KeyTupleArrayCursor( ArrayTree<V> arrayTree, K key )
66 {
67 this.key = key;
68 this.wrapped = new ArrayTreeCursor<>( arrayTree );
69
70 if ( IS_DEBUG )
71 {
72 LOG_CURSOR.debug( "Creating KeyTupleArrayCursor {}", this );
73 }
74 }
75
76
77 private void clearValue()
78 {
79 returnedTuple.setKey( key );
80 returnedTuple.setValue( null );
81 valueAvailable = false;
82 }
83
84
85 public boolean available()
86 {
87 return valueAvailable;
88 }
89
90
91 public void beforeKey( K key ) throws Exception
92 {
93 throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
94 }
95
96
97 public void afterKey( K key ) throws Exception
98 {
99 throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
100 }
101
102
103 public void beforeValue( K key, V value ) throws Exception
104 {
105 checkNotClosed();
106 if ( key != null && !key.equals( this.key ) )
107 {
108 throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
109 }
110
111 wrapped.before( value );
112 clearValue();
113 }
114
115
116 public void afterValue( K key, V value ) throws Exception
117 {
118 checkNotClosed();
119 if ( key != null && !key.equals( this.key ) )
120 {
121 throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
122 }
123
124 wrapped.after( value );
125 clearValue();
126 }
127
128
129
130
131
132
133
134
135
136
137
138 public void before( Tuple<K, V> element ) throws LdapException, CursorException
139 {
140 checkNotClosed();
141 wrapped.before( element.getValue() );
142 clearValue();
143 }
144
145
146
147
148
149 public void after( Tuple<K, V> element ) throws LdapException, CursorException
150 {
151 checkNotClosed();
152 wrapped.after( element.getValue() );
153 clearValue();
154 }
155
156
157
158
159
160 public void beforeFirst() throws LdapException, CursorException
161 {
162 checkNotClosed();
163 wrapped.beforeFirst();
164 clearValue();
165 }
166
167
168
169
170
171 public void afterLast() throws LdapException, CursorException
172 {
173 checkNotClosed();
174 wrapped.afterLast();
175 clearValue();
176 }
177
178
179
180
181
182 public boolean first() throws LdapException, CursorException
183 {
184 beforeFirst();
185
186 return next();
187 }
188
189
190
191
192
193 public boolean last() throws LdapException, CursorException
194 {
195 afterLast();
196
197 return previous();
198 }
199
200
201
202
203
204 public boolean previous() throws LdapException, CursorException
205 {
206 checkNotClosed();
207 if ( wrapped.previous() )
208 {
209 returnedTuple.setKey( key );
210 returnedTuple.setValue( wrapped.get() );
211 valueAvailable = true;
212 return true;
213 }
214 else
215 {
216 clearValue();
217 return false;
218 }
219 }
220
221
222
223
224
225 public boolean next() throws LdapException, CursorException
226 {
227 checkNotClosed();
228 if ( wrapped.next() )
229 {
230 returnedTuple.setKey( key );
231 returnedTuple.setValue( wrapped.get() );
232 valueAvailable = true;
233 return true;
234 }
235 else
236 {
237 clearValue();
238 return false;
239 }
240 }
241
242
243
244
245
246 public Tuple<K, V> get() throws CursorException
247 {
248 checkNotClosed();
249
250 if ( valueAvailable )
251 {
252 return returnedTuple;
253 }
254
255 throw new InvalidCursorPositionException();
256 }
257
258
259
260
261
262 @Override
263 public void close() throws IOException
264 {
265 if ( IS_DEBUG )
266 {
267 LOG_CURSOR.debug( "Closing KeyTupleArrayCursor {}", this );
268 }
269
270 if ( wrapped != null )
271 {
272 wrapped.close();
273 }
274
275 super.close();
276 }
277
278
279
280
281
282 @Override
283 public void close( Exception reason ) throws IOException
284 {
285 if ( IS_DEBUG )
286 {
287 LOG_CURSOR.debug( "Closing KeyTupleArrayCursor {}", this );
288 }
289
290 if ( wrapped != null )
291 {
292 wrapped.close( reason );
293 }
294
295 super.close( reason );
296 }
297
298
299
300
301
302 @Override
303 public String toString( String tabs )
304 {
305 StringBuilder sb = new StringBuilder();
306
307 sb.append( tabs ).append( "KeyTupleArrayCursor (" );
308
309 if ( available() )
310 {
311 sb.append( "available)" );
312 }
313 else
314 {
315 sb.append( "absent)" );
316 }
317
318 sb.append( "#" ).append( key );
319
320 sb.append( " :\n" );
321
322 sb.append( wrapped.toString( tabs + " " ) );
323
324 return sb.toString();
325 }
326
327
328
329
330
331 public String toString()
332 {
333 return toString( "" );
334 }
335 }