Clover coverage report - Code Coverage for tapestry release 4.0-alpha-3
Coverage timestamp: Mon May 16 2005 09:05:49 EDT
file stats: LOC: 298   Methods: 17
NCLOC: 169   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
EnhanceUtils.java 100% 85.9% 70.6% 84.7%
coverage coverage
 1   
 // Copyright 2004, 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.tapestry.enhance;
 16   
 
 17   
 import java.lang.reflect.Modifier;
 18   
 import java.util.HashMap;
 19   
 import java.util.Map;
 20   
 
 21   
 import org.apache.hivemind.ApplicationRuntimeException;
 22   
 import org.apache.hivemind.service.ClassFabUtils;
 23   
 import org.apache.hivemind.service.MethodSignature;
 24   
 import org.apache.hivemind.util.Defense;
 25   
 import org.apache.tapestry.IBinding;
 26   
 import org.apache.tapestry.IRequestCycle;
 27   
 import org.apache.tapestry.engine.IPageLoader;
 28   
 import org.apache.tapestry.event.PageEvent;
 29   
 import org.apache.tapestry.spec.IComponentSpecification;
 30   
 
 31   
 /**
 32   
  * Convienience methods needed by various parts of the enhancement subsystem.
 33   
  * 
 34   
  * @author Howard M. Lewis Ship
 35   
  * @since 4.0
 36   
  */
 37   
 public class EnhanceUtils
 38   
 {
 39   
     public static final MethodSignature FINISH_LOAD_SIGNATURE = new MethodSignature(void.class,
 40   
             "finishLoad", new Class[]
 41   
             { IRequestCycle.class, IPageLoader.class, IComponentSpecification.class }, null);
 42   
 
 43   
     public static final MethodSignature PAGE_DETACHED_SIGNATURE = new MethodSignature(void.class,
 44   
             "pageDetached", new Class[]
 45   
             { PageEvent.class }, null);
 46   
 
 47   
     public static final MethodSignature CLEANUP_AFTER_RENDER_SIGNATURE = new MethodSignature(
 48   
             void.class, "cleanupAfterRender", new Class[]
 49   
             { IRequestCycle.class }, null);
 50   
 
 51  1773
     public static String createMutatorMethodName(String propertyName)
 52   
     {
 53  1773
         return "set" + upcase(propertyName);
 54   
     }
 55   
 
 56  577
     public static String createAccessorMethodName(String propertyName)
 57   
     {
 58  577
         return "get" + upcase(propertyName);
 59   
     }
 60   
 
 61  2350
     private static String upcase(String name)
 62   
     {
 63  2350
         return name.substring(0, 1).toUpperCase() + name.substring(1);
 64   
     }
 65   
 
 66  1124
     public static void createSimpleAccessor(EnhancementOperation op, String fieldName,
 67   
             String propertyName, Class propertyType)
 68   
     {
 69  1124
         String methodName = op.getAccessorMethodName(propertyName);
 70   
 
 71  1124
         op.addMethod(
 72   
                 Modifier.PUBLIC,
 73   
                 new MethodSignature(propertyType, methodName, null, null),
 74   
                 "return " + fieldName + ";");
 75   
     }
 76   
 
 77  540
     public static void createSimpleMutator(EnhancementOperation op, String fieldName,
 78   
             String propertyName, Class propertyType)
 79   
     {
 80  540
         String methodName = createMutatorMethodName(propertyName);
 81   
 
 82  540
         op.addMethod(Modifier.PUBLIC, new MethodSignature(void.class, methodName, new Class[]
 83   
         { propertyType }, null), fieldName + " = $1;");
 84   
     }
 85   
 
 86   
     /**
 87   
      * Returns the correct class for a property to be enhanced into a class. If a type name is
 88   
      * non-null, then it is converted to a Class. If the class being enhanced defines a property,
 89   
      * then the type must be an exact match (this is largely a holdover from Tapestry 3.0, where the
 90   
      * type had to be provided in the specification). If the type name is null, then the value
 91   
      * returned is the type of the existing property (if such a property exists), or
 92   
      * java.lang.Object is no property exists.
 93   
      * 
 94   
      * @param op
 95   
      *            the enhancement operation, which provides most of this logic
 96   
      * @param propertyName
 97   
      *            the name of the property (the property may or may not exist)
 98   
      * @param definedTypeName
 99   
      *            the type indicated for the property, may be null to make the return value match
 100   
      *            the type of an existing property.
 101   
      */
 102   
 
 103  1371
     public static Class extractPropertyType(EnhancementOperation op, String propertyName,
 104   
             String definedTypeName)
 105   
     {
 106  1371
         Defense.notNull(op, "op");
 107  1371
         Defense.notNull(propertyName, "propertyName");
 108   
 
 109  1371
         if (definedTypeName != null)
 110   
         {
 111  106
             Class propertyType = op.convertTypeName(definedTypeName);
 112   
 
 113  104
             op.validateProperty(propertyName, propertyType);
 114   
 
 115  104
             return propertyType;
 116   
         }
 117   
 
 118  1265
         Class propertyType = op.getPropertyType(propertyName);
 119   
 
 120  1265
         return propertyType == null ? Object.class : propertyType;
 121   
     }
 122   
 
 123   
     // The following methods are actually invoked from fabricated methods in
 124   
     // enhanced classes.
 125   
 
 126  311
     public static boolean toBoolean(IBinding binding)
 127   
     {
 128  311
         Boolean wrapped = (Boolean) binding.getObject(Boolean.class);
 129   
 
 130  310
         return wrapped.booleanValue();
 131   
     }
 132   
 
 133  0
     public static byte toByte(IBinding binding)
 134   
     {
 135  0
         Byte wrapped = (Byte) binding.getObject(Byte.class);
 136   
 
 137  0
         return wrapped.byteValue();
 138   
     }
 139   
 
 140  0
     public static char toChar(IBinding binding)
 141   
     {
 142  0
         Character wrapped = (Character) binding.getObject(Character.class);
 143   
 
 144  0
         return wrapped.charValue();
 145   
     }
 146   
 
 147  0
     public static short toShort(IBinding binding)
 148   
     {
 149  0
         Short wrapped = (Short) binding.getObject(Short.class);
 150   
 
 151  0
         return wrapped.shortValue();
 152   
     }
 153   
 
 154  10
     public static int toInt(IBinding binding)
 155   
     {
 156  10
         Integer wrapped = (Integer) binding.getObject(Integer.class);
 157   
 
 158  10
         return wrapped.intValue();
 159   
     }
 160   
 
 161  0
     public static long toLong(IBinding binding)
 162   
     {
 163  0
         Long wrapped = (Long) binding.getObject(Long.class);
 164   
 
 165  0
         return wrapped.longValue();
 166   
     }
 167   
 
 168  0
     public static float toFloat(IBinding binding)
 169   
     {
 170  0
         Float wrapped = (Float) binding.getObject(Float.class);
 171   
 
 172  0
         return wrapped.floatValue();
 173   
     }
 174   
 
 175  2
     public static double toDouble(IBinding binding)
 176   
     {
 177  2
         Double wrapped = (Double) binding.getObject(Double.class);
 178   
 
 179  2
         return wrapped.doubleValue();
 180   
     }
 181   
 
 182   
     /**
 183   
      * Used to unwrap primitive types inside the accessor method. In each case, the binding is in a
 184   
      * variable named "binding", and {0} will be the actual type of the property. The Map is keyed
 185   
      * on the primtive type.
 186   
      */
 187   
 
 188   
     private static Map _unwrappers = new HashMap();
 189   
 
 190   
     static
 191   
     {
 192  1
         _unwrappers.put(boolean.class, "toBoolean");
 193  1
         _unwrappers.put(byte.class, "toByte");
 194  1
         _unwrappers.put(char.class, "toChar");
 195  1
         _unwrappers.put(short.class, "toShort");
 196  1
         _unwrappers.put(int.class, "toInt");
 197  1
         _unwrappers.put(long.class, "toLong");
 198  1
         _unwrappers.put(float.class, "toFloat");
 199  1
         _unwrappers.put(double.class, "toDouble");
 200   
     }
 201   
 
 202   
     /**
 203   
      * Returns the name of the static method, within EnhanceUtils, used to unwrap a binding to a
 204   
      * primitive type. Returns null if the type is not a primitve.
 205   
      */
 206   
 
 207  1139
     public static String getUnwrapperMethodName(Class type)
 208   
     {
 209  1139
         Defense.notNull(type, "type");
 210   
 
 211  1139
         return (String) _unwrappers.get(type);
 212   
     }
 213   
 
 214   
     /**
 215   
      * Builds a Javassist expression for unwrapping a binding's value to a type (either primitive or
 216   
      * a class type).
 217   
      * 
 218   
      * @param op
 219   
      *            the enhancement operation
 220   
      * @param bindingName
 221   
      *            the name of the field (or an expression) that will evaluate to the binding from
 222   
      *            which a value will be extracted.
 223   
      * @param valueType
 224   
      *            the type of value to be extracted from the binding.
 225   
      */
 226   
 
 227  1139
     public static String createUnwrapExpression(EnhancementOperation op, String bindingName,
 228   
             Class valueType)
 229   
     {
 230  1139
         Defense.notNull(op, "op");
 231  1139
         Defense.notNull(bindingName, "bindingName");
 232  1139
         Defense.notNull(valueType, "valueType");
 233   
 
 234  1139
         StringBuffer buffer = new StringBuffer();
 235   
 
 236  1139
         String unwrapper = getUnwrapperMethodName(valueType);
 237   
 
 238  1139
         if (unwrapper == null)
 239   
         {
 240  832
             String propertyTypeRef = op.getClassReference(valueType);
 241   
 
 242  832
             buffer.append("(");
 243  832
             buffer.append(ClassFabUtils.getJavaClassName(valueType));
 244  832
             buffer.append(") ");
 245  832
             buffer.append(bindingName);
 246  832
             buffer.append(".getObject(");
 247  832
             buffer.append(propertyTypeRef);
 248  832
             buffer.append(")");
 249   
         }
 250   
         else
 251   
         {
 252  307
             buffer.append(EnhanceUtils.class.getName());
 253  307
             buffer.append(".");
 254  307
             buffer.append(unwrapper);
 255  307
             buffer.append("(");
 256  307
             buffer.append(bindingName);
 257  307
             buffer.append(")");
 258   
         }
 259   
 
 260  1139
         return buffer.toString();
 261   
     }
 262   
 
 263   
     /**
 264   
      * Verifies that a property type can be assigned a particular type of value.
 265   
      * 
 266   
      * @param op
 267   
      *            the enhancement operation
 268   
      * @param propertyName
 269   
      *            the name of the property to check
 270   
      * @param requiredType
 271   
      *            the type of value that will be assigned to the property
 272   
      * @return the property type, or java.lang.Object if the class does not define the property
 273   
      */
 274  5
     public static Class verifyPropertyType(EnhancementOperation op, String propertyName,
 275   
             Class requiredType)
 276   
     {
 277  5
         Defense.notNull(op, "op");
 278  5
         Defense.notNull(propertyName, "propertyName");
 279  5
         Defense.notNull(requiredType, "requiredType");
 280   
 
 281  5
         Class propertyType = op.getPropertyType(propertyName);
 282   
 
 283   
         // When the property type is not defined, it will end up being
 284  5
         if (propertyType == null)
 285  1
             return Object.class;
 286   
 
 287   
         // Make sure that an object of the required type is assignable
 288   
         // to the property type.
 289   
 
 290  4
         if (!propertyType.isAssignableFrom(requiredType))
 291  1
             throw new ApplicationRuntimeException(EnhanceMessages.wrongTypeForProperty(
 292   
                     propertyName,
 293   
                     propertyType,
 294   
                     requiredType));
 295   
 
 296  3
         return propertyType;
 297   
     }
 298   
 }