/* 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.collections.bags.Bag; import xxl.core.collections.bags.ListBag; import xxl.core.cursors.sources.EmptyCursor; import xxl.core.functions.AbstractFunction; import xxl.core.predicates.LeftBind; /** * An implementation of the interface {@link SweepAreaImplementor} * based on the interface {@link xxl.core.collections.bags.Bag Bag}. * * @see SweepAreaImplementor * @see xxl.core.collections.bags.Bag */ public class BagSAImplementor<E> extends AbstractSAImplementor<E> { protected boolean countBagOperations = false; public class BagSAImplementorMetaDataManagement extends AbstractSAImplementorMetaDataManagement { public static final String BAG_OPERATION = "BAG_OPERATION"; protected long bagOperationCounter; public BagSAImplementorMetaDataManagement() { super(); this.bagOperationCounter = 0; } @Override protected boolean addMetaData(Object metaDataIdentifier) { if (metaDataIdentifier.equals(BAG_OPERATION)) { metaData.add(metaDataIdentifier, new AbstractFunction<Object,Long>() { @Override public Long invoke() { long res = bagOperationCounter; bagOperationCounter = 0; return res; } }); return true; } return false; } @Override protected boolean removeMetaData(Object metaDataIdentifier) { if (metaDataIdentifier.equals(BAG_OPERATION)) { countBagOperations = false; return true; } return false; } } /** * The bag storing the elements. */ protected Bag<E> bag; /** * Constructs a new BagSAImplementor. * * @param bag The underlying bag. */ public BagSAImplementor(Bag<E> bag) { this.bag = bag; } /** * Constructs a new BagSAImplementor * based on a {@link xxl.core.collections.bags.ListBag ListBag}. */ public BagSAImplementor() { this(new ListBag<E>()); } /** * Inserts the given element into the bag. * * @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 { bag.insert(o); if (countBagOperations) { synchronized (metaDataManagement) { ((BagSAImplementorMetaDataManagement)metaDataManagement).bagOperationCounter++; } } } /** * Removes the specified element from the bag. * This is achieved by querying the bag for <code>o</code> * and calling <tt>remove()</tt> if the cursor returned * by the query contains an element. Otherwise, <tt>false</tt> * is returned. * * @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 boolean remove(E o) throws IllegalArgumentException { Iterator<E> it = bag.query(new LeftBind<E>(equals, o)); if (it.hasNext()) { it.next(); it.remove(); if (countBagOperations) { synchronized (metaDataManagement) { ((BagSAImplementorMetaDataManagement)metaDataManagement).bagOperationCounter++; } } return true; } return false; } /** * Returns the size of this implementor, i.e., * the size of the bag. * * @return The size. */ public int size () { return bag.size(); } /** * Clears this implementor, i.e., * clears the bag. */ public void clear() { bag.clear(); } /** * Closes this implementor, i.e., * closes the bag. */ public void close() { bag.close(); } /** * Returns a cursor over the elements of the bag. * * @return A cursor over the elements of the bag. */ public Iterator<E> iterator() { return bag.cursor(); } /** * 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, xxl.core.predicates.Predicate[])}. * If the bag is empty, an empty cursor is returned. Otherwise, * the bag is filtered by calling * <code>filter(bag.cursor(), o, ID)</code> which produces * a cursor delivering all matching elements. * <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. * @see #filter(Iterator, Object, int) */ public Iterator<E> query (E o, int ID) { if (bag.size()==0) return new EmptyCursor<E>(); return filter(bag.cursor(), o, ID); } public void createMetaDataManagement() { if (metaDataManagement != null) throw new IllegalStateException("An instance of MetaDataManagement already exists."); metaDataManagement = new BagSAImplementorMetaDataManagement(); } }