| /******************************************************************************* |
| * Copyright (c) 2001, 2011 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * |
| * Jens Lukowski/Innoopract - initial renaming/restructuring |
| * |
| * Balazs Banfai: Bug 154737 getUserData/setUserData support for Node |
| * https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737 |
| * |
| * David Carver (STAR) - bug 295127 - implement isSameNode and compareDocumentPosition methods. |
| * Unit Tests covered in wst.xsl XPath 2.0 tests. |
| * David Carver (STAR) - bug 296999 - Inefficient use of new String() |
| *******************************************************************************/ |
| package org.eclipse.wst.xml.core.internal.document; |
| |
| |
| |
| import java.io.Serializable; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.wst.sse.core.internal.model.FactoryRegistry; |
| import org.eclipse.wst.sse.core.internal.provisional.AbstractNotifier; |
| import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; |
| import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; |
| import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; |
| import org.w3c.dom.DOMException; |
| import org.w3c.dom.DOMImplementation; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.DocumentFragment; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.Text; |
| import org.w3c.dom.TypeInfo; |
| import org.w3c.dom.UserDataHandler; |
| |
| /** |
| * NodeImpl class |
| */ |
| public abstract class NodeImpl extends AbstractNotifier implements Node, IDOMNode { |
| // define one empty nodelist, for repeated use |
| private final static NodeList EMPTY_NODE_LIST = new NodeListImpl(); |
| // DocumentPosition |
| //private final static short DOCUMENT_POSITION_DISCONNECTED = 0x01; |
| private final static short DOCUMENT_POSITION_PRECEDING = 0x02; |
| private final static short DOCUMENT_POSITION_FOLLOWING = 0x04; |
| //private final static short DOCUMENT_POSITION_CONTAINS = 0x08; |
| //private final static short DOCUMENT_POSITION_CONTAINED_BY = 0x10; |
| private final static short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; |
| |
| |
| private boolean fDataEditable = true; |
| private IStructuredDocumentRegion flatNode = null; |
| private NodeImpl nextSibling = null; |
| |
| private DocumentImpl ownerDocument = null; |
| private NodeImpl parentNode = null; |
| private NodeImpl previousSibling = null; |
| // define one empty String constant for repeated use |
| static final String EMPTY_STRING = ""; |
| |
| /** |
| * NodeImpl constructor |
| */ |
| protected NodeImpl() { |
| super(); |
| } |
| |
| /** |
| * NodeImpl constructor |
| * |
| * @param that |
| * NodeImpl |
| */ |
| protected NodeImpl(NodeImpl that) { |
| if (that != null) { |
| this.ownerDocument = that.ownerDocument; |
| } |
| } |
| |
| /** |
| * appendChild method |
| * |
| * @return org.w3c.dom.Node |
| * @param newChild |
| * org.w3c.dom.Node |
| */ |
| public Node appendChild(Node newChild) throws DOMException { |
| throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, DOMMessages.HIERARCHY_REQUEST_ERR); |
| } |
| |
| /** |
| * contains method |
| * |
| * @return boolean |
| * @param offset |
| * int |
| */ |
| public boolean contains(int offset) { |
| return (offset >= getStartOffset() && offset < getEndOffset()); |
| } |
| |
| /** |
| * @param s |
| * @param tagName |
| * @return |
| */ |
| protected String createDOMExceptionMessage(short s, String tagName) { |
| String result = null; |
| // TODO: Should localize these messages, and provide /u escaped |
| // version of tagName |
| result = lookupMessage(s) + " " + tagName; //$NON-NLS-1$ |
| return result; |
| } |
| |
| /** |
| * getAttributes method |
| * |
| * @return org.w3c.dom.NamedNodeMap |
| */ |
| public NamedNodeMap getAttributes() { |
| return null; |
| } |
| |
| /** |
| */ |
| protected String getCharValue(String name) { |
| DocumentImpl document = (DocumentImpl) getOwnerDocument(); |
| if (document == null) |
| return null; |
| return document.getCharValue(name); |
| } |
| |
| /** |
| * getChildNodes method |
| * |
| * @return org.w3c.dom.NodeList |
| */ |
| public NodeList getChildNodes() { |
| // As per DOM spec, correct behavior for getChildNodes is to return a |
| // zero length NodeList, not null, when there are no children. |
| // We'll use a common instance of an empty node list, just to prevent |
| // creating a trival object many many times. |
| |
| return EMPTY_NODE_LIST; |
| } |
| |
| /** |
| * getCommonAncestor method |
| * |
| * @return org.w3c.dom.Node |
| * @param node |
| * org.w3c.dom.Node |
| */ |
| public Node getCommonAncestor(Node node) { |
| if (node == null) |
| return null; |
| |
| for (Node na = node; na != null; na = na.getParentNode()) { |
| for (Node ta = this; ta != null; ta = ta.getParentNode()) { |
| if (ta == na) |
| return ta; |
| } |
| } |
| |
| return null; // not found |
| } |
| |
| /** |
| * getContainerDocument method |
| * |
| * @return org.w3c.dom.Document |
| */ |
| public Document getContainerDocument() { |
| Node parent = null; |
| for (Node node = this; node != null; node = parent) { |
| if (node.getNodeType() == Node.DOCUMENT_NODE) { |
| return (Document) node; |
| } |
| /* Break out of a bad hierarchy */ |
| if ((parent = node.getParentNode()) == node) |
| break; |
| } |
| return null; |
| } |
| |
| /** |
| * getEndOffset method |
| * |
| * @return int |
| */ |
| public int getEndOffset() { |
| Node node = this; |
| while (node != null) { |
| if (node.getNodeType() == Node.ELEMENT_NODE) { |
| ElementImpl element = (ElementImpl) node; |
| IStructuredDocumentRegion endStructuredDocumentRegion = element.getEndStructuredDocumentRegion(); |
| if (endStructuredDocumentRegion != null) |
| return endStructuredDocumentRegion.getEnd(); |
| } |
| |
| Node last = node.getLastChild(); |
| if (last != null) { // dig into the last |
| node = last; |
| continue; |
| } |
| |
| IStructuredDocumentRegion lastStructuredDocumentRegion = ((NodeImpl) node).getStructuredDocumentRegion(); |
| if (lastStructuredDocumentRegion != null) |
| return lastStructuredDocumentRegion.getEnd(); |
| |
| Node prev = node.getPreviousSibling(); |
| if (prev != null) { // move to the previous |
| node = prev; |
| continue; |
| } |
| |
| Node parent = node.getParentNode(); |
| node = null; |
| while (parent != null) { |
| if (parent.getNodeType() == Node.ELEMENT_NODE) { |
| ElementImpl element = (ElementImpl) parent; |
| IStructuredDocumentRegion startStructuredDocumentRegion = element.getStartStructuredDocumentRegion(); |
| if (startStructuredDocumentRegion != null) |
| return startStructuredDocumentRegion.getEnd(); |
| } |
| Node parentPrev = parent.getPreviousSibling(); |
| if (parentPrev != null) { // move to the previous |
| node = parentPrev; |
| break; |
| } |
| parent = parent.getParentNode(); |
| } |
| } |
| return 0; |
| } |
| |
| public IStructuredDocumentRegion getEndStructuredDocumentRegion() { |
| return null; |
| } |
| |
| /** |
| */ |
| public FactoryRegistry getFactoryRegistry() { |
| IDOMModel model = getModel(); |
| if (model != null) { |
| FactoryRegistry reg = model.getFactoryRegistry(); |
| if (reg != null) |
| return reg; |
| } |
| return null; |
| } |
| |
| /** |
| * getFirstChild method |
| * |
| * @return org.w3c.dom.Node |
| */ |
| public Node getFirstChild() { |
| return null; |
| } |
| |
| /** |
| * getFirstStructuredDocumentRegion method |
| * |
| */ |
| public IStructuredDocumentRegion getFirstStructuredDocumentRegion() { |
| return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.flatNode); |
| } |
| |
| /** |
| */ |
| public int getIndex() { |
| Node parent = getParentNode(); |
| if (parent == null) |
| return -1; // error |
| int index = 0; |
| for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) { |
| if (child == this) |
| return index; |
| index++; |
| } |
| return -1; // error |
| } |
| |
| /** |
| * getLastChild method |
| * |
| * @return org.w3c.dom.Node |
| */ |
| public Node getLastChild() { |
| return null; |
| } |
| |
| /** |
| * getLastStructuredDocumentRegion method |
| * |
| */ |
| public IStructuredDocumentRegion getLastStructuredDocumentRegion() { |
| return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.flatNode); |
| } |
| |
| /** |
| */ |
| public String getLocalName() { |
| return null; |
| } |
| |
| /** |
| * the default implementation can just refer to the owning document |
| */ |
| public IDOMModel getModel() { |
| if (this.ownerDocument == null) |
| return null; |
| return this.ownerDocument.getModel(); |
| } |
| |
| /** |
| * all but attr return null |
| */ |
| public ITextRegion getNameRegion() { |
| return null; |
| } |
| |
| /** |
| */ |
| public String getNamespaceURI() { |
| return null; |
| } |
| |
| /** |
| * getNextSibling method |
| * |
| * @return org.w3c.dom.Node |
| */ |
| public Node getNextSibling() { |
| return this.nextSibling; |
| } |
| |
| /** |
| * getNodeAt method |
| * |
| * @return org.w3c.dom.Node |
| * @param offset |
| * int |
| */ |
| Node getNodeAt(int offset) { |
| IDOMNode parent = this; |
| IDOMNode child = (IDOMNode) getFirstChild(); |
| while (child != null) { |
| if (child.getEndOffset() <= offset) { |
| child = (IDOMNode) child.getNextSibling(); |
| continue; |
| } |
| if (child.getStartOffset() > offset) { |
| break; |
| } |
| |
| IStructuredDocumentRegion startStructuredDocumentRegion = child.getStartStructuredDocumentRegion(); |
| if (startStructuredDocumentRegion != null) { |
| if (startStructuredDocumentRegion.getEnd() > offset) |
| return child; |
| } |
| |
| // dig more |
| parent = child; |
| child = (IDOMNode) parent.getFirstChild(); |
| } |
| |
| return parent; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.w3c.dom.Node#getNodeValue() |
| */ |
| public String getNodeValue() throws DOMException { |
| return null; |
| } |
| |
| /** |
| * getOwnerDocument method |
| * |
| * @return org.w3c.dom.Document |
| */ |
| public Document getOwnerDocument() { |
| return this.ownerDocument; |
| } |
| |
| /** |
| * getParentNode method |
| * |
| * @return org.w3c.dom.Node |
| */ |
| public Node getParentNode() { |
| return this.parentNode; |
| } |
| |
| /** |
| */ |
| public String getPrefix() { |
| return null; |
| } |
| |
| /** |
| * getPreviousSibling method |
| * |
| * @return org.w3c.dom.Node |
| */ |
| public Node getPreviousSibling() { |
| return this.previousSibling; |
| } |
| |
| /** |
| */ |
| public String getSource() { |
| if (this.flatNode == null) |
| return NodeImpl.EMPTY_STRING; |
| return this.flatNode.getText(); |
| } |
| |
| /** |
| * getStartOffset method |
| * |
| * @return int |
| */ |
| public int getStartOffset() { |
| if (this.flatNode != null) |
| return this.flatNode.getStart(); |
| NodeImpl prev = (NodeImpl) getPreviousSibling(); |
| if (prev != null) |
| return prev.getEndOffset(); |
| Node parent = getParentNode(); |
| if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) { |
| ElementImpl element = (ElementImpl) parent; |
| if (element.hasStartTag()) |
| return element.getStartEndOffset(); |
| return element.getStartOffset(); |
| } |
| // final fallback to look into first child |
| NodeImpl child = (NodeImpl) getFirstChild(); |
| while (child != null) { |
| IStructuredDocumentRegion childStructuredDocumentRegion = child.getStructuredDocumentRegion(); |
| if (childStructuredDocumentRegion != null) |
| return childStructuredDocumentRegion.getStart(); |
| child = (NodeImpl) child.getFirstChild(); |
| } |
| return 0; |
| } |
| |
| public IStructuredDocumentRegion getStartStructuredDocumentRegion() { |
| return getFirstStructuredDocumentRegion(); |
| } |
| |
| /** |
| * Every node (indirectly) knows its structuredDocument |
| */ |
| public IStructuredDocument getStructuredDocument() { |
| return getModel().getStructuredDocument(); |
| } |
| |
| /** |
| */ |
| IStructuredDocumentRegion getStructuredDocumentRegion() { |
| return this.flatNode; |
| } |
| |
| /** |
| * all but attr return null |
| */ |
| public ITextRegion getValueRegion() { |
| return null; |
| } |
| |
| /** |
| */ |
| public String getValueSource() { |
| return getNodeValue(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.w3c.dom.Node#hasAttributes() |
| */ |
| public boolean hasAttributes() { |
| return false; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.w3c.dom.Node#hasChildNodes() |
| */ |
| public boolean hasChildNodes() { |
| return false; |
| } |
| |
| /** |
| * hasProperties method |
| * |
| * @return boolean |
| */ |
| public boolean hasProperties() { |
| return false; |
| } |
| |
| /** |
| * insertBefore method |
| * |
| * @return org.w3c.dom.Node |
| * @param newChild |
| * org.w3c.dom.Node |
| * @param refChild |
| * org.w3c.dom.Node |
| */ |
| public Node insertBefore(Node newChild, Node refChild) throws DOMException { |
| throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, DOMMessages.HIERARCHY_REQUEST_ERR); |
| } |
| |
| public boolean isChildEditable() { |
| return false; |
| } |
| |
| /** |
| */ |
| public boolean isClosed() { |
| return true; |
| } |
| |
| /** |
| * isContainer method |
| * |
| * @return boolean |
| */ |
| public boolean isContainer() { |
| return false; |
| } |
| |
| public boolean isDataEditable() { |
| if (!fDataEditable) { |
| DOMModelImpl model = (DOMModelImpl) getModel(); |
| if (model != null && model.isReparsing()) { |
| return true; |
| } |
| } |
| return fDataEditable; |
| } |
| |
| /** |
| */ |
| public boolean isSupported(String feature, String version) { |
| if (this.ownerDocument == null) |
| return false; |
| DOMImplementation impl = this.ownerDocument.getImplementation(); |
| if (impl == null) |
| return false; |
| return impl.hasFeature(feature, version); |
| } |
| |
| /** |
| * @param s |
| * @return |
| */ |
| private String lookupMessage(short s) { |
| // TODO: make localized version |
| String result = null; |
| switch (s) { |
| case DOMException.DOMSTRING_SIZE_ERR : |
| result = DOMMessages.DOMSTRING_SIZE_ERR; |
| break; |
| case DOMException.HIERARCHY_REQUEST_ERR : |
| result = DOMMessages.HIERARCHY_REQUEST_ERR; |
| break; |
| case DOMException.INDEX_SIZE_ERR : |
| result = DOMMessages.INDEX_SIZE_ERR; |
| break; |
| case DOMException.INUSE_ATTRIBUTE_ERR : |
| result = DOMMessages.INUSE_ATTRIBUTE_ERR; |
| break; |
| case DOMException.INVALID_ACCESS_ERR : |
| result = DOMMessages.INVALID_ACCESS_ERR; |
| break; |
| case DOMException.INVALID_CHARACTER_ERR : |
| result = DOMMessages.INVALID_CHARACTER_ERR; |
| break; |
| case DOMException.INVALID_MODIFICATION_ERR : |
| result = DOMMessages.INVALID_MODIFICATION_ERR; |
| break; |
| case DOMException.INVALID_STATE_ERR : |
| result = DOMMessages.INVALID_STATE_ERR; |
| break; |
| case DOMException.NAMESPACE_ERR : |
| result = DOMMessages.NAMESPACE_ERR; |
| break; |
| case DOMException.NO_DATA_ALLOWED_ERR : |
| result = DOMMessages.NO_DATA_ALLOWED_ERR; |
| break; |
| case DOMException.NO_MODIFICATION_ALLOWED_ERR : |
| result = DOMMessages.NO_MODIFICATION_ALLOWED_ERR; |
| break; |
| case DOMException.NOT_FOUND_ERR : |
| result = DOMMessages.NOT_FOUND_ERR; |
| break; |
| case DOMException.NOT_SUPPORTED_ERR : |
| result = DOMMessages.NOT_SUPPORTED_ERR; |
| break; |
| case DOMException.SYNTAX_ERR : |
| result = DOMMessages.SYNTAX_ERR; |
| break; |
| case 17:// DOMException.TYPE_MISMATCH_ERR : |
| result = DOMMessages.TYPE_MISMATCH_ERR; |
| break; |
| case 16:// DOMException.VALIDATION_ERR : |
| result = DOMMessages.VALIDATION_ERR; |
| break; |
| case DOMException.WRONG_DOCUMENT_ERR : |
| result = DOMMessages.WRONG_DOCUMENT_ERR; |
| break; |
| default : |
| result = NodeImpl.EMPTY_STRING; |
| break; |
| } |
| return result; |
| } |
| |
| /** |
| * normalize method |
| */ |
| public void normalize() { |
| TextImpl prevText = null; |
| for (Node child = getFirstChild(); child != null; child = child.getNextSibling()) { |
| switch (child.getNodeType()) { |
| case TEXT_NODE : { |
| if (prevText == null) { |
| prevText = (TextImpl) child; |
| break; |
| } |
| Text text = (Text) child; |
| removeChild(text); |
| prevText.appendText(text); |
| child = prevText; |
| break; |
| } |
| case ELEMENT_NODE : { |
| Element element = (Element) child; |
| element.normalize(); |
| prevText = null; |
| break; |
| } |
| default : |
| prevText = null; |
| break; |
| } |
| } |
| } |
| |
| protected void notifyEditableChanged() { |
| DocumentImpl document = (DocumentImpl) getContainerDocument(); |
| if (document == null) |
| return; |
| DOMModelImpl model = (DOMModelImpl) document.getModel(); |
| if (model == null) |
| return; |
| model.editableChanged(this); |
| } |
| |
| /** |
| * notifyValueChanged method |
| */ |
| protected void notifyValueChanged() { |
| DocumentImpl document = (DocumentImpl) getContainerDocument(); |
| if (document == null) |
| return; |
| |
| syncDataEditableState(); |
| |
| DOMModelImpl model = (DOMModelImpl) document.getModel(); |
| if (model == null) |
| return; |
| model.valueChanged(this); |
| } |
| |
| /** |
| * removeChild method |
| * |
| * @return org.w3c.dom.Node |
| * @param oldChild |
| * org.w3c.dom.Node |
| */ |
| public Node removeChild(Node oldChild) throws DOMException { |
| throw new DOMException(DOMException.NOT_FOUND_ERR, DOMMessages.NOT_FOUND_ERR); |
| } |
| |
| /** |
| * removeChildNodes method |
| */ |
| public void removeChildNodes() { |
| } |
| |
| /** |
| * removeChildNodes method |
| * |
| * @return org.w3c.dom.DocumentFragment |
| * @param firstChild |
| * org.w3c.dom.Node |
| * @param lastChild |
| * org.w3c.dom.Node |
| */ |
| public DocumentFragment removeChildNodes(Node firstChild, Node lastChild) { |
| return null; |
| } |
| |
| /** |
| * replaceChild method |
| * |
| * @return org.w3c.dom.Node |
| * @param newChild |
| * org.w3c.dom.Node |
| * @param oldChild |
| * org.w3c.dom.Node |
| */ |
| public Node replaceChild(Node newChild, Node oldChild) throws DOMException { |
| throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, DOMMessages.HIERARCHY_REQUEST_ERR); |
| } |
| |
| /** |
| * Resets children values from IStructuredDocumentRegion. |
| */ |
| void resetStructuredDocumentRegions() { |
| for (NodeImpl child = (NodeImpl) getFirstChild(); child != null; child = (NodeImpl) child.getNextSibling()) { |
| child.resetStructuredDocumentRegions(); |
| } |
| this.flatNode = null; |
| } |
| |
| public void setChildEditable(boolean editable) { |
| // nop |
| } |
| |
| public void setDataEditable(boolean editable) { |
| if (fDataEditable == editable) { |
| return; |
| } |
| |
| ReadOnlyController roc = ReadOnlyController.getInstance(); |
| if (editable) { |
| roc.unlockData(this); |
| } |
| else { |
| roc.lockData(this); |
| } |
| |
| fDataEditable = editable; |
| |
| notifyEditableChanged(); |
| } |
| |
| public void setEditable(boolean editable, boolean deep) { |
| if (deep) { |
| IDOMNode node = (IDOMNode) getFirstChild(); |
| while (node != null) { |
| node.setEditable(editable, deep); |
| node = (IDOMNode) node.getNextSibling(); |
| } |
| } |
| setChildEditable(editable); |
| setDataEditable(editable); |
| } |
| |
| /** |
| * setNextSibling method |
| * |
| * @param nextSibling |
| * org.w3c.dom.Node |
| */ |
| protected void setNextSibling(Node nextSibling) { |
| this.nextSibling = (NodeImpl) nextSibling; |
| } |
| |
| /** |
| * setNodeValue method |
| * |
| * @param nodeValue |
| * java.lang.String |
| */ |
| public void setNodeValue(String nodeValue) throws DOMException { |
| } |
| |
| /** |
| * setOwnerDocument method |
| * |
| * @param ownerDocument |
| * org.w3c.dom.Document |
| */ |
| protected void setOwnerDocument(Document ownerDocument) { |
| this.ownerDocument = (DocumentImpl) ownerDocument; |
| } |
| |
| /** |
| */ |
| protected void setOwnerDocument(Document ownerDocument, boolean deep) { |
| this.ownerDocument = (DocumentImpl) ownerDocument; |
| |
| if (deep) { |
| for (NodeImpl child = (NodeImpl) getFirstChild(); child != null; child = (NodeImpl) child.getNextSibling()) { |
| child.setOwnerDocument(ownerDocument, deep); |
| } |
| } |
| } |
| |
| /** |
| * setParentNode method |
| * |
| * @param parentNode |
| * org.w3c.dom.Node |
| */ |
| protected void setParentNode(Node parentNode) { |
| this.parentNode = (NodeImpl) parentNode; |
| } |
| |
| /** |
| */ |
| public void setPrefix(String prefix) throws DOMException { |
| } |
| |
| /** |
| * setPreviousSibling method |
| * |
| * @param previousSibling |
| * org.w3c.dom.Node |
| */ |
| protected void setPreviousSibling(Node previousSibling) { |
| this.previousSibling = (NodeImpl) previousSibling; |
| } |
| |
| /** |
| */ |
| public void setSource(String source) throws InvalidCharacterException { |
| // not supported |
| } |
| |
| /** |
| */ |
| void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) { |
| this.flatNode = flatNode; |
| } |
| |
| /** |
| */ |
| public void setValueSource(String source) { |
| setNodeValue(source); |
| } |
| |
| protected void syncDataEditableState() { |
| ReadOnlyController roc = ReadOnlyController.getInstance(); |
| if (fDataEditable) { |
| roc.unlockData(this); |
| } |
| else { |
| roc.lockData(this); |
| } |
| } |
| |
| /** |
| * toString method |
| * |
| * @return java.lang.String |
| */ |
| public String toString() { |
| return getNodeName(); |
| } |
| |
| public int getLength() { |
| int result = -1; |
| int start = getStartOffset(); |
| if (start >= 0) { |
| int end = getEndOffset(); |
| if (end >= 0) { |
| result = end - start; |
| if (result < -1) { |
| result = -1; |
| } |
| } |
| } |
| return result; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.w3c.dom.Node#compareDocumentPosition(org.w3c.dom.Node) |
| */ |
| public short compareDocumentPosition(Node other) throws DOMException { |
| if (!(other instanceof IDOMNode)) |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, DOMMessages.NOT_SUPPORTED_ERR); |
| |
| int nodeStart = this.getStartOffset(); |
| int otherStart = ((IDOMNode) other).getStartOffset(); |
| |
| if (otherStart > nodeStart) { |
| return DOCUMENT_POSITION_FOLLOWING; |
| } |
| else if (otherStart < nodeStart) { |
| return DOCUMENT_POSITION_PRECEDING; |
| } |
| return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; |
| } |
| |
| /** |
| * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3 |
| */ |
| public String getBaseURI() { |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$ |
| } |
| |
| /** |
| * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3 |
| */ |
| public Object getFeature(String feature, String version) { |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$ |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.w3c.dom.Node#getTextContent() |
| */ |
| public String getTextContent() throws DOMException { |
| switch (getNodeType()) { |
| case Node.DOCUMENT_NODE : |
| case Node.DOCUMENT_TYPE_NODE : |
| case Node.NOTATION_NODE : |
| return null; |
| case Node.TEXT_NODE : |
| case Node.CDATA_SECTION_NODE : |
| case Node.COMMENT_NODE : |
| case Node.PROCESSING_INSTRUCTION_NODE : |
| return getNodeValue(); |
| } |
| |
| if (hasChildNodes()) { |
| final StringBuffer builder = new StringBuffer(); |
| |
| Node child = getFirstChild(); |
| while (child != null) { |
| short nodeType = child.getNodeType(); |
| if (nodeType == Node.COMMENT_NODE || nodeType == Node.PROCESSING_INSTRUCTION_NODE) { |
| child = child.getNextSibling(); |
| continue; |
| } |
| |
| String text = ((IDOMNode) child).getTextContent(); |
| if (text != null) { |
| builder.append(text); |
| } |
| child = child.getNextSibling(); |
| } |
| |
| return builder.toString(); |
| } |
| |
| return EMPTY_STRING; |
| } |
| |
| /** |
| * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3 |
| */ |
| public boolean isDefaultNamespace(String namespaceURI) { |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$ |
| } |
| |
| /* (non-Javadoc) |
| * @see org.w3c.dom.Node#isEqualNode(org.w3c.dom.Node) |
| */ |
| public boolean isEqualNode(Node arg) { |
| return this.equals(arg); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.w3c.dom.Node#isSameNode(org.w3c.dom.Node) |
| */ |
| public boolean isSameNode(Node other) { |
| return this == other; |
| } |
| |
| /** |
| * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3 |
| */ |
| public String lookupNamespaceURI(String prefix) { |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$ |
| } |
| |
| /** |
| * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3 |
| */ |
| public String lookupPrefix(String namespaceURI) { |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$ |
| } |
| |
| /** |
| * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3 |
| */ |
| public void setTextContent(String textContent) throws DOMException { |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$ |
| } |
| |
| /** |
| * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3 |
| */ |
| public TypeInfo getSchemaTypeInfo() { |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$ |
| } |
| |
| /** |
| * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3 |
| */ |
| public boolean isId() { |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Retrieves the object for a node associated to a key. |
| * |
| * @param key The key associated with the object. |
| * @return object The object for this node, associated with the key passed |
| * or null if there was none set. |
| * |
| * @since DOM Level 3 |
| */ |
| public Object getUserData(String key) { |
| |
| if (key==null) return null; |
| Map userDataTable = UserData.getInstance().getUserDataTable(this); |
| if (userDataTable!=null) { |
| UserDataAndHandler userDataAndHandler = (UserDataAndHandler) userDataTable.get(key); |
| if (userDataAndHandler!=null) { |
| return userDataAndHandler.getData(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Sets the user data and handler for a key |
| * |
| * @param key The key associated with the object. |
| * @param object The object for this node, associated with the key passed. |
| * Null passed removes the existing association to the key. |
| * @param handler UserDataHandler for the userdata associated with this key |
| * @return Object The previous userdata object if set, null if it was none. |
| * |
| * @since DOM Level 3 |
| */ |
| public Object setUserData(String key, Object data, UserDataHandler handler) { |
| |
| UserDataAndHandler previousDataAndHandler=null; |
| |
| //return immediately for null keys |
| if (key ==null) return null; |
| Map userDataTable = UserData.getInstance().getUserDataTable(this); |
| //remove association for the key if data is null |
| if (data==null) { |
| if (userDataTable==null) return null; |
| |
| //see if there is a previous value set |
| previousDataAndHandler = (UserDataAndHandler) userDataTable.get(key); |
| if (previousDataAndHandler!=null) { |
| userDataTable.remove(key); |
| return previousDataAndHandler.getData(); |
| } |
| //there is no previous value found |
| return null; |
| } |
| |
| //if data passed is not null |
| //the first data in the hashtable |
| if (userDataTable==null) { |
| userDataTable=new Hashtable(); |
| UserDataAndHandler userDataAndHandler=new UserDataAndHandler(data,handler); |
| userDataTable.put(key,userDataAndHandler); |
| return null; |
| //there is already data in the hashtable |
| } else { |
| UserDataAndHandler userDataAndHandler=new UserDataAndHandler(data,handler); |
| previousDataAndHandler=(UserDataAndHandler) userDataTable.put(key,userDataAndHandler); |
| |
| //if we replace a value |
| if (previousDataAndHandler!=null) |
| return previousDataAndHandler.getData(); |
| else { |
| return null; |
| } |
| } |
| } |
| |
| /** |
| * Notifies the UserDataHandlers of the node. |
| * |
| * @param operation |
| * @param destination |
| */ |
| protected void notifyUserDataHandlers(short operation, Node destination) { |
| |
| if (operation!=UserDataHandler.NODE_ADOPTED |
| & operation!=UserDataHandler.NODE_CLONED |
| & operation!=UserDataHandler.NODE_DELETED |
| & operation!=UserDataHandler.NODE_IMPORTED |
| & operation!=UserDataHandler.NODE_RENAMED) |
| return; |
| Map userDataTable = UserData.getInstance().getUserDataTable(this); |
| if (userDataTable!=null) { |
| Iterator entries =userDataTable.entrySet().iterator(); |
| while (entries.hasNext()) { |
| Map.Entry entry = (Map.Entry) entries.next(); |
| String key = entry.getKey().toString(); //should always be a string |
| UserDataAndHandler dataAndHandler = (UserDataAndHandler) entry.getValue(); |
| if (dataAndHandler!=null) { |
| UserDataHandler dataHandler=dataAndHandler.getHandler(); |
| if (dataHandler!=null) { |
| dataHandler.handle(operation, key, dataAndHandler.getData(), this, destination); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * |
| * Class for user data and UserDataHandler |
| */ |
| protected static class UserDataAndHandler implements Serializable { |
| |
| /** |
| * Generated Serial ID |
| */ |
| private static final long serialVersionUID = 4860521237315444841L; |
| /** |
| * Generated serialization version |
| */ |
| |
| private Object data; |
| private UserDataHandler handler; |
| |
| public UserDataAndHandler(Object data, UserDataHandler handler) |
| { |
| this.data=data; |
| this.handler=handler; |
| } |
| |
| public Object getData() { |
| return data; |
| } |
| |
| public void setData(Object data) { |
| this.data = data; |
| } |
| |
| public UserDataHandler getHandler() { |
| return handler; |
| } |
| |
| public void setHandler(UserDataHandler handler) { |
| this.handler = handler; |
| } |
| } |
| } |