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 */ 020 package org.apache.directory.server.core.avltree; 021 022 import org.apache.directory.shared.ldap.cursor.AbstractCursor; 023 import org.apache.directory.shared.ldap.cursor.InvalidCursorPositionException; 024 025 026 027 028 /** 029 * A Cursor for an ArrayTree. 030 * 031 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 032 * @version $Rev$, $Date$ 033 */ 034 public class ArrayTreeCursor<K> extends AbstractCursor<K> 035 { 036 /** The underlying ArrayTree */ 037 private ArrayTree<K> array; 038 039 /** The current node */ 040 private K node; 041 042 /** A flag set to true if we are pointing to a node */ 043 private boolean onNode = false; 044 045 /** A flag to tell if we are after the last node */ 046 private boolean isAfterLast = false; 047 048 /** A flag to tell if we are before the first node */ 049 private boolean isBeforeFirst = true; 050 051 /** The current position in the array */ 052 private int current; 053 054 055 /** 056 * Create a cursor on an ArrayTree 057 * @param array The array we want a cursor for 058 */ 059 public ArrayTreeCursor( ArrayTree<K> array ) 060 { 061 this.array = array; 062 current = -1; 063 } 064 065 066 /** 067 * {@inheritDoc} 068 */ 069 public void after( K element ) throws Exception 070 { 071 checkNotClosed( "after" ); 072 073 if ( element == null ) 074 { 075 afterLast(); 076 return; 077 } 078 079 int found = array.getAfterPosition( element ); 080 081 if ( found == -1 ) 082 { 083 // As the element has not been found, we move after the last 084 // position 085 afterLast(); 086 return; 087 } 088 089 // The element has been found, we have to pick the node, 090 // set the current position, and update the flags. 091 current = found; 092 //node = array.get( current ); 093 isAfterLast = false; 094 isBeforeFirst = false; 095 onNode = false; 096 } 097 098 099 /** 100 * {@inheritDoc} 101 */ 102 public void afterLast() throws Exception 103 { 104 checkNotClosed( "afterLast" ); 105 106 current = array.size() - 1; 107 node = array.getLast(); 108 isBeforeFirst = false; 109 isAfterLast = true; 110 onNode = false; 111 } 112 113 114 /** 115 * {@inheritDoc} 116 */ 117 public boolean available() 118 { 119 return onNode; 120 } 121 122 123 /** 124 * {@inheritDoc} 125 */ 126 public void before( K element ) throws Exception 127 { 128 checkNotClosed( "before" ); 129 130 if ( element == null ) 131 { 132 beforeFirst(); 133 return; 134 } 135 136 int found = array.getBeforePosition( element ); 137 138 // If the element has not been found, move to the 139 // first position 140 if ( found < 0 ) 141 { 142 beforeFirst(); 143 return; 144 } 145 146 current = found; 147 isAfterLast = false; 148 isBeforeFirst = false; 149 onNode = true; 150 node = array.get( current ); 151 } 152 153 154 /** 155 * {@inheritDoc} 156 */ 157 public void beforeFirst() throws Exception 158 { 159 checkNotClosed( "beforeFirst" ); 160 161 current = 0; 162 node = array.getFirst(); 163 isBeforeFirst = true; 164 isAfterLast = false; 165 onNode = false; 166 } 167 168 169 /** 170 * {@inheritDoc} 171 */ 172 public boolean first() throws Exception 173 { 174 checkNotClosed( "first" ); 175 176 current = 0; 177 node = array.getFirst(); 178 isBeforeFirst = false; 179 isAfterLast = false; 180 return onNode = node != null; 181 } 182 183 184 /** 185 * {@inheritDoc} 186 */ 187 public K get() throws Exception 188 { 189 checkNotClosed( "get" ); 190 191 if ( onNode ) 192 { 193 return node; 194 } 195 196 throw new InvalidCursorPositionException(); 197 } 198 199 200 /** 201 * {@inheritDoc} 202 */ 203 public boolean isElementReused() 204 { 205 return true; 206 } 207 208 209 /** 210 * {@inheritDoc} 211 */ 212 public boolean last() throws Exception 213 { 214 checkNotClosed( "last" ); 215 216 current = array.size() - 1; 217 node = array.getLast(); 218 isBeforeFirst = false; 219 isAfterLast = false; 220 return onNode = node != null; 221 } 222 223 224 /** 225 * {@inheritDoc} 226 */ 227 public boolean next() throws Exception 228 { 229 checkNotClosed( "next" ); 230 231 // If the array is empty, return false 232 if ( array.size() == 0 ) 233 { 234 return false; 235 } 236 237 // If we are at the beginning 238 if ( isBeforeFirst ) 239 { 240 current = 0; 241 node = array.getFirst(); 242 isBeforeFirst = false; 243 isAfterLast = false; 244 onNode = node != null; 245 return onNode; 246 } 247 248 if ( isAfterLast ) 249 { 250 return false; 251 } 252 253 if ( onNode ) 254 { 255 current++; 256 257 if ( current == array.size() ) 258 { 259 afterLast(); 260 return false; 261 } 262 } 263 264 node = array.get( current ); 265 onNode = node != null; 266 267 return onNode; 268 } 269 270 271 /** 272 * {@inheritDoc} 273 */ 274 public boolean previous() throws Exception 275 { 276 checkNotClosed( "previous" ); 277 278 if ( array.size() == 0 ) 279 { 280 return false; 281 } 282 283 if ( isBeforeFirst ) 284 { 285 return false; 286 } 287 288 if ( isAfterLast ) 289 { 290 current = array.size() - 1; 291 node = array.getLast(); 292 isBeforeFirst = false; 293 isAfterLast = false; 294 return onNode = node != null; 295 } 296 297 if ( onNode ) 298 { 299 current--; 300 301 if ( current < 0 ) 302 { 303 beforeFirst(); 304 return false; 305 } 306 } 307 308 node = array.get( current ); 309 onNode = node != null; 310 311 return onNode; 312 } 313 }