package xxl.core.collections.containers; import java.util.ArrayList; import java.util.Iterator; import java.util.NoSuchElementException; import xxl.core.cursors.mappers.Mapper; import xxl.core.cursors.sources.Enumerator; import xxl.core.functions.AbstractFunction; import xxl.core.functions.Function; import xxl.core.io.converters.FixedSizeConverter; import xxl.core.io.converters.LongConverter; /** * Stores entries in {@link ArrayList}. Long values represents index values. * Note this main memory container does not support remove operation! * Maximal number of objects are limited by positive integer value. * */ public class ArrayContainer extends AbstractContainer{ private ArrayList<Object> array; /** * A unique object used to identify mappings where no object has been * assigned to so far. */ protected static final Object empty = new Object(); /** * A counter that is used to create unique ids. Everytime an object is * inserted into the container the counter is increased and a * <tt>Long</tt> object with the actual value of the counter is * returned as id. */ protected int counter = 0; /** * * @param initialSize */ public ArrayContainer(int initialSize){ array = new ArrayList<Object>(initialSize); } /** * */ public ArrayContainer(){ this(2048); } /** * Returns a converter for the ids generated by this container. A * converter transforms an object to its byte representation and vice * versa - also known as serialization in Java.<br> * Because this container is returning <tt>Long</tt> objects as ids * the converter <code>LongConverter.DEFAULT_INSTANCE</code> is * returned. * * @return a converter for serializing the identifiers of the * container. * @see LongConverter#DEFAULT_INSTANCE */ public FixedSizeConverter objectIdConverter () { return LongConverter.DEFAULT_INSTANCE; } /** * Returns the size of the ids generated by this container in bytes, * which is 8. * @return 8 */ public int getIdSize() { return LongConverter.SIZE; } /** * Removes all elements from this container. After a call of this * method, <tt>size()</tt> will return 0. */ public void clear () { array.clear(); } /** * Returns <tt>true</tt> if there is an object stored within the container * having the identifier <tt>id</tt>. * * @param id identifier of the object. * @return true if the container contains an object for the specified * identifier. */ public boolean contains (Object id) { int index = ((Long)id).intValue(); return index < array.size(); } /** * 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>. The parameter <tt>unfix</tt> has no function because this * container is unbuffered. * * @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 { if (!contains(id)) throw new NoSuchElementException(); else{ int index = ((Long)id).intValue(); return array.get(index); } } /** * Returns an iterator that delivers all the identifiers of * the container that are in use. * * @return an iterator of all identifiers used by this container. */ public Iterator ids () { return new Mapper<Integer, Long>(new AbstractFunction<Integer, Long>() { @Override public Long invoke(Integer argument) { return Long.valueOf(argument.longValue()); } }, new Enumerator(array.size())) ; } /** * Inserts a new object into the container and returns the unique * identifier that the container has been associated to the object. * This container uses a counter to generate an unique id. Everytime * an object is inserted into the container the counter is increased * and a <tt>Long</tt> object with the actual value of the counter is * returned as id. So the identifier will not be reused again when the * object is deleted from the container. The parameter <tt>unfix</tt> * has no function because this container is unbuffered. * * @param object is the new object. * @param unfix signals a buffered container whether the object can * be removed from the underlying buffer. * @return the identifier of the object. */ public Object insert (Object object, boolean unfix) { int id = counter++; array.add(object); return Long.valueOf(id); } /** * Checks whether the <tt>id</tt> has been returned previously by a * call to insert or reserve and hasn't been removed so far. * * @param id the id to be checked. * @return true exactly if the <tt>id</tt> is still in use. */ public boolean isUsed (Object id) { int index = ((Long)id).intValue(); return index < array.size(); } /** * this method always throws {@link UnsupportedOperationException}, since this main memory container does not support remove operations. * @throws UnsupportedOperationException */ public void remove (Object id) throws NoSuchElementException { throw new UnsupportedOperationException("Array container does not support Remove Operation!"); } /** * 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) { int id = counter++; array.add(empty); return Long.valueOf(id); } /** * Returns the number of elements of the container. * * @return the number of elements. */ public int size () { return array.size(); } /** * 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 a buffered container 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 { if (isUsed(id)) { int index = ((Long)id).intValue(); array.set(index, object); } else throw new NoSuchElementException(); } }