Author: hlship
Date: Fri Feb 19 18:53:44 2010
New Revision: 911919

URL: http://svn.apache.org/viewvc?rev=911919&view=rev
Log:
Record PageResetAnnotationWorker using MethodAccess API

Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java?rev=911919&r1=911918&r2=911919&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java
 Fri Feb 19 18:53:44 2010
@@ -17,18 +17,23 @@
 import java.util.List;
 
 import org.apache.tapestry5.annotations.PageReset;
+import org.apache.tapestry5.internal.InternalComponentResources;
 import org.apache.tapestry5.internal.structure.PageResetListener;
+import org.apache.tapestry5.ioc.Predicate;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.model.MutableComponentModel;
 import org.apache.tapestry5.services.ClassTransformation;
 import org.apache.tapestry5.services.ComponentClassTransformWorker;
-import org.apache.tapestry5.services.MethodFilter;
+import org.apache.tapestry5.services.ComponentMethodAdvice;
+import org.apache.tapestry5.services.ComponentMethodInvocation;
+import org.apache.tapestry5.services.MethodAccess;
+import org.apache.tapestry5.services.MethodInvocationResult;
 import org.apache.tapestry5.services.TransformConstants;
+import org.apache.tapestry5.services.TransformMethod;
 import org.apache.tapestry5.services.TransformMethodSignature;
 
 /**
- * Implementation of the {...@link PageReset} annotation. Makes the component 
implement
- * {...@link PageResetListener} and,
- * optionally,
+ * Implementation of the {...@link PageReset} annotation. Makes the component 
implement {...@link PageResetListener}.
  * 
  * @since 5.2.0
  */
@@ -39,48 +44,118 @@
     private static final TransformMethodSignature CONTAINING_PAGE_DID_RESET = 
new TransformMethodSignature(
             "containingPageDidReset");
 
-    public void transform(final ClassTransformation transformation, 
MutableComponentModel model)
+    private final ComponentMethodAdvice registerAsListenerAdvice = new 
ComponentMethodAdvice()
     {
-        MethodFilter filter = new MethodFilter()
+        public void advise(ComponentMethodInvocation invocation)
         {
-            public boolean accept(TransformMethodSignature signature)
-            {
-                return signature.getMethodName().equalsIgnoreCase("pageReset")
-                        || transformation.getMethodAnnotation(signature, 
PageReset.class) != null;
-            }
-        };
+            invocation.proceed();
+
+            InternalComponentResources icr = (InternalComponentResources) 
invocation.getComponentResources();
+
+            icr.addPageResetListener((PageResetListener) 
invocation.getInstance());
+        }
+    };
 
-        List<TransformMethodSignature> methods = 
transformation.findMethods(filter);
+    public void transform(final ClassTransformation transformation, 
MutableComponentModel model)
+    {
+        List<TransformMethod> methods = matchPageResetMethods(transformation);
 
         if (methods.isEmpty())
             return;
 
-        String resourcesFieldName = transformation.getResourcesFieldName();
+        makeComponentRegisterAsPageResetListenerAtPageLoad(transformation, 
model);
 
-        if (model.getMeta(META_KEY) == null)
+        adviseContainingPageDidResetMethod(transformation, methods);
+    }
+
+    private void adviseContainingPageDidResetMethod(ClassTransformation 
transformation, List<TransformMethod> methods)
+    {
+        List<MethodAccess> methodAccess = convertToMethodAccess(methods);
+
+        ComponentMethodAdvice advice = createMethodAccessAdvice(methodAccess);
+
+        transformation.getMethod(CONTAINING_PAGE_DID_RESET).addAdvice(advice);
+    }
+
+    private ComponentMethodAdvice createMethodAccessAdvice(final 
List<MethodAccess> methodAccess)
+    {
+        ComponentMethodAdvice advice = new ComponentMethodAdvice()
         {
-            transformation.addImplementedInterface(PageResetListener.class);
+            public void advise(ComponentMethodInvocation invocation)
+            {
+                invocation.proceed();
+
+                invokeResetMethods(invocation.getInstance());
+            }
+
+            private void invokeResetMethods(Object instance)
+            {
+                for (MethodAccess access : methodAccess)
+                {
+                    MethodInvocationResult result = access.invoke(instance);
+
+                    result.rethrow();
+                }
+            }
+        };
+        return advice;
+    }
 
-            
transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE,
-                    String.format("%s.addPageResetListener(this);", 
resourcesFieldName));
+    private List<MethodAccess> convertToMethodAccess(List<TransformMethod> 
methods)
+    {
+        List<MethodAccess> result = CollectionFactory.newList();
 
-            model.setMeta(META_KEY, "true");
+        for (TransformMethod method : methods)
+        {
+            result.add(toMethodAccess(method));
         }
 
-        for (TransformMethodSignature sig : methods)
+        return result;
+    }
+
+    private void makeComponentRegisterAsPageResetListenerAtPageLoad(final 
ClassTransformation transformation,
+            MutableComponentModel model)
+    {
+        // The meta key tracks whether this has already occurred; it is only 
necessary for a base class
+        // (subclasses, even if they include pageReset methods, do not need to 
re-register if the base class
+        // already has).
+
+        if (model.getMeta(META_KEY) != null)
+            return;
+
+        transformation.addImplementedInterface(PageResetListener.class);
+
+        
transformation.getMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE).addAdvice(
+                registerAsListenerAdvice);
+
+        model.setMeta(META_KEY, "true");
+    }
+
+    private List<TransformMethod> matchPageResetMethods(final 
ClassTransformation transformation)
+    {
+        return transformation.matchMethods(new Predicate<TransformMethod>()
         {
-            boolean valid = sig.getParameterTypes().length == 0
-                    && sig.getReturnType().equals("void") && 
sig.getExceptionTypes().length == 0;
 
-            if (!valid)
-                throw new RuntimeException(
-                        String
-                                .format(
-                                        "Method %s of class %s is invalid: 
methods with the @PageReset annotation must return void, and have no parameters 
or thrown exceptions.",
-                                        sig, model.getComponentClassName()));
+            public boolean accept(TransformMethod method)
+            {
+                return method.getName().equalsIgnoreCase("pageReset") || 
method.getAnnotation(PageReset.class) != null;
+            }
+        });
+    }
 
-            transformation.extendMethod(CONTAINING_PAGE_DID_RESET, 
sig.getMethodName() + "();");
-        }
+    private MethodAccess toMethodAccess(TransformMethod method)
+    {
+        TransformMethodSignature sig = method.getSignature();
+
+        boolean valid = sig.getParameterTypes().length == 0 && 
sig.getReturnType().equals("void");
+
+        if (!valid)
+            throw new RuntimeException(
+                    String
+                            .format(
+                                    "Method %s is invalid: methods with the 
@PageReset annotation must return void, and have no parameters.",
+                                    method.getMethodIdentifier()));
 
+        return method.getAccess();
     }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java?rev=911919&r1=911918&r2=911919&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
 Fri Feb 19 18:53:44 2010
@@ -1465,6 +1465,8 @@
     {
         clickThru("PageReset Annotation Failure");
 
-        assertTextPresent("Method void reset(java.lang.String) of class 
org.apache.tapestry5.integration.app1.pages.PageResetFailure is invalid: 
methods with the @PageReset annotation must return void, and have no parameters 
or thrown exceptions.");
+        assertTextPresent(
+                "Method 
org.apache.tapestry5.integration.app1.pages.PageResetFailure.reset(java.lang.String)",
+                "is invalid: methods with the @PageReset annotation must 
return void, and have no parameters.");
     }
 }


Reply via email to