Clover coverage report - Code Coverage for tapestry release 4.0-beta-2
Coverage timestamp: Sat Jul 9 2005 22:02:17 EDT
file stats: LOC: 211   Methods: 8
NCLOC: 128   Classes: 1
30 day Evaluation License registered to hlship@comcast.net Your 30 day evaluation period has expired. Please visit http://www.cenqua.com 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  422 public void performEnhancement(EnhancementOperation op, IComponentSpecification spec)
 53    {
 54  422 Iterator i = spec.getPropertySpecificationNames().iterator();
 55   
 56  422 while (i.hasNext())
 57    {
 58  119 String name = (String) i.next();
 59  119 IPropertySpecification ps = spec.getPropertySpecification(name);
 60   
 61  119 try
 62    {
 63  119 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  119 private void performEnhancement(EnhancementOperation op, IPropertySpecification ps)
 76    {
 77  119 Defense.notNull(ps, "ps");
 78   
 79  119 String propertyName = ps.getName();
 80  119 String specifiedType = ps.getType();
 81  119 boolean persistent = ps.isPersistent();
 82  119 String initialValue = ps.getInitialValue();
 83  119 Location location = ps.getLocation();
 84   
 85  119 addProperty(op, propertyName, specifiedType, persistent, initialValue, location);
 86    }
 87   
 88  119 public void addProperty(EnhancementOperation op, String propertyName, String specifiedType, boolean persistent, String initialValue, Location location)
 89    {
 90  119 Class propertyType = EnhanceUtils.extractPropertyType(op, propertyName, specifiedType);
 91   
 92  118 op.claimProperty(propertyName);
 93   
 94  118 String field = "_$" + propertyName;
 95   
 96  118 op.addField(field, propertyType);
 97   
 98    // Release 3.0 would squack a bit about overriding non-abstract methods
 99    // if they exist. 4.0 is less picky ... it blindly adds new methods, possibly
 100    // overwriting methods in the base component class.
 101   
 102  118 EnhanceUtils.createSimpleAccessor(op, field, propertyName, propertyType);
 103   
 104  118 addMutator(op, propertyName, propertyType, field, persistent);
 105   
 106  118 if (initialValue == null)
 107  114 addReinitializer(op, propertyType, field);
 108    else
 109  4 addInitialValue(op, propertyName, propertyType, field, initialValue, location);
 110    }
 111   
 112  114 private void addReinitializer(EnhancementOperation op, Class propertyType, String fieldName)
 113    {
 114  114 String defaultFieldName = fieldName + "$default";
 115   
 116  114 op.addField(defaultFieldName, propertyType);
 117   
 118    // On finishLoad(), store the current value into the default field.
 119   
 120  114 op.extendMethodImplementation(
 121    IComponent.class,
 122    EnhanceUtils.FINISH_LOAD_SIGNATURE,
 123    defaultFieldName + " = " + fieldName + ";");
 124   
 125    // On pageDetach(), restore the attribute to its default value.
 126   
 127  114 op.extendMethodImplementation(
 128    PageDetachListener.class,
 129    EnhanceUtils.PAGE_DETACHED_SIGNATURE,
 130    fieldName + " = " + defaultFieldName + ";");
 131    }
 132   
 133  4 private void addInitialValue(EnhancementOperation op, String propertyName, Class propertyType,
 134    String fieldName, String initialValue, Location location)
 135    {
 136  4 String description = EnhanceMessages.initialValueForProperty(propertyName);
 137   
 138  4 InitialValueBindingCreator creator = new InitialValueBindingCreator(_bindingSource,
 139    description, initialValue, location);
 140   
 141  4 String creatorField = op.addInjectedField(
 142    fieldName + "$initialValueBindingCreator",
 143    InitialValueBindingCreator.class,
 144    creator);
 145   
 146  4 String bindingField = fieldName + "$initialValueBinding";
 147  4 op.addField(bindingField, IBinding.class);
 148   
 149  4 BodyBuilder builder = new BodyBuilder();
 150   
 151  4 builder.addln("{0} = {1}.createBinding(this);", bindingField, creatorField);
 152   
 153  4 op.extendMethodImplementation(IComponent.class, EnhanceUtils.FINISH_LOAD_SIGNATURE, builder
 154    .toString());
 155   
 156  4 builder.clear();
 157   
 158  4 builder.addln("{0} = {1};", fieldName, EnhanceUtils.createUnwrapExpression(
 159    op,
 160    bindingField,
 161    propertyType));
 162   
 163  4 String code = builder.toString();
 164   
 165    // In finishLoad() and pageDetach(), de-reference the binding to get the value
 166    // for the property.
 167   
 168  4 op.extendMethodImplementation(IComponent.class, EnhanceUtils.FINISH_LOAD_SIGNATURE, code);
 169  4 op.extendMethodImplementation(
 170    PageDetachListener.class,
 171    EnhanceUtils.PAGE_DETACHED_SIGNATURE,
 172    code);
 173   
 174    }
 175   
 176  118 private void addMutator(EnhancementOperation op, String propertyName, Class propertyType,
 177    String fieldName, boolean persistent)
 178    {
 179  118 String methodName = EnhanceUtils.createMutatorMethodName(propertyName);
 180   
 181  118 BodyBuilder body = new BodyBuilder();
 182   
 183  118 body.begin();
 184   
 185  118 if (persistent)
 186    {
 187  20 body.add("org.apache.tapestry.Tapestry#fireObservedChange(this, ");
 188  20 body.addQuoted(propertyName);
 189  20 body.addln(", ($w) $1);");
 190    }
 191   
 192  118 body.addln(fieldName + " = $1;");
 193   
 194  118 body.end();
 195   
 196  118 MethodSignature sig = new MethodSignature(void.class, methodName, new Class[]
 197    { propertyType }, null);
 198   
 199  118 op.addMethod(Modifier.PUBLIC, sig, body.toString());
 200    }
 201   
 202  42 public void setErrorLog(ErrorLog errorLog)
 203    {
 204  42 _errorLog = errorLog;
 205    }
 206   
 207  42 public void setBindingSource(BindingSource bindingSource)
 208    {
 209  42 _bindingSource = bindingSource;
 210    }
 211    }