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.annotations;
016
017 import java.lang.reflect.Method;
018
019 import org.apache.hivemind.ApplicationRuntimeException;
020 import org.apache.hivemind.HiveMind;
021 import org.apache.hivemind.Location;
022 import org.apache.tapestry.enhance.EnhancementOperation;
023 import org.apache.tapestry.spec.BindingSpecification;
024 import org.apache.tapestry.spec.BindingType;
025 import org.apache.tapestry.spec.ContainedComponent;
026 import org.apache.tapestry.spec.IBindingSpecification;
027 import org.apache.tapestry.spec.IComponentSpecification;
028 import org.apache.tapestry.spec.IContainedComponent;
029
030 /**
031 * Adds a {@link org.apache.tapestry.spec.IContainedComponent} to the
032 * {@link org.apache.tapestry.spec.IComponentSpecification}.
033 *
034 * @author Howard Lewis Ship
035 * @since 4.0
036 * @see Component
037 */
038 public class ComponentAnnotationWorker implements MethodAnnotationEnhancementWorker
039 {
040
041 public void performEnhancement(EnhancementOperation op, IComponentSpecification spec,
042 Method method, Location location)
043 {
044 Component component = method.getAnnotation(Component.class);
045
046 String propertyName = AnnotationUtils.getPropertyName(method);
047 String type = component.type();
048 String copyOf = component.copyOf();
049 boolean hasCopyOf = HiveMind.isNonBlank(copyOf);
050
051 if (hasCopyOf)
052 {
053 if (HiveMind.isNonBlank(type))
054 throw new ApplicationRuntimeException(AnnotationMessages.bothTypeAndCopyOf(propertyName));
055 type = null;
056 }
057 else
058 {
059 if (type.equals(""))
060 {
061 Class retTypeClazz = method.getReturnType();
062 type = resolveComponentType(retTypeClazz);
063 }
064 copyOf = null;
065 }
066
067 IContainedComponent cc = new ContainedComponent();
068
069 cc.setInheritInformalParameters(component.inheritInformalParameters());
070 cc.setType(type);
071 cc.setCopyOf(copyOf);
072 cc.setPropertyName(propertyName);
073 cc.setLocation(location);
074
075 for (String binding : component.bindings())
076 {
077 addBinding(cc, binding, location);
078 }
079
080 for (String binding : component.inheritedBindings())
081 {
082 addInheritedBinding(cc, binding, location);
083 }
084
085 String id = component.id();
086
087 if (id.equals(""))
088 id = propertyName;
089
090 spec.addComponent(id, cc);
091
092 if (hasCopyOf)
093 {
094 IContainedComponent source = spec.getComponent(copyOf);
095 if (source != null)
096 AnnotationUtils.copyBindings(source, cc);
097 }
098 }
099
100 protected String resolveComponentType(Class retTypeClass)
101 {
102 return retTypeClass.getSimpleName();
103 }
104
105 void addBinding(IContainedComponent component, String binding, Location location)
106 {
107 int equalsx = binding.indexOf('=');
108
109 if (equalsx < 1)
110 invalidBinding(binding);
111
112 if (equalsx + 1 >= binding.length())
113 invalidBinding(binding);
114
115 String name = binding.substring(0, equalsx).trim();
116 String value = binding.substring(equalsx + 1).trim();
117
118 IBindingSpecification bs = new BindingSpecification();
119 bs.setType(BindingType.PREFIXED);
120 bs.setValue(value);
121 bs.setLocation(location);
122
123 component.setBinding(name, bs);
124 }
125
126 /**
127 * @since 4.1.4
128 */
129 void addInheritedBinding(IContainedComponent component, String binding, Location location)
130 {
131 int equalsx = binding.indexOf('=');
132 String name;
133 String containerName;
134
135 if (equalsx < 0)
136 {
137 name = binding.trim();
138 containerName = name;
139 }
140 else
141 {
142 name = binding.substring(0, equalsx).trim();
143 containerName = binding.substring(equalsx + 1).trim();
144 }
145
146 IBindingSpecification bs = new BindingSpecification();
147 bs.setType(BindingType.INHERITED);
148 bs.setValue(containerName);
149 bs.setLocation(location);
150
151 component.setBinding(name, bs);
152 }
153
154 protected void invalidBinding(String binding)
155 {
156 throw new ApplicationRuntimeException(AnnotationMessages.bindingWrongFormat(binding));
157 }
158 }