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