001    // Copyright 2008, 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    
015    package org.apache.tapestry5.internal.transform;
016    
017    import org.apache.tapestry5.EventConstants;
018    import org.apache.tapestry5.annotations.PageActivationContext;
019    import org.apache.tapestry5.model.MutableComponentModel;
020    import org.apache.tapestry5.plastic.FieldHandle;
021    import org.apache.tapestry5.plastic.PlasticClass;
022    import org.apache.tapestry5.plastic.PlasticField;
023    import org.apache.tapestry5.runtime.Component;
024    import org.apache.tapestry5.runtime.ComponentEvent;
025    import org.apache.tapestry5.services.ComponentEventHandler;
026    import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2;
027    import org.apache.tapestry5.services.transform.TransformationSupport;
028    
029    import java.util.List;
030    
031    /**
032     * Provides the page activation context handlers.
033     *
034     * @see org.apache.tapestry5.annotations.PageActivationContext
035     */
036    public class PageActivationContextWorker implements ComponentClassTransformWorker2
037    {
038        public void transform(PlasticClass plasticClass, TransformationSupport support, MutableComponentModel model)
039        {
040            List<PlasticField> fields = plasticClass.getFieldsWithAnnotation(PageActivationContext.class);
041    
042            switch (fields.size())
043            {
044                case 0:
045                    break;
046    
047                case 1:
048    
049                    transformField(support, fields.get(0));
050    
051                    break;
052    
053                default:
054    
055                    throw new RuntimeException(TransformMessages.illegalNumberOfPageActivationContextHandlers2(fields));
056            }
057        }
058    
059        private void transformField(TransformationSupport support, PlasticField field)
060        {
061            PageActivationContext annotation = field.getAnnotation(PageActivationContext.class);
062    
063            FieldHandle handle = field.getHandle();
064    
065            if (annotation.activate())
066            {
067                support.addEventHandler(EventConstants.ACTIVATE, 1,
068                        "PageActivationContextWorker activate event handler",
069                        createActivationHandler(field.getTypeName(), handle));
070            }
071    
072            if (annotation.passivate())
073            {
074                support.addEventHandler(EventConstants.PASSIVATE, 0,
075                        "PageActivationContextWorker passivate event handler", createPassivateHandler(handle));
076            }
077    
078            // We don't claim the field, and other workers may even replace it with a FieldConduit.
079    
080        }
081    
082        private static ComponentEventHandler createActivationHandler(final String fieldType, final FieldHandle handle)
083        {
084            return new ComponentEventHandler()
085            {
086                public void handleEvent(Component instance, ComponentEvent event)
087                {
088                    Object value = event.coerceContext(0, fieldType);
089    
090                    handle.set(instance, value);
091                }
092            };
093        }
094    
095        private static ComponentEventHandler createPassivateHandler(final FieldHandle handle)
096        {
097            return new ComponentEventHandler()
098            {
099                public void handleEvent(Component instance, ComponentEvent event)
100                {
101                    Object value = handle.get(instance);
102    
103                    event.storeResult(value);
104                }
105            };
106        }
107    }