001 // Copyright 2007, 2008, 2010, 2011 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.tapestry5.internal.transform;
016
017 import org.apache.tapestry5.annotations.SessionState;
018 import org.apache.tapestry5.func.F;
019 import org.apache.tapestry5.func.Predicate;
020 import org.apache.tapestry5.internal.services.ComponentClassCache;
021 import org.apache.tapestry5.model.MutableComponentModel;
022 import org.apache.tapestry5.plastic.FieldConduit;
023 import org.apache.tapestry5.plastic.InstanceContext;
024 import org.apache.tapestry5.plastic.PlasticClass;
025 import org.apache.tapestry5.plastic.PlasticField;
026 import org.apache.tapestry5.services.ApplicationStateManager;
027 import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2;
028 import org.apache.tapestry5.services.transform.TransformationSupport;
029
030 import java.util.List;
031
032 /**
033 * Looks for the {@link org.apache.tapestry5.annotations.SessionState} annotations and
034 * converts read and write access on such fields into calls to the {@link ApplicationStateManager}.
035 */
036 public class ApplicationStateWorker implements ComponentClassTransformWorker2
037 {
038 private final ApplicationStateManager applicationStateManager;
039
040 private final ComponentClassCache componentClassCache;
041
042 public ApplicationStateWorker(ApplicationStateManager applicationStateManager,
043 ComponentClassCache componentClassCache)
044 {
045 this.applicationStateManager = applicationStateManager;
046 this.componentClassCache = componentClassCache;
047 }
048
049 public void transform(PlasticClass plasticClass, TransformationSupport support, MutableComponentModel model)
050 {
051 for (PlasticField field : plasticClass.getFieldsWithAnnotation(SessionState.class))
052 {
053 SessionState annotation = field.getAnnotation(SessionState.class);
054
055 transform(plasticClass, field, annotation.create());
056
057 field.claim(annotation);
058 }
059 }
060
061 @SuppressWarnings("unchecked")
062 private void transform(PlasticClass transformation, PlasticField field, final boolean create)
063 {
064 final Class fieldClass = componentClassCache.forName(field.getTypeName());
065
066 field.setConduit(new FieldConduit()
067 {
068 public void set(Object instance, InstanceContext context, Object newValue)
069 {
070 applicationStateManager.set(fieldClass, newValue);
071 }
072
073 public Object get(Object instance, InstanceContext context)
074 {
075 return create ? applicationStateManager.get(fieldClass) : applicationStateManager
076 .getIfExists(fieldClass);
077 }
078 });
079
080 final String expectedName = field.getName() + "Exists";
081
082 List<PlasticField> fields = F.flow(transformation.getAllFields()).filter(new Predicate<PlasticField>()
083 {
084 public boolean accept(PlasticField field)
085 {
086 return field.getTypeName().equals("boolean") && field.getName().equalsIgnoreCase(expectedName);
087 }
088 }).toList();
089
090 for (PlasticField existsField : fields)
091 {
092 existsField.claim(this);
093
094 final String className = transformation.getClassName();
095
096 final String fieldName = existsField.getName();
097
098 existsField.setConduit(new ReadOnlyComponentFieldConduit(className, fieldName)
099 {
100 public Object get(Object instance, InstanceContext context)
101 {
102 return applicationStateManager.exists(fieldClass);
103 }
104 });
105 }
106 }
107 }