001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.internal.services; 014 015import org.apache.tapestry5.Block; 016import org.apache.tapestry5.ComponentResources; 017import org.apache.tapestry5.annotations.Id; 018import org.apache.tapestry5.commons.ObjectLocator; 019import org.apache.tapestry5.internal.transform.ReadOnlyComponentFieldConduit; 020import org.apache.tapestry5.ioc.annotations.Inject; 021import org.apache.tapestry5.ioc.internal.util.InternalUtils; 022import org.apache.tapestry5.model.MutableComponentModel; 023import org.apache.tapestry5.plastic.FieldConduit; 024import org.apache.tapestry5.plastic.InstanceContext; 025import org.apache.tapestry5.plastic.PlasticField; 026import org.apache.tapestry5.services.transform.InjectionProvider2; 027 028/** 029 * Identifies fields of type {@link Block} that have the {@link Inject} annotation and converts them 030 * into read-only 031 * fields containing the injected Block from the template. The annotation's value is the id of the 032 * block to inject; if 033 * omitted, the block id is deduced from the field id. 034 * 035 * Must be scheduled before {@link DefaultInjectionProvider} because it uses the same annotation, Inject, with a 036 * different interpretation. 037 */ 038public class BlockInjectionProvider implements InjectionProvider2 039{ 040 private static final String BLOCK_TYPE_NAME = Block.class.getName(); 041 042 public boolean provideInjection(PlasticField field, ObjectLocator locator, MutableComponentModel componentModel) 043 { 044 if (!field.getTypeName().equals(BLOCK_TYPE_NAME)) 045 { 046 return false; 047 } 048 049 Id annotation = field.getAnnotation(Id.class); 050 051 String blockId = getBlockId(field.getName(), annotation); 052 053 FieldConduit<Object> conduit = createConduit(field, blockId); 054 055 field.setConduit(conduit); 056 057 return true; // claim the field 058 } 059 060 private FieldConduit<Object> createConduit(PlasticField field, final String blockId) 061 { 062 final String className = field.getPlasticClass().getClassName(); 063 final String fieldName = field.getName(); 064 065 return new ReadOnlyComponentFieldConduit(className, fieldName) 066 { 067 public Object get(Object instance, InstanceContext context) 068 { 069 ComponentResources resources = context.get(ComponentResources.class); 070 071 return resources.getBlock(blockId); 072 } 073 }; 074 } 075 076 private String getBlockId(String fieldName, Id annotation) 077 { 078 return annotation != null ? annotation.value() : InternalUtils.stripMemberName(fieldName); 079 } 080}