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.cursor;
21  
22  
23  import java.io.IOException;
24  
25  import org.apache.directory.api.ldap.model.constants.Loggers;
26  import org.apache.directory.api.ldap.model.cursor.CursorException;
27  import org.apache.directory.api.ldap.model.cursor.InvalidCursorPositionException;
28  import org.apache.directory.api.ldap.model.exception.LdapException;
29  import org.apache.directory.api.ldap.model.filter.ExprNode;
30  import org.apache.directory.server.core.api.partition.PartitionTxn;
31  import org.apache.directory.server.i18n.I18n;
32  import org.apache.directory.server.xdbm.AbstractIndexCursor;
33  import org.apache.directory.server.xdbm.IndexEntry;
34  import org.apache.directory.server.xdbm.Store;
35  import org.apache.directory.server.xdbm.search.Evaluator;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  
40  /**
41   * A Cursor returning candidates satisfying a logical negation expression.
42   *
43   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
44   */
45  public class NotCursor<V> extends AbstractIndexCursor<V>
46  {
47      /** A dedicated log for cursors */
48      private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
49  
50      /** Speedup for logs */
51      private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
52  
53      private static final String UNSUPPORTED_MSG = I18n.err( I18n.ERR_718 );
54      private final AllEntriesCursor uuidCursor;
55      private final Evaluator<? extends ExprNode> childEvaluator;
56  
57  
58      /**
59       * Creates a new instance of an NotCursor
60       * 
61       * @param partitionTxn The transaction to use
62       * @param store The store
63       * @param childEvaluator The inner evaluator
64       * @throws LdapException If the creation failed
65       */
66      public NotCursor( PartitionTxn partitionTxn, Store store, Evaluator<? extends ExprNode> childEvaluator ) 
67              throws LdapException
68      {
69          if ( IS_DEBUG )
70          {
71              LOG_CURSOR.debug( "Creating NotCursor {}", this );
72          }
73  
74          this.childEvaluator = childEvaluator;
75          this.partitionTxn = partitionTxn;
76          this.uuidCursor = new AllEntriesCursor( partitionTxn, store );
77  
78      }
79  
80  
81      /**
82       * {@inheritDoc}
83       */
84      protected String getUnsupportedMessage()
85      {
86          return UNSUPPORTED_MSG;
87      }
88  
89  
90      /**
91       * {@inheritDoc}
92       */
93      public void beforeFirst() throws LdapException, CursorException
94      {
95          checkNotClosed();
96          uuidCursor.beforeFirst();
97          setAvailable( false );
98      }
99  
100 
101     /**
102      * {@inheritDoc}
103      */
104     public void afterLast() throws LdapException, CursorException
105     {
106         checkNotClosed();
107         uuidCursor.afterLast();
108         setAvailable( false );
109     }
110 
111 
112     /**
113      * {@inheritDoc}
114      */
115     public boolean first() throws LdapException, CursorException
116     {
117         beforeFirst();
118 
119         return next();
120     }
121 
122 
123     /**
124      * {@inheritDoc}
125      */
126     public boolean last() throws LdapException, CursorException
127     {
128         afterLast();
129 
130         return previous();
131     }
132 
133 
134     /**
135      * {@inheritDoc}
136      */
137     @Override
138     public boolean previous() throws LdapException, CursorException
139     {
140         while ( uuidCursor.previous() )
141         {
142             checkNotClosed();
143             IndexEntry<?, String> candidate = uuidCursor.get();
144 
145             if ( !childEvaluator.evaluate( partitionTxn, candidate ) )
146             {
147                 return setAvailable( true );
148             }
149         }
150 
151         return setAvailable( false );
152     }
153 
154 
155     /**
156      * {@inheritDoc}
157      */
158     @Override
159     public boolean next() throws LdapException, CursorException
160     {
161         while ( uuidCursor.next() )
162         {
163             checkNotClosed();
164             IndexEntry<?, String> candidate = uuidCursor.get();
165 
166             if ( !childEvaluator.evaluate( partitionTxn, candidate ) )
167             {
168                 return setAvailable( true );
169             }
170         }
171 
172         return setAvailable( false );
173     }
174 
175 
176     /**
177      * {@inheritDoc}
178      */
179     public IndexEntry<V, String> get() throws CursorException
180     {
181         checkNotClosed();
182 
183         if ( available() )
184         {
185             return ( IndexEntry<V, String> ) uuidCursor.get();
186         }
187 
188         throw new InvalidCursorPositionException( I18n.err( I18n.ERR_708 ) );
189     }
190 
191 
192     /**
193      * {@inheritDoc}
194      */
195     @Override
196     public void close() throws IOException
197     {
198         if ( IS_DEBUG )
199         {
200             LOG_CURSOR.debug( "Closing NotCursor {}", this );
201         }
202 
203         super.close();
204         uuidCursor.close();
205     }
206 
207 
208     /**
209      * {@inheritDoc}
210      */
211     @Override
212     public void close( Exception cause ) throws IOException
213     {
214         if ( IS_DEBUG )
215         {
216             LOG_CURSOR.debug( "Closing NotCursor {}", this );
217         }
218 
219         super.close( cause );
220         uuidCursor.close( cause );
221     }
222 
223 
224     /**
225      * @see Object#toString()
226      */
227     @Override
228     public String toString( String tabs )
229     {
230         StringBuilder sb = new StringBuilder();
231 
232         sb.append( tabs ).append( "NotCursor (" );
233 
234         if ( available() )
235         {
236             sb.append( "available)" );
237         }
238         else
239         {
240             sb.append( "absent)" );
241         }
242 
243         sb.append( tabs + "  >>" ).append( childEvaluator ).append( '\n' );
244 
245         sb.append( uuidCursor.toString( tabs + "    " ) );
246 
247         return sb.toString();
248     }
249 
250 
251     /**
252      * @see Object#toString()
253      */
254     public String toString()
255     {
256         return "";
257     }
258 }