package com.skaringa.javaxml.handler.sax;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import com.skaringa.javaxml.SerializerException;
import com.skaringa.javaxml.handler.AttrImpl;
import com.skaringa.javaxml.handler.DocumentOutputHandlerInterface;
import com.skaringa.javaxml.serializers.ComponentSerializer;
import com.skaringa.javaxml.serializers.SerializerRegistry;
/**
* A implementation of the SAX2 XMLReader interface.
* This class is able to parse serializable objects and write their type
* definition as an XML schema definition (XSD).
*/
public final class ObjectXSDReader extends AbstractXMLReader {
private Collection _dependendClasses = new Vector();
/**
* @see AbstractXMLReader#parseObject(Object, Class, DocumentOutputHandlerInterface)
*/
public void parseObject(
Object obj,
Class type,
DocumentOutputHandlerInterface output)
throws SerializerException {
try {
type = (Class) obj;
}
catch (ClassCastException e) {
throw new SerializerException(
"wrong context: obj needs to be of type Class, but is: "
+ obj.getClass().getName());
}
SerializerRegistry reg = SerializerRegistry.getInstance();
ComponentSerializer ser = reg.getSerializer(type);
output.startDocument();
output.startElement("xsd:schema");
AttrImpl attr = new AttrImpl();
attr.addAttribute("name", ser.getXMLTypeName());
attr.addAttribute("type", ser.getXMLTypeName());
attr.addAttribute("nillable", "true");
output.startElement("xsd:element", attr);
output.endElement("xsd:element");
// get and document all used classes
_dependendClasses.add(type);
Set usedClasses = new HashSet();
Iterator it = _dependendClasses.iterator();
while (it.hasNext()) {
Class aClass = (Class) it.next();
ser = reg.getSerializer(aClass);
ser.addUsedClasses(aClass, usedClasses);
}
documentUsedClasses(usedClasses, output);
output.endElement("xsd:schema");
output.endDocument();
}
/**
* Add another class to document within the schema.
* This is useful for generating schemas for collections,
* because their component types are not documented in the class definition.
* @param usedClass The class used.
*/
public void addUsedClass(Class usedClass) {
_dependendClasses.add(usedClass);
}
/**
* Add a collection of classes to document within the schema.
* This is useful for generating schemas for collections,
* because their component types are not documented in the class definition.
* @param usedClasses A collection of classes used.
*/
public void addUsedClasses(Collection usedClasses) {
_dependendClasses.addAll(usedClasses);
}
/**
* Write the XML type definitions of the used classes.
* @param theClasses List of classes to document.
* @param output The output to write the definition to.
* @throws SerializerException If something goes wrong.
*/
private void documentUsedClasses(
Collection theClasses,
DocumentOutputHandlerInterface output)
throws SerializerException {
SerializerRegistry reg = SerializerRegistry.getInstance();
Iterator it = theClasses.iterator();
while (it.hasNext()) {
Class type = (Class) it.next();
ComponentSerializer ser = reg.getSerializer(type);
ser.writeXMLTypeDefinition(type, getPropertyMap(), output);
}
}
}