diff options
Diffstat (limited to 'libjava/gnu/xml/dom/DomDoctype.java')
-rw-r--r-- | libjava/gnu/xml/dom/DomDoctype.java | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/libjava/gnu/xml/dom/DomDoctype.java b/libjava/gnu/xml/dom/DomDoctype.java new file mode 100644 index 0000000..35fb613 --- /dev/null +++ b/libjava/gnu/xml/dom/DomDoctype.java @@ -0,0 +1,454 @@ +/* DomDoctype.java -- + Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.xml.dom; + +import java.util.HashMap; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Entity; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.Notation; + +/** + * <p> "DocumentType" implementation (with no extensions for supporting + * any document typing information). This is a non-core DOM class, + * supporting the "XML" feature. </p> + * + * <p> <em>Few XML applications will actually care about this partial + * DTD support</em>, since it doesn't expose any (!) of the data typing + * facilities which can motivate applications to use DTDs. It does not + * expose element content models, or information about attribute typing + * rules. Plus the information it exposes isn't very useful; as one example, + * DOM exposes information about unparsed ENTITY objects, which is only used + * with certain element attributes, but does not expose the information about + * those attributes which is needed to apply that data! </p> + * + * <p> Also, note that there are no nonportable ways to associate even the + * notation and entity information exposed by DOM with a DocumentType. While + * there is a DOM L2 method to construct a DocumentType, it only gives access + * to the textual content of the <!DOCTYPE ...> declaration. </p> + * + * <p> In short, <em>you are strongly advised not to rely on this incomplete + * DTD functionality</em> in your application code.</p> + * + * @see DomEntity + * @see DomEntityReference + * @see DomNotation + * + * @author David Brownell + * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> + */ +public class DomDoctype + extends DomExtern + implements DocumentType +{ + + private DomNamedNodeMap notations; + private DomNamedNodeMap entities; + private final DOMImplementation implementation; + private String subset; + + private HashMap elements = new HashMap(); + private boolean ids; + + /** + * Constructs a DocumentType node associated with the specified + * implementation, with the specified name. + * + * <p>This constructor should only be invoked by a DOMImplementation as + * part of its createDocumentType functionality, or through a subclass + * which is similarly used in a "Sub-DOM" style layer. + * + * <p> Note that at this time there is no standard SAX API granting + * access to the internal subset text, so that relying on that value + * is not currently portable. + * + * @param impl The implementation with which this object is associated + * @param name Name of this root element + * @param publicId If non-null, provides the external subset's + * PUBLIC identifier + * @param systemId If non-null, provides the external subset's + * SYSTEM identifier + * @param internalSubset Provides the literal value (unparsed, no + * entities expanded) of the DTD's internal subset. + */ + protected DomDoctype(DOMImplementation impl, + String name, + String publicId, + String systemId, + String internalSubset) + { + super(DOCUMENT_TYPE_NODE, null, name, publicId, systemId); + implementation = impl; + subset = internalSubset; + } + + /** + * JAXP builder constructor. + * @param doc the document + * @param name the name of the document element + * @param publicId the public ID of the document type declaration + * @param systemId the system ID of the document type declaration + */ + public DomDoctype(DomDocument doc, + String name, + String publicId, + String systemId) + { + super(DOCUMENT_TYPE_NODE, doc, name, publicId, systemId); + implementation = doc.getImplementation(); + } + + /** + * <b>DOM L1</b> + * Returns the root element's name (just like getNodeName). + */ + final public String getName() + { + return getNodeName(); + } + + /** + * <b>DOM L1</b> + * Returns information about any general entities declared + * in the DTD. + * + * <p><em>Note: DOM L1 doesn't throw a DOMException here, but + * then it doesn't have the strange construction rules of L2.</em> + * + * @exception DOMException HIERARCHY_REQUEST_ERR if the DocumentType + * is not associated with a document. + */ + public NamedNodeMap getEntities() + { + if (entities == null) + { + entities = new DomNamedNodeMap(this, Node.ENTITY_NODE); + } + return entities; + } + + /** + * Records the declaration of a general entity in this DocumentType. + * + * @param name Name of the entity + * @param publicId If non-null, provides the entity's PUBLIC identifier + * @param systemId Provides the entity's SYSTEM identifier + * @param notation If non-null, provides the entity's notation + * (indicating an unparsed entity) + * @return The Entity that was declared, or null if the entity wasn't + * recorded (because it's a parameter entity or because an entity with + * this name was already declared). + * + * @exception DOMException NO_MODIFICATION_ALLOWED_ERR if the + * DocumentType is no longer writable. + * @exception DOMException HIERARCHY_REQUEST_ERR if the DocumentType + * is not associated with a document. + */ + public Entity declareEntity(String name, + String publicId, + String systemId, + String notation) + { + DomEntity entity; + + if (name.charAt(0) == '%' || "[dtd]".equals(name)) + { + return null; + } + if (isReadonly()) + { + throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR); + } + getEntities(); + + DomDocument.checkName(name, (owner != null) ? + "1.1".equals(owner.getXmlVersion()) : false); + if (entities.getNamedItem(name) != null) + { + return null; + } + + entity = new DomEntity(owner, name, publicId, systemId, notation); + entities.setNamedItem(entity); + return entity; + } + + /** + * <b>DOM L1</b> + * Returns information about any notations declared in the DTD. + * + * <p><em>Note: DOM L1 doesn't throw a DOMException here, but + * then it doesn't have the strange construction rules of L2.</em> + * + * @exception DOMException HIERARCHY_REQUEST_ERR if the DocumentType + * is not associated with a document. + */ + public NamedNodeMap getNotations() + { + if (notations == null) + { + notations = new DomNamedNodeMap(this, Node.NOTATION_NODE); + } + return notations; + } + + /** + * Records the declaration of a notation in this DocumentType. + * + * @param name Name of the notation + * @param publicId If non-null, provides the notation's PUBLIC identifier + * @param systemId If non-null, provides the notation's SYSTEM identifier + * @return The notation that was declared. + * + * @exception DOMException NO_MODIFICATION_ALLOWED_ERR if the + * DocumentType is no longer writable. + * @exception DOMException HIERARCHY_REQUEST_ERR if the DocumentType + * is not associated with a document. + */ + public Notation declareNotation(String name, + String publicId, + String systemId) + { + DomNotation notation; + + if (isReadonly()) + { + throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR); + } + getNotations(); + + DomDocument.checkName(name, (owner != null) ? + "1.1".equals(owner.getXmlVersion()) : false); + + notation = new DomNotation(owner, name, publicId, systemId); + notations.setNamedItem(notation); + return notation; + } + + /** + * <b>DOM L2</b> + * Returns the internal subset of the document, as a string of unparsed + * XML declarations (and comments, PIs, whitespace); or returns null if + * there is no such subset. There is no vendor-independent expectation + * that this attribute be set, or that declarations found in it be + * reflected in the <em>entities</em> or <em>notations</em> attributes + * of this Document "Type" object. + * + * <p> Some application-specific XML profiles require that documents + * only use specific PUBLIC identifiers, without an internal subset + * to modify the interperetation of the declarations associated with + * that PUBLIC identifier through some standard. + */ + public String getInternalSubset() + { + return subset; + } + + /** + * The base URI of a DocumentType is always <code>null</code>. + * See the Infoset Mapping, appendix C. + */ + public final String getBaseURI() + { + return null; + } + + /** + * Sets the internal "readonly" flag so the node and its associated + * data (only lists of entities and notations, no type information + * at the moment) can't be changed. + */ + public void makeReadonly() + { + super.makeReadonly(); + if (entities != null) + { + entities.makeReadonly(); + } + if (notations != null) + { + notations.makeReadonly(); + } + } + + void setOwner(DomDocument doc) + { + if (entities != null) + { + for (DomNode ctx = entities.first; ctx != null; ctx = ctx.next) + { + ctx.setOwner(doc); + } + } + if (notations != null) + { + for (DomNode ctx = notations.first; ctx != null; ctx = ctx.next) + { + ctx.setOwner(doc); + } + } + super.setOwner(doc); + } + + /** + * <b>DOM L2</b> + * Consults the DOM implementation to determine if the requested + * feature is supported. + */ + final public boolean supports(String feature, String version) + { + return implementation.hasFeature(feature, version); + } + + /** + * Returns the implementation associated with this document type. + */ + final public DOMImplementation getImplementation() + { + return implementation; + } + + public void elementDecl(String name, String model) + { + DTDElementTypeInfo info = getElementTypeInfo(name); + if (info == null) + { + info = new DTDElementTypeInfo(name, model); + elements.put(name, info); + } + else + { + info.model = model; + } + } + + DTDElementTypeInfo getElementTypeInfo(String name) + { + return (DTDElementTypeInfo) elements.get(name); + } + + public void attributeDecl(String eName, String aName, String type, + String mode, String value) + { + DTDAttributeTypeInfo info = new DTDAttributeTypeInfo(eName, aName, type, + mode, value); + DTDElementTypeInfo elementInfo = getElementTypeInfo(eName); + if (elementInfo == null) + { + elementInfo = new DTDElementTypeInfo(eName, null); + elements.put(eName, elementInfo); + } + elementInfo.setAttributeTypeInfo(aName, info); + if ("ID".equals(type)) + { + ids = true; + } + } + + DTDAttributeTypeInfo getAttributeTypeInfo(String elementName, String name) + { + DTDElementTypeInfo elementInfo = + (DTDElementTypeInfo) elements.get(elementName); + return (elementInfo == null) ? null : + elementInfo.getAttributeTypeInfo(name); + } + + boolean hasIds() + { + return ids; + } + + public boolean isSameNode(Node arg) + { + if (equals(arg)) + { + return true; + } + if (!(arg instanceof DocumentType)) + { + return false; + } + DocumentType doctype = (DocumentType) arg; + if (!equal(getPublicId(), doctype.getPublicId())) + { + return false; + } + if (!equal(getSystemId(), doctype.getSystemId())) + { + return false; + } + if (!equal(getInternalSubset(), doctype.getInternalSubset())) + { + return false; + } + // TODO entities + // TODO notations + return true; + } + + /** + * Shallow clone of the doctype, except that associated + * entities and notations are (deep) cloned. + */ + public Object clone() + { + DomDoctype node = (DomDoctype) super.clone(); + + if (entities != null) + { + node.entities = new DomNamedNodeMap(node, Node.ENTITY_NODE); + for (DomNode ctx = entities.first; ctx != null; ctx = ctx.next) + { + node.entities.setNamedItem(ctx.cloneNode(true)); + } + } + if (notations != null) + { + node.notations = new DomNamedNodeMap(node, Node.NOTATION_NODE); + for (DomNode ctx = notations.first; ctx != null; ctx = ctx.next) + { + node.notations.setNamedItem(ctx.cloneNode(true)); + } + } + return node; + } + + +} |