diff --git a/src/main/java/org/jboss/staxmapper/FixedXMLStreamReader.java b/src/main/java/org/jboss/staxmapper/FixedXMLStreamReader.java
index b1463ba..8fc4f60 100644
--- a/src/main/java/org/jboss/staxmapper/FixedXMLStreamReader.java
+++ b/src/main/java/org/jboss/staxmapper/FixedXMLStreamReader.java
@@ -1,221 +1,266 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.staxmapper;
-
-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;
-
-/**
- * @author David M. Lloyd
- */
-final class FixedXMLStreamReader implements XMLStreamReader {
-
- private final XMLStreamReader delegate;
-
- FixedXMLStreamReader(final XMLStreamReader delegate) {
- this.delegate = delegate;
- }
-
- public Object getProperty(final String name) throws IllegalArgumentException {
- return delegate.getProperty(name);
- }
-
- public int next() throws XMLStreamException {
- throw new UnsupportedOperationException();
- }
-
- public void require(final int type, final String namespaceURI, final String localName) throws XMLStreamException {
- delegate.require(type, namespaceURI, localName);
- }
-
- public String getElementText() throws XMLStreamException {
- return delegate.getElementText();
- }
-
- public int nextTag() throws XMLStreamException {
- throw new UnsupportedOperationException();
- }
-
- public boolean hasNext() throws XMLStreamException {
- return delegate.hasNext();
- }
-
- public void close() throws XMLStreamException {
- throw new UnsupportedOperationException();
- }
-
- public String getNamespaceURI(final String prefix) {
- return delegate.getNamespaceURI(prefix);
- }
-
- public boolean isStartElement() {
- return delegate.isStartElement();
- }
-
- public boolean isEndElement() {
- return delegate.isEndElement();
- }
-
- public boolean isCharacters() {
- return delegate.isCharacters();
- }
-
- public boolean isWhiteSpace() {
- return delegate.isWhiteSpace();
- }
-
- public String getAttributeValue(final String namespaceURI, final String localName) {
- return delegate.getAttributeValue(namespaceURI, localName);
- }
-
- public int getAttributeCount() {
- return delegate.getAttributeCount();
- }
-
- public QName getAttributeName(final int index) {
- return delegate.getAttributeName(index);
- }
-
- public String getAttributeNamespace(final int index) {
- return delegate.getAttributeNamespace(index);
- }
-
- public String getAttributeLocalName(final int index) {
- return delegate.getAttributeLocalName(index);
- }
-
- public String getAttributePrefix(final int index) {
- return delegate.getAttributePrefix(index);
- }
-
- public String getAttributeType(final int index) {
- return delegate.getAttributeType(index);
- }
-
- public String getAttributeValue(final int index) {
- return delegate.getAttributeValue(index);
- }
-
- public boolean isAttributeSpecified(final int index) {
- return delegate.isAttributeSpecified(index);
- }
-
- public int getNamespaceCount() {
- return delegate.getNamespaceCount();
- }
-
- public String getNamespacePrefix(final int index) {
- return delegate.getNamespacePrefix(index);
- }
-
- public String getNamespaceURI(final int index) {
- return delegate.getNamespaceURI(index);
- }
-
- public NamespaceContext getNamespaceContext() {
- return delegate.getNamespaceContext();
- }
-
- public int getEventType() {
- return delegate.getEventType();
- }
-
- public String getText() {
- return delegate.getText();
- }
-
- public char[] getTextCharacters() {
- return delegate.getTextCharacters();
- }
-
- public int getTextCharacters(final int sourceStart, final char[] target, final int targetStart, final int length) throws XMLStreamException {
- return delegate.getTextCharacters(sourceStart, target, targetStart, length);
- }
-
- public int getTextStart() {
- return delegate.getTextStart();
- }
-
- public int getTextLength() {
- return delegate.getTextLength();
- }
-
- public String getEncoding() {
- return delegate.getEncoding();
- }
-
- public boolean hasText() {
- return delegate.hasText();
- }
-
- public Location getLocation() {
- return delegate.getLocation();
- }
-
- public QName getName() {
- return delegate.getName();
- }
-
- public String getLocalName() {
- return delegate.getLocalName();
- }
-
- public boolean hasName() {
- return delegate.hasName();
- }
-
- public String getNamespaceURI() {
- return delegate.getNamespaceURI();
- }
-
- public String getPrefix() {
- return delegate.getPrefix();
- }
-
- public String getVersion() {
- return delegate.getVersion();
- }
-
- public boolean isStandalone() {
- return delegate.isStandalone();
- }
-
- public boolean standaloneSet() {
- return delegate.standaloneSet();
- }
-
- public String getCharacterEncodingScheme() {
- return delegate.getCharacterEncodingScheme();
- }
-
- public String getPITarget() {
- return delegate.getPITarget();
- }
-
- public String getPIData() {
- return delegate.getPIData();
- }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.staxmapper;
+
+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;
+
+/**
+ * @author David M. Lloyd
+ */
+final class FixedXMLStreamReader implements XMLStreamReader {
+
+ private final XMLStreamReader delegate;
+
+ FixedXMLStreamReader(final XMLStreamReader delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public Object getProperty(final String name) throws IllegalArgumentException {
+ return delegate.getProperty(name);
+ }
+
+ @Override
+ public int next() throws XMLStreamException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void require(final int type, final String namespaceURI, final String localName) throws XMLStreamException {
+ delegate.require(type, namespaceURI, localName);
+ }
+
+ @Override
+ public String getElementText() throws XMLStreamException {
+ return delegate.getElementText();
+ }
+
+ @Override
+ public int nextTag() throws XMLStreamException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean hasNext() throws XMLStreamException {
+ return delegate.hasNext();
+ }
+
+ @Override
+ public void close() throws XMLStreamException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getNamespaceURI(final String prefix) {
+ return delegate.getNamespaceURI(prefix);
+ }
+
+ @Override
+ public boolean isStartElement() {
+ return delegate.isStartElement();
+ }
+
+ @Override
+ public boolean isEndElement() {
+ return delegate.isEndElement();
+ }
+
+ @Override
+ public boolean isCharacters() {
+ return delegate.isCharacters();
+ }
+
+ @Override
+ public boolean isWhiteSpace() {
+ return delegate.isWhiteSpace();
+ }
+
+ @Override
+ public String getAttributeValue(final String namespaceURI, final String localName) {
+ return delegate.getAttributeValue(namespaceURI, localName);
+ }
+
+ @Override
+ public int getAttributeCount() {
+ return delegate.getAttributeCount();
+ }
+
+ @Override
+ public QName getAttributeName(final int index) {
+ return delegate.getAttributeName(index);
+ }
+
+ @Override
+ public String getAttributeNamespace(final int index) {
+ return delegate.getAttributeNamespace(index);
+ }
+
+ @Override
+ public String getAttributeLocalName(final int index) {
+ return delegate.getAttributeLocalName(index);
+ }
+
+ @Override
+ public String getAttributePrefix(final int index) {
+ return delegate.getAttributePrefix(index);
+ }
+
+ @Override
+ public String getAttributeType(final int index) {
+ return delegate.getAttributeType(index);
+ }
+
+ @Override
+ public String getAttributeValue(final int index) {
+ return delegate.getAttributeValue(index);
+ }
+
+ @Override
+ public boolean isAttributeSpecified(final int index) {
+ return delegate.isAttributeSpecified(index);
+ }
+
+ @Override
+ public int getNamespaceCount() {
+ return delegate.getNamespaceCount();
+ }
+
+ @Override
+ public String getNamespacePrefix(final int index) {
+ return delegate.getNamespacePrefix(index);
+ }
+
+ @Override
+ public String getNamespaceURI(final int index) {
+ return delegate.getNamespaceURI(index);
+ }
+
+ @Override
+ public NamespaceContext getNamespaceContext() {
+ return delegate.getNamespaceContext();
+ }
+
+ @Override
+ public int getEventType() {
+ return delegate.getEventType();
+ }
+
+ @Override
+ public String getText() {
+ return delegate.getText();
+ }
+
+ @Override
+ public char[] getTextCharacters() {
+ return delegate.getTextCharacters();
+ }
+
+ @Override
+ public int getTextCharacters(final int sourceStart, final char[] target, final int targetStart, final int length) throws XMLStreamException {
+ return delegate.getTextCharacters(sourceStart, target, targetStart, length);
+ }
+
+ @Override
+ public int getTextStart() {
+ return delegate.getTextStart();
+ }
+
+ @Override
+ public int getTextLength() {
+ return delegate.getTextLength();
+ }
+
+ @Override
+ public String getEncoding() {
+ return delegate.getEncoding();
+ }
+
+ @Override
+ public boolean hasText() {
+ return delegate.hasText();
+ }
+
+ @Override
+ public Location getLocation() {
+ return delegate.getLocation();
+ }
+
+ @Override
+ public QName getName() {
+ return delegate.getName();
+ }
+
+ @Override
+ public String getLocalName() {
+ return delegate.getLocalName();
+ }
+
+ @Override
+ public boolean hasName() {
+ return delegate.hasName();
+ }
+
+ @Override
+ public String getNamespaceURI() {
+ return delegate.getNamespaceURI();
+ }
+
+ @Override
+ public String getPrefix() {
+ return delegate.getPrefix();
+ }
+
+ @Override
+ public String getVersion() {
+ return delegate.getVersion();
+ }
+
+ @Override
+ public boolean isStandalone() {
+ return delegate.isStandalone();
+ }
+
+ @Override
+ public boolean standaloneSet() {
+ return delegate.standaloneSet();
+ }
+
+ @Override
+ public String getCharacterEncodingScheme() {
+ return delegate.getCharacterEncodingScheme();
+ }
+
+ @Override
+ public String getPITarget() {
+ return delegate.getPITarget();
+ }
+
+ @Override
+ public String getPIData() {
+ return delegate.getPIData();
+ }
+}
diff --git a/src/main/java/org/jboss/staxmapper/FormattingXMLStreamWriter.java b/src/main/java/org/jboss/staxmapper/FormattingXMLStreamWriter.java
index 816a5d5..a731d75 100644
--- a/src/main/java/org/jboss/staxmapper/FormattingXMLStreamWriter.java
+++ b/src/main/java/org/jboss/staxmapper/FormattingXMLStreamWriter.java
@@ -1,528 +1,500 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.staxmapper;
-
-import java.lang.reflect.UndeclaredThrowableException;
-import java.util.ArrayDeque;
-import java.util.Iterator;
-
-import javax.xml.namespace.NamespaceContext;
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-
-/**
- * An XML stream writer which nicely formats the XML for configuration files.
- *
- * @author David M. Lloyd
- */
-public final class FormattingXMLStreamWriter implements XMLExtendedStreamWriter, XMLStreamConstants {
- private static final String NO_NAMESPACE = new String();
- private final XMLStreamWriter delegate;
- private final ArrayDeque attrQueue = new ArrayDeque();
- private int level;
- private int state = START_DOCUMENT;
- private boolean indentEndElement = false;
- private ArrayDeque unspecifiedNamespaces = new ArrayDeque();
-
-
- public FormattingXMLStreamWriter(final XMLStreamWriter delegate) {
- this.delegate = delegate;
- unspecifiedNamespaces.push(NO_NAMESPACE);
- }
-
- private void nl() throws XMLStreamException {
- delegate.writeCharacters("\n");
- }
-
- private void indent() throws XMLStreamException {
- int level = this.level;
- final XMLStreamWriter delegate = this.delegate;
- for (int i = 0; i < level; i ++) {
- delegate.writeCharacters(" ");
- }
- }
-
- private interface ArgRunnable {
- void run(int arg) throws XMLStreamException;
- }
-
- @Override
- public void setUnspecifiedElementNamespace(final String namespace) {
- ArrayDeque namespaces = this.unspecifiedNamespaces;
- namespaces.pop();
- namespaces.push(namespace == null ? NO_NAMESPACE : namespace);
- }
-
- private String nestUnspecifiedNamespace() {
- ArrayDeque namespaces = unspecifiedNamespaces;
- String clone = namespaces.getFirst();
- namespaces.push(clone);
- return clone;
- }
-
- @Override
- public void writeStartElement(final String localName) throws XMLStreamException {
- ArrayDeque namespaces = unspecifiedNamespaces;
- String namespace = namespaces.getFirst();
- if (namespace != NO_NAMESPACE) {
- writeStartElement(namespace, localName);
- return;
- }
-
- unspecifiedNamespaces.push(namespace);
-
- // If this is a nested element flush the outer
- runAttrQueue();
- nl();
- indent();
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- if (arg == 0) {
- delegate.writeStartElement(localName);
- } else {
- delegate.writeEmptyElement(localName);
- }
- }
- });
-
- level++;
- state = START_ELEMENT;
- indentEndElement = false;
- }
-
- @Override
- public void writeStartElement(final String namespaceURI, final String localName) throws XMLStreamException {
- nestUnspecifiedNamespace();
-
- // If this is a nested element flush the outer
- runAttrQueue();
- nl();
- indent();
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- if (arg == 0) {
- delegate.writeStartElement(namespaceURI, localName);
- } else {
- delegate.writeEmptyElement(namespaceURI, localName);
- }
- }
- });
- level++;
- state = START_ELEMENT;
- indentEndElement = false;
- }
-
- @Override
- public void writeStartElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
- nestUnspecifiedNamespace();
-
- // If this is a nested element flush the outer
- runAttrQueue();
- nl();
- indent();
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- if (arg == 0) {
- delegate.writeStartElement(prefix, namespaceURI, localName);
- } else {
- delegate.writeEmptyElement(prefix, namespaceURI, localName);
- }
- }
- });
- level++;
- state = START_ELEMENT;
- indentEndElement = false;
- }
-
- @Override
- public void writeEmptyElement(final String namespaceURI, final String localName) throws XMLStreamException {
- runAttrQueue();
- nl();
- indent();
- delegate.writeEmptyElement(namespaceURI, localName);
- state = END_ELEMENT;
- }
-
- @Override
- public void writeEmptyElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
- runAttrQueue();
- nl();
- indent();
- delegate.writeEmptyElement(prefix, namespaceURI, localName);
- state = END_ELEMENT;
- }
-
- @Override
- public void writeEmptyElement(final String localName) throws XMLStreamException {
- String namespace = unspecifiedNamespaces.getFirst();
- if (namespace != NO_NAMESPACE) {
- writeEmptyElement(namespace, localName);
- return;
- }
-
- runAttrQueue();
- nl();
- indent();
- delegate.writeEmptyElement(localName);
- state = END_ELEMENT;
- }
-
- @Override
- public void writeEndElement() throws XMLStreamException {
- level--;
- if (state != START_ELEMENT) {
- runAttrQueue();
- if (state != CHARACTERS || indentEndElement) {
- nl();
- indent();
- indentEndElement = false;
- }
- delegate.writeEndElement();
- } else {
- // Change the start element to an empty element
- ArgRunnable start = attrQueue.poll();
- if (start == null) {
- delegate.writeEndElement();
- } else {
- start.run(1);
- // Write everything else
- runAttrQueue();
- }
- }
-
- unspecifiedNamespaces.pop();
- state = END_ELEMENT;
- }
-
- private void runAttrQueue() throws XMLStreamException {
- ArgRunnable attr;
- while ((attr = attrQueue.poll()) != null) {
- attr.run(0);
- }
- }
-
- @Override
- public void writeEndDocument() throws XMLStreamException {
- delegate.writeEndDocument();
- state = END_DOCUMENT;
- }
-
- @Override
- public void close() throws XMLStreamException {
- delegate.close();
- state = END_DOCUMENT;
- }
-
- @Override
- public void flush() throws XMLStreamException {
- delegate.flush();
- }
-
- @Override
- public void writeAttribute(final String localName, final String value) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- try {
- delegate.writeAttribute(localName, value);
- } catch (XMLStreamException e) {
- throw new UndeclaredThrowableException(e);
- }
- }
- });
- }
-
- @Override
- public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final String value) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeAttribute(prefix, namespaceURI, localName, value);
- }
- });
- }
-
- @Override
- public void writeAttribute(final String namespaceURI, final String localName, final String value) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeAttribute(namespaceURI, localName, value);
- }
- });
- }
-
- @Override
- public void writeAttribute(final String localName, final String[] values) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeAttribute(localName, join(values));
- }
- });
- }
-
- @Override
- public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final String[] values) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeAttribute(prefix, namespaceURI, localName, join(values));
- }
- });
- }
-
- @Override
- public void writeAttribute(final String namespaceURI, final String localName, final String[] values) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeAttribute(namespaceURI, localName, join(values));
- }
- });
- }
-
- @Override
- public void writeAttribute(final String localName, final Iterable values) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeAttribute(localName, join(values));
- }
- });
- }
-
- @Override
- public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final Iterable values) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeAttribute(prefix, namespaceURI, localName, join(values));
- }
- });
- }
-
- @Override
- public void writeAttribute(final String namespaceURI, final String localName, final Iterable values) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeAttribute(namespaceURI, localName, join(values));
- }
- });
- }
-
- @Override
- public void writeNamespace(final String prefix, final String namespaceURI) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeNamespace(prefix, namespaceURI);
- }
- });
- }
-
- @Override
- public void writeDefaultNamespace(final String namespaceURI) throws XMLStreamException {
- attrQueue.add(new ArgRunnable() {
- public void run(int arg) throws XMLStreamException {
- delegate.writeDefaultNamespace(namespaceURI);
- }
- });
- }
-
- @Override
- public void writeComment(final String data) throws XMLStreamException {
- runAttrQueue();
- nl();
- indent();
- final StringBuilder b = new StringBuilder(data.length());
- final Iterator i = Spliterator.over(data, '\n');
- if (! i.hasNext()) {
- return;
- } else {
- final String first = i.next();
- if (! i.hasNext()) {
- delegate.writeComment(" " + first + " ");
- state = COMMENT;
- return;
- } else {
- b.append('\n');
- for (int q = 0; q < level; q++) {
- b.append(" ");
- }
- b.append(" ~ ");
- b.append(first);
- do {
- b.append('\n');
- for (int q = 0; q < level; q++) {
- b.append(" ");
- }
- b.append(" ~ ");
- b.append(i.next());
- } while (i.hasNext());
- }
- b.append('\n');
- for (int q = 0; q < level; q ++) {
- b.append(" ");
- }
- b.append(" ");
- delegate.writeComment(b.toString());
- state = COMMENT;
- }
- }
-
- @Override
- public void writeProcessingInstruction(final String target) throws XMLStreamException {
- runAttrQueue();
- nl();
- indent();
- delegate.writeProcessingInstruction(target);
- state = PROCESSING_INSTRUCTION;
- }
-
- @Override
- public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
- runAttrQueue();
- nl();
- indent();
- delegate.writeProcessingInstruction(target, data);
- state = PROCESSING_INSTRUCTION;
- }
-
- @Override
- public void writeCData(final String data) throws XMLStreamException {
- runAttrQueue();
- delegate.writeCData(data);
- state = CDATA;
- }
-
- @Override
- public void writeDTD(final String dtd) throws XMLStreamException {
- nl();
- indent();
- delegate.writeDTD(dtd);
- state = DTD;
- }
-
- @Override
- public void writeEntityRef(final String name) throws XMLStreamException {
- runAttrQueue();
- delegate.writeEntityRef(name);
- state = ENTITY_REFERENCE;
- }
-
- @Override
- public void writeStartDocument() throws XMLStreamException {
- delegate.writeStartDocument();
- state = START_DOCUMENT;
- }
-
- @Override
- public void writeStartDocument(final String version) throws XMLStreamException {
- delegate.writeStartDocument(version);
- state = START_DOCUMENT;
- }
-
- @Override
- public void writeStartDocument(final String encoding, final String version) throws XMLStreamException {
- delegate.writeStartDocument(encoding, version);
- state = START_DOCUMENT;
- }
-
- @Override
- public void writeCharacters(final String text) throws XMLStreamException {
- runAttrQueue();
- if (state != CHARACTERS) {
- nl();
- indent();
- }
- final Iterator iterator = Spliterator.over(text, '\n');
- while (iterator.hasNext()) {
- final String t = iterator.next();
- delegate.writeCharacters(t);
- if (iterator.hasNext()) {
- nl();
- indent();
- }
- }
- state = CHARACTERS;
- indentEndElement = true;
- }
-
- @Override
- public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
- runAttrQueue();
- delegate.writeCharacters(text, start, len);
- state = CHARACTERS;
- }
-
- @Override
- public String getPrefix(final String uri) throws XMLStreamException {
- return delegate.getPrefix(uri);
- }
-
- @Override
- public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
- delegate.setPrefix(prefix, uri);
- }
-
- @Override
- public void setDefaultNamespace(final String uri) throws XMLStreamException {
- runAttrQueue();
- delegate.setDefaultNamespace(uri);
- }
-
- @Override
- public void setNamespaceContext(final NamespaceContext context) throws XMLStreamException {
- delegate.setNamespaceContext(context);
- }
-
- @Override
- public NamespaceContext getNamespaceContext() {
- return delegate.getNamespaceContext();
- }
-
- @Override
- public Object getProperty(final String name) throws IllegalArgumentException {
- return delegate.getProperty(name);
- }
-
- private static String join(final String[] values) {
- final StringBuilder b = new StringBuilder();
- for (int i = 0, valuesLength = values.length; i < valuesLength; i++) {
- final String s = values[i];
- if (s != null) {
- if (i > 0) {
- b.append(' ');
- }
- b.append(s);
- }
- }
- return b.toString();
- }
-
- private static String join(final Iterable values) {
- final StringBuilder b = new StringBuilder();
- Iterator iterator = values.iterator();
- while (iterator.hasNext()) {
- final String s = iterator.next();
- if (s != null) {
- b.append(s);
- if (iterator.hasNext()) b.append(' ');
- }
- }
- return b.toString();
- }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.staxmapper;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.ArrayDeque;
+import java.util.Iterator;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+/**
+ * An XML stream writer which nicely formats the XML for configuration files.
+ *
+ * @author David M. Lloyd
+ */
+public final class FormattingXMLStreamWriter implements XMLExtendedStreamWriter, XMLStreamConstants {
+ private static final String NO_NAMESPACE = new String();
+ private final XMLStreamWriter delegate;
+ private final ArrayDeque attrQueue = new ArrayDeque<>();
+ private int level;
+ private int state = START_DOCUMENT;
+ private boolean indentEndElement = false;
+ private ArrayDeque unspecifiedNamespaces = new ArrayDeque<>();
+
+
+ public FormattingXMLStreamWriter(final XMLStreamWriter delegate) {
+ this.delegate = delegate;
+ unspecifiedNamespaces.push(NO_NAMESPACE);
+ }
+
+ private void nl() throws XMLStreamException {
+ delegate.writeCharacters("\r\n");
+ }
+
+ private void indent() throws XMLStreamException {
+ int level = this.level;
+ final XMLStreamWriter delegate = this.delegate;
+ for (int i = 0; i < level; i ++) {
+ delegate.writeCharacters(" ");
+ }
+ }
+
+ private interface ArgRunnable {
+ void run(int arg) throws XMLStreamException;
+ }
+
+ @Override
+ public void setUnspecifiedElementNamespace(final String namespace) {
+ ArrayDeque namespaces = this.unspecifiedNamespaces;
+ namespaces.pop();
+ namespaces.push(namespace == null ? NO_NAMESPACE : namespace);
+ }
+
+ private String nestUnspecifiedNamespace() {
+ ArrayDeque namespaces = unspecifiedNamespaces;
+ String clone = namespaces.getFirst();
+ namespaces.push(clone);
+ return clone;
+ }
+
+ @Override
+ public void writeStartElement(final String localName) throws XMLStreamException {
+ ArrayDeque namespaces = unspecifiedNamespaces;
+ String namespace = namespaces.getFirst();
+ if (namespace != NO_NAMESPACE) {
+ writeStartElement(namespace, localName);
+ return;
+ }
+
+ unspecifiedNamespaces.push(namespace);
+
+ // If this is a nested element flush the outer
+ runAttrQueue();
+ nl();
+ indent();
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ if (arg == 0) {
+ delegate.writeStartElement(localName);
+ } else {
+ delegate.writeEmptyElement(localName);
+ }
+ });
+
+ level++;
+ state = START_ELEMENT;
+ indentEndElement = false;
+ }
+
+ @Override
+ public void writeStartElement(final String namespaceURI, final String localName) throws XMLStreamException {
+ nestUnspecifiedNamespace();
+
+ // If this is a nested element flush the outer
+ runAttrQueue();
+ nl();
+ indent();
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ if (arg == 0) {
+ delegate.writeStartElement(namespaceURI, localName);
+ } else {
+ delegate.writeEmptyElement(namespaceURI, localName);
+ }
+ });
+ level++;
+ state = START_ELEMENT;
+ indentEndElement = false;
+ }
+
+ @Override
+ public void writeStartElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
+ nestUnspecifiedNamespace();
+
+ // If this is a nested element flush the outer
+ runAttrQueue();
+ nl();
+ indent();
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ if (arg == 0) {
+ delegate.writeStartElement(prefix, namespaceURI, localName);
+ } else {
+ delegate.writeEmptyElement(prefix, namespaceURI, localName);
+ }
+ });
+ level++;
+ state = START_ELEMENT;
+ indentEndElement = false;
+ }
+
+ @Override
+ public void writeEmptyElement(final String namespaceURI, final String localName) throws XMLStreamException {
+ runAttrQueue();
+ nl();
+ indent();
+ delegate.writeEmptyElement(namespaceURI, localName);
+ state = END_ELEMENT;
+ }
+
+ @Override
+ public void writeEmptyElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
+ runAttrQueue();
+ nl();
+ indent();
+ delegate.writeEmptyElement(prefix, namespaceURI, localName);
+ state = END_ELEMENT;
+ }
+
+ @Override
+ public void writeEmptyElement(final String localName) throws XMLStreamException {
+ String namespace = unspecifiedNamespaces.getFirst();
+ if (namespace != NO_NAMESPACE) {
+ writeEmptyElement(namespace, localName);
+ return;
+ }
+
+ runAttrQueue();
+ nl();
+ indent();
+ delegate.writeEmptyElement(localName);
+ state = END_ELEMENT;
+ }
+
+ @Override
+ public void writeEndElement() throws XMLStreamException {
+ level--;
+ if (state != START_ELEMENT) {
+ runAttrQueue();
+ if (state != CHARACTERS || indentEndElement) {
+ nl();
+ indent();
+ indentEndElement = false;
+ }
+ delegate.writeEndElement();
+ } else {
+ // Change the start element to an empty element
+ ArgRunnable start = attrQueue.poll();
+ if (start == null) {
+ delegate.writeEndElement();
+ } else {
+ start.run(1);
+ // Write everything else
+ runAttrQueue();
+ }
+ }
+
+ unspecifiedNamespaces.pop();
+ state = END_ELEMENT;
+ }
+
+ private void runAttrQueue() throws XMLStreamException {
+ ArgRunnable attr;
+ while ((attr = attrQueue.poll()) != null) {
+ attr.run(0);
+ }
+ }
+
+ @Override
+ public void writeEndDocument() throws XMLStreamException {
+ delegate.writeEndDocument();
+ state = END_DOCUMENT;
+ }
+
+ @Override
+ public void close() throws XMLStreamException {
+ delegate.close();
+ state = END_DOCUMENT;
+ }
+
+ @Override
+ public void flush() throws XMLStreamException {
+ delegate.flush();
+ }
+
+ @Override
+ public void writeAttribute(final String localName, final String value) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ try {
+ delegate.writeAttribute(localName, value);
+ } catch (XMLStreamException e) {
+ throw new UndeclaredThrowableException(e);
+ }
+ });
+ }
+
+ @Override
+ public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final String value) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeAttribute(prefix, namespaceURI, localName, value);
+ });
+ }
+
+ @Override
+ public void writeAttribute(final String namespaceURI, final String localName, final String value) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeAttribute(namespaceURI, localName, value);
+ });
+ }
+
+ @Override
+ public void writeAttribute(final String localName, final String[] values) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeAttribute(localName, join(values));
+ });
+ }
+
+ @Override
+ public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final String[] values) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeAttribute(prefix, namespaceURI, localName, join(values));
+ });
+ }
+
+ @Override
+ public void writeAttribute(final String namespaceURI, final String localName, final String[] values) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeAttribute(namespaceURI, localName, join(values));
+ });
+ }
+
+ @Override
+ public void writeAttribute(final String localName, final Iterable values) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeAttribute(localName, join(values));
+ });
+ }
+
+ @Override
+ public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final Iterable values) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeAttribute(prefix, namespaceURI, localName, join(values));
+ });
+ }
+
+ @Override
+ public void writeAttribute(final String namespaceURI, final String localName, final Iterable values) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeAttribute(namespaceURI, localName, join(values));
+ });
+ }
+
+ @Override
+ public void writeNamespace(final String prefix, final String namespaceURI) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeNamespace(prefix, namespaceURI);
+ });
+ }
+
+ @Override
+ public void writeDefaultNamespace(final String namespaceURI) throws XMLStreamException {
+ attrQueue.add((ArgRunnable) (int arg) -> {
+ delegate.writeDefaultNamespace(namespaceURI);
+ });
+ }
+
+ @Override
+ public void writeComment(final String data) throws XMLStreamException {
+ runAttrQueue();
+ nl();
+ indent();
+ final StringBuilder b = new StringBuilder(data.length());
+ final Iterator i = Spliterator.over(data, '\n');
+ if (! i.hasNext()) {
+ return;
+ } else {
+ final String first = i.next();
+ if (! i.hasNext()) {
+ delegate.writeComment(" " + first + " ");
+ state = COMMENT;
+ return;
+ } else {
+ b.append("\r\n");
+ for (int q = 0; q < level; q++) {
+ b.append(" ");
+ }
+ b.append(" ~ ");
+ b.append(first);
+ do {
+ b.append("\r\n");
+ for (int q = 0; q < level; q++) {
+ b.append(" ");
+ }
+ b.append(" ~ ");
+ b.append(i.next());
+ } while (i.hasNext());
+ }
+ b.append("\r\n");
+ for (int q = 0; q < level; q ++) {
+ b.append(" ");
+ }
+ b.append(" ");
+ delegate.writeComment(b.toString());
+ state = COMMENT;
+ }
+ }
+
+ @Override
+ public void writeProcessingInstruction(final String target) throws XMLStreamException {
+ runAttrQueue();
+ nl();
+ indent();
+ delegate.writeProcessingInstruction(target);
+ state = PROCESSING_INSTRUCTION;
+ }
+
+ @Override
+ public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
+ runAttrQueue();
+ nl();
+ indent();
+ delegate.writeProcessingInstruction(target, data);
+ state = PROCESSING_INSTRUCTION;
+ }
+
+ @Override
+ public void writeCData(final String data) throws XMLStreamException {
+ runAttrQueue();
+ delegate.writeCData(data);
+ state = CDATA;
+ }
+
+ @Override
+ public void writeDTD(final String dtd) throws XMLStreamException {
+ nl();
+ indent();
+ delegate.writeDTD(dtd);
+ state = DTD;
+ }
+
+ @Override
+ public void writeEntityRef(final String name) throws XMLStreamException {
+ runAttrQueue();
+ delegate.writeEntityRef(name);
+ state = ENTITY_REFERENCE;
+ }
+
+ @Override
+ public void writeStartDocument() throws XMLStreamException {
+ delegate.writeStartDocument();
+ state = START_DOCUMENT;
+ }
+
+ @Override
+ public void writeStartDocument(final String version) throws XMLStreamException {
+ delegate.writeStartDocument(version);
+ state = START_DOCUMENT;
+ }
+
+ @Override
+ public void writeStartDocument(final String encoding, final String version) throws XMLStreamException {
+ delegate.writeStartDocument(encoding, version);
+ state = START_DOCUMENT;
+ }
+
+ @Override
+ public void writeCharacters(final String text) throws XMLStreamException {
+ runAttrQueue();
+ if (state != CHARACTERS) {
+ nl();
+ indent();
+ }
+ final Iterator iterator = Spliterator.over(text, '\n');
+ while (iterator.hasNext()) {
+ final String t = iterator.next();
+ delegate.writeCharacters(t);
+ if (iterator.hasNext()) {
+ nl();
+ indent();
+ }
+ }
+ state = CHARACTERS;
+ indentEndElement = true;
+ }
+
+ @Override
+ public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
+ runAttrQueue();
+ delegate.writeCharacters(text, start, len);
+ state = CHARACTERS;
+ }
+
+ @Override
+ public String getPrefix(final String uri) throws XMLStreamException {
+ return delegate.getPrefix(uri);
+ }
+
+ @Override
+ public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
+ delegate.setPrefix(prefix, uri);
+ }
+
+ @Override
+ public void setDefaultNamespace(final String uri) throws XMLStreamException {
+ runAttrQueue();
+ delegate.setDefaultNamespace(uri);
+ }
+
+ @Override
+ public void setNamespaceContext(final NamespaceContext context) throws XMLStreamException {
+ delegate.setNamespaceContext(context);
+ }
+
+ @Override
+ public NamespaceContext getNamespaceContext() {
+ return delegate.getNamespaceContext();
+ }
+
+ @Override
+ public Object getProperty(final String name) throws IllegalArgumentException {
+ return delegate.getProperty(name);
+ }
+
+ private static String join(final String[] values) {
+ final StringBuilder b = new StringBuilder();
+ for (int i = 0, valuesLength = values.length; i < valuesLength; i++) {
+ final String s = values[i];
+ if (s != null) {
+ if (i > 0) {
+ b.append(' ');
+ }
+ b.append(s);
+ }
+ }
+ return b.toString();
+ }
+
+ private static String join(final Iterable values) {
+ final StringBuilder b = new StringBuilder();
+ Iterator iterator = values.iterator();
+ while (iterator.hasNext()) {
+ final String s = iterator.next();
+ if (s != null) {
+ b.append(s);
+ if (iterator.hasNext()) b.append(' ');
+ }
+ }
+ return b.toString();
+ }
+}
diff --git a/src/main/java/org/jboss/staxmapper/Spliterable.java b/src/main/java/org/jboss/staxmapper/Spliterable.java
index 4be1bc5..7517113 100644
--- a/src/main/java/org/jboss/staxmapper/Spliterable.java
+++ b/src/main/java/org/jboss/staxmapper/Spliterable.java
@@ -1,46 +1,47 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.staxmapper;
-
-import java.util.Iterator;
-
-/**
- * @author David M. Lloyd
- */
-final class Spliterable implements Iterable {
- private final String subject;
- private final char delimiter;
-
- Spliterable(final String subject, final char delimiter) {
- this.subject = subject;
- this.delimiter = delimiter;
- }
-
- static Spliterable over(String subject, char delimiter) {
- return new Spliterable(subject, delimiter);
- }
-
- public Iterator iterator() {
- return new Spliterator(subject, delimiter);
- }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.staxmapper;
+
+import java.util.Iterator;
+
+/**
+ * @author David M. Lloyd
+ */
+final class Spliterable implements Iterable {
+ private final String subject;
+ private final char delimiter;
+
+ Spliterable(final String subject, final char delimiter) {
+ this.subject = subject;
+ this.delimiter = delimiter;
+ }
+
+ static Spliterable over(String subject, char delimiter) {
+ return new Spliterable(subject, delimiter);
+ }
+
+ @Override
+ public Iterator iterator() {
+ return new Spliterator(subject, delimiter);
+ }
+}
diff --git a/src/main/java/org/jboss/staxmapper/Spliterator.java b/src/main/java/org/jboss/staxmapper/Spliterator.java
index 0117406..f589600 100644
--- a/src/main/java/org/jboss/staxmapper/Spliterator.java
+++ b/src/main/java/org/jboss/staxmapper/Spliterator.java
@@ -1,66 +1,69 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.staxmapper;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * @author David M. Lloyd
- */
-final class Spliterator implements Iterator {
- private final String subject;
- private final char delimiter;
- private int i;
-
- Spliterator(final String subject, final char delimiter) {
- this.subject = subject;
- this.delimiter = delimiter;
- i = 0;
- }
-
- static Spliterator over(String subject, char delimiter) {
- return new Spliterator(subject, delimiter);
- }
-
- public boolean hasNext() {
- return i != -1;
- }
-
- public String next() {
- final int i = this.i;
- if (i == -1) {
- throw new NoSuchElementException();
- }
- int n = subject.indexOf(delimiter, i);
- try {
- return n == -1 ? subject.substring(i) : subject.substring(i, n);
- } finally {
- this.i = n == -1 ? -1 : n + 1;
- }
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.staxmapper;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * @author David M. Lloyd
+ */
+final class Spliterator implements Iterator {
+ private final String subject;
+ private final char delimiter;
+ private int i;
+
+ Spliterator(final String subject, final char delimiter) {
+ this.subject = subject;
+ this.delimiter = delimiter;
+ i = 0;
+ }
+
+ static Spliterator over(String subject, char delimiter) {
+ return new Spliterator(subject, delimiter);
+ }
+
+ @Override
+ public boolean hasNext() {
+ return i != -1;
+ }
+
+ @Override
+ public String next() {
+ final int i = this.i;
+ if (i == -1) {
+ throw new NoSuchElementException();
+ }
+ int n = subject.indexOf(delimiter, i);
+ try {
+ return n == -1 ? subject.substring(i) : subject.substring(i, n);
+ } finally {
+ this.i = n == -1 ? -1 : n + 1;
+ }
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/main/java/org/jboss/staxmapper/XMLExtendedStreamReader.java b/src/main/java/org/jboss/staxmapper/XMLExtendedStreamReader.java
index d58cfa8..304c64b 100644
--- a/src/main/java/org/jboss/staxmapper/XMLExtendedStreamReader.java
+++ b/src/main/java/org/jboss/staxmapper/XMLExtendedStreamReader.java
@@ -1,160 +1,161 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.staxmapper;
-
-import java.util.List;
-
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-
-/**
- * An XML stream reader that can read nested {@code } content using a registered set of root elements.
- *
- * @author David M. Lloyd
- */
-public interface XMLExtendedStreamReader extends XMLStreamReader {
- /**
- * Handle an {@code }-type nested element, passing in the given value, returning after the end of the element.
- * Must be positioned on a {@code START_ELEMENT} or an exception will occur. On return the cursor will be positioned
- * on the corresponding {@code END_ELEMENT}.
- *
- * @param value the value to pass in
- * @throws XMLStreamException if an error occurs (e.g. the given value
- * does not match the type of the handler for the element, or the element is
- * unknown)
- */
- void handleAny(Object value) throws XMLStreamException;
-
- /**
- * Handle an extended attribute, passing in the given value.
- * Must be positioned on a {@code START_ELEMENT} or an exception will occur.
- * On return the cursor will be pointing at the same {@code START_ELEMENT}.
- *
- * @param value the value to pass in
- * @param index the index of the attribute to process
- * @throws XMLStreamException if an error occurs
- */
- void handleAttribute(Object value, int index) throws XMLStreamException;
-
- /**
- * Discard the remaining content of an element. Runs until a {@code END_ELEMENT} is
- * encountered. If a {@code START_ELEMENT} is encountered, then recursively consume and ignore
- * its content as well.
- *
- * @throws XMLStreamException if an error occurs.
- */
- void discardRemainder() throws XMLStreamException;
-
- /**
- * Get the value of an attribute as an integer.
- *
- * @param index the index of the attribute
- * @return the integer value
- * @throws XMLStreamException if an error occurs
- */
- int getIntAttributeValue(int index) throws XMLStreamException;
-
- /**
- * Get the value of an attribute as an integer list.
- *
- * @param index the index of the attribute
- * @return the integer values
- * @throws XMLStreamException if an error occurs
- */
- int[] getIntListAttributeValue(int index) throws XMLStreamException;
-
- /**
- * Get the value of an attribute as a space-delimited string list.
- *
- * @param index the index of the attribute
- * @return the values
- * @throws XMLStreamException if an error occurs
- */
- List getListAttributeValue(int index) throws XMLStreamException;
-
- /**
- * Get the value of an attribute as a long.
- *
- * @param index the index of the attribute
- * @return the long value
- * @throws XMLStreamException if an error occurs
- */
- long getLongAttributeValue(int index) throws XMLStreamException;
-
- /**
- * Get the value of an attribute as a long integer list.
- *
- * @param index the index of the attribute
- * @return the long values
- * @throws XMLStreamException if an error occurs
- */
- long[] getLongListAttributeValue(int index) throws XMLStreamException;
-
- /**
- * Get the attribute value using intelligent type conversion. Numeric types
- * will be parsed; enum types will be mapped.
- *
- * @param index the index of the attribute
- * @param kind the class of the expected object
- * @param the type of the expected object
- * @return the object equivalent
- * @throws XMLStreamException if an error occurs
- */
- T getAttributeValue(int index, Class kind) throws XMLStreamException;
-
- /**
- * Get the attribute value as a list using intelligent type conversion. Numeric types
- * will be parsed; enum types will be mapped.
- *
- * @param index the index of the attribute
- * @param kind the class of the expected object
- * @return the list of object equivalents
- * @throws XMLStreamException if an error occurs
- */
- List extends T> getListAttributeValue(int index, Class kind) throws XMLStreamException;
-
- /**
- * Get the XML ID attribute, if any.
- *
- * @return the attribute value
- * @throws XMLStreamException if an error occurs
- */
- String getId() throws XMLStreamException;
-
- /**
- * Gets the {@link XMLMapper} used to handle
- * {@link #handleAttribute(Object, int) extended attributes} and
- * {@link #handleAny(Object) xs:any-type nested elements}.
- *
- * @return the XMLMapper. Will not return {@code null}
- */
- XMLMapper getXMLMapper();
-
- /**
- * Whether or not {@link #getElementText} should trim content.
- * The default is true.
- *
- * @param trim trim if true, don't if false
- */
- void setTrimElementText(boolean trim);
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.staxmapper;
+
+import java.util.List;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+/**
+ * An XML stream reader that can read nested {@code } content using a registered set of root elements.
+ *
+ * @author David M. Lloyd
+ */
+public interface XMLExtendedStreamReader extends XMLStreamReader {
+ /**
+ * Handle an {@code }-type nested element, passing in the given value, returning after the end of the element.
+ * Must be positioned on a {@code START_ELEMENT} or an exception will occur. On return the cursor will be positioned
+ * on the corresponding {@code END_ELEMENT}.
+ *
+ * @param value the value to pass in
+ * @throws XMLStreamException if an error occurs (e.g. the given value
+ * does not match the type of the handler for the element, or the element is
+ * unknown)
+ */
+ void handleAny(Object value) throws XMLStreamException;
+
+ /**
+ * Handle an extended attribute, passing in the given value.
+ * Must be positioned on a {@code START_ELEMENT} or an exception will occur.
+ * On return the cursor will be pointing at the same {@code START_ELEMENT}.
+ *
+ * @param value the value to pass in
+ * @param index the index of the attribute to process
+ * @throws XMLStreamException if an error occurs
+ */
+ void handleAttribute(Object value, int index) throws XMLStreamException;
+
+ /**
+ * Discard the remaining content of an element. Runs until a {@code END_ELEMENT} is
+ * encountered. If a {@code START_ELEMENT} is encountered, then recursively consume and ignore
+ * its content as well.
+ *
+ * @throws XMLStreamException if an error occurs.
+ */
+ void discardRemainder() throws XMLStreamException;
+
+ /**
+ * Get the value of an attribute as an integer.
+ *
+ * @param index the index of the attribute
+ * @return the integer value
+ * @throws XMLStreamException if an error occurs
+ */
+ int getIntAttributeValue(int index) throws XMLStreamException;
+
+ /**
+ * Get the value of an attribute as an integer list.
+ *
+ * @param index the index of the attribute
+ * @return the integer values
+ * @throws XMLStreamException if an error occurs
+ */
+ int[] getIntListAttributeValue(int index) throws XMLStreamException;
+
+ /**
+ * Get the value of an attribute as a space-delimited string list.
+ *
+ * @param index the index of the attribute
+ * @return the values
+ * @throws XMLStreamException if an error occurs
+ */
+ List getListAttributeValue(int index) throws XMLStreamException;
+
+ /**
+ * Get the value of an attribute as a long.
+ *
+ * @param index the index of the attribute
+ * @return the long value
+ * @throws XMLStreamException if an error occurs
+ */
+ long getLongAttributeValue(int index) throws XMLStreamException;
+
+ /**
+ * Get the value of an attribute as a long integer list.
+ *
+ * @param index the index of the attribute
+ * @return the long values
+ * @throws XMLStreamException if an error occurs
+ */
+ long[] getLongListAttributeValue(int index) throws XMLStreamException;
+
+ /**
+ * Get the attribute value using intelligent type conversion. Numeric types
+ * will be parsed; enum types will be mapped.
+ *
+ * @param index the index of the attribute
+ * @param kind the class of the expected object
+ * @param the type of the expected object
+ * @return the object equivalent
+ * @throws XMLStreamException if an error occurs
+ */
+ T getAttributeValue(int index, Class kind) throws XMLStreamException;
+
+ /**
+ * Get the attribute value as a list using intelligent type conversion. Numeric types
+ * will be parsed; enum types will be mapped.
+ *
+ * @param the type of the expected object
+ * @param index the index of the attribute
+ * @param kind the class of the expected object
+ * @return the list of object equivalents
+ * @throws XMLStreamException if an error occurs
+ */
+ List extends T> getListAttributeValue(int index, Class kind) throws XMLStreamException;
+
+ /**
+ * Get the XML ID attribute, if any.
+ *
+ * @return the attribute value
+ * @throws XMLStreamException if an error occurs
+ */
+ String getId() throws XMLStreamException;
+
+ /**
+ * Gets the {@link XMLMapper} used to handle
+ * {@link #handleAttribute(Object, int) extended attributes} and
+ * {@link #handleAny(Object) xs:any-type nested elements}.
+ *
+ * @return the XMLMapper. Will not return {@code null}
+ */
+ XMLMapper getXMLMapper();
+
+ /**
+ * Whether or not {@link #getElementText} should trim content.
+ * The default is true.
+ *
+ * @param trim trim if true, don't if false
+ */
+ void setTrimElementText(boolean trim);
+}
diff --git a/src/main/java/org/jboss/staxmapper/XMLExtendedStreamReaderImpl.java b/src/main/java/org/jboss/staxmapper/XMLExtendedStreamReaderImpl.java
index 9b9eca6..825ec64 100644
--- a/src/main/java/org/jboss/staxmapper/XMLExtendedStreamReaderImpl.java
+++ b/src/main/java/org/jboss/staxmapper/XMLExtendedStreamReaderImpl.java
@@ -1,549 +1,549 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.staxmapper;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.List;
-
-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;
-
-/**
- * @author David M. Lloyd
- */
-final class XMLExtendedStreamReaderImpl implements XMLExtendedStreamReader {
-
- private final XMLMapperImpl xmlMapper;
- private final XMLStreamReader streamReader;
- private final XMLStreamReader fixedStreamReader;
- private final Deque stack = new ArrayDeque<>();
- private boolean trimElementText = true;
-
- XMLExtendedStreamReaderImpl(final XMLMapperImpl xmlMapper, final XMLStreamReader streamReader) {
- this.xmlMapper = xmlMapper;
- this.streamReader = streamReader;
- fixedStreamReader = new FixedXMLStreamReader(this.streamReader);
- stack.push(new Context());
- }
-
- @Override
- public void setTrimElementText(boolean trim) {
- this.trimElementText = trim;
- }
-
- @Override
- public void handleAny(final Object value) throws XMLStreamException {
- require(START_ELEMENT, null, null);
- boolean ok = false;
- try {
- final Deque stack = this.stack;
- stack.push(new Context());
- try {
- xmlMapper.processNested(this, value);
- } finally {
- stack.pop();
- }
- ok = true;
- } finally {
- if (! ok) {
- safeClose();
- }
- }
- }
-
- @Override
- public void handleAttribute(final Object value, final int index) throws XMLStreamException {
- require(START_ELEMENT, null, null);
- boolean ok = false;
- try {
- xmlMapper.processAttribute(fixedStreamReader, index, value);
- } finally {
- if (!ok) {
- safeClose();
- }
- }
- }
-
- @Override
- public void discardRemainder() throws XMLStreamException {
- final Context context = stack.getFirst();
- if (context.depth > 0) {
- try {
- doDiscard();
- } finally {
- context.depth--;
- }
- } else {
- try {
- throw readPastEnd(getLocation());
- } finally {
- safeClose();
- }
- }
- }
-
- @Override
- public Object getProperty(final String name) throws IllegalArgumentException {
- return streamReader.getProperty(name);
- }
-
- @Override
- public int next() throws XMLStreamException {
- final Context context = stack.getFirst();
- if (context.depth > 0) {
- final int next = streamReader.next();
- if (next == END_ELEMENT) {
- context.depth--;
- } else if(next == START_ELEMENT) {
- context.depth++;
- }
- return next;
- } else {
- try {
- throw readPastEnd(getLocation());
- } finally {
- safeClose();
- }
- }
- }
-
- @Override
- public void require(final int type, final String namespaceURI, final String localName) throws XMLStreamException {
- streamReader.require(type, namespaceURI, localName);
- }
-
- @Override
- public String getElementText() throws XMLStreamException {
- String text = streamReader.getElementText();
- return trimElementText ? text.trim() : text;
- }
-
- @Override
- public int nextTag() throws XMLStreamException {
- final Context context = stack.getFirst();
- if (context.depth > 0) {
- final int next = streamReader.nextTag();
- if (next == END_ELEMENT) {
- context.depth--;
- } else if(next == START_ELEMENT) {
- context.depth++;
- }
- return next;
- } else {
- try {
- throw readPastEnd(getLocation());
- } finally {
- safeClose();
- }
- }
- }
-
- @Override
- public boolean hasNext() throws XMLStreamException {
- return stack.getFirst().depth > 0 && streamReader.hasNext();
- }
-
- @Override
- public void close() throws XMLStreamException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getNamespaceURI(final String prefix) {
- return streamReader.getNamespaceURI(prefix);
- }
-
- @Override
- public boolean isStartElement() {
- return streamReader.isStartElement();
- }
-
- @Override
- public boolean isEndElement() {
- return streamReader.isEndElement();
- }
-
- @Override
- public boolean isCharacters() {
- return streamReader.isCharacters();
- }
-
- @Override
- public boolean isWhiteSpace() {
- return streamReader.isWhiteSpace();
- }
-
- @Override
- public String getAttributeValue(final String namespaceURI, final String localName) {
- return streamReader.getAttributeValue(namespaceURI, localName);
- }
-
- @Override
- public int getAttributeCount() {
- return streamReader.getAttributeCount();
- }
-
- @Override
- public QName getAttributeName(final int index) {
- return streamReader.getAttributeName(index);
- }
-
- @Override
- public String getAttributeNamespace(final int index) {
- return streamReader.getAttributeNamespace(index);
- }
-
- @Override
- public String getAttributeLocalName(final int index) {
- return streamReader.getAttributeLocalName(index);
- }
-
- @Override
- public String getAttributePrefix(final int index) {
- return streamReader.getAttributePrefix(index);
- }
-
- @Override
- public String getAttributeType(final int index) {
- return streamReader.getAttributeType(index);
- }
-
- @Override
- public String getAttributeValue(final int index) {
- return streamReader.getAttributeValue(index);
- }
-
- @Override
- public boolean isAttributeSpecified(final int index) {
- return streamReader.isAttributeSpecified(index);
- }
-
- @Override
- public int getNamespaceCount() {
- return streamReader.getNamespaceCount();
- }
-
- @Override
- public String getNamespacePrefix(final int index) {
- return streamReader.getNamespacePrefix(index);
- }
-
- @Override
- public String getNamespaceURI(final int index) {
- return streamReader.getNamespaceURI(index);
- }
-
- @Override
- public NamespaceContext getNamespaceContext() {
- return streamReader.getNamespaceContext();
- }
-
- @Override
- public int getEventType() {
- return streamReader.getEventType();
- }
-
- @Override
- public String getText() {
- return streamReader.getText();
- }
-
- @Override
- public char[] getTextCharacters() {
- return streamReader.getTextCharacters();
- }
-
- @Override
- public int getTextCharacters(final int sourceStart, final char[] target, final int targetStart, final int length) throws XMLStreamException {
- return streamReader.getTextCharacters(sourceStart, target, targetStart, length);
- }
-
- @Override
- public int getTextStart() {
- return streamReader.getTextStart();
- }
-
- @Override
- public int getTextLength() {
- return streamReader.getTextLength();
- }
-
- @Override
- public String getEncoding() {
- return streamReader.getEncoding();
- }
-
- @Override
- public boolean hasText() {
- return streamReader.hasText();
- }
-
- @Override
- public Location getLocation() {
- return streamReader.getLocation();
- }
-
- @Override
- public QName getName() {
- return streamReader.getName();
- }
-
- @Override
- public String getLocalName() {
- return streamReader.getLocalName();
- }
-
- @Override
- public boolean hasName() {
- return streamReader.hasName();
- }
-
- @Override
- public String getNamespaceURI() {
- return streamReader.getNamespaceURI();
- }
-
- @Override
- public String getPrefix() {
- return streamReader.getPrefix();
- }
-
- @Override
- public String getVersion() {
- return streamReader.getVersion();
- }
-
- @Override
- public boolean isStandalone() {
- return streamReader.isStandalone();
- }
-
- @Override
- public boolean standaloneSet() {
- return streamReader.standaloneSet();
- }
-
- @Override
- public String getCharacterEncodingScheme() {
- return streamReader.getCharacterEncodingScheme();
- }
-
- @Override
- public String getPITarget() {
- return streamReader.getPITarget();
- }
-
- @Override
- public String getPIData() {
- return streamReader.getPIData();
- }
-
- @Override
- public int getIntAttributeValue(final int index) throws XMLStreamException {
- try {
- return Integer.parseInt(getAttributeValue(index));
- } catch (NumberFormatException e) {
- throw intParseException(e, getLocation());
- }
- }
-
- @Override
- public int[] getIntListAttributeValue(final int index) throws XMLStreamException {
- try {
- return toInts(Spliterator.over(getAttributeValue(index), ' '), 0);
- } catch (NumberFormatException e) {
- throw intParseException(e, getLocation());
- }
- }
-
- @Override
- public List getListAttributeValue(final int index) throws XMLStreamException {
- return Arrays.asList(toStrings(Spliterator.over(getAttributeValue(index), ' '), 0));
- }
-
- @Override
- public long getLongAttributeValue(final int index) throws XMLStreamException {
- try {
- return Long.parseLong(getAttributeValue(index));
- } catch (NumberFormatException e) {
- throw intParseException(e, getLocation());
- }
- }
-
- @Override
- public long[] getLongListAttributeValue(final int index) throws XMLStreamException {
- try {
- return toLongs(Spliterator.over(getAttributeValue(index), ' '), 0);
- } catch (NumberFormatException e) {
- throw intParseException(e, getLocation());
- }
- }
-
- @Override
- public T getAttributeValue(final int index, final Class kind) throws XMLStreamException {
- if (kind == String.class || kind == Object.class) {
- return kind.cast(getAttributeValue(index));
- } else if (kind == Integer.class || kind == Number.class) {
- return kind.cast(Integer.valueOf(getIntAttributeValue(index)));
- } else if (kind == Long.class) {
- return kind.cast(Long.valueOf(getLongAttributeValue(index)));
- } else if (kind.isEnum()) {
- @SuppressWarnings({ "unchecked", "rawtypes" })
- T value = (T) Enum.valueOf((Class) kind, getAttributeValue(index));
- return value;
- } else if (kind == char[].class) {
- return kind.cast(getAttributeValue(index).toCharArray());
- } else {
- throw new XMLStreamException("Unknown value type of '" + kind + "'", getLocation());
- }
- }
-
- @Override
- @SuppressWarnings({ "unchecked" })
- public List extends T> getListAttributeValue(final int index, final Class kind) throws XMLStreamException {
- if (kind == String.class || kind == Object.class) {
- return (List extends T>) getListAttributeValue(index);
- } else if (kind == Integer.class || kind == Number.class) {
- final List list = new ArrayList();
- try {
- for (String s : Spliterable.over(getAttributeValue(index), ' ')) {
- list.add(kind.cast(Integer.valueOf(s)));
- }
- return list;
- } catch (NumberFormatException e) {
- throw intParseException(e, getLocation());
- }
- } else if (kind == Long.class) {
- final List list = new ArrayList();
- try {
- for (String s : Spliterable.over(getAttributeValue(index), ' ')) {
- list.add(kind.cast(Long.valueOf(s)));
- }
- return list;
- } catch (NumberFormatException e) {
- throw intParseException(e, getLocation());
- }
- } else if (kind.isEnum()) {
- final List list = new ArrayList<>();
- for (String s : Spliterable.over(getAttributeValue(index), ' ')) {
- Enum> en = Enum.valueOf(kind.asSubclass(Enum.class), s);
- list.add(kind.cast(en));
- }
- return list;
- } else if (kind == char[].class) {
- final List list = new ArrayList();
- for (String s : Spliterable.over(getAttributeValue(index), ' ')) {
- list.add(kind.cast(s.toCharArray()));
- }
- return list;
- } else {
- throw new XMLStreamException("Unknown value type of '" + kind + "'", getLocation());
- }
- }
-
- @Override
- public String getId() throws XMLStreamException {
- return getAttributeValue(null, "id");
- }
-
- @Override
- public XMLMapper getXMLMapper() {
- return xmlMapper;
- }
-
- // private members
-
- private static final class Context {
- int depth = 1;
- }
-
- private void doDiscard() throws XMLStreamException {
- int i;
- while ((i = streamReader.next()) != END_ELEMENT) {
- if (i == START_ELEMENT) {
- doDiscard();
- }
- }
- }
-
- private void safeClose() {
- try {
- streamReader.close();
- } catch (Exception e) {
- // ignore
- }
- }
-
- private static final int[] NO_INTS = new int[0];
- private static final long[] NO_LONGS = new long[0];
- private static final String[] NO_STRINGS = new String[0];
-
- private static int[] toInts(Iterator i, int count) {
- if (i.hasNext()) {
- final String n = i.next();
- final int[] ints = toInts(i, count + 1);
- ints[count] = Integer.parseInt(n);
- return ints;
- } else {
- return count == 0 ? NO_INTS : new int[count];
- }
- }
-
- private static long[] toLongs(Iterator i, int count) {
- if (i.hasNext()) {
- final String n = i.next();
- final long[] longs = toLongs(i, count + 1);
- longs[count] = Long.parseLong(n);
- return longs;
- } else {
- return count == 0 ? NO_LONGS : new long[count];
- }
- }
-
- private static String[] toStrings(Iterator i, int count) {
- if (i.hasNext()) {
- final String s = i.next();
- final String[] strings = toStrings(i, count + 1);
- strings[count] = s;
- return strings;
- } else {
- return count == 0 ? NO_STRINGS : new String[count];
- }
- }
-
- private static XMLStreamException readPastEnd(final Location location) {
- return new XMLStreamException("Attempt to read past end of element", location);
- }
-
- private static XMLStreamException intParseException(final NumberFormatException e, final Location location) {
- return new XMLStreamException("Failed to parse an integer attribute", location, e);
- }
-
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.staxmapper;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.List;
+
+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;
+
+/**
+ * @author David M. Lloyd
+ */
+final class XMLExtendedStreamReaderImpl implements XMLExtendedStreamReader {
+
+ private final XMLMapperImpl xmlMapper;
+ private final XMLStreamReader streamReader;
+ private final XMLStreamReader fixedStreamReader;
+ private final Deque stack = new ArrayDeque<>();
+ private boolean trimElementText = true;
+
+ XMLExtendedStreamReaderImpl(final XMLMapperImpl xmlMapper, final XMLStreamReader streamReader) {
+ this.xmlMapper = xmlMapper;
+ this.streamReader = streamReader;
+ fixedStreamReader = new FixedXMLStreamReader(this.streamReader);
+ stack.push(new Context());
+ }
+
+ @Override
+ public void setTrimElementText(boolean trim) {
+ this.trimElementText = trim;
+ }
+
+ @Override
+ public void handleAny(final Object value) throws XMLStreamException {
+ require(START_ELEMENT, null, null);
+ boolean ok = false;
+ try {
+ final Deque stack = this.stack;
+ stack.push(new Context());
+ try {
+ xmlMapper.processNested(this, value);
+ } finally {
+ stack.pop();
+ }
+ ok = true;
+ } finally {
+ if (! ok) {
+ safeClose();
+ }
+ }
+ }
+
+ @Override
+ public void handleAttribute(final Object value, final int index) throws XMLStreamException {
+ require(START_ELEMENT, null, null);
+ boolean ok = false;
+ try {
+ xmlMapper.processAttribute(fixedStreamReader, index, value);
+ } finally {
+ if (!ok) {
+ safeClose();
+ }
+ }
+ }
+
+ @Override
+ public void discardRemainder() throws XMLStreamException {
+ final Context context = stack.getFirst();
+ if (context.depth > 0) {
+ try {
+ doDiscard();
+ } finally {
+ context.depth--;
+ }
+ } else {
+ try {
+ throw readPastEnd(getLocation());
+ } finally {
+ safeClose();
+ }
+ }
+ }
+
+ @Override
+ public Object getProperty(final String name) throws IllegalArgumentException {
+ return streamReader.getProperty(name);
+ }
+
+ @Override
+ public int next() throws XMLStreamException {
+ final Context context = stack.getFirst();
+ if (context.depth > 0) {
+ final int next = streamReader.next();
+ if (next == END_ELEMENT) {
+ context.depth--;
+ } else if(next == START_ELEMENT) {
+ context.depth++;
+ }
+ return next;
+ } else {
+ try {
+ throw readPastEnd(getLocation());
+ } finally {
+ safeClose();
+ }
+ }
+ }
+
+ @Override
+ public void require(final int type, final String namespaceURI, final String localName) throws XMLStreamException {
+ streamReader.require(type, namespaceURI, localName);
+ }
+
+ @Override
+ public String getElementText() throws XMLStreamException {
+ String text = streamReader.getElementText();
+ return trimElementText ? text.trim() : text;
+ }
+
+ @Override
+ public int nextTag() throws XMLStreamException {
+ final Context context = stack.getFirst();
+ if (context.depth > 0) {
+ final int next = streamReader.nextTag();
+ if (next == END_ELEMENT) {
+ context.depth--;
+ } else if(next == START_ELEMENT) {
+ context.depth++;
+ }
+ return next;
+ } else {
+ try {
+ throw readPastEnd(getLocation());
+ } finally {
+ safeClose();
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext() throws XMLStreamException {
+ return stack.getFirst().depth > 0 && streamReader.hasNext();
+ }
+
+ @Override
+ public void close() throws XMLStreamException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getNamespaceURI(final String prefix) {
+ return streamReader.getNamespaceURI(prefix);
+ }
+
+ @Override
+ public boolean isStartElement() {
+ return streamReader.isStartElement();
+ }
+
+ @Override
+ public boolean isEndElement() {
+ return streamReader.isEndElement();
+ }
+
+ @Override
+ public boolean isCharacters() {
+ return streamReader.isCharacters();
+ }
+
+ @Override
+ public boolean isWhiteSpace() {
+ return streamReader.isWhiteSpace();
+ }
+
+ @Override
+ public String getAttributeValue(final String namespaceURI, final String localName) {
+ return streamReader.getAttributeValue(namespaceURI, localName);
+ }
+
+ @Override
+ public int getAttributeCount() {
+ return streamReader.getAttributeCount();
+ }
+
+ @Override
+ public QName getAttributeName(final int index) {
+ return streamReader.getAttributeName(index);
+ }
+
+ @Override
+ public String getAttributeNamespace(final int index) {
+ return streamReader.getAttributeNamespace(index);
+ }
+
+ @Override
+ public String getAttributeLocalName(final int index) {
+ return streamReader.getAttributeLocalName(index);
+ }
+
+ @Override
+ public String getAttributePrefix(final int index) {
+ return streamReader.getAttributePrefix(index);
+ }
+
+ @Override
+ public String getAttributeType(final int index) {
+ return streamReader.getAttributeType(index);
+ }
+
+ @Override
+ public String getAttributeValue(final int index) {
+ return streamReader.getAttributeValue(index);
+ }
+
+ @Override
+ public boolean isAttributeSpecified(final int index) {
+ return streamReader.isAttributeSpecified(index);
+ }
+
+ @Override
+ public int getNamespaceCount() {
+ return streamReader.getNamespaceCount();
+ }
+
+ @Override
+ public String getNamespacePrefix(final int index) {
+ return streamReader.getNamespacePrefix(index);
+ }
+
+ @Override
+ public String getNamespaceURI(final int index) {
+ return streamReader.getNamespaceURI(index);
+ }
+
+ @Override
+ public NamespaceContext getNamespaceContext() {
+ return streamReader.getNamespaceContext();
+ }
+
+ @Override
+ public int getEventType() {
+ return streamReader.getEventType();
+ }
+
+ @Override
+ public String getText() {
+ return streamReader.getText();
+ }
+
+ @Override
+ public char[] getTextCharacters() {
+ return streamReader.getTextCharacters();
+ }
+
+ @Override
+ public int getTextCharacters(final int sourceStart, final char[] target, final int targetStart, final int length) throws XMLStreamException {
+ return streamReader.getTextCharacters(sourceStart, target, targetStart, length);
+ }
+
+ @Override
+ public int getTextStart() {
+ return streamReader.getTextStart();
+ }
+
+ @Override
+ public int getTextLength() {
+ return streamReader.getTextLength();
+ }
+
+ @Override
+ public String getEncoding() {
+ return streamReader.getEncoding();
+ }
+
+ @Override
+ public boolean hasText() {
+ return streamReader.hasText();
+ }
+
+ @Override
+ public Location getLocation() {
+ return streamReader.getLocation();
+ }
+
+ @Override
+ public QName getName() {
+ return streamReader.getName();
+ }
+
+ @Override
+ public String getLocalName() {
+ return streamReader.getLocalName();
+ }
+
+ @Override
+ public boolean hasName() {
+ return streamReader.hasName();
+ }
+
+ @Override
+ public String getNamespaceURI() {
+ return streamReader.getNamespaceURI();
+ }
+
+ @Override
+ public String getPrefix() {
+ return streamReader.getPrefix();
+ }
+
+ @Override
+ public String getVersion() {
+ return streamReader.getVersion();
+ }
+
+ @Override
+ public boolean isStandalone() {
+ return streamReader.isStandalone();
+ }
+
+ @Override
+ public boolean standaloneSet() {
+ return streamReader.standaloneSet();
+ }
+
+ @Override
+ public String getCharacterEncodingScheme() {
+ return streamReader.getCharacterEncodingScheme();
+ }
+
+ @Override
+ public String getPITarget() {
+ return streamReader.getPITarget();
+ }
+
+ @Override
+ public String getPIData() {
+ return streamReader.getPIData();
+ }
+
+ @Override
+ public int getIntAttributeValue(final int index) throws XMLStreamException {
+ try {
+ return Integer.parseInt(getAttributeValue(index));
+ } catch (NumberFormatException e) {
+ throw intParseException(e, getLocation());
+ }
+ }
+
+ @Override
+ public int[] getIntListAttributeValue(final int index) throws XMLStreamException {
+ try {
+ return toInts(Spliterator.over(getAttributeValue(index), ' '), 0);
+ } catch (NumberFormatException e) {
+ throw intParseException(e, getLocation());
+ }
+ }
+
+ @Override
+ public List getListAttributeValue(final int index) throws XMLStreamException {
+ return Arrays.asList(toStrings(Spliterator.over(getAttributeValue(index), ' '), 0));
+ }
+
+ @Override
+ public long getLongAttributeValue(final int index) throws XMLStreamException {
+ try {
+ return Long.parseLong(getAttributeValue(index));
+ } catch (NumberFormatException e) {
+ throw intParseException(e, getLocation());
+ }
+ }
+
+ @Override
+ public long[] getLongListAttributeValue(final int index) throws XMLStreamException {
+ try {
+ return toLongs(Spliterator.over(getAttributeValue(index), ' '), 0);
+ } catch (NumberFormatException e) {
+ throw intParseException(e, getLocation());
+ }
+ }
+
+ @Override
+ public T getAttributeValue(final int index, final Class kind) throws XMLStreamException {
+ if (kind == String.class || kind == Object.class) {
+ return kind.cast(getAttributeValue(index));
+ } else if (kind == Integer.class || kind == Number.class) {
+ return kind.cast(Integer.valueOf(getIntAttributeValue(index)));
+ } else if (kind == Long.class) {
+ return kind.cast(Long.valueOf(getLongAttributeValue(index)));
+ } else if (kind.isEnum()) {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ T value = (T) Enum.valueOf((Class) kind, getAttributeValue(index));
+ return value;
+ } else if (kind == char[].class) {
+ return kind.cast(getAttributeValue(index).toCharArray());
+ } else {
+ throw new XMLStreamException("Unknown value type of '" + kind + "'", getLocation());
+ }
+ }
+
+ @Override
+ @SuppressWarnings({ "unchecked" })
+ public List extends T> getListAttributeValue(final int index, final Class kind) throws XMLStreamException {
+ if (kind == String.class || kind == Object.class) {
+ return (List extends T>) getListAttributeValue(index);
+ } else if (kind == Integer.class || kind == Number.class) {
+ final List list = new ArrayList<>();
+ try {
+ for (String s : Spliterable.over(getAttributeValue(index), ' ')) {
+ list.add(kind.cast(Integer.valueOf(s)));
+ }
+ return list;
+ } catch (NumberFormatException e) {
+ throw intParseException(e, getLocation());
+ }
+ } else if (kind == Long.class) {
+ final List list = new ArrayList<>();
+ try {
+ for (String s : Spliterable.over(getAttributeValue(index), ' ')) {
+ list.add(kind.cast(Long.valueOf(s)));
+ }
+ return list;
+ } catch (NumberFormatException e) {
+ throw intParseException(e, getLocation());
+ }
+ } else if (kind.isEnum()) {
+ final List list = new ArrayList<>();
+ for (String s : Spliterable.over(getAttributeValue(index), ' ')) {
+ Enum> en = Enum.valueOf(kind.asSubclass(Enum.class), s);
+ list.add(kind.cast(en));
+ }
+ return list;
+ } else if (kind == char[].class) {
+ final List list = new ArrayList<>();
+ for (String s : Spliterable.over(getAttributeValue(index), ' ')) {
+ list.add(kind.cast(s.toCharArray()));
+ }
+ return list;
+ } else {
+ throw new XMLStreamException("Unknown value type of '" + kind + "'", getLocation());
+ }
+ }
+
+ @Override
+ public String getId() throws XMLStreamException {
+ return getAttributeValue(null, "id");
+ }
+
+ @Override
+ public XMLMapper getXMLMapper() {
+ return xmlMapper;
+ }
+
+ // private members
+
+ private static final class Context {
+ int depth = 1;
+ }
+
+ private void doDiscard() throws XMLStreamException {
+ int i;
+ while ((i = streamReader.next()) != END_ELEMENT) {
+ if (i == START_ELEMENT) {
+ doDiscard();
+ }
+ }
+ }
+
+ private void safeClose() {
+ try {
+ streamReader.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ private static final int[] NO_INTS = new int[0];
+ private static final long[] NO_LONGS = new long[0];
+ private static final String[] NO_STRINGS = new String[0];
+
+ private static int[] toInts(Iterator i, int count) {
+ if (i.hasNext()) {
+ final String n = i.next();
+ final int[] ints = toInts(i, count + 1);
+ ints[count] = Integer.parseInt(n);
+ return ints;
+ } else {
+ return count == 0 ? NO_INTS : new int[count];
+ }
+ }
+
+ private static long[] toLongs(Iterator i, int count) {
+ if (i.hasNext()) {
+ final String n = i.next();
+ final long[] longs = toLongs(i, count + 1);
+ longs[count] = Long.parseLong(n);
+ return longs;
+ } else {
+ return count == 0 ? NO_LONGS : new long[count];
+ }
+ }
+
+ private static String[] toStrings(Iterator i, int count) {
+ if (i.hasNext()) {
+ final String s = i.next();
+ final String[] strings = toStrings(i, count + 1);
+ strings[count] = s;
+ return strings;
+ } else {
+ return count == 0 ? NO_STRINGS : new String[count];
+ }
+ }
+
+ private static XMLStreamException readPastEnd(final Location location) {
+ return new XMLStreamException("Attempt to read past end of element", location);
+ }
+
+ private static XMLStreamException intParseException(final NumberFormatException e, final Location location) {
+ return new XMLStreamException("Failed to parse an integer attribute", location, e);
+ }
+
+}
diff --git a/src/main/java/org/jboss/staxmapper/XMLMapper.java b/src/main/java/org/jboss/staxmapper/XMLMapper.java
index 8e0dff2..b3b3b13 100644
--- a/src/main/java/org/jboss/staxmapper/XMLMapper.java
+++ b/src/main/java/org/jboss/staxmapper/XMLMapper.java
@@ -1,128 +1,130 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.staxmapper;
-
-import java.util.function.Supplier;
-import javax.xml.namespace.QName;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.stream.XMLStreamWriter;
-
-/**
- * An XML mapper. Allows the creation of extensible streaming XML parsers.
- *
- * @author David M. Lloyd
- */
-public interface XMLMapper {
-
- /**
- * Add a known root element which can be read by {@link XMLExtendedStreamReader#handleAny(Object)}.
- *
- * @param name the element name
- * @param reader the reader which handles the element
- */
- void registerRootElement(QName name, XMLElementReader reader);
-
- /**
- * Add a known root element which can be read by {@link XMLExtendedStreamReader#handleAny(Object)}.
- *
- * @param name the element name
- * @param supplier provider for the reader which handles the element
- *
- * It is recommended that supplier always creates new instance of the {@link XMLElementReader}
- * instead of caching and returning always same instance. This way unused parsers can get GC-ed
- * when not needed.
- *
- */
- void registerRootElement(QName name, Supplier> supplier);
-
-
- /**
- * Removes a {@link #registerRootElement(QName, XMLElementReader) previously registered root element}.
- *
- * @param name the element name
- */
- void unregisterRootElement(QName name);
-
- /**
- * Add a known root attribute which can be read by {@link XMLExtendedStreamReader#handleAttribute(Object, int)}.
- *
- * @param name the attribute name
- * @param reader the reader which handles the attribute
- */
- void registerRootAttribute(QName name, XMLAttributeReader> reader);
-
- /**
- * Removes a {@link #registerRootAttribute(QName, XMLAttributeReader) previously registered root attribute}.
- *
- * @param name the element name
- */
- void unregisterRootAttribute(QName name);
-
- /**
- * Parse a document. The document must have a known, registered root element which can accept the given root object.
- *
- * @param rootObject the root object to send in
- * @param reader the reader from which the document should be read
- * @throws XMLStreamException if an error occurs
- */
- void parseDocument(Object rootObject, XMLStreamReader reader) throws XMLStreamException;
-
- /**
- * Format the element writer's output on to an XML stream writer.
- *
- * @param writer the element writer
- * @param rootObject the root object to send in
- * @param streamWriter the stream writer
- * @throws XMLStreamException if an exception occurs
- */
- void deparseDocument(XMLElementWriter> writer, Object rootObject, XMLStreamWriter streamWriter) throws XMLStreamException;
-
- /**
- * Format the content writer's output on to an XML stream writer.
- *
- * @param contentWriter the content writer
- * @param streamWriter the stream writer
- * @throws XMLStreamException if an exception occurs
- */
- @Deprecated
- void deparseDocument(XMLContentWriter contentWriter, XMLStreamWriter streamWriter) throws XMLStreamException;
-
- /**
- * A factory for creating an instance of {@link XMLMapper}.
- */
- class Factory {
-
- private Factory() {
- }
-
- /**
- * Create a new mapper instance.
- *
- * @return the new instance
- */
- public static XMLMapper create() {
- return new XMLMapperImpl();
- }
- }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.staxmapper;
+
+import java.util.function.Supplier;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+/**
+ * An XML mapper. Allows the creation of extensible streaming XML parsers.
+ *
+ * @author David M. Lloyd
+ */
+public interface XMLMapper {
+
+ /**
+ * Add a known root element which can be read by {@link XMLExtendedStreamReader#handleAny(Object)}.
+ *
+ * @param the type of the expected object
+ * @param name the element name
+ * @param reader the reader which handles the element
+ */
+ void registerRootElement(QName name, XMLElementReader reader);
+
+ /**
+ * Add a known root element which can be read by {@link XMLExtendedStreamReader#handleAny(Object)}.
+ *
+ * @param the type of the expected object
+ * @param name the element name
+ * @param supplier provider for the reader which handles the element
+ *
+ * It is recommended that supplier always creates new instance of the {@link XMLElementReader}
+ * instead of caching and returning always same instance. This way unused parsers can get GC-ed
+ * when not needed.
+ *
+ */
+ void registerRootElement(QName name, Supplier> supplier);
+
+
+ /**
+ * Removes a {@link #registerRootElement(QName, XMLElementReader) previously registered root element}.
+ *
+ * @param name the element name
+ */
+ void unregisterRootElement(QName name);
+
+ /**
+ * Add a known root attribute which can be read by {@link XMLExtendedStreamReader#handleAttribute(Object, int)}.
+ *
+ * @param name the attribute name
+ * @param reader the reader which handles the attribute
+ */
+ void registerRootAttribute(QName name, XMLAttributeReader> reader);
+
+ /**
+ * Removes a {@link #registerRootAttribute(QName, XMLAttributeReader) previously registered root attribute}.
+ *
+ * @param name the element name
+ */
+ void unregisterRootAttribute(QName name);
+
+ /**
+ * Parse a document. The document must have a known, registered root element which can accept the given root object.
+ *
+ * @param rootObject the root object to send in
+ * @param reader the reader from which the document should be read
+ * @throws XMLStreamException if an error occurs
+ */
+ void parseDocument(Object rootObject, XMLStreamReader reader) throws XMLStreamException;
+
+ /**
+ * Format the element writer's output on to an XML stream writer.
+ *
+ * @param writer the element writer
+ * @param rootObject the root object to send in
+ * @param streamWriter the stream writer
+ * @throws XMLStreamException if an exception occurs
+ */
+ void deparseDocument(XMLElementWriter> writer, Object rootObject, XMLStreamWriter streamWriter) throws XMLStreamException;
+
+ /**
+ * Format the content writer's output on to an XML stream writer.
+ *
+ * @param contentWriter the content writer
+ * @param streamWriter the stream writer
+ * @throws XMLStreamException if an exception occurs
+ */
+ @Deprecated
+ void deparseDocument(XMLContentWriter contentWriter, XMLStreamWriter streamWriter) throws XMLStreamException;
+
+ /**
+ * A factory for creating an instance of {@link XMLMapper}.
+ */
+ class Factory {
+
+ private Factory() {
+ }
+
+ /**
+ * Create a new mapper instance.
+ *
+ * @return the new instance
+ */
+ public static XMLMapper create() {
+ return new XMLMapperImpl();
+ }
+ }
+}
diff --git a/src/main/java/org/jboss/staxmapper/XMLMapperImpl.java b/src/main/java/org/jboss/staxmapper/XMLMapperImpl.java
index 0ab438f..3fd0816 100644
--- a/src/main/java/org/jboss/staxmapper/XMLMapperImpl.java
+++ b/src/main/java/org/jboss/staxmapper/XMLMapperImpl.java
@@ -1,134 +1,141 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.staxmapper;
-
-import static javax.xml.stream.XMLStreamConstants.END_DOCUMENT;
-import static javax.xml.stream.XMLStreamConstants.START_DOCUMENT;
-import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.function.Supplier;
-import javax.xml.namespace.QName;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.stream.XMLStreamWriter;
-
-/**
- * @author David M. Lloyd
- */
-final class XMLMapperImpl implements XMLMapper {
- private final ConcurrentMap> rootElements = new ConcurrentHashMap<>();
- private final ConcurrentMap>> rootElementsSuppliers = new ConcurrentHashMap<>();
- private final ConcurrentMap> rootAttributes = new ConcurrentHashMap<>();
-
- public void registerRootElement(QName name, XMLElementReader reader) {
- registerRootElement(name, () -> reader);
- }
-
- public void registerRootElement(QName name, Supplier> supplier) {
- if (rootElementsSuppliers.putIfAbsent(name, supplier) != null) {
- throw new IllegalArgumentException("Root element supplier for " + name + " already registered");
- }
- }
-
- @Override
- public void unregisterRootElement(QName name) {
- rootElements.remove(name);
- }
-
- public void registerRootAttribute(QName name, XMLAttributeReader> reader) {
- if (rootAttributes.putIfAbsent(name, reader) != null) {
- throw new IllegalArgumentException("Root attribute for " + name + " already registered");
- }
- }
-
- @Override
- public void unregisterRootAttribute(QName name) {
- rootAttributes.remove(name);
- }
-
- public void parseDocument(Object rootObject, XMLStreamReader reader) throws XMLStreamException {
- try {
- reader.require(START_DOCUMENT, null, null);
- reader.nextTag();
- reader.require(START_ELEMENT, null, null);
- processNested(new XMLExtendedStreamReaderImpl(this, reader), rootObject);
- while (reader.next() != END_DOCUMENT) {
- }
- reader.close();
- rootElements.clear(); //clear the parsers cache
- } finally {
- try {
- reader.close();
- } catch (Exception e) {
- // log it?
- }
- }
- }
-
- public void deparseDocument(final XMLElementWriter> writer, final Object rootObject, final XMLStreamWriter streamWriter) throws XMLStreamException {
- doDeparse(writer, rootObject, new FormattingXMLStreamWriter(streamWriter));
- }
-
- @SuppressWarnings( { "unchecked" })
- private void doDeparse(XMLElementWriter> writer, final T value, final XMLExtendedStreamWriter streamWriter) throws XMLStreamException {
- ((XMLElementWriter)writer).writeContent(streamWriter, value);
- }
-
- /**
- * Format the content writer's output on to an XML stream writer.
- *
- * @param contentWriter the content writer
- * @param streamWriter the stream writer
- * @throws XMLStreamException if an exception occurs
- */
- public void deparseDocument(XMLContentWriter contentWriter, XMLStreamWriter streamWriter) throws XMLStreamException {
- // todo: add validation based on the registered root elements?
- contentWriter.writeContent(new FormattingXMLStreamWriter(streamWriter));
- }
-
- private XMLElementReader> getParser(final QName name) {
- return rootElements.computeIfAbsent(name, qName -> rootElementsSuppliers.getOrDefault(name, () -> null).get());
- }
-
- @SuppressWarnings({"unchecked"})
- void processNested(final XMLExtendedStreamReader streamReader, final T value) throws XMLStreamException {
- final QName name = streamReader.getName();
- final XMLElementReader reader = (XMLElementReader) getParser(name);
- if (reader == null) {
- throw new XMLStreamException("Unexpected element '" + name + "'", streamReader.getLocation());
- }
- reader.readElement(streamReader, value);
- }
-
- @SuppressWarnings({ "unchecked" })
- void processAttribute(final XMLStreamReader streamReader, final int index, final T value) throws XMLStreamException {
- final QName name = streamReader.getName();
- final XMLAttributeReader reader = (XMLAttributeReader) rootAttributes.get(name);
- if (reader == null) {
- throw new XMLStreamException("Unexpected attribute '" + name + "'", streamReader.getLocation());
- }
- reader.readAttribute(streamReader, index, value);
- }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.staxmapper;
+
+import static javax.xml.stream.XMLStreamConstants.END_DOCUMENT;
+import static javax.xml.stream.XMLStreamConstants.START_DOCUMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Supplier;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+/**
+ * @author David M. Lloyd
+ */
+final class XMLMapperImpl implements XMLMapper {
+ private final ConcurrentMap> rootElements = new ConcurrentHashMap<>();
+ private final ConcurrentMap>> rootElementsSuppliers = new ConcurrentHashMap<>();
+ private final ConcurrentMap> rootAttributes = new ConcurrentHashMap<>();
+
+ @Override
+ public void registerRootElement(QName name, XMLElementReader reader) {
+ registerRootElement(name, () -> reader);
+ }
+
+ @Override
+ public void registerRootElement(QName name, Supplier> supplier) {
+ if (rootElementsSuppliers.putIfAbsent(name, supplier) != null) {
+ throw new IllegalArgumentException("Root element supplier for " + name + " already registered");
+ }
+ }
+
+ @Override
+ public void unregisterRootElement(QName name) {
+ rootElements.remove(name);
+ }
+
+ @Override
+ public void registerRootAttribute(QName name, XMLAttributeReader> reader) {
+ if (rootAttributes.putIfAbsent(name, reader) != null) {
+ throw new IllegalArgumentException("Root attribute for " + name + " already registered");
+ }
+ }
+
+ @Override
+ public void unregisterRootAttribute(QName name) {
+ rootAttributes.remove(name);
+ }
+
+ @Override
+ public void parseDocument(Object rootObject, XMLStreamReader reader) throws XMLStreamException {
+ try {
+ reader.require(START_DOCUMENT, null, null);
+ reader.nextTag();
+ reader.require(START_ELEMENT, null, null);
+ processNested(new XMLExtendedStreamReaderImpl(this, reader), rootObject);
+ while (reader.next() != END_DOCUMENT) {
+ }
+ reader.close();
+ rootElements.clear(); //clear the parsers cache
+ } finally {
+ try {
+ reader.close();
+ } catch (Exception e) {
+ // log it?
+ }
+ }
+ }
+
+ @Override
+ public void deparseDocument(final XMLElementWriter> writer, final Object rootObject, final XMLStreamWriter streamWriter) throws XMLStreamException {
+ doDeparse(writer, rootObject, new FormattingXMLStreamWriter(streamWriter));
+ }
+
+ @SuppressWarnings( { "unchecked" })
+ private void doDeparse(XMLElementWriter> writer, final T value, final XMLExtendedStreamWriter streamWriter) throws XMLStreamException {
+ ((XMLElementWriter)writer).writeContent(streamWriter, value);
+ }
+
+ /**
+ * Format the content writer's output on to an XML stream writer.
+ *
+ * @param contentWriter the content writer
+ * @param streamWriter the stream writer
+ * @throws XMLStreamException if an exception occurs
+ */
+ @Override
+ @SuppressWarnings( "deprecation" )
+ public void deparseDocument(XMLContentWriter contentWriter, XMLStreamWriter streamWriter) throws XMLStreamException {
+ // todo: add validation based on the registered root elements?
+ contentWriter.writeContent(new FormattingXMLStreamWriter(streamWriter));
+ }
+
+ private XMLElementReader> getParser(final QName name) {
+ return rootElements.computeIfAbsent(name, qName -> rootElementsSuppliers.getOrDefault(name, () -> null).get());
+ }
+
+ @SuppressWarnings({"unchecked"})
+ void processNested(final XMLExtendedStreamReader streamReader, final T value) throws XMLStreamException {
+ final QName name = streamReader.getName();
+ final XMLElementReader reader = (XMLElementReader) getParser(name);
+ if (reader == null) {
+ throw new XMLStreamException("Unexpected element '" + name + "'", streamReader.getLocation());
+ }
+ reader.readElement(streamReader, value);
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ void processAttribute(final XMLStreamReader streamReader, final int index, final T value) throws XMLStreamException {
+ final QName name = streamReader.getName();
+ final XMLAttributeReader reader = (XMLAttributeReader) rootAttributes.get(name);
+ if (reader == null) {
+ throw new XMLStreamException("Unexpected attribute '" + name + "'", streamReader.getLocation());
+ }
+ reader.readAttribute(streamReader, index, value);
+ }
+}
diff --git a/src/test/java/org/jboss/staxmapper/SimpleReadTest1.java b/src/test/java/org/jboss/staxmapper/SimpleReadTest1.java
index 61dbd8e..6b88118 100644
--- a/src/test/java/org/jboss/staxmapper/SimpleReadTest1.java
+++ b/src/test/java/org/jboss/staxmapper/SimpleReadTest1.java
@@ -1,81 +1,82 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.staxmapper;
-
-import static javax.xml.stream.XMLStreamConstants.COMMENT;
-import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
-import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
-
-import java.io.StringReader;
-
-import javax.xml.namespace.QName;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import org.junit.Test;
-
-/**
- * @author David M. Lloyd
- */
-public final class SimpleReadTest1 implements XMLElementReader