WICKET-6027 Nested TransparentWebMarkupContainer, markup of inner
component not found 

Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/1d654bf6
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/1d654bf6
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/1d654bf6

Branch: refs/heads/lambdas
Commit: 1d654bf6e6be146cd0658d3f4b79f7a044646ea0
Parents: 4385fcc
Author: Andrea Del Bene <[email protected]>
Authored: Sat Nov 14 20:27:53 2015 +0100
Committer: Andrea Del Bene <[email protected]>
Committed: Sat Nov 14 20:27:53 2015 +0100

----------------------------------------------------------------------
 .../panel/AbstractMarkupSourcingStrategy.java   | 109 +++++++++++++++----
 .../html/TransparentWebMarkupContainerTest.java |  43 ++++++++
 2 files changed, 132 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/1d654bf6/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/AbstractMarkupSourcingStrategy.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/AbstractMarkupSourcingStrategy.java
 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/AbstractMarkupSourcingStrategy.java
index e576d2b..ce5c1a1 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/AbstractMarkupSourcingStrategy.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/AbstractMarkupSourcingStrategy.java
@@ -16,7 +16,9 @@
  */
 package org.apache.wicket.markup.html.panel;
 
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 
 import org.apache.wicket.Component;
 import org.apache.wicket.MarkupContainer;
@@ -28,6 +30,8 @@ import 
org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
 import org.apache.wicket.markup.parser.XmlTag.TagType;
 import org.apache.wicket.markup.resolver.IComponentResolver;
 import org.apache.wicket.util.lang.Classes;
+import org.apache.wicket.util.visit.IVisit;
+import org.apache.wicket.util.visit.IVisitor;
 
 /**
  * Implements boilerplate as needed by many markup sourcing strategies.
@@ -67,38 +71,34 @@ public abstract class AbstractMarkupSourcingStrategy 
implements IMarkupSourcingS
        {
                IMarkupFragment childMarkupFound = null;
                Iterator<Component> childrenIterator = container.iterator();
-
+               final List<MarkupContainer> componentResolvers = new 
ArrayList<>();
+               
+               //collect all "transparent" (i.e. component resolvers) children
+               container.visitChildren(IComponentResolver.class, new 
IVisitor<MarkupContainer, Void>()
+               {
+                       @Override
+                       public void component(MarkupContainer child, 
IVisit<Void> visit)
+                       {
+                               componentResolvers.add(child);
+                       }
+               });
+                               
                while (childrenIterator.hasNext() && childMarkupFound == null)
                {
                        Component sibling = childrenIterator.next();
 
-                       if (sibling == child || !sibling.isVisible())
+                       if (sibling == child || !sibling.isVisible() || 
!(sibling instanceof MarkupContainer))
                        {
                                continue;
                        }
                        
                        IMarkupFragment siblingMarkup = 
containerMarkup.find(sibling.getId());
                        
-                       if (siblingMarkup != null && sibling instanceof 
MarkupContainer)
+                       if (siblingMarkup != null)
                        {
-                               IMarkupFragment childMarkup  = 
siblingMarkup.find(child.getId());
-                               
-                               if (childMarkup != null && sibling instanceof 
IComponentResolver)
+                               if (sibling instanceof IComponentResolver)
                                {
-                                       IComponentResolver componentResolver = 
(IComponentResolver)sibling;
-                                       MarkupStream stream = new 
MarkupStream(childMarkup);
-                                       ComponentTag tag = stream.getTag();
-                                       
-                                       Component resolvedComponent = 
sibling.get(tag.getId());
-                                       if (resolvedComponent == null)
-                                       {
-                                               resolvedComponent = 
componentResolver.resolve((MarkupContainer)sibling, stream, tag);
-                                       }
-                                       
-                                       if (child == resolvedComponent)
-                                       {
-                                               childMarkupFound = childMarkup;
-                                       }
+                                       childMarkupFound = 
searchInNestedTransparentResolvers(containerMarkup, child, componentResolvers);
                                }
                                else 
                                {
@@ -106,6 +106,75 @@ public abstract class AbstractMarkupSourcingStrategy 
implements IMarkupSourcingS
                                }
                        }
                }
+               
+               return childMarkupFound;
+       }
+       
+       /**
+        * 
+        * Search for the markup of a child that might be nested inside
+        * transparent siblings. For example:
+        * 
+        * <pre>
+        * &lt;div wicket:id=&quot;outerTransparent&quot;&gt;
+        *      &lt;div wicket:id=&quot;innerTransparent&quot;&gt;
+        *       &lt;span wicket:id=&quot;childComponent&quot;&gt;&lt;/span&gt;
+        *      &lt;/div&gt;
+        * &lt;/div&gt;
+        * </pre>
+        * 
+        * @param
+        *                containerMarkup
+        *                        the markup of the parent container.
+        * @param child
+        *            The component to find the markup for.
+        * @param componentResolvers
+        *                        the transparent siblings           
+        *
+        * @return the markup fragment for the child, or {@code null}.
+        */
+       protected IMarkupFragment 
searchInNestedTransparentResolvers(IMarkupFragment containerMarkup, Component 
child, 
+               List<MarkupContainer> componentResolvers)
+       {
+               IMarkupFragment childMarkupFound = null;
+               
+               for (MarkupContainer componentResolver : componentResolvers)
+               {
+                       IMarkupFragment resolverMarkup = 
containerMarkup.find(componentResolver.getId());
+                       IMarkupFragment childMarkup = resolverMarkup != null ? 
resolverMarkup.find(child.getId()) : null;
+                       
+                       if (childMarkup != null)
+                       {
+                       IComponentResolver resolverContainer = 
(IComponentResolver)componentResolver;
+                               MarkupStream stream = new 
MarkupStream(childMarkup);
+                               ComponentTag tag = stream.getTag();
+                               
+                               Component resolvedComponent = 
componentResolver.get(tag.getId());
+                               if (resolvedComponent == null)
+                               {
+                                       resolvedComponent = 
resolverContainer.resolve(componentResolver, stream, tag);
+                               }
+                               
+                               if (child == resolvedComponent)
+                               {
+                                       childMarkupFound = childMarkup;
+                               }
+                       }
+                       else if (resolverMarkup != null)
+                       {
+                               List<MarkupContainer> otherResolvers = new 
ArrayList<>(componentResolvers);
+                               
+                               otherResolvers.remove(componentResolver);
+                               
+                               childMarkupFound = 
searchInNestedTransparentResolvers(resolverMarkup, child, otherResolvers);
+                       }
+
+                   if (childMarkupFound != null)
+                       {
+                               break;
+                       }
+               }
+               
                return childMarkupFound;
        }
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/1d654bf6/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java
 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java
index 41bff97..f9adf4e 100644
--- 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java
+++ 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java
@@ -19,6 +19,7 @@ package org.apache.wicket.markup.html;
 import org.apache.wicket.Component;
 import org.apache.wicket.IPageManagerProvider;
 import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.Page;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
 import org.apache.wicket.core.util.lang.WicketObjects;
@@ -249,6 +250,19 @@ public class TransparentWebMarkupContainerTest extends 
WicketTestCase
                assertNotNull(scriptTag);
        }
        
+       @Test
+       public void nestedTransparentContainer() throws Exception
+       {
+               tester.startPage(TestEmbeddedTransparentMarkupContainer.class);
+               
tester.assertRenderedPage(TestEmbeddedTransparentMarkupContainer.class);
+               
+               final Page page = tester.getLastRenderedPage();
+               final Component label = page.get("label");
+               
+               
assertEquals(TestEmbeddedTransparentMarkupContainer.LABEL_MARKUP,
+                       label.getMarkup().toString(true));
+       }
+       
        /** */
        public static class TestPage extends WebPage implements 
IMarkupResourceStreamProvider
        {
@@ -379,4 +393,33 @@ public class TransparentWebMarkupContainerTest extends 
WicketTestCase
                                "</body></html>");
                }
        }
+       
+       public static class TestEmbeddedTransparentMarkupContainer extends 
WebPage implements IMarkupResourceStreamProvider
+       {
+               private static final long serialVersionUID = 1L;
+               
+               public static final String LABEL_MARKUP = "<span 
wicket:id=\"label\"></span>";
+               
+               /** */
+               public TestEmbeddedTransparentMarkupContainer()
+               {
+                       add(new TransparentWebMarkupContainer("outer"));
+                       add(new TransparentWebMarkupContainer("inner"));
+                       add(new Label("label"));
+               }
+
+               @Override
+               public IResourceStream getMarkupResourceStream(MarkupContainer 
container,
+                       Class<?> containerClass)
+               {
+                       return new StringResourceStream("" + //
+                               "<html><body>" + //
+                               "       <div wicket:id=\"outer\">" + //
+                               "               <div wicket:id=\"inner\">" + //
+                               "                       " + LABEL_MARKUP + //
+                               "               </div>" + //
+                               "       </div>" + //
+                               "</body></html>");
+               }
+       }
 }

Reply via email to