(This actually doesn't work that well and probably isn't what the Betwixt authors had in mind. For a better solution, see ../HierarchalClassNormalizer)
This works for marshalling, but has some quirks when unmarshalling. (Specifically, when unmarshalling the correct bean type is created, but none of the properties are initialized. I suspect this is because the AttributeDescriptor has no updaters, which may in turn be caused by some quirk when executing java.beans.Introspector on a subclass.)
import java.io.*;
import java.util.*;
import org.apache.commons.betwixt.*;
import org.apache.commons.betwixt.digester.*;
import org.apache.commons.logging.*;
/**
*
* @author Jesse Sweetland
*/
public class HierarchalXMLIntrospector extends XMLIntrospector {
/** Private, so we have to copy here */
private XMLBeanInfoDigester digester;
protected synchronized XMLBeanInfo findByXMLDescriptor(Class c) {
Set<Class> classes = new LinkedHashSet<Class>();
Class temp = c;
while(temp != null) {
classes.add(temp);
for(Class ifc: temp.getInterfaces()) {
classes.add(ifc);
}
temp = temp.getSuperclass();
}
for(Class c2: classes) {
String resourcePath = getResourcePath(c2);
InputStream in = c2.getResourceAsStream(resourcePath);
if(in != null) {
try {
configureDigester(c);
return (XMLBeanInfo)digester.parse(in);
} catch(Throwable t) {
getLog().warn("Error parsing XML bean info resource " + resourcePath, t);
}
}
}
return null;
}
/** Private, so we have to copy here */
private synchronized void configureDigester(Class aClass) {
if ( digester == null ) {
digester = new XMLBeanInfoDigester();
digester.setXMLIntrospector( this );
}
digester.setBeanClass( aClass );
}
protected String getResourcePath(Class c) {
return c.getName().substring(c.getName().lastIndexOf('.') + 1) + ".betwixt";
}
}To use this, just set the XMLIntrospector property on the BeanWriter:
BeanWriter bw = new BeanWriter(); bw.setXMLIntrospector(new HierarchalXMLIntrospector());