1 15 package org.apache.hivemind.lib.chain; 16 17 import java.lang.reflect.Modifier ; 18 import java.util.HashMap ; 19 import java.util.List ; 20 import java.util.Map ; 21 22 import org.apache.hivemind.ClassResolver; 23 import org.apache.hivemind.service.BodyBuilder; 24 import org.apache.hivemind.service.ClassFab; 25 import org.apache.hivemind.service.ClassFabUtils; 26 import org.apache.hivemind.service.ClassFactory; 27 import org.apache.hivemind.service.MethodIterator; 28 import org.apache.hivemind.service.MethodSignature; 29 import org.apache.hivemind.util.ConstructorUtils; 30 import org.apache.hivemind.util.Defense; 31 32 38 public class ChainBuilderImpl implements ChainBuilder 39 { 40 private ClassResolver _classResolver; 41 42 private ClassFactory _classFactory; 43 44 47 48 private Map _implementations = new HashMap (); 49 50 public Object buildImplementation(Class commandInterface, List commands, String toString) 51 { 52 Defense.notNull(commandInterface, "commandInterface"); 53 Defense.notNull(commands, "commands"); 54 Defense.notNull(toString, "toString"); 55 56 Class instanceClass = findImplementationClass(commandInterface); 57 58 return createInstance(instanceClass, commands, toString); 59 } 60 61 private synchronized Class findImplementationClass(Class commandInterface) 62 { 63 Class result = (Class ) _implementations.get(commandInterface); 64 65 if (result == null) 66 { 67 result = constructImplementationClass(commandInterface); 68 69 _implementations.put(commandInterface, result); 70 } 71 72 return result; 73 } 74 75 private Class constructImplementationClass(Class commandInterface) 76 { 77 String name = ClassFabUtils.generateClassName(commandInterface); 78 79 ClassFab cf = _classFactory.newClass(name, Object .class); 80 81 addInfrastructure(cf, commandInterface); 82 83 addMethods(cf, commandInterface); 84 85 return cf.createClass(); 86 } 87 88 void addInfrastructure(ClassFab cf, Class commandInterface) 89 { 90 Class array = _classResolver.findClass(commandInterface.getName() + "[]"); 91 92 cf.addInterface(commandInterface); 93 cf.addField("_commands", array); 94 cf.addField("_toString", String .class); 95 96 BodyBuilder builder = new BodyBuilder(); 97 98 builder.begin(); 99 builder.addln("_commands = ({0}[]) $1.toArray(new {0}[0]);", commandInterface.getName()); 100 builder.addln("_toString = $2;"); 101 builder.end(); 102 103 cf.addConstructor(new Class [] 104 { List .class, String .class }, null, builder.toString()); 105 } 106 107 private Object createInstance(Class instanceClass, List commands, String toString) 108 { 109 return ConstructorUtils.invokeConstructor(instanceClass, new Object [] 110 { commands, toString }); 111 } 112 113 void addMethods(ClassFab cf, Class commandInterface) 114 { 115 MethodIterator mi = new MethodIterator(commandInterface); 116 117 while (mi.hasNext()) 118 { 119 MethodSignature sig = mi.next(); 120 121 addMethod(cf, commandInterface, sig); 122 } 123 124 if (!mi.getToString()) 125 addToString(cf); 126 } 127 128 void addMethod(ClassFab cf, Class commandInterface, MethodSignature sig) 129 { 130 Class returnType = sig.getReturnType(); 131 132 if (returnType.equals(void.class)) 133 { 134 addVoidMethod(cf, commandInterface, sig); 135 return; 136 } 137 138 String defaultValue = defaultForReturnType(returnType); 139 140 BodyBuilder builder = new BodyBuilder(); 141 builder.begin(); 142 143 builder 144 .addln( 145 "{0} result = {1};", 146 ClassFabUtils.getJavaClassName(returnType), 147 defaultValue); 148 builder.addln("for (int i = 0; i < _commands.length; i++)"); 149 150 builder.begin(); 151 builder.addln("result = _commands[i].{0}($$);", sig.getName()); 152 153 builder.addln("if (result != {0}) break;", defaultValue); 154 155 builder.end(); 156 157 builder.addln("return result;"); 158 builder.end(); 159 160 cf.addMethod(Modifier.PUBLIC, sig, builder.toString()); 161 } 162 163 String defaultForReturnType(Class returnType) 164 { 165 167 if (!returnType.isPrimitive()) 168 return "null"; 169 170 if (returnType.equals(boolean.class)) 171 return "false"; 172 173 176 return "0"; 177 } 178 179 private void addVoidMethod(ClassFab cf, Class commandInterface, MethodSignature sig) 180 { 181 BodyBuilder builder = new BodyBuilder(); 182 183 builder.begin(); 184 185 builder.addln("for (int i = 0; i < _commands.length; i++)"); 186 builder.addln("_commands[i].{0}($$);", sig.getName()); 187 188 builder.end(); 189 190 cf.addMethod(Modifier.PUBLIC, sig, builder.toString()); 191 } 192 193 void addToString(ClassFab cf) 194 { 195 MethodSignature sig = new MethodSignature(String .class, "toString", null, null); 196 197 cf.addMethod(Modifier.PUBLIC, sig, "return _toString;"); 198 } 199 200 public void setClassFactory(ClassFactory classFactory) 201 { 202 _classFactory = classFactory; 203 } 204 205 public void setClassResolver(ClassResolver classResolver) 206 { 207 _classResolver = classResolver; 208 } 209 } | Popular Tags |