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: 201   Methods: 7
NCLOC: 118   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
SpecifiedPropertyWorker.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.Iterator;
 19   
 
 20   
 import org.apache.hivemind.ErrorLog;
 21   
 import org.apache.hivemind.Location;
 22   
 import org.apache.hivemind.service.BodyBuilder;
 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.IComponent;
 27   
 import org.apache.tapestry.binding.BindingSource;
 28   
 import org.apache.tapestry.event.PageDetachListener;
 29   
 import org.apache.tapestry.spec.IComponentSpecification;
 30   
 import org.apache.tapestry.spec.IPropertySpecification;
 31   
 
 32   
 /**
 33   
  * Responsible for adding properties to a class corresponding to specified properties in the
 34   
  * component's specification.
 35   
  * 
 36   
  * @author Howard M. Lewis Ship
 37   
  * @since 4.0
 38   
  */
 39   
 public class SpecifiedPropertyWorker implements EnhancementWorker
 40   
 {
 41   
     private ErrorLog _errorLog;
 42   
 
 43   
     private BindingSource _bindingSource;
 44   
 
 45   
     /**
 46   
      * Iterates over the specified properties, creating an enhanced property for each (a field, an
 47   
      * accessor, a mutator). Persistent properties will invoke
 48   
      * {@link org.apache.tapestry.Tapestry#fireObservedChange(IComponent, String, Object)}in thier
 49   
      * mutator.
 50   
      */
 51   
 
 52  466
     public void performEnhancement(EnhancementOperation op, IComponentSpecification spec)
 53   
     {
 54  466
         Iterator i = spec.getPropertySpecificationNames().iterator();
 55   
 
 56  466
         while (i.hasNext())
 57   
         {
 58  104
             String name = (String) i.next();
 59  104
             IPropertySpecification ps = spec.getPropertySpecification(name);
 60   
 
 61  104
             try
 62   
             {
 63  104
                 performEnhancement(op, ps);
 64   
             }
 65   
             catch (RuntimeException ex)
 66   
             {
 67  1
                 _errorLog.error(
 68   
                         EnhanceMessages.errorAddingProperty(name, op.getBaseClass(), ex),
 69   
                         ps.getLocation(),
 70   
                         ex);
 71   
             }
 72   
         }
 73   
     }
 74   
 
 75  104
     private void performEnhancement(EnhancementOperation op, IPropertySpecification ps)
 76   
     {
 77  104
         Defense.notNull(ps, "ps");
 78   
 
 79  104
         String propertyName = ps.getName();
 80   
 
 81  104
         Class propertyType = EnhanceUtils.extractPropertyType(op, propertyName, ps.getType());
 82   
 
 83  103
         op.claimProperty(propertyName);
 84   
 
 85  103
         String field = "_$" + propertyName;
 86   
 
 87  103
         op.addField(field, propertyType);
 88   
 
 89   
         // Release 3.0 would squack a bit about overriding non-abstract methods
 90   
         // if they exist. 4.0 is less picky ... it blindly adds new methods, possibly
 91   
         // overwriting methods in the base component class.
 92   
 
 93  103
         EnhanceUtils.createSimpleAccessor(op, field, propertyName, propertyType);
 94   
 
 95  103
         addMutator(op, propertyName, propertyType, field, ps.isPersistent());
 96   
 
 97  103
         String initialValue = ps.getInitialValue();
 98   
 
 99  103
         if (initialValue == null)
 100  97
             addReinitializer(op, propertyType, field);
 101   
         else
 102  6
             addInitialValue(op, propertyName, propertyType, field, initialValue, ps.getLocation());
 103   
     }
 104   
 
 105  97
     private void addReinitializer(EnhancementOperation op, Class propertyType, String fieldName)
 106   
     {
 107  97
         String defaultFieldName = fieldName + "$default";
 108   
 
 109  97
         op.addField(defaultFieldName, propertyType);
 110   
 
 111   
         // On finishLoad(), store the current value into the default field.
 112   
 
 113  97
         op.extendMethodImplementation(
 114   
                 IComponent.class,
 115   
                 EnhanceUtils.FINISH_LOAD_SIGNATURE,
 116   
                 defaultFieldName + " = " + fieldName + ";");
 117   
 
 118   
         // On pageDetach(), restore the attribute to its default value.
 119   
 
 120  97
         op.extendMethodImplementation(
 121   
                 PageDetachListener.class,
 122   
                 EnhanceUtils.PAGE_DETACHED_SIGNATURE,
 123   
                 fieldName + " = " + defaultFieldName + ";");
 124   
     }
 125   
 
 126  6
     private void addInitialValue(EnhancementOperation op, String propertyName, Class propertyType,
 127   
             String fieldName, String initialValue, Location location)
 128   
     {
 129  6
         String description = EnhanceMessages.initialValueForProperty(propertyName);
 130   
 
 131  6
         InitialValueBindingCreator creator = new InitialValueBindingCreator(_bindingSource,
 132   
                 description, initialValue, location);
 133   
 
 134  6
         String creatorField = op.addInjectedField(fieldName + "$initialValueBindingCreator", creator);
 135   
 
 136  6
         String bindingField = fieldName + "$initialValueBinding";
 137  6
         op.addField(bindingField, IBinding.class);
 138   
 
 139  6
         BodyBuilder builder = new BodyBuilder();
 140   
 
 141  6
         builder.addln("{0} = {1}.createBinding(this);", bindingField, creatorField);
 142   
 
 143  6
         op.extendMethodImplementation(IComponent.class, EnhanceUtils.FINISH_LOAD_SIGNATURE, builder
 144   
                 .toString());
 145   
 
 146  6
         builder.clear();
 147   
 
 148  6
         builder.addln("{0} = {1};", fieldName, EnhanceUtils.createUnwrapExpression(
 149   
                 op,
 150   
                 bindingField,
 151   
                 propertyType));
 152   
 
 153  6
         String code = builder.toString();
 154   
 
 155   
         // In finishLoad() and pageDetach(), de-reference the binding to get the value
 156   
         // for the property.
 157   
 
 158  6
         op.extendMethodImplementation(IComponent.class, EnhanceUtils.FINISH_LOAD_SIGNATURE, code);
 159  6
         op.extendMethodImplementation(
 160   
                 PageDetachListener.class,
 161   
                 EnhanceUtils.PAGE_DETACHED_SIGNATURE,
 162   
                 code);
 163   
 
 164   
     }
 165   
 
 166  103
     private void addMutator(EnhancementOperation op, String propertyName, Class propertyType,
 167   
             String fieldName, boolean persistent)
 168   
     {
 169  103
         String methodName = EnhanceUtils.createMutatorMethodName(propertyName);
 170   
 
 171  103
         BodyBuilder body = new BodyBuilder();
 172   
 
 173  103
         body.begin();
 174   
 
 175  103
         if (persistent)
 176   
         {
 177  23
             body.add("org.apache.tapestry.Tapestry#fireObservedChange(this, ");
 178  23
             body.addQuoted(propertyName);
 179  23
             body.addln(", ($w) $1);");
 180   
         }
 181   
 
 182  103
         body.addln(fieldName + " = $1;");
 183   
 
 184  103
         body.end();
 185   
 
 186  103
         MethodSignature sig = new MethodSignature(void.class, methodName, new Class[]
 187   
         { propertyType }, null);
 188   
 
 189  103
         op.addMethod(Modifier.PUBLIC, sig, body.toString());
 190   
     }
 191   
 
 192  46
     public void setErrorLog(ErrorLog errorLog)
 193   
     {
 194  46
         _errorLog = errorLog;
 195   
     }
 196   
 
 197  46
     public void setBindingSource(BindingSource bindingSource)
 198   
     {
 199  46
         _bindingSource = bindingSource;
 200   
     }
 201   
 }