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.services;
016
017import org.apache.tapestry5.Block;
018import org.apache.tapestry5.ComponentResources;
019import org.apache.tapestry5.annotations.Id;
020import org.apache.tapestry5.internal.transform.ReadOnlyComponentFieldConduit;
021import org.apache.tapestry5.ioc.ObjectLocator;
022import org.apache.tapestry5.ioc.annotations.Inject;
023import org.apache.tapestry5.ioc.internal.util.InternalUtils;
024import org.apache.tapestry5.model.MutableComponentModel;
025import org.apache.tapestry5.plastic.FieldConduit;
026import org.apache.tapestry5.plastic.InstanceContext;
027import org.apache.tapestry5.plastic.PlasticField;
028import 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 */
040public 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}