(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());

Betwixt/TipsAndHints/HierarchalXmlIntrospector (last edited 2009-09-20 23:48:42 by localhost)