2009/04/15 - Apache HiveMind has been retired.

For more information, please explore the Attic.

Clover coverage report - Code Coverage for hivemind-lib release 1.2.1
Coverage timestamp: Fri Feb 10 2006 16:34:07 PST
file stats: LOC: 209   Methods: 12
NCLOC: 130   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ChainBuilderImpl.java 91.7% 100% 100% 98.9%
coverage coverage
 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;
 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    /**
 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 _implementations = new HashMap();
 49   
 50  4 public Object buildImplementation(Class commandInterface, List commands, String toString)
 51    {
 52  4 Defense.notNull(commandInterface, "commandInterface");
 53  4 Defense.notNull(commands, "commands");
 54  4 Defense.notNull(toString, "toString");
 55   
 56  4 Class instanceClass = findImplementationClass(commandInterface);
 57   
 58  4 return createInstance(instanceClass, commands, toString);
 59    }
 60   
 61  4 private synchronized Class findImplementationClass(Class commandInterface)
 62    {
 63  4 Class result = (Class) _implementations.get(commandInterface);
 64   
 65  4 if (result == null)
 66    {
 67  3 result = constructImplementationClass(commandInterface);
 68   
 69  3 _implementations.put(commandInterface, result);
 70    }
 71   
 72  4 return result;
 73    }
 74   
 75  3 private Class constructImplementationClass(Class commandInterface)
 76    {
 77  3 String name = ClassFabUtils.generateClassName(commandInterface);
 78   
 79  3 ClassFab cf = _classFactory.newClass(name, Object.class);
 80   
 81  3 addInfrastructure(cf, commandInterface);
 82   
 83  3 addMethods(cf, commandInterface);
 84   
 85  3 return cf.createClass();
 86    }
 87   
 88  3 void addInfrastructure(ClassFab cf, Class commandInterface)
 89    {
 90  3 Class array = _classResolver.findClass(commandInterface.getName() + "[]");
 91   
 92  3 cf.addInterface(commandInterface);
 93  3 cf.addField("_commands", array);
 94  3 cf.addField("_toString", String.class);
 95   
 96  3 BodyBuilder builder = new BodyBuilder();
 97   
 98  3 builder.begin();
 99  3 builder.addln("_commands = ({0}[]) $1.toArray(new {0}[0]);", commandInterface.getName());
 100  3 builder.addln("_toString = $2;");
 101  3 builder.end();
 102   
 103  3 cf.addConstructor(new Class[]
 104    { List.class, String.class }, null, builder.toString());
 105    }
 106   
 107  4 private Object createInstance(Class instanceClass, List commands, String toString)
 108    {
 109  4 return ConstructorUtils.invokeConstructor(instanceClass, new Object[]
 110    { commands, toString });
 111    }
 112   
 113  3 void addMethods(ClassFab cf, Class commandInterface)
 114    {
 115  3 MethodIterator mi = new MethodIterator(commandInterface);
 116   
 117  3 while (mi.hasNext())
 118    {
 119  3 MethodSignature sig = mi.next();
 120   
 121  3 addMethod(cf, commandInterface, sig);
 122    }
 123   
 124  3 if (!mi.getToString())
 125  3 addToString(cf);
 126    }
 127   
 128  5 void addMethod(ClassFab cf, Class commandInterface, MethodSignature sig)
 129    {
 130  5 Class returnType = sig.getReturnType();
 131   
 132  5 if (returnType.equals(void.class))
 133    {
 134  1 addVoidMethod(cf, commandInterface, sig);
 135  1 return;
 136    }
 137   
 138  4 String defaultValue = defaultForReturnType(returnType);
 139   
 140  4 BodyBuilder builder = new BodyBuilder();
 141  4 builder.begin();
 142   
 143  4 builder
 144    .addln(
 145    "{0} result = {1};",
 146    ClassFabUtils.getJavaClassName(returnType),
 147    defaultValue);
 148  4 builder.addln("for (int i = 0; i < _commands.length; i++)");
 149   
 150  4 builder.begin();
 151  4 builder.addln("result = _commands[i].{0}($$);", sig.getName());
 152   
 153  4 builder.addln("if (result != {0}) break;", defaultValue);
 154   
 155  4 builder.end();
 156   
 157  4 builder.addln("return result;");
 158  4 builder.end();
 159   
 160  4 cf.addMethod(Modifier.PUBLIC, sig, builder.toString());
 161    }
 162   
 163  10 String defaultForReturnType(Class returnType)
 164    {
 165    // For all object and array types.
 166   
 167  10 if (!returnType.isPrimitive())
 168  4 return "null";
 169   
 170  6 if (returnType.equals(boolean.class))
 171  5 return "false";
 172   
 173    // Assume, then, that it is a numeric type (this method
 174    // isn't called for void).
 175   
 176  1 return "0";
 177    }
 178   
 179  1 private void addVoidMethod(ClassFab cf, Class commandInterface, MethodSignature sig)
 180    {
 181  1 BodyBuilder builder = new BodyBuilder();
 182   
 183  1 builder.begin();
 184   
 185  1 builder.addln("for (int i = 0; i < _commands.length; i++)");
 186  1 builder.addln("_commands[i].{0}($$);", sig.getName());
 187   
 188  1 builder.end();
 189   
 190  1 cf.addMethod(Modifier.PUBLIC, sig, builder.toString());
 191    }
 192   
 193  3 void addToString(ClassFab cf)
 194    {
 195  3 MethodSignature sig = new MethodSignature(String.class, "toString", null, null);
 196   
 197  3 cf.addMethod(Modifier.PUBLIC, sig, "return _toString;");
 198    }
 199   
 200  3 public void setClassFactory(ClassFactory classFactory)
 201    {
 202  3 _classFactory = classFactory;
 203    }
 204   
 205  3 public void setClassResolver(ClassResolver classResolver)
 206    {
 207  3 _classResolver = classResolver;
 208    }
 209    }