KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ldap > server > db > ResultFilteringEnumeration


1 /*
2  * Copyright 2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package org.apache.ldap.server.db;
18
19
20 import javax.naming.NamingEnumeration JavaDoc;
21 import javax.naming.NamingException JavaDoc;
22 import javax.naming.directory.SearchControls JavaDoc;
23 import javax.naming.directory.SearchResult JavaDoc;
24 import javax.naming.ldap.LdapContext JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.List JavaDoc;
28
29
30 /**
31  * A enumeration decorator which filters database search results as they are
32  * being enumerated back to the client caller.
33  *
34  * @see SearchResultFilter
35  * @author <a HREF="mailto:dev@directory.apache.org">Apache Directory Project</a>
36  * @version $Rev: 169198 $
37  */

38 public class ResultFilteringEnumeration implements NamingEnumeration JavaDoc
39 {
40     /** the list of filters to be applied */
41     private final List JavaDoc filters;
42     /** the underlying decorated enumeration */
43     private final NamingEnumeration JavaDoc decorated;
44
45     /** the first accepted search result that is prefetched */
46     private SearchResult JavaDoc prefetched;
47     /** flag storing closed state of this naming enumeration */
48     private boolean isClosed = false;
49     /** the controls associated with the search operation */
50     private final SearchControls JavaDoc searchControls;
51     /** the LDAP context that made the search creating this enumeration */
52     private final LdapContext JavaDoc ctx;
53
54
55     // ------------------------------------------------------------------------
56
// C O N S T R U C T O R S
57
// ------------------------------------------------------------------------
58

59
60     /**
61      * Creates a new database result filtering enumeration to decorate an
62      * underlying enumeration.
63      *
64      * @param decorated the underlying decorated enumeration
65      * @param searchControls the search controls associated with the search
66      * creating this enumeration
67      * @param ctx the LDAP context that made the search creating this
68      * enumeration
69      */

70     public ResultFilteringEnumeration( NamingEnumeration JavaDoc decorated,
71                                        SearchControls JavaDoc searchControls,
72                                        LdapContext JavaDoc ctx,
73                                        SearchResultFilter filter )
74             throws NamingException JavaDoc
75     {
76         this.searchControls = searchControls;
77         this.ctx = ctx;
78         this.filters = new ArrayList JavaDoc();
79         this.filters.add( filter );
80         this.decorated = decorated;
81
82         if ( ! decorated.hasMore() )
83         {
84             close();
85             return;
86         }
87
88         prefetch();
89     }
90
91
92     /**
93      * Creates a new database result filtering enumeration to decorate an
94      * underlying enumeration.
95      *
96      * @param decorated the underlying decorated enumeration
97      * @param searchControls the search controls associated with the search
98      * creating this enumeration
99      * @param ctx the LDAP context that made the search creating this
100      * enumeration
101      */

102     public ResultFilteringEnumeration( NamingEnumeration JavaDoc decorated,
103                                        SearchControls JavaDoc searchControls,
104                                        LdapContext JavaDoc ctx,
105                                        List JavaDoc filters )
106             throws NamingException JavaDoc
107     {
108         this.searchControls = searchControls;
109         this.ctx = ctx;
110         this.filters = new ArrayList JavaDoc();
111         this.filters.addAll( filters );
112         this.decorated = decorated;
113
114         if ( ! decorated.hasMore() )
115         {
116             close();
117             return;
118         }
119
120         prefetch();
121     }
122
123
124     // ------------------------------------------------------------------------
125
// New SearchResultFilter management methods
126
// ------------------------------------------------------------------------
127

128
129     /**
130      * Adds a database search result filter to this filtering enumeration at
131      * the very end of the filter list. Filters are applied in the order of
132      * addition.
133      *
134      * @param filter a filter to apply to the results
135      * @return the result of {@link List#add(Object)}
136      */

137     public boolean addResultFilter( SearchResultFilter filter )
138     {
139         return filters.add( filter );
140     }
141
142
143     /**
144      * Removes a database search result filter from the filter list of this
145      * filtering enumeration.
146      *
147      * @param filter a filter to remove from the filter list
148      * @return the result of {@link List#remove(Object)}
149      */

150     public boolean removeResultFilter( SearchResultFilter filter )
151     {
152         return filters.remove( filter );
153     }
154
155
156     /**
157      * Gets an unmodifiable list of filters.
158      *
159      * @return the result of {@link Collections#unmodifiableList(List)}
160      */

161     public List JavaDoc getFilters()
162     {
163         return Collections.unmodifiableList( filters );
164     }
165
166
167     // ------------------------------------------------------------------------
168
// NamingEnumeration Methods
169
// ------------------------------------------------------------------------
170

171
172     public void close() throws NamingException JavaDoc
173     {
174         isClosed = true;
175         decorated.close();
176     }
177
178
179     public boolean hasMore()
180     {
181         return !isClosed;
182     }
183
184
185     public Object JavaDoc next() throws NamingException JavaDoc
186     {
187         SearchResult JavaDoc retVal = this.prefetched;
188         prefetch();
189         return retVal;
190     }
191
192
193     // ------------------------------------------------------------------------
194
// Enumeration Methods
195
// ------------------------------------------------------------------------
196

197
198     public boolean hasMoreElements()
199     {
200         return !isClosed;
201     }
202
203
204     public Object JavaDoc nextElement()
205     {
206         SearchResult JavaDoc retVal = this.prefetched;
207
208         try
209         {
210             prefetch();
211         }
212         catch ( NamingException JavaDoc e )
213         {
214             e.printStackTrace();
215         }
216
217         return retVal;
218     }
219
220
221     // ------------------------------------------------------------------------
222
// Private utility methods
223
// ------------------------------------------------------------------------
224

225
226     /**
227      * Keeps getting results from the underlying decorated filter and applying
228      * the filters until a result is accepted by all and set as the prefetced
229      * result to return on the next() result request. If no prefetched value
230      * can be found before exhausting the decorated enumeration, then this and
231      * the underlying enumeration is closed.
232      *
233      * @throws NamingException if there are problems getting results from the
234      * underlying enumeration
235      */

236     private void prefetch() throws NamingException JavaDoc
237     {
238         SearchResult JavaDoc tmp = null;
239
240         while( decorated.hasMore() )
241         {
242             boolean accepted = true;
243             tmp = ( SearchResult JavaDoc ) decorated.next();
244
245             // don't waste using a for loop if we got 0 or 1 element
246
if ( filters.isEmpty() )
247             {
248                 this.prefetched = tmp;
249                 return;
250             }
251             else if ( filters.size() == 1 )
252             {
253                 accepted = ( ( SearchResultFilter ) filters.get( 0 ) )
254                         .accept( ctx, tmp, searchControls );
255                 if ( accepted )
256                 {
257                     this.prefetched = tmp;
258                     return;
259                 }
260
261                 continue;
262             }
263
264             // apply all filters shorting their application on result denials
265
for ( int ii = 0; ii < filters.size(); ii ++ )
266             {
267                 SearchResultFilter filter = ( SearchResultFilter ) filters.get( ii );
268                 accepted &= filter.accept( ctx, tmp, searchControls );
269
270                 if ( ! accepted )
271                 {
272                     continue;
273                 }
274             }
275
276             /*
277              * If we get here then a result has been accepted by all the
278              * filters so we set the result as the prefetched value to return
279              * on the following call to the next() or nextElement() methods
280              */

281             this.prefetched = tmp;
282             return;
283         }
284
285         /*
286          * If we get here then no result was found to be accepted by all
287          * filters before we exhausted the decorated enumeration so we close
288          */

289         close();
290     }
291 }
292
Popular Tags