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 }