org.milyn.javabean.binding.xml.XMLElementSerializationNode Maven / Gradle / Ivy
The newest version!
/*
* Milyn - Copyright (C) 2006 - 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License (version 2.1) as published by the Free Software
* Foundation.
*
* This library 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:
* http://www.gnu.org/licenses/lgpl.txt
*/
package org.milyn.javabean.binding.xml;
import org.milyn.cdr.xpath.SelectorStep;
import org.milyn.javabean.binding.SerializationContext;
import org.milyn.javabean.binding.model.get.Getter;
import org.milyn.javabean.binding.model.get.GetterGraph;
import org.milyn.javabean.gen.model.ClassConfig;
import org.milyn.xml.XmlUtil;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* Abstract XML Serialization Node.
*
* @author [email protected]
*/
public class XMLElementSerializationNode extends XMLSerializationNode {
private List attributes = new ArrayList();
private List elements = new ArrayList();
public XMLElementSerializationNode(QName qName) {
super(qName);
}
public List getAttributes() {
return attributes;
}
public List getElements() {
return elements;
}
@Override
public void serialize(Writer outputStream, SerializationContext context) throws IOException {
// Write the start of the element...
indent(outputStream, context);
outputStream.write("<");
writeName(outputStream);
// Write the attributes...
writeAttributes(outputStream, context);
if(elements.isEmpty()) {
String value = getValue(context);
if(value != null) {
char[] characters = value.toCharArray();
outputStream.write(">");
XmlUtil.encodeTextValue(characters, 0, characters.length, outputStream);
outputStream.write("");
writeName(outputStream);
outputStream.write(">");
} else {
outputStream.write("/>");
}
} else {
outputStream.write(">");
// Write the child elements...
writeElements(outputStream, context);
// Write the end of the element...
outputStream.write("\n");
indent(outputStream, context);
outputStream.write("");
writeName(outputStream);
outputStream.write(">");
}
}
private void writeAttributes(Writer outputStream, SerializationContext context) throws IOException {
for(XMLAttributeSerializationNode attribute : attributes) {
attribute.serialize(outputStream, context);
}
}
private void writeElements(Writer outputStream, SerializationContext context) throws IOException {
context.incDepth();
for(XMLElementSerializationNode element : elements) {
if(element.isCollection) {
NodeGetter collectionNodeGetter = element.getCollectionGetter();
Getter collectionGetter = collectionNodeGetter.getter;
Object collectionObject;
List> collection = null;
if (collectionGetter instanceof GetterGraph) {
collectionObject = context.getValue(((GetterGraph) collectionGetter).getContextObjectName(), collectionGetter);
} else {
collectionObject = context.getValue(collectionGetter);
}
if(collectionObject instanceof List) {
collection = (List>) collectionObject;
} else if(collectionObject instanceof Object[]) {
collection = Arrays.asList((Object[]) collectionObject);
}
if(collection != null && !collection.isEmpty()) {
try {
for (Object collectionItem : collection) {
context.addObject(collectionNodeGetter.contextObjectName, collectionItem);
outputStream.write("\n");
element.serialize(outputStream, context);
}
} finally {
// Be sure to clear this from the context...
context.removeObject(collectionNodeGetter.contextObjectName);
}
}
} else {
if(element.hasData(context)) {
outputStream.write("\n");
element.serialize(outputStream, context);
}
}
}
context.decDepth();
}
@Override
protected boolean hasData(SerializationContext context) {
// If any part of the element has data...
if(super.hasData(context)) {
return true;
}
for(XMLAttributeSerializationNode attribute : attributes) {
if(attribute.hasData(context)) {
return true;
}
}
return false;
}
private static final char[] INDENT_BUF = new char[512];
static {
Arrays.fill(INDENT_BUF, ' ');
}
private void indent(Writer outputStream, SerializationContext context) throws IOException {
int indent = context.getCurrentDepth() * 4; // Indent 4 spaces per level in the hierarchy...
if(indent > 0) {
indent = Math.min(indent, INDENT_BUF.length); // Making sure we don't OOB on the indent buffer
outputStream.write(INDENT_BUF, 0, indent);
}
}
public XMLSerializationNode findNode(SelectorStep[] selectorSteps) {
if(selectorSteps.length == 1) {
if(selectorSteps[0].getTargetAttribute() != null) {
return getAttribute(selectorSteps[0], attributes, false);
}
return this;
}
return getPathNode(selectorSteps, 1, false);
}
public XMLSerializationNode getPathNode(SelectorStep[] selectorSteps, int stepIndex, boolean create) {
if(stepIndex >= selectorSteps.length) {
throw new IllegalStateException("Unexpected call to 'addPathNode'. SelectorStep index out of bounds.");
}
SelectorStep selectorStep = selectorSteps[stepIndex];
if(stepIndex == selectorSteps.length - 1 && selectorStep.getTargetAttribute() != null) {
// It's an attribute node...
XMLElementSerializationNode elementNode = getElement(selectorStep, elements, create);
return addAttributeNode(elementNode, selectorStep, create);
} else {
// It's an element...
XMLElementSerializationNode childElement = getElement(selectorStep, elements, create);
if(childElement != null) {
childElement.setParent(this);
if(stepIndex < selectorSteps.length - 1) {
// Drill down again...
return childElement.getPathNode(selectorSteps, stepIndex + 1, create);
} else {
return childElement;
}
} else {
return null;
}
}
}
public static XMLSerializationNode addAttributeNode(XMLElementSerializationNode elementNode, SelectorStep selectorStep, boolean create) {
XMLAttributeSerializationNode attribute = getAttribute(selectorStep, elementNode.attributes, create);
if(attribute != null) {
attribute.setParent(elementNode);
}
return attribute;
}
public static XMLElementSerializationNode getElement(SelectorStep step, Collection elementList, boolean create) {
QName qName = step.getTargetElement();
XMLElementSerializationNode element = getNode(qName, elementList);
if(element == null && create) {
element = new XMLElementSerializationNode(qName);
elementList.add(element);
}
return element;
}
public static XMLAttributeSerializationNode getAttribute(SelectorStep step, Collection attributeList, boolean create) {
QName qName = step.getTargetAttribute();
XMLAttributeSerializationNode attribute = getNode(qName, attributeList);
if(attribute == null && create) {
attribute = new XMLAttributeSerializationNode(qName);
attributeList.add(attribute);
}
return attribute;
}
@Override
protected Object clone() {
XMLElementSerializationNode clone = new XMLElementSerializationNode(qName);
copyProperties(clone);
for(XMLElementSerializationNode element : elements) {
XMLElementSerializationNode elementClone = (XMLElementSerializationNode) element.clone();
clone.elements.add(elementClone);
elementClone.setParent(clone);
}
for(XMLAttributeSerializationNode attribute : attributes) {
XMLAttributeSerializationNode attributeClone = (XMLAttributeSerializationNode) attribute.clone();
clone.attributes.add(attributeClone);
attributeClone.setParent(clone);
}
return clone;
}
}