/* 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.DOMException;
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 &lt;!DOCTYPE ...&gt; 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 DomDOMException(DOMException.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 DomDOMException(DOMException.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;
  }


}
