/* 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.containers;
import java.util.List;
import java.util.NoSuchElementException;
import xxl.core.functions.AbstractFunction;
import xxl.core.functions.Function;
/**
* This class decorates a container with a counter functionality and
* counts every call of an insert, get, update and remove method. But the
* counter only works correctly when a container is decorated that
* insertAll, getAll, updateAll and removeAll methods are based the
* <i>counted</i> insert, get, update and remove methods. This must also
* hold for the iterators ids() and objects(). This constrained decorator
* is interesting for statistical use or the performance analysis of
* containers.<p>
*
* The numbers of calls are stored in public fields and can be reset by
* the reset method.<p>
*
* Usage example (1).
* <pre>
* // create a new counter container decorating an empty map container
*
* CounterContainer container = new CounterContainer(new MapContainer());
*
* // reset the counter container
*
* container.reset();
*
* // insert 20 elements and print the counters
*
* for (int i = 0; i < 20; i++)
* container.insert(new Integer(i));
* System.out.println(container);
* System.out.println();
*
* // create an iteration over the ids of the counter container
*
* java.util.Iterator iterator = container.ids();
*
* // get 10 elements and print the counters
*
* for (int i = 0; i < 10; i++)
* if (iterator.hasNext())
* container.get(iterator.next());
* System.out.println(container);
* System.out.println();
*
* // update 5 elements and print the counters
*
* for (int i = 0; i < 5; i++)
* if (iterator.hasNext())
* container.update(iterator.next(), new Integer(i));
* System.out.println(container);
* System.out.println();
*
* // remove an element and print the counters
*
* if (iterator.hasNext())
* container.remove(iterator.next());
* System.out.println(container);
* System.out.println();
*
* // close the open container after use
*
* container.close();
* </pre>
*
* @see Function
* @see NoSuchElementException
*/
public class CounterContainer extends ConstrainedDecoratorContainer {
/**
* A factory method to create a new CounterContainer. It may
* only be invoked with a <i>parameter list</i> (for further
* details see Function) of containers. The <i>parameter
* list</i> of containers will be used to initialize the decorated
* container by calling the constructor
* <code>CounterContainer(list.get(0))</code>.
*
* @see Function
*/
public static final Function<Container,CounterContainer> FACTORY_METHOD = new AbstractFunction<Container,CounterContainer>() {
public CounterContainer invoke (List<? extends Container> list) {
return new CounterContainer(list.get(0));
}
};
/**
* The number of times an insert method is called on this container
* since the last reset. This number is identical to the number of
* elements that are inserted since the last reset because the
* insertAll method calls for every element the insert method.
*/
public int inserts = 0;
/**
* The number of times a get method is called on this container since
* the last reset. This number is identical to the number of elements
* that are got since the last reset because the getAll method calls
* for every element the get method.
*/
public int gets = 0;
/**
* The number of times an update method is called on this container
* since the last reset. This number is identical to the number of
* elements that are updated since the last reset because the
* updateAll method calls for every element the update method.
*/
public int updates = 0;
/**
* The number of times a remove method is called on this container
* since the last reset. This number is identical to the number of
* elements that are removed since the last reset because the
* removeAll method calls for every element the remove method.
*/
public int removes = 0;
/**
* The number of times a reserve method is called on this container
* since the last reset.
*/
public int reserves = 0;
/**
* Constructes a new CounterContainer that decorates the specified
* container.
*
* @param container the container to be decorated with the counter.
*/
public CounterContainer (Container container) {
super(container);
}
/**
* Resets the counters for insert, get, update and remove methods.
* A call of this method sets every counter to 0.
*/
public void reset () {
inserts = gets = updates = removes = reserves = 0;
}
/**
* Returns the object associated to the identifier <tt>id</tt>. An
* exception is thrown if there is not object stored with this
* <tt>id</tt>. If unfix is set to true, the object can be removed
* from the underlying buffer. Otherwise (!unfix), the object has
* to be kept in the buffer.
*
* @param id identifier of the object.
* @param unfix signals whether the object can be removed from the
* underlying buffer.
* @return the object associated to the specified identifier.
* @throws NoSuchElementException if the desired object is not found.
*/
public Object get (Object id, boolean unfix) throws NoSuchElementException {
Object object = super.get(id, unfix);
gets++;
return object;
}
/**
* Inserts a new object into the container and returns the unique
* identifier that the container has been associated to the object.
* The identifier can be reused again when the object is deleted from
* the buffer. If unfixed, the object can be removed from the buffer.
* Otherwise, it has to be kept in the buffer until an
* <tt>unfix()</tt> is called.<br>
* After an insertion all the iterators operating on the container can
* be in an invalid state.<br>
* This method also allows an insertion of a null object. In the
* application would really like to have such objects in the
* container, some methods have to be modified.
*
* @param object is the new object.
* @param unfix signals whether the object can be removed from the
* underlying buffer.
* @return the identifier of the object.
*/
public Object insert (Object object, boolean unfix) {
Object id = super.insert(object, unfix);
inserts++;
return id;
}
/**
* Removes the object with identifier <tt>id</tt>. An exception is
* thrown when an object with an identifier <tt>id</tt> is not in the
* container.<br>
* After a call of <tt>remove()</tt> all the iterators (and cursors)
* can be in an invalid state.
*
* @param id an identifier of an object.
* @throws NoSuchElementException if an object with an identifier
* <tt>id</tt> is not in the container.
*/
public void remove (Object id) throws NoSuchElementException {
super.remove(id);
removes++;
}
/**
* Reserves an id for subsequent use. The container may or may not
* need an object to be able to reserve an id, depending on the
* implementation. If so, it will call the parameterless function
* provided by the parameter <tt>getObject</tt>.
*
* @param getObject A parameterless function providing the object for
* that an id should be reserved.
* @return the reserved id.
*/
public Object reserve (Function getObject) {
Object id = super.reserve(getObject);
reserves++;
return id;
}
/**
* Overwrites an existing (id,*)-element by (id, object). This method
* throws an exception if an object with an identifier <tt>id</tt>
* does not exist in the container.
*
* @param id identifier of the element.
* @param object the new object that should be associated to
* <tt>id</tt>.
* @param unfix signals whether the object can be removed from the
* underlying buffer.
* @throws NoSuchElementException if an object with an identifier
* <tt>id</tt> does not exist in the container.
*/
public void update (Object id, Object object, boolean unfix) throws NoSuchElementException {
super.update(id, object, unfix);
updates++;
}
/**
* Outputs the collected statistic to a String.
* @return a String representation of the collected statistics.
*/
public String toString() {
return "inserts = "+inserts + ", " +
"gets = "+gets + ", " +
"updates = "+updates + ", " +
"removes = "+removes + ", " +
"reserves = "+reserves;
}
}