View Javadoc

1   package org.lcsim.util.xml;
2   
3   import java.lang.reflect.Constructor;
4   import java.lang.reflect.InvocationTargetException;
5   import java.util.ArrayList;
6   import java.util.HashMap;
7   import java.util.List;
8   import java.util.Map;
9   import org.jdom.Element;
10  import org.jdom.JDOMException;
11  
12  
13  /**
14   * The default implementation of ElementFactory.
15   * @author tonyj
16   */
17  public class DefaultElementFactory implements ElementFactory
18  {
19     private List<Class> classes = new ArrayList<Class>();
20     private Map<Class,String> packageMap = new HashMap<Class,String>();
21     
22     /**
23      * Create the default element factory.
24      */
25     public DefaultElementFactory()
26     {}
27     
28     public <T> T createElement(Class<T> c, Element node, String type) throws JDOMException, ElementCreationException
29     {
30        if (type != null)
31        {
32           Class<T> cand = getElementClass(c,type);
33           if (cand != null) return create(cand,node);
34        }
35        for (Class cand  : classes)
36        {
37           if (c.isAssignableFrom(cand)) return create((Class<? extends T>) cand,node);
38        }
39        throw new ElementCreationException("Unknown element "+c);
40     }
41     
42     public void register(Class elementClass,String packageName)
43     {
44        packageMap.put(elementClass,packageName);
45     }
46     /**
47      * Register a class with the factory. Future calls to create any class which is a subclass 
48      * of this class will cause a new instance of this class to be created. The class specificed
49      * must have a constructor which takes a jdom Element as its argument.
50      * @param elementClass The class to register.
51      */
52     public void register(Class elementClass)
53     {
54        classes.add(0,elementClass);
55     }
56     private <T> T create(Class<T> type, Element node) throws ElementCreationException
57     {
58        try
59        {
60           Constructor<T> c = type.getDeclaredConstructor(Element.class);
61           c.setAccessible(true);
62           return c.newInstance(node);
63        }
64        catch (NoSuchMethodException x)
65        {
66           throw new ElementCreationException("Could not create element: "+type,x);
67        }
68        catch (InvocationTargetException x)
69        {
70           throw new ElementCreationException("Could not create element: "+type,x.getCause());
71        }
72        catch (InstantiationException x)
73        {
74           throw new ElementCreationException("Could not create element: "+type,x.getCause());
75        }
76        catch (IllegalAccessException x)
77        {
78           throw new ElementCreationException("Could not create element: "+type,x);
79        }
80     }
81     public <T> Class<T> getElementClass(Class<T> type, String name) throws ElementCreationException
82     {
83        String packageName = packageMap.get(type);
84        if (packageName == null) return null;
85        String key = packageName+"."+name;
86        try
87        {
88           Class result = Class.forName(key);
89           if (!type.isAssignableFrom(result)) throw new ElementCreationException("Element "+key+" is of wrong type");
90           return (Class<T>) result;
91        }
92        catch (ClassNotFoundException x)
93        {
94           return null;
95        }
96     }
97  }