Repository: wicket Updated Branches: refs/heads/master 1d64d4ccf -> db5be6ab0
WICKET-5730 Dequeue auto component can't resolve components if they are nested in child markup Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/db5be6ab Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/db5be6ab Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/db5be6ab Branch: refs/heads/master Commit: db5be6ab05545e1bb95f566c3aeb23e05cf93437 Parents: 1d64d4c Author: Andrea Del Bene <[email protected]> Authored: Tue Oct 21 12:47:38 2014 +0200 Committer: Andrea Del Bene <[email protected]> Committed: Tue Oct 21 14:13:39 2014 +0200 ---------------------------------------------------------------------- .../main/java/org/apache/wicket/Component.java | 6 +- .../java/org/apache/wicket/DequeueContext.java | 498 +++++++++---------- .../java/org/apache/wicket/MarkupContainer.java | 233 ++++----- .../org/apache/wicket/markup/ComponentTag.java | 23 +- .../wicket/markup/html/border/Border.java | 7 - .../markup/parser/filter/EnclosureHandler.java | 6 +- .../markup/parser/filter/HtmlHandler.java | 33 +- .../filter/RelativePathPrefixHandler.java | 48 +- 8 files changed, 455 insertions(+), 399 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/db5be6ab/wicket-core/src/main/java/org/apache/wicket/Component.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/Component.java b/wicket-core/src/main/java/org/apache/wicket/Component.java index 29cafa5..fb69ff0 100644 --- a/wicket-core/src/main/java/org/apache/wicket/Component.java +++ b/wicket-core/src/main/java/org/apache/wicket/Component.java @@ -397,9 +397,9 @@ public abstract class Component * Flag that makes we are in before-render callback phase Set after component.onBeforeRender is * invoked (right before invoking beforeRender on children) */ - private static final int FLAG_RENDERING = 0x2000000; - private static final int FLAG_PREPARED_FOR_RENDER = 0x4000000; - private static final int FLAG_AFTER_RENDERING = 0x8000000; + protected static final int FLAG_RENDERING = 0x2000000; + protected static final int FLAG_PREPARED_FOR_RENDER = 0x4000000; + protected static final int FLAG_AFTER_RENDERING = 0x8000000; /** * Flag that restricts visibility of a component when set to true. This is usually used when a http://git-wip-us.apache.org/repos/asf/wicket/blob/db5be6ab/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 1b35152..0f0b403 100644 --- a/wicket-core/src/main/java/org/apache/wicket/DequeueContext.java +++ b/wicket-core/src/main/java/org/apache/wicket/DequeueContext.java @@ -29,273 +29,273 @@ import org.apache.wicket.util.collections.ArrayListStack; */ public final class DequeueContext { - private final IMarkupFragment markup; - private int index; - private ComponentTag next; - private ArrayListStack<ComponentTag> tags = new ArrayListStack<>(); - private final boolean skipFirst; - private ComponentTag first; + private final IMarkupFragment markup; + 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<>(); + private ArrayListStack<MarkupContainer> containers = new ArrayListStack<>(); - /** A bookmark for the DequeueContext stack */ - public static final class Bookmark - { - private final int index; - private final ComponentTag next; - private final ArrayListStack<ComponentTag> tags; - private final ArrayListStack<MarkupContainer> containers; + /** A bookmark for the DequeueContext stack */ + public static final class Bookmark + { + private final int index; + private final ComponentTag next; + private final ArrayListStack<ComponentTag> tags; + private final ArrayListStack<MarkupContainer> containers; - private Bookmark(DequeueContext parser) - { - this.index = parser.index; - this.next = parser.next; - this.tags = new ArrayListStack<>(parser.tags); - this.containers = new ArrayListStack<>(parser.containers); - } + private Bookmark(DequeueContext parser) + { + this.index = parser.index; + this.next = parser.next; + this.tags = new ArrayListStack<>(parser.tags); + this.containers = new ArrayListStack<>(parser.containers); + } - private void restore(DequeueContext parser) - { - parser.index = index; - parser.next = next; - parser.tags = new ArrayListStack<>(tags); - parser.containers = new ArrayListStack<>(containers); - } - } - - public DequeueContext(IMarkupFragment markup, MarkupContainer root, boolean skipFirst) - { - this.markup = markup; - this.skipFirst = skipFirst; - containers.push(root); - next=nextTag(); - } - - /** - * Saves the state of the context into a bookmark which can later be used to restore it. - */ - public Bookmark save() - { - return new Bookmark(this); - } + private void restore(DequeueContext parser) + { + parser.index = index; + parser.next = next; + parser.tags = new ArrayListStack<>(tags); + parser.containers = new ArrayListStack<>(containers); + } + } - /** - * Restores the state of the context from the bookmark - * - * @param bookmark - */ - public void restore(Bookmark bookmark) - { - bookmark.restore(this); - } + public DequeueContext(IMarkupFragment markup, MarkupContainer root, boolean skipFirst) + { + this.markup = markup; + this.skipFirst = skipFirst; + this.containers.push(root); + this.next = nextTag(); + } + + /** + * Saves the state of the context into a bookmark which can later be used to restore it. + */ + public Bookmark save() + { + return new Bookmark(this); + } - /** - * Peeks markup tag that would be retrieved by call to {@link #takeTag()} - * - * @return - */ - public ComponentTag peekTag() - { - return next; - } - - /** - * Retrieves the next markup tag - * - * @return - */ - public ComponentTag takeTag() - { - ComponentTag taken=next; + /** + * Restores the state of the context from the bookmark + * + * @param bookmark + */ + public void restore(Bookmark bookmark) + { + bookmark.restore(this); + } - if (taken == null) - { - return null; - } + /** + * Peeks markup tag that would be retrieved by call to {@link #takeTag()} + * + * @return + */ + public ComponentTag peekTag() + { + return next; + } - if (taken.isOpen() && !taken.hasNoCloseTag()) - { - tags.push(taken); - } - else if (tags.size() > 0 && taken.closes(tags.peek())) - { - tags.pop(); - } - next=nextTag(); - return taken; - } - - /** - * Skips to the closing tag of the tag retrieved from last call to {@link #takeTag()} - */ - public void skipToCloseTag() - { - while (!next.closes(tags.peek())) - { - next = nextTag(); - } - } - - 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; - } - } - } + /** + * Retrieves the next markup tag + * + * @return + */ + public ComponentTag takeTag() + { + ComponentTag taken = next; - for (; index < markup.size(); index++) - { - MarkupElement element = markup.get(index); - if (element instanceof ComponentTag) - { - ComponentTag tag = (ComponentTag)element; + if (taken == null) + { + return null; + } - if (tag.isOpen() || tag.isOpenClose()) - { - 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) - && markup.get(index).closes(tag)) - { - found = true; - break; - } - } - if (!found) - { - throw new IllegalStateException( - String.format("Could not find close tag for tag '%s' in markup: %s ", - tag, markup)); - } + if (taken.isOpen() && !taken.hasNoCloseTag()) + { + tags.push(taken); + } + else if (tags.size() > 0 && taken.closes(tags.peek())) + { + tags.pop(); + } + next = nextTag(); + return taken; + } - } - } - else - { - // closed tag - ComponentTag open = tag.isClose() ? tag.getOpenTag() : tag; + /** + * Skips to the closing tag of the tag retrieved from last call to {@link #takeTag()} + */ + public void skipToCloseTag() + { + while (!next.closes(tags.peek())) + { + next = nextTag(); + } + } - if (skipFirst && first != null && open == first) - { - continue; - } + 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; + } + } + } - switch (canDequeueTag(open)) - { - case DEQUEUE : - index++; - return tag; - case IGNORE : - continue; - case SKIP : - throw new IllegalStateException( - String.format("Should not see closed tag of skipped open tag '%s' in markup:%s", - tag, markup)); - } - } - } - } - return null; - } - - private DequeueTagAction canDequeueTag(ComponentTag open) - { - if (containers.size() < 1) - { - // TODO queueing message: called too early - throw new IllegalStateException(); - } + for (; index < markup.size(); index++) + { + MarkupElement element = markup.get(index); + if (element instanceof ComponentTag) + { + ComponentTag tag = (ComponentTag)element; - DequeueTagAction action; - for (int i = containers.size() - 1; i >= 0; i--) - { - action = containers.get(i).canDequeueTag((open)); - if (action != null) - { - return action; - } - } - return DequeueTagAction.IGNORE; - } + if (tag.isOpen() || tag.isOpenClose()) + { + 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) + && markup.get(index).closes(tag)) + { + found = true; + break; + } + } + if (!found) + { + throw new IllegalStateException(String.format( + "Could not find close tag for tag '%s' in markup: %s ", tag, + markup)); + } - /** - * Checks if the tag returned by {@link #peekTag()} is either open or open-close. - * - * @return - */ - public boolean isAtOpenOrOpenCloseTag() - { - ComponentTag tag = peekTag(); - return tag != null && (tag.isOpen() || tag.isOpenClose()); - } + } + } + else + { + // closed tag + ComponentTag open = tag.isClose() ? tag.getOpenTag() : tag; - /** - * Retrieves the container on the top of the containers stack - * - * @return - */ - public MarkupContainer peekContainer() - { - return containers.peek(); - } + if (skipFirst && first != null && open == first) + { + continue; + } - /** - * Pushes a container onto the container stack - * - * @param container - */ - public void pushContainer(MarkupContainer container) - { - containers.push(container); - } + switch (canDequeueTag(open)) + { + case DEQUEUE : + index++; + return tag; + case IGNORE : + continue; + case SKIP : + throw new IllegalStateException(String.format( + "Should not see closed tag of skipped open tag '%s' in markup:%s", + tag, markup)); + } + } + } + } + return null; + } - /** - * Pops a container from the container stack - * - * @return - */ - public MarkupContainer popContainer() - { - return containers.pop(); - } + private DequeueTagAction canDequeueTag(ComponentTag open) + { + if (containers.size() < 1) + { + // TODO queueing message: called too early + throw new IllegalStateException(); + } - /** - * Searches the container stack for a component that can be dequeud - * - * @param tag - * @return - */ - public Component findComponentToDequeue(ComponentTag tag) - { - for (int j = containers.size() - 1; j >= 0; j--) - { - MarkupContainer container = containers.get(j); - Component child = container.findComponentToDequeue(tag); - if (child != null) - { - return child; - } - } - return null; - } + DequeueTagAction action; + for (int i = containers.size() - 1; i >= 0; i--) + { + action = containers.get(i).canDequeueTag((open)); + if (action != null) + { + return action; + } + } + return DequeueTagAction.IGNORE; + } + + /** + * Checks if the tag returned by {@link #peekTag()} is either open or open-close. + * + * @return + */ + public boolean isAtOpenOrOpenCloseTag() + { + ComponentTag tag = peekTag(); + return tag != null && (tag.isOpen() || tag.isOpenClose()); + } + + /** + * Retrieves the container on the top of the containers stack + * + * @return + */ + public MarkupContainer peekContainer() + { + return containers.peek(); + } + + /** + * Pushes a container onto the container stack + * + * @param container + */ + public void pushContainer(MarkupContainer container) + { + containers.push(container); + } + + /** + * Pops a container from the container stack + * + * @return + */ + public MarkupContainer popContainer() + { + return containers.pop(); + } + + /** + * Searches the container stack for a component that can be dequeued + * + * @param tag + * @return + */ + public Component findComponentToDequeue(ComponentTag tag) + { + for (int j = containers.size() - 1; j >= 0; j--) + { + MarkupContainer container = containers.get(j); + Component child = container.findComponentToDequeue(tag); + if (child != null) + { + return child; + } + } + return null; + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/db5be6ab/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 f8f9116..8a15571 100644 --- a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java +++ b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java @@ -262,10 +262,6 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp } add(component); - /** - * https://issues.apache.org/jira/browse/WICKET-5724 - */ - return true; } @@ -932,34 +928,22 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp ComponentStrings.toString(child, new MarkupException("added"))); } - Page page = null; - MarkupContainer queueRegion = null; - Component cursor = this; - while (cursor != null) - { - if (queueRegion == null && (cursor instanceof IQueueRegion)) - { - queueRegion = (MarkupContainer)cursor; - } - if (cursor instanceof Page) - { - page = (Page)cursor; - } - cursor = cursor.getParent(); - } - - // if we have a path to page dequeue any children - if (page != null) + Page page = findPage(); + + // if we have a path to page dequeue any container children. + // we can do it only if page is not already rendering! + if (page != null && !page.getFlag(FLAG_RENDERING) && child instanceof MarkupContainer) { - // if we are already dequeueing there is no need to dequeue again - if (!queueRegion.getRequestFlag(RFLAG_CONTAINER_DEQUEING)) + MarkupContainer childContainer = (MarkupContainer)child; + // if we are already dequeueing there is no need to dequeue again + if (!childContainer.getRequestFlag(RFLAG_CONTAINER_DEQUEING)) { /* * dequeue both normal and auto components * * https://issues.apache.org/jira/browse/WICKET-5724 */ - queueRegion.dequeue(); + childContainer.dequeue(); } } @@ -1520,11 +1504,7 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp protected void onInitialize() { super.onInitialize(); - if (this instanceof IQueueRegion) - { - // if this container is a queue region dequeue any queued up auto components - dequeueAutoComponents(); - } + dequeueAutoComponents(); } private void dequeueAutoComponents() @@ -1535,11 +1515,18 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp { for (ComponentTag tag = context.takeTag(); tag != null; tag = context.takeTag()) { - ComponentTag.IAutoComponentFactory autoComponentFactory = tag.getAutoComponentFactory(); - if (autoComponentFactory != null) - { - queue(autoComponentFactory.newComponent(this, tag)); - } + ComponentTag.IAutoComponentFactory autoComponentFactory = tag.getAutoComponentFactory(); + if (autoComponentFactory != null) + { + queue(autoComponentFactory.newComponent(this, tag)); + } + + // Every component is responsible just for its own auto components + // so skip to the close tag. + if (tag.isOpen() && !tag.hasNoCloseTag()) + { + context.skipToCloseTag(); + } } } } @@ -1964,6 +1951,7 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp * freedom when moving components in markup. * * @param components + * the components to queue * @return {@code this} for method chaining */ public MarkupContainer queue(Component... components) @@ -1974,40 +1962,11 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp } queue.add(components); - return internalQueue(); - } - - /** - * Runs the actual queuing process. - * - * @return {@code this} for method chaining - */ - private MarkupContainer internalQueue() - { - MarkupContainer region = null; - Page page = null; - - MarkupContainer cursor = this; - - while (cursor != null) - { - if (region == null && cursor instanceof IQueueRegion) - { - region = cursor; - } - if (cursor instanceof Page) - { - page = (Page)cursor; - } - cursor = cursor.getParent(); - } + Page page = findPage(); if (page != null) { - if (!region.getRequestFlag(RFLAG_CONTAINER_DEQUEING)) - { - region.dequeue(); - } + dequeue(); } return this; @@ -2018,12 +1977,33 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp */ public void dequeue() { - if (!(this instanceof IQueueRegion)) - { - throw new UnsupportedOperationException( - "Only implementations of IQueueRegion can use component queueing"); - } - + if (this instanceof IQueueRegion) + { + DequeueContext dequeue = newDequeueContext(); + dequeuePreamble(dequeue); + } + else + { + MarkupContainer queueRegion = (MarkupContainer)findParent(IQueueRegion.class); + + if (!queueRegion.getRequestFlag(RFLAG_CONTAINER_DEQUEING)) + { + queueRegion.dequeue(); + } + } + } + + /** + * Run preliminary operations before running {@link #dequeue(DequeueContext)}. More in detail + * it throws an exception if the container is already dequeuing, and it also takes care of + * setting flag {@code RFLAG_CONTAINER_DEQUEING} to true before running {@link #dequeue(DequeueContext)} + * and setting it back to false after dequeuing is completed. + * + * @param dequeue + * the dequeue context to use + */ + protected void dequeuePreamble(DequeueContext dequeue) + { if (getRequestFlag(RFLAG_CONTAINER_DEQUEING)) { throw new IllegalStateException("This container is already dequeing: " + this); @@ -2032,10 +2012,8 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp setRequestFlag(RFLAG_CONTAINER_DEQUEING, true); try { - DequeueContext dequeue = newDequeueContext(); if (dequeue == null) { - // not ready to dequeue yet return; } @@ -2056,14 +2034,12 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp * components in queues filled by a call to {@link #queue(Component...)}. It then delegates the * dequeueing to these children. * - * The provided {@link DequeueContext} is used to maintain the place in markup as well as the - * stack of components whose queues will be searched. For example, before delegating the call to - * a child the container will push the child onto the stack of components. * * Certain components that implement custom markup behaviors (such as repeaters and borders) * override this method to bring dequeueing in line with their custom markup handling. * * @param dequeue + * the dequeue context to use */ public void dequeue(DequeueContext dequeue) { @@ -2072,77 +2048,76 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp ComponentTag tag = dequeue.takeTag(); // see if child is already added to parent - Component child = get(tag.getId()); if (child == null) { // the container does not yet have a child with this id, see if we can // dequeue - child = dequeue.findComponentToDequeue(tag); if (child != null) { - addDequeuedComponent(child, tag); - if (child instanceof IQueueRegion) - { - ((MarkupContainer)child).dequeue(); - } - } - } - if (child == null || !(child instanceof MarkupContainer)) - { - // could not dequeue, or does not contain children - - if (tag.isOpen() && !tag.hasNoCloseTag()) - { - dequeue.skipToCloseTag(); - } - } - else - { - MarkupContainer container = (MarkupContainer)child; - if (container instanceof IQueueRegion) - { - // if this is a dequeue container we do not process its markup, it will do so - // itself when it is dequeued for the first time - if (tag.isOpen()) - { - dequeue.skipToCloseTag(); - } - } - else if (tag.isOpen()) - { - // this component has more markup and possibly more children to dequeue - dequeue.pushContainer(container); - container.dequeue(dequeue); - dequeue.popContainer(); + addDequeuedComponent(child, tag); } } - + if (tag.isOpen() && !tag.hasNoCloseTag()) - { - // pull the close tag off - ComponentTag close = dequeue.takeTag(); - if (!close.closes(tag)) - { - // sanity check - throw new IllegalStateException(String.format("Tag '%s' should be the closing one for '%s'", close, tag)); - } - } + { + dequeueChild(child, tag, dequeue); + } } } - /** @see IQueueRegion#newDequeueContext() */ + /** + * Propagates dequeuing to children components. + * + * @param child + * the children component + * @param tag + * the children tag + * @param dequeue + * the dequeue context to use + */ + private void dequeueChild(Component child, ComponentTag tag, DequeueContext dequeue) + { + if (child == null || child instanceof IQueueRegion) + { + // could not dequeue, or is a dequeue container + dequeue.skipToCloseTag(); + + } + else if (child instanceof MarkupContainer) + { + //propagate dequeuing to containers + MarkupContainer childContainer = (MarkupContainer)child; + + dequeue.pushContainer(childContainer); + childContainer.dequeue(dequeue); + dequeue.popContainer(); + } + + // pull the close tag off + ComponentTag close = dequeue.takeTag(); + if (!close.closes(tag)) + { + // sanity check + throw new IllegalStateException(String.format("Tag '%s' should be the closing one for '%s'", close, tag)); + } + + } + + /** @see IQueueRegion#newDequeueContext() */ public DequeueContext newDequeueContext() { - Markup markup = getAssociatedMarkup(); + IMarkupFragment markup = getAssociatedMarkup(); + if (markup == null) - { - return null; - } + { + return null; + } + return new DequeueContext(markup, this, false); } @@ -2159,7 +2134,7 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp */ protected DequeueTagAction canDequeueTag(ComponentTag tag) { - if (tag instanceof WicketTag) + if (tag instanceof WicketTag) { WicketTag wicketTag = (WicketTag)tag; if (wicketTag.isContainerTag()) http://git-wip-us.apache.org/repos/asf/wicket/blob/db5be6ab/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java b/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java index d93d3e5..08caf0d 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java @@ -92,6 +92,12 @@ public class ComponentTag extends MarkupElement /** Render the tag as RawMarkup even if no Component can be found */ public final static int RENDER_RAW = 0x0020; + + /** + * If true, the component is the parent (or the ancestor) of Wicket component explicitly added. + * (i.e. it contains child tag with a "wicket:id" attribute) + * */ + public final static int CONTAINS_WICKET_ID = 0x0040; /** If close tag, than reference to the corresponding open tag */ private ComponentTag openTag; @@ -827,7 +833,22 @@ public class ComponentTag extends MarkupElement { setFlag(NO_CLOSE_TAG, hasNoCloseTag); } - + + /** + * True if the HTML tag (e.g. br) has no close tag + * + * @param hasNoCloseTag + */ + public void setContainsWicketId(boolean containsWicketId) + { + setFlag(CONTAINS_WICKET_ID, containsWicketId); + } + + public boolean containsWicketId() + { + return getFlag(CONTAINS_WICKET_ID); + } + /** * In case of inherited markup, the base and the extended markups are merged and the information * about the tags origin is lost. In some cases like wicket:head and wicket:link this http://git-wip-us.apache.org/repos/asf/wicket/blob/db5be6ab/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 1c4a1ec..934ab39 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 @@ -216,13 +216,6 @@ public abstract class Border extends WebMarkupContainer implements IComponentRes } @Override - public Border queue(Component... components) - { - getBodyContainer().queue(components); - return this; - } - - @Override public Border remove(final Component component) { if (component == body) http://git-wip-us.apache.org/repos/asf/wicket/blob/db5be6ab/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/EnclosureHandler.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/EnclosureHandler.java b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/EnclosureHandler.java index 098533c..7739cd0 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/EnclosureHandler.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/EnclosureHandler.java @@ -33,6 +33,7 @@ import org.apache.wicket.markup.WicketTag; import org.apache.wicket.markup.html.internal.Enclosure; import org.apache.wicket.markup.parser.AbstractMarkupFilter; import org.apache.wicket.markup.resolver.IComponentResolver; +import org.apache.wicket.util.string.Strings; /** @@ -155,7 +156,7 @@ public final class EnclosureHandler extends AbstractMarkupFilter implements ICom ComponentTag lastEnclosure = stack.getLast(); // If the enclosure tag has NO child attribute, then ... - if (lastEnclosure.getAttribute(CHILD_ATTRIBUTE) == null) + if (Strings.isEmpty(lastEnclosure.getAttribute(CHILD_ATTRIBUTE))) { String id = tag.getAttribute(getWicketNamespace() + ":id"); if (id != null) @@ -186,8 +187,7 @@ public final class EnclosureHandler extends AbstractMarkupFilter implements ICom if ((tag instanceof WicketTag) && ((WicketTag)tag).isEnclosureTag()) { // Yes, we handled the tag - return new Enclosure(tag.getId() + container.getPage().getAutoIndex(), - tag.getAttribute(EnclosureHandler.CHILD_ATTRIBUTE)); + return new Enclosure(tag.getId(), tag.getAttribute(EnclosureHandler.CHILD_ATTRIBUTE)); } // We were not able to handle the tag http://git-wip-us.apache.org/repos/asf/wicket/blob/db5be6ab/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java index 0d007c1..5801b4e 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java @@ -106,8 +106,11 @@ public final class HtmlHandler extends AbstractMarkupFilter // Check tag type if (tag.isOpen()) { + // Check if open tags contains a "wicket:id" component + setContainsWicketIdFlag(tag); + // Push onto stack - stack.push(tag); + stack.push(tag); } else if (tag.isClose()) { @@ -123,13 +126,12 @@ public final class HtmlHandler extends AbstractMarkupFilter if (mismatch) { - top.setHasNoCloseTag(true); - // Pop any simple tags off the top of the stack while (mismatch && !requiresCloseTag(top.getName())) { top.setHasNoCloseTag(true); - + top.setContainsWicketId(false); + // Pop simple tag if (stack.isEmpty()) { @@ -167,8 +169,29 @@ public final class HtmlHandler extends AbstractMarkupFilter return tag; } - + /** + * Checks if the tag is a Wicket component explicitly added. i.e + * it has the "wicket:id" attribute. + * + * @param tag + */ + private void setContainsWicketIdFlag(ComponentTag tag) + { + //check if it is a wicket:id component + String wicketIdAttr = getWicketNamespace() + ":" + "id"; + boolean hasWicketId = tag.getAttributes().get(wicketIdAttr) != null; + + if (hasWicketId) + { + for (ComponentTag componentTag : stack) + { + componentTag.setContainsWicketId(hasWicketId); + } + } + } + + /** * Gets whether this tag does not require a closing tag. * * @param name http://git-wip-us.apache.org/repos/asf/wicket/blob/db5be6ab/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RelativePathPrefixHandler.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RelativePathPrefixHandler.java b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RelativePathPrefixHandler.java index 5e66d95..1ab60c8 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RelativePathPrefixHandler.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RelativePathPrefixHandler.java @@ -17,12 +17,15 @@ package org.apache.wicket.markup.parser.filter; import java.text.ParseException; +import java.util.Iterator; import java.util.concurrent.atomic.AtomicInteger; import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; import org.apache.wicket.behavior.Behavior; import org.apache.wicket.markup.ComponentTag; +import org.apache.wicket.markup.ComponentTag.IAutoComponentFactory; +import org.apache.wicket.markup.Markup; import org.apache.wicket.markup.MarkupElement; import org.apache.wicket.markup.MarkupResourceStream; import org.apache.wicket.markup.MarkupStream; @@ -97,6 +100,16 @@ public final class RelativePathPrefixHandler extends AbstractMarkupFilter } }; + private static final IAutoComponentFactory FACTORY = new IAutoComponentFactory() + { + @Override + public Component newComponent(MarkupContainer container, ComponentTag tag) + { + return new TransparentWebMarkupContainer(tag.getId()); + } + }; + + /** * https://issues.apache.org/jira/browse/WICKET-5724 * @@ -152,7 +165,7 @@ public final class RelativePathPrefixHandler extends AbstractMarkupFilter { tag.setId(getWicketRelativePathPrefix(null) + componentIndex.getAndIncrement()); - tag.setAutoComponentTag(true); + tag.setAutoComponentTag(true); } tag.addBehavior(RELATIVE_PATH_BEHAVIOR); @@ -178,7 +191,38 @@ public final class RelativePathPrefixHandler extends AbstractMarkupFilter } return null; } - + + @Override + public void postProcess(Markup markup) + { + /** + * https://issues.apache.org/jira/browse/WICKET-5724 + * + * Transparent component inside page body must allow + * queued children components. + */ + Iterator<MarkupElement> markupIterator = markup.iterator(); + while (markupIterator.hasNext()) + { + MarkupElement next = markupIterator.next(); + + if(next instanceof ComponentTag) + { + ComponentTag componentTag = (ComponentTag)next; + + /** + * if component tag is for a transparent component + * and contains "wicket:id", must be queueable. + */ + if (componentTag.containsWicketId() && + componentTag.getId().startsWith(getWicketRelativePathPrefix(null))) + { + componentTag.setAutoComponentFactory(FACTORY); + } + } + } + } + private String getWicketRelativePathPrefix(final MarkupStream markupStream) { return getWicketNamespace(markupStream) + WICKET_RELATIVE_PATH_PREFIX_CONTAINER_ID;
