package com.kixeye.kixmpp.jdom;
/*
* #%L
* KIXMPP Parent
* %%
* Copyright (C) 2014 KIXEYE, Inc
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import org.codehaus.stax2.XMLStreamReader2;
import org.jdom2.Attribute;
import org.jdom2.AttributeType;
import org.jdom2.DefaultJDOMFactory;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.JDOMFactory;
import org.jdom2.Namespace;
import org.jdom2.input.stax.DTDParser;
/**
* Builds a JDOM {@link Document} from a StAX Stream. This class is NOT thread safe.
*
* @author ebahtijaragic
*/
public class StAXElementBuilder {
private JDOMFactory builderFactory = new DefaultJDOMFactory();
private final boolean ignoreInvalidNamespaces;
private Element rootElement;
private Element currentElement;
/**
* @param ignoreInvalidNamespaces
*/
public StAXElementBuilder(boolean ignoreInvalidNamespaces) {
this.ignoreInvalidNamespaces = ignoreInvalidNamespaces;
}
/**
* Processes the current event on a stream reader.
*
* @param streamReader
* @throws JDOMException
*/
public void process(XMLStreamReader2 streamReader) throws JDOMException {
switch (streamReader.getEventType()) {
case XMLStreamReader2.START_ELEMENT:
{
// build the element
Namespace namespace = getNamespace(streamReader.getPrefix(), streamReader.getNamespaceURI());
Element element = null;
if (namespace == null) {
element = builderFactory.element(streamReader.getLocalName());
} else {
element = builderFactory.element(streamReader.getLocalName(), getNamespace(streamReader.getPrefix(), streamReader.getNamespaceURI()));
}
if (rootElement == null) {
rootElement = element;
currentElement = element;
} else {
currentElement.addContent(element);
currentElement = element;
}
// set attributes
for (int i = 0, len = streamReader.getAttributeCount(); i<len ; i++) {
namespace = getNamespace(streamReader.getAttributePrefix(i), streamReader.getAttributeNamespace(i));
Attribute attribute = null;
if (namespace == null) {
attribute = builderFactory.attribute(
streamReader.getAttributeLocalName(i),
streamReader.getAttributeValue(i),
AttributeType.getAttributeType(streamReader.getAttributeType(i)),
getNamespace(streamReader.getAttributePrefix(i), streamReader.getAttributeNamespace(i)));
} else {
attribute = builderFactory.attribute(
streamReader.getAttributeLocalName(i),
streamReader.getAttributeValue(i),
AttributeType.getAttributeType(streamReader.getAttributeType(i)));
}
builderFactory.setAttribute(element, attribute);
}
// set namespaces
for (int i = 0, len = streamReader.getNamespaceCount(); i < len; i++) {
namespace = getNamespace(streamReader.getNamespacePrefix(i), streamReader.getNamespaceURI(i));
if (namespace != null) {
element.addNamespaceDeclaration(namespace);
}
}
}
break;
case XMLStreamReader2.END_ELEMENT:
{
if (currentElement != null) {
currentElement = currentElement.getParentElement();
if (currentElement == null) {
currentElement = rootElement;
}
}
}
break;
case XMLStreamReader2.SPACE:
case XMLStreamReader2.CHARACTERS:
{
currentElement.addContent(builderFactory.text(streamReader.getText()));
}
break;
case XMLStreamReader2.CDATA:
{
currentElement.addContent(builderFactory.cdata(streamReader.getText()));
}
break;
case XMLStreamReader2.ENTITY_REFERENCE:
{
currentElement.addContent(builderFactory.entityRef(streamReader.getText()));
}
break;
case XMLStreamReader2.COMMENT:
{
currentElement.addContent(builderFactory.comment(streamReader.getText()));
}
break;
case XMLStreamReader2.PROCESSING_INSTRUCTION:
{
currentElement.addContent(builderFactory.processingInstruction(streamReader.getPITarget(), streamReader.getPIData()));
}
break;
case XMLStreamReader2.DTD:
{
currentElement.addContent(DTDParser.parse(streamReader.getText(), builderFactory));
}
break;
}
}
/**
* Gets the namespace.
*
* @param prefix
* @param uri
* @return
*/
private Namespace getNamespace(String prefix, String uri) {
Namespace namespace = null;
try {
namespace = Namespace.getNamespace(prefix, uri);
} catch (Exception e) {
if (!ignoreInvalidNamespaces) {
throw e;
}
}
return namespace;
}
/**
* Gets the element in the current state.
*
* @return
*/
public Element getElement() {
return rootElement;
}
}