/* XXL: The eXtensible and fleXible Library for data processing
Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger
Head of the Database Research Group
Department of Mathematics and Computer Science
University of Marburg
Germany
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; If not, see <http://www.gnu.org/licenses/>.
http://code.google.com/p/xxl/
*/
package xxl.core.cursors;
import java.util.Iterator;
import xxl.core.util.Decorator;
/**
* This class decorates an object implementing the interface
* {@link xxl.core.cursors.Cursor} such that all method calls on the decorator
* are passed to its decorated object. For these purposes it realizes the
* design pattern, named <i>Decorator</i>. The intent of this design pattern is
* to attach additional responsibilities to an object dynamically. So
* decorators provide a flexible alternative to subclassing for extending
* functionality. For further information see: "Gamma et al.:
* <i>DesignPatterns. Elements of Reusable Object-Oriented Software.</i>
* Addision Wesley 1998."
*
* <p><b>Note:</b> When the given input iteration only implements the interface
* {@link java.util.Iterator} it is wrapped to a cursor by a call to the static
* method {@link xxl.core.cursors.Cursors#wrap(Iterator) wrap}.
*
* @param <E> the type of the elements returned by this iteration.
* @see java.util.Iterator
* @see xxl.core.cursors.Cursor
*/
public abstract class DecoratorCursor<E> implements Cursor<E>, Decorator<Cursor<E>> {
/**
* The decorated cursor that is used for passing method calls to.
*/
protected Cursor<E> cursor;
/**
* Creates a new decorator-cursor. The given iterator is wrapped to a
* cursor by calling the method
* {@link xxl.core.cursors.Cursors#wrap(java.util.Iterator)} and all method
* calls are finally passed to it.
*
* @param iterator the iterator to be decorated.
*/
public DecoratorCursor(Iterator<E> iterator) {
this.cursor = Cursors.wrap(iterator);
}
/**
* Opens the cursor, i.e., signals the cursor to reserve resources, open
* files, etc. Before a cursor has been opened calls to methods like
* <code>next</code> or <code>peek</code> are not guaranteed to yield
* proper results. Therefore <code>open</code> must be called before a
* cursor's data can be processed. Multiple calls to <code>open</code> do
* not have any effect, i.e., if <code>open</code> was called the cursor
* remains in the state <i>opened</i> until its <code>close</code> method
* is called.
*
* <p>Note, that a call to the <code>open</code> method of a closed cursor
* usually does not open it again because of the fact that its state
* generally cannot be restored when resources are released respectively
* files are closed.</p>
*/
public void open() {
cursor.open();
}
/**
* Closes the cursor, i.e., signals the cursor to clean up resources, close
* files, etc. When a cursor has been closed calls to methods like
* <code>next</code> or <code>peek</code> are not guaranteed to yield
* proper results. Multiple calls to <code>close</code> do not have any
* effect, i.e., if <code>close</code> was called the cursor remains in the
* state <i>closed</i>.
*
* <p>Note, that a closed cursor usually cannot be opened again because of
* the fact that its state generally cannot be restored when resources are
* released respectively files are closed.</p>
*/
public void close() {
cursor.close();
}
/**
* Returns <code>true</code> if the iteration has more elements. (In other
* words, returns <code>true</code> if <code>next</code> or
* <code>peek</code> would return an element rather than throwing an
* exception.)
*
* <p>This operation is implemented idempotent, i.e., consequent calls to
* <code>hasNext</code> do not have any effect.</p>
*
* @return <code>true</code> if the cursor has more elements.
* @throws IllegalStateException if the cursor is already closed when this
* method is called.
*/
public boolean hasNext() throws IllegalStateException {
return cursor.hasNext();
}
/**
* Returns the next element in the iteration.
*
* @return the next element in the iteration.
* @throws IllegalStateException if the cursor is already closed when this
* method is called.
*/
public E next() throws IllegalStateException {
return cursor.next();
}
/**
* Shows the next element in the iteration without proceeding the iteration
* (optional operation).
*
* <p>Note, that this operation is optional and might not work for all
* cursors. After calling the <code>peek</code> method a call to
* <code>next</code> is strongly recommended.</p>
*
* @return the next element in the iteration.
* @throws IllegalStateException if the cursor is already closed when this
* method is called.
*/
public E peek() throws IllegalStateException {
return cursor.peek();
}
/**
* Returns <code>true</code> if the <code>peek</code> operation is
* supported by the cursor. Otherwise it returns <code>false</code>.
*
* @return <code>true</code> if the <code>peek</code> operation is
* supported by the cursor, otherwise <code>false</code>.
*/
public boolean supportsPeek() {
return cursor.supportsPeek();
}
/**
* Removes from the underlying data structure the last element returned by
* the cursor (optional operation).
*
* <p>Note, that this operation is optional and might not work for all
* cursors.</p>
*/
public void remove() {
cursor.remove();
}
/**
* Returns <code>true</code> if the <code>remove</code> operation is
* supported by the cursor. Otherwise it returns <code>false</code>.
*
* @return <code>true</code> if the <code>remove</code> operation is
* supported by the cursor, otherwise <code>false</code>.
*/
public boolean supportsRemove() {
return cursor.supportsRemove();
}
/**
* Replaces the last element returned by the cursor in the underlying data
* structure (optional operation).
*
* <p>Note, that this operation is optional and might not work for all
* cursors.</p>
*
* @param object the object that replaces the last element returned by the
* cursor.
*/
public void update(E object) {
cursor.update(object);
}
/**
* Returns <code>true</code> if the <code>update</code> operation is
* supported by the cursor. Otherwise it returns <code>false</code>.
*
* @return <code>true</code> if the <code>update</code> operation is
* supported by the cursor, otherwise <code>false</code>.
*/
public boolean supportsUpdate() {
return cursor.supportsUpdate();
}
/**
* Resets the cursor to its initial state such that the caller is able to
* traverse the underlying data structure again without constructing a new
* cursor (optional operation). The modifications, removes and updates
* concerning the underlying data structure, are still persistent.
*
* <p>Note, that this operation is optional and might not work for all
* cursors.</p>
*/
public void reset() {
cursor.reset();
}
/**
* Returns <code>true</code> if the <code>reset</code> operation is
* supported by the cursor. Otherwise it returns <code>false</code>.
*
* @return <code>true</code> if the <code>reset</code> operation is
* supported by the cursor, otherwise <code>false</code>.
*/
public boolean supportsReset() {
return cursor.supportsReset();
}
/**
* Returns the cursor decorated by this decorator cursor, that is used for
* passing method calls to. Note that is returned cursor and the iterator
* submitted at construction time are usually not the same, because the
* submitted iterator will be wrapped by a call to the method
* {@link xxl.core.cursors.Cursors#wrap(java.util.Iterator)}.
*
* @return the cursor decorated by this decorator cursor.
*/
@Override
public Cursor<E> getDecoree() {
return cursor;
}
}