Revision: 1372
          http://stripes.svn.sourceforge.net/stripes/?rev=1372&view=rev
Author:   bengunter
Date:     2010-12-28 23:25:13 +0000 (Tue, 28 Dec 2010)

Log Message:
-----------
Fix for STS-788: Layout issues after upgrade from 1.5.3. This fixes the second 
case where a component definition appears within a render within another 
component definition. The component path is now tracked for each layout context 
so that all the components that must execute for a nested component to execute 
will execute during the component render phase.

Modified Paths:
--------------
    
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
    
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
    
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTag.java

Modified: 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
===================================================================
--- 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
       2010-12-28 19:06:45 UTC (rev 1371)
+++ 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
       2010-12-28 23:25:13 UTC (rev 1372)
@@ -14,6 +14,8 @@
  */
 package net.sourceforge.stripes.tag.layout;
 
+import java.util.Iterator;
+import java.util.List;
 import java.util.regex.Pattern;
 
 import javax.servlet.jsp.JspException;
@@ -68,6 +70,42 @@
     }
 
     /**
+     * True if this tag is a component that must execute so that the current 
component tag can
+     * execute. That is, this tag is a parent of the current component.
+     * 
+     * @throws StripesJspException if thrown by {...@link #getContext()}.
+     */
+    protected boolean isPathComponent() throws StripesJspException {
+        List<String> path = getContext().getComponentPath();
+        return path == null ? false : isPathComponent(this, path.iterator());
+    }
+
+    /**
+     * Recursive method called from {...@link #isPathComponent()} that returns 
true if the specified
+     * tag's name is present in the component path iterator at the same 
position where this tag
+     * occurs in the render/component tag tree. For example, if the path 
iterator contains the
+     * component names {...@code ["foo", "bar"]} then this method will return 
true if the tag's name is
+     * {...@code "bar"} and it is a child of a render tag that is a child of a 
component tag whose name
+     * is {...@code "foo"}.
+     * 
+     * @param tag The tag to check
+     * @param path The path to the check the tag against
+     * @return
+     */
+    protected boolean isPathComponent(LayoutComponentTag tag, Iterator<String> 
path) {
+        LayoutTag parent = tag.getLayoutParent();
+        if (parent instanceof LayoutRenderTag) {
+            parent = parent.getLayoutParent();
+            if (parent == null || parent instanceof LayoutComponentTag
+                    && isPathComponent((LayoutComponentTag) parent, path) && 
path.hasNext()) {
+                return tag.getName().equals(path.next());
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * True if this tag is the component to be rendered on this pass from
      * {...@link LayoutDefinitionTag}.
      * 
@@ -109,6 +147,11 @@
                         context.getOut().setSilent(false, pageContext);
                         return EVAL_BODY_INCLUDE;
                     }
+                    else if (isPathComponent()) {
+                        log.debug("Silently execute '", getName(), "' in ", 
context.getRenderPage());
+                        context.getOut().setSilent(true, pageContext);
+                        return EVAL_BODY_INCLUDE;
+                    }
                     else {
                         log.debug("No-op for ", getName(), " in ", 
context.getRenderPage());
                     }

Modified: 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
===================================================================
--- 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
    2010-12-28 19:06:45 UTC (rev 1371)
+++ 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
    2010-12-28 23:25:13 UTC (rev 1372)
@@ -14,7 +14,10 @@
  */
 package net.sourceforge.stripes.tag.layout;
 
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
 import javax.servlet.jsp.PageContext;
@@ -94,6 +97,7 @@
     private Map<String,LayoutComponentRenderer> components = new 
HashMap<String,LayoutComponentRenderer>();
     private Map<String,Object> parameters = new HashMap<String,Object>();
     private String renderPage, component;
+    private List<String> componentPath;
     private boolean componentRenderPhase, rendered;
 
     /**
@@ -105,6 +109,22 @@
     public LayoutContext(LayoutRenderTag renderTag) {
         this.renderTag = renderTag;
         this.renderPage = renderTag.getCurrentPagePath();
+
+        LinkedList<String> path = null;
+        for (LayoutTag parent = renderTag.getLayoutParent(); parent instanceof 
LayoutComponentTag;) {
+            if (path == null)
+                path = new LinkedList<String>();
+
+            path.addFirst(((LayoutComponentTag) parent).getName());
+
+            parent = parent.getLayoutParent();
+            parent = parent instanceof LayoutRenderTag ? 
parent.getLayoutParent() : null;
+        }
+
+        if (path != null) {
+            this.componentPath = Collections.unmodifiableList(path);
+            log.debug("Path is ", this.componentPath);
+        }
     }
 
     /** Get the previous layout context from the stack. */
@@ -165,6 +185,12 @@
     /** Set the name of the component to be rendered during the current phase 
of execution. */
     public void setComponent(String component) { this.component = component; }
 
+    /**
+     * Get the list of components in the render page that must execute so that 
the render tag that
+     * created this context can execute.
+     */
+    public List<String> getComponentPath() { return componentPath; }
+
     /** Get the layout writer to which the layout is rendered. */
     public LayoutWriter getOut() { return out; }
 

Modified: 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTag.java
===================================================================
--- 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTag.java
  2010-12-28 19:06:45 UTC (rev 1371)
+++ 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTag.java
  2010-12-28 23:25:13 UTC (rev 1372)
@@ -20,6 +20,7 @@
 import javax.servlet.jsp.tagext.DynamicAttributes;
 
 import net.sourceforge.stripes.exception.StripesJspException;
+import net.sourceforge.stripes.exception.StripesRuntimeException;
 import net.sourceforge.stripes.util.Log;
 
 /**
@@ -50,7 +51,7 @@
             boolean contextIsNew = false;
 
             if (context == null || !context.isComponentRenderPhase()
-                    || context.isComponentRenderPhase() && 
isChildOfComponent()) {
+                    || context.isComponentRenderPhase() && 
isChildOfCurrentComponent()) {
                 context = LayoutContext.push(this);
                 contextIsNew = true;
             }
@@ -62,6 +63,19 @@
         return context;
     }
 
+    /** Returns true if this tag is a child of the current component tag. */
+    public boolean isChildOfCurrentComponent() {
+        try {
+            LayoutTag parent = getLayoutParent();
+            return parent instanceof LayoutComponentTag
+                    && ((LayoutComponentTag) parent).isCurrentComponent();
+        }
+        catch (StripesJspException e) {
+            // This exception would have been thrown before this tag ever 
executed
+            throw new StripesRuntimeException("Something has happened that 
should never happen", e);
+        }
+    }
+
     /** True if this is the outermost layout tag, the one that initiated the 
render process. */
     public boolean isOuterLayoutTag() {
         return getLayoutParent() == null;


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to