    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    }