KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > hivemind > lib > chain > ChainBuilderImpl


1 // Copyright 2005 The Apache Software Foundation
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15 package org.apache.hivemind.lib.chain;
16
17 import java.lang.reflect.Modifier JavaDoc;
18 import java.util.HashMap JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
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 /**
33  * Gang of Four Chain of Commands Pattern.
34  *
35  * @author Howard M. Lewis Ship
36  * @since 1.1
37  */

38 public class ChainBuilderImpl implements ChainBuilder
39 {
40     private ClassResolver _classResolver;
41
42     private ClassFactory _classFactory;
43
44     /**
45      * Map, keyed on service interface, of Class.
46      */

47
48     private Map JavaDoc _implementations = new HashMap JavaDoc();
49
50     public Object JavaDoc buildImplementation(Class JavaDoc commandInterface, List JavaDoc commands, String JavaDoc toString)
51     {
52         Defense.notNull(commandInterface, "commandInterface");
53         Defense.notNull(commands, "commands");
54         Defense.notNull(toString, "toString");
55
56         Class JavaDoc instanceClass = findImplementationClass(commandInterface);
57
58         return createInstance(instanceClass, commands, toString);
59     }
60
61     private synchronized Class JavaDoc findImplementationClass(Class JavaDoc commandInterface)
62     {
63         Class JavaDoc result = (Class JavaDoc) _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 JavaDoc constructImplementationClass(Class JavaDoc commandInterface)
76     {
77         String JavaDoc name = ClassFabUtils.generateClassName(commandInterface);
78
79         ClassFab cf = _classFactory.newClass(name, Object JavaDoc.class);
80
81         addInfrastructure(cf, commandInterface);
82
83         addMethods(cf, commandInterface);
84
85         return cf.createClass();
86     }
87
88     void addInfrastructure(ClassFab cf, Class JavaDoc commandInterface)
89     {
90         Class JavaDoc array = _classResolver.findClass(commandInterface.getName() + "[]");
91
92         cf.addInterface(commandInterface);
93         cf.addField("_commands", array);
94         cf.addField("_toString", String JavaDoc.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 JavaDoc[]
104         { List JavaDoc.class, String JavaDoc.class }, null, builder.toString());
105     }
106
107     private Object JavaDoc createInstance(Class JavaDoc instanceClass, List JavaDoc commands, String JavaDoc toString)
108     {
109         return ConstructorUtils.invokeConstructor(instanceClass, new Object JavaDoc[]
110         { commands, toString });
111     }
112
113     void addMethods(ClassFab cf, Class JavaDoc 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 JavaDoc commandInterface, MethodSignature sig)
129     {
130         Class JavaDoc returnType = sig.getReturnType();
131
132         if (returnType.equals(void.class))
133         {
134             addVoidMethod(cf, commandInterface, sig);
135             return;
136         }
137
138         String JavaDoc 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 JavaDoc defaultForReturnType(Class JavaDoc returnType)
164     {
165         // For all object and array types.
166

167         if (!returnType.isPrimitive())
168             return "null";
169
170         if (returnType.equals(boolean.class))
171             return "false";
172
173         // Assume, then, that it is a numeric type (this method
174
// isn't called for void).
175

176         return "0";
177     }
178
179     private void addVoidMethod(ClassFab cf, Class JavaDoc 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 JavaDoc.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