    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}