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.xdbm.search.impl;
21
22
23 import org.apache.directory.server.core.cursor.InvalidCursorPositionException;
24 import org.apache.directory.server.core.entry.ServerEntry;
25 import org.apache.directory.server.xdbm.IndexEntry;
26 import org.apache.directory.server.xdbm.Store;
27 import org.apache.directory.server.xdbm.AbstractIndexCursor;
28 import org.apache.directory.server.xdbm.IndexCursor;
29
30
31
32
33
34
35
36
37
38 public class SubtreeScopeCursor extends AbstractIndexCursor<Long, ServerEntry>
39 {
40 private static final String UNSUPPORTED_MSG =
41 "Scope Cursors are not ordered and do not support positioning by element.";
42
43
44 private final Store<ServerEntry> db;
45
46
47 private final SubtreeScopeEvaluator<ServerEntry> evaluator;
48
49
50 private final IndexCursor<Long,ServerEntry> scopeCursor;
51
52
53 private final IndexCursor<Long,ServerEntry> dereferencedCursor;
54
55
56 private IndexCursor<Long,ServerEntry> cursor;
57
58
59 private boolean available = false;
60
61 private Long contextEntryId;
62
63
64
65
66
67
68
69
70
71 public SubtreeScopeCursor( Store<ServerEntry> db, SubtreeScopeEvaluator<ServerEntry> evaluator ) throws Exception
72 {
73 this.db = db;
74 this.evaluator = evaluator;
75
76 if ( evaluator.getBaseId() == getContextEntryId() )
77 {
78 scopeCursor = new AllEntriesCursor( db );
79 }
80 else
81 {
82 scopeCursor = db.getSubLevelIndex().forwardCursor( evaluator.getBaseId() );
83 }
84
85 if ( evaluator.isDereferencing() )
86 {
87 dereferencedCursor = db.getSubAliasIndex().forwardCursor( evaluator.getBaseId() );
88 }
89 else
90 {
91 dereferencedCursor = null;
92 }
93 }
94
95
96 private Long getContextEntryId()
97 {
98 if ( contextEntryId == null )
99 {
100 try
101 {
102 this.contextEntryId = db.getEntryId( db.getSuffix().getNormName() );
103 }
104 catch ( Exception e )
105 {
106
107
108 }
109 }
110
111 if ( contextEntryId == null )
112 {
113 return 1L;
114 }
115
116 return contextEntryId;
117 }
118
119
120 public boolean available()
121 {
122 return available;
123 }
124
125
126 public void beforeValue( Long id, Long value ) throws Exception
127 {
128 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
129 }
130
131
132 public void before( IndexEntry<Long, ServerEntry> element ) throws Exception
133 {
134 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
135 }
136
137
138 public void afterValue( Long id, Long value ) throws Exception
139 {
140 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
141 }
142
143
144 public void after( IndexEntry<Long, ServerEntry> element ) throws Exception
145 {
146 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
147 }
148
149
150 public void beforeFirst() throws Exception
151 {
152 checkNotClosed( "beforeFirst()" );
153 cursor = scopeCursor;
154 cursor.beforeFirst();
155 available = false;
156 }
157
158
159 public void afterLast() throws Exception
160 {
161 checkNotClosed( "afterLast()" );
162 if ( evaluator.isDereferencing() )
163 {
164 cursor = dereferencedCursor;
165 }
166 else
167 {
168 cursor = scopeCursor;
169 }
170
171 cursor.afterLast();
172 available = false;
173 }
174
175
176 public boolean first() throws Exception
177 {
178 beforeFirst();
179 return next();
180 }
181
182
183 public boolean last() throws Exception
184 {
185 afterLast();
186 return previous();
187 }
188
189
190 public boolean previous() throws Exception
191 {
192 checkNotClosed( "previous()" );
193
194 if ( cursor == null )
195 {
196 afterLast();
197 }
198
199
200 if ( cursor == scopeCursor )
201 {
202
203
204
205
206 if ( evaluator.isDereferencing() )
207 {
208
209 do
210 {
211 checkNotClosed( "previous()" );
212 available = cursor.previous();
213 if ( available && db.getAliasIndex().reverseLookup( cursor.get().getId() ) == null )
214 {
215 break;
216 }
217 }
218 while ( available );
219 }
220 else
221 {
222 available = cursor.previous();
223 }
224
225 return available;
226 }
227
228
229
230
231
232
233
234 available = cursor.previous();
235 if ( ! available )
236 {
237 cursor = scopeCursor;
238 cursor.afterLast();
239
240
241 do
242 {
243 checkNotClosed( "previous()" );
244 available = cursor.previous();
245
246 if ( available && db.getAliasIndex().reverseLookup( cursor.get().getId() ) == null )
247 {
248 break;
249 }
250 }
251 while ( available );
252
253 return available;
254 }
255
256 return true;
257 }
258
259
260 public boolean next() throws Exception
261 {
262 checkNotClosed( "next()" );
263
264 if ( cursor == null )
265 {
266 beforeFirst();
267 }
268
269
270
271
272
273 if ( evaluator.isDereferencing() )
274 {
275
276 do
277 {
278 checkNotClosed( "next()" );
279 available = cursor.next();
280
281 if ( available && db.getAliasIndex().reverseLookup( cursor.get().getId() ) == null )
282 {
283 break;
284 }
285 }
286 while ( available );
287 }
288 else
289 {
290 available = cursor.next();
291 }
292
293
294 if ( cursor == dereferencedCursor )
295 {
296 return available;
297 }
298
299
300
301
302
303
304
305 if ( ! available )
306 {
307 if ( dereferencedCursor != null )
308 {
309 cursor = dereferencedCursor;
310 cursor.beforeFirst();
311 return available = cursor.next();
312 }
313
314 return false;
315 }
316
317 return true;
318 }
319
320
321 public IndexEntry<Long, ServerEntry> get() throws Exception
322 {
323 checkNotClosed( "get()" );
324 if ( available )
325 {
326 return cursor.get();
327 }
328
329 throw new InvalidCursorPositionException( "Cursor has not been positioned yet." );
330 }
331
332
333 public boolean isElementReused()
334 {
335 return scopeCursor.isElementReused() ||
336 ( dereferencedCursor != null && dereferencedCursor.isElementReused() );
337 }
338 }