package LBJ2.parse; import java.util.Vector; /** * A <code>LinkedVector</code> is used to store a vector of * <code>LinkedChild</code>ren which all maintain links between each other * and the parent <code>LinkedVector</code>. * * @see LinkedChild * @author Nick Rizzolo **/ public class LinkedVector extends LinkedChild { /** The linked vector is simply represented as a vector of children. */ protected Vector children; /** Initializes the vector. */ public LinkedVector() { children = new Vector(); } /** * Constructor for when only a single child from anywhere in this vector is * available. It is assumed that the <code>previous</code> and * <code>next</code> links are filled in by every child. * * @param c Any child in this vector. **/ public LinkedVector(LinkedChild c) { children = new Vector(); while (c.previous != null) c = c.previous; start = c.start; for (; c.next != null; c = c.next) { c.parent = this; children.add(c); } c.parent = this; children.add(c); end = c.end; } /** * Useful when the information that this child represents is parsed * forwards. * * @param p The previous child in the parent vector. **/ public LinkedVector(LinkedVector p) { super(p); children = new Vector(); } /** * Constructor that sets the character offsets of this vector. * * @param s The offset at which this sentence starts. * @param e The offset at which this sentence ends. **/ public LinkedVector(int s, int e) { super(s, e); children = new Vector(); } /** * Constructor for when only a single child from anywhere in this vector is * available. It is assumed that the <code>previous</code> and * <code>next</code> links are filled in by every child. * * @param c Any child in this vector. * @param s The offset at which this sentence starts. * @param e The offset at which this sentence ends. **/ public LinkedVector(LinkedChild c, int s, int e) { super(s, e); children = new Vector(); while (c.previous != null) c = c.previous; for (; c != null; c = c.next) add(c); } /** * Useful when the information that this child represents is parsed * forwards. * * @param p The previous child in the parent vector. * @param s The offset at which this sentence starts. * @param e The offset at which this sentence ends. **/ public LinkedVector(LinkedVector p, int s, int e) { super(p, s, e); children = new Vector(); } /** * Adds the specified child to the end of the vector, informing the child * of its parent and index and linking the child to its only neighbor * (which was previously the last child in the vector). * * @param c The child to add. **/ public boolean add(LinkedChild c) { c.parent = this; if (children.size() > 0) { LinkedChild p = get(children.size() - 1); p.next = c; c.previous = p; } return children.add(c); } /** * Removes the child at the specified index. * * @param i The index of the child to remove. * @return The child removed, or <code>null</code> if there was no child at * that index. **/ public LinkedChild remove(int i) { LinkedChild before = (i - 1 < 0) ? null : (LinkedChild) children.get(i - 1); LinkedChild after = (i + 1 >= children.size()) ? null : (LinkedChild) children.get(i + 1); if (before != null) before.next = after; if (after != null) after.previous = before; LinkedChild removed = null; try { removed = (LinkedChild) children.remove(i); } catch (ArrayIndexOutOfBoundsException e) { return null; } removed.parent = null; removed.next = removed.previous = null; return removed; } /** * Inserts the specified child into the specified index. All children that * previously had index greater than or equal to the specified index are * shifted up one. * * @param c The child to insert. * @param i The index at which to insert the child. * @return <code>true</code> if and only if the insert was successful. **/ public boolean insert(LinkedChild c, int i) { try { children.insertElementAt(c, i); } catch (ArrayIndexOutOfBoundsException e) { return false; } c.parent = this; c.previous = (i - 1 < 0) ? null : (LinkedChild) children.get(i - 1); c.next = (i + 1 >= children.size()) ? null : (LinkedChild) children.get(i + 1); if (c.previous != null) c.previous.next = c; if (c.next != null) c.next.previous = c; return true; } /** * Retrieves the child at the specified index in the vector. * * @param i The index from which to retrieve a child. * @return The child at the specified index, or <code>null</code> if there * was no child at that index. **/ public LinkedChild get(int i) { try { return (LinkedChild) children.get(i); } catch (ArrayIndexOutOfBoundsException e) { } return null; } /** * Returns the size of the vector. * * @return The size of the vector. **/ public int size() { return children.size(); } /** * Returns a clone of this object that is deep in the sense that all of the * children objects are cloned. * * @return A deep clone of this object. **/ public Object clone() { LinkedVector clone = (LinkedVector) super.clone(); clone.children = (Vector) clone.children.clone(); // This may look inefficient, but there is a purpose. Subclasses of // LinkedVector that don't define any new non-primitive member fields will // not need to override this method, as it already produces an object of // the subclass's type. for (int i = 0; i < size(); ++i) clone.insert((LinkedChild) clone.remove(i).clone(), i); return clone; } }