1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.partition.impl.btree;
18
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.Iterator;
23 import java.util.NoSuchElementException;
24 import java.util.TreeSet;
25
26 import javax.naming.NamingEnumeration;
27 import javax.naming.NamingException;
28
29
30 /***
31 * NamingEnumeration that enumerates over duplicate values nested into a value
32 * using a TreeSet.
33 *
34 * @warning The Tuple returned by this listing is always the same instance
35 * object returned every time. It is reused to for the sake of efficency rather
36 * than creating a new tuple for each next() call.
37 *
38 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
39 * @version $Rev: 264732 $
40 */
41 public class DupsEnumeration implements NamingEnumeration
42 {
43 /*** Marker for whether or not next() will return successfully */
44 private boolean hasMore = true;
45 /*** The Tuple to return */
46 private final Tuple returned = new Tuple();
47 /*** The Tuple to store prefetched values with */
48 private final Tuple prefetched = new Tuple();
49 /*** The underlying no duplicates enumeration this enum expands out */
50 private final NoDupsEnumeration underlying;
51
52 /***
53 * The current Tuple returned from the underlying NoDupsEnumeration which
54 * contains TreeSets for Tuple values. A NoDupsEnumeration on a Table that
55 * allows duplicates essentially returns Strings for keys and TreeSets for
56 * their values.
57 */
58 private Tuple duplicates;
59 /***
60 * The iterator over a set of Tuple values with the same key. Basically
61 * iterates over the TreeSet values in the duplicates Tuple.
62 */
63 private Iterator dupIterator;
64
65
66
67
68
69
70
71 /***
72 * Creates a DupsEnumeration over a enumeration of Tuples holding TreeSets
73 * for values that have the same key.
74 *
75 * @param list the underlying enumeration
76 * @throws NamingException if there is a problem
77 */
78 public DupsEnumeration( NoDupsEnumeration list ) throws NamingException
79 {
80 underlying = list;
81
82
83 if ( ! underlying.hasMore() )
84 {
85 close();
86 return;
87 }
88
89 prefetch();
90 }
91
92
93
94
95
96
97
98 /***
99 * Returns the same Tuple every time but with different key/value pairs.
100 *
101 * @see javax.naming.NamingEnumeration#next()
102 */
103 public Object next() throws NamingException
104 {
105 returned.setKey( prefetched.getKey() );
106 returned.setValue( prefetched.getValue() );
107
108 prefetch();
109
110 return returned;
111 }
112
113
114 /***
115 * Returns the same Tuple every time but with different key/value pairs.
116 *
117 * @see java.util.Enumeration#nextElement()
118 */
119 public Object nextElement()
120 {
121 try
122 {
123 return next();
124 }
125 catch ( NamingException ne )
126 {
127 throw new NoSuchElementException();
128 }
129 }
130
131
132 /***
133 * @see javax.naming.NamingEnumeration#hasMore()
134 */
135 public boolean hasMore()
136 {
137 return hasMore;
138 }
139
140
141 /***
142 * Calls hasMore.
143 *
144 * @see java.util.Enumeration#hasMoreElements()
145 */
146 public boolean hasMoreElements()
147 {
148 return hasMore;
149 }
150
151
152 /***
153 * Closes the underlying NamingEnumeration
154 *
155 * @see javax.naming.NamingEnumeration#close()
156 */
157 public void close()
158 {
159 hasMore = false;
160 underlying.close();
161 }
162
163
164
165
166
167
168
169 /***
170 * Prefetches values into the prefetched Tuple taking into account that
171 * the returned Tuple values of the underlying enumeration list are really
172 * TreeSets that hold multiple sorted values for the same key.
173 *
174 * <p> The values prefetched into the prefetched Tuple are actual values
175 * taken from the TreeSet. So this NamingEnumeration simply expands out
176 * duplicate keyed Tuples which it returns. iterator is an iteration over
177 * the values held in the TreeSet returned by the underlying enumeration.
178 * The values pulled off of this iterator are put into prefetched.
179 * </p>
180 */
181 private void prefetch() throws NamingException
182 {
183
184
185
186
187 while ( null == dupIterator || ! dupIterator.hasNext() )
188 {
189
190
191
192
193 if ( underlying.hasMore() )
194 {
195 duplicates = ( Tuple ) underlying.next();
196 TreeSet set = ( TreeSet ) duplicates.getValue();
197
198 if ( underlying.doAscendingScan() )
199 {
200 dupIterator = set.iterator();
201 }
202 else
203 {
204
205
206
207
208
209
210
211
212 ArrayList list = new ArrayList( set.size() );
213 list.addAll( set );
214 Collections.reverse( list );
215 dupIterator = list.iterator();
216 }
217 }
218 else
219 {
220 close();
221 return;
222 }
223 }
224
225
226
227
228
229
230
231
232 prefetched.setKey( duplicates.getKey() );
233 prefetched.setValue( dupIterator.next() );
234 }
235 }