Package org.apache.xindice.xml.dom

Source Code of org.apache.xindice.xml.dom.DocumentImpl

package org.apache.xindice.xml.dom;

/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 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 "Xindice" 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-2001, The dbXML
* Group, L.L.C., http://www.dbxmlgroup.com.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* $Id: DocumentImpl.java,v 1.5 2002/10/31 07:16:52 vladimir Exp $
*/

import org.apache.xindice.util.XindiceException;
import org.apache.xindice.xml.NodeSource;
import org.apache.xindice.xml.SymbolTable;
import org.apache.xindice.xml.dom.traversal.TreeWalkerImpl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.w3c.dom.*;
import org.w3c.dom.traversal.*;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
* DocumentImpl
*/

public final class DocumentImpl extends ContainerNodeImpl implements CompressedDocument, DBDocument, DocumentTraversal {

   private static Log log = LogFactory.getLog("org.apache.xindice.xml");

   private DocumentType docType = null;
   private String version = null;
   private String actualEncoding = null;
   private String encoding = null;
   private boolean standalone = false;
   private boolean strictErrorChecking = false;
   private SymbolTable symbols = null;
   private boolean readOnly = false;

   public DocumentImpl() {
      super(null, true);
   }

   public DocumentImpl(byte[] data, int pos, int len) {
      super(null, data, pos, len);
   }

   public DocumentImpl(byte[] data) {
      this(data, 0, data.length);
   }

   public DocumentImpl(byte[] data, SymbolTable symbols, NodeSource source) {
      this(data);
      this.symbols = symbols;
      this.source = source;
   }

   public DocumentImpl(Document doc) throws XindiceException {
      super(null, true);

      boolean compress = true;

      if ( doc instanceof CompressedDocument ) {
         CompressedDocument c = (CompressedDocument)doc;
         symbols = c.getSymbols();
         if ( !c.isDirty() ) {
            data = c.getDataBytes();
            pos = c.getDataPos();
            len = c.getDataLen();
            compress = false;
         }
      }

      if ( compress ) {
         if ( symbols == null )
            symbols = new SymbolTable();
         data = DOMCompressor.Compress(doc, symbols);
         pos = 0;
         len = data.length;
      }

      if ( doc instanceof DBDocument ) {
         DBDocument d = (DBDocument)doc;
         source = d.getSource();
      }
   }

   public boolean isReadOnly() {
      return readOnly;
   }

   protected void checkLoaded() {
      if ( loaded )
         return;
      else
         loaded = true;

      try {
         if ( data != null )
            loadChildren(symbols);
      }
      catch ( Exception e ) {
         if (log.isDebugEnabled()) {
            log.debug("No message", e);
         }
      }
   }

   public boolean isCaching() {
      String cache = DBDocument.CACHE;

      int size = childNodes.getLength();
      for ( int i = 0; i < size; i++ ) {
         Node n = childNodes.item(i);
         if ( n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE
           && n.getNodeName().equals(CACHE_CONTROL) ) {
            cache = n.getNodeValue().trim();
            break;
         }
      }

      return (cache != null && cache.equals(CACHE));
   }

   public void setCaching(boolean caching) {
      // TODO delete String cache = DBDocument.CACHE;

      int size = childNodes.getLength();
      for ( int i = 0; i < size; i++ ) {
         Node n = childNodes.item(i);
         if ( n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE
           && n.getNodeName().equals(CACHE_CONTROL) ) {
              n.setNodeValue(caching ? CACHE : NOCACHE);
            return;
         }
      }

      ProcessingInstruction pi = createProcessingInstruction(CACHE_CONTROL, caching ? CACHE : NOCACHE);
      insertBefore(pi, getDocumentElement());
   }

   public SymbolTable getSymbols() {
      return symbols;
   }

   public void setSymbols(SymbolTable symbols) {
      this.symbols = symbols;
   }

   public void expandSource() {
      ElementImpl e = (ElementImpl)getDocumentElement();
      if ( e != null )
         e.expandSource();
   }

   public Node getNodeAtPos(int pos) {
      return null; // TODO: This
   }

   public short getNodeType() {
      return Node.DOCUMENT_NODE;
   }

   public String getNodeName() {
      return "#document";
   }

   /**
    * The Document Type Declaration (see <code>DocumentType</code>) associated
    * with  this document. For HTML documents as well as XML documents without
    * a document type declaration this returns <code>null</code>. The DOM Level
    *  1 does not support editing the Document Type Declaration, therefore
    * <code>docType</code> cannot be altered in any way.
    */
   public DocumentType getDoctype() {
      return docType;
   }

   public void setDoctype(DocumentType docType) {
      this.docType = docType;
   }

   /**
    * The <code>DOMImplementation</code> object that handles this document. A
    * DOM application may use objects from multiple  implementations.
    */
   public DOMImplementation getImplementation() {
      return DOMImplementationImpl.getInstance();
   }

   /**
    * Creates a <code>Text</code> node given the specified string.
    * @param data The data for the node.
    * @return The new <code>Text</code> object.
    */
   public Text createTextNode(String data) {
      return new TextImpl(this, data);
   }

   /**
    * This is a convenience attribute that allows direct access to the child
    * node that is the root element of  the document. For HTML documents, this
    * is the element with the tagName "HTML".
    */
   public Element getDocumentElement() {
      checkLoaded();
      Iterator enum = childNodes.iterator();
      while ( enum.hasNext() ) {
         Node node = (Node)enum.next();
         if ( node.getNodeType() == Node.ELEMENT_NODE )
            return (Element)node;
      }
      return null;
   }

   /**
    * Creates a <code>CDATASection</code> node whose value  is the specified
    * string.
    * @param data The data for the <code>CDATASection</code> contents.
    * @return The new <code>CDATASection</code> object.
    * @exception DOMException
    *   NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
    */
   public CDATASection createCDATASection(String data) throws DOMException {
      return new CDATASectionImpl(this, data);
   }

   /**
    * Creates an element of the type specified. Note that the instance returned
    * implements the Element interface, so attributes can be specified
    * directly  on the returned object.
    * @param tagName The name of the element type to instantiate. For XML, this
    *   is case-sensitive. For HTML, the  <code>tagName</code> parameter may
    *   be provided in any case,  but it must be mapped to the canonical
    *   uppercase form by  the DOM implementation.
    * @return A new <code>Element</code> object.
    * @exception DOMException
    *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
    *   invalid character.
    */
   public Element createElement(String tagName) throws DOMException {
      return new ElementImpl(this, tagName);
   }

   /**
    * Creates an empty <code>DocumentFragment</code> object.
    * @return A new <code>DocumentFragment</code>.
    */
   public DocumentFragment createDocumentFragment() {
      return new DocumentFragmentImpl(this);
   }

   /**
    * Creates an <code>Attr</code> of the given name. Note that the
    * <code>Attr</code> instance can then be set on an <code>Element</code>
    * using the <code>setAttribute</code> method.
    * @param name The name of the attribute.
    * @return A new <code>Attr</code> object.
    * @exception DOMException
    *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
    *   invalid character.
    */
   public Attr createAttribute(String name) throws DOMException {
      return new AttrImpl(this, name);
   }

   /**
    * Creates a <code>Comment</code> node given the specified string.
    * @param data The data for the node.
    * @return The new <code>Comment</code> object.
    */
   public Comment createComment(String data) {
      return new CommentImpl(this, data);
   }

   /**
    * Creates a <code>ProcessingInstruction</code> node given the specified
    * name and data strings.
    * @param target The target part of the processing instruction.
    * @param data The data for the node.
    * @return The new <code>ProcessingInstruction</code> object.
    * @exception DOMException
    *   INVALID_CHARACTER_ERR: Raised if an invalid character is specified.
    *   <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
    */
   public ProcessingInstruction createProcessingInstruction(String target, String data) throws DOMException {
      return new ProcessingInstructionImpl(this, target, data);
   }

   /**
    * Creates an EntityReference object.
    * @param name The name of the entity to reference.
    * @return The new <code>EntityReference</code> object.
    * @exception DOMException
    *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
    *   invalid character.
    *   <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
    */
   public EntityReference createEntityReference(String name) throws DOMException {
      return new EntityReferenceImpl(this, name);
   }

   private void importNamespaces(Node source, Node target) {
      if ( target.getNodeType() == Node.ELEMENT_NODE ) {
         // Retrieve Namespace definitions in scope
         Set set = new HashSet();
         Node n = source;
         Element elem = (Element)target;
         while ( n != null ) {
            NamedNodeMap nm = n.getAttributes();
            for ( int i = 0; i < nm.getLength(); i++ ) {
               Attr a = (Attr)nm.item(i);
               String name = a.getNodeName();
               if ( ( name.startsWith("xmlns:")
                 || name.equals("xmlns") )
                 && !set.contains(name) ) {
                  set.add(name);
                  elem.setAttribute(name, a.getValue());
               }
            }
            n = n.getParentNode();
            if ( n.getNodeType() == DOCUMENT_NODE
              || n.getNodeType() == DOCUMENT_FRAGMENT_NODE )
               n = null;
         }
      }
   }

   public Node importNode(Node importedNode, boolean deep) {
      try {
         // If we're a Xindice DOM Node and share the same symbol table,
         // then we're golden
         if ( importedNode instanceof NodeImpl ) {
            NodeImpl impl = (NodeImpl)importedNode;
            DocumentImpl docImpl = (DocumentImpl)impl.getOwnerDocument();
            if ( docImpl.getSymbols() != null && ( docImpl.getSymbols() == symbols ) ) {
               NodeImpl clone = (NodeImpl)impl.cloneNode(deep);
               clone.setParentNode(this);
               importNamespaces(importedNode, clone);
               return clone;
            }
         }

         // Crap, we have to do a full graph copy
         Node result = null;
         switch ( importedNode.getNodeType() ) {
            case Node.ATTRIBUTE_NODE:
               Attr sattr = (Attr)importedNode;
               Attr attr = createAttribute(sattr.getName());
               attr.setValue(sattr.getValue());
               result = attr;
               break;

            case Node.CDATA_SECTION_NODE:
               result = createCDATASection(importedNode.getNodeValue());
               break;

            case Node.COMMENT_NODE:
               result = createComment(importedNode.getNodeValue());
               break;

            case Node.ELEMENT_NODE:
               Element selem = (Element)importedNode;
               Element elem = createElement(selem.getTagName());
               NamedNodeMap attrs = selem.getAttributes();
               int size = attrs.getLength();
               for ( int i = 0; i < size; i++ ) {
                  Attr a = (Attr)attrs.item(i);
                  Attr ai = createAttribute(a.getName());
                  ai.setValue(a.getValue());
                  elem.setAttributeNode(ai);
               }
               result = elem;
               importNamespaces(importedNode, result);
               break;

            case Node.ENTITY_REFERENCE_NODE:
               result = createEntityReference(importedNode.getNodeValue());
               break;

            case Node.PROCESSING_INSTRUCTION_NODE:
               result = createProcessingInstruction(importedNode.getNodeName(), importedNode.getNodeValue());
               break;

            case Node.TEXT_NODE:
               result = createTextNode(importedNode.getNodeValue());
               break;

            default:
         }

         if ( deep && result != null ) {
            NodeList list = importedNode.getChildNodes();
            int size = list.getLength();
            for ( int i = 0; i < size; i++ ) {
               Node n = list.item(i);
               result.appendChild(importNode(n, deep));
            }
         }

         return result;
      }
      catch ( Exception e ) {
         if (log.isDebugEnabled()) {
            log.debug("No message", e);
         }
         return null;
      }
   }

   public Element createElementNS(String namespaceURI, String qualifiedName) {
      return new ElementImpl(this, qualifiedName);
   }

   public Attr createAttributeNS(String namespaceURI, String qualifiedName) {
      return new AttrImpl(this, qualifiedName);
   }

   public NodeIterator createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
      return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
   }

   public TreeWalker createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
      return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
   }

   // DOM Level 3 Stuff

   public Node adoptNode(Node src) {
      // If we're a Xindice DOM Node and share the same symbol table
      // or the adopted node has no symbol table, then we're golden
      if ( src instanceof NodeImpl ) {
         NodeImpl impl = (NodeImpl)src;
         DocumentImpl docImpl = (DocumentImpl)impl.getOwnerDocument();
         if ( docImpl.getSymbols() == null || docImpl.getSymbols() == symbols ) {
            impl.getParentNode().removeChild(impl);
            impl.setParentNode(this);
            return impl;
         }
      }
      return importNode(src, true);
   }

   public String getActualEncoding() {
      checkLoaded();
      return actualEncoding;
   }

   public void setActualEncoding(String actualEncoding) {
      checkReadOnly();
      checkLoaded();
      this.actualEncoding = actualEncoding;
   }

   public String getEncoding() {
      checkLoaded();
      return encoding;
   }

   public void setEncoding(String encoding) {
      checkReadOnly();
      checkLoaded();
      this.encoding = encoding;
   }

   public String getVersion() {
      checkLoaded();
      return version;
   }

   public void setVersion(String version) {
      checkReadOnly();
      checkLoaded();
      this.version = version;
   }

   public boolean getStandalone() {
      checkLoaded();
      return standalone;
   }

   public void setStandalone(boolean standalone) {
      checkReadOnly();
      checkLoaded();
      this.standalone = standalone;
   }

   public boolean getStrictErrorChecking() {
      checkLoaded();
      return strictErrorChecking;
   }

   public void setStrictErrorChecking(boolean strictErrorChecking) {
      checkReadOnly();
      checkLoaded();
      this.strictErrorChecking = strictErrorChecking;
   }
}
TOP

Related Classes of org.apache.xindice.xml.dom.DocumentImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.