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.xdbm.Index;
24 import org.apache.directory.server.xdbm.IndexEntry;
25 import org.apache.directory.server.xdbm.Store;
26 import org.apache.directory.server.xdbm.AbstractIndexCursor;
27 import org.apache.directory.server.xdbm.IndexCursor;
28 import org.apache.directory.server.core.cursor.InvalidCursorPositionException;
29 import org.apache.directory.server.core.entry.ServerEntry;
30 import org.apache.directory.shared.ldap.entry.Value;
31
32
33
34
35
36
37
38
39
40
41
42
43 public class EqualityCursor<V> extends AbstractIndexCursor<V, ServerEntry>
44 {
45 private static final String UNSUPPORTED_MSG =
46 "EqualityCursors only support positioning by element when a user index exists on the asserted attribute.";
47
48
49 @SuppressWarnings("unchecked")
50 private final EqualityEvaluator equalityEvaluator;
51
52
53 private final IndexCursor<V,ServerEntry> userIdxCursor;
54
55
56 private final IndexCursor<String,ServerEntry> ndnIdxCursor;
57
58
59 private boolean available = false;
60
61
62 @SuppressWarnings("unchecked")
63 public EqualityCursor( Store<ServerEntry> db, EqualityEvaluator equalityEvaluator ) throws Exception
64 {
65 this.equalityEvaluator = equalityEvaluator;
66
67 String attribute = equalityEvaluator.getExpression().getAttribute();
68 Value<V> value = equalityEvaluator.getExpression().getValue();
69 if ( db.hasUserIndexOn( attribute ) )
70 {
71 Index<V,ServerEntry> userIndex = ( Index<V, ServerEntry> ) db.getUserIndex( attribute );
72 userIdxCursor = userIndex.forwardCursor( value.get() );
73 ndnIdxCursor = null;
74 }
75 else
76 {
77 ndnIdxCursor = db.getNdnIndex().forwardCursor();
78 userIdxCursor = null;
79 }
80 }
81
82
83 public boolean available()
84 {
85 if ( userIdxCursor != null )
86 {
87 return userIdxCursor.available();
88 }
89
90 return available;
91 }
92
93
94 public void beforeValue( Long id, V value ) throws Exception
95 {
96 checkNotClosed( "beforeValue()" );
97 if ( userIdxCursor != null )
98 {
99 userIdxCursor.beforeValue( id, value );
100 }
101 else
102 {
103 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
104 }
105 }
106
107
108 public void before( IndexEntry<V, ServerEntry> element ) throws Exception
109 {
110 checkNotClosed( "before()" );
111 if ( userIdxCursor != null )
112 {
113 userIdxCursor.before( element );
114 }
115 else
116 {
117 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
118 }
119 }
120
121
122 public void afterValue( Long id, V key ) throws Exception
123 {
124 checkNotClosed( "afterValue()" );
125 if ( userIdxCursor != null )
126 {
127 userIdxCursor.afterValue( id, key );
128 }
129 else
130 {
131 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
132 }
133 }
134
135
136 public void after( IndexEntry<V, ServerEntry> element ) throws Exception
137 {
138 checkNotClosed( "after()" );
139 if ( userIdxCursor != null )
140 {
141 userIdxCursor.after( element );
142 }
143 else
144 {
145 throw new UnsupportedOperationException( UNSUPPORTED_MSG );
146 }
147 }
148
149
150 public void beforeFirst() throws Exception
151 {
152 checkNotClosed( "beforeFirst()" );
153 if ( userIdxCursor != null )
154 {
155 userIdxCursor.beforeFirst();
156 }
157 else
158 {
159 ndnIdxCursor.beforeFirst();
160 available = false;
161 }
162 }
163
164
165 public void afterLast() throws Exception
166 {
167 checkNotClosed( "afterLast()" );
168 if ( userIdxCursor != null )
169 {
170 userIdxCursor.afterLast();
171 }
172 else
173 {
174 ndnIdxCursor.afterLast();
175 available = false;
176 }
177 }
178
179
180 public boolean first() throws Exception
181 {
182 beforeFirst();
183 return next();
184 }
185
186
187 public boolean last() throws Exception
188 {
189 afterLast();
190 return previous();
191 }
192
193
194 @SuppressWarnings("unchecked")
195 public boolean previous() throws Exception
196 {
197 if ( userIdxCursor != null )
198 {
199 return userIdxCursor.previous();
200 }
201
202 while( ndnIdxCursor.previous() )
203 {
204 checkNotClosed( "previous()" );
205 IndexEntry<?,ServerEntry> candidate = ndnIdxCursor.get();
206 if ( equalityEvaluator.evaluate( candidate ) )
207 {
208 return available = true;
209 }
210 }
211
212 return available = false;
213 }
214
215
216 @SuppressWarnings("unchecked")
217 public boolean next() throws Exception
218 {
219 if ( userIdxCursor != null )
220 {
221 return userIdxCursor.next();
222 }
223
224 while( ndnIdxCursor.next() )
225 {
226 checkNotClosed( "next()" );
227 IndexEntry<?,ServerEntry> candidate = ndnIdxCursor.get();
228 if ( equalityEvaluator.evaluate( candidate ) )
229 {
230 return available = true;
231 }
232 }
233
234 return available = false;
235 }
236
237
238 @SuppressWarnings("unchecked")
239 public IndexEntry<V, ServerEntry> get() throws Exception
240 {
241 checkNotClosed( "get()" );
242 if ( userIdxCursor != null )
243 {
244 return userIdxCursor.get();
245 }
246
247 if ( available )
248 {
249 return ( IndexEntry<V, ServerEntry> )ndnIdxCursor.get();
250 }
251
252 throw new InvalidCursorPositionException( "Cursor has not been positioned yet." );
253 }
254
255
256 public boolean isElementReused()
257 {
258 if ( userIdxCursor != null )
259 {
260 return userIdxCursor.isElementReused();
261 }
262
263 return ndnIdxCursor.isElementReused();
264 }
265
266
267 public void close() throws Exception
268 {
269 super.close();
270
271 if ( userIdxCursor != null )
272 {
273 userIdxCursor.close();
274 }
275 else
276 {
277 ndnIdxCursor.close();
278 }
279 }
280 }