001 // Copyright 2005 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.tapestry.enhance; 016 017 import java.util.Iterator; 018 019 import org.apache.hivemind.ErrorLog; 020 import org.apache.hivemind.Location; 021 import org.apache.hivemind.service.BodyBuilder; 022 import org.apache.hivemind.service.ClassFabUtils; 023 import org.apache.hivemind.util.Defense; 024 import org.apache.tapestry.IComponent; 025 import org.apache.tapestry.TapestryUtils; 026 import org.apache.tapestry.spec.IComponentSpecification; 027 import org.apache.tapestry.spec.IContainedComponent; 028 029 /** 030 * Injects components for which the property attribute of the <component> 031 * element was specified. This makes it easier to reference a particular 032 * component from Java code. 033 * 034 * @author Howard M. Lewis Ship 035 * @since 4.0 036 */ 037 public class InjectComponentWorker implements EnhancementWorker 038 { 039 040 private ErrorLog _errorLog; 041 042 public void performEnhancement(EnhancementOperation op, 043 IComponentSpecification spec) 044 { 045 Iterator i = spec.getComponentIds().iterator(); 046 047 while(i.hasNext()) 048 { 049 String id = (String) i.next(); 050 051 IContainedComponent cc = spec.getComponent(id); 052 053 String propertyName = cc.getPropertyName(); 054 055 if (propertyName != null) 056 { 057 try 058 { 059 injectComponent(op, id, propertyName, cc.getLocation()); 060 } 061 catch (Exception ex) 062 { 063 _errorLog.error(EnhanceMessages.errorAddingProperty( 064 propertyName, op.getBaseClass(), ex), cc 065 .getLocation(), ex); 066 } 067 } 068 } 069 } 070 071 public void injectComponent(EnhancementOperation op, String componentId, 072 String propertyName, Location location) 073 { 074 Defense.notNull(op, "op"); 075 Defense.notNull(componentId, "componentId"); 076 Defense.notNull(propertyName, "propertyName"); 077 078 Class propertyType = EnhanceUtils.extractPropertyType(op, propertyName, 079 null); 080 081 op.claimReadonlyProperty(propertyName); 082 083 String fieldName = "_$" + propertyName; 084 String classField = op.getClassReference(propertyType); 085 String locationField = op.addInjectedField(fieldName + "$location", 086 Location.class, location); 087 088 op.addField(fieldName, propertyType); 089 090 EnhanceUtils.createSimpleAccessor(op, fieldName, propertyName, 091 propertyType, location); 092 093 // I.e. _$fred = (IComponent) TapestryUtils.getComponent(this, "fred", 094 // IComponent.class, 095 // location) 096 097 BodyBuilder builder = new BodyBuilder(); 098 099 builder.add("{0} = ({1}) ", fieldName, ClassFabUtils 100 .getJavaClassName(propertyType)); 101 builder.add("{0}#getComponent(this, ", TapestryUtils.class.getName()); 102 builder.addQuoted(componentId); 103 builder.add(", {0}, {1});", classField, locationField); 104 105 op.extendMethodImplementation(IComponent.class, 106 EnhanceUtils.FINISH_LOAD_SIGNATURE, builder.toString()); 107 } 108 109 public void setErrorLog(ErrorLog errorLog) 110 { 111 _errorLog = errorLog; 112 } 113 }