Author: hlship
Date: Wed Dec 20 16:27:14 2006
New Revision: 489232

URL: http://svn.apache.org/viewvc?view=rev&rev=489232
Log:
Allow render phase methods to be identified simply by specific names, in 
addition to arbitrary names with annotations

Added:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodFilter.java
Modified:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Output.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Strong.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java?view=diff&rev=489232&r1=489231&r2=489232
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java
 Wed Dec 20 16:27:14 2006
@@ -12,136 +12,157 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.services;
-
-import java.lang.annotation.Annotation;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.tapestry.MarkupWriter;
+package org.apache.tapestry.internal.services;
+
+import java.lang.annotation.Annotation;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.internal.util.MethodInvocationBuilder;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.util.BodyBuilder;
-import org.apache.tapestry.model.MutableComponentModel;
-import org.apache.tapestry.services.ClassTransformation;
-import org.apache.tapestry.services.ComponentClassTransformWorker;
-import org.apache.tapestry.services.MethodSignature;
-
-/**
- * Converts one of the methods of [EMAIL PROTECTED] 
org.apache.tapestry.runtime.Component} into a
- * chain of command that, itself, invokes certain methods marked with an 
annotation.
- */
-public class ComponentLifecycleMethodWorker implements 
ComponentClassTransformWorker
-{
-    private static final String CHECK_ABORT_FLAG = "if ($2.isAborted()) 
return;";
-
-    private final Class<? extends Annotation> _methodAnnotation;
-
-    private final MethodSignature _lifecycleMethodSignature;
-
-    private final String _lifecycleMethodName;
-
-    private final boolean _reverse;
-
-    private final MethodInvocationBuilder _invocationBuilder = new 
MethodInvocationBuilder();
-
-    /**
-     * Normal method invocation: parent class, then methods in ascending 
alphabetical order. Reverse
-     * order: method in descending alphabetical order, then parent class.
-     * 
-     * @param lifecycleMethodSignature
-     *            the signature of the method to be implemented in the 
component class
-     * @param methodAnnotation
-     *            the class of the corresponding annotation
-     * @param reverse
-     *            if true, the normal method invocation order is reversed
-     */
-    public ComponentLifecycleMethodWorker(MethodSignature 
lifecycleMethodSignature,
-            Class<? extends Annotation> methodAnnotation, boolean reverse)
-    {
-        _lifecycleMethodSignature = lifecycleMethodSignature;
-        _methodAnnotation = methodAnnotation;
-        _reverse = reverse;
-        _lifecycleMethodName = lifecycleMethodSignature.getMethodName();
-
-        _invocationBuilder.addParameter(MarkupWriter.class.getName(), "$1");
-    }
-
-    @Override
-    public String toString()
-    {
-        return String.format("ComponentLifecycleMethodWorker[%s]", 
_methodAnnotation.getName());
-    }
-
-    public void transform(ClassTransformation transformation, 
MutableComponentModel model)
-    {
-        List<MethodSignature> methods = 
transformation.findMethodsWithAnnotation(_methodAnnotation);
-
-        // Except in the root class, don't bother to add a new method unless 
there's something to
-        // call (beside super).
-
-        if (methods.isEmpty())
-            return;
-
-        BodyBuilder builder = new BodyBuilder();
-        builder.begin();
-
-        // If in a subclass, and in normal order mode, invoke the super class 
version first.
-
-        if (!(_reverse || model.isRootClass()))
-        {
-            builder.addln("super.%s($$);", _lifecycleMethodName);
-            builder.addln(CHECK_ABORT_FLAG);
-        }
-
-        Iterator<MethodSignature> i = _reverse ? 
InternalUtils.reverseIterator(methods) : methods
-                .iterator();
-
-        while (i.hasNext())
-            addMethodCallToBody(builder, i.next(), transformation);
-
-        // In reverse order in a a subclass, invoke the super method last.
-
-        if (_reverse && !model.isRootClass())
-            builder.addln("super.%s($$);", _lifecycleMethodName);
-
-        builder.end();
-
-        // Let's see if this works; for base classes, we are adding an empty 
method the adding a
-        // non-empty
-        // method "on top of it".
-
-        transformation.addMethod(_lifecycleMethodSignature, 
builder.toString());
-    }
-
-    private void addMethodCallToBody(BodyBuilder builder, MethodSignature sig,
-            ClassTransformation transformation)
-    {
-        boolean isVoid = sig.getReturnType().equals("void");
-
-        if (!isVoid)
-            builder.add("if ($2.storeResult(($w) ");
-
-        // This is the best part; the method can even be private and this 
still works. It's a lot
-        // like how javac enables access to private members for inner classes 
(by introducing
-        // synthetic, static methods).
-
-        builder.add(_invocationBuilder.buildMethodInvocation(sig, 
transformation));
-
-        // Now, if non void ...
-
-        if (!isVoid)
-        {
-            // Complete the call to storeResult(), with a string that
-            // identifies the class and the method. Finish off the if(...) that
-            // checks the return value and returns early. The return value of
-            // LifecycleEvent.storeResult() is true if the event is aborted by 
the call.
-
-            builder.addln(", \"%s.%s\")) return;", 
transformation.getClassName(), sig
-                    .getMediumDescription());
-        }
-        else
-            builder.addln(";");
-    }
-
-}
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.MethodFilter;
+import org.apache.tapestry.services.MethodSignature;
+
+/**
+ * Converts one of the methods of [EMAIL PROTECTED] 
org.apache.tapestry.runtime.Component} into a chain of
+ * command that, itself, invokes certain methods (render phase methods) marked 
with an annotation,
+ * or named in a specific way.
+ */
+public class ComponentLifecycleMethodWorker implements 
ComponentClassTransformWorker
+{
+    private static final String CHECK_ABORT_FLAG = "if ($2.isAborted()) 
return;";
+
+    private final Class<? extends Annotation> _methodAnnotation;
+
+    private final MethodSignature _lifecycleMethodSignature;
+
+    private final String _lifecycleMethodName;
+
+    private final boolean _reverse;
+
+    private final MethodInvocationBuilder _invocationBuilder = new 
MethodInvocationBuilder();
+
+    /**
+     * Normal method invocation: parent class, then methods in ascending 
alphabetical order. Reverse
+     * order: method in descending alphabetical order, then parent class.
+     * 
+     * @param lifecycleMethodSignature
+     *            the signature of the method to be implemented in the 
component class
+     * @param methodAnnotation
+     *            the class of the corresponding annotation
+     * @param reverse
+     *            if true, the normal method invocation order is reversed
+     */
+    public ComponentLifecycleMethodWorker(MethodSignature 
lifecycleMethodSignature,
+            Class<? extends Annotation> methodAnnotation, boolean reverse)
+    {
+        _lifecycleMethodSignature = lifecycleMethodSignature;
+        _methodAnnotation = methodAnnotation;
+        _reverse = reverse;
+        _lifecycleMethodName = lifecycleMethodSignature.getMethodName();
+
+        _invocationBuilder.addParameter(MarkupWriter.class.getName(), "$1");
+    }
+
+    @Override
+    public String toString()
+    {
+        return String.format("ComponentLifecycleMethodWorker[%s]", 
_methodAnnotation.getName());
+    }
+
+    public void transform(final ClassTransformation transformation, 
MutableComponentModel model)
+    {
+        MethodFilter filter = new MethodFilter()
+        {
+            public boolean accept(MethodSignature signature)
+            {
+                // These methods get added to base classes and otherwise fall 
into this filter.  If we don't
+                // include this filter, then we get endless loops.
+                
+                if (signature.equals(_lifecycleMethodSignature))
+                    return false;
+
+                // A degenerate case would be a method, say beginRender(), 
with an conflicting
+                // annotation, say @AfterRender. In that case, this code is 
broken, as the method
+                // will be invoked for both phases!
+
+                return signature.getMethodName().equals(_lifecycleMethodName)
+                        || transformation.getMethodAnnotation(signature, 
_methodAnnotation) != null;
+            }
+        };
+
+        List<MethodSignature> methods = transformation.findMethods(filter);
+
+        // Except in the root class, don't bother to add a new method unless 
there's something to
+        // call (beside super).
+
+        if (methods.isEmpty())
+            return;
+
+        BodyBuilder builder = new BodyBuilder();
+        builder.begin();
+
+        // If in a subclass, and in normal order mode, invoke the super class 
version first.
+
+        if (!(_reverse || model.isRootClass()))
+        {
+            builder.addln("super.%s($$);", _lifecycleMethodName);
+            builder.addln(CHECK_ABORT_FLAG);
+        }
+
+        Iterator<MethodSignature> i = _reverse ? 
InternalUtils.reverseIterator(methods) : methods
+                .iterator();
+
+        while (i.hasNext())
+            addMethodCallToBody(builder, i.next(), transformation);
+
+        // In reverse order in a a subclass, invoke the super method last.
+
+        if (_reverse && !model.isRootClass())
+            builder.addln("super.%s($$);", _lifecycleMethodName);
+
+        builder.end();
+
+        // Let's see if this works; for base classes, we are adding an empty 
method the adding a
+        // non-empty
+        // method "on top of it".
+
+        transformation.addMethod(_lifecycleMethodSignature, 
builder.toString());
+    }
+
+    private void addMethodCallToBody(BodyBuilder builder, MethodSignature sig,
+            ClassTransformation transformation)
+    {
+        boolean isVoid = sig.getReturnType().equals("void");
+
+        if (!isVoid)
+            builder.add("if ($2.storeResult(($w) ");
+
+        // This is the best part; the method can even be private and this 
still works. It's a lot
+        // like how javac enables access to private members for inner classes 
(by introducing
+        // synthetic, static methods).
+
+        builder.add(_invocationBuilder.buildMethodInvocation(sig, 
transformation));
+
+        // Now, if non void ...
+
+        if (!isVoid)
+        {
+            // Complete the call to storeResult(), with a string that
+            // identifies the class and the method. Finish off the if(...) that
+            // checks the return value and returns early. The return value of
+            // LifecycleEvent.storeResult() is true if the event is aborted by 
the call.
+
+            builder.addln(", \"%s.%s\")) return;", 
transformation.getClassName(), sig
+                    .getMediumDescription());
+        }
+        else
+            builder.addln(";");
+    }
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java?view=diff&rev=489232&r1=489231&r2=489232
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
 Wed Dec 20 16:27:14 2006
@@ -52,6 +52,7 @@
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.model.ComponentModel;
 import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.services.MethodFilter;
 import org.apache.tapestry.services.MethodSignature;
 import org.apache.tapestry.services.TransformUtils;
 
@@ -866,6 +867,25 @@
                 MethodSignature sig = getMethodSignature(method);
                 result.add(sig);
             }
+        }
+
+        Collections.sort(result);
+
+        return result;
+    }
+
+    public List<MethodSignature> findMethods(MethodFilter filter)
+    {
+        notNull(filter, "filter");
+
+        List<MethodSignature> result = newList();
+
+        for (CtMethod method : _ctClass.getDeclaredMethods())
+        {
+            MethodSignature sig = getMethodSignature(method);
+
+            if (filter.accept(sig))
+                result.add(sig);
         }
 
         Collections.sort(result);

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java?view=diff&rev=489232&r1=489231&r2=489232
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
 Wed Dec 20 16:27:14 2006
@@ -79,6 +79,15 @@
     List<MethodSignature> findMethodsWithAnnotation(Class<? extends 
Annotation> annotationClass);
 
     /**
+     * Finds all methods matched by the provided filter.
+     * 
+     * @param filter
+     *            Passed each method signature, it may include or exclude each 
potential
+     * @return a list of matching method signatures (which may be empty) in 
ascending order
+     */
+    List<MethodSignature> findMethods(MethodFilter filter);
+
+    /**
      * Finds an annotation for the class itself, including any annotations 
inherited from parent
      * classes.
      * 

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodFilter.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodFilter.java?view=auto&rev=489232
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodFilter.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodFilter.java
 Wed Dec 20 16:27:14 2006
@@ -0,0 +1,13 @@
+package org.apache.tapestry.services;
+
+/**
+ * Used by [EMAIL PROTECTED] ClassTransformation#findMethods(MethodFilter)} to 
accept or reject each method.
+ */
+public interface MethodFilter
+{
+    /**
+     * Passed each signature in turn, only signatures for which this method 
returns true will be
+     * included in the final result.
+     */
+    boolean accept(MethodSignature signature);
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?view=diff&rev=489232&r1=489231&r2=489232
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
 Wed Dec 20 16:27:14 2006
@@ -16,6 +16,7 @@
 
 import static java.lang.Thread.sleep;
 import static org.apache.tapestry.internal.test.CodeEq.codeEq;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
 import static org.easymock.EasyMock.eq;
 
 import java.io.File;
@@ -56,6 +57,7 @@
 import org.apache.tapestry.services.ClasspathAssetAliasManager;
 import org.apache.tapestry.services.ComponentClassResolver;
 import org.apache.tapestry.services.InjectionProvider;
+import org.apache.tapestry.services.MethodFilter;
 import org.apache.tapestry.services.MethodSignature;
 import org.apache.tapestry.services.ResourceDigestGenerator;
 import org.apache.tapestry.services.Context;
@@ -63,6 +65,8 @@
 import org.apache.tapestry.services.RequestHandler;
 import org.apache.tapestry.services.Response;
 import org.apache.tapestry.services.Session;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
 
 /**
  * Base test case that adds a number of convienience factory and training 
methods for the public
@@ -511,5 +515,39 @@
     protected final void train_getDateHeader(Request request, String name, 
long value)
     {
         expect(request.getDateHeader(name)).andReturn(value).atLeastOnce();
+    }
+
+    protected final void train_findMethods(ClassTransformation transformation, 
final MethodSignature... signatures)
+    {
+        IAnswer<List<MethodSignature>> answer = new 
IAnswer<List<MethodSignature>>()
+        {
+            public List<MethodSignature> answer() throws Throwable
+            {
+                // Can't think of a way to do this without duplicating some 
code out of
+                // InternalClassTransformationImpl
+    
+                List<MethodSignature> result = newList();
+                MethodFilter filter = (MethodFilter) 
EasyMock.getCurrentArguments()[0];
+    
+                for (MethodSignature sig : signatures)
+                {
+                    if (filter.accept(sig))
+                        result.add(sig);
+                }
+    
+                // We don't have to sort them for testing purposes. Usually 
there's just going to be
+                // one in there.
+    
+                return result;
+            }
+    
+        };
+    
+        
expect(transformation.findMethods(EasyMock.isA(MethodFilter.class))).andAnswer(answer);
+    }
+
+    protected final void train_isRootClass(MutableComponentModel model, 
boolean isRootClass)
+    {
+        expect(model.isRootClass()).andReturn(isRootClass);
     }
 }

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt?view=diff&rev=489232&r1=489231&r2=489232
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt Wed 
Dec 20 16:27:14 2006
@@ -194,6 +194,75 @@
 * 
{{{../apidocs/org/apache/tapestry/annotations/CleanupRender.html}CleanupRender}}
   
   The counterpart to SetupRender, this allows final cleanups to occur.
+  
+Using Method Names instead of Annotations
+
+  If you prefer to avoid using annotations on your methods, you may do so by 
providing specific names for your methods.  
+  The required method name is the annotation name, with the first character 
decapitalized:  setupRender(), beginRender(), etc.
+  As with annotated render phase methods, Tapestry is flexible about 
visibility, return type and parameters.
+  
+  Using this mechanism, the earlier example can be rewritten as:
+    
++---+
+package org.example.app.components;
+
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Parameter;
+
[EMAIL PROTECTED]
+public class Count
+{
+    @Parameter
+    private int _start = 1;
+
+    @Parameter(required = true)
+    private int _end;
+
+    @Parameter
+    private int _value;
+
+    private boolean _increment;
+
+    void setupRender()
+    {
+        _value = _start;
+
+        _increment = _start < _end;
+    }
+
+    boolean afterRender()
+    {
+        if (_increment)
+        {
+            int newValue = _value + 1;
+
+            if (newValue <= _end)
+            {
+                _value = newValue;
+                return true;
+            }
+        }
+        else
+        {
+            int newValue = _value - 1;
+
+            if (newValue >= _end)
+            {
+                _value = newValue;
+                return true; 
+            }
+        }
+
+        return false;
+    }
+}
++---+   
+
+  This style is a tradeoff: on the gain side, the code is <even> simpler and 
shorter, and the method names will, by design, be more consistent from one 
class to the next.
+  The down side is that the names are very generic, and may in some cases, be 
less descriptive than using annotated methods (<<<initializeValue()>>> and 
<<<next()>>> are,
+  to some eyes, more descriptive).
+  
+  You can, of course, mix and match, using specifically named render phase 
methods in some cases, and annotated render phase methods in other cases. 
 
 Method Conflicts and Ordering
 

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Output.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Output.java?view=diff&rev=489232&r1=489231&r2=489232
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Output.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Output.java
 Wed Dec 20 16:27:14 2006
@@ -12,30 +12,28 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.integration.app1.components;
-
-import java.text.Format;
-
-import org.apache.tapestry.MarkupWriter;
-import org.apache.tapestry.annotations.BeginRender;
-import org.apache.tapestry.annotations.ComponentClass;
-import org.apache.tapestry.annotations.Parameter;
-
-/** component that formats a value and outputs it. */
[EMAIL PROTECTED]
-public class Output
-{
-    @Parameter(required = true)
-    private Object _value;
-
-    @Parameter(required = true)
-    private Format _format;
-
-    @BeginRender
-    void render(MarkupWriter writer)
-    {
-        String formatted = _format.format(_value);
-
-        writer.write(formatted);
-    }
-}
+package org.apache.tapestry.integration.app1.components;
+
+import java.text.Format;
+
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Parameter;
+
+/** component that formats a value and outputs it. */
[EMAIL PROTECTED]
+public class Output
+{
+    @Parameter(required = true)
+    private Object _value;
+
+    @Parameter(required = true)
+    private Format _format;
+
+    void beginRender(MarkupWriter writer)
+    {
+        String formatted = _format.format(_value);
+
+        writer.write(formatted);
+    }
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Strong.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Strong.java?view=diff&rev=489232&r1=489231&r2=489232
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Strong.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Strong.java
 Wed Dec 20 16:27:14 2006
@@ -12,25 +12,21 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.integration.app1.components;
-
-import org.apache.tapestry.MarkupWriter;
-import org.apache.tapestry.annotations.AfterRender;
-import org.apache.tapestry.annotations.BeginRender;
-import org.apache.tapestry.annotations.ComponentClass;
-
[EMAIL PROTECTED]
-public class Strong
-{
-    @BeginRender
-    public void start(MarkupWriter writer)
-    {
-        writer.element("strong");
-    }
-
-    @AfterRender
-    public void end(MarkupWriter writer)
-    {
-        writer.end();
-    }
-}
+package org.apache.tapestry.integration.app1.components;
+
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.ComponentClass;
+
[EMAIL PROTECTED]
+public class Strong
+{
+    void beginRender(MarkupWriter writer)
+    {
+        writer.element("strong");
+    }
+
+    void afterRender(MarkupWriter writer)
+    {
+        writer.end();
+    }
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java?view=diff&rev=489232&r1=489231&r2=489232
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
 Wed Dec 20 16:27:14 2006
@@ -14,10 +14,7 @@
 
 package org.apache.tapestry.internal.services;
 
-import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
-
 import java.lang.reflect.Modifier;
-import java.util.List;
 
 import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.annotations.SetupRender;
@@ -29,9 +26,6 @@
 import org.apache.tapestry.test.TapestryTestCase;
 import org.testng.annotations.Test;
 
-/**
- * 
- */
 public class ComponentLifecycleMethodWorkerTest extends TapestryTestCase
 {
     @Test
@@ -40,9 +34,29 @@
         ClassTransformation tf = newClassTransformation();
         MutableComponentModel model = newMutableComponentModel();
 
-        List<MethodSignature> sigs = newList();
+        MethodSignature sig = new MethodSignature("someRandomMethod");
+
+        train_findMethods(tf, sig);
+
+        train_getMethodAnnotation(tf, sig, SetupRender.class, null);
+
+        replay();
+
+        ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
false);
+
+        worker.transform(tf, model);
+
+        verify();
+    }
+
+    @Test
+    public void added_lifecycle_method_is_ignored()
+    {
+        ClassTransformation tf = newClassTransformation();
+        MutableComponentModel model = newMutableComponentModel();
 
-        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
+        train_findMethods(tf, TransformConstants.SETUP_RENDER_SIGNATURE);
 
         replay();
 
@@ -59,12 +73,13 @@
     {
         ClassTransformation tf = newClassTransformation();
         MutableComponentModel model = newMutableComponentModel();
+        SetupRender annotation = newSetupRender();
 
-        List<MethodSignature> sigs = newList();
+        MethodSignature sig = new MethodSignature("aMethod");
 
-        sigs.add(new MethodSignature("aMethod"));
+        train_findMethods(tf, sig);
 
-        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
+        train_getMethodAnnotation(tf, sig, SetupRender.class, annotation);
 
         train_isRootClass(model, false);
 
@@ -84,17 +99,51 @@
     }
 
     @Test
+    public void match_on_method_name()
+    {
+        ClassTransformation tf = newClassTransformation();
+        MutableComponentModel model = newMutableComponentModel();
+
+        MethodSignature sig = new MethodSignature("setupRender");
+
+        train_findMethods(tf, sig);
+
+        train_isRootClass(model, false);
+
+        train_addMethod(
+                tf,
+                TransformConstants.SETUP_RENDER_SIGNATURE,
+                "{ super.setupRender($$); if ($2.isAborted()) return;  
setupRender(); }");
+
+        replay();
+
+        ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
false);
+
+        worker.transform(tf, model);
+
+        verify();
+    }
+
+    protected final SetupRender newSetupRender()
+    {
+        return newMock(SetupRender.class);
+    }
+
+    @Test
     public void multiple_methods_reverse_order()
     {
         ClassTransformation tf = newClassTransformation();
         MutableComponentModel model = newMutableComponentModel();
+        SetupRender annotation = newSetupRender();
 
-        List<MethodSignature> sigs = newList();
+        MethodSignature siga = new MethodSignature("aMethod");
+        MethodSignature sigb = new MethodSignature("bMethod");
 
-        sigs.add(new MethodSignature("aMethod"));
-        sigs.add(new MethodSignature("bMethod"));
+        train_findMethods(tf, siga, sigb);
 
-        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
+        train_getMethodAnnotation(tf, siga, SetupRender.class, annotation);
+        train_getMethodAnnotation(tf, sigb, SetupRender.class, annotation);
 
         train_isRootClass(model, false);
 
@@ -118,13 +167,16 @@
     {
         ClassTransformation tf = newClassTransformation();
         MutableComponentModel model = newMutableComponentModel();
+        SetupRender annotation = newSetupRender();
+
+        MethodSignature siga = new MethodSignature("aMethod");
+        MethodSignature sigb = new MethodSignature("bMethod");
 
-        List<MethodSignature> sigs = newList();
+        train_findMethods(tf, siga, sigb);
 
-        sigs.add(new MethodSignature("aMethod"));
-        sigs.add(new MethodSignature("bMethod"));
+        train_getMethodAnnotation(tf, siga, SetupRender.class, annotation);
+        train_getMethodAnnotation(tf, sigb, SetupRender.class, annotation);
 
-        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
         train_isRootClass(model, true);
 
         train_addMethod(tf, TransformConstants.SETUP_RENDER_SIGNATURE, "{ 
bMethod(); aMethod(); }");
@@ -145,14 +197,15 @@
     {
         ClassTransformation tf = newClassTransformation();
         MutableComponentModel model = newMutableComponentModel();
+        SetupRender annotation = newSetupRender();
 
-        train_isRootClass(model, true);
+        MethodSignature sig = new MethodSignature("aMethod");
 
-        List<MethodSignature> sigs = newList();
+        train_findMethods(tf, sig);
 
-        sigs.add(new MethodSignature("aMethod"));
+        train_getMethodAnnotation(tf, sig, SetupRender.class, annotation);
 
-        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
+        train_isRootClass(model, true);
 
         train_addMethod(tf, TransformConstants.SETUP_RENDER_SIGNATURE, "{ 
aMethod(); }");
 
@@ -167,23 +220,19 @@
 
     }
 
-    protected final void train_isRootClass(MutableComponentModel model, 
boolean isRootClass)
-    {
-        expect(model.isRootClass()).andReturn(isRootClass);
-    }
-
     @Test
     public void method_with_markup_writer_parameter()
     {
         ClassTransformation tf = newClassTransformation();
         MutableComponentModel model = newMutableComponentModel();
+        SetupRender annotation = newSetupRender();
 
-        List<MethodSignature> sigs = newList();
+        MethodSignature sig = new MethodSignature(Modifier.PUBLIC, "void", 
"aMethod", new String[]
+        { MarkupWriter.class.getName() }, null);
 
-        sigs.add(new MethodSignature(Modifier.PUBLIC, "void", "aMethod", new 
String[]
-        { MarkupWriter.class.getName() }, null));
+        train_findMethods(tf, sig);
 
-        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
+        train_getMethodAnnotation(tf, sig, SetupRender.class, annotation);
 
         train_isRootClass(model, false);
 
@@ -208,12 +257,14 @@
     {
         ClassTransformation tf = newClassTransformation();
         MutableComponentModel model = newMutableComponentModel();
+        SetupRender annotation = newSetupRender();
 
-        List<MethodSignature> sigs = newList();
+        MethodSignature sig = new MethodSignature(Modifier.PROTECTED, 
"boolean", "aMethod", null,
+                null);
 
-        sigs.add(new MethodSignature(Modifier.PROTECTED, "boolean", "aMethod", 
null, null));
+        train_findMethods(tf, sig);
 
-        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
+        train_getMethodAnnotation(tf, sig, SetupRender.class, annotation);
 
         train_getClassName(tf, "biff.Baz");
 
@@ -243,15 +294,20 @@
     {
         ClassTransformation tf = newClassTransformation();
         MutableComponentModel model = newMutableComponentModel();
+        SetupRender annotation = newSetupRender();
+
+        MethodSignature siga = new MethodSignature(Modifier.PROTECTED, 
"boolean", "aMethod", null,
+                null);
+        MethodSignature sigb = new MethodSignature(Modifier.PUBLIC, "void", 
"bMethod", new String[]
+        { MarkupWriter.class.getName() }, null);
 
-        List<MethodSignature> sigs = newList();
+        train_findMethods(tf, siga, sigb);
 
-        sigs.add(new MethodSignature(Modifier.PROTECTED, "boolean", "aMethod", 
null, null));
-        sigs.add(new MethodSignature(Modifier.PUBLIC, "void", "bMethod", new 
String[]
-        { MarkupWriter.class.getName() }, null));
+        train_getMethodAnnotation(tf, siga, SetupRender.class, annotation);
+        train_getMethodAnnotation(tf, sigb, SetupRender.class, annotation);
 
-        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
         train_isRootClass(model, false);
+
         train_getClassName(tf, "foo.Bar");
 
         train_addMethod(

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java?view=diff&rev=489232&r1=489231&r2=489232
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
 Wed Dec 20 16:27:14 2006
@@ -54,6 +54,7 @@
 import org.apache.tapestry.runtime.Component;
 import org.apache.tapestry.runtime.ComponentResourcesAware;
 import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.MethodFilter;
 import org.apache.tapestry.services.MethodSignature;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
@@ -818,6 +819,44 @@
         ClassTransformation ct = 
createClassTransformation(AnnotatedPage.class, log);
 
         List<MethodSignature> l = 
ct.findMethodsWithAnnotation(SetupRender.class);
+
+        // Check order
+
+        assertEquals(l.size(), 2);
+        assertEquals(l.get(0).toString(), "void beforeRender()");
+        assertEquals(l.get(1).toString(), "boolean 
earlyRender(org.apache.tapestry.MarkupWriter)");
+
+        // Check up on cacheing
+
+        assertEquals(ct.findMethodsWithAnnotation(SetupRender.class), l);
+
+        // Check up on no match.
+
+        assertTrue(ct.findFieldsWithAnnotation(Deprecated.class).isEmpty());
+
+        verify();
+    }
+
+    @Test
+    public void find_methods_using_filter() throws Exception
+    {
+        Log log = newLog();
+
+        replay();
+
+        final ClassTransformation ct = 
createClassTransformation(AnnotatedPage.class, log);
+
+        // Duplicates, somewhat less efficiently, the logic in 
find_methods_with_annotation().
+
+        MethodFilter filter = new MethodFilter()
+        {
+            public boolean accept(MethodSignature signature)
+            {
+                return ct.getMethodAnnotation(signature, SetupRender.class) != 
null;
+            }
+        };
+
+        List<MethodSignature> l = ct.findMethods(filter);
 
         // Check order
 


Reply via email to