package jsx3.xml; import java.util.Iterator; import java.util.LinkedList; /** * A Node is a container of Records. * In use, Node has a parent Node and is part of a CdfDocument. * @author Joe Walker [joe at getahead dot ltd dot uk] */ public class Node implements Iterable<Record> { /** * You should not be directly creating Nodes */ protected Node(String id) { this.id = id; } /** * You should not be directly creating Nodes */ protected Node() { } /** * A <code>NodeList</code> that contains all children of this node. If * there are no children, this is a <code>NodeList</code> containing no * nodes. */ public Iterator<Record> iterator() { return children.iterator(); } /** * Inserts the node <code>newChild</code> at the given <code>position</code> * @param position The position at which to insert the new Record * @param newRecord The node to insert. */ public void insertRecord(int position, Record newRecord) { children.add(position, newRecord); if (newRecord.getOwnerDocument() != null) { newRecord.getParentNode().removeRecord(newRecord); } newRecord.joinDocument(this); } /** * Replaces the child Record <code>oldRecord</code> with <code>newRecord</code> * in the list of children, and returns the <code>oldRecord</code> Record. * If the <code>newRecord</code> is already in the tree, it is first removed. * @param newRecord The new Record to put in the child list. * @param oldRecord The Record being replaced in the list. */ public void replaceRecord(Record newRecord, Record oldRecord) { int index = children.indexOf(oldRecord); if (index == -1) { appendRecord(newRecord); } else { removeRecord(oldRecord); insertRecord(index, oldRecord); } } /** * Removes the child Record indicated by <code>oldRecord</code> from the list * of children, and returns it. * @param oldRecord The Record being removed. */ public void removeRecord(Record oldRecord) { boolean removed = children.remove(oldRecord); if (removed) { oldRecord.leaveDocument(); } } /** * Adds the Record <code>newRecord</code> to the end of the list of children * of this Record. If the <code>newRecord</code> is already in the tree, it * is first removed. * @param newRecord The Record to add. */ public void appendRecord(Record newRecord) { if (newRecord.getOwnerDocument() != null) { newRecord.getParentNode().removeRecord(newRecord); } newRecord.joinDocument(this); children.add(newRecord); } /** * The parent of this node. The * If a node has just been created and not yet added to the * tree, or if it has been removed from the tree, this is * <code>null</code>. */ public Node getParentNode() { return parentNode; } /** * The {@link CdfDocument} object associated with this node. * @return This Records parent Document */ public CdfDocument getOwnerDocument() { return document; } /** * Remove all the nodes from this node */ public void clear() { for (Record record : children) { removeRecord(record); } } /** * Internal setter for the parent node. * @param parent The new parent Node */ protected void joinDocument(Node parent) { this.document = parent.getOwnerDocument(); this.parentNode = parent; } /** * Internal way to disconnect a Node from a Document */ protected void leaveDocument() { this.document = null; this.parentNode = null; } /** * @return the id */ public String getId() { return id; } /** * @param id the id to set */ public void setId(String id) { this.id = id; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (this == obj) { return true; } if (!(obj instanceof Node)) { return false; } return super.equals(obj); } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37829 + id.hashCode(); } /** * Local utility to create an indentation string * @param depth the number of indents that have been done * @return A string of depth <code>depth * 2</code> */ protected static String indent(int depth) { StringBuilder reply = new StringBuilder(depth * 2); for (int i = 0; i < depth; i++) { reply.append(" "); } return reply.toString(); } /** * The JSXID of this node */ protected String id; /** * Our parent record */ protected Node parentNode; /** * The CdfDocument that we are a part of */ protected CdfDocument document; /** * The records that we contain */ protected LinkedList<Record> children = new LinkedList<Record>(); }