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.jdbm;
20  
21  
22  import org.apache.directory.server.core.cursor.InvalidCursorPositionException;
23  import org.apache.directory.server.xdbm.Tuple;
24  import org.apache.directory.server.xdbm.AbstractTupleCursor;
25  
26  import java.io.IOException;
27  
28  import jdbm.helper.TupleBrowser;
29  
30  
31  /**
32   * Cursor over the Tuples of a JDBM BTree.  Duplicate keys are not supported
33   * by JDBM natively so you will not see duplicate keys.  For this reason as
34   * well before() and after() positioning only considers the key of the Tuple
35   * arguments provided.
36   *
37   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38   * @version $Rev$, $Date$
39   */
40  class NoDupsCursor<K,V> extends AbstractTupleCursor<K,V>
41  {
42      private final JdbmTable<K,V> table;
43  
44      private jdbm.helper.Tuple jdbmTuple = new jdbm.helper.Tuple();
45      private Tuple<K,V> returnedTuple = new Tuple<K,V>();
46      private TupleBrowser browser;
47      private boolean valueAvailable;
48  
49  
50      /**
51       * Creates a Cursor over the tuples of a JDBM table.
52       *
53       * @param table the JDBM Table to build a Cursor over
54       * @throws IOException of there are problems accessing the BTree
55       */
56      public NoDupsCursor( JdbmTable<K,V> table ) throws IOException
57      {
58          this.table = table;
59      }
60  
61  
62      private void clearValue()
63      {
64          returnedTuple.setKey( null );
65          returnedTuple.setValue( null );
66          jdbmTuple.setKey( null );
67          jdbmTuple.setValue( null );
68          valueAvailable = false;
69      }
70  
71  
72      public boolean available()
73      {
74          return valueAvailable;
75      }
76  
77  
78      public void beforeKey( K key ) throws Exception
79      {
80          checkNotClosed( "beforeKey()" );
81          browser = table.getBTree().browse( key );
82          clearValue();
83      }
84  
85  
86      @SuppressWarnings("unchecked")
87      public void afterKey( K key ) throws Exception
88      {
89          browser = table.getBTree().browse( key );
90  
91          /*
92           * While the next value is less than or equal to the element keep
93           * advancing forward to the next item.  If we cannot advance any
94           * further then stop and return.  If we find a value greater than
95           * the element then we stop, backup, and return so subsequent calls
96           * to getNext() will return a value greater than the element.
97           */
98          while ( browser.getNext( jdbmTuple ) )
99          {
100             checkNotClosed( "afterKey()" );
101             K next = ( K ) jdbmTuple.getKey();
102 
103             int nextCompared = table.getKeyComparator().compare( next, key );
104 
105             if ( nextCompared > 0 )
106             {
107                 browser.getPrevious( jdbmTuple );
108                 clearValue();
109                 return;
110             }
111         }
112 
113         clearValue();
114     }
115 
116 
117     public void beforeValue( K key, V value ) throws Exception
118     {
119         throw new UnsupportedOperationException( "This Cursor does not support duplicate keys." );
120     }
121 
122 
123     public void afterValue( K key, V value ) throws Exception
124     {
125         throw new UnsupportedOperationException( "This Cursor does not support duplicate keys." );
126     }
127 
128 
129     /**
130      * Positions this Cursor before the key of the supplied tuple.
131      *
132      * @param element the tuple who's key is used to position this Cursor
133      * @throws IOException if there are failures to position the Cursor
134      */
135     public void before( Tuple<K,V> element ) throws Exception
136     {
137         beforeKey( element.getKey() );
138     }
139 
140 
141     public void after( Tuple<K,V> element ) throws Exception
142     {
143         afterKey( element.getKey() );
144     }
145 
146 
147     public void beforeFirst() throws Exception
148     {
149         checkNotClosed( "beforeFirst()" );
150         browser = table.getBTree().browse();
151         clearValue();
152     }
153 
154 
155     public void afterLast() throws Exception
156     {
157         checkNotClosed( "afterLast()" );
158         browser = table.getBTree().browse( null );
159         clearValue();
160     }
161 
162 
163     public boolean first() throws Exception
164     {
165         beforeFirst();
166         return next();
167     }
168 
169 
170     public boolean last() throws Exception
171     {
172         afterLast();
173         return previous();
174     }
175 
176 
177     @SuppressWarnings("unchecked")
178     public boolean previous() throws Exception
179     {
180         checkNotClosed( "previous()" );
181         if ( browser == null )
182         {
183             afterLast();
184         }
185 
186         if ( browser.getPrevious( jdbmTuple ) )
187         {
188             if( returnedTuple.getKey() != null )
189             {
190                 if( table.getKeyComparator().compare(
191                     ( K) jdbmTuple.getKey(), ( K) returnedTuple.getKey() ) == 0 )
192                 {
193                     browser.getPrevious( jdbmTuple );
194                 }
195             }
196 
197             returnedTuple.setKey( ( K ) jdbmTuple.getKey() );
198             returnedTuple.setValue( ( V ) jdbmTuple.getValue() );
199             return valueAvailable = true;
200         }
201         else
202         {
203             clearValue();
204             return false;
205         }
206     }
207 
208 
209     @SuppressWarnings("unchecked")
210     public boolean next() throws Exception
211     {
212         checkNotClosed( "previous()" );
213         if ( browser == null )
214         {
215             beforeFirst();
216         }
217 
218         if ( browser.getNext( jdbmTuple ) )
219         {
220             if( returnedTuple.getKey() != null )
221             {
222                 if( table.getKeyComparator().compare(
223                     ( K) jdbmTuple.getKey(), ( K) returnedTuple.getKey() ) == 0 )
224                 {
225                     browser.getNext( jdbmTuple );
226                 }
227             }
228             
229             returnedTuple.setKey( ( K ) jdbmTuple.getKey() );
230             returnedTuple.setValue( ( V ) jdbmTuple.getValue() );
231             return valueAvailable = true;
232         }
233         else
234         {
235             clearValue();
236             return false;
237         }
238     }
239 
240 
241     public Tuple<K,V> get() throws Exception
242     {
243         checkNotClosed( "get()" );
244         if ( valueAvailable )
245         {
246             return returnedTuple;
247         }
248 
249         throw new InvalidCursorPositionException();
250     }
251 
252 
253     public boolean isElementReused()
254     {
255         return true;
256     }
257 }