Clover coverage report - Code Coverage for tapestry release 4.0-rc-2
Coverage timestamp: Sat Dec 17 2005 09:39:46 PST
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  2942 public static String createMutatorMethodName(String propertyName)
 53    {
 54  2942 return "set" + upcase(propertyName);
 55    }
 56   
 57  561 public static String createAccessorMethodName(String propertyName)
 58    {
 59  561 return "get" + upcase(propertyName);
 60    }
 61   
 62  3503 private static String upcase(String name)
 63    {
 64  3503 return name.substring(0, 1).toUpperCase() + name.substring(1);
 65    }
 66   
 67  2279 public static void createSimpleAccessor(EnhancementOperation op, String fieldName,
 68    String propertyName, Class propertyType, Location location)
 69    {
 70  2279 String methodName = op.getAccessorMethodName(propertyName);
 71   
 72  2279 op.addMethod(
 73    Modifier.PUBLIC,
 74    new MethodSignature(propertyType, methodName, null, null),
 75    "return " + fieldName + ";",
 76    location);
 77    }
 78   
 79  1758 public static void createSimpleMutator(EnhancementOperation op, String fieldName,
 80    String propertyName, Class propertyType, Location location)
 81    {
 82  1758 String methodName = createMutatorMethodName(propertyName);
 83   
 84  1758 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  1535 public static Class extractPropertyType(EnhancementOperation op, String propertyName,
 106    String definedTypeName)
 107    {
 108  1535 Defense.notNull(op, "op");
 109  1535 Defense.notNull(propertyName, "propertyName");
 110   
 111  1535 if (definedTypeName != null)
 112    {
 113  92 Class propertyType = op.convertTypeName(definedTypeName);
 114   
 115  90 op.validateProperty(propertyName, propertyType);
 116   
 117  90 return propertyType;
 118    }
 119   
 120  1443 Class propertyType = op.getPropertyType(propertyName);
 121   
 122  1443 return propertyType == null ? Object.class : propertyType;
 123    }
 124   
 125    // The following methods are actually invoked from fabricated methods in
 126    // enhanced classes.
 127   
 128  266 public static boolean toBoolean(IBinding binding)
 129    {
 130  266 Boolean wrapped = (Boolean) binding.getObject(Boolean.class);
 131   
 132  265 return wrapped == null ? false : wrapped.booleanValue();
 133    }
 134   
 135  2 public static byte toByte(IBinding binding)
 136    {
 137  2 Byte wrapped = (Byte) binding.getObject(Byte.class);
 138   
 139  2 return wrapped == null ? 0 : wrapped.byteValue();
 140    }
 141   
 142  2 public static char toChar(IBinding binding)
 143    {
 144  2 Character wrapped = (Character) binding.getObject(Character.class);
 145   
 146  2 return wrapped == null ? 0 : wrapped.charValue();
 147    }
 148   
 149  2 public static short toShort(IBinding binding)
 150    {
 151  2 Short wrapped = (Short) binding.getObject(Short.class);
 152   
 153  2 return wrapped == null ? 0 : wrapped.shortValue();
 154    }
 155   
 156  12 public static int toInt(IBinding binding)
 157    {
 158  12 Integer wrapped = (Integer) binding.getObject(Integer.class);
 159   
 160  12 return wrapped == null ? 0 : wrapped.intValue();
 161    }
 162   
 163  2 public static long toLong(IBinding binding)
 164    {
 165  2 Long wrapped = (Long) binding.getObject(Long.class);
 166   
 167  2 return wrapped == null ? 0 : wrapped.longValue();
 168    }
 169   
 170  2 public static float toFloat(IBinding binding)
 171    {
 172  2 Float wrapped = (Float) binding.getObject(Float.class);
 173   
 174  2 return wrapped == null ? 0.0f : wrapped.floatValue();
 175    }
 176   
 177  4 public static double toDouble(IBinding binding)
 178    {
 179  4 Double wrapped = (Double) binding.getObject(Double.class);
 180   
 181  4 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  1 _unwrappers.put(boolean.class, "toBoolean");
 195  1 _unwrappers.put(byte.class, "toByte");
 196  1 _unwrappers.put(char.class, "toChar");
 197  1 _unwrappers.put(short.class, "toShort");
 198  1 _unwrappers.put(int.class, "toInt");
 199  1 _unwrappers.put(long.class, "toLong");
 200  1 _unwrappers.put(float.class, "toFloat");
 201  1 _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  1081 public static String getUnwrapperMethodName(Class type)
 210    {
 211  1081 Defense.notNull(type, "type");
 212   
 213  1081 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  1081 public static String createUnwrapExpression(EnhancementOperation op, String bindingName,
 230    Class valueType)
 231    {
 232  1081 Defense.notNull(op, "op");
 233  1081 Defense.notNull(bindingName, "bindingName");
 234  1081 Defense.notNull(valueType, "valueType");
 235   
 236  1081 StringBuffer buffer = new StringBuffer();
 237   
 238  1081 String unwrapper = getUnwrapperMethodName(valueType);
 239   
 240  1081 if (unwrapper == null)
 241    {
 242  811 String propertyTypeRef = op.getClassReference(valueType);
 243   
 244  811 buffer.append("(");
 245  811 buffer.append(ClassFabUtils.getJavaClassName(valueType));
 246  811 buffer.append(") ");
 247  811 buffer.append(bindingName);
 248  811 buffer.append(".getObject(");
 249  811 buffer.append(propertyTypeRef);
 250  811 buffer.append(")");
 251    }
 252    else
 253    {
 254  270 buffer.append(EnhanceUtils.class.getName());
 255  270 buffer.append(".");
 256  270 buffer.append(unwrapper);
 257  270 buffer.append("(");
 258  270 buffer.append(bindingName);
 259  270 buffer.append(")");
 260    }
 261   
 262  1081 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  5 public static Class verifyPropertyType(EnhancementOperation op, String propertyName,
 277    Class requiredType)
 278    {
 279  5 Defense.notNull(op, "op");
 280  5 Defense.notNull(propertyName, "propertyName");
 281  5 Defense.notNull(requiredType, "requiredType");
 282   
 283  5 Class propertyType = op.getPropertyType(propertyName);
 284   
 285    // When the property type is not defined, it will end up being
 286  5 if (propertyType == null)
 287  1 return Object.class;
 288   
 289    // Make sure that an object of the required type is assignable
 290    // to the property type.
 291   
 292  4 if (!propertyType.isAssignableFrom(requiredType))
 293  1 throw new ApplicationRuntimeException(EnhanceMessages.wrongTypeForProperty(
 294    propertyName,
 295    propertyType,
 296    requiredType));
 297   
 298  3 return propertyType;
 299    }
 300    }