Clover coverage report - Drools - 2.0-rc2
Coverage timestamp: Wed May 11 2005 07:12:26 BST
file stats: LOC: 311   Methods: 24
NCLOC: 276   Classes: 7
 
 Source file Conditionals Statements Methods TOTAL
AnnonatedPojoRuleBuilder.java 90.6% 96.5% 95.8% 95.1%
coverage coverage
 1    package org.drools.semantics.annotation.model;
 2   
 3    import java.lang.annotation.Annotation;
 4    import java.lang.reflect.Method;
 5    import java.util.ArrayList;
 6    import java.util.HashSet;
 7    import java.util.List;
 8    import java.util.Set;
 9   
 10    import org.drools.DroolsException;
 11    import org.drools.rule.Declaration;
 12    import org.drools.rule.InvalidRuleException;
 13    import org.drools.rule.Rule;
 14    import org.drools.semantics.annotation.DroolsParameter;
 15    import org.drools.semantics.annotation.DroolsApplicationData;
 16    import org.drools.semantics.annotation.DroolsCondition;
 17    import org.drools.semantics.annotation.DroolsConsequence;
 18    import org.drools.semantics.base.ClassObjectType;
 19    import org.drools.spi.Consequence;
 20    import org.drools.spi.KnowledgeHelper;
 21   
 22    public class AnnonatedPojoRuleBuilder
 23    {
 24    // TODO Extract the parameter factory registy to its own abstraction
 25    private static final Set<ParameterValueFactory> parameterValueFatories
 26    = new HashSet<ParameterValueFactory>();
 27   
 28    static {
 29  4 registerParameterValueFactory(new KnowledgeHelperParameterValueFactory());
 30  4 registerParameterValueFactory(new DroolsTupleParameterValueFactory());
 31  4 registerParameterValueFactory(new DroolsApplicationDataParameterValueFactory());
 32    }
 33   
 34  12 public static void registerParameterValueFactory( ParameterValueFactory factory)
 35    {
 36  12 for (ParameterValueFactory registeredFactory : parameterValueFatories) {
 37  12 if (factory.getParameterValueType() == registeredFactory.getParameterValueType()) {
 38  0 throw new IllegalArgumentException("ParameterValueFactory already registered"
 39    + ": type=" + factory.getParameterValueType()
 40    + ", factory =" + factory
 41    + ", registered factory=" + registeredFactory);
 42    }
 43    }
 44  12 parameterValueFatories.add(factory);
 45    }
 46   
 47    private static interface ParameterValidator
 48    {
 49    void assertParameter( ParameterValue newParameterValue, List<ParameterValue> parameterValues )
 50    throws DroolsException;
 51    }
 52   
 53  17 public Rule buildRule( Rule rule, Object pojo ) throws DroolsException
 54    {
 55  17 Class< ? > ruleClass = pojo.getClass( );
 56  17 buildConditions( rule, ruleClass, pojo );
 57  14 buildConsequence( rule, ruleClass, pojo );
 58  9 return rule;
 59    }
 60   
 61  17 private static void buildConditions( Rule rule, Class< ? > ruleClass, Object pojo )
 62    throws DroolsException
 63    {
 64  17 for (Method method : ruleClass.getMethods( ))
 65    {
 66  164 DroolsCondition conditionAnnotation = method.getAnnotation( DroolsCondition.class );
 67  164 if (conditionAnnotation != null)
 68    {
 69  14 PojoCondition condition = newPojoCondition( rule, pojo, method );
 70  11 rule.addCondition( condition );
 71    }
 72    }
 73    }
 74   
 75  14 private static void buildConsequence( Rule rule, Class< ? > ruleClass, Object pojo )
 76    throws DroolsException
 77    {
 78  14 Consequence consequence = null;
 79  14 for (Method method : ruleClass.getMethods( ))
 80    {
 81  124 DroolsConsequence consequenceAnnotation = method
 82    .getAnnotation( DroolsConsequence.class );
 83  124 if (consequenceAnnotation != null)
 84    {
 85  14 if (consequence != null)
 86    {
 87  1 throw new DroolsException( "Rule must only contain one consequence method"
 88    + ": class = " + ruleClass + ", method = " + method );
 89    }
 90  13 consequence = newPojoConsequence( rule, pojo, method );
 91  10 rule.setConsequence( consequence );
 92    }
 93    }
 94  10 if (consequence == null)
 95    {
 96  1 throw new DroolsException( "Rule must define a consequence method" + ": class = "
 97    + ruleClass );
 98    }
 99    }
 100   
 101  14 private static PojoCondition newPojoCondition( Rule rule, Object pojo, Method pojoMethod )
 102    throws DroolsException
 103    {
 104  14 assertReturnType( pojoMethod, boolean.class );
 105  13 ParameterValidator parameterValidator = new ParameterValidator( ) {
 106  16 public void assertParameter( ParameterValue newParameterValue,
 107    List<ParameterValue> parameterValues )
 108    throws DroolsException
 109    {
 110  16 if (newParameterValue instanceof KnowledgeHelperParameterValue)
 111    {
 112  1 throw new DroolsException(
 113    "Condition methods cannot declare a parameter of type KnowledgeHelper" );
 114    }
 115    }
 116    };
 117  13 return new PojoCondition( new RuleReflectMethod( rule, pojo, pojoMethod,
 118    getParameterValues( rule, pojoMethod, parameterValidator ) ) );
 119    }
 120   
 121  13 private static PojoConsequence newPojoConsequence( Rule rule, Object pojo, Method pojoMethod )
 122    throws DroolsException
 123    {
 124  13 assertReturnType( pojoMethod, void.class );
 125  12 ParameterValidator parameterValidator = new ParameterValidator( ) {
 126    private boolean hasDroolsParameterValue;
 127   
 128  18 public void assertParameter( ParameterValue newParameterValue,
 129    List<ParameterValue> parameterValues )
 130    throws DroolsException
 131    {
 132  18 if (newParameterValue instanceof KnowledgeHelperParameterValue)
 133    {
 134  9 if (hasDroolsParameterValue)
 135    {
 136  1 throw new DroolsException(
 137    "Consequence methods can only declare on parameter of type Drools" );
 138    }
 139  8 hasDroolsParameterValue = true;
 140    }
 141    }
 142    };
 143  12 return new PojoConsequence( new RuleReflectMethod( rule, pojo, pojoMethod,
 144    getParameterValues( rule, pojoMethod, parameterValidator ) ) );
 145    }
 146   
 147  27 private static void assertReturnType( Method method, Class returnClass ) throws DroolsException
 148    {
 149  27 if (method.getReturnType( ) != returnClass)
 150    {
 151  2 throw new DroolsException( "Rule method returns the wrong class" + ": method = "
 152    + method + ", expected return class = " + returnClass
 153    + ", actual return class = " + method.getReturnType( ) );
 154    }
 155    }
 156   
 157  25 private static ParameterValue[] getParameterValues( Rule rule, Method method,
 158    ParameterValidator validator )
 159    throws DroolsException
 160    {
 161  25 Class< ? >[] parameterClasses = method.getParameterTypes( );
 162  25 Annotation[][] parameterAnnotations = method.getParameterAnnotations( );
 163  25 List<ParameterValue> parameterValues = new ArrayList<ParameterValue>( );
 164   
 165  25 for (int i = 0; i < parameterClasses.length; i++)
 166    {
 167  36 Class< ? > parameterClass = parameterClasses[i];
 168  36 ParameterValue parameterValue = null;
 169  36 try
 170    {
 171  36 parameterValue = getParameterValue( rule, parameterClass, parameterAnnotations[i] );
 172  34 validator.assertParameter( parameterValue, parameterValues );
 173    }
 174    catch (DroolsException e)
 175    {
 176  4 throwContextDroolsException( method, i, parameterClass, e );
 177    }
 178  32 parameterValues.add( parameterValue );
 179    }
 180  21 return parameterValues.toArray( new ParameterValue[parameterValues.size( )] );
 181    }
 182   
 183    // TODO Extract all these classes to file-level.
 184    public interface ParameterValueFactory
 185    {
 186    Class<? extends ParameterValue> getParameterValueType();
 187   
 188    ParameterValue create ( Rule rule, Class< ? > parameterClass,
 189    Annotation[] parameterAnnotations) throws DroolsException;
 190    }
 191   
 192    public static abstract class AnnotationParameterValueFactory implements ParameterValueFactory
 193    {
 194    private final Class<? extends Annotation> annotationClass;
 195   
 196  8 protected AnnotationParameterValueFactory(Class<? extends Annotation> annotationClass) {
 197  8 this.annotationClass = annotationClass;
 198    }
 199   
 200    protected abstract ParameterValue doCreate( Rule rule,
 201    Class< ? > parameterClass,
 202    Annotation annotation) throws InvalidRuleException;
 203   
 204  43 public ParameterValue create ( Rule rule, Class< ? > parameterClass,
 205    Annotation[] parameterAnnotations) throws DroolsException {
 206  43 Annotation annotation = getAnnotation(annotationClass, parameterAnnotations);
 207  43 if (annotation == null) {
 208  19 return null;
 209    }
 210  24 return doCreate(rule, parameterClass, annotation);
 211    }
 212   
 213  43 private Annotation getAnnotation(Class<? extends Annotation> annotationClass, Annotation[] parameterAnnotations) {
 214  43 for (Annotation annotation : parameterAnnotations) {
 215  39 if (annotationClass.isAssignableFrom(annotation.getClass())) {
 216  24 return annotation;
 217    }
 218    }
 219  19 return null;
 220    }
 221    }
 222   
 223    public static class KnowledgeHelperParameterValueFactory implements ParameterValueFactory
 224    {
 225  8 public Class<? extends ParameterValue> getParameterValueType() {
 226  8 return KnowledgeHelperParameterValue.class;
 227    }
 228   
 229  30 public ParameterValue create ( Rule rule, Class< ? > parameterClass,
 230    Annotation[] parameterAnnotations) {
 231  30 if (parameterClass != KnowledgeHelper.class) {
 232  20 return null;
 233    }
 234  10 return new KnowledgeHelperParameterValue( rule );
 235    }
 236    }
 237   
 238    public static class DroolsTupleParameterValueFactory extends AnnotationParameterValueFactory
 239    {
 240  4 public DroolsTupleParameterValueFactory() {
 241  4 super(DroolsParameter.class);
 242    }
 243   
 244  8 public Class<? extends ParameterValue> getParameterValueType() {
 245  8 return TupleParameterValue.class;
 246    }
 247   
 248  21 @Override
 249    public ParameterValue doCreate ( Rule rule, Class< ? > parameterClass,
 250    Annotation annotation) throws InvalidRuleException {
 251  21 String parameterId = ((DroolsParameter) annotation).value( );
 252  21 Declaration declaration = rule.getParameterDeclaration( parameterId );
 253  21 if (declaration == null)
 254    {
 255  11 ClassObjectType classObjectType = new ClassObjectType( parameterClass );
 256  11 declaration = rule.addParameterDeclaration( parameterId, classObjectType );
 257    }
 258  21 return new TupleParameterValue( declaration );
 259    }
 260    }
 261   
 262    public static class DroolsApplicationDataParameterValueFactory extends AnnotationParameterValueFactory
 263    {
 264  4 public DroolsApplicationDataParameterValueFactory() {
 265  4 super(DroolsApplicationData.class);
 266    }
 267   
 268  8 public Class<? extends ParameterValue> getParameterValueType() {
 269  8 return ApplicationDataParameterValue.class;
 270    }
 271   
 272  3 @Override
 273    public ParameterValue doCreate ( Rule rule, Class< ? > parameterClass,
 274    Annotation annotation) {
 275  3 String parameterId = ((DroolsApplicationData) annotation).value( );
 276  3 return new ApplicationDataParameterValue( parameterId, parameterClass );
 277    }
 278    }
 279   
 280  36 private static ParameterValue getParameterValue( Rule rule, Class< ? > parameterClass,
 281    Annotation[] parameterAnnotations )
 282    throws DroolsException
 283    {
 284  36 ParameterValue parameterValue;
 285  36 for (ParameterValueFactory factory : parameterValueFatories) {
 286  73 parameterValue = factory.create(rule, parameterClass, parameterAnnotations);
 287  73 if (parameterValue != null) {
 288  34 return parameterValue;
 289    }
 290    }
 291  2 throw new DroolsException(
 292    "Method parameter type not recognized or not annotated" );
 293    }
 294   
 295  4 private static void throwContextDroolsException( Method method, int i,
 296    Class< ? > parameterClass, Exception e )
 297    throws DroolsException
 298    {
 299  4 throw new DroolsException( e.getMessage( ) + ": method = " + method + ", parameter[" + i
 300    + "] = " + parameterClass, e );
 301    }
 302   
 303  0 private static void assertNonConflictingParameterAnnotation( ParameterValue parameterValue )
 304    throws DroolsException
 305    {
 306  0 if (parameterValue != null)
 307    {
 308  0 throw new DroolsException( "Method parameter contains conflicting @Drools annotations" );
 309    }
 310    }
 311    }