Package org.ozoneDB.xml.util

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

// 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: SAXChunkConsumer.java,v 1.1 2001/12/18 10:31:31 per_nyfelt Exp $

package org.ozoneDB.xml.util;

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

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.EntityReference;
import org.w3c.dom.Comment;
import org.w3c.dom.CDATASection;

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

import org.ozoneDB.DxLib.DxHashMap;
import org.ozoneDB.DxLib.DxDeque;
import org.ozoneDB.OzoneObject;


/**
* Objects of this class can be used to convert a sequence of
* {@link SAXEventChunk}s back into a DOM tree or SAX events.
* WARNING: Don't reuse instances of this class. Create a new instance for each
* chunk set (chunks containing information about the same XML tree).
* @version $Revision: 1.1 $ $Date: 2001/12/18 10:31:31 $
* @author <a href="http://www.smb-tec.com">SMB</a>
*/
public final class SAXChunkConsumer implements ContentHandler, LexicalHandler, Serializable {
   
    private final static boolean debug = false;
   
    private final Node appendTo;

    protected Node startNode = null;
   
    protected Node currentNode = null;
   
    protected final Document domFactory;
   
    protected final boolean domLevel2;
   
    protected final ContentHandler contentHandler;
   
    protected final LexicalHandler lexicalHandler;

    protected final ChunkInputStream chunkInput;
   
    protected final CompiledXMLInputStream cxmlInput;
   
    protected int processLevel;
   
    protected ModifiableNodeList resultNodeList;
   
    /**
     *  Use this chunk consumer to produce a DOM tree out of the consumed
     *  chunks.
     *  @param _node The node where the newly created DOM tree will be appended to
     *  @throws IllegalArgumentException if the given node was null
     */
    public SAXChunkConsumer(Document domFactory,  Node appendTo) throws IOException{
        if (domFactory == null) {
            throw new IllegalArgumentException("provided DOM factory node was null!");
        }

        this.contentHandler = this;
        this.lexicalHandler = this;
       
        this.appendTo = appendTo;
        this.processLevel = 0;
       
        this.resultNodeList = new ModifiableNodeList();
       
        this.domFactory = domFactory;
       // this.domLevel2 = domFactory.getImplementation().hasFeature("XML", "2.0");
        this.domLevel2 = false;
       
        this.chunkInput = new ChunkInputStream(null);
        this.cxmlInput = new CompiledXMLInputStream(this.chunkInput);
    }
   
   
    /**
     *  Use this chunk consumer to produce SAX events out of the consumed chunks.
     *  @param _contentHandler the handler the SAX events will be send to
     *  @throws IllegalArgumentException if the given content handler was null
     */
    public SAXChunkConsumer(ContentHandler contentHandler) throws IOException{
        if (contentHandler == null) {
            throw new IllegalArgumentException("provided SAX content handler was null");
        }
        this.contentHandler = contentHandler;
        this.lexicalHandler = (contentHandler instanceof LexicalHandler)
                ? (LexicalHandler)contentHandler
                : null;
        this.appendTo = null;
       
        this.chunkInput = new ChunkInputStream(null);
        this.cxmlInput = new CompiledXMLInputStream(this.chunkInput);
       
        this.domLevel2 = false;
        this.domFactory = null;
    }
   
   
    /**
     *  Takes a chunk and produces corresponding SAX events
     *  @param _chunk the chunk containing definitions of events to be thrown
     *  @throws IllegalArgumentException if the given chunk was null
     */
    public final void processChunk(byte[] chunkData) throws SAXException, IOException {
        if (chunkData == null) {
            throw new IllegalArgumentException("provided event chunk was null");
        }
       
        this.chunkInput.setBuffer(chunkData);
       
        while (this.chunkInput.available() > 0) {
            switch (cxmlInput.readEvent()) {
            case CXMLContentHandler.START_DOCUMENT:
                if (debug) {
                    System.out.println(this.getClass().getName() + ": startDocument()");
                }
                this.contentHandler.startDocument();
                break;
            case CXMLContentHandler.END_DOCUMENT:
                this.contentHandler.endDocument();
                return;
            case CXMLContentHandler.START_PREFIX_MAPPING:
                this.contentHandler.startPrefixMapping(cxmlInput.readString(), cxmlInput.readString());
                break;
            case CXMLContentHandler.END_PREFIX_MAPPING:
                this.contentHandler.endPrefixMapping(cxmlInput.readString());
                break;
            case CXMLContentHandler.START_ELEMENT:
                if (debug) {
                    System.out.println(this.getClass().getName() + ": startElement()");
                }
                int attributes = cxmlInput.readAttributes();
                AttributesImpl atts = new AttributesImpl();
                for (int i = 0; i < attributes; i++) {
//                    atts.addAttribute(cxmlInput.readString(), cxmlInput.readString(), cxmlInput.readString(),
//                            cxmlInput.readString(), cxmlInput.readString());
                    atts.addAttribute(cxmlInput.readString(), cxmlInput.readString(), cxmlInput.readString(),
                            cxmlInput.readString(), new String( cxmlInput.readChars() ) );
                }
                String namespace = cxmlInput.readString();
                String localname = cxmlInput.readString();
                String qname = cxmlInput.readString();

                if (debug) {
                    System.out.println(this.getClass().getName() + "namespace=" + namespace + ", localname=" + localname + ", qname=" + qname);
                }

                this.contentHandler.startElement( namespace, localname, qname , atts);
                break;
            case CXMLContentHandler.END_ELEMENT:
                this.contentHandler.endElement(cxmlInput.readString(), cxmlInput.readString(), cxmlInput.readString());
                break;
            case CXMLContentHandler.CHARACTERS:
                char[] chars = cxmlInput.readChars();
                this.contentHandler.characters(chars, 0, chars.length);
                break;
            case CXMLContentHandler.IGNORABLE_WHITESPACE:
                char[] spaces = cxmlInput.readChars();
                this.contentHandler.characters(spaces, 0, spaces.length);
                break;
            case CXMLContentHandler.PROCESSING_INSTRUCTION:
                this.contentHandler.processingInstruction(cxmlInput.readString(), cxmlInput.readString());
                break;
            case CXMLContentHandler.COMMENT:
                if (this.lexicalHandler != null) {
                    char[] comment = cxmlInput.readChars();
                    this.lexicalHandler.comment(comment, 0, comment.length);
                }
                break;
            case CXMLContentHandler.START_CDATA:
                if (this.lexicalHandler != null) {
                    this.lexicalHandler.startCDATA();
                }
                break;
            case CXMLContentHandler.END_CDATA:
                if (this.lexicalHandler != null) {
                    this.lexicalHandler.endCDATA();
                }
                break;
            default:
                throw new IOException("parsing error: event not supported: ");
            }
        }
    }
   
   
    /**
     *  @return the last created result node, if this consumer was initialized
     *      for DOM creation.
     */
    public final Node getResultNode() {
        return startNode;
    }
   
   
    /**
     *  @return the result node list, if this consumer was initialized for
     *  DOM creation.
     */
    public final NodeList getResultNodeList() {
        return resultNodeList;
    }
   
   
    //
    // SAX content handler implemenation
    //
       
   
    /**
     *  Received notification of the beginning of the document.
     */
    public final void startDocument() {
        if (this.startNode == null) {
            this.startNode = (this.appendTo != null) ? this.appendTo : this.domFactory;
        }

        if (debug) {
            System.out.println(this.getClass().getName() + ": startDocument()");
        }
       
        if (this.startNode.getNodeType() != Node.DOCUMENT_NODE) {
            throw new IllegalStateException("A document can't be appended to another node!");
        }

        if (this.startNode.hasChildNodes()) {
            throw new RuntimeException("The given DOM document must not have children if a whole document shall be converted!");
        }

        if (this.processLevel != 0) {
            throw new RuntimeException("startDocument event must not occur within other start-end-event pairs!");
        }

        this.resultNodeList.addNode(this.startNode);
        this.currentNode = this.startNode;
        this.processLevel++;
    }
   
   
    /**
     *  Received notification of the end of the document.
     */
    public final void endDocument() {
        if (debug) {
            System.out.println(this.getClass().getName() + ": endDocument()");
        }
       
        this.currentNode = this.currentNode.getParentNode();
        this.processLevel--;
    }


    /**
     *  Receive notification of the start of an element.
     *  Note: Namespace handling has to be revised.
     */
    public final void startElement(String _namespaceURI, String _localName, String _rawName, Attributes _atts) {
        if (debug) {
            System.out.println(this.getClass().getName() + ": startElement(...)");
        }
       
        Element newElem;
        if (domLevel2) {
            newElem = domFactory.createElementNS(_namespaceURI, _rawName);
           
            //add the attributes
            for (int i = 0; i < _atts.getLength(); i++) {
                newElem.setAttributeNS(_atts.getURI(i), _atts.getQName(i), _atts.getValue(i));
            }
        } else {
            newElem = domFactory.createElement(_rawName);
           
            //add the attributes
            for (int i = 0; i < _atts.getLength(); i++) {
                newElem.setAttribute(_atts.getQName(i), _atts.getValue(i));
            }
       
        }

        if (this.processLevel == 0) {
            this.resultNodeList.addNode(newElem);
            this.startNode = newElem;
            this.currentNode = newElem;
            if (this.appendTo != null) {
                this.appendTo.appendChild(newElem);
            }
        } else {
            this.currentNode.appendChild(newElem);
            this.currentNode = newElem;
        }
        this.processLevel++;
    }
   
   
    /**
     *  Receive notification of the end of an element.
     */
    public final void endElement(String _namespaceURI, String _localName, String _rawName) {
        if (debug) {
            System.out.println(this.getClass().getName() + ": endElement(...)");
        }
       
        this.currentNode = this.currentNode.getParentNode();
        this.processLevel--;
    }
   
   
    /**
     *  Begin the scope of a prefix-URI Namespace mapping.
     */
    public final void startPrefixMapping(String _prefix, String _uri) {
        return;
    }
   

    /**
     *  End the scope of a prefix-URI mapping.
     */
    public final void endPrefixMapping(String prefix) {
        // Ozone is not yet namespace aware, so we ignore the prefix mappings
    }
   
   
    /**
     *  Receive notification of character data inside an element.
     */
    public final void characters(char[] ch, int start, int length) {

        if ((this.currentNode != null)
                && (this.currentNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
            //we receive a CDATA section
           
            StringBuffer chars = new StringBuffer();
           
            chars.append(ch, start, length);
            chars.append(this.currentNode.getNodeValue());
            this.currentNode.setNodeValue(chars.toString());
        } else {
            //just normal characters
            Text textNode = this.domFactory.createTextNode(new String(ch, start, length));
            if (debug) {
                System.out.println(this.getClass().getName() + ": characters(...)");
            }
           
            if (this.processLevel == 0) {
                this.resultNodeList.addNode(textNode);
                this.startNode = textNode;
                this.currentNode = textNode;
                if (this.appendTo != null) {
                    this.appendTo.appendChild(textNode);
                }
            } else {
                this.currentNode.appendChild(textNode);
            }
        }
    }
   
   
    /**
     *  Receive notification of a processing instruction.
     */
    public final void processingInstruction(String _target, String _data) {
        ProcessingInstruction piNode = domFactory.createProcessingInstruction(_target, _data);
        if (debug) {
            System.out.println(this.getClass().getName() + ": processingInstruction(...)");
        }

        if (this.processLevel == 0) {
            this.resultNodeList.addNode(piNode);
            this.startNode = piNode;
            this.currentNode = piNode;
            if (this.appendTo != null) {
                this.appendTo.appendChild(piNode);
            }
        } else {
            this.currentNode.appendChild(piNode);
        }
    }
   
   
    /**
     *  Receive notification of a skipped entity.
     */
    public final void skippedEntity(java.lang.String _name) {
        EntityReference erNode = domFactory.createEntityReference(_name);
        if (debug) {
            System.out.println(this.getClass().getName() + ": skippedEntity(...)");
        }

        if (this.processLevel == 0) {
            this.resultNodeList.addNode(erNode);
            this.startNode = erNode;
            this.currentNode = erNode;
            if (this.appendTo != null) {
                this.appendTo.appendChild(erNode);
            }
        } else {
            this.currentNode.appendChild(erNode);
        }
    }
   
   
    /**
     *  Receive notification of ignorable whitespace in element content.
     */
    public final void ignorableWhitespace(char[] _ch, int _start, int _length) {
        Text whitespace = domFactory.createTextNode(new String(_ch, _start, _length));
        if (debug) {
            System.out.println(this.getClass().getName() + ": ignorableWhitespace(...)");
        }
       
        if (this.processLevel == 0) {
            this.resultNodeList.addNode(whitespace);
            this.startNode = whitespace;
            this.currentNode = whitespace;
            if (this.appendTo != null) {
                this.appendTo.appendChild(whitespace);
            }
        } else {
            this.currentNode.appendChild(whitespace);
        }
    }
   
   
    /**
     *  Receive an object for locating the origin of SAX document events.
     */
    public final void setDocumentLocator(Locator locator) {
    // we don't care about the origin of the document
    }
   
   
    //
    // SAX LexicalHandler implemenation
    //


    public void comment( char[] ch, int start, int length ) throws SAXException {
       
        Comment commentNode = this.domFactory.createComment(new String(ch, start, length));

        if (debug) {
            System.out.println(this.getClass().getName() + ": comment(...)");
        }
       
        if (this.processLevel == 0) {
            this.resultNodeList.addNode(commentNode);
            this.startNode = commentNode;
            this.currentNode = commentNode;
            if (this.appendTo != null) {
                this.appendTo.appendChild(commentNode);
            }
        } else {
            this.currentNode.appendChild(commentNode);
        }
    }
   

    public void startCDATA() throws SAXException {
        CDATASection cdata = this.domFactory.createCDATASection("");
        if (debug) {
            System.out.println(this.getClass().getName() + ": startCDATA(...)");
        }
       
        if (this.processLevel == 0) {
            this.resultNodeList.addNode(cdata);
            this.startNode = cdata;
            this.currentNode = cdata;
            if (this.appendTo != null) {
                this.appendTo.appendChild(cdata);
            }
        } else {
            this.currentNode.appendChild(cdata);
            this.currentNode = cdata;
        }
        this.processLevel++;
    }
   
   
    public void endCDATA() throws SAXException {
        if (debug) {
            System.out.println(this.getClass().getName() + ": endCDATA(...)");
        }
       
        this.currentNode = this.currentNode.getParentNode();
        this.processLevel--;
    }
   

    public void startDTD(String name, String publicId, String systemId)
            throws SAXException {
        //FIXME(?)
        //not handled
    }


    public void endDTD() throws SAXException {
        //FIXME(?)
        //not handled
    }


    public void startEntity(String name) throws SAXException {
        //FIXME(?)
        //not handled
    }
   
   
    public void endEntity(String name) throws SAXException {
        //FIXME(?)
        //not handled
    }
}
TOP

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

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.