001: // Copyright 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.internal.services;
016:
017: import static java.lang.String.format;
018:
019: import java.lang.reflect.Modifier;
020: import java.util.List;
021:
022: import org.apache.tapestry.annotations.ApplicationState;
023: import org.apache.tapestry.model.MutableComponentModel;
024: import org.apache.tapestry.services.ApplicationStateManager;
025: import org.apache.tapestry.services.ClassTransformation;
026: import org.apache.tapestry.services.ComponentClassTransformWorker;
027: import org.apache.tapestry.services.MethodSignature;
028:
029: /**
030: * Looks for the {@link ApplicationState} annotation and converts read and write access on such
031: * fields into calls to the {@link ApplicationStateManager}.
032: */
033: public class ApplicationStateWorker implements
034: ComponentClassTransformWorker {
035: private final ApplicationStateManager _applicationStateManager;
036:
037: private final ClassLoader _classLoader = Thread.currentThread()
038: .getContextClassLoader();
039:
040: public ApplicationStateWorker(
041: ApplicationStateManager applicationStateManager) {
042: _applicationStateManager = applicationStateManager;
043: }
044:
045: public void transform(ClassTransformation transformation,
046: MutableComponentModel model) {
047: List<String> names = transformation
048: .findFieldsWithAnnotation(ApplicationState.class);
049:
050: if (names.isEmpty())
051: return;
052:
053: String managerFieldName = transformation.addInjectedField(
054: ApplicationStateManager.class,
055: "applicationStateManager", _applicationStateManager);
056:
057: for (String fieldName : names) {
058: String fieldType = transformation.getFieldType(fieldName);
059:
060: Class fieldClass = null;
061:
062: try {
063: fieldClass = _classLoader.loadClass(fieldType);
064: } catch (ClassNotFoundException ex) {
065: throw new RuntimeException(ex);
066:
067: }
068:
069: String typeFieldName = transformation.addInjectedField(
070: Class.class, fieldName + "_type", fieldClass);
071:
072: replaceRead(transformation, fieldName, fieldType,
073: managerFieldName, typeFieldName);
074:
075: replaceWrite(transformation, fieldName, fieldType,
076: managerFieldName, typeFieldName);
077:
078: transformation.removeField(fieldName);
079:
080: String booleanFieldName = fieldName + "Exists";
081:
082: if (transformation.isField(booleanFieldName)
083: && transformation.getFieldType(booleanFieldName)
084: .equals("boolean")) {
085: replaceFlagRead(transformation, booleanFieldName,
086: typeFieldName, managerFieldName);
087: }
088: }
089: }
090:
091: private void replaceFlagRead(ClassTransformation transformation,
092: String booleanFieldName, String typeFieldName,
093: String managerFieldName) {
094: String readMethodName = transformation.newMemberName("read",
095: booleanFieldName);
096:
097: MethodSignature sig = new MethodSignature(Modifier.PRIVATE,
098: "boolean", readMethodName, null, null);
099:
100: String body = format("return %s.exists(%s);", managerFieldName,
101: typeFieldName);
102:
103: transformation.addMethod(sig, body);
104:
105: transformation.replaceReadAccess(booleanFieldName,
106: readMethodName);
107: transformation.makeReadOnly(booleanFieldName);
108: transformation.removeField(booleanFieldName);
109: }
110:
111: private void replaceWrite(ClassTransformation transformation,
112: String fieldName, String fieldType,
113: String managerFieldName, String typeFieldName) {
114: String writeMethodName = transformation.newMemberName("write",
115: fieldName);
116:
117: MethodSignature writeSignature = new MethodSignature(
118: Modifier.PRIVATE, "void", writeMethodName,
119: new String[] { fieldType }, null);
120:
121: String body = format("%s.set(%s, $1);", managerFieldName,
122: typeFieldName);
123:
124: transformation.addMethod(writeSignature, body);
125:
126: transformation.replaceWriteAccess(fieldName, writeMethodName);
127: }
128:
129: private void replaceRead(ClassTransformation transformation,
130: String fieldName, String fieldType,
131: String managerFieldName, String typeFieldName) {
132:
133: String readMethodName = transformation.newMemberName("read",
134: fieldName);
135:
136: MethodSignature readMethodSignature = new MethodSignature(
137: Modifier.PRIVATE, fieldType, readMethodName, null, null);
138:
139: String body = format("return (%s) %s.get(%s);", fieldType,
140: managerFieldName, typeFieldName);
141:
142: transformation.addMethod(readMethodSignature, body);
143:
144: transformation.replaceReadAccess(fieldName, readMethodName);
145: }
146: }
|