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