/* * 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.sca.common.xml.stax.reader; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; 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; /** * * @version $Rev$ $Date$ */ public class XmlTreeStreamReaderImpl implements XMLStreamReader { protected int state; protected XmlNodeIterator iterator; protected XmlNode current; protected XMLStreamReader reader; /* * we need to pass in a namespace context since when delegated, we've no * idea of the current namespace context. So it needs to be passed on here! */ public XmlTreeStreamReaderImpl(XmlNode root) { this.iterator = new XmlNodeIterator(root); this.current = null; this.state = START_DOCUMENT; this.reader = null; } public void close() throws XMLStreamException { if (reader != null) { reader.close(); } } private void checkElementState() { if (getEventType() != START_ELEMENT && getEventType() != END_ELEMENT) { throw new IllegalStateException(); } } private List<XmlNode> getAttributes() { if (current != null && current.attributes() != null) { return current.attributes(); } else { return Collections.emptyList(); } } public int getAttributeCount() { checkElementState(); if (reader != null) { return reader.getAttributeCount(); } return getAttributes().size(); } public String getAttributeLocalName(int i) { checkElementState(); if (reader != null) { return reader.getAttributeLocalName(i); } return getAttributes().get(i).getName().getLocalPart(); } /** * @param i */ public QName getAttributeName(int i) { checkElementState(); if (reader != null) { return reader.getAttributeName(i); } return getAttributes().get(i).getName(); } public String getAttributeNamespace(int i) { checkElementState(); if (reader != null) { return reader.getAttributeNamespace(i); } return getAttributes().get(i).getName().getNamespaceURI(); } public String getAttributePrefix(int i) { checkElementState(); if (reader != null) { return reader.getAttributePrefix(i); } return getAttributes().get(i).getName().getPrefix(); } public String getAttributeType(int i) { if (reader != null) { return reader.getAttributeType(i); } return null; // not supported } public String getAttributeValue(int i) { checkElementState(); if (reader != null) { return reader.getAttributeValue(i); } return getAttributes().get(i).getValue(); } public String getAttributeValue(String nsUri, String localName) { checkElementState(); if (reader != null) { return reader.getAttributeValue(nsUri, localName); } int count = getAttributeCount(); String value = null; QName attrQName; for (int i = 0; i < count; i++) { attrQName = getAttributeName(i); if (nsUri == null) { if (localName.equals(attrQName.getLocalPart())) { value = getAttributeValue(i); break; } } else { if (localName.equals(attrQName.getLocalPart()) && nsUri.equals(attrQName.getNamespaceURI())) { value = getAttributeValue(i); break; } } } return value; } public String getCharacterEncodingScheme() { if (reader != null) { return reader.getCharacterEncodingScheme(); } return "UTF-8"; } public String getElementText() throws XMLStreamException { checkElementState(); if (reader != null) { return reader.getElementText(); } return current.getValue(); } public String getEncoding() { if (reader != null) { return reader.getEncoding(); } return "UTF-8"; } public int getEventType() { return state; } public String getLocalName() { checkElementState(); if (reader != null) { return reader.getLocalName(); } return current.getName().getLocalPart(); } /** */ public Location getLocation() { if (reader != null) { return reader.getLocation(); } // return a default location return new Location() { public int getCharacterOffset() { return 0; } public int getColumnNumber() { return 0; } public int getLineNumber() { return 0; } public String getPublicId() { return null; } public String getSystemId() { return null; } }; } public QName getName() { checkElementState(); if (reader != null) { return reader.getName(); } return current.getName(); } public NamespaceContext getNamespaceContext() { if (reader != null) { return reader.getNamespaceContext(); } return iterator.getNamespaceContext(); } private Map<String, String> getNamespaces() { if (current != null && current.namespaces() != null) { return current.namespaces(); } else { return Collections.emptyMap(); } } public int getNamespaceCount() { checkElementState(); if (reader != null) { return reader.getNamespaceCount(); } return getNamespaces().size(); } /** * @param i */ public String getNamespacePrefix(int i) { checkElementState(); if (reader != null) { return reader.getNamespacePrefix(i); } return new ArrayList<Map.Entry<String, String>>(getNamespaces().entrySet()).get(i).getKey(); } public String getNamespaceURI() { checkElementState(); if (reader != null) { return reader.getNamespaceURI(); } return current.getName().getNamespaceURI(); } public String getNamespaceURI(int i) { checkElementState(); if (reader != null) { return reader.getNamespaceURI(i); } return new ArrayList<Map.Entry<String, String>>(getNamespaces().entrySet()).get(i).getValue(); } public String getNamespaceURI(String prefix) { if (reader != null) { return reader.getNamespaceURI(prefix); } return getNamespaceContext().getNamespaceURI(prefix); } public String getPIData() { if (reader != null) { return reader.getPIData(); } throw new UnsupportedOperationException("Yet to be implemented !!"); } public String getPITarget() { if (reader != null) { return reader.getPITarget(); } throw new UnsupportedOperationException("Yet to be implemented !!"); } public String getPrefix() { if (reader != null) { return reader.getPrefix(); } if (state == START_ELEMENT || state == END_ELEMENT) { String prefix = current.getName().getPrefix(); return "".equals(prefix) ? null : prefix; } else if (state == START_DOCUMENT) { return null; } else { throw new IllegalStateException("State==" + state); } } /** * @param key * @throws IllegalArgumentException */ public Object getProperty(String key) throws IllegalArgumentException { if (reader != null) { return reader.getProperty(key); } return null; } public String getText() { if (reader != null) { return reader.getText(); } return current.getValue(); } public char[] getTextCharacters() { if (reader != null) { return reader.getTextCharacters(); } String value = current.getValue(); return value == null ? new char[0] : value.toCharArray(); } private int copy(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 getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { if (reader != null) { return reader.getTextCharacters(i, chars, i1, i2); } return copy(i, chars, i1, i2); } public int getTextLength() { if (reader != null) { return reader.getTextLength(); } return getTextCharacters().length; } public int getTextStart() { if (reader != null) { return reader.getTextStart(); } return 0; } public String getVersion() { return "1.0"; } public boolean hasName() { if (reader != null) { return reader.hasName(); } return current.getName() != null; } /** * @throws XMLStreamException */ public boolean hasNext() throws XMLStreamException { return iterator.hasNext() || state != END_DOCUMENT || (reader != null && reader.hasNext()); } public boolean hasText() { if (reader != null) { return reader.hasText(); } return current.getType() == XmlNode.Type.CHARACTERS; } public boolean isAttributeSpecified(int i) { if (reader != null) { return reader.isAttributeSpecified(i); } return false; // not supported } public boolean isCharacters() { if (reader != null) { return reader.isCharacters(); } return current.getType() == XmlNode.Type.CHARACTERS; } public boolean isEndElement() { if (reader != null) { return reader.isEndElement(); } return getEventType() == END_ELEMENT; } public boolean isStandalone() { return true; } public boolean isStartElement() { if (reader != null) { return reader.isStartElement(); } return getEventType() == START_ELEMENT; } public boolean isWhiteSpace() { if (reader != null) { return reader.isWhiteSpace(); } return false; } /** * By far this should be the most important method in this class this method * changes the state of the parser */ public int next() throws XMLStreamException { if (!hasNext()) { throw new IllegalStateException("No more events"); } if (reader != null) { if (!reader.hasNext()) { this.reader = null; } else { // Go to the delegation mode state = reader.next(); return state; } } if (!iterator.hasNext()) { state = END_DOCUMENT; current = null; return state; } current = iterator.next(); XmlNode.Type type = current.getType(); int itState = iterator.getState(); if (itState == XmlNodeIterator.END) { if (type == XmlNode.Type.ELEMENT) { state = END_ELEMENT; } else { // Ignore the pop state = next(); } } if (itState == XmlNodeIterator.START) { if (type == XmlNode.Type.ELEMENT) { state = START_ELEMENT; } else if (type == XmlNode.Type.CHARACTERS) { state = CHARACTERS; } else if (type == XmlNode.Type.READER) { XMLStreamReader value = current.getValue(); this.reader = new WrappingXMLStreamReader(value); state = reader.getEventType(); return state; } } return state; } /** * TODO implement this * * @throws XMLStreamException */ public int nextTag() throws XMLStreamException { while (true) { int event = next(); if (event == START_ELEMENT || event == END_ELEMENT) { return event; } } } public void require(int i, String ns, String localPart) throws XMLStreamException { if (reader != null) { reader.require(i, ns, localPart); return; } int event = getEventType(); if (event != i) { throw new IllegalStateException("Event type is " + event + " (!=" + i + ")"); } QName name = getName(); String ns1 = name.getNamespaceURI(); String localName1 = name.getLocalPart(); if (ns != null && !ns.equals(ns1)) { throw new IllegalStateException("Namespace URI is " + ns1 + " (!=" + ns + ")"); } if (localPart != null && !localPart.equals(localName1)) { throw new IllegalStateException("Local name is " + localName1 + " (!=" + localPart + ")"); } } public boolean standaloneSet() { return true; } }