1 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 39 public class SpecifiedPropertyWorker implements EnhancementWorker 40 { 41 private ErrorLog _errorLog; 42 43 private BindingSource _bindingSource; 44 45 51 52 public void performEnhancement(EnhancementOperation op, IComponentSpecification spec) 53 { 54 Iterator i = spec.getPropertySpecificationNames().iterator(); 55 56 while (i.hasNext()) 57 { 58 String name = (String ) i.next(); 59 IPropertySpecification ps = spec.getPropertySpecification(name); 60 61 try 62 { 63 performEnhancement(op, ps); 64 } 65 catch (RuntimeException ex) 66 { 67 _errorLog.error( 68 EnhanceMessages.errorAddingProperty(name, op.getBaseClass(), ex), 69 ps.getLocation(), 70 ex); 71 } 72 } 73 } 74 75 private void performEnhancement(EnhancementOperation op, IPropertySpecification ps) 76 { 77 Defense.notNull(ps, "ps"); 78 79 String propertyName = ps.getName(); 80 String specifiedType = ps.getType(); 81 boolean persistent = ps.isPersistent(); 82 String initialValue = ps.getInitialValue(); 83 Location location = ps.getLocation(); 84 85 addProperty(op, propertyName, specifiedType, persistent, initialValue, location); 86 } 87 88 public void addProperty(EnhancementOperation op, String propertyName, String specifiedType, boolean persistent, String initialValue, Location location) 89 { 90 Class propertyType = EnhanceUtils.extractPropertyType(op, propertyName, specifiedType); 91 92 op.claimProperty(propertyName); 93 94 String field = "_$" + propertyName; 95 96 op.addField(field, propertyType); 97 98 102 EnhanceUtils.createSimpleAccessor(op, field, propertyName, propertyType); 103 104 addMutator(op, propertyName, propertyType, field, persistent); 105 106 if (initialValue == null) 107 addReinitializer(op, propertyType, field); 108 else 109 addInitialValue(op, propertyName, propertyType, field, initialValue, location); 110 } 111 112 private void addReinitializer(EnhancementOperation op, Class propertyType, String fieldName) 113 { 114 String defaultFieldName = fieldName + "$default"; 115 116 op.addField(defaultFieldName, propertyType); 117 118 120 op.extendMethodImplementation( 121 IComponent.class, 122 EnhanceUtils.FINISH_LOAD_SIGNATURE, 123 defaultFieldName + " = " + fieldName + ";"); 124 125 127 op.extendMethodImplementation( 128 PageDetachListener.class, 129 EnhanceUtils.PAGE_DETACHED_SIGNATURE, 130 fieldName + " = " + defaultFieldName + ";"); 131 } 132 133 private void addInitialValue(EnhancementOperation op, String propertyName, Class propertyType, 134 String fieldName, String initialValue, Location location) 135 { 136 String description = EnhanceMessages.initialValueForProperty(propertyName); 137 138 InitialValueBindingCreator creator = new InitialValueBindingCreator(_bindingSource, 139 description, initialValue, location); 140 141 String creatorField = op.addInjectedField( 142 fieldName + "$initialValueBindingCreator", 143 InitialValueBindingCreator.class, 144 creator); 145 146 String bindingField = fieldName + "$initialValueBinding"; 147 op.addField(bindingField, IBinding.class); 148 149 BodyBuilder builder = new BodyBuilder(); 150 151 builder.addln("{0} = {1}.createBinding(this);", bindingField, creatorField); 152 153 op.extendMethodImplementation(IComponent.class, EnhanceUtils.FINISH_LOAD_SIGNATURE, builder 154 .toString()); 155 156 builder.clear(); 157 158 builder.addln("{0} = {1};", fieldName, EnhanceUtils.createUnwrapExpression( 159 op, 160 bindingField, 161 propertyType)); 162 163 String code = builder.toString(); 164 165 168 op.extendMethodImplementation(IComponent.class, EnhanceUtils.FINISH_LOAD_SIGNATURE, code); 169 op.extendMethodImplementation( 170 PageDetachListener.class, 171 EnhanceUtils.PAGE_DETACHED_SIGNATURE, 172 code); 173 174 } 175 176 private void addMutator(EnhancementOperation op, String propertyName, Class propertyType, 177 String fieldName, boolean persistent) 178 { 179 String methodName = EnhanceUtils.createMutatorMethodName(propertyName); 180 181 BodyBuilder body = new BodyBuilder(); 182 183 body.begin(); 184 185 if (persistent) 186 { 187 body.add("org.apache.tapestry.Tapestry#fireObservedChange(this, "); 188 body.addQuoted(propertyName); 189 body.addln(", ($w) $1);"); 190 } 191 192 body.addln(fieldName + " = $1;"); 193 194 body.end(); 195 196 MethodSignature sig = new MethodSignature(void.class, methodName, new Class [] 197 { propertyType }, null); 198 199 op.addMethod(Modifier.PUBLIC, sig, body.toString()); 200 } 201 202 public void setErrorLog(ErrorLog errorLog) 203 { 204 _errorLog = errorLog; 205 } 206 207 public void setBindingSource(BindingSource bindingSource) 208 { 209 _bindingSource = bindingSource; 210 } 211 } | Popular Tags |