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.util.Comparator;
27  
28  import jdbm.helper.TupleBrowser;
29  import jdbm.btree.BTree;
30  
31  
32  /**
33   * Cursor over a set of values for the same key which are store in another
34   * BTree.  This Cursor is limited to the same key and it's tuples will always
35   * return the same key.
36   *
37   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38   * @version $Rev$, $Date$
39   */
40  public class KeyTupleBTreeCursor<K,V> extends AbstractTupleCursor<K,V>
41  {
42      private final Comparator<V> comparator;
43      private final BTree btree;
44      private final K key;
45  
46      private jdbm.helper.Tuple valueTuple = new jdbm.helper.Tuple();
47      private Tuple<K,V> returnedTuple = new Tuple<K,V>();
48      private TupleBrowser browser;
49      private boolean valueAvailable;
50  
51  
52      /**
53       * Creates a Cursor over the tuples of a JDBM BTree.
54       *
55       * @param btree the JDBM BTree to build a Cursor over
56       * @param key the constant key for which values are returned
57       * @param comparator the Comparator used to determine <b>key</b> ordering
58       * @throws Exception of there are problems accessing the BTree
59       */
60      public KeyTupleBTreeCursor( BTree btree, K key, Comparator<V> comparator ) throws Exception
61      {
62          this.key = key;
63          this.btree = btree;
64          this.comparator = comparator;
65          this.browser = btree.browse();
66      }
67  
68  
69      private void clearValue()
70      {
71          returnedTuple.setKey( key );
72          returnedTuple.setValue( null );
73          valueAvailable = false;
74      }
75  
76  
77      public boolean available()
78      {
79          return valueAvailable;
80      }
81  
82  
83      public void beforeKey( K key ) throws Exception
84      {
85          throw new UnsupportedOperationException( "This cursor locks down the key so keywise advances are not allowed." );
86      }
87  
88  
89      public void afterKey( K key ) throws Exception
90      {
91          throw new UnsupportedOperationException( "This cursor locks down the key so keywise advances are not allowed." );
92      }
93  
94  
95      public void beforeValue( K key, V value ) throws Exception
96      {
97          checkNotClosed( "beforeValue()" );
98          if ( key != null && ! key.equals( this.key ) )
99          {
100             throw new UnsupportedOperationException( "This cursor locks down the key so keywise advances are not allowed." );
101         }
102 
103         browser = btree.browse( value );
104         clearValue();
105     }
106 
107 
108     @SuppressWarnings("unchecked")
109     public void afterValue( K key, V value ) throws Exception
110     {
111         if ( key != null && ! key.equals( this.key ) )
112         {
113             throw new UnsupportedOperationException( "This cursor locks down the key so keywise advances are not allowed." );
114         }
115 
116         browser = btree.browse( value );
117 
118         /*
119          * While the next value is less than or equal to the element keep
120          * advancing forward to the next item.  If we cannot advance any
121          * further then stop and return.  If we find a value greater than
122          * the element then we stop, backup, and return so subsequent calls
123          * to getNext() will return a value greater than the element.
124          */
125         while ( browser.getNext( valueTuple ) )
126         {
127             checkNotClosed( "afterValue" );
128 
129             V next = ( V ) valueTuple.getKey();
130 
131             int nextCompared = comparator.compare( next, value );
132 
133             if ( nextCompared <= 0 )
134             {
135                 // just continue
136             }
137             else if ( nextCompared > 0 )
138             {
139                 /*
140                  * If we just have values greater than the element argument
141                  * then we are before the first element and cannot backup, and
142                  * the call below to getPrevious() will fail.  In this special
143                  * case we just reset the Cursor's browser and return.
144                  */
145                 if ( browser.getPrevious( valueTuple ) )
146                 {
147                 }
148                 else
149                 {
150                     browser = btree.browse( this.key );
151                 }
152 
153                 clearValue();
154                 return;
155             }
156         }
157 
158         clearValue();
159     }
160 
161 
162     /**
163      * Positions this Cursor over the same keys before the value of the
164      * supplied valueTuple.  The supplied element Tuple's key is not considered at
165      * all.
166      *
167      * @param element the valueTuple who's value is used to position this Cursor
168      * @throws Exception if there are failures to position the Cursor
169      */
170     public void before( Tuple<K,V> element ) throws Exception
171     {
172         checkNotClosed( "before()" );
173         browser = btree.browse( element.getValue() );
174         clearValue();
175     }
176 
177 
178     public void after( Tuple<K,V> element ) throws Exception
179     {
180         afterValue( key, element.getValue() );
181     }
182 
183 
184     public void beforeFirst() throws Exception
185     {
186         checkNotClosed( "beforeFirst()" );
187         browser = btree.browse();
188         clearValue();
189     }
190 
191 
192     public void afterLast() throws Exception
193     {
194         checkNotClosed( "afterLast()" );
195         browser = btree.browse( null );
196     }
197 
198 
199     public boolean first() throws Exception
200     {
201         beforeFirst();
202         return next();
203     }
204 
205 
206     public boolean last() throws Exception
207     {
208         afterLast();
209         return previous();
210     }
211 
212 
213     @SuppressWarnings("unchecked")
214     public boolean previous() throws Exception
215     {
216         checkNotClosed( "previous()" );
217         if ( browser.getPrevious( valueTuple ) )
218         {
219             // work around to fix direction change problem with jdbm browser
220             if ( returnedTuple.getValue() != null &&
221                 comparator.compare( ( V ) valueTuple.getKey(), returnedTuple.getValue() ) == 0 )
222             {
223                 browser.getPrevious( valueTuple ) ;
224             }
225             returnedTuple.setKey( key );
226             returnedTuple.setValue( ( V ) valueTuple.getKey() );
227             return valueAvailable = true;
228         }
229         else
230         {
231             clearValue();
232             return false;
233         }
234     }
235 
236 
237     @SuppressWarnings("unchecked")
238     public boolean next() throws Exception
239     {
240         checkNotClosed( "next()" );
241         if ( browser.getNext( valueTuple ) )
242         {
243             // work around to fix direction change problem with jdbm browser
244             if ( returnedTuple.getValue() != null &&
245                  comparator.compare( ( V ) valueTuple.getKey(), returnedTuple.getValue() ) == 0 )
246             {
247                 browser.getNext( valueTuple ) ;
248             }
249             returnedTuple.setKey( key );
250             returnedTuple.setValue( ( V ) valueTuple.getKey() );
251             return valueAvailable = true;
252         }
253         else
254         {
255             clearValue();
256             return false;
257         }
258     }
259 
260 
261     public Tuple<K,V> get() throws Exception
262     {
263         checkNotClosed( "get()" );
264         if ( valueAvailable )
265         {
266             return returnedTuple;
267         }
268 
269         throw new InvalidCursorPositionException();
270     }
271 
272 
273     public boolean isElementReused()
274     {
275         return true;
276     }
277 }