/* QuiXProc: efficient evaluation of XProc Pipelines. Copyright (C) 2011-2015 Innovimax All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package innovimax.quixproc.datamodel.convert; import java.util.ArrayList; import java.util.List; import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; import javax.xml.stream.Location; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import innovimax.quixproc.datamodel.QuiXException; import innovimax.quixproc.datamodel.event.AQuiXEvent; import innovimax.quixproc.datamodel.event.AQuiXEvent.Attribute; import innovimax.quixproc.datamodel.event.AQuiXEvent.Namespace; import innovimax.quixproc.datamodel.event.IQuiXEventStreamReader; public class QuiXEventStream2XMLStreamReader implements XMLStreamReader { private final IQuiXEventStreamReader qs; private static final boolean DEBUG = false; private static final int POSITION = 1; public QuiXEventStream2XMLStreamReader(IQuiXEventStreamReader qs) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); this.qs = qs; } @Override public Object getProperty(String name) throws IllegalArgumentException { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return null; } @Override public boolean hasNext() throws XMLStreamException { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); if (this.future != null) return true; try { return this.qs.hasNext(); } catch (QuiXException e) { throw new XMLStreamException(e); } } private AQuiXEvent current = null; private AQuiXEvent future = null; private final List<Namespace> namespaces = new ArrayList<Namespace>(); private final List<Attribute> attributes = new ArrayList<Attribute>(); @Override public int next() throws XMLStreamException { try { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); if (DEBUG) System.out.println("QuixStreamReader.next : (" + this.future + "," + this.current + ")"); while (this.future != null || this.qs.hasNext()) { if (this.future != null) { this.current = this.future; this.future = null; } else { this.current = this.qs.next(); } switch (this.current.getType()) { case START_SEQUENCE: // DO NOTHING : should be already processed by caller break; case END_SEQUENCE: // DO NOTHING : should be already processed by caller break; case START_DOCUMENT: return XMLStreamConstants.START_DOCUMENT; case END_DOCUMENT: return XMLStreamConstants.END_DOCUMENT; case START_ELEMENT: // get the attributes if any this.attributes.clear(); this.namespaces.clear(); while (true) { boolean test = this.qs.hasNext(); if (!test) throw new QuiXException("Impossible"); this.future = this.qs.next(); if (this.future.isAttribute()) { this.attributes.add(this.future.asAttribute()); } else if (this.future.isNamespace()) { this.namespaces.add(this.future.asNamespace()); } else { break; } } return XMLStreamConstants.START_ELEMENT; case END_ELEMENT: return XMLStreamConstants.END_ELEMENT; case ATTRIBUTE: // This should never happen since attribute are // processed // DO NOTHING break; case COMMENT: return XMLStreamConstants.COMMENT; case PROCESSING_INSTRUCTION: return XMLStreamConstants.PROCESSING_INSTRUCTION; case TEXT: return XMLStreamConstants.CHARACTERS; default: } } } catch (QuiXException e) { throw new XMLStreamException(e); } return XMLStreamConstants.END_DOCUMENT; } @Override public void require(int type, String namespaceURI, String localName) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); throw new RuntimeException("no such method"); } @Override public String getElementText() throws XMLStreamException { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); if (getEventType() != XMLStreamConstants.START_ELEMENT) { throw new XMLStreamException("parser must be on START_ELEMENT to read next text", getLocation()); } int eventType = next(); StringBuilder content = new StringBuilder(); while (eventType != XMLStreamConstants.END_ELEMENT) { if (eventType == XMLStreamConstants.CHARACTERS || eventType == XMLStreamConstants.CDATA || eventType == XMLStreamConstants.SPACE || eventType == XMLStreamConstants.ENTITY_REFERENCE) { content.append(getText()); } else if (eventType == XMLStreamConstants.PROCESSING_INSTRUCTION || eventType == XMLStreamConstants.COMMENT) { // skipping } else if (eventType == XMLStreamConstants.END_DOCUMENT) { throw new XMLStreamException("unexpected end of document when reading element text content", getLocation()); } else if (eventType == XMLStreamConstants.START_ELEMENT) { throw new XMLStreamException("element text content may not contain START_ELEMENT", getLocation()); } else { throw new XMLStreamException("Unexpected event type " + eventType, getLocation()); } eventType = next(); } return content.toString(); } @Override public int nextTag() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); throw new RuntimeException("no such method"); } @Override public void close() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); this.qs.close(); } @Override public String getNamespaceURI(String prefix) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return null; } @Override public boolean isStartElement() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.current.isStartElement(); } @Override public boolean isEndElement() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.current.isEndElement(); } @Override public boolean isCharacters() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.current.isText(); } @Override public boolean isWhiteSpace() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return false; } @Override public String getAttributeValue(String namespaceURI, String localName) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); for (Attribute attribute : this.attributes) { // TODO compare between String and QuiXCharStream if (localName.equals(attribute.getLocalName()) && namespaceURI.equals(attribute.getURI())) return attribute.getValue().toString(); } return null; } @Override public int getAttributeCount() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.attributes.size(); } @Override public QName getAttributeName(int index) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.attributes.get(index).getQName().asQName(); } @Override public String getAttributeNamespace(int index) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.attributes.get(index).getURI().toString(); } @Override public String getAttributeLocalName(int index) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.attributes.get(index).getLocalName().toString(); } @Override public String getAttributePrefix(int index) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.attributes.get(index).getPrefix().toString(); } @Override public String getAttributeType(int index) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return null; // no type stored } @Override public String getAttributeValue(int index) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.attributes.get(index).getValue().toString(); } @Override public boolean isAttributeSpecified(int index) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return true; } @Override public int getNamespaceCount() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.namespaces.size(); } @Override public String getNamespacePrefix(int index) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.namespaces.get(index).getPrefix().toString(); } @Override public String getNamespaceURI(int index) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return this.namespaces.get(index).getURI().toString(); } @Override public NamespaceContext getNamespaceContext() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return null; } @Override public int getEventType() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); if (this.current == null) return XMLStreamConstants.START_DOCUMENT; switch (this.current.getType()) { case START_DOCUMENT: return XMLStreamConstants.START_DOCUMENT; case END_DOCUMENT: return XMLStreamConstants.END_DOCUMENT; case START_ELEMENT: return XMLStreamConstants.START_ELEMENT; case END_ELEMENT: return XMLStreamConstants.END_ELEMENT; case ATTRIBUTE: return XMLStreamConstants.ATTRIBUTE; // Not really possible case COMMENT: return XMLStreamConstants.COMMENT; case PROCESSING_INSTRUCTION: return XMLStreamConstants.PROCESSING_INSTRUCTION; case TEXT: return XMLStreamConstants.CHARACTERS; case START_SEQUENCE: // Not Possible break; case END_SEQUENCE: // Not Possible break; default: } return 0; } @Override public String getText() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // Returns the current value of the parse event as a string, // this returns the string value of a CHARACTERS event, // returns the value of a COMMENT, // the replacement value for an ENTITY_REFERENCE, // the string value of a CDATA section, // the string value for a SPACE event, // or the String value of the internal subset of the DTD. // If an ENTITY_REFERENCE has been resolved, any character data will be // reported as CHARACTERS events. switch (this.current.getType()) { case TEXT: return this.current.asText().getData().toString(); case COMMENT: return this.current.asComment().getData().toString(); default: } return null; } @Override public char[] getTextCharacters() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); String text = getText(); return (text == null ? null : text.toCharArray()); } @Override public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName() + "+++"); // TODO Auto-generated method stub return 0; } @Override public int getTextStart() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return 0; } @Override public int getTextLength() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return getText().length(); } @Override public String getEncoding() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return null; } @Override public boolean hasText() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // return true if the current event has text, false otherwise // The following events have text: // CHARACTERS,DTD // ,ENTITY_REFERENCE, COMMENT, SPACE // TODO Auto-generated method stub return this.current.isText() || this.current.isComment(); } @Override public Location getLocation() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Put real info here return new Location() { @Override public int getLineNumber() { // TODO Auto-generated method stub return 0; } @Override public int getColumnNumber() { // TODO Auto-generated method stub return 0; } @Override public int getCharacterOffset() { // TODO Auto-generated method stub return 0; } @Override public String getPublicId() { // TODO Auto-generated method stub return null; } @Override public String getSystemId() { // TODO Auto-generated method stub return null; } }; } @Override public QName getName() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); switch (this.current.getType()) { case START_ELEMENT: case END_ELEMENT: return this.current.asNamedEvent().getQName().asQName(); default: } return null; } @Override public String getLocalName() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); switch (this.current.getType()) { case START_ELEMENT: case END_ELEMENT: return this.current.asNamedEvent().getLocalName().toString(); default: } return null; } @Override public boolean hasName() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.current.isStartElement() || this.current.isEndElement(); } @Override public String getNamespaceURI() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); switch (this.current.getType()) { case START_ELEMENT: case END_ELEMENT: return this.current.asNamedEvent().getURI().toString(); default: } return null; } @Override public String getPrefix() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); switch (this.current.getType()) { case START_ELEMENT: case END_ELEMENT: return this.current.asNamedEvent().getPrefix().toString(); default: } return null; } @Override public String getVersion() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return null; } @Override public boolean isStandalone() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return false; } @Override public boolean standaloneSet() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return false; } @Override public String getCharacterEncodingScheme() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); // TODO Auto-generated method stub return null; } @Override public String getPITarget() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.current.asPI().getTarget().toString(); } @Override public String getPIData() { if (DEBUG) System.out.println(Thread.currentThread().getStackTrace()[POSITION].getMethodName()); return this.current.asPI().getData().toString(); } }