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 015package org.apache.tapestry.enhance; 016 017import java.lang.reflect.Modifier; 018import java.util.HashMap; 019import java.util.Map; 020 021import org.apache.hivemind.Location; 022import org.apache.hivemind.service.BodyBuilder; 023import org.apache.hivemind.service.ClassFabUtils; 024import org.apache.hivemind.service.MethodSignature; 025import org.apache.hivemind.util.Defense; 026import org.apache.tapestry.coerce.ValueConverter; 027import org.apache.tapestry.services.ComponentPropertySource; 028import org.apache.tapestry.spec.InjectSpecification; 029 030/** 031 * Injects meta data obtained via {@link org.apache.tapestry.services.ComponentPropertySource} 032 * (meaning that meta-data is searched for in the component's specification, then it's namespace 033 * (library or application specification), then the global application properties. 034 * 035 * @author Howard M. Lewis Ship 036 * @since 4.0 037 */ 038public class InjectMetaWorker implements InjectEnhancementWorker 039{ 040 static final String SOURCE_NAME = "_$componentPropertySource"; 041 042 private ComponentPropertySource _source; 043 044 private ValueConverter _valueConverter; 045 046 private Map _primitiveParser = new HashMap(); 047 048 { 049 _primitiveParser.put(boolean.class, "java.lang.Boolean.parseBoolean"); 050 _primitiveParser.put(short.class, "java.lang.Short.parseShort"); 051 _primitiveParser.put(int.class, "java.lang.Integer.parseInt"); 052 _primitiveParser.put(long.class, "java.lang.Long.parseLong"); 053 _primitiveParser.put(double.class, "java.lang.Double.parseDouble"); 054 _primitiveParser.put(float.class, "java.lang.Float.parseFloat"); 055 } 056 057 public void performEnhancement(EnhancementOperation op, InjectSpecification spec) 058 { 059 String propertyName = spec.getProperty(); 060 String metaKey = spec.getObject(); 061 062 injectMetaValue(op, propertyName, metaKey, spec.getLocation()); 063 } 064 065 public void injectMetaValue(EnhancementOperation op, String propertyName, String metaKey, 066 Location location) 067 { 068 Defense.notNull(op, "op"); 069 Defense.notNull(propertyName, "propertyName"); 070 Defense.notNull(metaKey, "metaKey"); 071 072 Class propertyType = op.getPropertyType(propertyName); 073 074 op.claimReadonlyProperty(propertyName); 075 076 String sourceName = op 077 .addInjectedField(SOURCE_NAME, ComponentPropertySource.class, _source); 078 079 MethodSignature sig = new MethodSignature(propertyType, op 080 .getAccessorMethodName(propertyName), null, null); 081 082 String parser = (String) _primitiveParser.get(propertyType); 083 084 if (parser != null) 085 { 086 addPrimitive(op, metaKey, propertyName, sig, sourceName, parser, location); 087 return; 088 } 089 090 if (propertyType == char.class) 091 { 092 addCharacterPrimitive(op, metaKey, propertyName, sig, sourceName, location); 093 return; 094 } 095 096 addObject(op, metaKey, propertyName, propertyType, sig, sourceName, location); 097 } 098 099 private void addPrimitive(EnhancementOperation op, String metaKey, String propertyName, 100 MethodSignature sig, String sourceName, String parser, Location location) 101 { 102 BodyBuilder builder = new BodyBuilder(); 103 builder.begin(); 104 builder.addln( 105 "java.lang.String meta = {0}.getComponentProperty(this, \"{1}\");", 106 sourceName, 107 metaKey); 108 builder.addln("return {0}(meta);", parser); 109 builder.end(); 110 111 op.addMethod(Modifier.PUBLIC, sig, builder.toString(), location); 112 } 113 114 private void addCharacterPrimitive(EnhancementOperation op, String metaKey, 115 String propertyName, MethodSignature sig, String sourceName, Location location) 116 { 117 BodyBuilder builder = new BodyBuilder(); 118 builder.begin(); 119 builder.addln( 120 "java.lang.String meta = {0}.getComponentProperty(this, \"{1}\");", 121 sourceName, 122 metaKey); 123 builder.addln("return meta.charAt(0);"); 124 builder.end(); 125 126 op.addMethod(Modifier.PUBLIC, sig, builder.toString(), location); 127 } 128 129 private void addObject(EnhancementOperation op, String metaKey, String propertyName, 130 Class propertyType, MethodSignature sig, String sourceName, Location location) 131 { 132 String valueConverterName = op.addInjectedField( 133 "_$valueConverter", 134 ValueConverter.class, 135 _valueConverter); 136 String classRef = op.getClassReference(propertyType); 137 138 BodyBuilder builder = new BodyBuilder(); 139 builder.begin(); 140 builder.addln( 141 "java.lang.String meta = {0}.getComponentProperty(this, \"{1}\");", 142 sourceName, 143 metaKey); 144 builder.addln("return ({0}) {1}.coerceValue(meta, {2});", ClassFabUtils 145 .getJavaClassName(propertyType), valueConverterName, classRef); 146 builder.end(); 147 148 op.addMethod(Modifier.PUBLIC, sig, builder.toString(), location); 149 } 150 151 public void setSource(ComponentPropertySource source) 152 { 153 _source = source; 154 } 155 156 public void setValueConverter(ValueConverter valueConverter) 157 { 158 _valueConverter = valueConverter; 159 } 160}