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  package org.apache.directory.server.core.partition.impl.btree.mavibot;
20  
21  
22  import java.io.IOException;
23  
24  import org.apache.directory.api.ldap.model.constants.Loggers;
25  import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
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.cursor.Tuple;
29  import org.apache.directory.api.ldap.model.exception.LdapException;
30  import org.apache.directory.mavibot.btree.ValueCursor;
31  import org.apache.directory.server.i18n.I18n;
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  
35  
36  /**
37   * Cursor over a set of values for the same key which are store in an in
38   * memory ArrayTree.  This Cursor is limited to the same key and it's tuples
39   * will always return the same key.
40   *
41   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
42   */
43  public class KeyTupleValueCursor<K, V> extends AbstractCursor<Tuple<K, V>>
44  {
45      /** A dedicated log for cursors */
46      private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
47  
48      /** Speedup for logs */
49      private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
50  
51      private final ValueCursor<V> wrapped;
52      private final K key;
53  
54      private Tuple<K, V> returnedTuple = new Tuple<>();
55      private boolean valueAvailable;
56  
57  
58      /**
59       * Creates a Cursor over the tuples of an ArrayTree.
60       *
61       * @param cursor The wrapped cursor 
62       * @param key the constant key for which values are returned
63       */
64      public KeyTupleValueCursor( ValueCursor<V> cursor, K key )
65      {
66          this.key = key;
67  
68          this.wrapped = cursor;
69  
70          if ( IS_DEBUG )
71          {
72              LOG_CURSOR.debug( "Creating KeyTupleArrayCursor {}", this );
73          }
74      }
75  
76  
77      private void clearValue()
78      {
79          returnedTuple.setKey( key );
80          returnedTuple.setValue( null );
81          valueAvailable = false;
82      }
83  
84  
85      public boolean available()
86      {
87          return valueAvailable;
88      }
89  
90  
91      public void beforeKey( K key ) throws Exception
92      {
93          throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
94      }
95  
96  
97      public void afterKey( K key ) throws Exception
98      {
99          throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
100     }
101 
102 
103     public void beforeValue( K key, V value ) throws Exception
104     {
105         throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
106     }
107 
108 
109     public void afterValue( K key, V value ) throws Exception
110     {
111         throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
112     }
113 
114 
115     /**
116      * Positions this Cursor over the same keys before the value of the
117      * supplied element Tuple.  The supplied element Tuple's key is not
118      * considered at all.
119      *
120      * @param element the valueTuple who's value is used to position this Cursor
121      * @throws LdapException if there are failures to position the Cursor
122      * @throws CursorException if there are failures to position the Cursor
123      */
124     public void before( Tuple<K, V> element ) throws LdapException, CursorException
125     {
126         throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
127     }
128 
129 
130     /**
131      * {@inheritDoc}
132      */
133     public void after( Tuple<K, V> element ) throws LdapException, CursorException
134     {
135         throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
136     }
137 
138 
139     /**
140      * {@inheritDoc}
141      */
142     public void beforeFirst() throws LdapException, CursorException
143     {
144     }
145 
146 
147     /**
148      * {@inheritDoc}
149      */
150     public void afterLast() throws LdapException, CursorException
151     {
152     }
153 
154 
155     /**
156      * {@inheritDoc}
157      */
158     public boolean first() throws LdapException, CursorException
159     {
160         throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
161     }
162 
163 
164     /**
165      * {@inheritDoc}
166      */
167     public boolean last() throws LdapException, CursorException
168     {
169         throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
170     }
171 
172 
173     /**
174      * {@inheritDoc}
175      */
176     public boolean previous() throws LdapException, CursorException
177     {
178         checkNotClosed();
179 
180         try
181         {
182             if ( wrapped.hasPrev() )
183             {
184                 returnedTuple.setKey( key );
185                 returnedTuple.setValue( wrapped.prev() );
186                 valueAvailable = true;
187                 return true;
188             }
189             else
190             {
191                 clearValue();
192                 return false;
193             }
194         }
195         catch ( IOException e )
196         {
197             throw new CursorException( e );
198         }
199     }
200 
201 
202     /**
203      * {@inheritDoc}
204      */
205     public boolean next() throws LdapException, CursorException
206     {
207         checkNotClosed();
208 
209         try
210         {
211             if ( wrapped.hasNext() )
212             {
213                 returnedTuple.setKey( key );
214                 returnedTuple.setValue( wrapped.next() );
215 
216                 valueAvailable = true;
217                 return true;
218             }
219             else
220             {
221                 clearValue();
222 
223                 return false;
224             }
225         }
226         catch ( IOException e )
227         {
228             throw new CursorException( e );
229         }
230     }
231 
232 
233     /**
234      * {@inheritDoc}
235      */
236     public Tuple<K, V> get() throws CursorException
237     {
238         checkNotClosed();
239 
240         if ( valueAvailable )
241         {
242             return returnedTuple;
243         }
244 
245         throw new InvalidCursorPositionException();
246     }
247 
248 
249     /**
250      * {@inheritDoc}
251      */
252     @Override
253     public void close() throws IOException
254     {
255         if ( IS_DEBUG )
256         {
257             LOG_CURSOR.debug( "Closing KeyTupleArrayCursor {}", this );
258         }
259 
260         if ( wrapped != null )
261         {
262             wrapped.close();
263         }
264 
265         super.close();
266     }
267 
268 
269     /**
270      * {@inheritDoc}
271      */
272     @Override
273     public void close( Exception reason ) throws IOException
274     {
275         if ( IS_DEBUG )
276         {
277             LOG_CURSOR.debug( "Closing KeyTupleArrayCursor {}", this );
278         }
279 
280         if ( wrapped != null )
281         {
282             wrapped.close();
283         }
284 
285         super.close( reason );
286     }
287 
288 
289     /**
290      * @see Object#toString()
291      */
292     @Override
293     public String toString( String tabs )
294     {
295         StringBuilder sb = new StringBuilder();
296 
297         sb.append( tabs ).append( "KeyTupleArrayCursor (" );
298 
299         if ( available() )
300         {
301             sb.append( "available)" );
302         }
303         else
304         {
305             sb.append( "absent)" );
306         }
307 
308         sb.append( "#" ).append( key );
309 
310         sb.append( " :\n" );
311 
312         sb.append( wrapped.toString() );
313 
314         return sb.toString();
315     }
316 
317 
318     /**
319      * @see Object#toString()
320      */
321     public String toString()
322     {
323         return toString( "" );
324     }
325 }