blob: 0797fc4c6993c2c9c4e360ecc98816db82559ae6 [file] [log] [blame]
/*
* $Id$
*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Crimson" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, Sun Microsystems, Inc.,
* http://www.sun.com. For more information on the Apache Software
* Foundation, please see <http://www.apache.org/>.
*/
package org.apache.xerces.tree;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
import java.io.Writer;
import java.io.IOException;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
//Don't need this looks like.
//import org.apache.crimson.parser.Parser;
/**
* Class representing a DTD in DOM Level 1; this class exists purely
* for editor support, and is of dubious interest otherwise.
*
* @author David Brownell
* @version $Revision$
*/
final class Doctype extends NodeBase implements DocumentType
{
// Stuff generated during parsing ...
private String name;
private Nodemap entities;
private Nodemap notations;
// ... stuff assigned by apps separately
private String publicId;
private String systemId;
private String internalSubset;
// package private
Doctype (String n)
{
name = n;
entities = new Nodemap ();
notations = new Nodemap ();
}
// package private
Doctype (String pub, String sys, String subset)
{
publicId = pub;
systemId = sys;
internalSubset = subset;
}
// package private
Doctype(String name, String publicId, String systemId,
String internalSubset)
{
this.name = name;
this.publicId = publicId;
this.systemId = systemId;
this.internalSubset = internalSubset;
}
// package private
void setPrintInfo (String pub, String sys, String subset)
{
publicId = pub;
systemId = sys;
internalSubset = subset;
}
/**
* Writes out a textual DTD, trusting that any internal subset text
* is in fact well formed XML.
*/
public void writeXml (XmlWriteContext context) throws IOException
{
Writer out = context.getWriter ();
Element root = getOwnerDocument ().getDocumentElement ();
out.write ("<!DOCTYPE ");
out.write (root == null ? "UNKNOWN-ROOT" : root.getNodeName ());
if (systemId != null) {
if (publicId != null) {
out.write (" PUBLIC '");
out.write (publicId);
out.write ("' '");
} else
out.write (" SYSTEM '");
out.write (systemId);
out.write ("'");
}
if (internalSubset != null) {
out.write (XmlDocument.eol);
out.write ("[");
out.write (internalSubset);
out.write ("]");
}
out.write (">");
out.write (XmlDocument.eol);
}
/** DOM: Returns DOCUMENT_TYPE_NODE */
public short getNodeType ()
{ return DOCUMENT_TYPE_NODE; }
/** DOM: Returns the name declared for the document root node. */
public String getName ()
{ return name; }
/** DOM: Returns the name declared for the document root node. */
public String getNodeName ()
{ return name; }
/** DOM: NYI
* @deprecated Not yet implemented.
*/
public Node cloneNode (boolean deep)
{
// XXX
throw new RuntimeException (getMessage ("DT-000"));
}
/**
* DOM: Returns the internal, external, and unparsed entities
* declared in this DTD.
*/
public NamedNodeMap getEntities ()
{ return entities; }
/** DOM: Returns the notations declared in this DTD. */
public NamedNodeMap getNotations ()
{ return notations; }
/**
* The public identifier of the external subset.
* @since DOM Level 2
*/
public String getPublicId() {
return publicId;
}
/**
* The system identifier of the external subset.
* @since DOM Level 2
*/
public String getSystemId() {
return systemId;
}
/**
* The internal subset as a string.
* @since DOM Level 2
*/
public String getInternalSubset() {
return internalSubset;
}
// package private
void setOwnerDocument (XmlDocument doc)
{
super.setOwnerDocument (doc);
if (entities != null)
for (int i = 0; entities.item (i) != null; i++)
((NodeBase)entities.item (i)).setOwnerDocument (doc);
if (notations != null)
for (int i = 0; notations.item (i) != null; i++)
((NodeBase)notations.item (i)).setOwnerDocument (doc);
}
/** Adds a notation node. */
// package private
void addNotation (String name, String pub, String sys)
{
NotationNode node = new NotationNode (name, pub, sys);
node.setOwnerDocument ((XmlDocument)getOwnerDocument ());
notations.setNamedItem (node);
}
/**
* Adds an entity node for an external entity, which
* could be parsed or unparsed.
*/
// package private
void addEntityNode (String name, String pub, String sys, String not)
{
EntityNode node = new EntityNode (name, pub, sys, not);
node.setOwnerDocument ((XmlDocument)getOwnerDocument ());
entities.setNamedItem (node);
}
/** Adds an entity node for an internal parsed entity. */
// package private
void addEntityNode (String name, String value)
{
if ("lt".equals (name) || "gt".equals (name)
|| "apos".equals (name) || "quot".equals (name)
|| "amp".equals (name))
return; // predeclared, immutable
EntityNode node = new EntityNode (name, value);
node.setOwnerDocument ((XmlDocument)getOwnerDocument ());
entities.setNamedItem (node);
}
/** Marks the sets of entities and notations as readonly. */
// package private
void setReadonly ()
{
entities.readonly = true;
notations.readonly = true;
}
static class NotationNode extends NodeBase implements Notation
{
private String notation;
private String publicId;
private String systemId;
NotationNode (String name, String pub, String sys)
{
notation = name;
publicId = pub;
systemId = sys;
}
public String getPublicId ()
{ return publicId; }
public String getSystemId ()
{ return systemId; }
public short getNodeType ()
{ return NOTATION_NODE; }
public String getNodeName ()
{ return notation; }
public Node cloneNode (boolean ignored)
{
NotationNode retval;
retval = new NotationNode (notation, publicId, systemId);
retval.setOwnerDocument ((XmlDocument)getOwnerDocument ());
return retval;
}
public void writeXml (XmlWriteContext context) throws IOException
{
Writer out = context.getWriter ();
out.write ("<!NOTATION ");
out.write (notation);
if (publicId != null) {
out.write (" PUBLIC '");
out.write (publicId);
if (systemId != null) {
out.write ("' '");
out.write (systemId);
}
} else {
out.write (" SYSTEM '");
out.write (systemId);
}
out.write ("'>");
}
}
// DOM permits the children to be null ... we do that consistently
static class EntityNode extends NodeBase implements Entity
{
private String entityName;
private String publicId;
private String systemId;
private String notation;
private String value;
EntityNode (String name, String pub, String sys, String not)
{
entityName = name;
publicId = pub;
systemId = sys;
notation = not;
}
EntityNode (String name, String value)
{
entityName = name;
this.value = value;
}
public String getNodeName ()
{ return entityName; }
public short getNodeType ()
{ return ENTITY_NODE; }
public String getPublicId ()
{ return publicId; }
public String getSystemId ()
{ return systemId; }
public String getNotationName ()
{ return notation; }
public Node cloneNode (boolean ignored)
{
EntityNode retval;
retval = new EntityNode (entityName, publicId, systemId,
notation);
retval.setOwnerDocument ((XmlDocument)getOwnerDocument ());
return retval;
}
public void writeXml (XmlWriteContext context) throws IOException
{
Writer out = context.getWriter ();
out.write ("<!ENTITY ");
out.write (entityName);
if (value == null) {
if (publicId != null) {
out.write (" PUBLIC '");
out.write (publicId);
out.write ("' '");
} else
out.write (" SYSTEM '");
out.write (systemId);
out.write ("'");
if (notation != null) {
out.write (" NDATA ");
out.write (notation);
}
} else {
out.write (" \"");
int length = value.length ();
for (int i = 0; i < length; i++) {
char c = value.charAt (i);
if (c == '"')
out.write ("&quot;");
else
out.write (c);
}
out.write ('"');
}
out.write (">");
}
}
static class Nodemap implements NamedNodeMap
{
// package private
boolean readonly;
// package private
java.util.Vector list = new java.util.Vector ();
// XXX copied from AttributeSet; share implementation!
public Node getNamedItem (String name)
{
int length = list.size ();
Node value;
for (int i = 0; i < length; i++) {
value = item (i);
if (value.getNodeName ().equals (name))
return value;
}
return null;
}
/**
* <b>DOM2:</b>
*/
public Node getNamedItemNS(String namespaceURI, String localName) {
return null;
}
// XXX copied from AttributeSet; share implementation!
public int getLength ()
{
return list.size ();
}
// XXX copied from AttributeSet; share implementation!
public Node item (int index)
{
if (index < 0 || index >= list.size ())
return null;
return (Node) list.elementAt (index);
}
public Node removeNamedItem (String name)
throws DOMException
{
throw new DomEx (DOMException.NO_MODIFICATION_ALLOWED_ERR);
}
/**
* <b>DOM2:</b>
*/
public Node removeNamedItemNS(String namespaceURI, String localName)
throws DOMException
{
throw new DomEx(DOMException.NO_MODIFICATION_ALLOWED_ERR);
}
// caller guarantees (e.g. from parser) uniqueness
public Node setNamedItem (Node item) throws DOMException
{
if (readonly)
throw new DomEx (DOMException.NO_MODIFICATION_ALLOWED_ERR);
list.addElement (item);
return null;
}
/**
* <b>DOM2:</b>
*/
public Node setNamedItemNS(Node arg) throws DOMException {
if (readonly) {
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
}
list.addElement(arg);
return null;
}
}
}