Package org.ozoneDB.xml.util

Source Code of org.ozoneDB.xml.util.XMLContainer

// You can redistribute this software and/or modify it under the terms of
// the Ozone Library License version 1 published by ozone-db.org.
//
// The original code and portions created by SMB are
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
//
// $Id: XMLContainer.java,v 1.1 2001/12/18 11:03:24 per_nyfelt Exp $

package org.ozoneDB.xml.util;

import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectInput;
import java.io.Externalizable;

import org.ozoneDB.*;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.xml.sax.InputSource;
import org.xml.sax.ContentHandler;

import org.infozone.tools.xml.queries.XObject;
import org.infozone.tools.xml.queries.XPathQuery;
import org.infozone.tools.xml.queries.XUpdateQuery;

import org.ozoneDB.xml.dom.DocumentProxy;


/**
* <p>This class is the central part of the ozone/XML API. Basically it provides a
* persistent container for a XML document, which is stored in an ozone database.</p>
*
* <p><dl><dt>IMPORTANT:</dt><dd>Before calling one of the store or extract methods the
* thread <b>must</b> have joined a transaction.</dd></dl>
* </p>
*
* Usage of the SAX methods is recomended, because of the better performance.
*
* @version $Revision: 1.1 $ $Date: 2001/12/18 11:03:24 $
* @author <a href="http://www.smb-tec.com">SMB</a>
*/
public class XMLContainer implements Externalizable, SAXChunkProducerDelegate {
   
    // Class data
   
    public final static boolean debug = false;
   
    // Data
   
    private XMLContainerHelper  helper;
   
    private transient           OzoneInterface db;
   
    private transient Document  doc;

    /** True if this object runs outside an ozone server. */
    private transient boolean   runsExternal;
   
   
    // Class methods
   
   
    /**
     *  Creates a new container with the given name.
     *  @param _db The database where the container will be stored.
     *  @param _docName The name of the container (and the document).
     *  @return the new container.
     */
    public static XMLContainer newContainer( OzoneInterface _db, String _docName ) throws Exception {
        XMLContainerHelper helper = (XMLContainerHelper)_db.createObject(
                "org.ozoneDB.xml.util.XMLContainerHelperImpl",
                OzoneInterface.Public,
                _docName );
       
        return new XMLContainer( _db, helper );
    }
   
   
    /**
     *  Returns the XMLContainer representing the document with the given name.
     *  @param _db The database where the container is stored.
     *  @param _docName The name under which the container has been stored.
     *  @return the container for the given name or null if the container
     *          does not exist.
     */
    public static XMLContainer forName( OzoneInterface _db, String _docName ) throws Exception {
        XMLContainerHelper helper = (XMLContainerHelper)_db.objectForName( _docName );
        return helper != null ? new XMLContainer( _db, helper ) : null;
    }
   
   
    /**
     *  Returns the XMLContainer representing the document the given node
     *  belongs to.
     *  @param _db The database where the container is stored.
     *  @param _pNode A node of the document the container represents.
     *  @return the container for the given node or null if the node has not
     *          been stored using the XMLContainer class.
     */
    public static XMLContainer forNode( OzoneInterface _db, Node _pNode ) throws Exception {
        if (!(_pNode instanceof OzoneProxy)) {
            throw new IllegalArgumentException("Not a persistent DOM node: " + _pNode.getClass().getName());
        }

        DocumentProxy pDoc = _pNode instanceof Document
                ? (DocumentProxy)_pNode
                : (DocumentProxy)_pNode.getOwnerDocument();

        XMLContainerHelper helper = (XMLContainerHelper)pDoc.getContainer();
        return helper != null ? new XMLContainer( _db, helper ) : null;
    }
   
   
    // Constructors
   
   
    protected XMLContainer( OzoneInterface _db, XMLContainerHelper _helper ) {
        db = _db;
        helper = _helper;
        runsExternal = (db instanceof ExternalDatabase);
    }
   
   
    // Methods
   
    /**
     * Changes the name of this container.
     * @param _name The new name of this container or null to remove the
     *     current name.
     */
    public void setName( String _name ) throws Exception {
        if (helper == null) {
            throw new IllegalStateException( "Document has already been deleted." );
        }
        db.nameObject( helper, _name );
    }


    /**
     * Deletes the container (and the associated document) from the database.
     */
    public synchronized void delete() throws Exception {
        if (helper == null) {
            throw new IllegalStateException("Document has already been deleted.");
        }
        db.deleteObject(helper);
        helper = null;
        doc = null;
    }
   
   
    /**
     *  Get the underlying persistent document that this container is working on.
     *  @return The persistent document.
     */
    public Document getPDocument() throws Exception {
        if (helper == null) {
            throw new IllegalStateException( "Document has already been deleted." );
        }
        // not synchronized because it wouldn't make a difference here
        if (doc == null) {
            doc = helper.getDocument();
        }
        return doc;
    }
   
   
    /**
     * Stores a transient DOM tree database. The newly created Nodes are
     * appended to the Document Node of this container.
     *
     * @see #storeDOM(Node, Node)
     */
    public void storeDOM( Document _tNode ) throws Exception {
        if (helper == null)
            throw new IllegalStateException("Document has already been deleted.");

        storeDOM( null, _tNode );
    }


    /**
     *  Stores a transient node into the database.
     *
     *  <p>Before calling this method the current thread <b>must</b> have joined an
     *  {@link org.ozoneDB.ExternalTransaction explicit Transaction}. This is an
     *  exception to the normal case, where an implicit transaction (handled by
     *  Ozone) is more appropriate.</p>
     <p><dl><dt>Note:</dt><dd>If ever possible the corresponding
     *  {@link #storeSAX(Node) SAX method} should be used, because the performance
     *  of SAX storage is much better.</dd></dl></p>
     *
     *  @param _pNode The persistent node where the stored node will be appended to.
     *      Null replaces the current document.
     *  @param _tnode The transient node to be stored.
     *
     *  @throws IllegalStateException if the underlying document has already been deleted.
     *  @throws IllegalArgumentException if _tnode was null.
     *  @throws IllegalStateException if the current thread has not joined a
     *          {@link org.ozoneDB.ExternalTransaction transaction}.
     *  @see org.ozoneDB.ExternalTransaction
     *  @see org.ozoneDB.ExternalDatabase#newTransaction()
     */
    public void storeDOM(Node _pNode, Node _tNode ) throws Exception {
        long time = 0;
        long starttime = 0;
       
        if (helper == null) {
            throw new IllegalStateException( "Document has already been deleted." );
        }
        if (_tNode == null) {
            throw new IllegalArgumentException( "tNode == null." );
        }
        // thread must have joined a transaction
        if (runsExternal && ((ExternalDatabase)db).currentTransaction() == null) {
            throw new IllegalStateException( "Thread must have joined a transaction!" );
        }
       
        SAXChunkConsumer consumer = helper.beginInputSequence(_pNode);
        ModifiableNodeList mnl = new ModifiableNodeList(1);
        mnl.addNode(_tNode);
        SAXChunkProducer producer = new SAXChunkProducer(mnl);
        ChunkOutputStream cos = producer.chunkStream();

        do {
            cos.reset();
            producer.createNextChunk();
            if (XMLContainer.debug) {
                starttime = System.currentTimeMillis();
            }
            consumer = helper.putChunk(cos.toByteArray(), consumer);
            if (XMLContainer.debug) {
                time += (System.currentTimeMillis() - starttime);
            }
        } while (!cos.getEndFlag());

        if (XMLContainer.debug) {
            System.out.println("DOM store: store in db time: " + time + " ms");
        }
    }
   
   
    /**
     * Stores a DOM tree represented by SAX events in the datasabase. The
     * newly created Nodes are appended to the Document Node of this container.
     *
     * @see #storeSAX(Node)
     */
    public ContentHandler storeSAX() throws Exception {
        if (helper == null) {
            throw new IllegalStateException( "Document has already been deleted." );
        }
        return storeSAX( null );
    }
   

    /**
     *  Stores XML represented by SAX events into the database.
     *  <p>The entire storage process <b>must</b> be enclosed by an
     *  {@link org.ozoneDB.ExternalTransaction explicit Transaction}. This is an
     *  exception to the normal case, where an implicit transaction (handled by
     *  Ozone) is more appropriate. The storage process starts with the call to this
     *  method and ends with the last event send to the content handler. The SAX
     *  events must be properly terminated, i.e. there must be an end event for
     *  for every start event, otherwise the correct storage can't be guaranteed.</p>
     *
     *  @param _pNode The persistent node where the stored data will be appended to.
     *
     *  @return the content handler which stores all XML data it recieves into the
     *          database.
     *
     *  @throws IllegalStateException if the underlying document has already been deleted.
     *  @throws IllegalStateException if the current thread has not joined a
     *          {@link org.ozoneDB.ExternalTransaction transaction}.
     *  @see org.ozoneDB.ExternalTransaction
     *  @see org.ozoneDB.ExternalDatabase#newTransaction()
     */
    public ContentHandler storeSAX(Node _pNode) throws Exception {
        if (helper == null) {
            throw new IllegalStateException( "Document has already been deleted." );
        }
        // thread must have joined a transaction
        if (runsExternal && ((ExternalDatabase)db).currentTransaction() == null) {
            throw new IllegalStateException( "Thread must have joined a transaction!" );
        }
       
        // this eventually blocks if there is another thread storing something already
        SAXChunkConsumer consumer = helper.beginInputSequence(_pNode);
       
        SAXChunkProducer producer = new SAXChunkProducer(this);
       
        producer.dbConsumer = consumer;
        return producer;
    }
   
   
    /**
     *  This method is for internal use only. <b>Don't call it directly.</b>
     */
    public void processChunk(SAXChunkProducer _producer) throws Exception {
        if (XMLContainer.debug) {
            System.out.print("XMLContainer.processChunk()... ");
        }
       
        ChunkOutputStream cos = _producer.chunkStream();
        if (XMLContainer.debug) {
            System.out.print("putChunk(" + cos.count + ")... ");
        }
       
        _producer.dbConsumer = helper.putChunk(cos.toByteArray(), _producer.dbConsumer);
       
    }
   
    /**
     * @see #extractDOM(Document, Node, Node , int)
     */
    public Document extractDOM( Document _domFactory ) throws Exception {
        return (Document) extractDOM( _domFactory, (Node)null, null, -1 );
    }


    /**
     * @see #extractDOM(Document, Node, Node , int)
     */
    public Node extractDOM( Document _domFactory, Node _pNode, Node _appendTo) throws Exception {
        return extractDOM( _domFactory, _pNode, _appendTo, -1 );
    }


    /**
     * Extracts a given DOM node and all its descendants.
     *
     * <p>Before calling this method the current thread <b>must</b> have joined an
     * {@link org.ozoneDB.ExternalTransaction explicit Transaction}. This is an
     * exception to the normal case, where an implicit transaction (handled by
     * Ozone) is more appropriate.</p>
     *
     * <p><dl><dt>Note:</dt><dd>If possible, the corresponding
     * {@link #extractSAX(ContentHandler) SAX method} should be used, because the
     * performance of SAX retrieval is much better.</dd></dl></p>
     *
     * @param _domFactory The DOM Document that is used to create the extracted DOM nodes.
     * @param _pNode The persistent DOM node
     * @param _appendTo The transient DOM node where the extracted content will
     *     will be appended to.
     *  @param _depth The number of hierarchy steps that should be extracted or
     *      null if the entire hierarchy should be extracted.
     */
    public Node extractDOM ( Document _domFactory, Node _pNode, Node _appendTo, int _depth) throws Exception {
       
        ModifiableNodeList mnl = null;
        if (_pNode != null) {
            mnl = new ModifiableNodeList(1);
            mnl.addNode(_pNode);
        }
       
        NodeList resultList = extractDOM (_domFactory, mnl, _appendTo, _depth);
       
        return resultList.item(0);
       
/*        if (helper == null) {
            throw new IllegalStateException ("Document has already been deleted.");
        }
        // thread must have joined a transaction
        if (runsExternal && ((ExternalDatabase)db).currentTransaction() == null) {
            throw new IllegalStateException( "Thread must have joined a transaction!" );
        }
       
        SAXChunkProducer producer = helper.beginOutputSequence( _pNode, _depth );
        SAXChunkConsumer consumer = new SAXChunkConsumer(_domFactory, _appendTo);
        ChunkOutputStream cos;
        do {
            producer = helper.createNextChunk( producer );
            cos = producer.chunkStream();
            consumer.processChunk( cos.toByteArray() );
            cos.reset();
        } while (!cos.getEndFlag());
       
        return consumer.getResultNode();*/
    }
   
   
    public NodeList extractDOM (Document _domFactory, NodeList _pNodes, Node _appendTo, int _depth) throws Exception {
        if (helper == null) {
            throw new IllegalStateException ("Document has already been deleted.");
        }
        // thread must have joined a transaction
        if (runsExternal && ((ExternalDatabase)db).currentTransaction() == null) {
            throw new IllegalStateException( "Thread must have joined a transaction!" );
        }
       
        SAXChunkProducer producer = helper.beginOutputSequence( _pNodes, _depth );
        SAXChunkConsumer consumer = new SAXChunkConsumer(_domFactory, _appendTo);
        ChunkOutputStream cos;
        do {
            producer = helper.createNextChunk( producer );
            cos = producer.chunkStream();
            consumer.processChunk( cos.toByteArray() );
            cos.reset();
        } while (!cos.getEndFlag());
       
        return consumer.getResultNodeList();
    }
   
   
    /**
     * @see #extractSAX(ContentHandler, Node, int)
     */
    public void extractSAX( ContentHandler _contentHandler ) throws Exception {
        extractSAX( _contentHandler, null, -1 );
    }
   
   
    /**
     * @see #extractSAX(ContentHandler, Node , int )
     */
    public void extractSAX( ContentHandler _contentHandler, Node _pNode ) throws Exception {
        extractSAX( _contentHandler, _pNode, -1 );
    }
   
   
    /**
     *  Extracts a given DOM node and all its descendants.
     *
     *  <p>Before calling this method the current thread <b>must</b> have joined an
     *  {@link org.ozoneDB.ExternalTransaction explicit Transaction}. This is an
     *  exception to the normal case, where an implicit transaction (handled by
     *  Ozone) is more appropriate.</p>
     *
     *  @param _contentHandler The ContentHandler that will receive the generated
     *      SAX events.
     *  @param _pNode The persistent DOM node that is the starting point, or null
     *      if the entire document should be extracted.
     *  @param _depth The number of hierarchy steps that should be extracted or
     *      null if the entire hierarchy should be extracted.
     */
    public void extractSAX( ContentHandler _contentHandler, Node _pNode, int _depth ) throws Exception {
       
        if (helper == null) {
            throw new IllegalStateException( "Document has already been deleted." );
        }
        // thread must have joined a transaction
        if (runsExternal && ((ExternalDatabase)db).currentTransaction() == null) {
            throw new IllegalStateException( "Thread must have joined a transaction!" );
        }

        ModifiableNodeList mnl = null;
        if (_pNode != null) {
            mnl = new ModifiableNodeList(1);
            mnl.addNode(_pNode);
        }

        SAXChunkProducer producer = helper.beginOutputSequence(mnl, _depth );
        SAXChunkConsumer consumer = new SAXChunkConsumer( _contentHandler );
        ChunkOutputStream cos;
        do {
            producer = helper.createNextChunk( producer );
            cos = producer.chunkStream();
            consumer.processChunk( cos.toByteArray() );
            cos.reset();
        } while (!cos.getEndFlag());
    }
   
   
    /**
     * Create a new XUpdate query. XUpdate is a descriptive XML update
     * language. XUpdate is the recommended way to change a document in the
     * database. See <a href=http://www.xmldb.org>www.xmldb.org</a> for more
     * information and some XUpdate documentation.
     *
     * @see OzoneXUpdateQuery
     */
    public OzoneXUpdateQuery newXUpdateQuery() {
        return new OzoneXUpdateQuery( this );
    }
   
   
    /**
     * Create a new XPath query.
     *
     * @see OzoneXPathQuery
     */
    public OzoneXPathQuery newXPathQuery() {
        return new OzoneXPathQuery( this );
    }
   
   
    protected void executeXUpdate( OzoneXUpdateQuery _query ) throws Exception {
        if (_query == null) {
            throw new IllegalArgumentException( "_query == null." );
        }
        helper.executeXUpdate( _query );
    }
   
   
    protected XObject executeXPath( OzoneXPathQuery _query ) throws Exception {
        if (_query == null) {
            throw new IllegalArgumentException( "_query == null." );
        }
        return helper.executeXPath( _query );
    }
   
   
    /**
     * Determines the absolute XPath for the given node.
     *
     * @param node The W3C DOM node whose XPath is to determine.
     * @return The string representing the absolute XPath for this node.
     */
    public String xpathForNode( Node _pnode ) {
        if (helper == null) {
            throw new IllegalStateException( "Document has already been deleted." );
        }
        return helper.xpathForNode( _pnode );
    }
   
   
    public void writeExternal( ObjectOutput _out ) throws IOException {
        if (runsExternal) {
            throw new IllegalStateException( "XMLContainer cannot be serialized outside an ozone server." );
        }
        _out.writeObject( helper );
    }
   
   
    public void readExternal( ObjectInput _in ) throws IOException, ClassNotFoundException {
        if (runsExternal) {
            throw new IllegalStateException( "XMLContainer cannot be deserialized outside an ozone server." );
        }
        helper = (XMLContainerHelper)_in.readObject();
        db = org.ozoneDB.core.Env.currentEnv().database;
    }
   
}
TOP

Related Classes of org.ozoneDB.xml.util.XMLContainer

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.