From 195774c489a1a671aca514b0afa88332bf9c6ee3 Mon Sep 17 00:00:00 2001 From: lresende Date: Tue, 10 Nov 2009 19:20:12 +0000 Subject: Moving SDO tags git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@834617 13f79535-47bb-0310-9956-ffa450edef68 --- .../resource/RecordedEventXMLStreamReader.java | 868 +++++++++++++++++++++ 1 file changed, 868 insertions(+) create mode 100644 sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java (limited to 'sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java') diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java new file mode 100644 index 0000000000..b2b3036692 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java @@ -0,0 +1,868 @@ +/** + * + * 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.tuscany.sdo.util.resource; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.eclipse.emf.ecore.xmi.XMLResource; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +/** + * This special purpose XMLStreamReader is used to produce a StAX event stream corresponding to a list of events + * recorded earlier. The recorded events are generated by the inner class RecordedEventXMLStreamReader.Tag, + * which records the events in either of 2 ways: + * + * 1) in conjunction with class SDOXMLLoadImpl, it records events corresponding to the SAX events being + * handled by the SDOXMLLoadImpl when loading XML using SDOXMLResourceImpl. + * 2) when Tag.record() is called (see class ChangeSummaryStreamDeserializer), it walks through and records + * the StAX events produced by another XMLStreamReader. + * + * This class is used by the SDO StAX-based ChangeSummaryType-property loader, class + * ChangeSummaryStreamDeserializer, which is inoked by and uses (for loading deleted object XML fragments) + * the SAX-based loader class XMLResourceImpl. + */ +public abstract class RecordedEventXMLStreamReader implements XMLStreamReader { + + static private class Event { + int type; + + public NamespaceContext nameSpaceContext; + + Location location; + + protected final void initialize(XMLStreamReader reader) { + nameSpaceContext = reader.getNamespaceContext(); + location = reader.getLocation(); + } + + protected final void location(final Locator locator) { + location = new Location() { + public int getCharacterOffset() { + return -1; + } + + public int getColumnNumber() { + return locator.getColumnNumber(); + } + + public int getLineNumber() { + return locator.getLineNumber(); + } + + public String getPublicId() { + return locator.getPublicId(); + } + + public String getSystemId() { + return locator.getSystemId(); + } + }; + } + } + + static class ValueEvent extends Event { + final String value; + + protected ValueEvent(String v) { + value = v; + } + } + + static protected class Reference extends ValueEvent { + final String target; + + protected Reference(String name, String data) { + super(data); + target = name; + } + } + + static protected final class AttributeEvent extends Reference { + final QName name; + + final String nameSpace, prefix; + + int attributes; + + final boolean specified; + + protected AttributeEvent(XMLStreamReader reader) { + super(reader.getAttributeType(0), reader.getAttributeValue(0)); + attributes = reader.getAttributeCount(); + name = reader.getAttributeName(0); + nameSpace = reader.getAttributeNamespace(0); + prefix = reader.getAttributePrefix(0); + specified = reader.isAttributeSpecified(0); + } + } + + static protected final class NameSpaceEvent extends Reference { + int nameSpaces; + + protected NameSpaceEvent(XMLStreamReader reader) { + super(reader.getNamespacePrefix(0), reader.getNamespaceURI(0)); + nameSpaces = reader.getNamespaceCount(); + } + } + + static protected String prefix(String qName, String nameSpace) { + int delimiter = qName.indexOf(':'); + if (delimiter != -1) + return qName.substring(0, delimiter); + if (nameSpace.length() != 0) + return XMLConstants.DEFAULT_NS_PREFIX; + // if (nameSpaceContext.getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX) != null || xsdHelper.getGlobalProperty(null, name, element) == null) + return null; + } + + static class EndElement extends Event { + List nameSpaces/* = null */; + + public final QName name; + + public final String nameSpace; + + final String prefix; + + protected EndElement(XMLStreamReader reader) { + name = reader.getName(); + nameSpace = reader.getNamespaceURI(); + prefix = reader.getPrefix(); + int count = reader.getNamespaceCount(); + if (count == 0) + return; + nameSpaces = new ArrayList(count); + int index = 0; + do + Tag.bind(reader.getNamespacePrefix(index), reader.getNamespaceURI(index), nameSpaces); + while (++index != count); + } + + protected EndElement(String uri, String local, String p, Locator locator) { + if (p == null) { + name = new QName(uri, local, XMLConstants.DEFAULT_NS_PREFIX); + nameSpace = null; + } else { + name = new QName(uri, local, p); + nameSpace = uri; + } + prefix = p; + location(locator); + } + } + + static class NameSpace { + final String prefix, uri; + + protected NameSpace(String p, String nameSpace) { + prefix = p; + uri = nameSpace; + } + } + + static final class Attribute extends NameSpace { + final String type, value; + + final QName qName; + + boolean specified/* = false */; + + protected Attribute(String t, String v, QName name, String prefix, String nameSpace) { + super(prefix, nameSpace); + type = t; + value = v; + qName = name; + } + } + + static final class AttributeList /* implements Attributes */{// TODO exclude XMLConstants.XMLNS_ATTRIBUTE + final List attributes; + + protected AttributeList(int size) { + attributes = new ArrayList(size); + } + + /* + * @param uri Never null + */ + public final int getIndex(String uri, String localName) { + for (int index = getLength(); index != 0;) + if (getLocalName(--index).equals(localName) && uri.equals(getURI(index))) + return index; + return -1; + } + + public final int getLength() { + return attributes.size(); + } + + protected final Attribute attribute(int index) { + return (Attribute) attributes.get(index); + } + + public final String getLocalName(int index) { + return attribute(index).qName.getLocalPart(); + } + + public final String getType(int index) { + return attribute(index).type; + } + + /*public String getType(String uri, String localName) { + int index = getIndex(uri, localName); + return index == -1 ? null: getType(index); + } */ + + public final String getURI(int index) { + return attribute(index).uri; + } + + public final String getValue(int index) { + return attribute(index).value; + } + + /* + * @param uri Never null + */ + public final String getValue(String uri, String localName) { + int index = getIndex(uri, localName); + return index == -1 ? null : getValue(index); + } + } + + static protected class StartElement extends EndElement { + final AttributeList attributes; + + protected StartElement(XMLStreamReader reader) { + super(reader); + int count = reader.getAttributeCount(); + if (count == 0) + attributes = null; + else { + attributes = new AttributeList(count); + int index = 0; + do { + Attribute attribute = new Attribute(reader.getAttributeType(index), reader.getAttributeValue(index), reader + .getAttributeName(index), reader.getAttributePrefix(index), reader.getAttributeNamespace(index)); + attribute.specified = reader.isAttributeSpecified(index); + attributes.attributes.add(attribute); + } while (++index != count); + } + } + + protected StartElement(String nameSpace, String local, String prefix, Attributes attributeArray, Locator locator, List bindings, + final NamespaceContext context) { + super(nameSpace, local, prefix, locator); + nameSpaces = bindings; + nameSpaceContext = bindings == null || bindings.isEmpty() ? context : new NamespaceContext() { + public String getNamespaceURI(String prefix) { + for (int index = nameSpaces.size(); index != 0;) { + NameSpace binding = (NameSpace) nameSpaces.get(--index); + if (binding.prefix.equals(prefix)) + return binding.uri; + } + return context.getNamespaceURI(prefix); + } + + public String getPrefix(String namespaceURI) { + for (int index = nameSpaces.size(); index != 0;) { + NameSpace binding = (NameSpace) nameSpaces.get(--index); + if (binding.uri.equals(namespaceURI)) + return binding.prefix; + } + return context.getPrefix(namespaceURI); + } + + public Iterator getPrefixes(final String namespaceURI) { + final Iterator iterator = context.getPrefixes(namespaceURI); + return new Iterator() { + Iterator bindings = nameSpaces.iterator(); + + NameSpace binding/* = null */; + + protected final boolean prefix() { + while (bindings.hasNext()) { + binding = (NameSpace) bindings.next(); + if (binding.uri.equals(namespaceURI)) + return true; + } + bindings = null; + return false; + } + + public boolean hasNext() { + return bindings != null && prefix() || iterator.hasNext(); + } + + protected NameSpace nameSpace; + + public Object next() { + if (bindings == null || binding == null && !prefix()) + return iterator.next(); + nameSpace = binding; + binding = null; + return nameSpace.prefix; + } + + public void remove() { + if (bindings == null) + iterator.remove(); + else + nameSpaces.remove(nameSpace); + } + }; + } + }; + int count = attributeArray.getLength(); + if (count == 0) + attributes = null; + else { + attributes = new AttributeList(count); + int index = 0; + do { + QName name; + nameSpace = attributeArray.getURI(index); + local = attributeArray.getLocalName(index); + prefix = prefix(attributeArray.getQName(index), nameSpace); + if (prefix == null) { + name = new QName(nameSpace, local, XMLConstants.DEFAULT_NS_PREFIX); + nameSpace = null; + } else + name = new QName(nameSpace, local, prefix); + attributes.attributes.add(new Attribute(attributeArray.getType(index), attributeArray.getValue(index), name, prefix, nameSpace)); + } while (++index != count); + } + } + } + + static public class Tag extends StartElement { + public Tag(XMLStreamReader reader) { + super(reader); + initialize(reader); + } + + public List events/* = null */; // may be empty + + protected final void events() { + events = new ArrayList(); + } + + public Tag(String nameSpace, String local, String prefix, Attributes attributes, Locator locator, NamespaceContext context, List bindings) { + super(nameSpace, local, prefix, attributes, locator, bindings, context); + events(); + } + + static public void bind(String prefix, String nameSpace, Collection nameSpaces) { + nameSpaces.add(new NameSpace(prefix, nameSpace)); + } + + protected int nest/* = 0 */; + + public final void start(String nameSpace, String local, String qName, Attributes attributes, Locator locator, List bindings) { + Event event; + for (int index = events.size();/* true */;) { + if (index == 0) { + event = this; + break; + } + event = (Event) events.get(--index); + if (event.type != END_ELEMENT) + break; + siblings: for (int nest = 0;/* true */;) + switch (((Event) events.get(--index)).type) { + case START_ELEMENT: + if (nest == 0) + break siblings; + --nest; + break; + case END_ELEMENT: + ++nest; + } + } + Event start = new StartElement(nameSpace, local, prefix(qName, nameSpace), attributes, locator, bindings, event.nameSpaceContext); + start.type = START_ELEMENT; + events.add(start); + ++nest; + } + + protected final void add (Event event) + { + int index = events.size(); + event.nameSpaceContext = index == 0 ? nameSpaceContext : ((Event) events.get(--index)).nameSpaceContext; + events.add(event); + } + + public final void text(int type, String value, Locator locator) { + Event event = new ValueEvent(value); + event.type = type; + event.location(locator); + //int index = events.size(); + add(event); + } + + public final boolean end(String nameSpace, String local, String qName, Locator locator) { + Event end = new EndElement(nameSpace, local, prefix(qName, nameSpace), locator); + end.type = END_ELEMENT; + add(end); + if (nest == 0) + return true; + --nest; + return false; + } + + public final XMLStreamReader play(final XMLResource resource) { + return new RecordedEventXMLStreamReader(this) { + public void close() { + } + + public String getCharacterEncodingScheme() { + return null; // TODO + } + + public String getEncoding() { + return resource.getEncoding(); + } + + public Object getProperty(String property) { + return null; // TODO javax.xml.stream.notations & javax.xml.stream.entities for DTD + } + + public String getVersion() { + return resource.getXMLVersion(); + } + + public boolean isStandalone() { + return false; // TODO + } + + public boolean standaloneSet() { + return false; // TODO + } + }; + } + + protected final void add(Event event, int type, XMLStreamReader reader) { + event.type = type; + event.initialize(reader); + events.add(event); + } + + public final boolean record(XMLStreamReader reader) throws XMLStreamException { + events(); + for (int nest = 0; reader.hasNext();) { + Event event; + int type = reader.next(); + switch (type) { + case CHARACTERS: + case CDATA: + case COMMENT: + case SPACE: + case DTD: + event = new ValueEvent(reader.getText()); + break; + case ENTITY_REFERENCE: + event = new Reference(reader.getLocalName(), reader.getText()); + break; + case PROCESSING_INSTRUCTION: + event = new Reference(reader.getPITarget(), reader.getPIData()); + break; + case ATTRIBUTE: + event = new AttributeEvent(reader); + break; + case NAMESPACE: + event = new NameSpaceEvent(reader); + break; + case START_ELEMENT: + ++nest; + event = new StartElement(reader); + break; + case END_ELEMENT: + add(new EndElement(reader), type, reader); + if (nest == 0) + return false; + --nest; + continue; + case END_DOCUMENT: + return true; // report error? + default: // new type + event = new Event(); + } + add(event, type, reader); + } + return true; // report error? + } + + public final XMLStreamReader play(final XMLStreamReader reader) { + return new RecordedEventXMLStreamReader(this) { + public void close() throws XMLStreamException { + reader.close(); + } + + public String getCharacterEncodingScheme() { + return reader.getCharacterEncodingScheme(); + } + + public String getEncoding() { + return reader.getEncoding(); + } + + public Object getProperty(String property) { + return reader.getProperty(property); // TODO javax.xml.stream.notations & javax.xml.stream.entities for DTD + } + + public String getVersion() { + return reader.getVersion(); + } + + public boolean isStandalone() { + return reader.isStandalone(); + } + + public boolean standaloneSet() { + return reader.standaloneSet(); + } + }; + } + } + + Event event; + + final List events; + + final int size; + + protected RecordedEventXMLStreamReader(Tag tag) { + event = tag; + tag.type = START_ELEMENT; + events = tag.events; + size = events.size(); + } + + public int getAttributeCount() { + switch (getEventType()) { + case START_ELEMENT: + AttributeList attributes = ((StartElement) event).attributes; + return attributes == null ? 0 : attributes.getLength(); + case ATTRIBUTE: + return ((AttributeEvent) event).attributes; + } + throw new IllegalStateException("Neither START_ELEMENT nor ATTRIBUTE"); + } + + protected final AttributeList attributes() { + if (getEventType() == START_ELEMENT) + return ((StartElement) event).attributes; + throw new IllegalStateException("Neither START_ELEMENT nor ATTRIBUTE"); + } + + public String getAttributeLocalName(int index) { + return attributes().getLocalName(index); + } + + static Attribute attribute(AttributeList attributes, int index) { + return (Attribute) attributes.attributes.get(index); + } + + public QName getAttributeName(int index) { + return getEventType() == ATTRIBUTE ? ((AttributeEvent) event).name : attribute(attributes(), index).qName; + } + + public String getAttributeNamespace(int index) { + return getEventType() == ATTRIBUTE ? ((AttributeEvent) event).nameSpace : attributes().getURI(index); + } + + public String getAttributePrefix(int index) { + return getEventType() == ATTRIBUTE ? ((AttributeEvent) event).prefix : attribute(attributes(), index).prefix; + } + + public String getAttributeType(int index) { + return getEventType() == ATTRIBUTE ? ((Reference) event).target : attributes().getType(index); + } + + public String getAttributeValue(int index) { + return getEventType() == ATTRIBUTE ? ((ValueEvent) event).value : attributes().getValue(index); + } + + public boolean isAttributeSpecified(int index) { + if (getEventType() == ATTRIBUTE) + return ((AttributeEvent) event).specified; + AttributeList attributes = attributes(); + return attribute(attributes, index).specified; + } + + public String getAttributeValue(String nameSpace, String name) { + if (getEventType() == ATTRIBUTE) { + AttributeEvent attribute = (AttributeEvent) event; + return !attribute.name.getLocalPart().equals(name) ? null : nameSpace == null ? (attribute.nameSpace == null ? attribute.value : null) + : nameSpace.equals(attribute.nameSpace) ? attribute.value : null; + } + AttributeList attributes = attributes(); + return attributes == null ? null : attributes.getValue(nameSpace == null ? "" : nameSpace, name); + } + + protected StringBuffer buffer/* = null */; + + public String getElementText() { + if (buffer != null) + buffer.delete(0, buffer.length()); + for (;;) + switch (next()) { + case END_ELEMENT: + return buffer == null ? null : buffer.toString(); + default: + if (buffer == null) + buffer = new StringBuffer(); + buffer.append(getText()); + case PROCESSING_INSTRUCTION: + case COMMENT: + } + } + + public final int getEventType() { + return event.type; + } + + public String getLocalName() { + if (getEventType() == ENTITY_REFERENCE) + return ((Reference) event).target; + if (event instanceof EndElement) + return ((EndElement) event).name.getLocalPart(); + throw new IllegalStateException("Neither START_ELEMENT, END_ELEMENT nor ENTITY_REFERENCE"); + } + + public final Location getLocation() { + return event.location; + } + + public QName getName() { + if (hasName()) + return ((EndElement) event).name; + throw new IllegalStateException("Neither START_ELEMENT nor END_ELEMENT"); + } + + public final NamespaceContext getNamespaceContext() { + return event.nameSpaceContext; + } + + public int getNamespaceCount() { + if (getEventType() == NAMESPACE) + return ((NameSpaceEvent) event).nameSpaces; + if (!(event instanceof EndElement)) + throw new IllegalStateException("Neither START_ELEMENT, END_ELEMENT nor NAMESPACE"); + Collection nameSpaces = ((EndElement) event).nameSpaces; + return nameSpaces == null ? 0 : nameSpaces.size(); + } + + protected final NameSpace getNameSpace(int index) { + if (event instanceof EndElement) + return (NameSpace) ((EndElement) event).nameSpaces.get(index); + throw new IllegalStateException("Neither START_ELEMENT, END_ELEMENT nor NAMESPACE"); + } + + public String getNamespacePrefix(int index) { + return getEventType() == NAMESPACE ? ((Reference) event).target : getNameSpace(index).prefix; + } + + public final String getNamespaceURI() { + switch (getEventType()) { + case ATTRIBUTE: + return ((AttributeEvent) event).nameSpace; + case NAMESPACE: + return ((ValueEvent) event).value; + } + return event instanceof EndElement ? ((EndElement) event).nameSpace : null; + } + + public String getNamespaceURI(String prefix) { + return getNamespaceContext().getNamespaceURI(prefix); + } + + public String getNamespaceURI(int index) { + return getEventType() == NAMESPACE ? ((ValueEvent) event).value : getNameSpace(index).uri; + } + + public String getPIData() { + return getEventType() == PROCESSING_INSTRUCTION ? ((ValueEvent) event).value : null; + } + + public String getPITarget() { + return getEventType() == PROCESSING_INSTRUCTION ? ((Reference) event).target : null; + } + + public String getPrefix() { + switch (getEventType()) { + case ATTRIBUTE: + return ((AttributeEvent) event).prefix; + case NAMESPACE: + return ((Reference) event).target; + } + return event instanceof EndElement ? ((EndElement) event).prefix : null; + } + + public final String getText() { + if (hasText()) + return ((ValueEvent) event).value; + throw new IllegalStateException("Neither CHARACTERS, CDATA, COMMENT, SPACE, ENTITY_REFERENCE nor DTD"); + } + + public final char[] getTextCharacters() { + switch (getEventType()) { + case CHARACTERS: + case CDATA: + case COMMENT: + case SPACE: + return ((ValueEvent) event).value.toCharArray(); + } + throw new IllegalStateException("Neither CHARACTERS, CDATA, COMMENT nor SPACE"); + } + + public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) { + char[] source = getTextCharacters(); + if (sourceStart > source.length) + throw new IndexOutOfBoundsException("source start > source length"); + int sourceLen = source.length - sourceStart; + if (length > sourceLen) + length = sourceLen; + System.arraycopy(source, sourceStart, target, targetStart, length); + return sourceLen; + } + + public int getTextLength() { + return getTextCharacters().length; + } + + public int getTextStart() { + return 0; + } + + public final boolean hasName() { + return event instanceof EndElement; + } + + protected int next/* = 0 */; + + public final boolean hasNext() { + return next != size; + } + + public final boolean hasText() { + switch (getEventType()) { + case CHARACTERS: + case CDATA: + case COMMENT: + case SPACE: + case ENTITY_REFERENCE: + case DTD: + return true; + } + return false; + } + + public boolean isCharacters() { + switch (getEventType()) { + case CHARACTERS: + case CDATA: + case SPACE: + return true; + } + return false; + } + + public boolean isEndElement() { + return getEventType() == END_ELEMENT; + } + + public boolean isStartElement() { + return getEventType() == START_ELEMENT; + } + + protected final boolean areWhiteSpace() { + String text = getText(); + for (int index = text.length(); index != 0;) + if (!Character.isWhitespace(text.charAt(--index))) + return false; + return true; + } + + public boolean isWhiteSpace() { + switch (getEventType()) { + case CHARACTERS: + case CDATA: + return areWhiteSpace(); + case SPACE: + return true; + } + return false; + } + + public final int next() { + if (!hasNext()) + throw new NoSuchElementException(); + event = (Event) events.get(next++); + return event.type; + } + + protected final void throwXMLStreamException(String message) throws XMLStreamException { + throw new XMLStreamException(message, getLocation()); + } + + public int nextTag() throws XMLStreamException { + for (;;) { + int type = next(); + switch (type) { + case CHARACTERS: + case CDATA: + if (!areWhiteSpace()) + break; + case SPACE: + case PROCESSING_INSTRUCTION: + case COMMENT: + continue; + case START_ELEMENT: + case END_ELEMENT: + return type; + } + throwXMLStreamException("expected start or end tag"); + } + } + + public void require(int type, String nameSpace, String name) throws XMLStreamException { + if (getEventType() != type) + throwXMLStreamException("type not matched"); + if (nameSpace != null && !nameSpace.equals(getNamespaceURI())) + throwXMLStreamException("Name Space not matched"); + if (name != null + && !(getEventType() == ATTRIBUTE ? name.equals(((AttributeEvent) event).name.getLocalPart()) : event instanceof EndElement + && name.equals(((EndElement) event).name.getLocalPart()))) + throwXMLStreamException("name not matched"); + } +} -- cgit v1.2.3