001    //
002    // Licensed under the Apache License, Version 2.0 (the "License");
003    // you may not use this file except in compliance with the License.
004    // You may obtain a copy of the License at
005    //
006    //     http://www.apache.org/licenses/LICENSE-2.0
007    //
008    // Unless required by applicable law or agreed to in writing, software
009    // distributed under the License is distributed on an "AS IS" BASIS,
010    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011    // See the License for the specific language governing permissions and
012    // limitations under the License.
013    
014    package net.sf.tacos.annotations;
015    
016    import java.lang.reflect.Method;
017    import java.lang.reflect.Modifier;
018    
019    import org.apache.hivemind.ApplicationRuntimeException;
020    import org.apache.hivemind.Location;
021    import org.apache.hivemind.service.BodyBuilder;
022    import org.apache.hivemind.service.MethodSignature;
023    import org.apache.tapestry.Tapestry;
024    import org.apache.tapestry.annotations.AnnotationUtils;
025    import org.apache.tapestry.annotations.MethodAnnotationEnhancementWorker;
026    import org.apache.tapestry.engine.ILink;
027    import org.apache.tapestry.enhance.EnhancementOperation;
028    import org.apache.tapestry.spec.IComponentSpecification;
029    
030    /**
031     * @author Ming Jiang
032     * @author Andreas Andreou
033     */
034    
035    public class InjectExternalLinkAnnotationWorker implements
036                    MethodAnnotationEnhancementWorker {
037    
038        public void performEnhancement(EnhancementOperation op, IComponentSpecification spec,
039                Method method, Location location) {
040            if (!method.getReturnType().equals(ILink.class))
041                    throw new ApplicationRuntimeException("injectExternalLink annotation must return ILink");
042    
043            InjectExternalLink injectExternalLink = method.getAnnotation(InjectExternalLink.class);
044    
045            String pageName = injectExternalLink.value();
046    
047            BodyBuilder builder = new BodyBuilder();
048    
049            builder.begin();
050            builder.addln("String pageName=\"{0}\";", pageName);
051            if (injectExternalLink.currentNamespace())
052                builder.addln("pageName=getNamespace().constructQualifiedName(pageName);");        
053    
054            Class[] parameterTypes = method.getParameterTypes();
055            int paramCount = Tapestry.size(parameterTypes);
056    
057            if (paramCount > 0) {
058                    if (parameterTypes[0].isArray()) {
059                            builder.addln("return getPage().getRequestCycle().getInfrastructure().getServiceMap()." +
060                                    "getService(org.apache.tapestry.Tapestry.EXTERNAL_SERVICE).getLink(false, new org.apache.tapestry.engine.ExternalServiceParameter(pageName,$1));");
061                    } else {
062                            builder.addln("java.lang.Object[] params = new java.lang.Object[{0}];", paramCount);
063                            for (int i = 0; i < paramCount; i++) {
064                                    builder.add("params[{0}] = ", i);
065                                    if (parameterTypes[i].isPrimitive())
066                                            builder.add("($w) ");
067                                    builder.addln("${0};", i + 1);
068                            }
069                            builder.addln("return getPage().getRequestCycle().getInfrastructure().getServiceMap()." +
070                                    "getService(org.apache.tapestry.Tapestry.EXTERNAL_SERVICE).getLink(false, new org.apache.tapestry.engine.ExternalServiceParameter(pageName,params));");
071                    }
072            }
073    
074            builder.end();
075    
076            op.addMethod(Modifier.PUBLIC, new MethodSignature(method), builder
077                            .toString(), location);
078    
079            if (isGetter(method))
080                    op.claimReadonlyProperty(AnnotationUtils.getPropertyName(method));
081        }
082    
083        boolean isGetter(Method method) {
084                return method.getName().startsWith("get")
085                                && method.getParameterTypes().length == 0;
086        }
087    }