    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.services;
    016
    017    import org.apache.tapestry5.Block;
    018    import org.apache.tapestry5.ComponentResources;
    019    import org.apache.tapestry5.annotations.Id;
    020    import org.apache.tapestry5.internal.transform.ReadOnlyComponentFieldConduit;
    021    import org.apache.tapestry5.ioc.ObjectLocator;
    022    import org.apache.tapestry5.ioc.annotations.Inject;
    023    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    024    import org.apache.tapestry5.model.MutableComponentModel;
    025    import org.apache.tapestry5.plastic.FieldConduit;
    026    import org.apache.tapestry5.plastic.InstanceContext;
    027    import org.apache.tapestry5.plastic.PlasticField;
    028    import org.apache.tapestry5.services.transform.InjectionProvider2;
    029
    030    /**
    031     * Identifies fields of type {@link Block} that have the {@link Inject} annotation and converts them
    032     * into read-only
    033     * fields containing the injected Block from the template. The annotation's value is the id of the
    034     * block to inject; if
    035     * omitted, the block id is deduced from the field id.
    036     * <p/>
    037     * Must be scheduled before {@link DefaultInjectionProvider} because it uses the same annotation, Inject, with a
    038     * different interpretation.
    039     */
    040    public class BlockInjectionProvider implements InjectionProvider2
    041    {
    042        private static final String BLOCK_TYPE_NAME = Block.class.getName();
    043
    044        public boolean provideInjection(PlasticField field, ObjectLocator locator, MutableComponentModel componentModel)
    045        {
    046            if (!field.getTypeName().equals(BLOCK_TYPE_NAME))
    047            {
    048                return false;
    049            }
    050
    051            Id annotation = field.getAnnotation(Id.class);
    052
    053            String blockId = getBlockId(field.getName(), annotation);
    054
    055            FieldConduit<Object> conduit = createConduit(field, blockId);
    056
    057            field.setConduit(conduit);
    058
    059            return true; // claim the field
    060        }
    061
    062        private FieldConduit<Object> createConduit(PlasticField field, final String blockId)
    063        {
    064            final String className = field.getPlasticClass().getClassName();
    065            final String fieldName = field.getName();
    066
    067            return new ReadOnlyComponentFieldConduit(className, fieldName)
    068            {
    069                public Object get(Object instance, InstanceContext context)
    070                {
    071                    ComponentResources resources = context.get(ComponentResources.class);
    072
    073                    return resources.getBlock(blockId);
    074                }
    075            };
    076        }
    077
    078        private String getBlockId(String fieldName, Id annotation)
    079        {
    080            return annotation != null ? annotation.value() : InternalUtils.stripMemberName(fieldName);
    081        }
    082    }