/* 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.collections.sweepAreas; import java.util.Iterator; import xxl.core.cursors.AbstractCursor; import xxl.core.predicates.Predicate; import xxl.core.util.metaData.AbstractMetaDataManagement; import xxl.core.util.metaData.CompositeMetaData; import xxl.core.util.metaData.ExternalTriggeredPeriodicMetaData; import xxl.core.util.metaData.MetaDataManagement; /** * A pre-implementation of the interface {@link SweepAreaImplementor}. * It provides the basic code for the initialization of a * SweepAreaImplementor as well as a default implementation of * the retrieval functionality. * * @see SweepAreaImplementor * @see xxl.core.predicates.Predicate * @see java.util.Iterator */ public abstract class AbstractSAImplementor<E> implements SweepAreaImplementor<E> { public class AbstractSAImplementorMetaDataManagement extends AbstractMetaDataManagement<Object,Object> implements ExternalTriggeredPeriodicMetaData { @Override protected boolean addMetaData(Object metaDataIdentifier) { return false; } @Override protected boolean removeMetaData(Object metaDataIdentifier) { return false; } public void updatePeriodicMetaData(long period) { } public boolean needsPeriodicUpdate(Object metaDataIdentifier) { return false; } } /** * Binary predicates used to query this implementor. * To offer a retrieval depending on the ID passed * to the query calls, an implementor requires such an * array of predicates. <br> * This array is set during the {@link #initialize(int, Predicate[])} * method. */ protected Predicate<? super E>[] predicates; /** * The ID of the SweepArea this implementor belongs to. <br> * This ID is set during the {@link #initialize(int, Predicate[])} * method. */ protected int ID; protected Predicate<? super E> equals; protected MetaDataManagement<Object,Object> metaDataManagement; /** * Constructor */ public AbstractSAImplementor() { createMetaDataManagement(); } /** * This method is used to initialize the implementor * of a SweepArea. Commonly, it is invoked in the * constructor of a SweepArea to inform the underlying * implementor about the ID and the query-predicates * of the corresponding SweepArea. * * @param ID The ID of the corresponding SweepArea. * @param predicates The query-predicates of the corresponding SweepArea. * @param equals The predicate used to determine equality of objects within the SweepArea. */ public void initialize(int ID, Predicate<? super E>[] predicates, Predicate<? super E> equals) { this.ID = ID; this.predicates = predicates; this.equals = equals; } /** * Inserts the given element. * * @param o The object to be inserted. * @throws IllegalArgumentException Throws an IllegalArgumentException * if something goes wrong with the insertion due to the passed argument. */ public abstract void insert(E o) throws IllegalArgumentException; /** * Removes the specified element. * * @param o The object to be removed. * @return <tt>True</tt> if the removal has been successful, otherwise <tt>false</tt>. * @throws IllegalArgumentException Throws an IllegalArgumentException * if something goes wrong with the removal due to the passed argument. */ public abstract boolean remove(E o) throws IllegalArgumentException; /** * Checks if element <tt>o1</tt> is contained and * if <tt>true</tt> updates it with </tt>o2</tt>. * * <p>This implementation throws an * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.</p> * * @param o1 The object to be replaced. * @param o2 The new object. * @return The updated object is returned. * @throws IllegalArgumentException Throws an IllegalArgumentException * if something goes wrong with the update operation due to the passed arguments. * @throws UnsupportedOperationException Throws an UnsupportedOperationException * if this method is not supported. */ public E update(E o1, E o2) throws IllegalArgumentException, UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Clears this implementor. Removes all its * elements, but holds its allocated resources. */ public abstract void clear(); /** * Closes this implementor and * releases all its allocated resources. */ public abstract void close(); /** * Returns the size of this implementor. * * @return The size. */ public abstract int size(); /** * Returns an iterator over the elements of this * implementor. * * @return An iterator over the elements of this SweepAreaImplementor. * @throws UnsupportedOperationException If this operation is not supported. */ public abstract Iterator<E> iterator(); /** * Queries this implementor with the help of the * specified query object <code>o</code> and the query-predicates * set during initialization, see method {@link #initialize(int, Predicate[])}. * Returns all matching elements as an iterator. <br> * <i>Note:</i> * The returned iterator should not be used to remove any elements from * this implementor! * * @param o The query object. This object is typically probed against * the elements contained in this implementor. * @param ID An ID determining from which input this method * is triggered. * @return All matching elements of this implementor are returned as an iterator. * @throws IllegalArgumentException Throws an IllegalArgumentException * if something goes wrong due to the passed arguments during retrieval. */ public abstract Iterator<E> query(E o, int ID) throws IllegalArgumentException; /** * Calls {@link #query(Object[], int[], int)} by setting * <code>valid</code> to <code>os.length</code>. * * @param os The query objects. These objects are typically probed against * the elements contained in this implementor. * @param IDs IDs determining from which input the query objects come from. * @return All matching elements of this implementor are returned as an iterator. * @throws IllegalArgumentException Throws an IllegalArgumentException * if something goes wrong due to the passed arguments during retrieval. * @see SweepAreaImplementor#query(Object[], int[], int) */ public Iterator<E> query(E[] os, int [] IDs) throws IllegalArgumentException { return query(os, IDs, os.length); } /** * The default implementation is restricted to the probing with * single elements by calling the method * {@link #query(Object, int)} on <code>os[0]</code> and * <code>IDs[0]</code>. * * @param os The query objects. These objects are typically probed against * the elements contained in this implementor. * @param IDs IDs determining from which input the query objects come from. * @param valid Determines how many entries at the beginning of * <tt>os</tt> and <tt>IDs</tt> are valid and therefore taken into account. * @return All matching elements of this SweepArea are returned as an iterator. * @throws IllegalArgumentException If <code>valid</code> is != 1. */ public Iterator<E> query(E[] os, int [] IDs, int valid) throws IllegalArgumentException { if (valid != 1) throw new IllegalArgumentException(); return query(os[0],IDs[0]); } /** * Returns a {@link xxl.core.cursors.Cursor Cursor} that * results from filtering the passed iterator <code>it</code> with the * query-predicate at position <code>ID</code> in the predicate array. * Since the query-predicates are binary, the second * argument (the right one) is fixed by setting it * to the passed object <code>o</code>. <br> * The same functionality could be achieved by applying a * {@link xxl.core.cursors.filters.Filter Filter} to the * iterator <code>it</code>. But in this case, the binary * query-predicates have to be wrapped to unary ones using * the class {@link xxl.core.predicates.RightBind RightBind}. * However, the latter approach suffers from decreased * efficiency since it doubles the number of method calls. * * @param it The iterator to be filtered. * @param o Specifies the second (right) argument when the * binary query-predicate is invoked. * @param ID Determines the query-predicate. * <code>predicates[ID]</code> is utilized for probing. * @return A cursor that delivers all elements of the underlying * iterator where <code>predicates[ID].invoke(it.next(), o)</code> * holds. */ protected Iterator<E> filter(final Iterator<? extends E> it, final E o, final int ID) { return new AbstractCursor<E>() { @Override public boolean hasNextObject() { while(it.hasNext()) { if(predicates[ID].invoke(next = it.next(), o)) return true; } return false; } @Override public E nextObject() { return next; } @Override public void remove() throws IllegalStateException, UnsupportedOperationException { super.remove(); it.remove(); } @Override public boolean supportsRemove() { return true; } }; } protected Iterator<E> filter(final Iterator<? extends E> it, final E[] os, final int[] IDs, final int valid) { return new AbstractCursor<E>() { @Override public boolean hasNextObject() { search: while(it.hasNext()) { next = it.next(); for (int i=0; i<valid; i++) if(!predicates[IDs[i]].invoke(next, os[i])) continue search; return true; } return false; } @Override public E nextObject() { return next; } @Override public void remove() throws IllegalStateException, UnsupportedOperationException { super.remove(); it.remove(); } @Override public boolean supportsRemove() { return true; } }; } public void createMetaDataManagement() { if (metaDataManagement != null) throw new IllegalStateException("An instance of MetaDataManagement already exists."); metaDataManagement = new AbstractSAImplementorMetaDataManagement(); } public MetaDataManagement<Object,Object> getMetaDataManagement() { return metaDataManagement; } public CompositeMetaData<Object,Object> getMetaData() { return metaDataManagement.getMetaData(); } }