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