KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > enhance > SpecifiedPropertyWorker


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 JavaDoc;
18 import java.util.Iterator JavaDoc;
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     public void performEnhancement(EnhancementOperation op, IComponentSpecification spec)
53     {
54         Iterator JavaDoc i = spec.getPropertySpecificationNames().iterator();
55
56         while (i.hasNext())
57         {
58             String JavaDoc name = (String JavaDoc) i.next();
59             IPropertySpecification ps = spec.getPropertySpecification(name);
60
61             try
62             {
63                 performEnhancement(op, ps);
64             }
65             catch (RuntimeException JavaDoc 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 JavaDoc propertyName = ps.getName();
80         String JavaDoc specifiedType = ps.getType();
81         boolean persistent = ps.isPersistent();
82         String JavaDoc 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 JavaDoc propertyName, String JavaDoc specifiedType, boolean persistent, String JavaDoc initialValue, Location location)
89     {
90         Class JavaDoc propertyType = EnhanceUtils.extractPropertyType(op, propertyName, specifiedType);
91
92         op.claimProperty(propertyName);
93
94         String JavaDoc field = "_$" + propertyName;
95
96         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         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 JavaDoc propertyType, String JavaDoc fieldName)
113     {
114         String JavaDoc defaultFieldName = fieldName + "$default";
115
116         op.addField(defaultFieldName, propertyType);
117
118         // On finishLoad(), store the current value into the default field.
119

120         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         op.extendMethodImplementation(
128                 PageDetachListener.class,
129                 EnhanceUtils.PAGE_DETACHED_SIGNATURE,
130                 fieldName + " = " + defaultFieldName + ";");
131     }
132
133     private void addInitialValue(EnhancementOperation op, String JavaDoc propertyName, Class JavaDoc propertyType,
134             String JavaDoc fieldName, String JavaDoc initialValue, Location location)
135     {
136         String JavaDoc description = EnhanceMessages.initialValueForProperty(propertyName);
137
138         InitialValueBindingCreator creator = new InitialValueBindingCreator(_bindingSource,
139                 description, initialValue, location);
140
141         String JavaDoc creatorField = op.addInjectedField(
142                 fieldName + "$initialValueBindingCreator",
143                 InitialValueBindingCreator.class,
144                 creator);
145
146         String JavaDoc 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 JavaDoc code = builder.toString();
164
165         // In finishLoad() and pageDetach(), de-reference the binding to get the value
166
// for the property.
167

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 JavaDoc propertyName, Class JavaDoc propertyType,
177             String JavaDoc fieldName, boolean persistent)
178     {
179         String JavaDoc 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 JavaDoc[]
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