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.partition.impl.btree.jdbm;
21
22
23 import org.apache.directory.server.core.cursor.InvalidCursorPositionException;
24 import org.apache.directory.server.xdbm.Tuple;
25 import org.apache.directory.server.xdbm.AbstractTupleCursor;
26 import jdbm.helper.TupleBrowser;
27
28 import java.io.IOException;
29
30
31
32
33
34
35
36
37
38 public class DupsContainerCursor<K,V> extends AbstractTupleCursor<K, DupsContainer<V>>
39 {
40 private final JdbmTable<K,V> table;
41
42 private jdbm.helper.Tuple jdbmTuple = new jdbm.helper.Tuple();
43 private Tuple<K,DupsContainer<V>> returnedTuple = new Tuple<K,DupsContainer<V>>();
44 private TupleBrowser browser;
45 private boolean valueAvailable;
46 private Boolean forwardDirection;
47
48
49
50
51
52
53
54
55 public DupsContainerCursor( JdbmTable<K,V> table ) throws IOException
56 {
57 if ( ! table.isDupsEnabled() )
58 {
59 throw new IllegalStateException(
60 "This cursor can only be used with tables that have duplicate keys enabled." );
61 }
62
63 this.table = table;
64 }
65
66
67 private void clearValue()
68 {
69 returnedTuple.setKey( null );
70 returnedTuple.setValue( null );
71 jdbmTuple.setKey( null );
72 jdbmTuple.setValue( null );
73 valueAvailable = false;
74 }
75
76
77 public boolean available()
78 {
79 return valueAvailable;
80 }
81
82
83 public void beforeKey( K key ) throws Exception
84 {
85 checkNotClosed( "beforeKey()" );
86 browser = table.getBTree().browse( key );
87 forwardDirection = null;
88 clearValue();
89 }
90
91
92 @SuppressWarnings("unchecked")
93 public void afterKey( K key ) throws Exception
94 {
95 browser = table.getBTree().browse( key );
96 forwardDirection = null;
97
98
99
100
101
102
103
104
105 while ( browser.getNext( jdbmTuple ) )
106 {
107 checkNotClosed( "afterKey()" );
108 K next = ( K ) jdbmTuple.getKey();
109
110 int nextCompared = table.getKeyComparator().compare( next, key );
111
112 if ( nextCompared > 0 )
113 {
114 browser.getPrevious( jdbmTuple );
115
116
117
118
119 browser.getPrevious( jdbmTuple );
120 forwardDirection = false;
121 clearValue();
122 return;
123 }
124 }
125
126 clearValue();
127 }
128
129
130 public void beforeValue( K key, DupsContainer<V> value ) throws Exception
131 {
132 throw new UnsupportedOperationException( "Value based advances not supported." );
133 }
134
135
136 public void afterValue( K key, DupsContainer<V> value ) throws Exception
137 {
138 throw new UnsupportedOperationException( "Value based advances not supported." );
139 }
140
141
142
143
144
145
146
147
148 public void before( Tuple<K,DupsContainer<V>> element ) throws Exception
149 {
150 beforeKey( element.getKey() );
151 }
152
153
154 public void after( Tuple<K,DupsContainer<V>> element ) throws Exception
155 {
156 afterKey( element.getKey() );
157 }
158
159
160 public void beforeFirst() throws Exception
161 {
162 checkNotClosed( "afterKey()" );
163 browser = table.getBTree().browse();
164 forwardDirection = null;
165 clearValue();
166 }
167
168
169 public void afterLast() throws Exception
170 {
171 checkNotClosed( "afterKey()" );
172 browser = table.getBTree().browse( null );
173 forwardDirection = null;
174 clearValue();
175 }
176
177
178 public boolean first() throws Exception
179 {
180 beforeFirst();
181 return next();
182 }
183
184
185 public boolean last() throws Exception
186 {
187 afterLast();
188 return previous();
189 }
190
191
192 @SuppressWarnings("unchecked")
193 public boolean previous() throws Exception
194 {
195 checkNotClosed( "previous()" );
196 if ( browser == null )
197 {
198 afterLast();
199 }
200
201 boolean advanceSuccess = browser.getPrevious( jdbmTuple );
202
203
204
205 if ( forwardDirection == null && advanceSuccess )
206 {
207 forwardDirection = false;
208 }
209
210 if ( forwardDirection != null && forwardDirection )
211 {
212 advanceSuccess = browser.getPrevious( jdbmTuple );
213 forwardDirection = false;
214 }
215
216 if ( advanceSuccess )
217 {
218 returnedTuple.setKey( ( K ) jdbmTuple.getKey() );
219 returnedTuple.setValue( table.getDupsContainer( ( byte[] ) jdbmTuple.getValue() ) );
220 return valueAvailable = true;
221 }
222 else
223 {
224 clearValue();
225 return false;
226 }
227 }
228
229
230 @SuppressWarnings("unchecked")
231 public boolean next() throws Exception
232 {
233 checkNotClosed( "next()" );
234 if ( browser == null )
235 {
236 beforeFirst();
237 }
238
239 boolean advanceSuccess = browser.getNext( jdbmTuple );
240
241
242
243 if ( forwardDirection == null && advanceSuccess )
244 {
245 forwardDirection = true;
246 }
247
248 if ( forwardDirection != null && ! forwardDirection )
249 {
250 advanceSuccess = browser.getNext( jdbmTuple );
251 forwardDirection = true;
252 }
253
254 if ( advanceSuccess )
255 {
256 returnedTuple.setKey( ( K ) jdbmTuple.getKey() );
257 returnedTuple.setValue( table.getDupsContainer( ( byte[] ) jdbmTuple.getValue() ) );
258 return valueAvailable = true;
259 }
260 else
261 {
262 clearValue();
263 return false;
264 }
265 }
266
267
268 public Tuple<K,DupsContainer<V>> get() throws Exception
269 {
270 checkNotClosed( "get()" );
271 if ( valueAvailable )
272 {
273 return returnedTuple;
274 }
275
276 throw new InvalidCursorPositionException();
277 }
278
279
280 public boolean isElementReused()
281 {
282 return true;
283 }
284 }