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   *  https://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.api.ldap.model.cursor;
20  
21  
22  import java.io.IOException;
23  import java.util.Comparator;
24  
25  import org.apache.directory.api.i18n.I18n;
26  import org.apache.directory.api.ldap.model.constants.Loggers;
27  import org.apache.directory.api.ldap.model.exception.LdapException;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  
32  /**
33   * A Cursor over a single element.
34   *
35   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
36   * @param <E> The type of element on which this cursor will iterate
37   */
38  public class SingletonCursor<E> extends AbstractCursor<E>
39  {
40      /** A dedicated log for cursors */
41      private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
42  
43      /** A flag to tell if the cursor is set before the first element */
44      private boolean beforeFirst = true;
45  
46      /** A flag to tell if the cursor is set after the last element */
47      private boolean afterLast;
48  
49      /** A flag to tell if the cursor is on the element */
50      private boolean onSingleton;
51  
52      /** The comparator used for this cursor. */
53      private final Comparator<E> comparator;
54  
55      /** The unique element stored in the cursor */
56      private final E singleton;
57  
58  
59      /**
60       * Creates a new instance of SingletonCursor.
61       *
62       * @param singleton The unique element to store into this cursor
63       */
64      public SingletonCursor( E singleton )
65      {
66          this( singleton, null );
67      }
68  
69  
70      /**
71       * Creates a new instance of SingletonCursor, with its associated
72       * comparator
73       *
74       * @param singleton The unique element to store into this cursor
75       * @param comparator The associated comparator
76       */
77      public SingletonCursor( E singleton, Comparator<E> comparator )
78      {
79          if ( LOG_CURSOR.isDebugEnabled() )
80          {
81              LOG_CURSOR.debug( I18n.msg( I18n.MSG_13106_CREATING_SINGLE_CURSOR, this ) );
82          }
83  
84          this.singleton = singleton;
85          this.comparator = comparator;
86      }
87  
88  
89      /**
90       * {@inheritDoc}
91       */
92      @Override
93      public boolean available()
94      {
95          return onSingleton;
96      }
97  
98  
99      /**
100      * {@inheritDoc}
101      */
102     @Override
103     public void before( E element ) throws LdapException, CursorException
104     {
105         checkNotClosed();
106 
107         if ( comparator == null )
108         {
109             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13110_NO_COMPARATOR_CANT_MOVE_BEFORE ) );
110         }
111 
112         int comparison = comparator.compare( singleton, element );
113 
114         if ( comparison < 0 )
115         {
116             first();
117         }
118         else
119         {
120             beforeFirst();
121         }
122     }
123 
124 
125     /**
126      * {@inheritDoc}
127      */
128     @Override
129 public void after( E element ) throws LdapException, CursorException
130     {
131         checkNotClosed();
132 
133         if ( comparator == null )
134         {
135             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13111_NO_COMPARATOR_CANT_MOVE_AFTER ) );
136         }
137 
138         int comparison = comparator.compare( singleton, element );
139 
140         if ( comparison > 0 )
141         {
142             first();
143         }
144         else
145         {
146             afterLast();
147         }
148     }
149 
150 
151     /**
152      * {@inheritDoc}
153      */
154     @Override
155     public void beforeFirst() throws LdapException, CursorException
156     {
157         checkNotClosed();
158         beforeFirst = true;
159         afterLast = false;
160         onSingleton = false;
161     }
162 
163 
164     /**
165      * {@inheritDoc}
166      */
167     @Override
168     public void afterLast() throws LdapException, CursorException
169     {
170         checkNotClosed();
171         beforeFirst = false;
172         afterLast = true;
173         onSingleton = false;
174     }
175 
176 
177     /**
178      * {@inheritDoc}
179      */
180     @Override
181     public boolean first() throws LdapException, CursorException
182     {
183         checkNotClosed();
184         beforeFirst = false;
185         onSingleton = true;
186         afterLast = false;
187 
188         return true;
189     }
190 
191 
192     /**
193      * {@inheritDoc}
194      */
195     @Override
196     public boolean last() throws LdapException, CursorException
197     {
198         checkNotClosed();
199         beforeFirst = false;
200         onSingleton = true;
201         afterLast = false;
202 
203         return true;
204     }
205 
206 
207     /**
208      * {@inheritDoc}
209      */
210     @Override
211     public boolean isFirst()
212     {
213         return onSingleton;
214     }
215 
216 
217     /**
218      * {@inheritDoc}
219      */
220     @Override
221     public boolean isLast()
222     {
223         return onSingleton;
224     }
225 
226 
227     /**
228      * {@inheritDoc}
229      */
230     @Override
231     public boolean isAfterLast()
232     {
233         return afterLast;
234     }
235 
236 
237     /**
238      * {@inheritDoc}
239      */
240     @Override
241     public boolean isBeforeFirst()
242     {
243         return beforeFirst;
244     }
245 
246 
247     /**
248      * {@inheritDoc}
249      */
250     @Override
251     public boolean previous() throws LdapException, CursorException
252     {
253         checkNotClosed();
254 
255         if ( beforeFirst )
256         {
257             return false;
258         }
259 
260         if ( afterLast )
261         {
262             beforeFirst = false;
263             onSingleton = true;
264             afterLast = false;
265 
266             return true;
267         }
268 
269         // must be on the singleton
270         beforeFirst = true;
271         onSingleton = false;
272         afterLast = false;
273 
274         return false;
275     }
276 
277 
278     /**
279      * {@inheritDoc}
280      */
281     @Override
282     public boolean next() throws LdapException, CursorException
283     {
284         checkNotClosed();
285 
286         if ( beforeFirst )
287         {
288             beforeFirst = false;
289             onSingleton = true;
290             afterLast = false;
291 
292             return true;
293         }
294 
295         if ( afterLast )
296         {
297             return false;
298         }
299 
300         // must be on the singleton
301         beforeFirst = false;
302         onSingleton = false;
303         afterLast = true;
304 
305         return false;
306     }
307 
308 
309     /**
310      * {@inheritDoc}
311      */
312     @Override
313     public E get() throws CursorException
314     {
315         checkNotClosed();
316 
317         if ( onSingleton )
318         {
319             return singleton;
320         }
321 
322         if ( beforeFirst )
323         {
324             throw new InvalidCursorPositionException( I18n.err( I18n.ERR_13112_CANNOT_ACCESS_IF_BEFORE_FIRST ) );
325         }
326         else
327         {
328             throw new InvalidCursorPositionException( I18n.err( I18n.ERR_13113_CANNOT_ACCESS_IF_AFTER_LAST ) );
329         }
330     }
331 
332 
333     /**
334      * {@inheritDoc}
335      */
336     @Override
337     public void close() throws IOException
338     {
339         if ( LOG_CURSOR.isDebugEnabled() )
340         {
341             LOG_CURSOR.debug( I18n.msg( I18n.MSG_13102_CLOSING_SINGLETON_CURSOR, this ) );
342         }
343 
344         super.close();
345     }
346 
347 
348     /**
349      * {@inheritDoc}
350      */
351     @Override
352     public void close( Exception cause ) throws IOException
353     {
354         if ( LOG_CURSOR.isDebugEnabled() )
355         {
356             LOG_CURSOR.debug( I18n.msg( I18n.MSG_13102_CLOSING_SINGLETON_CURSOR, this ) );
357         }
358 
359         super.close( cause );
360     }
361 }