View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.xdbm.search.impl;
21  
22  
23  import org.apache.directory.server.xdbm.IndexEntry;
24  import org.apache.directory.server.xdbm.Store;
25  import org.apache.directory.server.xdbm.AbstractIndexCursor;
26  import org.apache.directory.server.xdbm.IndexCursor;
27  import org.apache.directory.server.core.cursor.InvalidCursorPositionException;
28  import org.apache.directory.server.core.entry.ServerEntry;
29  import org.apache.directory.shared.ldap.schema.AttributeType;
30  
31  
32  /**
33   * A returning candidates satisfying an attribute presence expression.
34   *
35   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
36   * @version $$Rev$$
37   */
38  public class PresenceCursor extends AbstractIndexCursor<String, ServerEntry>
39  {
40      private static final String UNSUPPORTED_MSG =
41          "PresenceCursors do not support positioning by element without a user index on the presence attribute.";
42      private final IndexCursor<String,ServerEntry> ndnCursor;
43      private final IndexCursor<String,ServerEntry> presenceCursor;
44      private final PresenceEvaluator presenceEvaluator;
45      private boolean available = false;
46  
47  
48      public PresenceCursor( Store<ServerEntry> db, PresenceEvaluator presenceEvaluator ) throws Exception
49      {
50          this.presenceEvaluator = presenceEvaluator;
51          AttributeType type = presenceEvaluator.getAttributeType();
52  
53          if ( db.hasUserIndexOn( type.getOid() ) )
54          {
55              presenceCursor = db.getPresenceIndex().forwardCursor( type.getOid() );
56              ndnCursor = null;
57          }
58          else
59          {
60              presenceCursor = null;
61              ndnCursor = db.getNdnIndex().forwardCursor();
62          }
63      }
64  
65  
66      public boolean available()
67      {
68          if ( presenceCursor != null )
69          {
70              return presenceCursor.available();
71          }
72  
73          return available;
74      }
75  
76  
77      public void beforeValue( Long id, String value ) throws Exception
78      {
79          checkNotClosed( "beforeValue()" );
80          if ( presenceCursor != null )
81          {
82              presenceCursor.beforeValue( id, value );
83              return;
84          }
85  
86          throw new UnsupportedOperationException( UNSUPPORTED_MSG );
87      }
88  
89  
90      public void before( IndexEntry<String, ServerEntry> element ) throws Exception
91      {
92          checkNotClosed( "before()" );
93          if ( presenceCursor != null )
94          {
95              presenceCursor.before( element );
96              return;
97          }
98  
99          throw new UnsupportedOperationException( UNSUPPORTED_MSG );
100     }
101 
102 
103     public void afterValue( Long id, String value ) throws Exception
104     {
105         checkNotClosed( "afterValue()" );
106         if ( presenceCursor != null )
107         {
108             presenceCursor.afterValue( id, value );
109             return;
110         }
111 
112         throw new UnsupportedOperationException( UNSUPPORTED_MSG );
113     }
114 
115 
116     public void after( IndexEntry<String, ServerEntry> element ) throws Exception
117     {
118         checkNotClosed( "after()" );
119         if ( presenceCursor != null )
120         {
121             presenceCursor.after( element );
122             return;
123         }
124 
125         throw new UnsupportedOperationException( UNSUPPORTED_MSG );
126     }
127 
128 
129     public void beforeFirst() throws Exception
130     {
131         checkNotClosed( "beforeFirst()" );
132         if ( presenceCursor != null )
133         {
134             presenceCursor.beforeFirst();
135             return;
136         }
137 
138         ndnCursor.beforeFirst();
139         available = false;
140     }
141 
142 
143     public void afterLast() throws Exception
144     {
145         checkNotClosed( "afterLast()" );
146         if ( presenceCursor != null )
147         {
148             presenceCursor.afterLast();
149             return;
150         }
151 
152         ndnCursor.afterLast();
153         available = false;
154     }
155 
156 
157     public boolean first() throws Exception
158     {
159         checkNotClosed( "first()" );
160         if ( presenceCursor != null )
161         {
162             return presenceCursor.first();
163         }
164 
165         beforeFirst();
166         return next();
167     }
168 
169 
170     public boolean last() throws Exception
171     {
172         checkNotClosed( "last()" );
173         if ( presenceCursor != null )
174         {
175             return presenceCursor.last();
176         }
177 
178         afterLast();
179         return previous();
180     }
181 
182 
183     public boolean previous() throws Exception
184     {
185         checkNotClosed( "previous()" );
186         if ( presenceCursor != null )
187         {
188             return presenceCursor.previous();
189         }
190 
191         while ( ndnCursor.previous() )
192         {
193             checkNotClosed( "previous()" );
194             IndexEntry<?,ServerEntry> candidate = ndnCursor.get();
195             if ( presenceEvaluator.evaluate( candidate ) )
196             {
197                 return available = true;
198             }
199         }
200         
201         return available = false;
202     }
203 
204 
205     public boolean next() throws Exception
206     {
207         checkNotClosed( "next()" );
208         if ( presenceCursor != null )
209         {
210             return presenceCursor.next();
211         }
212 
213         while ( ndnCursor.next() )
214         {
215             checkNotClosed( "next()" );
216             IndexEntry<?,ServerEntry> candidate = ndnCursor.get();
217             if ( presenceEvaluator.evaluate( candidate ) )
218             {
219                 return available = true;
220             }
221         }
222 
223         return available = false;
224     }
225 
226 
227     public IndexEntry<String, ServerEntry> get() throws Exception
228     {
229         checkNotClosed( "get()" );
230         if ( presenceCursor != null )
231         {
232             if ( presenceCursor.available() )
233             {
234                 return presenceCursor.get();
235             }
236 
237             throw new InvalidCursorPositionException( "Cursor has not been positioned yet." );
238         }
239 
240         if ( available )
241         {
242             /*
243              * The value of NDN indices is the normalized dn and we want the
244              * value to be the value of the attribute in question.  So we will
245              * set that accordingly here.
246              */
247             IndexEntry<String, ServerEntry> indexEntry = ndnCursor.get();
248             indexEntry.setValue( presenceEvaluator.getAttributeType().getOid() );
249             return indexEntry;
250         }
251 
252         throw new InvalidCursorPositionException( "Cursor has not been positioned yet." );
253     }
254 
255 
256     public boolean isElementReused()
257     {
258         if ( presenceCursor != null )
259         {
260             return presenceCursor.isElementReused();
261         }
262 
263         return ndnCursor.isElementReused();
264     }
265 
266 
267     public void close() throws Exception
268     {
269         super.close();
270 
271         if ( presenceCursor != null )
272         {
273             presenceCursor.close();
274         }
275         else
276         {
277             ndnCursor.close();
278         }
279     }
280 }