package net.sourceforge.javautil.common.xml;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import net.sourceforge.javautil.common.CollectionUtil;
import net.sourceforge.javautil.common.ReflectionUtil;
import net.sourceforge.javautil.common.reflection.ObjectManager;
import net.sourceforge.javautil.common.reflection.cache.ClassMethod;
import net.sourceforge.javautil.common.reflection.cache.ClassProperty;
import net.sourceforge.javautil.common.xml.annotation.XmlParent;
import net.sourceforge.javautil.common.xml.annotation.XmlCollection.CollectionType;
import net.sourceforge.javautil.common.xml.annotation.XmlTag.ElementType;
import org.xml.sax.Attributes;
/**
* This is the basis for {@link XMLDocument} element handling.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: XMLDocumentElementComplexType.java 2465 2010-10-24 11:42:26Z ponderator $
*/
public class XMLDocumentElementComplexType<T> extends XMLDocumentElementBase {
protected final ObjectManager instance;
protected XMLDocumentElementComplexType(XMLDocumentElementDefinition definition, T instance) {
this(null, definition, instance);
}
public XMLDocumentElementComplexType(XMLDocumentElement parent, XMLDocumentElementDefinition definition, T instance) {
super(parent, definition);
this.instance = ObjectManager.getManager(instance);
ClassProperty parentMethod = this.instance.getDescriptor().getProperty(XmlParent.class);
if (parentMethod != null) {
XMLDocumentElement parentElement = this.getComplexParent(parent, parentMethod.getType());
if (parentMethod != null) {
parentMethod.setValue(instance, parentElement.getManager().getInstance());
}
}
}
public XMLDocumentElement getComplexParent (XMLDocumentElement parent, Class type) {
while (parent.getParent() != null) {
parent = parent.getParent();
if (type.isAssignableFrom(parent.getManager().getInstance().getClass())) break;
}
return parent;
}
public void applyAttributes(Attributes attributes) {
for (int a=0; a<attributes.getLength(); a++) {
XMLDocumentElementDefinition def = definition.getComplexProperty(attributes.getQName(a)); //.getLocalName(a));
if (def != null && (def.getElementType() == ElementType.Attribute)) {
getManager().setProperty(def.getName(), ReflectionUtil.coerce(def.getClassType(), attributes.getValue(a)));
}
}
}
@Override public ObjectManager getManager() { return instance; }
public XMLDocumentElement startElement(String namespace, String prefix, String name) {
XMLDocumentElementDefinition def = definition.getComplexProperty(name);
XMLDocumentElement element = def != null && def.isXml() ? create(def) : null;
if (element instanceof XMLDocumentElementCollection && def.getCollectionType() == CollectionType.CUMMULATIVE) {
return element.startElement(namespace, prefix, name);
}
return element;
}
public void appendContents(char[] contents, int offset, int length, boolean cdata, boolean ignorable) {}
public void write(XMLWriter writer) {
this.writeStart(writer);
this.writeAttributes(writer);
this.writeContents(writer);
this.writeEnd(writer);
}
public void writeStart(XMLWriter writer) {
writer.startElement(this.getName());
}
public void writeAttributes(XMLWriter writer) {
Map<String, ClassProperty> properties = this.instance.getDescriptor().getProperties();
for (String propertyName : properties.keySet()) {
XMLDocumentElementDefinition def = new XMLDocumentElementDefinition(definition, properties.get(propertyName));
if (def.getElementType() == ElementType.Attribute) {
Object value = this.instance.getProperty(propertyName);
if (value != null)
writer.writeAttribute(null, def.getTagName(), ReflectionUtil.coerce(String.class, value));
}
}
}
public void writeContents(XMLWriter writer) {
Map<String, ClassProperty> properties = this.instance.getDescriptor().getProperties();
List<XMLDocumentElementDefinition> children = new ArrayList<XMLDocumentElementDefinition>();
for (String propertyName : properties.keySet()) {
XMLDocumentElementDefinition def = new XMLDocumentElementDefinition(definition, properties.get(propertyName));
if (def == null || (def != null && !def.isXml())) continue;
if (def.getElementType() != ElementType.Attribute) {
children.add(def);
}
}
Collections.sort(children);
for (XMLDocumentElementDefinition child : children) {
Object instance = this.instance.getProperty(child.getName());
if (instance != null) {
XMLDocumentElement childElement = this.create(child, instance);
childElement.write(writer);
}
}
}
public void writeEnd(XMLWriter writer) {
writer.endElement(this.getName());
}
}