On Tue, Feb 25, 2014 at 8:28 AM, <ivaynb...@apache.org> wrote: > Repository: wicket > Updated Branches: > refs/heads/master cc5d56a50 -> 2008dfb70 > > > WICKET-3335 refactor/cleanup component queueing - a clean way to ignore > outer tags which is necessary for proper fragment and border support > > > Project: http://git-wip-us.apache.org/repos/asf/wicket/repo > Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/2008dfb7 > Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/2008dfb7 > Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/2008dfb7 > > Branch: refs/heads/master > Commit: 2008dfb7044f544d7b112cf4666dfacf42406b89 > Parents: cc5d56a > Author: Igor Vaynberg <igor.vaynb...@gmail.com> > Authored: Mon Feb 24 22:28:03 2014 -0800 > Committer: Igor Vaynberg <igor.vaynb...@gmail.com> > Committed: Mon Feb 24 22:28:03 2014 -0800 > > ---------------------------------------------------------------------- > .../java/org/apache/wicket/DequeueContext.java | 90 ++++++++++++++++++-- > .../org/apache/wicket/DequeueTagAction.java | 11 +++ > .../java/org/apache/wicket/IQueueRegion.java | 8 +- > .../java/org/apache/wicket/MarkupContainer.java | 59 +++++++------ > .../wicket/markup/html/border/Border.java | 59 ++----------- > .../html/panel/DequeueMarkupFragment.java | 6 ++ > .../wicket/markup/html/panel/Fragment.java | 16 ++-- > .../wicket/queueing/ComponentQueueingTest.java | 24 +++++- > 8 files changed, 168 insertions(+), 105 deletions(-) > ---------------------------------------------------------------------- > > > > http://git-wip-us.apache.org/repos/asf/wicket/blob/2008dfb7/wicket-core/src/main/java/org/apache/wicket/DequeueContext.java > ---------------------------------------------------------------------- > diff --git > a/wicket-core/src/main/java/org/apache/wicket/DequeueContext.java > b/wicket-core/src/main/java/org/apache/wicket/DequeueContext.java > index a5bb925..2717e8c 100644 > --- a/wicket-core/src/main/java/org/apache/wicket/DequeueContext.java > +++ b/wicket-core/src/main/java/org/apache/wicket/DequeueContext.java > @@ -34,6 +34,8 @@ public final class DequeueContext > private int index; > private ComponentTag next; > private ArrayListStack<ComponentTag> tags = new ArrayListStack<>(); > + private final boolean skipFirst; > + private ComponentTag first; > > private ArrayListStack<MarkupContainer> containers = new > ArrayListStack<>(); > > @@ -62,9 +64,10 @@ public final class DequeueContext > } > } > > - public DequeueContext(IMarkupFragment markup, MarkupContainer root) > + public DequeueContext(IMarkupFragment markup, MarkupContainer > root, boolean skipFirst) > { > this.markup = markup; > + this.skipFirst = skipFirst; > containers.push(root); > next=nextTag(); > } > @@ -105,6 +108,12 @@ public final class DequeueContext > public ComponentTag takeTag() > { > ComponentTag taken=next; > + > + if (taken == null) > + { > + return null; > + } > + > if (taken.isOpen() && !taken.hasNoCloseTag()) > { > tags.push(taken); > @@ -130,27 +139,89 @@ public final class DequeueContext > > private ComponentTag nextTag() > { > + if (skipFirst && first == null) > + { > + for (; index < markup.size(); index++) > + { > + MarkupElement element = markup.get(index); > + if (element instanceof ComponentTag) > + { > + first = (ComponentTag)element; > + index++; > + break; > + } > + } > + } > + > for (; index < markup.size(); index++) > { > MarkupElement element = markup.get(index); > if (element instanceof ComponentTag) > { > ComponentTag tag = (ComponentTag)element; > - ComponentTag open = tag.isClose() ? > tag.getOpenTag() : tag; > - if (open != null && canDequeueTag(open)) > + > + if (tag.isOpen() || tag.isOpenClose()) > { > - index++; > - return tag; > + DequeueTagAction action = > canDequeueTag(tag); > + switch (action) > + { > + case IGNORE : > + continue; > + case DEQUEUE : > + index++; > + return tag; > + case SKIP : // skip to > close tag > + boolean found = > false; > + for (; index < > markup.size(); index++) > + { > + if > ((markup.get(index) instanceof ComponentTag) > + && > ((ComponentTag)markup.get(index)).closes(tag)) > + { > + > found = true; > + > break; > + } > + } > + if (!found) > + { > + throw new > IllegalStateException( > + > "Could not find close tag for tag: " + tag); > + } > + > + } > + } > + else > + { > + // closed tag > + ComponentTag open = tag.isClose() > ? tag.getOpenTag() : tag; > + > + if (skipFirst && first != null && > open == first) > + { > + continue; > + } > + > + switch (canDequeueTag(open)) > + { > + case DEQUEUE : > + index++; > + return tag; > + case IGNORE : > + continue; > + case SKIP : > + throw new > IllegalStateException( > + "Should > not see closed tag of skipped open tag: " + tag); > + } > } > } > } > return null; > } > > - private boolean canDequeueTag(ComponentTag open) > + private DequeueTagAction canDequeueTag(ComponentTag open) > { > Args.notNull(open, "open"); > > + DequeueTagAction action = null; > + > if (containers.size() < 1) > { > // TODO queueing message: called too early > @@ -158,12 +229,13 @@ public final class DequeueContext > } > for (int i = containers.size() - 1; i >= 0; i--) > { > - if (containers.get(i).canDequeueTag((open))) > + action = containers.get(i).canDequeueTag((open)); > + if (action != null) > { > - return true; > + return action; > } > } > - return false; > + return DequeueTagAction.IGNORE; > } > > /** > > > http://git-wip-us.apache.org/repos/asf/wicket/blob/2008dfb7/wicket-core/src/main/java/org/apache/wicket/DequeueTagAction.java > ---------------------------------------------------------------------- > diff --git > a/wicket-core/src/main/java/org/apache/wicket/DequeueTagAction.java > b/wicket-core/src/main/java/org/apache/wicket/DequeueTagAction.java > new file mode 100644 > index 0000000..5981cb1 > --- /dev/null > +++ b/wicket-core/src/main/java/org/apache/wicket/DequeueTagAction.java > @@ -0,0 +1,11 @@ > +package org.apache.wicket; > + > +public enum DequeueTagAction > +{ > + /** dequeue the tag */ > + DEQUEUE, > + /** skip this tag and all its children */ > + SKIP, > + /** ignore this tag, skip it but do not skip its children */ > + IGNORE; > +} > > > http://git-wip-us.apache.org/repos/asf/wicket/blob/2008dfb7/wicket-core/src/main/java/org/apache/wicket/IQueueRegion.java > ---------------------------------------------------------------------- > diff --git a/wicket-core/src/main/java/org/apache/wicket/IQueueRegion.java > b/wicket-core/src/main/java/org/apache/wicket/IQueueRegion.java > index c0e431a..4bad6f7 100644 > --- a/wicket-core/src/main/java/org/apache/wicket/IQueueRegion.java > +++ b/wicket-core/src/main/java/org/apache/wicket/IQueueRegion.java > @@ -16,7 +16,6 @@ > */ > package org.apache.wicket; > > -import org.apache.wicket.markup.IMarkupFragment; > > /** > * Demarcates components that act as a root can dequeue children. These > are usually components with > @@ -33,13 +32,14 @@ import org.apache.wicket.markup.IMarkupFragment; > public interface IQueueRegion > { > /** > - * Gets the markup that will be used to dequeue components in this > container. Usually containers > - * will return their associated markup by simply delegating to > + * Creates a new {@link DequeueContext} that will be used to > dequeue children of this region. > + * > + * Usually containers will create a context with their associated > markup by getting it via > * {@link MarkupContainer#getAssociatedMarkup()}, but components > that do not render markup in a > * standard way (such as repeaters and borders) may choose to > override this method to implement > * custom behavior for the dequeueing process. > */ > - public IMarkupFragment getDequeueMarkup(); > + public DequeueContext newDequeueContext(); > > /** > * Starts component dequeueing on this {@link IQueueRegion}. This > is the entry point into the > > > http://git-wip-us.apache.org/repos/asf/wicket/blob/2008dfb7/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java > ---------------------------------------------------------------------- > diff --git > a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java > b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java > index 1aba865..616654f 100644 > --- a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java > +++ b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java > @@ -1525,21 +1525,14 @@ public abstract class MarkupContainer extends > Component implements Iterable<Comp > private void dequeueAutoComponents() > { > // dequeue auto components > - IMarkupFragment markup = getDequeueMarkup(); > - if (markup != null) > + DequeueContext context = newDequeueContext(); > + if (context != null && context.peekTag() != null) > { > - // make sure we have markup, when running inside > tests we wont > - for (int i = 0; i < markup.size(); i++) > + for (ComponentTag tag = context.takeTag(); tag != > null; tag = context.takeTag()) > { > - MarkupElement element = markup.get(i); > - if (element instanceof ComponentTag) > + if (tag.getAutoComponentFactory() != null) > { > - ComponentTag tag = > (ComponentTag)element; > - if (tag.getAutoComponentFactory() > != null) > - { > - Component auto = > tag.getAutoComponentFactory().newComponent(tag); > - queue(auto); > - } > + > queue(tag.getAutoComponentFactory().newComponent(tag)); > } > } > } > @@ -2039,16 +2032,13 @@ public abstract class MarkupContainer extends > Component implements Iterable<Comp > setRequestFlag(RFLAG_CONTAINER_DEQUEING, true); > try > { > - IMarkupFragment markup = getDequeueMarkup(); > - if (markup == null) > + DequeueContext dequeue = newDequeueContext(); > + if (dequeue == null) > { > - // markup not found, skip dequeuing > - // this sometimes happens when we are in a > unit test > + // not ready to dequeue yet > return; > } > > - DequeueContext dequeue = new > DequeueContext(markup, this); > - > if (dequeue.peekTag() != null) > { > dequeue(dequeue); > @@ -2083,9 +2073,8 @@ public abstract class MarkupContainer extends > Component implements Iterable<Comp > > // see if child is already added to parent > > - Component child = get(tag.getId()); // TODO > queueing add this into findInQueue and > - > // rename it to dequeue > - > + Component child = get(tag.getId()); > + > if (child == null) > { > // the container does not yet have a child > with this id, see if we can > @@ -2147,12 +2136,17 @@ public abstract class MarkupContainer extends > Component implements Iterable<Comp > > } > > - /** @see IQueueRegion#getDequeueMarkup() */ > - public IMarkupFragment getDequeueMarkup() > + /** @see IQueueRegion#newDequeueContext() */ > + public DequeueContext newDequeueContext() > { > - return getAssociatedMarkup(); > + Markup markup = getAssociatedMarkup(); > + if (markup == null) > + { > + return null; > + } > + return new DequeueContext(markup, this, false); > } > - > + > /** > * Checks if this container can dequeue a child represented by the > specified tag. This method > * should be overridden when containers can dequeue components > represented by non-standard tags. > @@ -2164,25 +2158,30 @@ public abstract class MarkupContainer extends > Component implements Iterable<Comp > * > * @param tag > */ > - protected boolean canDequeueTag(ComponentTag tag) > + protected DequeueTagAction canDequeueTag(ComponentTag tag) > { > if (tag instanceof WicketTag) > { > WicketTag wicketTag = (WicketTag)tag; > if (wicketTag.isContainerTag()) > { > - return true; > + return DequeueTagAction.DEQUEUE; > } > + else > if (wicketTag.getAutoComponentFactory() != null) > { > - return true; > + return DequeueTagAction.DEQUEUE; > + } > + else if (wicketTag.isFragmentTag()) > + { > + return DequeueTagAction.SKIP; > } > else > { > - return false; > + return null; // dont know > } > } > - return true; > + return DequeueTagAction.DEQUEUE; > } > > /** > > > http://git-wip-us.apache.org/repos/asf/wicket/blob/2008dfb7/wicket-core/src/main/java/org/apache/wicket/markup/html/border/Border.java > ---------------------------------------------------------------------- > diff --git > a/wicket-core/src/main/java/org/apache/wicket/markup/html/border/Border.java > b/wicket-core/src/main/java/org/apache/wicket/markup/html/border/Border.java > index a53b780..f60fc8a 100644 > --- > a/wicket-core/src/main/java/org/apache/wicket/markup/html/border/Border.java > +++ > b/wicket-core/src/main/java/org/apache/wicket/markup/html/border/Border.java > @@ -17,6 +17,8 @@ > package org.apache.wicket.markup.html.border; > > import org.apache.wicket.Component; > +import org.apache.wicket.DequeueContext; > +import org.apache.wicket.DequeueTagAction; > import org.apache.wicket.IQueueRegion; > import org.apache.wicket.MarkupContainer; > import org.apache.wicket.markup.ComponentTag; > @@ -538,7 +540,7 @@ public abstract class Border extends > WebMarkupContainer implements IComponentRes > } > > @Override > - public IMarkupFragment getDequeueMarkup() > + public DequeueContext newDequeueContext() > { > Border border=findParent(Border.class); > IMarkupFragment fragment = border.getMarkup(); > @@ -548,56 +550,7 @@ public abstract class Border extends > WebMarkupContainer implements IComponentRes > return null; > } > > - /* > - * we want to get the contents of the border here > (the markup that > - * is represented by the body tag) to do this we > need to strip the > - * tag that the border is attached to (usually the > first tag) > - */ > - > - int i = 0; > - while (i < fragment.size()) > - { > - // TODO queueing Use > fragment.find(border.getId()); instead ?! > - MarkupElement element = fragment.get(i); > - if (element instanceof ComponentTag > - && > ((ComponentTag)element).getId().equals(border.getId())) > - { > - break; > - } > - i++; > - } > - > - if (i >= fragment.size()) > - { > - throw new IllegalStateException("Could not > find starting border tag for border: " > - + border.getId() + " in > markup: " + fragment); > - } > - > - > - /* > - * (i) is now at the border tag, find the next > component tag (the tag that will belong > - * to the first direct child > - */ > - > - i++; > - while (i < fragment.size()) > - { > - MarkupElement element = fragment.get(i); > - if (element instanceof ComponentTag) > - { > - break; > - } > - i++; > - } > - > - ComponentTag tag = (ComponentTag)fragment.get(i); > - if (tag.isClose()) > - { > - // this closes the border tag, border only > has raw markup > - return null; > - } > - > - return new MarkupFragment(fragment, i); > + return new DequeueContext(fragment, this, true); > } > > @Override > @@ -636,11 +589,11 @@ public abstract class Border extends > WebMarkupContainer implements IComponentRes > } > > @Override > - protected boolean canDequeueTag(ComponentTag tag) > + protected DequeueTagAction canDequeueTag(ComponentTag tag) > { > if ((tag instanceof WicketTag) && > ((WicketTag)tag).isBodyTag()) > { > - return true; > + return DequeueTagAction.DEQUEUE; > } > > return super.canDequeueTag(tag); > > > http://git-wip-us.apache.org/repos/asf/wicket/blob/2008dfb7/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/DequeueMarkupFragment.java > ---------------------------------------------------------------------- > diff --git > a/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/DequeueMarkupFragment.java > b/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/DequeueMarkupFragment.java > new file mode 100644 > index 0000000..5e0a874 > --- /dev/null > +++ > b/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/DequeueMarkupFragment.java > @@ -0,0 +1,6 @@ > +package org.apache.wicket.markup.html.panel; > + > +public class DequeueMarkupFragment >
This class is not used at the moment Do we need it ? > +{ > + > +} > > > http://git-wip-us.apache.org/repos/asf/wicket/blob/2008dfb7/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java > ---------------------------------------------------------------------- > diff --git > a/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java > b/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java > index 676cca5..e915714 100644 > --- > a/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java > +++ > b/wicket-core/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java > @@ -17,12 +17,10 @@ > package org.apache.wicket.markup.html.panel; > > import org.apache.wicket.Component; > +import org.apache.wicket.DequeueContext; > import org.apache.wicket.IQueueRegion; > import org.apache.wicket.MarkupContainer; > import org.apache.wicket.markup.IMarkupFragment; > -import org.apache.wicket.markup.MarkupElement; > -import org.apache.wicket.markup.MarkupFragment; > -import org.apache.wicket.markup.WicketTag; > import org.apache.wicket.markup.html.WebMarkupContainer; > import org.apache.wicket.model.IModel; > import org.apache.wicket.util.lang.Args; > @@ -134,8 +132,16 @@ public class Fragment extends WebMarkupContainer > implements IQueueRegion > return associatedMarkupId; > } > > + > @Override > - public IMarkupFragment getDequeueMarkup() { > - return newMarkupSourcingStrategy().getMarkup(this, null); > + public DequeueContext newDequeueContext() > + { > + IMarkupFragment markup = > newMarkupSourcingStrategy().getMarkup(this, null); > + if (markup == null) > + { > + return null; > + } > + > + return new DequeueContext(markup, this, true); > } > } > > > http://git-wip-us.apache.org/repos/asf/wicket/blob/2008dfb7/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java > ---------------------------------------------------------------------- > diff --git > a/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java > b/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java > index 96f0c77..ed76db5 100644 > --- > a/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java > +++ > b/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java > @@ -18,6 +18,7 @@ package org.apache.wicket.queueing; > > import static org.apache.wicket.queueing.WicketMatchers.hasPath; > import static org.hamcrest.Matchers.is; > +import static org.hamcrest.Matchers.nullValue; > > import java.util.ArrayList; > > @@ -56,10 +57,8 @@ public class ComponentQueueingTest extends > WicketTestCase > MarkupContainer a = new A(), b = new B(), c = new C(); > > p.queue(b, c, a); > - > - tester.startPage(p); > - > assertThat(p, hasPath(a, b, c)); > + tester.startPage(p); > } > > /** {@code [a[b,c]] -> [a[b[c]]] } */ > @@ -600,7 +599,7 @@ public class ComponentQueueingTest extends > WicketTestCase > > > @Test > - public void nestedBorders() > + public void border_nested() > { > MarkupContainer a = new A(), b = new B(), c= new C(), d = > new D(), r = new R(), s = new S(); > > @@ -644,6 +643,23 @@ public class ComponentQueueingTest extends > WicketTestCase > assertThat(page, hasPath(new Path(fragment, r))); > assertThat(page, hasPath(new Path(fragment, s))); > } > + > + @Test > + public void fragment_doesNotDequeueAcrossRegion() > + { > + MarkupContainer a = new A(); > + > + TestPage page = new TestPage(); > + page.setPageMarkup("<f > wicket:id='fragment'></f><wicket:fragment wicket:id='f'><a > wicket:id='a'></a></wicket:fragment>"); > + > + Fragment fragment = new Fragment("fragment", "f", page); > + > + page.queue(a, fragment); > + > + assertThat(page, hasPath(new Path(fragment))); > + assertThat(a.getParent(), is(nullValue())); > + } > + > > @Test > public void containerTag1() > >