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> + * <div wicket:id="outerTransparent"> + * <div wicket:id="innerTransparent"> + * <span wicket:id="childComponent"></span> + * </div> + * </div> + * </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>"); + } + } }
