You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by mr...@apache.org on 2008/08/08 19:42:07 UTC

svn commit: r684021 - /xerces/java/trunk/src/org/apache/xerces/impl/xs/traversers/StAXSchemaParser.java

Author: mrglavas
Date: Fri Aug  8 10:42:07 2008
New Revision: 684021

URL: http://svn.apache.org/viewvc?rev=684021&view=rev
Log:
JIRA Issue #1313:
http://issues.apache.org/jira/browse/XERCESJ-1313

Adding support for construction of a Schema DOM from a StAXSource. 
Still need to hook this up to the XSDHandler.

Added:
    xerces/java/trunk/src/org/apache/xerces/impl/xs/traversers/StAXSchemaParser.java   (with props)

Added: xerces/java/trunk/src/org/apache/xerces/impl/xs/traversers/StAXSchemaParser.java
URL: http://svn.apache.org/viewvc/xerces/java/trunk/src/org/apache/xerces/impl/xs/traversers/StAXSchemaParser.java?rev=684021&view=auto
==============================================================================
--- xerces/java/trunk/src/org/apache/xerces/impl/xs/traversers/StAXSchemaParser.java (added)
+++ xerces/java/trunk/src/org/apache/xerces/impl/xs/traversers/StAXSchemaParser.java Fri Aug  8 10:42:07 2008
@@ -0,0 +1,409 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xs.traversers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.Namespace;
+import javax.xml.stream.events.ProcessingInstruction;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+import org.apache.xerces.impl.xs.opti.SchemaDOMParser;
+import org.apache.xerces.util.JAXPNamespaceContextWrapper;
+import org.apache.xerces.util.StAXLocationWrapper;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLAttributesImpl;
+import org.apache.xerces.util.XMLStringBuffer;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+import org.w3c.dom.Document;
+
+/**
+ * <p>StAXSchemaParser reads StAX events, converts them into XNI events
+ * and passes them directly to the SchemaDOMParser.</p>
+ * 
+ * @xerces.internal
+ * 
+ * @version $Id$
+ */
+final class StAXSchemaParser {
+    
+    /** Chunk size (1024). */
+    private static final int CHUNK_SIZE = (1 << 10);
+    
+    /** Chunk mask (CHUNK_SIZE - 1). */
+    private static final int CHUNK_MASK = CHUNK_SIZE - 1;
+
+    /** Array for holding character data. **/
+    private final char [] fCharBuffer = new char[CHUNK_SIZE];
+    
+    /** Symbol table **/
+    private SymbolTable fSymbolTable;
+    
+    /** SchemaDOMParser, events will be delegated to SchemaDOMParser to pass */
+    private SchemaDOMParser fSchemaDOMParser;
+    
+    /** XML Locator wrapper for SAX. **/
+    private final StAXLocationWrapper fLocationWrapper = new StAXLocationWrapper();
+    
+    /** The namespace context of this document: stores namespaces in scope */
+    private final JAXPNamespaceContextWrapper fNamespaceContext = new JAXPNamespaceContextWrapper(fSymbolTable);
+    
+    /** Fields for start element, end element and characters. */
+    private final QName fElementQName = new QName();
+    private final QName fAttributeQName = new QName();
+    private final XMLAttributesImpl fAttributes = new XMLAttributesImpl();
+    private final XMLString fTempString = new XMLString();
+    private final ArrayList fDeclaredPrefixes = new ArrayList();
+    private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
+    private int fDepth;
+    
+    public void reset(SchemaDOMParser schemaDOMParser, SymbolTable symbolTable) {
+        fSchemaDOMParser = schemaDOMParser;
+        fSymbolTable = symbolTable;
+        fNamespaceContext.setSymbolTable(fSymbolTable);
+    }
+
+    public Document getDocument() {
+        return fSchemaDOMParser.getDocument();
+    }
+
+    public void parse(XMLEventReader input) throws XMLStreamException, XNIException {
+        XMLEvent currentEvent = input.peek();
+        if (currentEvent != null) {
+            int eventType = currentEvent.getEventType();
+            if (eventType != XMLStreamConstants.START_DOCUMENT &&
+                eventType != XMLStreamConstants.START_ELEMENT) {
+                throw new XMLStreamException();
+            }
+            fSchemaDOMParser.startDocument(fLocationWrapper, null, fNamespaceContext, null);
+            loop: while (input.hasNext()) {
+                currentEvent = input.nextEvent();
+                eventType = currentEvent.getEventType();
+                switch (eventType) {
+                case XMLStreamConstants.START_ELEMENT:
+                    ++fDepth;
+                    StartElement start = currentEvent.asStartElement();
+                    fillQName(fElementQName, start.getName());
+                    fLocationWrapper.setLocation(start.getLocation());
+                    fNamespaceContext.setNamespaceContext(start.getNamespaceContext());
+                    fillXMLAttributes(start);
+                    fillDeclaredPrefixes(start);
+                    addNamespaceDeclarations();
+                    fSchemaDOMParser.startElement(fElementQName, fAttributes, null);
+                    break;
+                case XMLStreamConstants.END_ELEMENT:
+                    EndElement end = currentEvent.asEndElement();
+                    fillQName(fElementQName, end.getName());
+                    fillDeclaredPrefixes(end);
+                    fLocationWrapper.setLocation(end.getLocation());
+                    fSchemaDOMParser.endElement(fElementQName, null);
+                    --fDepth;
+                    if (fDepth <= 0) {
+                        break loop;
+                    }
+                    break;
+                case XMLStreamConstants.CHARACTERS:
+                    sendCharactersToSchemaParser(currentEvent.asCharacters().getData(), false);
+                    break;
+                case XMLStreamConstants.SPACE:
+                    sendCharactersToSchemaParser(currentEvent.asCharacters().getData(), true);
+                    break;
+                case XMLStreamConstants.CDATA:
+                    fSchemaDOMParser.startCDATA(null);
+                    sendCharactersToSchemaParser(currentEvent.asCharacters().getData(), false);
+                    fSchemaDOMParser.endCDATA(null);
+                    break;
+                case XMLStreamConstants.PROCESSING_INSTRUCTION:
+                    ProcessingInstruction pi = (ProcessingInstruction)currentEvent;
+                    fillProcessingInstruction(pi.getData());
+                    fSchemaDOMParser.processingInstruction(pi.getTarget(), fTempString, null);
+                    break;
+                case XMLStreamConstants.DTD:
+                    /* There shouldn't be a DTD in the schema */
+                    break;
+                case XMLStreamConstants.ENTITY_REFERENCE:
+                    /* Not needed for schemas */
+                    break;
+                case XMLStreamConstants.COMMENT:
+                    /* No point in sending comments */
+                    break;
+                case XMLStreamConstants.START_DOCUMENT:
+                    fDepth++;
+                    /* We automatically call startDocument before the loop */
+                    break;
+                case XMLStreamConstants.END_DOCUMENT:
+                    /* We automatically call endDocument after the loop */
+                    break;
+                }
+            }
+            fLocationWrapper.setLocation(null);
+            fNamespaceContext.setNamespaceContext(null);
+            fSchemaDOMParser.endDocument(null);
+        }
+    }
+    
+    public void parse(XMLStreamReader input) throws XMLStreamException, XNIException {
+        if (input.hasNext()) {
+            int eventType = input.getEventType();
+            if (eventType != XMLStreamConstants.START_DOCUMENT &&
+                eventType != XMLStreamConstants.START_ELEMENT) {
+                throw new XMLStreamException();
+            }
+            fSchemaDOMParser.startDocument(fLocationWrapper, null, fNamespaceContext, null);
+            boolean first = true;
+            loop: while (input.hasNext()) {
+                if (!first) {
+                    eventType = input.next();
+                }
+                else {
+                    first = false;
+                }
+                switch (eventType) {
+                case XMLStreamConstants.START_ELEMENT:
+                    ++fDepth;
+                    fLocationWrapper.setLocation(input.getLocation());
+                    fNamespaceContext.setNamespaceContext(input.getNamespaceContext());
+                    fillQName(fElementQName, input.getNamespaceURI(),
+                        input.getLocalName(), input.getPrefix());
+                    fillXMLAttributes(input);
+                    fillDeclaredPrefixes(input);
+                    addNamespaceDeclarations();
+                    fSchemaDOMParser.startElement(fElementQName, fAttributes, null);
+                    break;
+                case XMLStreamConstants.END_ELEMENT:
+                    fLocationWrapper.setLocation(input.getLocation());
+                    fNamespaceContext.setNamespaceContext(input.getNamespaceContext());
+                    fillQName(fElementQName, input.getNamespaceURI(), 
+                        input.getLocalName(), input.getPrefix());
+                    fillDeclaredPrefixes(input);
+                    fSchemaDOMParser.endElement(fElementQName, null);
+                    --fDepth;
+                    if (fDepth <= 0) {
+                        break loop;
+                    }
+                    break;
+                case XMLStreamConstants.CHARACTERS:
+                    fTempString.setValues(input.getTextCharacters(), 
+                        input.getTextStart(), input.getTextLength());
+                    fSchemaDOMParser.characters(fTempString, null);
+                    break;
+                case XMLStreamConstants.SPACE:
+                    fTempString.setValues(input.getTextCharacters(), 
+                        input.getTextStart(), input.getTextLength());
+                    fSchemaDOMParser.ignorableWhitespace(fTempString, null);
+                    break;
+                case XMLStreamConstants.CDATA:
+                    fSchemaDOMParser.startCDATA(null);
+                    fTempString.setValues(input.getTextCharacters(), 
+                        input.getTextStart(), input.getTextLength());
+                    fSchemaDOMParser.characters(fTempString, null);
+                    fSchemaDOMParser.endCDATA(null);
+                    break;
+                case XMLStreamConstants.PROCESSING_INSTRUCTION:
+                    fillProcessingInstruction(input.getPIData());
+                    fSchemaDOMParser.processingInstruction(input.getPITarget(), fTempString, null);
+                    break;
+                case XMLStreamConstants.DTD:
+                    /* There shouldn't be a DTD in the schema */
+                    break;
+                case XMLStreamConstants.ENTITY_REFERENCE:
+                    /* Not needed for schemas */
+                    break;
+                case XMLStreamConstants.COMMENT:
+                    /* No point in sending comments */
+                    break;
+                case XMLStreamConstants.START_DOCUMENT:
+                    ++fDepth;
+                    /* We automatically call startDocument before the loop */
+                    break;
+                case XMLStreamConstants.END_DOCUMENT:
+                    /* We automatically call endDocument after the loop */
+                    break;
+                }
+            }
+            fLocationWrapper.setLocation(null);
+            fNamespaceContext.setNamespaceContext(null);
+            fSchemaDOMParser.endDocument(null);
+        }
+    }
+    
+    /** Send characters to the validator in CHUNK_SIZE character chunks. */
+    private void sendCharactersToSchemaParser(String str, boolean whitespace) {
+        if (str != null) {
+            final int length = str.length();
+            final int remainder = length & CHUNK_MASK;
+            if (remainder > 0) {
+                str.getChars(0, remainder, fCharBuffer, 0);
+                fTempString.setValues(fCharBuffer, 0, remainder);
+                if (whitespace) {
+                    fSchemaDOMParser.ignorableWhitespace(fTempString, null);
+                }
+                else {
+                    fSchemaDOMParser.characters(fTempString, null);
+                }
+            }
+            int i = remainder;
+            while (i < length) {
+                str.getChars(i, i += CHUNK_SIZE, fCharBuffer, 0);
+                fTempString.setValues(fCharBuffer, 0, CHUNK_SIZE);
+                if (whitespace) {
+                    fSchemaDOMParser.ignorableWhitespace(fTempString, null);
+                }
+                else {
+                    fSchemaDOMParser.characters(fTempString, null);
+                }
+            }
+        }
+    }
+    
+    // processing instructions must be sent all in one chunk
+    private void fillProcessingInstruction(String data) {
+        final int dataLength = data.length();
+        char [] charBuffer = fCharBuffer;
+        if (charBuffer.length < dataLength) {
+            // toCharArray() creates a newly allocated array, so it's okay
+            // to keep a reference to it.
+            charBuffer = data.toCharArray();
+        }
+        else {
+            data.getChars(0, dataLength, charBuffer, 0);
+        }
+        fTempString.setValues(charBuffer, 0, dataLength);
+    }
+
+    private void fillXMLAttributes(StartElement event) {
+        fAttributes.removeAllAttributes();
+        final Iterator attrs = event.getAttributes();
+        while (attrs.hasNext()) {
+            Attribute attr = (Attribute) attrs.next();
+            fillQName(fAttributeQName, attr.getName());
+            String type = attr.getDTDType();
+            int idx = fAttributes.getLength();
+            fAttributes.addAttributeNS(fAttributeQName, 
+                    (type != null) ? type : XMLSymbols.fCDATASymbol, attr.getValue());
+            fAttributes.setSpecified(idx, attr.isSpecified());
+        }
+    }
+    
+    private void fillXMLAttributes(XMLStreamReader input) {
+        fAttributes.removeAllAttributes();
+        final int len = input.getAttributeCount();
+        for (int i = 0; i < len; ++i) {
+            fillQName(fAttributeQName, input.getAttributeNamespace(i), 
+                input.getAttributeLocalName(i), input.getAttributePrefix(i));
+            String type = input.getAttributeType(i);
+            fAttributes.addAttributeNS(fAttributeQName, 
+                    (type != null) ? type : XMLSymbols.fCDATASymbol, input.getAttributeValue(i));
+            fAttributes.setSpecified(i, input.isAttributeSpecified(i));
+        }
+    }
+    
+    private void addNamespaceDeclarations() {
+        String prefix = null;
+        String localpart = null;
+        String rawname = null;
+        String nsPrefix = null;
+        String nsURI = null;
+        
+        final Iterator iter = fDeclaredPrefixes.iterator();
+        while (iter.hasNext()) {
+            nsPrefix = (String) iter.next();
+            nsURI = fNamespaceContext.getURI(nsPrefix);
+            if (nsPrefix.length() > 0) {
+                prefix = XMLSymbols.PREFIX_XMLNS;
+                localpart = nsPrefix;
+                fStringBuffer.clear();
+                fStringBuffer.append(prefix);
+                fStringBuffer.append(':');
+                fStringBuffer.append(localpart);
+                rawname = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
+            }
+            else {
+                prefix = XMLSymbols.EMPTY_STRING;
+                localpart = XMLSymbols.PREFIX_XMLNS;
+                rawname = XMLSymbols.PREFIX_XMLNS;
+            }
+            fAttributeQName.setValues(prefix, localpart, rawname, NamespaceContext.XMLNS_URI);
+            fAttributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, nsURI);
+        }
+    }
+    
+    /** Fills in the list of declared prefixes. */
+    private void fillDeclaredPrefixes(StartElement event) {
+        fillDeclaredPrefixes(event.getNamespaces());
+    }
+    
+    /** Fills in the list of declared prefixes. */
+    private void fillDeclaredPrefixes(EndElement event) {
+        fillDeclaredPrefixes(event.getNamespaces());
+    }
+    
+    /** Fills in the list of declared prefixes. */
+    private void fillDeclaredPrefixes(Iterator namespaces) {
+        fDeclaredPrefixes.clear();
+        while (namespaces.hasNext()) {
+            Namespace ns = (Namespace) namespaces.next();
+            String prefix = ns.getPrefix();
+            fDeclaredPrefixes.add(prefix != null ? prefix : "");
+        }
+    }
+    
+    /** Fills in the list of declared prefixes. */
+    private void fillDeclaredPrefixes(XMLStreamReader reader) {
+        fDeclaredPrefixes.clear();
+        final int len = reader.getNamespaceCount();
+        for (int i = 0; i < len; ++i) {
+            String prefix = reader.getNamespacePrefix(i);
+            fDeclaredPrefixes.add(prefix != null ? prefix : "");
+        }
+    }
+
+    /** Fills in a QName object. */
+    private void fillQName(QName toFill, javax.xml.namespace.QName toCopy) {
+        fillQName(toFill, toCopy.getNamespaceURI(), toCopy.getLocalPart(), toCopy.getPrefix());
+    }
+
+    /** Fills in a QName object. */
+    final void fillQName(QName toFill, String uri, String localpart, String prefix) {
+        uri = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null;
+        localpart = (localpart != null) ? fSymbolTable.addSymbol(localpart) : XMLSymbols.EMPTY_STRING;
+        prefix = (prefix != null && prefix.length() > 0) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING;
+        String raw = localpart;
+        if (prefix != XMLSymbols.EMPTY_STRING) {
+            fStringBuffer.clear();
+            fStringBuffer.append(prefix);
+            fStringBuffer.append(':');
+            fStringBuffer.append(localpart);
+            raw = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
+        }
+        toFill.setValues(prefix, localpart, raw, uri);
+    }
+    
+} // StAXSchemaParser

Propchange: xerces/java/trunk/src/org/apache/xerces/impl/xs/traversers/StAXSchemaParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xerces/java/trunk/src/org/apache/xerces/impl/xs/traversers/StAXSchemaParser.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xerces.apache.org
For additional commands, e-mail: commits-help@xerces.apache.org