Clover coverage report - Code Coverage for hivemind-lib release 1.1-alpha-3
Coverage timestamp: Tue Mar 22 2005 09:11:37 EST
file stats: LOC: 209   Methods: 12
NCLOC: 130   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 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   
 }