Author: hlship
Date: Wed Oct 25 07:30:59 2006
New Revision: 467668

URL: http://svn.apache.org/viewvc?view=rev&rev=467668
Log:
Change the AfterRender and CleanupRender phases to invoke phase listener 
methods in reverse order.

Added:
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/AbstractTracer.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Tracer.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/mixins/TracerMixin.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.html
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/structure/ComponentPageElementImpl.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt
    tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.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/util/InternalUtilsTest.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=467668&r1=467667&r2=467668
==============================================================================
--- 
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 Oct 25 07:30:59 2006
@@ -15,9 +15,11 @@
 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.InternalUtils;
 import org.apache.tapestry.model.MutableComponentModel;
 import org.apache.tapestry.services.ClassTransformation;
 import org.apache.tapestry.services.ComponentClassTransformWorker;
@@ -37,17 +39,32 @@
 
     private final MethodSignature _lifecycleMethodSignature;
 
-    private final MethodInvocationBuilder _invocationBuilder = new 
MethodInvocationBuilder();
+    private final String _lifecycleMethodName;
 
-    {
-        _invocationBuilder.addParameter(MarkupWriter.class.getName(), "$1");
-    }
+    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)
+            Class<? extends Annotation> methodAnnotation, boolean reverse)
     {
         _lifecycleMethodSignature = lifecycleMethodSignature;
         _methodAnnotation = methodAnnotation;
+        _reverse = reverse;
+        _lifecycleMethodName = lifecycleMethodSignature.getMethodName();
+
+        _invocationBuilder.addParameter(MarkupWriter.class.getName(), "$1");
     }
 
     @Override
@@ -69,16 +86,24 @@
         BodyBuilder builder = new BodyBuilder();
         builder.begin();
 
-        // If in a subclass, invoke the super class version first.
+        // If in a subclass, and in normal order mode, invoke the super class 
version first.
 
-        if (!model.isRootClass())
+        if (!(_reverse || model.isRootClass()))
         {
-            builder.addln("super.%s($$);", 
_lifecycleMethodSignature.getMethodName());
+            builder.addln("super.%s($$);", _lifecycleMethodName);
             builder.addln(CHECK_ABORT_FLAG);
         }
 
-        for (MethodSignature sig : methods)
-            addMethodCallToBody(builder, sig, transformation);
+        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();
 

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?view=diff&rev=467668&r1=467667&r2=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
 Wed Oct 25 07:30:59 2006
@@ -17,6 +17,7 @@
 import static org.apache.tapestry.util.CollectionFactory.newList;
 import static org.apache.tapestry.util.CollectionFactory.newMap;
 
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -352,8 +353,10 @@
         {
             LifecycleEvent<Boolean> event = newEvent(false);
 
-            for (ComponentLifecycle component : _components)
-                component.afterRender(writer, event);
+            Iterator<ComponentLifecycle> i = 
InternalUtils.reverseIterator(_components);
+
+            while (i.hasNext())
+                i.next().afterRender(writer, event);
 
             if (event.getResult())
                 queue.push(_beginRender);
@@ -374,8 +377,10 @@
         {
             LifecycleEvent<Boolean> event = newEvent(false);
 
-            for (ComponentLifecycle component : _components)
-                component.cleanupRender(writer, event);
+            Iterator<ComponentLifecycle> i = 
InternalUtils.reverseIterator(_components);
+
+            while (i.hasNext())
+                i.next().cleanupRender(writer, event);
 
             if (event.getResult())
             {
@@ -385,6 +390,8 @@
             else
             {
                 _rendering = false;
+
+                // Order here should not matter.
 
                 for (ComponentLifecycle component : _components)
                     component.postRenderCleanup();

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java?view=diff&rev=467668&r1=467667&r2=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java
 Wed Oct 25 07:30:59 2006
@@ -22,7 +22,9 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.Iterator;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 
 import org.apache.tapestry.Locatable;
@@ -352,5 +354,30 @@
     public static final boolean isStatic(Method method)
     {
         return Modifier.isStatic(method.getModifiers());
+    }
+
+    public static final <T> Iterator<T> reverseIterator(final List<T> list)
+    {
+        final ListIterator<T> normal = list.listIterator(list.size());
+
+        return new Iterator<T>()
+        {
+            public boolean hasNext()
+            {
+                return normal.hasPrevious();
+            }
+
+            public T next()
+            {
+                // TODO Auto-generated method stub
+                return normal.previous();
+            }
+
+            public void remove()
+            {
+                throw new UnsupportedOperationException();
+            }
+
+        };
     }
 }

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=467668&r1=467667&r2=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
 Wed Oct 25 07:30:59 2006
@@ -509,11 +509,14 @@
         // Workers for the component rendering state machine methods; this is 
in typical
         // execution order.
 
-        add(configuration, TransformConstants.SETUP_RENDER_SIGNATURE, 
SetupRender.class);
-        add(configuration, TransformConstants.BEGIN_RENDER_SIGNATURE, 
BeginRender.class);
-        add(configuration, TransformConstants.BEFORE_RENDER_BODY_SIGNATURE, 
BeforeRenderBody.class);
-        add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, 
AfterRender.class);
-        add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, 
CleanupRender.class);
+        add(configuration, TransformConstants.SETUP_RENDER_SIGNATURE, 
SetupRender.class, false);
+        add(configuration, TransformConstants.BEGIN_RENDER_SIGNATURE, 
BeginRender.class, false);
+        add(configuration, TransformConstants.BEFORE_RENDER_BODY_SIGNATURE, 
BeforeRenderBody.class, false);
+        
+        // These phases operate in reverse order.
+        
+        add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, 
AfterRender.class, true);
+        add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, 
CleanupRender.class, true);
 
         configuration.add("Retain", new RetainWorker());
         configuration.add("Persist", new PersistWorker());
@@ -521,13 +524,13 @@
     }
 
     private static void 
add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
-            MethodSignature signature, Class<? extends Annotation> 
annotationClass)
+            MethodSignature signature, Class<? extends Annotation> 
annotationClass, boolean reverse)
     {
         // make the name match the annotation class name.
 
         String name = IOCUtilities.toSimpleId(annotationClass.getName());
 
-        configuration.add(name, new ComponentLifecycleMethodWorker(signature, 
annotationClass));
+        configuration.add(name, new ComponentLifecycleMethodWorker(signature, 
annotationClass, reverse));
     }
 
     @Lifecycle("perthread")

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt?view=diff&rev=467668&r1=467667&r2=467668
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt Wed 
Oct 25 07:30:59 2006
@@ -95,11 +95,8 @@
   
 Render Phase Ordering
 
-  This is under consideration. To some degree, if a mixin and the core 
component both implement
-  methods for the same render phase, then the order of operations for 
BeginRender and AfterRender
-  should be reversed.
-  
-  Currently, the order is mixins, then render phase methods from the 
components' super classes, the render phase
-  methods in the component's class.
+  All mixins for a component execute their render phase methods <before> the 
component's render phase
+  methods for most phases.  However, in the later phases (AfterRender, 
CleanupRender) the order of executing
+  is reversed.
   
   

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=467668&r1=467667&r2=467668
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt Wed 
Oct 25 07:30:59 2006
@@ -42,9 +42,10 @@
   
   Render phase methods may take no parameters, or may take
   a parameter of type {{{dom.html}MarkupWriter}}.  The methods can have any 
visibility
-  you like ... typically, package private is used, as it
-  makes it possible to test your code without making the methods part of the 
component's
-  public API.
+  you like ... typically, package private is used, as this visibility
+  makes it possible to test your code (from within the same Java package)
+  without making the methods part of the component's
+  <public> API.
   
   These methods are <<optional>>, a default behavior is associated with each 
phase.
  
@@ -161,7 +162,7 @@
   is reached, or automatically if the component has no template (but the 
component does
   have a body).
   
-  <TODO: At some point in the future, we may add a PostRenderBody phase, which 
would allow
+  <TODO: At some point in the future, we may add an AfterRenderBody phase, 
which would allow
   the component to wrap the body in additional markup, as desired.>
   
 * {{{../apidocs/org/apache/tapestry/annotations/AfterRender.html}AfterRender}}
@@ -171,9 +172,7 @@
   AfterRender phase can continue on to CleanupRender, or revert back to 
BeginRender (as
   in our Count component example, above).
   
-  <TODO: Perhaps this should be called "FinishRender"?>
-  
-  If no methods are annotated with FinishRender, then no special output 
occurs, and the
+  If no methods are annotated with AfterRender, then no special output occurs, 
and the
   CleanupRender phase is triggered.
    
 * 
{{{../apidocs/org/apache/tapestry/annotations/CleanupRender.html}CleanupRender}}
@@ -185,13 +184,39 @@
   It is possible to have multiple methods that are annotated with the
   same render phase annotation.  This may include methods in the same class, or
   a mix of method defined in a class and inherited from other classes.
+ 
+* Mixins Before Component
+
+  When a component has {{{mixins.html}mixins}}, then the mixins' render phase 
methods execute <before>
+  the component's render phase methods.  If a mixin extends from a base class, 
the mixin's
+  parent class methods execute before the mixin subclass' render phase methods.
+  
+  The order in which the mixins execute is not defined at this time.
   
 * Parents before Child
 
   Ordering is always parent-first.  Methods defined in the parent class are 
always invoked
   before methods defined in the child class.
   
-* Within a Class
+* Reverse Ordering for AfterRender and CleanupRender
+
+  The AfterRender phase exists to balance the BeginRender phase.  Often 
elements will
+  be started inside the BeginRender phase and then the elements will be ended 
(closed)
+  inside the AfterRender support (with the body and template of the component 
rendering
+  between).
+  
+  In order to ensure that operations occur in the correct, and natural order, 
the
+  render phase methods for these two stages are invoked in <reverse order>:
+  
+  * Subclass methods 
+  
+  * Parent class methods
+  
+  * Mixin subclass methods
+  
+  * Mixin parent class methods
+  
+* Within a Single Class
 
   Currently, methods are sorted alphabetically. Methods with the same name are
   sorted by number of parameters.  Even so, this is not a great idea ... just 
define

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html?view=diff&rev=467668&r1=467667&r2=467668
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html Wed Oct 25 
07:30:59 2006
@@ -35,9 +35,12 @@
                 <li>
                     <a href="ActionPage.html">Action Page</a> -- tests fixture 
for ActionLink
                     component </li>
-            <li>
-                <a href="InstanceMixin.html">InstanceMixin</a> -- Mixin added 
to particular component instance
-            </li>
+                <li>
+                    <a href="InstanceMixin.html">InstanceMixin</a> -- Mixin 
added to particular
+                    component instance </li>
+                <li>
+                    <a href="RenderPhaseOrder.html">RenderPhaseOrder</a> -- 
Order of operations when
+                    invoking render phase methods </li>
             </ul>
         </p>
         <p> Feast your eyes: </p>

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=467668&r1=467667&r2=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 Wed Oct 25 07:30:59 2006
@@ -257,4 +257,17 @@
             assertTrue(body.contains(snippet), snippet);
         }
     }
+
+    @Test
+    public void app1_render_phase_order()
+    {
+        _selenium.open(BASE_URL);
+
+        clickAndWait("link=RenderPhaseOrder");
+
+        String body = _selenium.getBodyText().replaceAll("\\s+", " ");
+
+        assertTrue(body
+                .contains("[BEGIN-TRACER-MIXIN BEGIN-ABSTRACT-TRACER 
BEGIN-TRACER BODY AFTER-TRACER AFTER-ABSTRACT-TRACER AFTER-TRACER-MIXIN]"));
+    }
 }

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/AbstractTracer.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/AbstractTracer.java?view=auto&rev=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/AbstractTracer.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/AbstractTracer.java
 Wed Oct 25 07:30:59 2006
@@ -0,0 +1,23 @@
+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 abstract class AbstractTracer
+{
+    @BeginRender
+    void begin(MarkupWriter writer)
+    {
+        writer.write("BEGIN-ABSTRACT-TRACER ");
+    }
+
+    @AfterRender
+    void after(MarkupWriter writer)
+    {
+        writer.write("AFTER-ABSTRACT-TRACER ");
+    }
+
+}

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Tracer.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Tracer.java?view=auto&rev=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Tracer.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Tracer.java
 Wed Oct 25 07:30:59 2006
@@ -0,0 +1,21 @@
+package org.apache.tapestry.integration.app1.components;
+
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.AfterRender;
+import org.apache.tapestry.annotations.BeginRender;
+
+public class Tracer extends AbstractTracer
+{
+    @BeginRender
+    void beginChild(MarkupWriter writer)
+    {
+        writer.write("BEGIN-TRACER ");
+    }
+
+    @AfterRender
+    void afterChild(MarkupWriter writer)
+    {
+        writer.write("AFTER-TRACER ");
+    }
+
+}

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/mixins/TracerMixin.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/mixins/TracerMixin.java?view=auto&rev=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/mixins/TracerMixin.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/mixins/TracerMixin.java
 Wed Oct 25 07:30:59 2006
@@ -0,0 +1,23 @@
+package org.apache.tapestry.integration.app1.mixins;
+
+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 TracerMixin
+{
+    @BeginRender
+    void begin(MarkupWriter writer)
+    {
+        writer.write("BEGIN-TRACER-MIXIN ");
+    }
+
+    @AfterRender
+    void after(MarkupWriter writer)
+    {
+        writer.write("AFTER-TRACER-MIXIN");
+    }
+
+}

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.java?view=auto&rev=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.java
 Wed Oct 25 07:30:59 2006
@@ -0,0 +1,9 @@
+package org.apache.tapestry.integration.app1.pages;
+
+import org.apache.tapestry.annotations.ComponentClass;
+
[EMAIL PROTECTED]
+public class RenderPhaseOrder
+{
+
+}

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=467668&r1=467667&r2=467668
==============================================================================
--- 
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 Oct 25 07:30:59 2006
@@ -47,7 +47,7 @@
         replay();
 
         ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
-                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
false);
 
         worker.transform(tf, model);
 
@@ -74,12 +74,71 @@
         replay();
 
         ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
-                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
false);
 
         worker.transform(tf, model);
 
         verify();
     }
+    
+    @Test
+    public void multiple_methods_reverse_order()
+    {
+        ClassTransformation tf = newClassTransformation();
+        MutableComponentModel model = newMutableComponentModel();
+
+        List<MethodSignature> sigs = newList();
+
+        sigs.add(new MethodSignature("aMethod"));
+        sigs.add(new MethodSignature("bMethod"));
+
+        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
+
+        train_addMethod(
+                tf,
+                TransformConstants.SETUP_RENDER_SIGNATURE,
+                "{ bMethod(); aMethod(); super.setupRender($$); }");
+
+        replay();
+
+        ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
true);
+
+        worker.transform(tf, model);
+
+        verify();        
+    }
+    
+    @Test
+    public void multiple_methods_parent_class_reverse_order()
+    {
+        ClassTransformation tf = newClassTransformation();
+        MutableComponentModel model = newMutableComponentModel();
+
+        List<MethodSignature> sigs = newList();
+
+        sigs.add(new MethodSignature("aMethod"));
+        sigs.add(new MethodSignature("bMethod"));
+
+        train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
+        train_isRootClass(model, true);
+        
+        train_addMethod(
+                tf,
+                TransformConstants.SETUP_RENDER_SIGNATURE,
+                "{ bMethod(); aMethod(); }");
+
+        replay();
+
+        ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
true);
+
+        worker.transform(tf, model);
+
+        verify();
+        
+    }
+
 
     @Test
     public void method_in_base_class()
@@ -103,7 +162,7 @@
         replay();
 
         ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
-                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
false);
 
         worker.transform(tf, model);
 
@@ -138,7 +197,7 @@
         replay();
 
         ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
-                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
false);
 
         worker.transform(tf, model);
 
@@ -172,7 +231,7 @@
         replay();
 
         ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
-                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
false);
 
         worker.transform(tf, model);
 
@@ -205,7 +264,7 @@
         replay();
 
         ComponentClassTransformWorker worker = new 
ComponentLifecycleMethodWorker(
-                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
+                TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, 
false);
 
         worker.transform(tf, model);
 

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java?view=diff&rev=467668&r1=467667&r2=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java
 Wed Oct 25 07:30:59 2006
@@ -22,6 +22,7 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Enumeration;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -243,5 +244,42 @@
         map.put("fred", "flintstone");
 
         assertEquals("flintstone", InternalUtils.get(map, "fred"));
+    }
+
+    @Test
+    public void reverse_iterator()
+    {
+        List<String> list = Arrays.asList("a", "b", "c");
+
+        Iterator<String> i = InternalUtils.reverseIterator(list);
+
+        assertTrue(i.hasNext());
+        assertEquals(i.next(), "c");
+
+        assertTrue(i.hasNext());
+        assertEquals(i.next(), "b");
+
+        assertTrue(i.hasNext());
+        assertEquals(i.next(), "a");
+
+        assertFalse(i.hasNext());
+    }
+
+    @Test
+    public void reverse_iterator_does_not_support_remove()
+    {
+        List<String> list = Arrays.asList("a", "b", "c");
+
+        Iterator<String> i = InternalUtils.reverseIterator(list);
+
+        try
+        {
+            i.remove();
+            unreachable();
+        }
+        catch (UnsupportedOperationException ex)
+        {
+
+        }
     }
 }

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.html
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.html?view=auto&rev=467668
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.html
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.html
 Wed Oct 25 07:30:59 2006
@@ -0,0 +1,13 @@
+<t:comp type="Border" 
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
+
+    <p>
+        This page demonstrates the order of render phase operations. Certains 
later phases
+        will execute in the exact opposite order from the earlier phases, to 
ensure
+        that output operations balance.
+    </p>
+    
+    <p>
+        [<t:comp type="Tracer" mixins="TracerMixin"> BODY </t:comp>]
+    </p>
+
+</t:comp>


Reply via email to