Coverage Report - org.apache.tapestry5.internal.transform.ApplicationStateWorker
 
Classes in this File Line Coverage Branch Coverage Complexity
ApplicationStateWorker
100%
51/51
93%
13/14
0
 
 1  
 // Copyright 2007, 2008 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.tapestry5.internal.transform;
 16  
 
 17  
 import org.apache.tapestry5.annotations.ApplicationState;
 18  
 import org.apache.tapestry5.annotations.SessionState;
 19  
 import org.apache.tapestry5.internal.services.ComponentClassCache;
 20  
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 21  
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 22  
 import org.apache.tapestry5.model.MutableComponentModel;
 23  
 import org.apache.tapestry5.services.ApplicationStateManager;
 24  
 import org.apache.tapestry5.services.ClassTransformation;
 25  
 import org.apache.tapestry5.services.ComponentClassTransformWorker;
 26  
 import org.apache.tapestry5.services.TransformMethodSignature;
 27  
 
 28  
 import static java.lang.String.format;
 29  
 import java.lang.reflect.Modifier;
 30  
 import java.util.List;
 31  
 import java.util.Map;
 32  
 
 33  
 /**
 34  
  * Looks for the {@link ApplicationState} and {@link org.apache.tapestry5.annotations.SessionState} annotations and
 35  
  * converts read and write access on such fields into calls to the {@link ApplicationStateManager}.
 36  
  */
 37  
 public class ApplicationStateWorker implements ComponentClassTransformWorker
 38  
 {
 39  
     private final ApplicationStateManager applicationStateManager;
 40  
 
 41  
     private final ComponentClassCache componentClassCache;
 42  
 
 43  
     public ApplicationStateWorker(ApplicationStateManager applicationStateManager,
 44  
                                   ComponentClassCache componentClassCache)
 45  64
     {
 46  64
         this.applicationStateManager = applicationStateManager;
 47  64
         this.componentClassCache = componentClassCache;
 48  64
     }
 49  
 
 50  
     public void transform(ClassTransformation transformation, MutableComponentModel model)
 51  
     {
 52  816
         Map<String, Boolean> fields = CollectionFactory.newMap();
 53  
 
 54  816
         List<String> asoNames = transformation.findFieldsWithAnnotation(ApplicationState.class);
 55  
 
 56  816
         for (String name : asoNames)
 57  
         {
 58  28
             ApplicationState applicationState = transformation.getFieldAnnotation(name, ApplicationState.class);
 59  
 
 60  28
             fields.put(name, applicationState.create());
 61  28
         }
 62  
 
 63  
 
 64  816
         List<String> ssoNames = transformation.findFieldsWithAnnotation(SessionState.class);
 65  
 
 66  816
         for (String name : ssoNames)
 67  
         {
 68  2
             SessionState sessionState = transformation.getFieldAnnotation(name, SessionState.class);
 69  
 
 70  2
             fields.put(name, sessionState.create());
 71  2
         }
 72  
 
 73  
 
 74  816
         if (fields.isEmpty()) return;
 75  
 
 76  26
         String managerFieldName = transformation.addInjectedField(ApplicationStateManager.class,
 77  
                                                                   "applicationStateManager", applicationStateManager);
 78  
 
 79  26
         for (String fieldName : InternalUtils.sortedKeys(fields))
 80  
         {
 81  30
             processField(fieldName, managerFieldName, transformation, fields.get(fieldName));
 82  
         }
 83  26
     }
 84  
 
 85  
     private void processField(String fieldName, String managerFieldName, ClassTransformation transformation,
 86  
                               boolean create)
 87  
     {
 88  30
         String fieldType = transformation.getFieldType(fieldName);
 89  
 
 90  30
         Class fieldClass = componentClassCache.forName(fieldType);
 91  
 
 92  30
         String typeFieldName = transformation.addInjectedField(Class.class, fieldName + "_type", fieldClass);
 93  
 
 94  30
         replaceRead(transformation, fieldName, fieldType, managerFieldName, typeFieldName, create);
 95  
 
 96  30
         replaceWrite(transformation, fieldName, fieldType, managerFieldName, typeFieldName);
 97  
 
 98  30
         transformation.removeField(fieldName);
 99  
 
 100  30
         String booleanFieldName = fieldName + "Exists";
 101  
 
 102  30
         if (transformation.isField(booleanFieldName) && transformation.getFieldType(booleanFieldName).equals("boolean"))
 103  
         {
 104  2
             replaceFlagRead(transformation, booleanFieldName, typeFieldName, managerFieldName);
 105  
         }
 106  30
     }
 107  
 
 108  
     private void replaceFlagRead(ClassTransformation transformation, String booleanFieldName, String typeFieldName,
 109  
                                  String managerFieldName)
 110  
     {
 111  2
         String readMethodName = transformation.newMemberName("read", booleanFieldName);
 112  
 
 113  2
         TransformMethodSignature sig = new TransformMethodSignature(Modifier.PRIVATE, "boolean", readMethodName, null,
 114  
                                                                     null);
 115  
 
 116  2
         String body = format("return %s.exists(%s);", managerFieldName, typeFieldName);
 117  
 
 118  2
         transformation.addMethod(sig, body);
 119  
 
 120  2
         transformation.replaceReadAccess(booleanFieldName, readMethodName);
 121  2
         transformation.makeReadOnly(booleanFieldName);
 122  2
         transformation.removeField(booleanFieldName);
 123  2
     }
 124  
 
 125  
     private void replaceWrite(ClassTransformation transformation, String fieldName, String fieldType,
 126  
                               String managerFieldName, String typeFieldName)
 127  
     {
 128  30
         String writeMethodName = transformation.newMemberName("write", fieldName);
 129  
 
 130  30
         TransformMethodSignature writeSignature = new TransformMethodSignature(Modifier.PRIVATE, "void",
 131  
                                                                                writeMethodName,
 132  
                                                                                new String[] { fieldType },
 133  
                                                                                null);
 134  
 
 135  30
         String body = format("%s.set(%s, $1);", managerFieldName, typeFieldName);
 136  
 
 137  30
         transformation.addMethod(writeSignature, body);
 138  
 
 139  30
         transformation.replaceWriteAccess(fieldName, writeMethodName);
 140  30
     }
 141  
 
 142  
     private void replaceRead(ClassTransformation transformation, String fieldName, String fieldType,
 143  
                              String managerFieldName, String typeFieldName, boolean create)
 144  
     {
 145  30
         String readMethodName = transformation.newMemberName("read", fieldName);
 146  
 
 147  30
         TransformMethodSignature readMethodSignature = new TransformMethodSignature(Modifier.PRIVATE, fieldType,
 148  
                                                                                     readMethodName, null, null);
 149  
 
 150  30
         String methodName = create ? "get" : "getIfExists";
 151  
 
 152  30
         String body = format("return (%s) %s.%s(%s);", fieldType, managerFieldName, methodName, typeFieldName);
 153  
 
 154  30
         transformation.addMethod(readMethodSignature, body);
 155  
 
 156  30
         transformation.replaceReadAccess(fieldName, readMethodName);
 157  30
     }
 158  
 }