/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* 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
*******************************************************************************/
package org.ebayopensource.turmeric.runtime.binding.objectnode;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
/**
* Utility class to render an {@link ObjectNode} to a previously-created {@link XMLStreamWriter}.
* The class is stateless and therefore thread-safe (provided the method arguments are thread-safe).
* <strong>Note: </strong>This utility should only be used when JAXB-based serialization
* is not available.
*
* @author mpoplacenel
*/
public final class ObjectNodeWriter {
private static final String INDENT = " ";
private static final String NL = System.getProperty("line.separator");
/**
* Prints the given object node to the given {@link XMLStreamWriter}.
*
* @param objNode the node to be printed.
* @param xmlStreamWriter the XML stream writer to write to.
*
* @throws XMLStreamException for access problems.
*/
public void write(ObjectNode objNode, XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
write(objNode, xmlStreamWriter, false);
}
/**
* Prints the given object node to the given {@link XMLStreamWriter}.
*
* @param objNode the node to be printed.
* @param xmlStreamWriter the XML stream writer to write to.
* @param prettyPrint <code>true</code> for a human-friendly, pretty-printed version,
* <code>false</code> for a more compact and economical one.
*
* @throws XMLStreamException for access problems.
*/
public void write(ObjectNode objNode, XMLStreamWriter xmlStreamWriter, boolean prettyPrint)
throws XMLStreamException {
writeAsXMLInternal(0, objNode, xmlStreamWriter, false);
}
/**
* The method writes an XML node including its attributes and child nodes.
*
* @param level The nested level
* @param objNode The ObjectNode to write
* @param xsw The XMLStreamWriter to output the payload.
* @param prettyPrint formats the payload if it is true.
* @throws XMLStreamException an XMLStream exception
*/
protected final void writeAsXMLInternal(int level, ObjectNode objNode, XMLStreamWriter xsw, boolean prettyPrint)
throws XMLStreamException {
final QName nodeQName = objNode.getNodeName();
xsw.writeStartElement(nodeQName.getNamespaceURI(), nodeQName.getLocalPart());
writeAttributes(objNode, xsw);
writeChildren(level, objNode, xsw, prettyPrint);
xsw.writeEndElement();
}
/**
* Write the children of the given object node.
* @param level the level the node is at.
* @param objNode the object node.
* @param xsw The XMLStreamWriter to output the payload.
* @param prettyPrint formats the payload if it is true.
* @throws XMLStreamException an XMLStream exception
*/
protected void writeChildren(int level, ObjectNode objNode,
XMLStreamWriter xsw, boolean prettyPrint) throws XMLStreamException {
List<ObjectNode> childNodes = objNode.getChildNodes();
if (childNodes != null && childNodes.size() > 0) {
indent(prettyPrint, level + 1, xsw);
int i = 0;
for (ObjectNode childNode : childNodes) {
if (i++ > 0) {
indent(prettyPrint, level + 1, xsw);
}
writeAsXMLInternal(level + 1, childNode, xsw, prettyPrint);
}
indent(prettyPrint, level, xsw);
} else {
final Object nodeValue = objNode.getNodeValue() == null ? "" : objNode.getNodeValue();
xsw.writeCharacters(nodeValue.toString());
}
}
/**
* Writes all the attributes of the given ObjectNode.
*
* @param objNode the ObjectNode of an attribute
* @param xsw The XMLStreamWriter to output the payload.
* @throws XMLStreamException an XMLStream exception
*/
protected void writeAttributes(ObjectNode objNode, XMLStreamWriter xsw)
throws XMLStreamException {
List<ObjectNode> attributes = objNode.getAttributes();
if (attributes != null && attributes.size() > 0) {
for (ObjectNode attrNode : attributes) {
writeAttributeNode(attrNode, xsw);
}
}
}
/**
* Writes the given attribute node.
* @param attrNode ObjectNode for an attribute.
* @param xsw an XMLStreamWriter to output the payload.
* @throws XMLStreamException XMLStream exception.
*/
protected void writeAttributeNode(ObjectNode attrNode, XMLStreamWriter xsw)
throws XMLStreamException {
QName attrQName = attrNode.getNodeName();
Object attrValue = attrNode.getNodeValue() == null ? "" : attrNode.getNodeValue();
xsw.writeAttribute(attrQName.getNamespaceURI(), attrQName.getLocalPart(), attrValue.toString());
}
/**
* Goes to next line and advance to the indent location.
* @param prettyPrint format the output if true.
* @param level The level of indentation.
* @param xsw an XMLStreamWriter to output the payload.
* @throws XMLStreamException XMLStream exception.
*/
protected void indent(boolean prettyPrint, int level, XMLStreamWriter xsw) throws XMLStreamException {
if (!prettyPrint) return;
xsw.writeCharacters(NL);
doIndent(level, xsw);
}
/**
* Advances to the indent location.
* @param level The level of indentation.
* @param xsw an XMLStreamWriter to output the payload.
* @throws XMLStreamException XMLStream exception.
*/
protected void doIndent(int level, XMLStreamWriter xsw) throws XMLStreamException {
for (int j = 0; j < level; j++) {
xsw.writeCharacters(INDENT);
}
}
}