/* 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 static xxl.core.util.metaData.CostModelMetaDataIdentifiers.COST_MEASUREMENT; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import xxl.core.cursors.Cursors; import xxl.core.cursors.filters.Filter; import xxl.core.cursors.filters.Remover; import xxl.core.cursors.sources.EmptyCursor; import xxl.core.functions.AbstractFunction; import xxl.core.functions.Function; import xxl.core.predicates.CountingPredicate; import xxl.core.predicates.Equal; import xxl.core.predicates.Not; import xxl.core.predicates.Predicate; import xxl.core.predicates.Predicates; import xxl.core.predicates.RightBind; import xxl.core.util.memory.MemoryMonitorable; import xxl.core.util.metaData.ExternalTriggeredPeriodicMetaData; /** * A SweepArea is a highly dynamic datastructure with flexible * insertion, retrieval and reorganization capabilities. It is * utilized to remain the state of an operation. <br> * This abstract implementation relies on the design pattern <i>Bridge</i> * with the intention to "decouple an abstraction from its * implementation so that the two can vary independently". * For further information see: "Gamma et al.: <i>DesignPatterns. * Elements of Reusable Object-Oriented Software.</i> Addision * Wesley 1998." * * @see SweepAreaImplementor * @see xxl.core.cursors.joins.SortMergeJoin * @see xxl.core.cursors.joins.MultiWaySortMergeJoin * @see xxl.core.predicates.Predicate * @see xxl.core.predicates.RightBind * @see java.util.Iterator */ public class ImplementorBasedSweepArea<E> extends AbstractSweepArea<E,E> { public class RemovingIterator implements Iterator<E> { protected Iterator<E> iterator; protected E lastNext; public RemovingIterator(Iterator<E> iterator) { this.iterator = iterator; } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public E next() { return (lastNext = iterator.next()); } @Override public void remove() { outerRemove(lastNext); iterator.remove(); } } /** * The underlying implementor. */ protected final SweepAreaImplementor<E> impl; /** * The ID of this SweepArea. */ protected final int ID; /** * This flag determines if this SweepArea * can reorganize itself. To trigger this event, the * <tt>ID</tt> passed to the reorganize call * has to be identical with the internal ID of this * SweepArea. */ protected final boolean selfReorganize; /** * Binary predicates used to query this SweepArea and * its underlying SweepAreaImplementor, respectively. * To offer a retrieval depending on the ID passed * to the query calls, a SweepArea requires such an * array of predicates. */ protected final Predicate<? super E>[] queryPredicates; /** * Binary predicates determining if an element of a * SweepArea and its underlying SweepAreaImplementor, * respectively, can be removed. * To offer a removal depending on the ID passed * to the reorganization or expiration calls, a SweepArea * requires such an array of predicates. <br> */ protected final Predicate<? super E>[] removePredicates; /** * The default implementation removes all expired * elements from a SweepArea by sequentially iterating * over all elements. The iteration is performed by * a {@link xxl.core.cursors.filters.Filter Filter} applying * an unary selection predicate. For this purpose, * the constructors of this class wrap the array * of binary remove-predicates to an array of unary * remove-predicates <code>removeRightBinds</code>. * The element passed to the reorganization and * expiration, respectively, is implicitly set as * right argument. */ protected final RightBind<E>[] removeRightBinds; public class ImplementorBasedSAMetaDataManagement extends AbstractSAMetaDataManagement implements ExternalTriggeredPeriodicMetaData { public ImplementorBasedSAMetaDataManagement() { super(); } protected Set<Object> metaDataFromImplementor; protected boolean addMetaDataFromImplementor(final Object metaDataIdentifier) { if (impl.getMetaDataManagement().include(metaDataIdentifier)) { metaData.add(metaDataIdentifier, new AbstractFunction<Object,Object>() { @Override public Object invoke() { synchronized(metaDataManagement) { return ((Function<?,Object>)impl.getMetaData().get(metaDataIdentifier)).invoke(); } } } ); if (metaDataFromImplementor==null) metaDataFromImplementor = new HashSet<Object>(); metaDataFromImplementor.add(metaDataIdentifier); return true; } return false; } protected boolean removeMetaDataFromImplementor(final Object metaDataIdentifier) { if (metaDataFromImplementor!=null && metaDataFromImplementor.remove(metaDataIdentifier)) { impl.getMetaDataManagement().exclude(metaDataIdentifier); if (metaDataFromImplementor.size()==0) metaDataFromImplementor = null; return true; } return false; } public static final String QUERY_PREDICATE_DECORATION = "QUERY_PREDICATE_DECORATION"; protected volatile boolean decorateQueryPredicate = false; protected long[][] queryPredicateCounters; public static final String REMOVE_PREDICATE_DECORATION = "REMOVE_PREDICATE_DECORATION"; protected volatile boolean decorateRemovePredicate = false; protected long[][] removePredicateCounters; public static final String SINGLE_QUERY_PREDICATE_COSTS = "SINGLE_QUERY_PREDICATE_COSTS"; protected double singleQueryPredicateCosts[]; public static final String QUERY_COSTS = "QUERY_COSTS"; protected volatile boolean measureQueryCosts = false; protected double queryCosts = 0.0; public static final String SINGLE_REMOVE_PREDICATE_COSTS = "SINGLE_REMOVE_PREDICATE_COSTS"; protected double singleRemovePredicateCosts[]; public static final String REMOVE_COSTS = "REMOVE_COSTS"; protected volatile boolean measureRemoveCosts = false; protected double removeCosts = 0.0; protected volatile boolean measureCosts = false; protected double costs = 0.0; public boolean needsPeriodicUpdate(Object metaDataIdentifier) { if (metaDataIdentifier.equals(QUERY_PREDICATE_DECORATION) || metaDataIdentifier.equals(QUERY_COSTS) || metaDataIdentifier.equals(REMOVE_PREDICATE_DECORATION) || metaDataIdentifier.equals(REMOVE_COSTS) || metaDataIdentifier.equals(COST_MEASUREMENT)) { return true; } return false; } public void updatePeriodicMetaData(long period) { ((ExternalTriggeredPeriodicMetaData)impl.getMetaDataManagement()).updatePeriodicMetaData(period); CountingPredicate<E> cp; if (decorateQueryPredicate) { queryPredicateCounters = new long [queryPredicates.length][2]; for (int i = 0; i < queryPredicates.length; i++) { cp = (CountingPredicate<E>)queryPredicates[i]; queryPredicateCounters[i][0] += cp.getNoOfHits(); queryPredicateCounters[i][1] += cp.getNoOfCalls(); cp.resetCounters(); } } if (decorateRemovePredicate) { removePredicateCounters = new long [removePredicates.length][2]; for (int i = 0; i < removePredicates.length; i++) { cp = (CountingPredicate<E>)removePredicates[i]; removePredicateCounters[i][0] += cp.getNoOfHits(); removePredicateCounters[i][1] += cp.getNoOfCalls(); cp.resetCounters(); } } if (measureQueryCosts) { queryCosts = 0.0; if (singleQueryPredicateCosts!=null) for (int i=0; i<queryPredicates.length; i++) queryCosts += (queryPredicateCounters[i][1] * singleQueryPredicateCosts[i]) / period; } if (measureRemoveCosts) { removeCosts = 0.0; if (singleRemovePredicateCosts != null) for (int i=0; i<queryPredicates.length; i++) removeCosts += (removePredicateCounters[i][1] * singleRemovePredicateCosts[i]) / period; } if (measureCosts) { costs = queryCosts + removeCosts; costs += ((Function<?,Double>)impl.getMetaDataManagement().getMetaData().get(COST_MEASUREMENT)).invoke(); } } public void setSingleQueryPredicateCosts(double [] costs) { singleQueryPredicateCosts = costs; } public void setSingleRemovePredicateCosts(double [] costs) { singleRemovePredicateCosts = costs; } public void setCostFactors(double [] queryPredicateCosts, double[] removePredicateCosts) { setSingleQueryPredicateCosts(queryPredicateCosts); setSingleRemovePredicateCosts(removePredicateCosts); } @Override protected boolean addMetaData(Object metaDataIdentifier) { if (super.addMetaData(metaDataIdentifier)) return true; if (metaDataIdentifier.equals(QUERY_PREDICATE_DECORATION)) { // decorate query predicates for (int i = 0; i < queryPredicates.length; i++) queryPredicates[i] = new CountingPredicate<E>(queryPredicates[i]); impl.initialize(ID, queryPredicates, equals); decorateQueryPredicate = true; metaData.add(metaDataIdentifier, new AbstractFunction<Object,long[][]>() { @Override public long[][] invoke() { return queryPredicateCounters; } }); return true; } if (metaDataIdentifier.equals(SINGLE_QUERY_PREDICATE_COSTS)) { metaData.add(metaDataIdentifier, new AbstractFunction<Object,double[]>() { @Override public double[] invoke() { return singleQueryPredicateCosts; } }); } if (metaDataIdentifier.equals(QUERY_COSTS)) { include(QUERY_PREDICATE_DECORATION); queryCosts = 0.0; measureQueryCosts = true; metaData.add(metaDataIdentifier, new AbstractFunction<Object,Double>() { @Override public Double invoke() { return queryCosts; } }); return true; } if (metaDataIdentifier.equals(REMOVE_PREDICATE_DECORATION)) { // decorate remove predicates for (int i = 0; i < removePredicates.length; i++) { removePredicates[i] = new CountingPredicate<E>(removePredicates[i]); removeRightBinds[i] = new RightBind<E>(removePredicates[i], null); } decorateRemovePredicate = true; metaData.add(metaDataIdentifier, new AbstractFunction<Object,long[][]>() { @Override public long[][] invoke() { return removePredicateCounters; } }); return true; } if (metaDataIdentifier.equals(SINGLE_REMOVE_PREDICATE_COSTS)) { metaData.add(metaDataIdentifier, new AbstractFunction<Object,double[]>() { @Override public double[] invoke() { return singleRemovePredicateCosts; } }); } if (metaDataIdentifier.equals(REMOVE_COSTS)) { include(REMOVE_PREDICATE_DECORATION); removeCosts = 0.0; measureRemoveCosts = true; metaData.add(metaDataIdentifier, new AbstractFunction<Object,Double>() { @Override public Double invoke() { return removeCosts; } }); return true; } if (metaDataIdentifier.equals(COST_MEASUREMENT)) { include(QUERY_COSTS); include(REMOVE_COSTS); boolean res = impl.getMetaDataManagement().include(COST_MEASUREMENT); costs = 0.0; measureCosts = true; metaData.add(metaDataIdentifier, new AbstractFunction<Object,Double>() { @Override public Double invoke() { return costs; } }); return res; } return addMetaDataFromImplementor(metaDataIdentifier); } @Override protected boolean removeMetaData(Object metaDataIdentifier) { if (super.removeMetaData(metaDataIdentifier)) return true; if (metaDataIdentifier.equals(QUERY_PREDICATE_DECORATION)) { // undecorate query predicates for (int i = 0; i < queryPredicates.length; i++) queryPredicates[i] = ((CountingPredicate<E>)queryPredicates[i]).getDecoree(); impl.initialize(ID, queryPredicates, equals); decorateQueryPredicate = false; metaData.remove(metaDataIdentifier); return true; } if (metaDataIdentifier.equals(QUERY_COSTS)) { exclude(QUERY_PREDICATE_DECORATION); measureQueryCosts = false; metaData.remove(metaDataIdentifier); return true; } if (metaDataIdentifier.equals(REMOVE_PREDICATE_DECORATION)) { // undecorate remove predicates for (int i = 0; i < removePredicates.length; i++) { removePredicates[i] = ((CountingPredicate<E>)removePredicates[i]).getDecoree(); removeRightBinds[i] = new RightBind<E>(removePredicates[i], null); } decorateRemovePredicate = false; metaData.remove(metaDataIdentifier); return true; } if (metaDataIdentifier.equals(REMOVE_COSTS)) { exclude(REMOVE_PREDICATE_DECORATION); measureRemoveCosts = false; metaData.remove(metaDataIdentifier); return true; } if (metaDataIdentifier.equals(COST_MEASUREMENT)) { exclude(QUERY_COSTS); exclude(REMOVE_COSTS); impl.getMetaDataManagement().exclude(COST_MEASUREMENT); measureCosts = false; metaData.remove(metaDataIdentifier); return true; } if (metaDataIdentifier.equals(SINGLE_QUERY_PREDICATE_COSTS) || metaDataIdentifier.equals(SINGLE_REMOVE_PREDICATE_COSTS)) { metaData.remove(metaDataIdentifier); return true; } return removeMetaDataFromImplementor(metaDataIdentifier); } } /** * Constructs a new SweepArea. * * @param impl The underlying implementor. * @param ID The ID of this SweepArea. * @param selfReorganize A flag to determine if this SweepArea can reorganize itself. * @param queryPredicates An array of binary query-predicates used to probe this SweepArea. * Depending on the ID passed to the query-call, different query-predicates can be chosen * for retrieval. * @param removePredicates An array of binary remove-predicates utilized during the reorganization. * With the help of this predicates, the elements of a SweepArea are probed for expiration. * In analogy to the query-predicates, the predicate actually applied to this SweepArea * depends on the ID passed to the expiration and reorganization call, respectively. * @param equals The predicate used to determine equality of objects within the SweepArea. * @param objectSize The object size of the elements in the sweeparea. */ public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E>[] queryPredicates, Predicate<? super E>[] removePredicates, Predicate<? super E> equals, int objectSize) { super(equals, objectSize); this.impl = impl; this.ID = ID; this.selfReorganize = selfReorganize; this.queryPredicates = queryPredicates; this.removePredicates = removePredicates; this.removeRightBinds = new RightBind[removePredicates.length]; for (int i = 0; i < removePredicates.length; i++) this.removeRightBinds[i] = new RightBind<E>(removePredicates[i], null); this.impl.initialize(ID, this.queryPredicates, this.equals); } public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E>[] queryPredicates, Predicate<? super E>[] removePredicates, int objectSize) { this(impl, ID, selfReorganize, queryPredicates, removePredicates, new Equal<E>(), objectSize); } /** * Constructs a new SweepArea. Sets objectSize to unknown. * The object size will be determined with reflection during the first insert() call. * * @param impl The underlying implementor. * @param ID The ID of this SweepArea. * @param selfReorganize A flag to determine if this SweepArea can reorganize itself. * @param queryPredicates An array of binary query-predicates used to probe this SweepArea. * Depending on the ID passed to the query-call, different query-predicates can be chosen * for retrieval. * @param removePredicates An array of binary remove-predicates utilized during the reorganization. * With the help of this predicates, the elements of a SweepArea are probed for expiration. * In analogy to the query-predicates, the predicate actually applied to this SweepArea * depends on the ID passed to the expiration and reorganization call, respectively. * @param equals The predicate used to determine equality of objects within the SweepArea. */ public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E>[] queryPredicates, Predicate<? super E>[] removePredicates, Predicate<? super E> equals) { this(impl, ID, selfReorganize, queryPredicates, removePredicates, equals, MemoryMonitorable.SIZE_UNKNOWN); } public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E>[] queryPredicates, Predicate<? super E>[] removePredicates) { this(impl, ID, selfReorganize, queryPredicates, removePredicates, new Equal<E>(), MemoryMonitorable.SIZE_UNKNOWN); } /** * Constructs a new SweepArea and uses the predicate <code>removePredicate</code> as * default during reorganization. * * @param impl The underlying implementor. * @param ID The ID of this SweepArea. * @param selfReorganize A flag to determine if this SweepArea can reorganize itself. * @param queryPredicates An array of binary query-predicates used to probe this SweepArea. * Depending on the ID passed to the query-call, different query-predicates can be chosen * for retrieval. * @param removePredicate Default predicate for reorganization, which is applied independently * from the ID passed to reorganization and expiration calls. * @param equals The predicate used to determine equality of objects within the SweepArea. * @param objectSize The object size of the elements in the sweeparea. */ public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E>[] queryPredicates, Predicate<? super E> removePredicate, Predicate<? super E> equals, int objectSize) { super(equals, objectSize); this.impl = impl; this.ID = ID; this.selfReorganize = selfReorganize; this.queryPredicates = queryPredicates; this.removePredicates = new Predicate[queryPredicates.length]; this.removeRightBinds = new RightBind[queryPredicates.length]; for (int i = 0; i < removePredicates.length; i++) { this.removePredicates[i] = removePredicate; this.removeRightBinds[i] = new RightBind<E>(removePredicate, null); } this.impl.initialize(ID, this.queryPredicates, this.equals); } public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E>[] queryPredicates, Predicate<? super E> removePredicate, int objectSize) { this(impl, ID, selfReorganize, queryPredicates, removePredicate, new Equal<E>(), objectSize); } /** * Constructs a new SweepArea and uses the predicate <code>removePredicate</code> as * default during reorganization. Sets objectSize to unknown. * The object size will be determined with reflection during the first insert() call. * * * @param impl The underlying implementor. * @param ID The ID of this SweepArea. * @param selfReorganize A flag to determine if this SweepArea can reorganize itself. * @param queryPredicates An array of binary query-predicates used to probe this SweepArea. * Depending on the ID passed to the query-call, different query-predicates can be chosen * for retrieval. * @param equals The predicate used to determine equality of objects within the SweepArea. * @param removePredicate Default predicate for reorganization, which is applied independently * from the ID passed to reorganization and expiration calls. */ public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E>[] queryPredicates, Predicate<? super E> removePredicate, Predicate<? super E> equals) { this(impl, ID, selfReorganize, queryPredicates, removePredicate, equals, MemoryMonitorable.SIZE_UNKNOWN); } public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E>[] queryPredicates, Predicate<? super E> removePredicate) { this(impl, ID, selfReorganize, queryPredicates, removePredicate, new Equal<E>(), MemoryMonitorable.SIZE_UNKNOWN); } /** * Constructs a new SweepArea, but performs no reorganization. * This is achieved by internally reorganizing with * <code>Predicates.FALSE</code>. Sets objectSize to unknown. * The object size will be determined with reflection during the first insert() call. * * @param impl The underlying implementor. * @param ID The ID of this SweepArea. * @param selfReorganize A flag to determine if this SweepArea can reorganize itself. * @param queryPredicates An array of binary query-predicates used to probe this SweepArea. * Depending on the ID passed to the query-call, different query-predicates can be chosen * for retrieval. * @param equals The predicate used to determine equality of objects within the SweepArea. */ public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, Predicate<? super E> equals, boolean selfReorganize, Predicate<? super E>[] queryPredicates) { this(impl, ID, selfReorganize, queryPredicates, Predicates.FALSE, equals); } public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E>[] queryPredicates) { this(impl, ID, selfReorganize, queryPredicates, Predicates.FALSE, new Equal<E>()); } /** * Constructs a new SweepArea with a generally applicable query- and reorganization predicate. * Sets objectSize to unknown. The object size will be determined with * reflection during the first insert() call. * * @param impl The underlying implementor. * @param ID The ID of this SweepArea. * @param selfReorganize A flag to determine if this SweepArea can reorganize itself. * @param queryPredicate A generally applicable binary query-predicate used to probe this SweepArea. * Hence, this predicate is applied independently from the ID passed to query calls. * @param removePredicate A generally applicable binary remove-predicates utilized during the reorganization. * With the help of this predicates, the elements of a SweepArea are probed for expiration. * This predicate is applied independently from the ID passed to reorganization and expiration calls. * @param dim The dimensionality of this SweepArea, i.e., the number of possible inputs or in other words * the number of different IDs that can be passed to method calls of this SweepArea. * @param equals The predicate used to determine equality of objects within the SweepArea. * @param objectSize The object size of the elements in the sweeparea. */ public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E> queryPredicate, Predicate<? super E> removePredicate, Predicate<? super E> equals, int dim, int objectSize) { super(equals, objectSize); this.impl = impl; this.ID = ID; this.selfReorganize = selfReorganize; this.queryPredicates = new Predicate[dim]; Arrays.fill(queryPredicates, queryPredicate); this.removePredicates = new Predicate[dim]; this.removeRightBinds = new RightBind[dim]; for (int i = 0; i < removePredicates.length; i++) { this.removePredicates[i] = removePredicate; this.removeRightBinds[i] = new RightBind<E>(removePredicate, null); } this.impl.initialize(ID, queryPredicates, equals); } public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E> queryPredicate, Predicate<? super E> removePredicate, int dim, int objectSize) { this(impl, ID, selfReorganize, queryPredicate, removePredicate, new Equal<E>(), dim, objectSize); } /** * Constructs a new SweepArea with a generally applicable query- and reorganization predicate. * Sets objectSize to unknown. The object size will be determined with * reflection during the first insert() call. * * @param impl The underlying implementor. * @param ID The ID of this SweepArea. * @param selfReorganize A flag to determine if this SweepArea can reorganize itself. * @param queryPredicate A generally applicable binary query-predicate used to probe this SweepArea. * Hence, this predicate is applied independently from the ID passed to query calls. * @param removePredicate A generally applicable binary remove-predicates utilized during the reorganization. * With the help of this predicates, the elements of a SweepArea are probed for expiration. * This predicate is applied independently from the ID passed to reorganization and expiration calls. * @param equals The predicate used to determine equality of objects within the SweepArea. * @param dim The dimensionality of this SweepArea, i.e., the number of possible inputs or in other words * the number of different IDs that can be passed to method calls of this SweepArea. */ public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E> queryPredicate, Predicate<? super E> removePredicate, Predicate<? super E> equals, int dim) { this(impl, ID, selfReorganize, queryPredicate, removePredicate, equals, dim, MemoryMonitorable.SIZE_UNKNOWN); } public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E> queryPredicate, Predicate<? super E> removePredicate, int dim) { this(impl, ID, selfReorganize, queryPredicate, removePredicate, new Equal<E>(), dim, MemoryMonitorable.SIZE_UNKNOWN); } /** * Constructs a new SweepArea with a generally applicable query- and reorganization predicate. * This SweepArea performs no reorganization. This is achieved by internally reorganizing with * <code>Predicates.FALSE</code>. Sets objectSize to unknown. * The object size will be determined with reflection during the first insert() call. * * @param impl The underlying implementor. * @param ID The ID of this SweepArea. * @param selfReorganize A flag to determine if this SweepArea can reorganize itself. * @param queryPredicate A generally applicable binary query-predicate used to probe this SweepArea. * Hence, this predicate is applied independently from the ID passed to query calls. * @param dim The dimensionality of this SweepArea, i.e., the number of possible inputs or in other words * the number of different IDs that can be passed to method calls of this SweepArea. */ public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E> queryPredicate, int dim, Predicate<? super E> equals) { this(impl, ID, selfReorganize, queryPredicate, Predicates.FALSE, equals, dim); } public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, boolean selfReorganize, Predicate<? super E> queryPredicate, int dim) { this(impl, ID, selfReorganize, queryPredicate, Predicates.FALSE, new Equal<E>(), dim); } /** * Constructs a new SweepArea with a generally applicable query- and reorganization predicate. * This SweepArea uses <code>Equal.DEFAULT_INSTANCE</code> for querying and * <code>new Not(Equal.DEFAULT_INSTANCE)</code> for reorganization. A self-reorganization * is permitted. Sets objectSize to unknown. The object size will be determined * with reflection during the first insert() call. * * @param impl The underlying implementor. * @param ID The ID of this SweepArea. * @param dim The dimensionality of this SweepArea, i.e., the number of possible inputs or in other words * the number of different IDs that can be passed to method calls of this SweepArea. */ public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, Predicate<? super E> equals, int ID, int dim) { this(impl, ID, true, equals, new Not<E>(equals), equals, dim); } public ImplementorBasedSweepArea(SweepAreaImplementor<E> impl, int ID, int dim) { this(impl, ID, true, new Equal<E>(), new Not<E>(new Equal<E>()), new Equal<E>(), dim); } /** * Inserts the given element into this SweepArea. The default implementation * simply forwards this call to the underlying implementor. Thus, * it calls <code>impl.insert(o)</code>. * * @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 void insert(E o) throws IllegalArgumentException { super.insert(o); impl.insert(o); } /** * Clears this SweepArea by clearing the underlying * implementor. Calls <code>impl.clear()</code>. <br> * This method should remove all elements of a * SweepArea, but holds its allocated resources. */ public void clear() { impl.clear(); } /** * Closes this SweepArea by closing the underlying * implementor. Calls <code>impl.close()</code>.<br> * This method should release all allocated resources * of a SweepArea. */ public void close() { impl.close(); } /** * Returns the size of this SweepArea by * determining the size of the underlying implementor. * Returns <code>impl.size()</code>. * * @return The size of this SweepArea. */ public int size() { return impl.size(); } /** * Returns an iterator over this SweepArea by * delivering an iterator over the underlying implementor. * Returns <code>impl.iterator()</code>. * * @return An iterator over this SweepArea. * @throws UnsupportedOperationException if this SweepArea is not able * to provide an iteration over its elements. */ public Iterator<E> iterator() throws UnsupportedOperationException { return new RemovingIterator(impl.iterator()); } /** * Queries this SweepArea with the help of the * specified query object <code>o</code>. Returns all * matching elements as an iterator. The default implementation * of this method directly passes the call to the underlying implementor, * i.e., it returns <code>impl.query(o, ID)</code>. <br> * <i>Note:</i> * This iterator should not be used to remove any elements of a * SweepArea! * * @param o The query object. This object is typically probed against * the elements contained in this SweepArea. * @param ID An ID determining from which input this method * is triggered. * @return All matching elements of this SweepArea are returned as an iterator. * @throws IllegalArgumentException Throws an IllegalArgumentException * if something goes wrong due to the passed arguments during retrieval. */ @Override public Iterator<E> query(E o, int ID) throws IllegalArgumentException { return new RemovingIterator(impl.query(o, ID)); } /** * Queries this SweepArea with the help of the * specified query objects <code>os</code>. Returns all matching elements * as an iterator. This version of query additionally allows to use partially * filled arrays and specifies how many entries of such a partially * filled array are valid.<br> * The default implementation of this method * directly passes the call to the underlying implementor and * returns <code>impl.query(os, IDs, valid)</code>. * * @param os The query objects. These objects are typically probed against * the elements contained in this SweepArea. * @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 Throws an IllegalArgumentException * if something goes wrong due to the passed arguments during retrieval. */ @Override public Iterator<E> query(E [] os, int [] IDs, int valid) throws IllegalArgumentException { return new RemovingIterator(impl.query(os, IDs, valid)); } /** * Queries this SweepArea with the help of the * specified query objects <code>os</code>. Returns all matching elements * as an iterator. <br> The default implementation of this method * directly passes the call to the underlying implementor. * Returns <code>impl.query(os, IDs)</code>. * * @param os The query objects. These objects are typically probed against * the elements contained in this SweepArea. * @param IDs IDs determining from which input the query objects come from. * @return All matching elements of this SweepArea are returned as an iterator. * @throws IllegalArgumentException Throws an IllegalArgumentException * if something goes wrong due to the passed arguments during retrieval. */ @Override public Iterator<E> query(E [] os, int [] IDs) throws IllegalArgumentException { return new RemovingIterator(impl.query(os, IDs)); } /** * Determines which elements in this SweepArea expire with respect to the object * <tt>currentStatus</tt> and an <tt>ID</tt>. The latter is commonly used * to differ by which input this reorganization step is initiated.<br> * If no elements qualify for removal, an empty cursor is returned and all * elements are remained. <br> * In order to remove the expired elements, either the returned iterator has to * support and execute the remove operation for each expired element during traversal * or the {@link #reorganize(Object, int)} has to be overwritten to perform * the final removal. <p> * The default implementation in this class performs a sequential scan: * <code><pre> * new Remover(new Filter(iterator(), removeRightBinds[ID].setRight(currentStatus))); * </code></pre> * Hence, specialized SweepAreas should overwrite this method to gain a more * efficient reorganization. * * @param currentStatus The object containing the necessary information * to detect expired elements. * @param ID An ID determining from which input this method * is triggered. * @return an iteration over the elements which expire with respect to the * object <tt>currentStatus</tt> and an <tt>ID</tt>. * @throws UnsupportedOperationException An UnsupportedOperationException is thrown, if * this method is not supported by this SweepArea. * @throws IllegalStateException Throws an IllegalStateException if * this method is called at an invalid state. */ @Override public Iterator<E> expire (E currentStatus, int ID) throws UnsupportedOperationException, IllegalStateException { if (ID == this.ID && !selfReorganize) return new EmptyCursor<E>(); return new Remover<E>(new Filter<E>(iterator(), removeRightBinds[ID].setRight(currentStatus))); } /** * In contrast to the method {@link #expire(Object, int)}, this method removes * all expired elements from a SweepArea without returning them. * The default implementation removes all elements returned by a call to * {@link #expire(Object, int)}.<BR> * In order to perform a more efficient removal, this method should * be overwritten, e.g., by implementing a bulk deletion. * * @param currentStatus The object containing the necessary information * to perform the reorganization step. * @param ID An ID determining from which input this reorganization step * is triggered. * @throws UnsupportedOperationException An UnsupportedOperationException is thrown, if * is method is not supported by this SweepArea. * @throws IllegalStateException Throws an IllegalStateException if * this method is called at an invalid state. */ public void reorganize(E currentStatus, int ID) throws UnsupportedOperationException, IllegalStateException { Cursors.consume(expire(currentStatus, ID)); } protected void outerRemove(E object) { } protected void remove(E object) { impl.remove(object); } protected boolean supportsRemove() { return true; } /** * Returns a reference to the underlying implementor. * * @return The underlying implementor. * @throws UnsupportedOperationException If this operation is not supported. */ public SweepAreaImplementor<? super E> getImplementor() throws UnsupportedOperationException { return impl; } /** * Returns the ID of this SweepArea. * * @return The ID of this SweepArea. */ public int getID() { return ID; } /** * Returns the array of binary query-predicates. * * @return The Array of query-predicates. * @throws UnsupportedOperationException If this operation is not supported. */ public Predicate<? super E>[] getQueryPredicates() throws UnsupportedOperationException { return this.queryPredicates; } /** * Returns the array of binary remove-predicates. * * @return The Array of remove-predicates * @throws UnsupportedOperationException If this operation is not supported. */ public Predicate<? super E>[] getRemovePredicates() throws UnsupportedOperationException { return this.removePredicates; } /** * Returns <tt>true</tt> if this SweepArea permits * self-reorganization. In this case, the * <tt>ID</tt> passed to the reorganize call * is the same as the internal ID of this SweepArea. * Otherwise <tt>false</tt> is returned. * * @return <tt>True</tt> if this SweepArea permits * self-reorganization, otherwise <tt>false</tt>. */ public boolean allowsSelfReorganize() { return selfReorganize; } public void createMetaDataManagement() { if (metaDataManagement != null) throw new IllegalStateException("An instance of MetaDataManagement already exists."); metaDataManagement = new ImplementorBasedSAMetaDataManagement(); } }