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.api.ldap.model.cursor;
020
021
022import java.io.IOException;
023
024import org.apache.directory.api.ldap.model.exception.LdapException;
025
026
027/**
028 * A Cursor for bidirectional traversal over elements in a dataSet. Cursors
029 * unlike Iterators or Enumerations may advance to an element by calling
030 * next() or previous() which returns true or false if the request succeeds
031 * with a viable element at the new position.  Operations for relative
032 * positioning in larger increments are provided.  If the cursor can not
033 * advance, then the Cursor is either positioned before the first element or
034 * after the last element in which case the user of the Cursor must stop
035 * advancing in the respective direction.  If an advance succeeds a get()
036 * operation retrieves the current object at the Cursors position.
037 *
038 * Although this interface presumes Cursors can advance bidirectionally,
039 * implementations may restrict this by throwing
040 * UnsupportedOperationExceptions.
041 *
042 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043 * @param <E> The type of element on which this cursor will iterate
044 */
045public interface Cursor<E> extends Iterable<E>
046{
047    /**
048     * Determines whether or not a call to get() will succeed.
049     *
050     * @return true if a call to the get() method will succeed, false otherwise
051     */
052    boolean available();
053
054
055    /**
056     * Prepares this Cursor, so a subsequent call to Cursor#next() with a
057     * true return value, will have positioned the Cursor on a dataSet 
058     * element equal to or less than the element argument but not greater.  
059     * A call to Cursor#previous() with a true return value will position 
060     * the Cursor on a dataSet element less than the argument.  If 
061     * Cursor#next() returns false then the Cursor is past the last element 
062     * and so all values in the dataSet are less than the argument.  If 
063     * Cursor#previous() returns false then the Cursor is positioned before 
064     * the first element and all elements in the dataSet are greater than 
065     * the argument.
066     *
067     * @param element the element to be positioned before
068     * @throws Exception with problems accessing the underlying btree
069     */
070    void before( E element ) throws LdapException, CursorException;
071
072
073    /**
074     * Prepares this Cursor, so a subsequent call to Cursor#previous() with a
075     * true return value, will have positioned the Cursor on a dataSet element
076     * equal to or less than the element argument but not greater. A call to
077     * Cursor#next() with a true return value will position the Cursor on a
078     * dataSet element greater than the argument.  If Cursor#next() returns
079     * false then the Cursor is past the last element and so all values in the
080     * dataSet are less than or equal to the argument.  If Cursor#previous()
081     * returns false then the Cursor is positioned before the first element
082     * and all elements in the dataSet are greater than the argument.
083     *
084     * @param element the element to be positioned after
085     * @throws Exception if there are problems positioning this cursor or if
086     * this Cursor is closed
087     */
088    void after( E element ) throws LdapException, CursorException;
089
090
091    /**
092     * Positions this Cursor before the first element.
093     *
094     * @throws Exception if there are problems positioning this cursor or if
095     * this Cursor is closed
096     */
097    void beforeFirst() throws LdapException, CursorException;
098
099
100    /**
101     * Positions this Cursor after the last element.
102     *
103     * @throws Exception if there are problems positioning this Cursor or if
104     * this Cursor is closed
105     */
106    void afterLast() throws LdapException, CursorException;
107
108
109    /**
110     * Positions this Cursor at the first element.
111     *
112     * @return true if the position has been successfully changed to the first
113     * element, false otherwise
114     * @throws Exception if there are problems positioning this Cursor or if
115     * this Cursor is closed
116     */
117    boolean first() throws LdapException, CursorException;
118
119
120    /**
121     * Is this Cursor positioned at the first element.
122     *
123     * @return true if this cursor is positioned at the first element, 
124     * false otherwise
125     * @throws Exception if there are problems querying the position of this Cursor
126     * or if this Cursor is closed
127     */
128    boolean isFirst();
129
130
131    /**
132     * Is this Cursor positioned before the first element.
133     *
134     * @return true if this cursor is positioned before the first element, 
135     * false otherwise
136     * @throws Exception if there are problems querying the position of this Cursor
137     * or if this Cursor is closed
138     */
139    boolean isBeforeFirst();
140
141
142    /**
143     * Positions this Cursor at the last element.
144     *
145     * @return true if the position has been successfully changed to the last
146     * element, false otherwise
147     * @throws Exception if there are problems positioning this Cursor or if
148     * this Cursor is closed
149     */
150    boolean last() throws LdapException, CursorException;
151
152
153    /**
154     * Is this Cursor positioned at the last element.
155     *
156     * @return true if this cursor is positioned at the last element, 
157     * false otherwise
158     * @throws Exception if there are problems querying the position of this Cursor
159     * or if this Cursor is closed
160     */
161    boolean isLast();
162
163
164    /**
165     * Is this Cursor positioned after the last element.
166     *
167     * @return true if this cursor is positioned after the last element, 
168     * false otherwise
169     * @throws Exception if there are problems querying the position of this Cursor
170     * or if this Cursor is closed
171     */
172    boolean isAfterLast();
173
174
175    /**
176     * Checks if this Cursor is closed.  Calls to this operation should not
177     * fail with exceptions if and only if the cursor is in the closed state.
178     *
179     * @return true if this Cursor is closed, false otherwise
180     */
181    boolean isClosed();
182
183
184    /**
185     * Advances this Cursor to the previous position.  If called before
186     * explicitly positioning this Cursor, the position is presumed to be
187     * after the last element and this method moves the cursor back to the
188     * last element.
189     *
190     * @return true if the advance succeeded, false otherwise
191     * @throws Exception if there are problems advancing to the next position
192     */
193    boolean previous() throws LdapException, CursorException;
194
195
196    /**
197     * Advances this Cursor to the next position.  If called before
198     * explicitly positioning this Cursor, the position is presumed to be
199     * before the first element and this method moves the cursor forward to
200     * the first element.
201     *
202     * @return true if the advance succeeded, false otherwise
203     * @throws LdapException if we have get any LDAP exception while operating
204     * the cursor
205     * @throws CursorException if there are problems advancing to this Cursor to
206     * the next position, or if this Cursor is closed 
207     * @throws IOException If we have had any IO Exception
208     */
209    boolean next() throws LdapException, CursorException;
210
211
212    /**
213     * Gets the object at the current position.  Cursor implementations may
214     * choose to reuse element objects by re-populating them on advances
215     * instead of creating new objects on each advance.
216     *
217     * @return the object at the current position
218     * @throws CursorException if the object at this Cursor's current position
219     * cannot be retrieved, or if this Cursor is closed
220     * @throws IOException If we have had any IO Exception
221     */
222    E get() throws CursorException;
223
224
225    /**
226     * Closes this Cursor and frees any resources it my have allocated.
227     * Repeated calls to this method after this Cursor has already been
228     * called should not fail with exceptions.
229     */
230    void close();
231
232
233    /**
234     * Closes this Cursor and frees any resources it my have allocated.
235     * Repeated calls to this method after this Cursor has already been
236     * called should not fail with exceptions.  The reason argument is 
237     * the Exception instance thrown instead of the standard 
238     * CursorClosedException.
239     *
240     * @param reason exception thrown when this Cursor is accessed after close
241     */
242    void close( Exception reason );
243
244
245    /**
246     * Sets a non-null closure monitor to associate with this Cursor.
247     *
248     * @param monitor the monitor to use for detecting Cursor close events
249     */
250    void setClosureMonitor( ClosureMonitor monitor );
251
252
253    /**
254     * Pretty-print a cursor and its wrapped cursor.
255     * @param tabs The spaces to add at each level
256     * @return The cursor and all it's wrapped elements, recursively printed
257     */
258    String toString( String tabs );
259}