001// Copyright 2009, 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.SessionAttribute;
018import org.apache.tapestry5.http.services.Request;
019import org.apache.tapestry5.http.services.Session;
020import org.apache.tapestry5.model.MutableComponentModel;
021import org.apache.tapestry5.plastic.FieldConduit;
022import org.apache.tapestry5.plastic.InstanceContext;
023import org.apache.tapestry5.plastic.PlasticClass;
024import org.apache.tapestry5.plastic.PlasticField;
025import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2;
026import org.apache.tapestry5.services.transform.TransformationSupport;
027
028/**
029 * Looks for the {@link SessionAttribute} annotation and converts read and write access on such
030 * fields into calls to the {@link Session#getAttribute(String)} and {@link Session#setAttribute(String, Object)}.
031 */
032public class SessionAttributeWorker implements ComponentClassTransformWorker2
033{
034    private final Request request;
035
036    private class SessionKeyConduit implements FieldConduit<Object>
037    {
038        private final String key;
039
040        public SessionKeyConduit(String key)
041        {
042            this.key = key;
043        }
044
045        public Object get(Object instance, InstanceContext context)
046        {
047            Session session = getSession();
048
049            if (session == null)
050            {
051                return null;
052            }
053
054            return session.getAttribute(key);
055        }
056
057        public void set(Object instance, InstanceContext context, Object newValue)
058        {
059            request.getSession(true).setAttribute(key, newValue);
060        }
061
062        private Session getSession()
063        {
064            return request.getSession(false);
065        }
066    }
067
068    public SessionAttributeWorker(Request request)
069    {
070        this.request = request;
071    }
072
073
074    public void transform(PlasticClass plasticClass, TransformationSupport support, MutableComponentModel model)
075    {
076        for (PlasticField field : plasticClass.getFieldsWithAnnotation(SessionAttribute.class))
077        {
078            convertFieldToSessionAccess(field);
079        }
080    }
081
082    private void convertFieldToSessionAccess(PlasticField field)
083    {
084        SessionAttribute annotation = field.getAnnotation(SessionAttribute.class);
085
086        field.claim(annotation);
087
088        String key = determineSessionKey(field, annotation.value());
089
090        field.setConduit(new SessionKeyConduit(key));
091    }
092
093    private String determineSessionKey(PlasticField field, String value)
094    {
095        return value.equals("") ? field.getName() : value;
096    }
097}