package arkref.ext.fig.basic; import java.io.Serializable; import java.lang.reflect.Array; import java.util.AbstractList; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Maintains a two-way map between a set of objects and contiguous integers from * 0 to the number of objects. Use get(i) to look up object i, and * indexOf(object) to look up the index of an object. * * @author Dan Klein */ public class Indexer<E> extends AbstractList<E> implements Serializable { private static final long serialVersionUID = -8769544079136550516L; protected List<E> objects; protected Map<E, Integer> indexes; protected boolean locked = false; @Override public void clear() { objects.clear(); indexes.clear(); } public void lock() { this.locked = true; } public void unlock() { this.locked = false; } /** * Return the object with the given index * * @param index */ @Override @Deprecated public E get(int index) { return objects.get(index); } public E getObject(int index) { return objects.get(index); } /** * @author aria42 */ @Override public boolean add(E elem) { if (locked) throw new IllegalStateException("Tried to add to locked indexer"); if (contains(elem)) { return false; } indexes.put(elem, size()); objects.add(elem); return true; } /** * Returns the number of objects indexed. */ @Override public int size() { return objects.size(); } /** * Returns the index of the given object, or -1 if the object is not present * in the indexer. * * @param o * @return */ @Override public int indexOf(Object o) { Integer index = indexes.get(o); if (index == null) return -1; return index; } /** * Constant time override for contains. */ @Override public boolean contains(Object o) { return indexes.keySet().contains(o); } // Return the index of the element // If doesn't exist, add it. public int getIndex(E e) { if (e == null) return -1; Integer index = indexes.get(e); if (index == null) { if (locked) return -1; index = size(); objects.add(e); indexes.put(e, index); } return index; } public Indexer() { objects = new ArrayList<E>(); indexes = new HashMap<E, Integer>(); } public Indexer(Collection<? extends E> c) { this(); for (E a : c) getIndex(a); } // Not really safe; trust them not to modify it public List<E> getObjects() { return objects; } public E[] getObjects(int[] is) { if (size() == 0) throw Exceptions.bad("Can't instantiate array"); int n = is.length; Class c = objects.get(0).getClass(); E[] os = (E[]) Array.newInstance(c, n); for (int i = 0; i < n; i++) os[i] = is[i] == -1 ? null : getObject(is[i]); return os; } }