dequeue docs

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

Branch: refs/heads/master
Commit: fd7ab849202144b183c3cbd69c81b7e4e433be99
Parents: 2e57d8d
Author: Igor Vaynberg <igor.vaynb...@gmail.com>
Authored: Sat Feb 15 21:56:18 2014 -0800
Committer: Igor Vaynberg <igor.vaynb...@gmail.com>
Committed: Thu Feb 20 23:37:16 2014 -0800

----------------------------------------------------------------------
 .../java/org/apache/wicket/DequeueContext.java  |  68 ++++++-
 .../java/org/apache/wicket/IQueueRegion.java    |  22 ++-
 .../java/org/apache/wicket/MarkupContainer.java | 190 ++++++++++---------
 .../wicket/markup/html/border/Border.java       |   8 +-
 .../markup/repeater/AbstractRepeater.java       |   4 +
 5 files changed, 188 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/fd7ab849/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 4e62c3e..c13b0f2 100644
--- a/wicket-core/src/main/java/org/apache/wicket/DequeueContext.java
+++ b/wicket-core/src/main/java/org/apache/wicket/DequeueContext.java
@@ -2,19 +2,26 @@ package org.apache.wicket;
 
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.IMarkupFragment;
-import org.apache.wicket.markup.Markup;
 import org.apache.wicket.markup.MarkupElement;
 import org.apache.wicket.util.collections.ArrayListStack;
 
-public class DequeueContext
+/**
+ * Context for component dequeueing. Keeps track of markup position and 
container stack.
+ * 
+ * @author igor
+ *
+ */
+public final class DequeueContext
 {
        private final IMarkupFragment markup;
        private int index;
        private ComponentTag next;
        private ArrayListStack<ComponentTag> tags = new ArrayListStack<>();
+
        private ArrayListStack<MarkupContainer> containers = new 
ArrayListStack<>();
 
-       public static class Bookmark
+       /** A bookmark for the DequeueContext stack */
+       public static final class Bookmark
        {
                private final int index;
                private final ComponentTag next;
@@ -45,21 +52,39 @@ public class DequeueContext
                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);
        }
 
+       /**
+        * Restores the state of the context from the bookmark
+        * 
+        * @param bookmark
+        */
        public void restore(Bookmark bookmark)
        {
                bookmark.restore(this);
        }
 
+       /**
+        * Peeks markup tag that would be retrieved by call to {@link #popTag()}
+        * 
+        * @return
+        */
        public ComponentTag peekTag()
        {
                return next;
        }
        
+       /**
+        * Retrieves the next markup tag
+        * 
+        * @return
+        */
        public ComponentTag popTag()
        {
                ComponentTag taken=next;
@@ -68,6 +93,9 @@ public class DequeueContext
                return taken;
        }
        
+       /**
+        * Skips to the closing tag of the tag retrieved from last call to 
{@link #popTag()}
+        */
        public void skipToCloseTag()
        {
                if (tags.peek().isOpen())
@@ -89,7 +117,7 @@ public class DequeueContext
                        {
                                ComponentTag tag = (ComponentTag)element;
                                ComponentTag open = tag.isClose() ? 
tag.getOpenTag() : tag;
-                               if (canDequeue(open))
+                               if (canDequeueTag(open))
                                {
                                        index++;
                                        return tag;
@@ -99,7 +127,7 @@ public class DequeueContext
                return null;
        }
        
-       private boolean canDequeue(ComponentTag open)
+       private boolean canDequeueTag(ComponentTag open)
        {
                if (containers.size() < 1)
                {
@@ -108,7 +136,7 @@ public class DequeueContext
                }
                for (int i = containers.size() - 1; i >= 0; i--)
                {
-                       if (containers.get(i).supportsDequeueingFrom((open)))
+                       if (containers.get(i).canDequeueTag((open)))
                        {
                                return true;
                        }
@@ -116,27 +144,53 @@ public class DequeueContext
                return false;
        }
 
+       /**
+        * Checks if the tag returned by {@link #peekTag()} is either open or 
open-close.
+        * 
+        * @return
+        */
        public boolean isAtOpenOrOpenCloseTag()
        {
                return peekTag() != null && (peekTag().isOpen() || 
peekTag().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();
        }
 
-       public Component dequeue(ComponentTag tag)
+       /**
+        * 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--)
                {

http://git-wip-us.apache.org/repos/asf/wicket/blob/fd7ab849/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 86e30c6..beebdda 100644
--- a/wicket-core/src/main/java/org/apache/wicket/IQueueRegion.java
+++ b/wicket-core/src/main/java/org/apache/wicket/IQueueRegion.java
@@ -16,9 +16,11 @@
  */
 package org.apache.wicket;
 
+import org.apache.wicket.markup.IMarkupFragment;
+
 /**
- * Demarcates components that can dequeue children. These are usually 
components with associated
- * markup since the markup is needed to dequeue.
+ * Demarcates components that act as a root can dequeue children. These are 
usually components with
+ * associated markup since the markup is needed to dequeue.
  * 
  * It is also important to note that components queued outside of a region 
cannot be dequeued into
  * it since regions act as roots for the dequeue process because they contain 
the markup. As such,
@@ -30,5 +32,21 @@ package org.apache.wicket;
  */
 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
+        * {@link MarkupContainer#getAssociatedMarkup()}, but compoennts 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 dequeuing process.
+        */
+       public IMarkupFragment getDequeueMarkup();
 
+       /**
+        * Starts component dequeueing on this {@link IQueueRegion}. This is 
the entry point into the
+        * dequeuing process, it creates the {@link DequeueContext} and 
delegates the opreation to the
+        * {@link #dequeue(DequeueContext)} method which performs the actual 
dequeuing. The context's
+        * markup is retrieved using the {@link #getDequeueMarkup()} method 
which allows subclasses to
+        * provide dequeueing-specific markup.
+        */
+       public void dequeue();
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/fd7ab849/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 e213f35..3fe7c98 100644
--- a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
+++ b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
@@ -36,13 +36,11 @@ import org.apache.wicket.markup.MarkupType;
 import org.apache.wicket.markup.WicketTag;
 import org.apache.wicket.markup.html.border.Border;
 import org.apache.wicket.markup.html.internal.InlineEnclosure;
-import org.apache.wicket.markup.repeater.AbstractRepeater;
 import org.apache.wicket.markup.resolver.ComponentResolvers;
 import org.apache.wicket.model.IComponentInheritedModel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.IWrapModel;
 import org.apache.wicket.settings.DebugSettings;
-import org.apache.wicket.util.collections.ArrayListStack;
 import org.apache.wicket.util.io.IClusterable;
 import org.apache.wicket.util.iterator.ComponentHierarchyIterator;
 import org.apache.wicket.util.lang.Args;
@@ -1519,22 +1517,28 @@ public abstract class MarkupContainer extends Component 
implements Iterable<Comp
                super.onInitialize();
                if (this instanceof IQueueRegion)
                {
-                       // dequeue auto components
-                       Markup markup = getAssociatedMarkup();
-                       if (markup != null)
+                       // if this container is a queue region dequeue any 
queued up auto components
+                       dequeueAutoComponents();
+               }
+       }
+
+       private void dequeueAutoComponents()
+       {
+               // dequeue auto components
+               IMarkupFragment markup = getDequeueMarkup();
+               if (markup != null)
+               {
+                       // make sure we have markup, when running inside tests 
we wont
+                       for (int i = 0; i < markup.size(); i++)
                        {
-                               // make sure we have markup, when running 
inside tests we wont
-                               for (int i = 0; i < markup.size(); i++)
+                               MarkupElement element = markup.get(i);
+                               if (element instanceof ComponentTag)
                                {
-                                       MarkupElement element = markup.get(i);
-                                       if (element instanceof ComponentTag)
+                                       ComponentTag tag = 
(ComponentTag)element;
+                                       if (tag.getAutoComponentFactory() != 
null)
                                        {
-                                               ComponentTag tag = 
(ComponentTag)element;
-                                               if 
(tag.getAutoComponentFactory() != null)
-                                               {
-                                                       Component auto = 
tag.getAutoComponentFactory().newComponent(tag);
-                                                       queue(auto);
-                                               }
+                                               Component auto = 
tag.getAutoComponentFactory().newComponent(tag);
+                                               queue(auto);
                                        }
                                }
                        }
@@ -1952,55 +1956,6 @@ public abstract class MarkupContainer extends Component 
implements Iterable<Comp
                }
        }
 
-       /**
-        * Automatically create components for <wicket:xxx> tag.
-        */
-       // to use it call it from #onInitialize()
-       private void createAndAddComponentsForWicketTags()
-       {
-               // Markup must be available
-               IMarkupFragment markup = getMarkup();
-               if ((markup != null) && (markup.size() > 1))
-               {
-                       MarkupStream stream = new MarkupStream(markup);
-
-                       // Skip the first component tag which already belongs 
to 'this' container
-                       if (stream.skipUntil(ComponentTag.class))
-                       {
-                               stream.next();
-                       }
-
-                       // Search for <wicket:xxx> in the remaining markup and 
try to resolve the component
-                       while (stream.skipUntil(ComponentTag.class))
-                       {
-                               ComponentTag tag = stream.getTag();
-                               if (tag.isOpen() || tag.isOpenClose())
-                               {
-                                       if (tag instanceof WicketTag)
-                                       {
-                                               Component component = 
ComponentResolvers.resolve(this, stream, tag, null);
-                                               if ((component != null) && 
(component.getParent() == null))
-                                               {
-                                                       if 
(component.getId().equals(tag.getId()) == false)
-                                                       {
-                                                               // make sure we 
are able to get() the component during rendering
-                                                               
tag.setId(component.getId());
-                                                               
tag.setModified(true);
-                                                       }
-                                                       add(component);
-                                               }
-                                       }
-
-                                       if (tag.isOpen())
-                                       {
-                                               
stream.skipToMatchingCloseTag(tag);
-                                       }
-                               }
-                               stream.next();
-                       }
-               }
-       }
-
        @Override
        protected void onDetach()
        {
@@ -2017,6 +1972,17 @@ public abstract class MarkupContainer extends Component 
implements Iterable<Comp
 
        private transient ComponentQueue queue;
 
+       /**
+        * Queues a component to be dequeued later. The advantage of this 
method over the
+        * {@link #add(Component...)} method is that the component does not 
have to be added to its
+        * direct parent, only to a parent upstream; it will be dequeued into 
the correct parent using
+        * the hierarchy defined in the markup. This allows the component 
hiearchy to be maintined only
+        * in markup instead of in markup and in java code; affording designers 
and developers more
+        * freedom when moving components in markup.
+        * 
+        * @param components
+        * @return
+        */
        public MarkupContainer queue(Component... components)
        {
                if (queue == null)
@@ -2054,7 +2020,10 @@ public abstract class MarkupContainer extends Component 
implements Iterable<Comp
                return this;
        }
 
-       void dequeue()
+       /**
+        * @see IQueueRegion#dequeue()
+        */
+       public void dequeue()
        {
                if (!(this instanceof IQueueRegion))
                {
@@ -2070,7 +2039,20 @@ public abstract class MarkupContainer extends Component 
implements Iterable<Comp
                setRequestFlag(RFLAG_CONTAINER_DEQUEING, true);
                try
                {
-                       internalDequeue();
+                       IMarkupFragment markup = getDequeueMarkup();
+                       if (markup == null)
+                       {
+                               // markup not found, skip dequeuing
+                               // this sometimes happens when we are in a unit 
test
+                               return;
+                       }
+
+                       DequeueContext dequeue = new DequeueContext(markup, 
this);
+
+                       if (dequeue.peekTag() != null)
+                       {
+                               dequeue(dequeue);
+                       }
                }
                finally
                {
@@ -2078,29 +2060,23 @@ public abstract class MarkupContainer extends Component 
implements Iterable<Comp
                }
        }
 
-       private void internalDequeue()
-       {
-               IMarkupFragment markup = getDequeueMarkup();
-               if (markup == null)
-               {
-                       // markup not found, skip dequeuing
-                       // this sometimes happens when we are in a unit test
-                       return;
-               }
-
-               DequeueContext dequeue = new DequeueContext(markup, this);
-
-               if (dequeue.peekTag() != null)
-               {
-                       dequeue(dequeue);
-               }
-
-
-       }
+       /**
+        * Dequeues components. The default implementation iterates direct 
children of this container
+        * found in the markup (retrieved via {@link #getDequeueMarkup()}) and 
tries to find matching
+        * components in queues filled by a call to {@link 
#queue(Component...)}. It then delegates the
+        * dequeing 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 dequeuing in line with their custom 
markup handling.
+        * 
+        * @param dequeue
+        */
        public void dequeue(DequeueContext dequeue)
        {
-               
-
                while (dequeue.isAtOpenOrOpenCloseTag())
                {
                
@@ -2117,7 +2093,7 @@ public abstract class MarkupContainer extends Component 
implements Iterable<Comp
                                // the container does not yet have a child with 
this id, see if we can
                                // dequeue
                                
-                               child = dequeue.dequeue(tag);
+                               child = dequeue.findComponentToDequeue(tag);
        
                                if (child != null)
                                {
@@ -2154,17 +2130,28 @@ public abstract class MarkupContainer extends Component 
implements Iterable<Comp
                                        throw new IllegalStateException();
                                }
                        }
-
-
                }
 
        }
        
-       protected IMarkupFragment getDequeueMarkup() {
+       /** @see IQueueRegion#getDequeueMarkup() */
+       public IMarkupFragment getDequeueMarkup()
+       {
                return getAssociatedMarkup();
        }
        
-       protected boolean supportsDequeueingFrom(ComponentTag tag) {
+       /**
+        * 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.
+        * For example, borders override this method and dequeue their body 
container when processing
+        * the body tag.
+        * 
+        * By default all {@link ComponentTag}s are supported as well as {@link 
WicketTag}s that return
+        * a non-null value from {@link WicketTag#getAutoComponentFactory()} 
method.
+        * 
+        * @param tag
+        */
+       protected boolean canDequeueTag(ComponentTag tag) {
                if (tag instanceof WicketTag) {
                        WicketTag wicketTag=(WicketTag)tag;
                        if (wicketTag.getAutoComponentFactory() != null)
@@ -2177,11 +2164,30 @@ public abstract class MarkupContainer extends Component 
implements Iterable<Comp
                return true;
        }
        
+       /**
+        * Queries this container to find a child that can be dequeued that 
matches the specified tag.
+        * The default implementation will check if there is a component in the 
queue that has the same
+        * id as a tag, but sometimes custom tags can be dequeued and in those 
situations this method
+        * should be overridden.
+        * 
+        * @param tag
+        * @return
+        */
        public Component findComponentToDequeue(ComponentTag tag)
        {
                return queue == null ? null : queue.remove(tag.getId());
        }
 
+       /**
+        * Adds a dequeued component to this container. This method should 
rarely be overridden becase
+        * the common case of simply forwarding the component to
+        * {@link MarkupContainer#add(Component...))} method should cover most 
cases. Components that
+        * implement a custom hierarchy, such as borders, may wish to override 
it to support edge-case
+        * non-standard behavior.
+        * 
+        * @param component
+        * @param tag
+        */
        protected void addDequeuedComponent(Component component, ComponentTag 
tag) {
                add(component);
        }

http://git-wip-us.apache.org/repos/asf/wicket/blob/fd7ab849/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 54fa141..e916d18 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
@@ -537,7 +537,8 @@ public abstract class Border extends WebMarkupContainer 
implements IComponentRes
                        return markup.find(child.getId());
                }
                
-               protected IMarkupFragment getDequeueMarkup() {
+               public IMarkupFragment getDequeueMarkup()
+               {
                        Border border=findParent(Border.class);
                        IMarkupFragment 
fragment=findParent(Border.class).getMarkup();
                        /*
@@ -614,12 +615,12 @@ public abstract class Border extends WebMarkupContainer 
implements IComponentRes
        
        
        @Override
-       protected boolean supportsDequeueingFrom(ComponentTag tag) {
+       protected boolean canDequeueTag(ComponentTag tag) {
                if ((tag instanceof WicketTag)&&((WicketTag)tag).isBodyTag()) {
                        return true;
                }
 
-               return super.supportsDequeueingFrom(tag);
+               return super.canDequeueTag(tag);
        }
        
        @Override
@@ -632,6 +633,7 @@ public abstract class Border extends WebMarkupContainer 
implements IComponentRes
        
        @Override
        protected void addDequeuedComponent(Component component, ComponentTag 
tag) {
+               // components queued in border get dequeued into the border not 
into the body container
                addToBorder(component);
        }
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/fd7ab849/wicket-core/src/main/java/org/apache/wicket/markup/repeater/AbstractRepeater.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/repeater/AbstractRepeater.java
 
b/wicket-core/src/main/java/org/apache/wicket/markup/repeater/AbstractRepeater.java
index 134e239..2b1a4bb 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/markup/repeater/AbstractRepeater.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/markup/repeater/AbstractRepeater.java
@@ -157,6 +157,10 @@ public abstract class AbstractRepeater extends 
WebMarkupContainer
        @Override
        public void dequeue(DequeueContext dequeue) {
                if (size()>0) {
+                       // essentially what we do is for every child replace 
the repeater with the child in
+                       // dequeue container stack and run the dequeue on the 
child. we also take care to reset
+                       // the state of the dequeue context after we process 
every child.
+
                        Bookmark bookmark=dequeue.save();
                        
                        for (Component child:this) {

Reply via email to