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.lang.reflect.Modifier;
018 import java.util.HashMap;
019 import java.util.Map;
020
021 import org.apache.hivemind.Location;
022 import org.apache.hivemind.service.BodyBuilder;
023 import org.apache.hivemind.service.ClassFabUtils;
024 import org.apache.hivemind.service.MethodSignature;
025 import org.apache.hivemind.util.Defense;
026 import org.apache.tapestry.coerce.ValueConverter;
027 import org.apache.tapestry.services.ComponentPropertySource;
028 import 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 */
038 public 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 }