1 package net.sourceforge.jparam.conversion.creators;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Modifier;
6 import java.util.HashSet;
7 import java.util.Iterator;
8 import java.util.Set;
9
10 import net.sourceforge.jparam.conversion.ConverterRegistry;
11 import net.sourceforge.jparam.conversion.converters.CreatorConverter;
12 import net.sourceforge.jparam.conversion.converters.ParentConverter;
13 import net.sourceforge.jparam.util.MultiMap;
14 import net.sourceforge.jparam.util.Utils;
15
16 /***
17 * This registry holds all the available creators for all registered Java
18 * classes
19 *
20 * Once a <code>Class</code> is registered, all of its constructors are
21 * defined as creator
22 * <p>
23 * Constructors with a single argument are also defined as converters from the
24 * arguments type to the class type
25 *
26 * @author ron_sidi
27 *
28 */
29 public class CreatorRegistry {
30 private static CreatorRegistry registry = null;
31
32 private MultiMap creators = new MultiMap();
33
34 private Set registeredClasses = new HashSet();
35
36 private CreatorRegistry() {
37 }
38
39 public static CreatorRegistry getInstance() {
40 if (registry == null) {
41 registry = new CreatorRegistry();
42 }
43 return registry;
44 }
45
46 Set getCreators(Class c) {
47 return creators.get(c);
48 }
49
50 /***
51 * Register all the creation method defined in the given helper class, a
52 * method is considered a creation method if:
53 * <p>
54 * <li>The method name begins with create (this is needed because Java
55 * doesn't distinguish between methods according to their return type)
56 * <li>The method is <code>public</code></li>
57 * <li>The method is <code>static</code></li>
58 * <li>The method has exactly one argument</li>
59 * <li>The method has a typed return value that is not primitive or void</li>
60 *
61 *
62 * @param c
63 */
64 public void registerHelperClass(Class c) {
65 Method[] creatorClassMethods = c.getMethods();
66 for (int i = 0; i < creatorClassMethods.length; i++) {
67 Method m = creatorClassMethods[i];
68
69 if (MethodCreator.isMethodValid(m)) {
70 MethodCreator mc = new MethodCreator(m);
71
72 registerCreator(mc);
73 }
74 }
75 }
76
77 public void registerClass(Class c) {
78 Utils.assert(!registeredClasses.contains(c), "Class " + c.getName()
79 + " already registered");
80 registeredClasses.add(c);
81 Constructor[] classConstructors = c.getConstructors();
82 for (int i = 0; i < classConstructors.length; i++) {
83 if (Modifier.isPublic(classConstructors[i].getModifiers())) {
84 ConstructorCreator creator = new ConstructorCreator(
85 classConstructors[i]);
86 registerCreator(creator);
87 }
88 }
89
90
91
92
93
94
95
96
97
98
99 for (Iterator iter = registeredClasses.iterator(); iter.hasNext();) {
100 Class existingClass = (Class) iter.next();
101 if (existingClass.equals(c.getSuperclass())) {
102 ConverterRegistry.getInstance().registerConverter(
103 new ParentConverter(existingClass, c));
104 }
105
106 if (c.equals(existingClass.getSuperclass())) {
107 ConverterRegistry.getInstance().registerConverter(
108 new ParentConverter(c, existingClass));
109 }
110 }
111 }
112
113 private void registerCreator(ICreator c) {
114 Utils.assert(registeredClasses.contains(c.getReturnClass()),
115 "Registering creator for non-registered class..." + c);
116 creators.put(c.getReturnClass(), c);
117 if (c.getParameterTypes().length == 1) {
118 ConverterRegistry.getInstance().registerConverter(
119 new CreatorConverter(c));
120 }
121 }
122
123 public static void clearSingleton() {
124 registry = null;
125 }
126 }