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 015package org.apache.tapestry5.internal.transform; 016 017import org.apache.tapestry5.annotations.SessionState; 018import org.apache.tapestry5.func.F; 019import org.apache.tapestry5.func.Predicate; 020import org.apache.tapestry5.internal.services.ComponentClassCache; 021import org.apache.tapestry5.model.MutableComponentModel; 022import org.apache.tapestry5.plastic.FieldConduit; 023import org.apache.tapestry5.plastic.InstanceContext; 024import org.apache.tapestry5.plastic.PlasticClass; 025import org.apache.tapestry5.plastic.PlasticField; 026import org.apache.tapestry5.services.ApplicationStateManager; 027import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; 028import org.apache.tapestry5.services.transform.TransformationSupport; 029 030import 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 */ 036public 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}