0001: /*
0002: * The Apache Software License, Version 1.1
0003: *
0004: *
0005: * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
0006: * reserved.
0007: *
0008: * Redistribution and use in source and binary forms, with or without
0009: * modification, are permitted provided that the following conditions
0010: * are met:
0011: *
0012: * 1. Redistributions of source code must retain the above copyright
0013: * notice, this list of conditions and the following disclaimer.
0014: *
0015: * 2. Redistributions in binary form must reproduce the above copyright
0016: * notice, this list of conditions and the following disclaimer in
0017: * the documentation and/or other materials provided with the
0018: * distribution.
0019: *
0020: * 3. The end-user documentation included with the redistribution,
0021: * if any, must include the following acknowledgment:
0022: * "This product includes software developed by the
0023: * Apache Software Foundation (http://www.apache.org/)."
0024: * Alternately, this acknowledgment may appear in the software itself,
0025: * if and wherever such third-party acknowledgments normally appear.
0026: *
0027: * 4. The names "Xerces" and "Apache Software Foundation" must
0028: * not be used to endorse or promote products derived from this
0029: * software without prior written permission. For written
0030: * permission, please contact apache@apache.org.
0031: *
0032: * 5. Products derived from this software may not be called "Apache",
0033: * nor may "Apache" appear in their name, without prior written
0034: * permission of the Apache Software Foundation.
0035: *
0036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0039: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0040: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0047: * SUCH DAMAGE.
0048: * ====================================================================
0049: *
0050: * This software consists of voluntary contributions made by many
0051: * individuals on behalf of the Apache Software Foundation and was
0052: * originally based on software copyright (c) 1999, International
0053: * Business Machines, Inc., http://www.apache.org. For more
0054: * information on the Apache Software Foundation, please see
0055: * <http://www.apache.org/>.
0056: */
0057:
0058: package org.apache.xerces.dom;
0059:
0060: import java.util.Enumeration;
0061: import java.util.Hashtable;
0062:
0063: import org.w3c.dom.Attr;
0064: import org.w3c.dom.CDATASection;
0065: import org.w3c.dom.Comment;
0066: import org.w3c.dom.DOMException;
0067: import org.w3c.dom.DOMImplementation;
0068: import org.w3c.dom.Document;
0069: import org.w3c.dom.DocumentFragment;
0070: import org.w3c.dom.DocumentType;
0071: import org.w3c.dom.Element;
0072: import org.w3c.dom.Entity;
0073: import org.w3c.dom.EntityReference;
0074: import org.w3c.dom.NamedNodeMap;
0075: import org.w3c.dom.Node;
0076: import org.w3c.dom.NodeList;
0077: import org.w3c.dom.Notation;
0078: import org.w3c.dom.ProcessingInstruction;
0079: import org.w3c.dom.Text;
0080:
0081: import org.w3c.dom.events.Event;
0082: import org.w3c.dom.events.EventListener;
0083: import org.w3c.dom.events.EventTarget;
0084:
0085: import org.apache.xerces.utils.XMLCharacterProperties;
0086:
0087: /**
0088: * The Document interface represents the entire HTML or XML document.
0089: * Conceptually, it is the root of the document tree, and provides the
0090: * primary access to the document's data.
0091: * <P>
0092: * Since elements, text nodes, comments, processing instructions,
0093: * etc. cannot exist outside the context of a Document, the Document
0094: * interface also contains the factory methods needed to create these
0095: * objects. The Node objects created have a ownerDocument attribute
0096: * which associates them with the Document within whose context they
0097: * were created.
0098: * <p>
0099: * The CoreDocumentImpl class only implements the DOM Core. Additional modules
0100: * are supported by the more complete DocumentImpl subclass.
0101: * <p>
0102: * <b>Note:</b> When any node in the document is serialized, the
0103: * entire document is serialized along with it.
0104: *
0105: * @author Arnaud Le Hors, IBM
0106: * @author Joe Kesselman, IBM
0107: * @author Andy Clark, IBM
0108: * @author Ralf Pfeiffer, IBM
0109: * @version
0110: * @since PR-DOM-Level-1-19980818.
0111: */
0112: public class CoreDocumentImpl extends ParentNode implements Document {
0113:
0114: //
0115: // Constants
0116: //
0117:
0118: /** Serialization version. */
0119: static final long serialVersionUID = 0;
0120:
0121: //
0122: // Data
0123: //
0124:
0125: // document information
0126:
0127: /** Document type. */
0128: protected DocumentTypeImpl docType;
0129:
0130: /** Document element. */
0131: protected ElementImpl docElement;
0132:
0133: /**Experimental DOM Level 3 feature: Document encoding */
0134: protected String encoding;
0135:
0136: /**Experimental DOM Level 3 feature: Document version */
0137: protected String version;
0138:
0139: /**Experimental DOM Level 3 feature: Document standalone */
0140: protected boolean standalone;
0141:
0142: /** Identifiers. */
0143: protected Hashtable identifiers;
0144:
0145: /** Table for quick check of child insertion. */
0146: protected static int[] kidOK;
0147:
0148: /**
0149: * Number of alterations made to this document since its creation.
0150: * Serves as a "dirty bit" so that live objects such as NodeList can
0151: * recognize when an alteration has been made and discard its cached
0152: * state information.
0153: * <p>
0154: * Any method that alters the tree structure MUST cause or be
0155: * accompanied by a call to changed(), to inform it that any outstanding
0156: * NodeLists may have to be updated.
0157: * <p>
0158: * (Required because NodeList is simultaneously "live" and integer-
0159: * indexed -- a bad decision in the DOM's design.)
0160: * <p>
0161: * Note that changes which do not affect the tree's structure -- changing
0162: * the node's name, for example -- do _not_ have to call changed().
0163: * <p>
0164: * Alternative implementation would be to use a cryptographic
0165: * Digest value rather than a count. This would have the advantage that
0166: * "harmless" changes (those producing equal() trees) would not force
0167: * NodeList to resynchronize. Disadvantage is that it's slightly more prone
0168: * to "false negatives", though that's the difference between "wildly
0169: * unlikely" and "absurdly unlikely". IF we start maintaining digests,
0170: * we should consider taking advantage of them.
0171: *
0172: * Note: This used to be done a node basis, so that we knew what
0173: * subtree changed. But since only DeepNodeList really use this today,
0174: * the gain appears to be really small compared to the cost of having
0175: * an int on every (parent) node plus having to walk up the tree all the
0176: * way to the root to mark the branch as changed everytime a node is
0177: * changed.
0178: * So we now have a single counter global to the document. It means that
0179: * some objects may flush their cache more often than necessary, but this
0180: * makes nodes smaller and only the document needs to be marked as changed.
0181: */
0182: protected int changes = 0;
0183:
0184: // experimental
0185:
0186: /** Allow grammar access. */
0187: protected boolean allowGrammarAccess;
0188:
0189: /** Bypass error checking. */
0190: protected boolean errorChecking = true;
0191:
0192: //
0193: // Static initialization
0194: //
0195:
0196: static {
0197:
0198: kidOK = new int[13];
0199:
0200: kidOK[DOCUMENT_NODE] = 1 << ELEMENT_NODE
0201: | 1 << PROCESSING_INSTRUCTION_NODE | 1 << COMMENT_NODE
0202: | 1 << DOCUMENT_TYPE_NODE;
0203:
0204: kidOK[DOCUMENT_FRAGMENT_NODE] = kidOK[ENTITY_NODE] = kidOK[ENTITY_REFERENCE_NODE] = kidOK[ELEMENT_NODE] = 1 << ELEMENT_NODE
0205: | 1 << PROCESSING_INSTRUCTION_NODE
0206: | 1 << COMMENT_NODE
0207: | 1 << TEXT_NODE
0208: | 1 << CDATA_SECTION_NODE
0209: | 1 << ENTITY_REFERENCE_NODE;
0210:
0211: kidOK[ATTRIBUTE_NODE] = 1 << TEXT_NODE
0212: | 1 << ENTITY_REFERENCE_NODE;
0213:
0214: kidOK[DOCUMENT_TYPE_NODE] = kidOK[PROCESSING_INSTRUCTION_NODE] = kidOK[COMMENT_NODE] = kidOK[TEXT_NODE] = kidOK[CDATA_SECTION_NODE] = kidOK[NOTATION_NODE] = 0;
0215:
0216: } // static
0217:
0218: //
0219: // Constructors
0220: //
0221:
0222: /**
0223: * NON-DOM: Actually creating a Document is outside the DOM's spec,
0224: * since it has to operate in terms of a particular implementation.
0225: */
0226: public CoreDocumentImpl() {
0227: this (false);
0228: // make sure the XMLCharacterProperties class is initilialized
0229: XMLCharacterProperties.initCharFlags();
0230: }
0231:
0232: /** Constructor. */
0233: public CoreDocumentImpl(boolean grammarAccess) {
0234: super (null);
0235: ownerDocument = this ;
0236: allowGrammarAccess = grammarAccess;
0237: // make sure the XMLCharacterProperties class is initilialized
0238: XMLCharacterProperties.initCharFlags();
0239: }
0240:
0241: /**
0242: * For DOM2 support.
0243: * The createDocument factory method is in DOMImplementation.
0244: */
0245: public CoreDocumentImpl(DocumentType doctype) {
0246: this (doctype, false);
0247: // make sure the XMLCharacterProperties class is initilialized
0248: XMLCharacterProperties.initCharFlags();
0249: }
0250:
0251: /** For DOM2 support. */
0252: public CoreDocumentImpl(DocumentType doctype, boolean grammarAccess) {
0253: this (grammarAccess);
0254: if (doctype != null) {
0255: DocumentTypeImpl doctypeImpl;
0256: try {
0257: doctypeImpl = (DocumentTypeImpl) doctype;
0258: } catch (ClassCastException e) {
0259: throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
0260: "DOM005 Wrong document");
0261: }
0262: doctypeImpl.ownerDocument = this ;
0263: appendChild(doctype);
0264: }
0265: // make sure the XMLCharacterProperties class is initilialized
0266: XMLCharacterProperties.initCharFlags();
0267: }
0268:
0269: //
0270: // Node methods
0271: //
0272:
0273: // even though ownerDocument refers to this in this implementation
0274: // the DOM Level 2 spec says it must be null, so make it appear so
0275: final public Document getOwnerDocument() {
0276: return null;
0277: }
0278:
0279: /** Returns the node type. */
0280: public short getNodeType() {
0281: return Node.DOCUMENT_NODE;
0282: }
0283:
0284: /** Returns the node name. */
0285: public String getNodeName() {
0286: return "#document";
0287: }
0288:
0289: /**
0290: * Deep-clone a document, including fixing ownerDoc for the cloned
0291: * children. Note that this requires bypassing the WRONG_DOCUMENT_ERR
0292: * protection. I've chosen to implement it by calling importNode
0293: * which is DOM Level 2.
0294: *
0295: * @return org.w3c.dom.Node
0296: * @param deep boolean, iff true replicate children
0297: */
0298: public Node cloneNode(boolean deep) {
0299:
0300: CoreDocumentImpl newdoc = new CoreDocumentImpl();
0301: cloneNode(newdoc, deep);
0302:
0303: return newdoc;
0304:
0305: } // cloneNode(boolean):Node
0306:
0307: /**
0308: * internal method to share code with subclass
0309: **/
0310: protected void cloneNode(CoreDocumentImpl newdoc, boolean deep) {
0311:
0312: // clone the children by importing them
0313: if (needsSyncChildren()) {
0314: synchronizeChildren();
0315: }
0316:
0317: if (deep) {
0318: Hashtable reversedIdentifiers = null;
0319:
0320: if (identifiers != null) {
0321: // Build a reverse mapping from element to identifier.
0322: reversedIdentifiers = new Hashtable();
0323: Enumeration elementIds = identifiers.keys();
0324: while (elementIds.hasMoreElements()) {
0325: Object elementId = elementIds.nextElement();
0326: reversedIdentifiers.put(identifiers.get(elementId),
0327: elementId);
0328: }
0329: }
0330:
0331: // Copy children into new document.
0332: for (ChildNode kid = firstChild; kid != null; kid = kid.nextSibling) {
0333: newdoc.appendChild(newdoc.importNode(kid, true,
0334: reversedIdentifiers));
0335: }
0336: }
0337:
0338: // experimental
0339: newdoc.allowGrammarAccess = allowGrammarAccess;
0340: newdoc.errorChecking = errorChecking;
0341:
0342: } // cloneNode(CoreDocumentImpl,boolean):void
0343:
0344: /**
0345: * Since a Document may contain at most one top-level Element child,
0346: * and at most one DocumentType declaraction, we need to subclass our
0347: * add-children methods to implement this constraint.
0348: * Since appendChild() is implemented as insertBefore(,null),
0349: * altering the latter fixes both.
0350: * <p>
0351: * While I'm doing so, I've taken advantage of the opportunity to
0352: * cache documentElement and docType so we don't have to
0353: * search for them.
0354: *
0355: * REVISIT: According to the spec it is not allowed to alter neither the
0356: * document element nor the document type in any way
0357: */
0358: public Node insertBefore(Node newChild, Node refChild)
0359: throws DOMException {
0360:
0361: // Only one such child permitted
0362: int type = newChild.getNodeType();
0363: if (errorChecking) {
0364: if ((type == Node.ELEMENT_NODE && docElement != null)
0365: || (type == Node.DOCUMENT_TYPE_NODE && docType != null)) {
0366: throw new DOMException(
0367: DOMException.HIERARCHY_REQUEST_ERR,
0368: "DOM006 Hierarchy request error");
0369: }
0370: }
0371:
0372: super .insertBefore(newChild, refChild);
0373:
0374: // If insert succeeded, cache the kid appropriately
0375: if (type == Node.ELEMENT_NODE) {
0376: docElement = (ElementImpl) newChild;
0377: } else if (type == Node.DOCUMENT_TYPE_NODE) {
0378: docType = (DocumentTypeImpl) newChild;
0379: }
0380:
0381: return newChild;
0382:
0383: } // insertBefore(Node,Node):Node
0384:
0385: /**
0386: * Since insertBefore caches the docElement (and, currently, docType),
0387: * removeChild has to know how to undo the cache
0388: *
0389: * REVISIT: According to the spec it is not allowed to alter neither the
0390: * document element nor the document type in any way
0391: */
0392: public Node removeChild(Node oldChild) throws DOMException {
0393: super .removeChild(oldChild);
0394:
0395: // If remove succeeded, un-cache the kid appropriately
0396: int type = oldChild.getNodeType();
0397: if (type == Node.ELEMENT_NODE) {
0398: docElement = null;
0399: } else if (type == Node.DOCUMENT_TYPE_NODE) {
0400: docType = null;
0401: }
0402:
0403: return oldChild;
0404:
0405: } // removeChild(Node):Node
0406:
0407: /**
0408: * Since we cache the docElement (and, currently, docType),
0409: * replaceChild has to update the cache
0410: *
0411: * REVISIT: According to the spec it is not allowed to alter neither the
0412: * document element nor the document type in any way
0413: */
0414: public Node replaceChild(Node newChild, Node oldChild)
0415: throws DOMException {
0416:
0417: super .replaceChild(newChild, oldChild);
0418:
0419: int type = oldChild.getNodeType();
0420: if (type == Node.ELEMENT_NODE) {
0421: docElement = (ElementImpl) newChild;
0422: } else if (type == Node.DOCUMENT_TYPE_NODE) {
0423: docType = (DocumentTypeImpl) newChild;
0424: }
0425: return oldChild;
0426: } // replaceChild(Node,Node):Node
0427:
0428: //
0429: // Document methods
0430: //
0431:
0432: // factory methods
0433:
0434: /**
0435: * Factory method; creates an Attribute having this Document as its
0436: * OwnerDoc.
0437: *
0438: * @param name The name of the attribute. Note that the attribute's value
0439: * is _not_ established at the factory; remember to set it!
0440: *
0441: * @throws DOMException(INVALID_NAME_ERR) if the attribute name is not
0442: * acceptable.
0443: */
0444: public Attr createAttribute(String name) throws DOMException {
0445:
0446: if (errorChecking && !isXMLName(name)) {
0447: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
0448: "DOM002 Illegal character");
0449: }
0450: return new AttrImpl(this , name);
0451:
0452: } // createAttribute(String):Attr
0453:
0454: /**
0455: * Factory method; creates a CDATASection having this Document as
0456: * its OwnerDoc.
0457: *
0458: * @param data The initial contents of the CDATA
0459: *
0460: * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents. (HTML
0461: * not yet implemented.)
0462: */
0463: public CDATASection createCDATASection(String data)
0464: throws DOMException {
0465: return new CDATASectionImpl(this , data);
0466: }
0467:
0468: /**
0469: * Factory method; creates a Comment having this Document as its
0470: * OwnerDoc.
0471: *
0472: * @param data The initial contents of the Comment. */
0473: public Comment createComment(String data) {
0474: return new CommentImpl(this , data);
0475: }
0476:
0477: /**
0478: * Factory method; creates a DocumentFragment having this Document
0479: * as its OwnerDoc.
0480: */
0481: public DocumentFragment createDocumentFragment() {
0482: return new DocumentFragmentImpl(this );
0483: }
0484:
0485: /**
0486: * Factory method; creates an Element having this Document
0487: * as its OwnerDoc.
0488: *
0489: * @param tagName The name of the element type to instantiate. For
0490: * XML, this is case-sensitive. For HTML, the tagName parameter may
0491: * be provided in any case, but it must be mapped to the canonical
0492: * uppercase form by the DOM implementation.
0493: *
0494: * @throws DOMException(INVALID_NAME_ERR) if the tag name is not
0495: * acceptable.
0496: */
0497: public Element createElement(String tagName) throws DOMException {
0498:
0499: if (errorChecking && !isXMLName(tagName)) {
0500: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
0501: "DOM002 Illegal character");
0502: }
0503: return new ElementImpl(this , tagName);
0504:
0505: } // createElement(String):Element
0506:
0507: /**
0508: * Factory method; creates an EntityReference having this Document
0509: * as its OwnerDoc.
0510: *
0511: * @param name The name of the Entity we wish to refer to
0512: *
0513: * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
0514: * nonstandard entities are not permitted. (HTML not yet
0515: * implemented.)
0516: */
0517: public EntityReference createEntityReference(String name)
0518: throws DOMException {
0519:
0520: if (errorChecking && !isXMLName(name)) {
0521: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
0522: "DOM002 Illegal character");
0523: }
0524: return new EntityReferenceImpl(this , name);
0525:
0526: } // createEntityReference(String):EntityReference
0527:
0528: /**
0529: * Factory method; creates a ProcessingInstruction having this Document
0530: * as its OwnerDoc.
0531: *
0532: * @param target The target "processor channel"
0533: * @param data Parameter string to be passed to the target.
0534: *
0535: * @throws DOMException(INVALID_NAME_ERR) if the target name is not
0536: * acceptable.
0537: *
0538: * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents. (HTML
0539: * not yet implemented.)
0540: */
0541: public ProcessingInstruction createProcessingInstruction(
0542: String target, String data) throws DOMException {
0543:
0544: if (errorChecking && !isXMLName(target)) {
0545: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
0546: "DOM002 Illegal character");
0547: }
0548: return new ProcessingInstructionImpl(this , target, data);
0549:
0550: } // createProcessingInstruction(String,String):ProcessingInstruction
0551:
0552: /**
0553: * Factory method; creates a Text node having this Document as its
0554: * OwnerDoc.
0555: *
0556: * @param data The initial contents of the Text.
0557: */
0558: public Text createTextNode(String data) {
0559: return new TextImpl(this , data);
0560: }
0561:
0562: // other document methods
0563:
0564: /**
0565: * For XML, this provides access to the Document Type Definition.
0566: * For HTML documents, and XML documents which don't specify a DTD,
0567: * it will be null.
0568: */
0569: public DocumentType getDoctype() {
0570: if (needsSyncChildren()) {
0571: synchronizeChildren();
0572: }
0573: return docType;
0574: }
0575:
0576: /**
0577: * DOM Level 3 WD - Experimental.
0578: * The encoding of this document (part of XML Declaration)
0579: */
0580: public String getEncoding() {
0581: return encoding;
0582: }
0583:
0584: /**
0585: * DOM Level 3 WD - Experimental.
0586: * The version of this document (part of XML Declaration)
0587: */
0588: public String getVersion() {
0589: return version;
0590: }
0591:
0592: /**
0593: * DOM Level 3 WD - Experimental.
0594: * standalone that specifies whether this document is standalone
0595: * (part of XML Declaration)
0596: */
0597: public boolean getStandalone() {
0598: return standalone;
0599: }
0600:
0601: /**
0602: * Convenience method, allowing direct access to the child node
0603: * which is considered the root of the actual document content. For
0604: * HTML, where it is legal to have more than one Element at the top
0605: * level of the document, we pick the one with the tagName
0606: * "HTML". For XML there should be only one top-level
0607: *
0608: * (HTML not yet supported.)
0609: */
0610: public Element getDocumentElement() {
0611: if (needsSyncChildren()) {
0612: synchronizeChildren();
0613: }
0614: return docElement;
0615: }
0616:
0617: /**
0618: * Return a <em>live</em> collection of all descendent Elements (not just
0619: * immediate children) having the specified tag name.
0620: *
0621: * @param tagname The type of Element we want to gather. "*" will be
0622: * taken as a wildcard, meaning "all elements in the document."
0623: *
0624: * @see DeepNodeListImpl
0625: */
0626: public NodeList getElementsByTagName(String tagname) {
0627: return new DeepNodeListImpl(this , tagname);
0628: }
0629:
0630: /**
0631: * Retrieve information describing the abilities of this particular
0632: * DOM implementation. Intended to support applications that may be
0633: * using DOMs retrieved from several different sources, potentially
0634: * with different underlying representations.
0635: */
0636: public DOMImplementation getImplementation() {
0637: // Currently implemented as a singleton, since it's hardcoded
0638: // information anyway.
0639: return CoreDOMImplementationImpl.getDOMImplementation();
0640: }
0641:
0642: //
0643: // Public methods
0644: //
0645:
0646: // properties
0647:
0648: /**
0649: * Sets whether the DOM implementation performs error checking
0650: * upon operations. Turning off error checking only affects
0651: * the following DOM checks:
0652: * <ul>
0653: * <li>Checking strings to make sure that all characters are
0654: * legal XML characters
0655: * <li>Hierarchy checking such as allowed children, checks for
0656: * cycles, etc.
0657: * </ul>
0658: * <p>
0659: * Turning off error checking does <em>not</em> turn off the
0660: * following checks:
0661: * <ul>
0662: * <li>Read only checks
0663: * <li>Checks related to DOM events
0664: * </ul>
0665: */
0666:
0667: public void setErrorChecking(boolean check) {
0668: errorChecking = check;
0669: }
0670:
0671: /*
0672: * DOM Level 3 WD - Experimental.
0673: */
0674: public void setStrictErrorChecking(boolean check) {
0675: errorChecking = check;
0676: }
0677:
0678: /**
0679: * DOM Level 3 WD - Experimental.
0680: * An attribute specifying, as part of the XML declaration,
0681: * the encoding of this document. This is null when unspecified.
0682: */
0683: public void setEncoding(String value) {
0684: encoding = value;
0685: }
0686:
0687: /**
0688: * DOM Level 3 WD - Experimental.
0689: * version - An attribute specifying, as part of the XML declaration,
0690: * the version number of this document. This is null when unspecified
0691: */
0692: public void setVersion(String value) {
0693: version = value;
0694: }
0695:
0696: /**
0697: * DOM Level 3 WD - Experimental.
0698: * standalone - An attribute specifying, as part of the XML declaration,
0699: * whether this document is standalone
0700: */
0701: public void setStandalone(boolean value) {
0702: standalone = value;
0703: }
0704:
0705: /**
0706: * Returns true if the DOM implementation performs error checking.
0707: */
0708: public boolean getErrorChecking() {
0709: return errorChecking;
0710: }
0711:
0712: /*
0713: * DOM Level 3 WD - Experimental.
0714: */
0715: public boolean getStrictErrorChecking() {
0716: return errorChecking;
0717: }
0718:
0719: /**
0720: * Sets whether the DOM implementation generates mutation events
0721: * upon operations.
0722: */
0723: void setMutationEvents(boolean set) {
0724: // does nothing by default - overidden in subclass
0725: }
0726:
0727: /**
0728: * Returns true if the DOM implementation generates mutation events.
0729: */
0730: boolean getMutationEvents() {
0731: // does nothing by default - overriden in subclass
0732: return false;
0733: }
0734:
0735: // non-DOM factory methods
0736:
0737: /**
0738: * NON-DOM
0739: * Factory method; creates a DocumentType having this Document
0740: * as its OwnerDoc. (REC-DOM-Level-1-19981001 left the process of building
0741: * DTD information unspecified.)
0742: *
0743: * @param name The name of the Entity we wish to provide a value for.
0744: *
0745: * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
0746: * DTDs are not permitted. (HTML not yet implemented.)
0747: */
0748: public DocumentType createDocumentType(String qualifiedName,
0749: String publicID, String systemID) throws DOMException {
0750:
0751: if (errorChecking && !isXMLName(qualifiedName)) {
0752: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
0753: "DOM002 Illegal character");
0754: }
0755: return new DocumentTypeImpl(this , qualifiedName, publicID,
0756: systemID);
0757:
0758: } // createDocumentType(String):DocumentType
0759:
0760: /**
0761: * NON-DOM
0762: * Factory method; creates an Entity having this Document
0763: * as its OwnerDoc. (REC-DOM-Level-1-19981001 left the process of building
0764: * DTD information unspecified.)
0765: *
0766: * @param name The name of the Entity we wish to provide a value for.
0767: *
0768: * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
0769: * nonstandard entities are not permitted. (HTML not yet
0770: * implemented.)
0771: */
0772: public Entity createEntity(String name) throws DOMException {
0773:
0774: if (errorChecking && !isXMLName(name)) {
0775: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
0776: "DOM002 Illegal character");
0777: }
0778: return new EntityImpl(this , name);
0779:
0780: } // createEntity(String):Entity
0781:
0782: /**
0783: * NON-DOM
0784: * Factory method; creates a Notation having this Document
0785: * as its OwnerDoc. (REC-DOM-Level-1-19981001 left the process of building
0786: * DTD information unspecified.)
0787: *
0788: * @param name The name of the Notation we wish to describe
0789: *
0790: * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
0791: * notations are not permitted. (HTML not yet
0792: * implemented.)
0793: */
0794: public Notation createNotation(String name) throws DOMException {
0795:
0796: if (errorChecking && !isXMLName(name)) {
0797: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
0798: "DOM002 Illegal character");
0799: }
0800: return new NotationImpl(this , name);
0801:
0802: } // createNotation(String):Notation
0803:
0804: /**
0805: * NON-DOM Factory method: creates an element definition. Element
0806: * definitions hold default attribute values.
0807: */
0808: public ElementDefinitionImpl createElementDefinition(String name)
0809: throws DOMException {
0810:
0811: if (errorChecking && !isXMLName(name)) {
0812: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
0813: "DOM002 Illegal character");
0814: }
0815: return new ElementDefinitionImpl(this , name);
0816:
0817: } // createElementDefinition(String):ElementDefinitionImpl
0818:
0819: // other non-DOM methods
0820:
0821: /**
0822: * Copies a node from another document to this document. The new nodes are
0823: * created using this document's factory methods and are populated with the
0824: * data from the source's accessor methods defined by the DOM interfaces.
0825: * Its behavior is otherwise similar to that of cloneNode.
0826: * <p>
0827: * According to the DOM specifications, document nodes cannot be imported
0828: * and a NOT_SUPPORTED_ERR exception is thrown if attempted.
0829: */
0830: public Node importNode(Node source, boolean deep)
0831: throws DOMException {
0832: return importNode(source, deep, null);
0833: } // importNode(Node,boolean):Node
0834:
0835: /**
0836: * Overloaded implementation of DOM's importNode method. This method
0837: * provides the core functionality for the public importNode and cloneNode
0838: * methods.
0839: *
0840: * The reversedIdentifiers parameter is provided for cloneNode to
0841: * preserve the document's identifiers. The Hashtable has Elements as the
0842: * keys and their identifiers as the values. When an element is being
0843: * imported, a check is done for an associated identifier. If one exists,
0844: * the identifier is registered with the new, imported element. If
0845: * reversedIdentifiers is null, the parameter is not applied.
0846: */
0847: private Node importNode(Node source, boolean deep,
0848: Hashtable reversedIdentifiers) throws DOMException {
0849: Node newnode = null;
0850:
0851: // Sigh. This doesn't work; too many nodes have private data that
0852: // would have to be manually tweaked. May be able to add local
0853: // shortcuts to each nodetype. Consider ?????
0854: // if(source instanceof NodeImpl &&
0855: // !(source instanceof DocumentImpl))
0856: // {
0857: // // Can't clone DocumentImpl since it invokes us...
0858: // newnode=(NodeImpl)source.cloneNode(false);
0859: // newnode.ownerDocument=this;
0860: // }
0861: // else
0862:
0863: // get source implementation
0864:
0865: int type = source.getNodeType();
0866:
0867: switch (type) {
0868: case ELEMENT_NODE: {
0869: Element newElement;
0870: boolean domLevel20 = source.getOwnerDocument()
0871: .getImplementation().hasFeature("XML", "2.0");
0872: // Create element according to namespace support/qualification.
0873: if (domLevel20 == false || source.getLocalName() == null)
0874: newElement = createElement(source.getNodeName());
0875: else
0876: newElement = createElementNS(source.getNamespaceURI(),
0877: source.getNodeName());
0878:
0879: // Copy element's attributes, if any.
0880: NamedNodeMap sourceAttrs = source.getAttributes();
0881: if (sourceAttrs != null) {
0882: int length = sourceAttrs.getLength();
0883: for (int index = 0; index < length; index++) {
0884: Attr attr = (Attr) sourceAttrs.item(index);
0885:
0886: // Copy the attribute only if it is not a default.
0887: if (attr.getSpecified()) {
0888: Attr newAttr = (Attr) importNode(attr, true,
0889: reversedIdentifiers);
0890:
0891: // Attach attribute according to namespace
0892: // support/qualification.
0893: if (domLevel20 == false
0894: || attr.getLocalName() == null)
0895: newElement.setAttributeNode(newAttr);
0896: else
0897: newElement.setAttributeNodeNS(newAttr);
0898: }
0899: }
0900: }
0901:
0902: // Register element identifier.
0903: if (reversedIdentifiers != null) {
0904: // Does element have an associated identifier?
0905: Object elementId = reversedIdentifiers.get(source);
0906: if (elementId != null) {
0907: if (identifiers == null)
0908: identifiers = new Hashtable();
0909:
0910: identifiers.put(elementId, newElement);
0911: }
0912: }
0913:
0914: newnode = newElement;
0915: break;
0916: }
0917:
0918: case ATTRIBUTE_NODE: {
0919:
0920: if (source.getOwnerDocument().getImplementation()
0921: .hasFeature("XML", "2.0")) {
0922: if (source.getLocalName() == null) {
0923: newnode = createAttribute(source.getNodeName());
0924: } else {
0925: newnode = createAttributeNS(source
0926: .getNamespaceURI(), source.getNodeName());
0927: }
0928: } else {
0929: newnode = createAttribute(source.getNodeName());
0930: }
0931: // if source is an AttrImpl from this very same implementation
0932: // avoid creating the child nodes if possible
0933: if (source instanceof AttrImpl) {
0934: AttrImpl attr = (AttrImpl) source;
0935: if (attr.hasStringValue()) {
0936: AttrImpl newattr = (AttrImpl) newnode;
0937: newattr.setValue(attr.getValue());
0938: deep = false;
0939: } else {
0940: deep = true;
0941: }
0942: } else {
0943: // According to the DOM spec the kids carry the value.
0944: // However, there are non compliant implementations out
0945: // there that fail to do so. To avoid ending up with no
0946: // value at all, in this case we simply copy the text value
0947: // directly.
0948: if (source.getFirstChild() == null) {
0949: newnode.setNodeValue(source.getNodeValue());
0950: deep = false;
0951: } else {
0952: deep = true;
0953: }
0954: }
0955: break;
0956: }
0957:
0958: case TEXT_NODE: {
0959: newnode = createTextNode(source.getNodeValue());
0960: break;
0961: }
0962:
0963: case CDATA_SECTION_NODE: {
0964: newnode = createCDATASection(source.getNodeValue());
0965: break;
0966: }
0967:
0968: case ENTITY_REFERENCE_NODE: {
0969: newnode = createEntityReference(source.getNodeName());
0970: // allow deep import temporarily
0971: ((EntityReferenceImpl) newnode).isReadOnly(false);
0972: break;
0973: }
0974:
0975: case ENTITY_NODE: {
0976: Entity srcentity = (Entity) source;
0977: EntityImpl newentity = (EntityImpl) createEntity(source
0978: .getNodeName());
0979: newentity.setPublicId(srcentity.getPublicId());
0980: newentity.setSystemId(srcentity.getSystemId());
0981: newentity.setNotationName(srcentity.getNotationName());
0982: // Kids carry additional value
0983: newentity.isReadOnly(false); // allow deep import temporarily
0984: newnode = newentity;
0985: break;
0986: }
0987:
0988: case PROCESSING_INSTRUCTION_NODE: {
0989: newnode = createProcessingInstruction(source.getNodeName(),
0990: source.getNodeValue());
0991: break;
0992: }
0993:
0994: case COMMENT_NODE: {
0995: newnode = createComment(source.getNodeValue());
0996: break;
0997: }
0998:
0999: case DOCUMENT_FRAGMENT_NODE: {
1000: newnode = createDocumentFragment();
1001: // No name, kids carry value
1002: break;
1003: }
1004:
1005: case NOTATION_NODE: {
1006: Notation srcnotation = (Notation) source;
1007: NotationImpl newnotation = (NotationImpl) createNotation(source
1008: .getNodeName());
1009: newnotation.setPublicId(srcnotation.getPublicId());
1010: newnotation.setSystemId(srcnotation.getSystemId());
1011: // Kids carry additional value
1012: newnode = newnotation;
1013: // No name, no value
1014: break;
1015: }
1016: case DOCUMENT_TYPE_NODE:
1017: case DOCUMENT_NODE: // Can't import document nodes
1018: default: { // Unknown node type
1019: throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
1020: "Node type being imported is not supported");
1021: }
1022: }
1023:
1024: // If deep, replicate and attach the kids.
1025: if (deep) {
1026: for (Node srckid = source.getFirstChild(); srckid != null; srckid = srckid
1027: .getNextSibling()) {
1028: newnode.appendChild(importNode(srckid, true,
1029: reversedIdentifiers));
1030: }
1031: }
1032: if (newnode.getNodeType() == Node.ENTITY_REFERENCE_NODE
1033: || newnode.getNodeType() == Node.ENTITY_NODE) {
1034: ((NodeImpl) newnode).setReadOnly(true, true);
1035: }
1036: return newnode;
1037:
1038: } // importNode(Node,boolean,Hashtable):Node
1039:
1040: /**
1041: * DOM Level 3 WD - Experimental
1042: * Change the node's ownerDocument, and its subtree, to this Document
1043: *
1044: * @param source The node to adopt.
1045: * @see DocumentImpl.importNode
1046: **/
1047: public Node adoptNode(Node source) {
1048: NodeImpl node;
1049: try {
1050: node = (NodeImpl) source;
1051: } catch (ClassCastException e) {
1052: // source node comes from a different DOMImplementation
1053: return null;
1054: }
1055: switch (node.getNodeType()) {
1056: case ATTRIBUTE_NODE: {
1057: AttrImpl attr = (AttrImpl) node;
1058: // remove node from wherever it is
1059: attr.getOwnerElement().removeAttributeNode(attr);
1060: // mark it as specified
1061: attr.isSpecified(true);
1062: // change ownership
1063: attr.setOwnerDocument(this );
1064: break;
1065: }
1066: case DOCUMENT_NODE:
1067: case DOCUMENT_TYPE_NODE: {
1068: throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
1069: "cannot adopt this type of node.");
1070: }
1071: case ENTITY_REFERENCE_NODE: {
1072: // remove node from wherever it is
1073: Node parent = node.getParentNode();
1074: if (parent != null) {
1075: parent.removeChild(source);
1076: }
1077: // discard its replacement value
1078: Node child;
1079: while ((child = node.getFirstChild()) != null) {
1080: node.removeChild(child);
1081: }
1082: // change ownership
1083: node.setOwnerDocument(this );
1084: // set its new replacement value if any
1085: if (docType == null) {
1086: break;
1087: }
1088: NamedNodeMap entities = docType.getEntities();
1089: Node entityNode = entities.getNamedItem(node.getNodeName());
1090: if (entityNode == null) {
1091: break;
1092: }
1093: EntityImpl entity = (EntityImpl) entityNode;
1094: for (child = entityNode.getFirstChild(); child != null; child = child
1095: .getNextSibling()) {
1096: Node childClone = child.cloneNode(true);
1097: node.appendChild(childClone);
1098: }
1099: break;
1100: }
1101: case ELEMENT_NODE: {
1102: // remove node from wherever it is
1103: Node parent = node.getParentNode();
1104: if (parent != null) {
1105: parent.removeChild(source);
1106: }
1107: // change ownership
1108: node.setOwnerDocument(this );
1109: // reconcile default attributes
1110: ((ElementImpl) node).reconcileDefaultAttributes();
1111: break;
1112: }
1113: default: {
1114: // remove node from wherever it is
1115: Node parent = node.getParentNode();
1116: if (parent != null) {
1117: parent.removeChild(source);
1118: }
1119: // change ownership
1120: node.setOwnerDocument(this );
1121: }
1122: }
1123: return node;
1124: }
1125:
1126: // identifier maintenence
1127: /**
1128: * Introduced in DOM Level 2
1129: * Returns the Element whose ID is given by elementId. If no such element
1130: * exists, returns null. Behavior is not defined if more than one element
1131: * has this ID.
1132: * <p>
1133: * Note: The DOM implementation must have information that says which
1134: * attributes are of type ID. Attributes with the name "ID" are not of type
1135: * ID unless so defined. Implementations that do not know whether
1136: * attributes are of type ID or not are expected to return null.
1137: * @see #getIdentifier
1138: */
1139: public Element getElementById(String elementId) {
1140: return getIdentifier(elementId);
1141: }
1142:
1143: /**
1144: * Registers an identifier name with a specified element node.
1145: * If the identifier is already registered, the new element
1146: * node replaces the previous node. If the specified element
1147: * node is null, removeIdentifier() is called.
1148: *
1149: * @see #getIdentifier
1150: * @see #removeIdentifier
1151: */
1152: public void putIdentifier(String idName, Element element) {
1153:
1154: if (element == null) {
1155: removeIdentifier(idName);
1156: return;
1157: }
1158:
1159: if (needsSyncData()) {
1160: synchronizeData();
1161: }
1162:
1163: if (identifiers == null) {
1164: identifiers = new Hashtable();
1165: }
1166:
1167: identifiers.put(idName, element);
1168:
1169: } // putIdentifier(String,Element)
1170:
1171: /**
1172: * Returns a previously registered element with the specified
1173: * identifier name, or null if no element is registered.
1174: *
1175: * @see #putIdentifier
1176: * @see #removeIdentifier
1177: */
1178: public Element getIdentifier(String idName) {
1179:
1180: if (needsSyncData()) {
1181: synchronizeData();
1182: }
1183:
1184: if (identifiers == null) {
1185: return null;
1186: }
1187:
1188: return (Element) identifiers.get(idName);
1189:
1190: } // getIdentifier(String):Element
1191:
1192: /**
1193: * Removes a previously registered element with the specified
1194: * identifier name.
1195: *
1196: * @see #putIdentifier
1197: * @see #getIdentifier
1198: */
1199: public void removeIdentifier(String idName) {
1200:
1201: if (needsSyncData()) {
1202: synchronizeData();
1203: }
1204:
1205: if (identifiers == null) {
1206: return;
1207: }
1208:
1209: identifiers.remove(idName);
1210:
1211: } // removeIdentifier(String)
1212:
1213: /** Returns an enumeration registered of identifier names. */
1214: public Enumeration getIdentifiers() {
1215:
1216: if (needsSyncData()) {
1217: synchronizeData();
1218: }
1219:
1220: if (identifiers == null) {
1221: identifiers = new Hashtable();
1222: }
1223:
1224: return identifiers.keys();
1225:
1226: } // getIdentifiers():Enumeration
1227:
1228: //
1229: // DOM2: Namespace methods
1230: //
1231:
1232: /**
1233: * Introduced in DOM Level 2. <p>
1234: * Creates an element of the given qualified name and namespace URI.
1235: * If the given namespaceURI is null or an empty string and the
1236: * qualifiedName has a prefix that is "xml", the created element
1237: * is bound to the predefined namespace
1238: * "http://www.w3.org/XML/1998/namespace" [Namespaces].
1239: * @param namespaceURI The namespace URI of the element to
1240: * create.
1241: * @param qualifiedName The qualified name of the element type to
1242: * instantiate.
1243: * @return Element A new Element object with the following attributes:
1244: * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified
1245: name contains an invalid character.
1246: * @throws DOMException NAMESPACE_ERR: Raised if the qualifiedName has a
1247: * prefix that is "xml" and the namespaceURI is
1248: * neither null nor an empty string nor
1249: * "http://www.w3.org/XML/1998/namespace", or
1250: * if the qualifiedName has a prefix different
1251: * from "xml" and the namespaceURI is null or an
1252: * empty string.
1253: * @since WD-DOM-Level-2-19990923
1254: */
1255: public Element createElementNS(String namespaceURI,
1256: String qualifiedName) throws DOMException {
1257: if (errorChecking && !isXMLName(qualifiedName)) {
1258: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
1259: "DOM002 Illegal character");
1260: }
1261: return new ElementNSImpl(this , namespaceURI, qualifiedName);
1262: }
1263:
1264: /**
1265: * Introduced in DOM Level 2. <p>
1266: * Creates an attribute of the given qualified name and namespace URI.
1267: * If the given namespaceURI is null or an empty string and the
1268: * qualifiedName has a prefix that is "xml", the created element
1269: * is bound to the predefined namespace
1270: * "http://www.w3.org/XML/1998/namespace" [Namespaces].
1271: *
1272: * @param namespaceURI The namespace URI of the attribute to
1273: * create. When it is null or an empty string,
1274: * this method behaves like createAttribute.
1275: * @param qualifiedName The qualified name of the attribute to
1276: * instantiate.
1277: * @return Attr A new Attr object.
1278: * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified
1279: name contains an invalid character.
1280: * @since WD-DOM-Level-2-19990923
1281: */
1282: public Attr createAttributeNS(String namespaceURI,
1283: String qualifiedName) throws DOMException {
1284: if (errorChecking && !isXMLName(qualifiedName)) {
1285: throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
1286: "DOM002 Illegal character");
1287: }
1288: return new AttrNSImpl(this , namespaceURI, qualifiedName);
1289: }
1290:
1291: /**
1292: * Introduced in DOM Level 2. <p>
1293: * Returns a NodeList of all the Elements with a given local name and
1294: * namespace URI in the order in which they would be encountered in a
1295: * preorder traversal of the Document tree.
1296: * @param namespaceURI The namespace URI of the elements to match
1297: * on. The special value "*" matches all
1298: * namespaces. When it is null or an empty
1299: * string, this method behaves like
1300: * getElementsByTagName.
1301: * @param localName The local name of the elements to match on.
1302: * The special value "*" matches all local names.
1303: * @return NodeList A new NodeList object containing all the matched
1304: * Elements.
1305: * @since WD-DOM-Level-2-19990923
1306: */
1307: public NodeList getElementsByTagNameNS(String namespaceURI,
1308: String localName) {
1309: return new DeepNodeListImpl(this , namespaceURI, localName);
1310: }
1311:
1312: //
1313: // Object methods
1314: //
1315:
1316: /** Clone. */
1317: public Object clone() throws CloneNotSupportedException {
1318: CoreDocumentImpl newdoc = (CoreDocumentImpl) super .clone();
1319: newdoc.docType = null;
1320: newdoc.docElement = null;
1321: return newdoc;
1322: }
1323:
1324: //
1325: // Public static methods
1326: //
1327:
1328: /**
1329: * Check the string against XML's definition of acceptable names for
1330: * elements and attributes and so on using the XMLCharacterProperties
1331: * utility class
1332: */
1333: public static boolean isXMLName(String s) {
1334:
1335: if (s == null) {
1336: return false;
1337: }
1338: return XMLCharacterProperties.validName(s);
1339:
1340: } // isXMLName(String):boolean
1341:
1342: //
1343: // Protected methods
1344: //
1345:
1346: /**
1347: * Uses the kidOK lookup table to check whether the proposed
1348: * tree structure is legal.
1349: */
1350: protected boolean isKidOK(Node parent, Node child) {
1351: if (allowGrammarAccess
1352: && parent.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
1353: return child.getNodeType() == Node.ELEMENT_NODE;
1354: }
1355: return 0 != (kidOK[parent.getNodeType()] & 1 << child
1356: .getNodeType());
1357: }
1358:
1359: /**
1360: * Denotes that this node has changed.
1361: */
1362: protected void changed() {
1363: changes++;
1364: }
1365:
1366: /**
1367: * Returns the number of changes to this node.
1368: */
1369: protected int changes() {
1370: return changes;
1371: }
1372:
1373: /**
1374: * Store user data related to a given node
1375: * This is a place where we could use weak references! Indeed, the node
1376: * here won't be GC'ed as long as some user data is attached to it, since
1377: * the userData table will have a reference to the node.
1378: */
1379: protected void setUserData(NodeImpl n, Object data) {
1380: // does nothing by default - overidden in subclass
1381: }
1382:
1383: /**
1384: * Retreive user data related to a given node
1385: */
1386: protected Object getUserData(NodeImpl n) {
1387: // does nothing by default - overidden in subclass
1388: return null;
1389: }
1390:
1391: protected void addEventListener(NodeImpl node, String type,
1392: EventListener listener, boolean useCapture) {
1393: // does nothing by default - overidden in subclass
1394: }
1395:
1396: protected void removeEventListener(NodeImpl node, String type,
1397: EventListener listener, boolean useCapture) {
1398: // does nothing by default - overidden in subclass
1399: }
1400:
1401: protected boolean dispatchEvent(NodeImpl node, Event event) {
1402: // does nothing by default - overidden in subclass
1403: return false;
1404: }
1405:
1406: // Notification methods overidden in subclasses
1407:
1408: /**
1409: * A method to be called when some text was changed in a text node,
1410: * so that live objects can be notified.
1411: */
1412: void replacedText(NodeImpl node) {
1413: }
1414:
1415: /**
1416: * A method to be called when some text was deleted from a text node,
1417: * so that live objects can be notified.
1418: */
1419: void deletedText(NodeImpl node, int offset, int count) {
1420: }
1421:
1422: /**
1423: * A method to be called when some text was inserted into a text node,
1424: * so that live objects can be notified.
1425: */
1426: void insertedText(NodeImpl node, int offset, int count) {
1427: }
1428:
1429: /**
1430: * A method to be called when a character data node has been modified
1431: */
1432: void modifyingCharacterData(NodeImpl node) {
1433: }
1434:
1435: /**
1436: * A method to be called when a character data node has been modified
1437: */
1438: void modifiedCharacterData(NodeImpl node, String oldvalue,
1439: String value) {
1440: }
1441:
1442: /**
1443: * A method to be called when a node is about to be inserted in the tree.
1444: */
1445: void insertingNode(NodeImpl node, boolean replace) {
1446: }
1447:
1448: /**
1449: * A method to be called when a node has been inserted in the tree.
1450: */
1451: void insertedNode(NodeImpl node, NodeImpl newInternal,
1452: boolean replace) {
1453: }
1454:
1455: /**
1456: * A method to be called when a node is about to be removed from the tree.
1457: */
1458: void removingNode(NodeImpl node, NodeImpl oldChild, boolean replace) {
1459: }
1460:
1461: /**
1462: * A method to be called when a node has been removed from the tree.
1463: */
1464: void removedNode(NodeImpl node, boolean replace) {
1465: }
1466:
1467: /**
1468: * A method to be called when a node is about to be replaced in the tree.
1469: */
1470: void replacingNode(NodeImpl node) {
1471: }
1472:
1473: /**
1474: * A method to be called when a node has been replaced in the tree.
1475: */
1476: void replacedNode(NodeImpl node) {
1477: }
1478:
1479: /**
1480: * A method to be called when an attribute value has been modified
1481: */
1482: void modifiedAttrValue(AttrImpl attr, String oldvalue) {
1483: }
1484:
1485: /**
1486: * A method to be called when an attribute node has been set
1487: */
1488: void setAttrNode(AttrImpl attr, AttrImpl previous) {
1489: }
1490:
1491: /**
1492: * A method to be called when an attribute node has been removed
1493: */
1494: void removedAttrNode(AttrImpl attr, NodeImpl oldOwner, String name) {
1495: }
1496:
1497: } // class CoreDocumentImpl
|