001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 package org.apache.directory.server.core.partition.impl.btree.jdbm; 020 021 022 import jdbm.btree.BTree; 023 import jdbm.helper.Tuple; 024 import jdbm.helper.TupleBrowser; 025 026 import java.util.Comparator; 027 028 import org.apache.directory.shared.ldap.cursor.AbstractCursor; 029 import org.apache.directory.shared.ldap.cursor.InvalidCursorPositionException; 030 031 032 /** 033 * Cursor over the keys of a JDBM BTree. Obviously does not return duplicate 034 * keys since JDBM does not natively support multiple values for the same key. 035 * 036 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 037 * @version $Rev$, $Date$ 038 */ 039 public class KeyBTreeCursor<E> extends AbstractCursor<E> 040 { 041 private final Tuple tuple = new Tuple(); 042 043 private final BTree btree; 044 private final Comparator<E> comparator; 045 private boolean valueAvailable; 046 private TupleBrowser browser; 047 048 049 /** 050 * Creates a Cursor over the keys of a JDBM BTree. 051 * 052 * @param btree the JDBM BTree to build a Cursor over 053 * @param comparator the Comparator used to determine key ordering 054 * @throws Exception of there are problems accessing the BTree 055 */ 056 public KeyBTreeCursor( BTree btree, Comparator<E> comparator ) throws Exception 057 { 058 this.btree = btree; 059 this.comparator = comparator; 060 } 061 062 063 private void clearValue() 064 { 065 tuple.setKey( null ); 066 tuple.setValue( null ); 067 valueAvailable = false; 068 } 069 070 071 public boolean available() 072 { 073 return valueAvailable; 074 } 075 076 077 public void before( E element ) throws Exception 078 { 079 checkNotClosed( "before()" ); 080 browser = btree.browse( element ); 081 clearValue(); 082 } 083 084 085 @SuppressWarnings("unchecked") 086 public void after( E element ) throws Exception 087 { 088 browser = btree.browse( element ); 089 090 /* 091 * While the next value is less than or equal to the element keep 092 * advancing forward to the next item. If we cannot advance any 093 * further then stop and return. If we find a value greater than 094 * the element then we stop, backup, and return so subsequent calls 095 * to getNext() will return a value greater than the element. 096 */ 097 while ( browser.getNext( tuple ) ) 098 { 099 checkNotClosed( "after()" ); 100 E next = ( E ) tuple.getKey(); 101 int nextCompared = comparator.compare( next, element ); 102 103 if ( nextCompared <= 0 ) 104 { 105 // just continue 106 } 107 else 108 { 109 /* 110 * If we just have values greater than the element argument 111 * then we are before the first element and must backup to 112 * before the first element state for the JDBM browser which 113 * apparently the browser supports. 114 */ 115 browser.getPrevious( tuple ); 116 clearValue(); 117 return; 118 } 119 } 120 121 clearValue(); 122 // just return 123 } 124 125 126 public void beforeFirst() throws Exception 127 { 128 checkNotClosed( "beforeFirst()" ); 129 browser = btree.browse(); 130 clearValue(); 131 } 132 133 134 public void afterLast() throws Exception 135 { 136 checkNotClosed( "afterLast()" ); 137 browser = btree.browse( null ); 138 } 139 140 141 public boolean first() throws Exception 142 { 143 beforeFirst(); 144 return next(); 145 } 146 147 148 public boolean last() throws Exception 149 { 150 afterLast(); 151 return previous(); 152 } 153 154 155 public boolean previous() throws Exception 156 { 157 checkNotClosed( "previous()" ); 158 if ( browser == null ) 159 { 160 browser = btree.browse( null ); 161 } 162 163 if ( browser.getPrevious( tuple ) ) 164 { 165 return valueAvailable = true; 166 } 167 else 168 { 169 clearValue(); 170 return false; 171 } 172 } 173 174 175 public boolean next() throws Exception 176 { 177 checkNotClosed( "next()" ); 178 if ( browser == null ) 179 { 180 browser = btree.browse(); 181 } 182 183 if ( browser.getNext( tuple ) ) 184 { 185 return valueAvailable = true; 186 } 187 else 188 { 189 clearValue(); 190 return false; 191 } 192 } 193 194 195 @SuppressWarnings("unchecked") 196 public E get() throws Exception 197 { 198 checkNotClosed( "get()" ); 199 if ( valueAvailable ) 200 { 201 return ( E ) tuple.getKey(); 202 } 203 204 throw new InvalidCursorPositionException(); 205 } 206 207 208 public boolean isElementReused() 209 { 210 return false; 211 } 212 }