⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 saxchunkproducer.java

📁 Java的面向对象数据库系统的源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
// 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: SAXChunkProducer.java,v 1.4 2003/11/07 21:34:22 per_nyfelt Exp $

package org.ozoneDB.xml.util;

import java.io.IOException;
import java.io.Serializable;

import org.ozoneDB.DxLib.DxDeque;
import org.ozoneDB.DxLib.DxArrayDeque;

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

import org.xml.sax.ContentHandler;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;


/**
 * This class produces a sequence of SAXEventChunks out of SAX events or
 * out of a DOM tree. These chunks are used to communicate between client and
 * server.
 *
 *
 * @version $Revision: 1.4 $ $Date: 2003/11/07 21:34:22 $
 * @author <a href="http://www.smb-tec.com">SMB</a>
 */
public final class SAXChunkProducer implements ContentHandler, LexicalHandler, Serializable {

    // Constants

    private final static boolean debug = false;

    private final static int DEFAULT_CHUNK_SIZE = 100000;

    private final static int DEFAULT_CHUNK_INCREASE = 4096;

    /** the default state */
    private final static int CHUNK_STATE_INVALID = -1;

    /** the initial state */
    private final static int CHUNK_STATE_INIT = 0;

    /** a new node has to be processed */
    private final static int CHUNK_STATE_NODE = 1;

    /** Next step is to close an element (or document) */
    private final static int CHUNK_STATE_CLOSE = 3;

    /** Conversion was finished. I.e. there are no more events to throw */
    private final static int CHUNK_STATE_FINISH = 4;


    // Data

    /**
     *  Used for SAX storage. Because chunk processing is done using
     *  {@link SAXChunkProducerDelegate} (which means consumer creation and
     *  consumer usage happens in different methods) the consumer has to be
     *  stored somewhere. I choose the corresponding producer.
     */
    public SAXChunkConsumer dbConsumer;


    private final SAXChunkProducerDelegate delegate;

    private final ChunkOutputStream chunkOutput;

    private final CXMLContentHandler contentHandler;

    private final LexicalHandler lexicalHandler;

    /**
     *  True if all descendant children shall be traversed, false otherwise.
     *  @see #depth
     */
    private final boolean deep;


    /**
     *  The depth of the traversal. If {@link #deep} is false this determines
     *  how deep descendant shall be traversed, otherwise this member is ignored.
     */
    private int depth;


    private int processLevel = 0;

    /**
     * Keeps information about which nodes have already been opened.
     * (used by {@link #createNextChunk() createNextChunk})
     */
    private final DxDeque endEvents;


    private NodeList sourceNodes;
    private int sourceNodesIndex;

    /**
     * The node that has to be converted next; used by
     * {@link #createNextChunk() createNextChunk}. This has to be initialized to
     * the start node before calling {@link #createNextChunk() createNextChunk}
     * the first time.
     */
    private Node nextNode;


    /**
     * implies that the node to be converted was created by a DOM Level 2
     * implementation.
     * used by {@link #createNextChunk() createNextChunk}.
     */
    private final boolean domLevel2;

    /**
     *  the state of the {@link #createNextChunk() createNextChunk} method
     *  @see #CHUNK_STATE_INVALID
     *  @see #CHUNK_STATE_INIT
     *  @see #CHUNK_STATE_NODE
     *  @see #CHUNK_STATE_CLOSE
     */
    private int chunkState = CHUNK_STATE_INVALID;


    /**
     */
/*    public SAXChunkProducer( Node node ) throws IOException{
        this( node, SAXChunkProducer.DEFAULT_CHUNK_SIZE, -1 );
    }
*/

    /**
     */
/*    public SAXChunkProducer( Node node, int _depth ) throws IOException{
        this( node, SAXChunkProducer.DEFAULT_CHUNK_SIZE, _depth );
    }
*/

    /**
     */
/*    public SAXChunkProducer( Node _node, int _maxParts, int _depth ) throws IOException{
        ModifiableNodeList mnl = new ModifiableNodeList(1);
        mnl.addNode(_node);
        this(mnl, _maxParts, _depth);
    }
*/

    /**
     */
    public SAXChunkProducer(NodeList _nodelist) throws IOException{
        this(_nodelist, SAXChunkProducer.DEFAULT_CHUNK_SIZE, -1);
    }


    /**
     */
    public SAXChunkProducer(NodeList _nodelist, int _depth) throws IOException{
        this(_nodelist, SAXChunkProducer.DEFAULT_CHUNK_SIZE, _depth);
    }


    /**
     */
    public SAXChunkProducer(NodeList _nodelist, int _maxParts, int _depth) throws IOException{
        this.deep = _depth < 0;
        this.depth = _depth < 0 ? 0 : _depth;

        this.delegate = null;

        this.sourceNodes = _nodelist;
        this.sourceNodesIndex = 0;
        this.nextNode = _nodelist.item(0);

        this.chunkState = CHUNK_STATE_NODE;
        this.endEvents = new DxArrayDeque();

        Document factory = (Document)((this.nextNode.getNodeType() == Node.DOCUMENT_NODE)
                ? this.nextNode : this.nextNode.getOwnerDocument());
        this.domLevel2 = factory.getImplementation().hasFeature( "XML", "2.0" );

        this.chunkOutput = new ChunkOutputStream( SAXChunkProducer.DEFAULT_CHUNK_SIZE, SAXChunkProducer.DEFAULT_CHUNK_INCREASE );
        this.contentHandler = new CXMLContentHandler( this.chunkOutput );
        this.lexicalHandler = (this.contentHandler instanceof LexicalHandler)
                ? this.contentHandler
                : null;
    }


    /**
     */
    public SAXChunkProducer( SAXChunkProducerDelegate _delegate ) throws IOException{
        this( _delegate, SAXChunkProducer.DEFAULT_CHUNK_SIZE, -1 );
    }


    /**
     */
    public SAXChunkProducer( SAXChunkProducerDelegate _delegate, int _depth ) throws IOException{
        this( _delegate, SAXChunkProducer.DEFAULT_CHUNK_SIZE, _depth );
    }


    /**
     */
    public SAXChunkProducer( SAXChunkProducerDelegate _delegate, int _maxParts, int _depth ) throws IOException{
        this.deep = _depth == -1;
        this.depth = this.deep ? 0 : _depth;

        this.delegate = _delegate;

        this.chunkOutput = new ChunkOutputStream( SAXChunkProducer.DEFAULT_CHUNK_SIZE,
                SAXChunkProducer.DEFAULT_CHUNK_INCREASE );
        this.contentHandler = new CXMLContentHandler( this.chunkOutput );
        this.lexicalHandler = (this.contentHandler instanceof LexicalHandler)
                ? this.contentHandler
                : null;

        this.domLevel2 = false;
        this.endEvents = null;
    }


    /**
     * @return the data of the chunk created during the last call of
     *          {@link #createNextChunk()}.
     */
    public ChunkOutputStream chunkStream() throws SAXException {
        return this.chunkOutput;
    }


    /**
     *  Converts a given DOM tree in multiple steps to SAX events.
     *  Every call throws the specified number of events (or less, if the
     *  conversion is finished).
     *  Before calling this method the first time {@link #nextNode nextNode} has to
     *  be set to the root node of the DOM tree to convert, and
     *  {@link #chunkState} has to be set to
     *  {@link #CHUNK_STATE_INIT}. (The same way you can reset the nextChunk
     *  context.)
     *
     *  @throws SAXException
     *  @throws IllegalStateException if {@link #chunkState} has
     *          not been set or has been set to an unknown value.
     *  @throws IllegalArgumentException if the value of _eventsToThrow was
     *          equal or less than 0.
     */
    public final void createNextChunk() throws SAXException {
        String uri;
        String qName;
        String lName;

        // now on the client
       // chunkOutput.reset();

        while (chunkOutput.getState() != ChunkOutputStream.STATE_OVERFLOW && chunkState != CHUNK_STATE_FINISH) {
            //throw events until the chunk is filled

            switch (chunkState) {
            case CHUNK_STATE_NODE:
                switch (nextNode.getNodeType()) {
                case Node.DOCUMENT_NODE:
                    contentHandler.startDocument();
                    depth -= deep ? 0 : 1;

                    endEvents.push( nextNode );

                    //any children to process ?
                    nextNode = nextNode.getFirstChild();
                    chunkState = ((nextNode == null) || (depth < 0))
                            ? CHUNK_STATE_CLOSE
                            : CHUNK_STATE_NODE;
                    nextNode = (chunkState == CHUNK_STATE_CLOSE) ? (Node)endEvents.pop() : nextNode;
                    break;
                case Node.ELEMENT_NODE:
                    Element elem = (Element)nextNode;
                    Attributes saxAttr = createSAXAttributes(elem);
                    uri = domLevel2 ? elem.getNamespaceURI() : "";
                    qName = elem.getNodeName();
                    lName = domLevel2 ? elem.getLocalName() : qName;

                    contentHandler.startElement(
                            uri == null ? ""  : uri,
                            lName == null ? qName : lName,
                            qName, saxAttr );

                    endEvents.push(nextNode);

                    depth -= deep ? 0 : 1;

                    nextNode = nextNode.getFirstChild();
                    chunkState = ((nextNode == null) || (depth < 0)) ? CHUNK_STATE_CLOSE : CHUNK_STATE_NODE;
                    nextNode = (chunkState == CHUNK_STATE_CLOSE) ? (Node)endEvents.pop() : nextNode;
                    break;
                default:
                    convertSingleEventNode( nextNode );

                    nextNode = nextNode.getNextSibling();
                    chunkState = ((nextNode != null) && (endEvents.peek() != null))
                            ? CHUNK_STATE_NODE
                            : ((nextNode = (Node)endEvents.pop()) != null)
                                ? CHUNK_STATE_CLOSE
                                : CHUNK_STATE_FINISH;

                    if (this.chunkState == CHUNK_STATE_FINISH) {
                        this.sourceNodesIndex++;
                        if (this.sourceNodesIndex < this.sourceNodes.getLength()) {
                            this.nextNode = this.sourceNodes.item(this.sourceNodesIndex);
                            this.chunkState = CHUNK_STATE_NODE;
                        }

                    }

                    break;
                }
                break;

            case CHUNK_STATE_CLOSE: {
                switch (nextNode.getNodeType()) {
                case Node.ELEMENT_NODE:
                    depth += deep ? 0 : 1;

                    Element elem = (Element)nextNode;
                    uri = domLevel2 ? elem.getNamespaceURI() : "";
                    qName = elem.getNodeName();
                    lName = domLevel2 ? elem.getLocalName() : qName;
                    contentHandler.endElement(
                            uri == null ? "" : uri,
                            lName == null ? qName : lName,
                            qName);

                    nextNode = elem.getNextSibling();
                    break;
                case Node.DOCUMENT_NODE:
                    depth += deep ? 0 : 1;
                    contentHandler.endDocument();
                    nextNode = null;
                    break;
                default:
                    throw new IllegalStateException( "endEvents stack contains unproper value: " + nextNode );
                    //break;
                }

                chunkState = ((nextNode != null) && (endEvents.peek() != null))
                        ? CHUNK_STATE_NODE
                        : ((nextNode = (Node)endEvents.pop()) != null)
                            ? CHUNK_STATE_CLOSE
                            : CHUNK_STATE_FINISH;

                if (this.chunkState == CHUNK_STATE_FINISH) {
                    this.sourceNodesIndex++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -