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.annotations.MethodAnnotationEnhancementWorker; 024 import org.apache.tapestry.enhance.EnhancementOperation; 025 import org.apache.tapestry.enhance.EnhanceUtils; 026 import org.apache.tapestry.spec.IComponentSpecification; 027 import org.apache.tapestry.IComponent; 028 029 /** 030 * @author Andreas Andreou 031 */ 032 033 public class CachedAnnotationWorker implements MethodAnnotationEnhancementWorker { 034 035 public void performEnhancement(EnhancementOperation op, IComponentSpecification spec, 036 Method method, Location location) { 037 Class<?> type = method.getReturnType(); 038 if (type.equals(void.class)) 039 throw new ApplicationRuntimeException( 040 "Cached annotation cannot be used with a method that returns void"); 041 042 String fieldName = "_$cached$" + method.getName(); 043 MethodSignature signature = new MethodSignature(method); 044 045 op.addField(fieldName, type); 046 047 BodyBuilder builder = createCacheMethod(signature, fieldName); 048 op.addMethod(Modifier.PUBLIC, signature, builder.toString(), location); 049 050 extendCleanupAfterRender(op, fieldName); 051 } 052 053 BodyBuilder createCacheMethod(MethodSignature sig, String cacheField) 054 { 055 BodyBuilder result = new BodyBuilder(); 056 057 result.begin(); 058 059 result.addln("if (this.{0}==null)", cacheField); 060 result.addln("this.{0} = super.{1}($$);", cacheField, sig.getName()); 061 062 result.addln("return this.{0};", cacheField); 063 064 result.end(); 065 066 return result; 067 } 068 069 void extendCleanupAfterRender(EnhancementOperation op, String fieldName) 070 { 071 BodyBuilder cleanupBody = new BodyBuilder(); 072 cleanupBody.addln("{0} = null;", fieldName); 073 op.extendMethodImplementation(IComponent.class, 074 EnhanceUtils.CLEANUP_AFTER_RENDER_SIGNATURE, cleanupBody.toString()); 075 } 076 }