1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
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.ApplicationRuntimeException; |
21 |
| import org.apache.hivemind.ErrorLog; |
22 |
| import org.apache.hivemind.service.BodyBuilder; |
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.IComponent; |
28 |
| import org.apache.tapestry.spec.IComponentSpecification; |
29 |
| import org.apache.tapestry.spec.IParameterSpecification; |
30 |
| |
31 |
| |
32 |
| |
33 |
| |
34 |
| |
35 |
| |
36 |
| |
37 |
| public class ParameterPropertyWorker implements EnhancementWorker |
38 |
| { |
39 |
| private ErrorLog _errorLog; |
40 |
| |
41 |
422
| public void performEnhancement(EnhancementOperation op, IComponentSpecification spec)
|
42 |
| { |
43 |
422
| Iterator i = spec.getParameterNames().iterator();
|
44 |
422
| while (i.hasNext())
|
45 |
| { |
46 |
1096
| String name = (String) i.next();
|
47 |
| |
48 |
1096
| IParameterSpecification ps = spec.getParameter(name);
|
49 |
| |
50 |
1096
| try
|
51 |
| { |
52 |
1096
| performEnhancement(op, name, ps);
|
53 |
| } |
54 |
| catch (RuntimeException ex) |
55 |
| { |
56 |
1
| _errorLog.error(EnhanceMessages.errorAddingProperty(ps.getPropertyName(), op
|
57 |
| .getBaseClass(), ex), ps.getLocation(), ex); |
58 |
| } |
59 |
| } |
60 |
| } |
61 |
| |
62 |
| |
63 |
| |
64 |
| |
65 |
| |
66 |
| |
67 |
1096
| private void performEnhancement(EnhancementOperation op, String parameterName,
|
68 |
| IParameterSpecification ps) |
69 |
| { |
70 |
| |
71 |
| |
72 |
| |
73 |
1096
| if (!parameterName.equals(ps.getParameterName()))
|
74 |
1
| return;
|
75 |
| |
76 |
1095
| String propertyName = ps.getPropertyName();
|
77 |
1095
| String specifiedType = ps.getType();
|
78 |
1095
| boolean cache = ps.getCache();
|
79 |
| |
80 |
1095
| addParameter(op, parameterName, propertyName, specifiedType, cache);
|
81 |
| } |
82 |
| |
83 |
| |
84 |
| |
85 |
| |
86 |
| |
87 |
| |
88 |
| |
89 |
| |
90 |
| |
91 |
| |
92 |
| |
93 |
| |
94 |
| |
95 |
| |
96 |
| |
97 |
| |
98 |
| |
99 |
| |
100 |
| |
101 |
1095
| public void addParameter(EnhancementOperation op, String parameterName, String propertyName,
|
102 |
| String specifiedType, boolean cache) |
103 |
| { |
104 |
1095
| Defense.notNull(op, "op");
|
105 |
1095
| Defense.notNull(parameterName, "parameterName");
|
106 |
1095
| Defense.notNull(propertyName, "propertyName");
|
107 |
| |
108 |
1095
| Class propertyType = EnhanceUtils.extractPropertyType(op, propertyName, specifiedType);
|
109 |
| |
110 |
| |
111 |
| |
112 |
| |
113 |
| |
114 |
1094
| op.claimProperty(propertyName);
|
115 |
| |
116 |
| |
117 |
| |
118 |
| |
119 |
1094
| String fieldName = "_$" + propertyName;
|
120 |
1094
| String defaultFieldName = fieldName + "$Default";
|
121 |
1094
| String cachedFieldName = fieldName + "$Cached";
|
122 |
| |
123 |
1094
| op.addField(fieldName, propertyType);
|
124 |
1094
| op.addField(defaultFieldName, propertyType);
|
125 |
1094
| op.addField(cachedFieldName, boolean.class);
|
126 |
| |
127 |
1094
| buildAccessor(
|
128 |
| op, |
129 |
| parameterName, |
130 |
| propertyName, |
131 |
| propertyType, |
132 |
| fieldName, |
133 |
| defaultFieldName, |
134 |
| cachedFieldName, |
135 |
| cache); |
136 |
| |
137 |
1094
| buildMutator(
|
138 |
| op, |
139 |
| parameterName, |
140 |
| propertyName, |
141 |
| propertyType, |
142 |
| fieldName, |
143 |
| defaultFieldName, |
144 |
| cachedFieldName); |
145 |
| |
146 |
1094
| extendCleanupAfterRender(
|
147 |
| op, |
148 |
| parameterName, |
149 |
| propertyName, |
150 |
| propertyType, |
151 |
| fieldName, |
152 |
| defaultFieldName, |
153 |
| cachedFieldName); |
154 |
| } |
155 |
| |
156 |
1094
| private void extendCleanupAfterRender(EnhancementOperation op, String parameterName,
|
157 |
| String propertyName, Class propertyType, String fieldName, String defaultFieldName, |
158 |
| String cachedFieldName) |
159 |
| { |
160 |
1094
| BodyBuilder cleanupBody = new BodyBuilder();
|
161 |
| |
162 |
| |
163 |
| |
164 |
| |
165 |
| |
166 |
| |
167 |
1094
| String bindingName = propertyName + "Binding";
|
168 |
| |
169 |
1094
| addBindingReference(cleanupBody, bindingName, parameterName);
|
170 |
| |
171 |
1094
| cleanupBody.addln("if ({0} && ! {1}.isInvariant())", cachedFieldName, bindingName);
|
172 |
1094
| cleanupBody.begin();
|
173 |
1094
| cleanupBody.addln("{0} = false;", cachedFieldName);
|
174 |
1094
| cleanupBody.addln("{0} = {1};", fieldName, defaultFieldName);
|
175 |
1094
| cleanupBody.end();
|
176 |
| |
177 |
1094
| op.extendMethodImplementation(
|
178 |
| IComponent.class, |
179 |
| EnhanceUtils.CLEANUP_AFTER_RENDER_SIGNATURE, |
180 |
| cleanupBody.toString()); |
181 |
| } |
182 |
| |
183 |
3284
| private void addBindingReference(BodyBuilder builder, String localVariableName,
|
184 |
| String parameterName) |
185 |
| { |
186 |
3284
| builder.addln(
|
187 |
| "{0} {1} = getBinding(\"{2}\");", |
188 |
| IBinding.class.getName(), |
189 |
| localVariableName, |
190 |
| parameterName); |
191 |
| } |
192 |
| |
193 |
1094
| private void buildMutator(EnhancementOperation op, String parameterName, String propertyName,
|
194 |
| Class propertyType, String fieldName, String defaultFieldName, String cachedFieldName) |
195 |
| { |
196 |
1094
| BodyBuilder builder = new BodyBuilder();
|
197 |
1094
| builder.begin();
|
198 |
| |
199 |
| |
200 |
| |
201 |
| |
202 |
| |
203 |
1094
| builder.addln("if (! isInActiveState())");
|
204 |
1094
| builder.begin();
|
205 |
1094
| builder.addln("{0} = $1;", defaultFieldName);
|
206 |
1094
| builder.addln("return;");
|
207 |
1094
| builder.end();
|
208 |
| |
209 |
| |
210 |
| |
211 |
| |
212 |
1094
| addBindingReference(builder, "binding", parameterName);
|
213 |
| |
214 |
1094
| builder.addln("if (binding == null)");
|
215 |
1094
| builder.addln(
|
216 |
| " throw new {0}(\"Parameter ''{1}'' is not bound and can not be updated.\");", |
217 |
| ApplicationRuntimeException.class.getName(), |
218 |
| parameterName); |
219 |
| |
220 |
| |
221 |
| |
222 |
1094
| builder.addln("binding.setObject(($w) $1);");
|
223 |
| |
224 |
| |
225 |
| |
226 |
| |
227 |
| |
228 |
1094
| builder.addln("if (isRendering())");
|
229 |
1094
| builder.begin();
|
230 |
1094
| builder.addln("{0} = $1;", fieldName);
|
231 |
1094
| builder.addln("{0} = true;", cachedFieldName);
|
232 |
1094
| builder.end();
|
233 |
| |
234 |
1094
| builder.end();
|
235 |
| |
236 |
1094
| String mutatorMethodName = EnhanceUtils.createMutatorMethodName(propertyName);
|
237 |
| |
238 |
1094
| op.addMethod(Modifier.PUBLIC, new MethodSignature(void.class, mutatorMethodName,
|
239 |
| new Class[] |
240 |
| { propertyType }, null), builder.toString()); |
241 |
| } |
242 |
| |
243 |
| |
244 |
| |
245 |
1096
| void buildAccessor(EnhancementOperation op, String parameterName, String propertyName,
|
246 |
| Class propertyType, String fieldName, String defaultFieldName, String cachedFieldName, |
247 |
| boolean cache) |
248 |
| { |
249 |
1096
| BodyBuilder builder = new BodyBuilder();
|
250 |
1096
| builder.begin();
|
251 |
| |
252 |
1096
| builder.addln("if ({0}) return {1};", cachedFieldName, fieldName);
|
253 |
| |
254 |
1096
| addBindingReference(builder, "binding", parameterName);
|
255 |
| |
256 |
1096
| builder.addln("if (binding == null) return {0};", defaultFieldName);
|
257 |
| |
258 |
1096
| String javaTypeName = ClassFabUtils.getJavaClassName(propertyType);
|
259 |
| |
260 |
1096
| builder.addln("{0} result = {1};", javaTypeName, EnhanceUtils.createUnwrapExpression(
|
261 |
| op, |
262 |
| "binding", |
263 |
| propertyType)); |
264 |
| |
265 |
| |
266 |
| |
267 |
| |
268 |
| |
269 |
| |
270 |
1096
| String expression = cache ? "isRendering() || binding.isInvariant()"
|
271 |
| : "binding.isInvariant()"; |
272 |
| |
273 |
1096
| builder.addln("if ({0})", expression);
|
274 |
1096
| builder.begin();
|
275 |
1096
| builder.addln("{0} = result;", fieldName);
|
276 |
1096
| builder.addln("{0} = true;", cachedFieldName);
|
277 |
1096
| builder.end();
|
278 |
| |
279 |
1096
| builder.addln("return result;");
|
280 |
| |
281 |
1096
| builder.end();
|
282 |
| |
283 |
1096
| String accessorMethodName = op.getAccessorMethodName(propertyName);
|
284 |
| |
285 |
1096
| op.addMethod(Modifier.PUBLIC, new MethodSignature(propertyType, accessorMethodName, null,
|
286 |
| null), builder.toString()); |
287 |
| } |
288 |
| |
289 |
42
| public void setErrorLog(ErrorLog errorLog)
|
290 |
| { |
291 |
42
| _errorLog = errorLog;
|
292 |
| } |
293 |
| } |