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