Author: jdonnerstag
Date: Sat Nov 14 09:37:44 2009
New Revision: 836148

URL: http://svn.apache.org/viewvc?rev=836148&view=rev
Log:
wip on MarkupFragments; cleaning up old APIs

Added:
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/OpenTagIterator.java
Modified:
    wicket/trunk/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/ComponentTag.java
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/IMarkupFragment.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/Markup.java
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupFragment.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupStream.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MergedMarkup.java
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/WebMarkupContainerWithAssociatedMarkup.java
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/border/Border.java
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponentPanel.java
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.html
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.java
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Panel.java
    
wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/MarkupParserTest.java
    
wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/html/panel/InlinePanelPage_5.java

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/MarkupContainer.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/MarkupContainer.java 
(original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/MarkupContainer.java 
Sat Nov 14 09:37:44 2009
@@ -472,7 +472,7 @@
                }
 
                // Find the child's markup
-               markup = markup.find(null, child.getId(), 0);
+               markup = markup.find(child.getId(), 0);
                if (markup != null)
                {
                        return markup;

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/ComponentTag.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/ComponentTag.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/ComponentTag.java 
(original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/ComponentTag.java 
Sat Nov 14 09:37:44 2009
@@ -70,9 +70,6 @@
         */
        private String id;
 
-       /** The component's path in the markup */
-       private String path;
-
        /** True, if attributes have been modified or added */
        private transient boolean modified = false;
 
@@ -434,7 +431,6 @@
        {
                dest.id = id;
                dest.setHasNoCloseTag(hasNoCloseTag);
-               dest.setPath(path);
                dest.setAutoComponentTag(autoComponent);
                if (markupClassRef != null)
                {
@@ -743,27 +739,6 @@
        }
 
        /**
-        * Gets the component path of wicket elements
-        * 
-        * @return path
-        */
-       public String getPath()
-       {
-               return path;
-       }
-
-       /**
-        * Sets the component path of wicket elements
-        * 
-        * @param path
-        *            path
-        */
-       void setPath(final String path)
-       {
-               this.path = path;
-       }
-
-       /**
         * 
         * @return True if the HTML tag (e.g. br) has no close tag
         */

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/IMarkupFragment.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/IMarkupFragment.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/IMarkupFragment.java 
(original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/IMarkupFragment.java 
Sat Nov 14 09:37:44 2009
@@ -65,7 +65,7 @@
         *            Index to start searching
         * @return -1, if not found
         */
-       int findComponentIndex(final String path, final String id, final int 
startIndex);
+       int findComponentIndex(final String id, final int startIndex);
 
        /**
         * Find the markup element index of the component with 'path'
@@ -78,7 +78,7 @@
         *            Index to start searching
         * @return -1, if not found
         */
-       IMarkupFragment find(final String path, final String id, final int 
startIndex);
+       IMarkupFragment find(final String id, final int startIndex);
 
        /**
         * 

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/Markup.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/Markup.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/Markup.java 
(original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/Markup.java Sat 
Nov 14 09:37:44 2009
@@ -18,15 +18,12 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.apache.wicket.util.resource.IFixedLocationResourceStream;
 import org.apache.wicket.util.string.AppendingStringBuffer;
+import org.apache.wicket.util.string.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,15 +51,6 @@
        /** The associated markup file */
        private final MarkupResourceStream markupResourceStream;
 
-       /** A cache which maps (componentPath + id) to the componentTags index 
in the markup */
-       private Map<String, Integer> componentMap;
-
-       /**
-        * Used at markup load time to maintain the current component path (not 
id) while adding markup
-        * elements to this Markup instance
-        */
-       private StringBuffer currentPath;
-
        /**
         * Private Constructor for NO_MARKUP only
         */
@@ -160,160 +148,42 @@
                }
 
                markupElements = Collections.unmodifiableList(markupElements);
-               initialize();
-       }
-
-       /**
-        * Add the tag to the local cache if open or open-close and if 
wicket:id is present
-        * 
-        * @param index
-        * @param tag
-        */
-       private void addToCache(final int index, final ComponentTag tag)
-       {
-               // Only if the tag has wicket:id="xx" and open or open-close
-               if ((tag.isOpen() || tag.isOpenClose()) &&
-                       
tag.getAttributes().containsKey(getMarkupResourceStream().getWicketId()))
-               {
-                       // Add the tag to the cache
-                       if (componentMap == null)
-                       {
-                               componentMap = new HashMap<String, Integer>();
-                       }
-
-                       /*
-                        * XXX cleanup - this fragment check probably needs to 
be in
-                        * componenttag.isWantToBeDirectMarkupChild() or 
something similar instead of being here
-                        */
-                       final boolean fragment = (tag instanceof WicketTag && 
((WicketTag)tag).isFragementTag());
-
-                       final String key;
-
-                       if (tag.getPath() != null && !fragment/* WICKET-404 */)
-                       {
-                               key = tag.getPath() + ":" + tag.getId();
-                       }
-                       else
-                       {
-                               key = tag.getId();
-                       }
-                       componentMap.put(key, new Integer(index));
-               }
-       }
-
-       /**
-        * Set the components path within the markup and add the component tag 
to the local cache
-        * 
-        * @param componentPath
-        * @param tag
-        * @return componentPath
-        */
-       private StringBuffer setComponentPathForTag(final StringBuffer 
componentPath,
-               final ComponentTag tag)
-       {
-               // Only if the tag has wicket:id="xx" and open or open-close
-               if ((tag.isOpen() || tag.isOpenClose()) &&
-                       
tag.getAttributes().containsKey(markupResourceStream.getWicketId()))
-               {
-                       // With open-close the path does not change. It 
can/will not have
-                       // children. The same is true for HTML tags like <br> 
or <img>
-                       // which might not have close tags.
-                       if (tag.isOpenClose() || tag.hasNoCloseTag())
-                       {
-                               // Set the components path.
-                               if ((currentPath != null) && 
(currentPath.length() > 0))
-                               {
-                                       tag.setPath(currentPath.toString());
-                               }
-                       }
-                       else
-                       {
-                               // Set the components path.
-                               if (currentPath == null)
-                               {
-                                       currentPath = new StringBuffer(100);
-                               }
-                               else if (currentPath.length() > 0)
-                               {
-                                       tag.setPath(currentPath.toString());
-                                       currentPath.append(':');
-                               }
-
-                               // .. and append the tags id to the component 
path for the
-                               // children to come
-                               currentPath.append(tag.getId());
-                       }
-               }
-               else if (tag.isClose() && (currentPath != null))
-               {
-                       // For example <wicket:message> does not have an id
-                       if ((tag.getOpenTag() == null) ||
-                               
tag.getOpenTag().getAttributes().containsKey(markupResourceStream.getWicketId()))
-                       {
-                               // Remove the last element from the component 
path
-                               int index = currentPath.lastIndexOf(":");
-                               if (index != -1)
-                               {
-                                       currentPath.setLength(index);
-                               }
-                               else
-                               {
-                                       currentPath.setLength(0);
-                               }
-                       }
-               }
-
-               return currentPath;
        }
 
        /**
         * @see 
org.apache.wicket.markup.IMarkupFragment#findComponentIndex(java.lang.String,
         *      java.lang.String, int)
         */
-       public final int findComponentIndex(final String path, final String id, 
final int startIndex)
+       public final int findComponentIndex(final String id, final int 
startIndex)
        {
-               if ((id == null) || (id.length() == 0))
-               {
-                       throw new IllegalArgumentException("Parameter 'id' must 
not be null");
-               }
-
-               // TODO Post 1.2: A component path e.g. "panel:label" does not 
match 1:1
-               // with the markup in case of ListView, where the path contains 
a number
-               // for each list item. E.g. list:0:label. What we currently do 
is simply
-               // remove the number from the path and hope that no user uses 
an integer
-               // for a component id. This is a hack only. A much better 
solution would
-               // delegate to the various components recursively to search 
within there
-               // realm only for the components markup. ListItems could then 
simply
-               // do nothing and delegate to their parents.
-               String completePath = (path == null || path.length() == 0 ? id 
: path + ":" + id);
-
-               // s/:\d+//g
-               Pattern re = Pattern.compile(":\\d+");
-               Matcher matcher = re.matcher(completePath);
-               completePath = matcher.replaceAll("");
-
-               // All component tags are registered with the cache
-               if (componentMap != null)
+               if (Strings.isEmpty(id))
                {
-                       final Integer value = componentMap.get(completePath);
-                       if (value != null)
-                       {
-                               // return the components position in the markup 
stream
-                               return value.intValue();
-                       }
+                       throw new IllegalArgumentException("Parameter 'id' must 
not be null or empty");
                }
 
-               for (int i = Math.max(0, startIndex); i < size(); i++)
+               MarkupStream stream = new MarkupStream(this);
+               stream.setCurrentIndex(Math.max(0, startIndex));
+               while (stream.hasMore())
                {
-                       MarkupElement elem = get(i);
+                       MarkupElement elem = stream.get();
                        if (elem instanceof ComponentTag)
                        {
-                               ComponentTag tag = (ComponentTag)elem;
-                               if (tag.isAutoComponentTag() && (tag.getId() != 
null) && tag.getId().startsWith(id))
+                               ComponentTag tag = stream.getTag();
+                               if (tag.isOpen() || tag.isOpenClose())
                                {
-                                       return i;
+                                       if (tag.getId().equals(id))
+                                       {
+                                               return stream.getCurrentIndex();
+                                       }
+                                       if (tag.isOpen() && 
!tag.hasNoCloseTag() && !(tag instanceof WicketTag) &&
+                                               !"head".equals(tag.getName()) 
&& !tag.isAutoComponentTag())
+                                       {
+                                               
stream.skipToMatchingCloseTag(tag);
+                                       }
                                }
                        }
+
+                       stream.next();
                }
 
                return -1;
@@ -324,9 +194,9 @@
         * @param that
         * @return true, if equal
         */
-       public final IMarkupFragment find(final String path, final String id, 
final int startIndex)
+       public final IMarkupFragment find(final String id, final int startIndex)
        {
-               int index = findComponentIndex(path, id, startIndex);
+               int index = findComponentIndex(id, startIndex);
                if (index >= 0)
                {
                        return new MarkupFragment(this, index);
@@ -335,42 +205,6 @@
        }
 
        /**
-        * Initialize the index where wicket tags can be found
-        */
-       protected final void initialize()
-       {
-               // Reset
-               componentMap = null;
-
-               if (markupElements != null)
-               {
-                       // HTML tags like <img> may not have a close tag. But 
because that
-                       // can only be detected until later on in the 
sequential markup
-                       // reading loop, we only can do it now.
-                       StringBuffer componentPath = null;
-                       for (int i = 0; i < size(); i++)
-                       {
-                               MarkupElement elem = get(i);
-                               if (elem instanceof ComponentTag)
-                               {
-                                       ComponentTag tag = (ComponentTag)elem;
-
-                                       // Set the tags components path
-                                       componentPath = 
setComponentPathForTag(componentPath, tag);
-
-                                       // and add it to the local cache to be 
found fast if
-                                       // required
-                                       addToCache(i, tag);
-                               }
-                       }
-               }
-
-               // The variable is only needed while adding markup elements.
-               // initialize() is invoked after all elements have been added.
-               currentPath = null;
-       }
-
-       /**
         * @see org.apache.wicket.markup.IMarkupFragment#toString()
         */
        @Override

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupFragment.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupFragment.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupFragment.java 
(original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupFragment.java 
Sat Nov 14 09:37:44 2009
@@ -17,6 +17,7 @@
 package org.apache.wicket.markup;
 
 import org.apache.wicket.util.string.AppendingStringBuffer;
+import org.apache.wicket.util.string.Strings;
 
 /**
  * Represents a portion of a markup file, but always spans a complete tag. E.g.
@@ -43,9 +44,6 @@
        /** The size of the fragment (usually from open to close tag) */
        private final int size;
 
-       /** the component id of the start tag */
-       private final String rootPath;
-
        /**
         * Construct.
         * 
@@ -127,26 +125,6 @@
                }
 
                size = endIndex - startIndex + 1;
-
-               // @TODO Setting the rootPath depending on specific tags is 
really ugly, since there is
-               // no way for user to enhance it in case he creates its own 
wicket tag. It probably can
-               // be removed once we switch to the markup resolution process.
-               if (startTag instanceof WicketTag)
-               {
-                       WicketTag tag = (WicketTag)startTag;
-                       if (tag.isFragementTag() || tag.isContainerTag())
-                       {
-                               rootPath = startTag.getId();
-                       }
-                       else
-                       {
-                               rootPath = null;
-                       }
-               }
-               else
-               {
-                       rootPath = startTag.getId();
-               }
        }
 
        /**
@@ -168,18 +146,35 @@
         * @see 
org.apache.wicket.markup.IMarkupFragment#findComponentIndex(java.lang.String,
         *      java.lang.String)
         */
-       public final int findComponentIndex(String path, final String id, final 
int startIndex)
+       public final int findComponentIndex(final String id, final int 
startIndex)
        {
-               // Prepend rootPath to the 'path' parameter
-               path = (path == null ? rootPath : (rootPath == null ? path : 
rootPath + ":" + path));
-
-               // Search the markup
-               int index = markup.findComponentIndex(path, id, this.startIndex 
+ startIndex) -
-                       this.startIndex;
+               if (Strings.isEmpty(id))
+               {
+                       throw new IllegalArgumentException("Parameter 'id' must 
not be null or empty");
+               }
 
-               if ((index >= 0) && (index < size))
+               MarkupStream stream = new MarkupStream(this);
+               stream.setCurrentIndex(Math.max(1, startIndex));
+               while (stream.hasMore())
                {
-                       return index;
+                       MarkupElement elem = stream.get();
+                       if (elem instanceof ComponentTag)
+                       {
+                               ComponentTag tag = stream.getTag();
+                               if (tag.isOpen() || tag.isOpenClose())
+                               {
+                                       if (tag.getId().equals(id))
+                                       {
+                                               return stream.getCurrentIndex();
+                                       }
+                                       if (tag.isOpen() && 
!tag.hasNoCloseTag() && !(tag instanceof WicketTag))
+                                       {
+                                               
stream.skipToMatchingCloseTag(tag);
+                                       }
+                               }
+                       }
+
+                       stream.next();
                }
 
                return -1;
@@ -188,9 +183,9 @@
        /**
         * @see org.apache.wicket.markup.IMarkupFragment#find(java.lang.String, 
java.lang.String, int)
         */
-       public final IMarkupFragment find(final String path, final String id, 
final int startIndex)
+       public final IMarkupFragment find(final String id, final int startIndex)
        {
-               int index = findComponentIndex(path, id, startIndex);
+               int index = findComponentIndex(id, startIndex);
                if (index >= 0)
                {
                        return new MarkupFragment(this, index);

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupStream.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupStream.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupStream.java 
(original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupStream.java 
Sat Nov 14 09:37:44 2009
@@ -196,9 +196,9 @@
         *            The component's id to search for
         * @return -1, if not found
         */
-       public final int findComponentIndex(final String path, final String id)
+       public final int findComponentIndex(final String id)
        {
-               return markup.findComponentIndex(path, id, 0);
+               return markup.findComponentIndex(id, 0);
        }
 
        /**
@@ -324,6 +324,29 @@
        }
 
        /**
+        * Note:
+        * 
+        * @return The next markup element in the stream
+        */
+       public MarkupElement nextOpenTag()
+       {
+               while (next() != null)
+               {
+                       MarkupElement elem = get();
+                       if (elem instanceof ComponentTag)
+                       {
+                               ComponentTag tag = (ComponentTag)elem;
+                               if (tag.isOpen() || tag.isOpenClose())
+                               {
+                                       return current = get(currentIndex);
+                               }
+                       }
+               }
+
+               return null;
+       }
+
+       /**
         * @param currentIndex
         *            New current index in the stream
         */

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MergedMarkup.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MergedMarkup.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MergedMarkup.java 
(original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MergedMarkup.java 
Sat Nov 14 09:37:44 2009
@@ -78,9 +78,6 @@
                // Merge derived and base markup
                merge(markup, baseMarkup, extendIndex);
 
-               // Initialize internals based on new markup
-               initialize();
-
                if (log.isDebugEnabled())
                {
                        log.debug("Merge markup: " + toString());

Added: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/OpenTagIterator.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/OpenTagIterator.java?rev=836148&view=auto
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/OpenTagIterator.java 
(added)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/OpenTagIterator.java 
Sat Nov 14 09:37:44 2009
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup;
+
+import java.util.Iterator;
+
+/**
+ * @author Juergen Donnerstag
+ */
+public class OpenTagIterator implements Iterator<ComponentTag>
+{
+       private final IMarkupFragment markup;
+
+       private int index = -1;
+
+       /**
+        * Construct.
+        * 
+        * @param markup
+        */
+       public OpenTagIterator(final IMarkupFragment markup)
+       {
+               this.markup = markup;
+       }
+
+       /**
+        * @see java.util.Iterator#hasNext()
+        */
+       public boolean hasNext()
+       {
+               while (++index < markup.size())
+               {
+                       MarkupElement elem = markup.get(index);
+                       if (elem instanceof ComponentTag)
+                       {
+                               ComponentTag tag = (ComponentTag)elem;
+                               if (tag.isOpen() || tag.isOpenClose())
+                               {
+                                       return true;
+                               }
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * @see java.util.Iterator#next()
+        */
+       public ComponentTag next()
+       {
+               return (index < markup.size() ? (ComponentTag)markup.get(index) 
: null);
+       }
+
+       /**
+        * 
+        * @return MarkupFragment
+        */
+       public final IMarkupFragment getMarkupFragment()
+       {
+               return new MarkupFragment(markup, index);
+       }
+
+       /**
+        * @see java.util.Iterator#remove()
+        */
+       public void remove()
+       {
+               throw new UnsupportedOperationException("remove() is not 
supported");
+       }
+}

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/WebMarkupContainerWithAssociatedMarkup.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/WebMarkupContainerWithAssociatedMarkup.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/WebMarkupContainerWithAssociatedMarkup.java
 (original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/WebMarkupContainerWithAssociatedMarkup.java
 Sat Nov 14 09:37:44 2009
@@ -17,6 +17,9 @@
 package org.apache.wicket.markup.html;
 
 import org.apache.wicket.Component;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.IMarkupFragment;
+import org.apache.wicket.markup.OpenTagIterator;
 import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
 import org.apache.wicket.model.IModel;
 
@@ -24,7 +27,6 @@
  * WebMarkupContainer with it's own markup and possibly <wicket:head> tag.
  * 
  * @author Juergen Donnerstag
- * 
  */
 public class WebMarkupContainerWithAssociatedMarkup extends WebMarkupContainer
        implements
@@ -81,4 +83,35 @@
        {
                return new HeaderPartContainer(id, this, scope);
        }
+
+       /**
+        * Search the child's markup in the header section of the markup
+        * 
+        * @param markup
+        * @param child
+        * @return Null, if not found
+        */
+       public IMarkupFragment findMarkupInAssociatedFileHeader(final 
IMarkupFragment markup,
+               final Component child)
+       {
+               IMarkupFragment childMarkup = null;
+               OpenTagIterator iter = new OpenTagIterator(markup);
+               while (iter.hasNext() && (childMarkup == null))
+               {
+                       ComponentTag tag = iter.next();
+                       if ((child != null) && "_header_".equals(tag.getId()))
+                       {
+                               childMarkup = 
iter.getMarkupFragment().find(child.getId(), 0);
+                       }
+                       else if ((child != null) && "_head".equals(tag.getId()))
+                       {
+                               if (tag.getMarkupClass() == null)
+                               {
+                                       childMarkup = 
iter.getMarkupFragment().find(child.getId(), 0);
+                               }
+                       }
+               }
+
+               return childMarkup;
+       }
 }
\ No newline at end of file

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/border/Border.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/border/Border.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/border/Border.java
 (original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/border/Border.java
 Sat Nov 14 09:37:44 2009
@@ -414,15 +414,27 @@
                        return new MarkupFragment(markup, i);
                }
 
+               IMarkupFragment childMarkup = null;
+
                // Since we created the body component instance, identifying 
that we found it is easy.
                if (child == body)
                {
                        // Find the markup for the child component. Make sure 
you use the preset default value.
-                       return markup.find(null, BODY_ID, i);
+                       childMarkup = markup.find(BODY_ID, i);
+                       if (childMarkup != null)
+                       {
+                               return childMarkup;
+                       }
                }
 
                // Find the markup for the child component
-               return markup.find(null, child.getId(), i);
+               childMarkup = markup.find(child.getId(), i);
+               if (childMarkup != null)
+               {
+                       return childMarkup;
+               }
+
+               return findMarkupInAssociatedFileHeader(markup, child);
        }
 
        /**
@@ -534,7 +546,7 @@
                                return markup;
                        }
 
-                       return markup.find(null, child.getId(), 0);
+                       return markup.find(child.getId(), 0);
                }
        }
 }

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponentPanel.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponentPanel.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponentPanel.java
 (original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponentPanel.java
 Sat Nov 14 09:37:44 2009
@@ -247,7 +247,7 @@
                }
 
                // Find <wicket:panel>
-               int index = markup.findComponentIndex(null, "_panel", 0);
+               int index = markup.findComponentIndex("_panel", 0);
                if (index == -1)
                {
                        throw new MarkupException(
@@ -262,6 +262,6 @@
                }
 
                // else, find the markup fragment for the child component
-               return markup.find(null, child.getId(), index);
+               return markup.find(child.getId(), index);
        }
 }

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java
 (original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java
 Sat Nov 14 09:37:44 2009
@@ -27,8 +27,8 @@
 import org.apache.wicket.Response;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.IMarkupFragment;
+import org.apache.wicket.markup.MarkupElement;
 import org.apache.wicket.markup.MarkupException;
-import org.apache.wicket.markup.MarkupFragment;
 import org.apache.wicket.markup.MarkupStream;
 import org.apache.wicket.markup.html.IHeaderResponse;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -350,16 +350,32 @@
                }
 
                // wicket id can be either "_header_" or "_head"
-               int index1 = markup.findComponentIndex(null, "_header_", 0);
-               int index2 = markup.findComponentIndex(null, "_head", 0);
-               if (((ComponentTag)markup.get(index2)).getMarkupClass() != null)
-               {
-                       index2 = -1;
-               }
-               int index = (index1 == -1 ? index2 : (index2 == -1) ? index1 : 
Math.min(index1, index2));
-               if (index >= 0)
+
+               // Find the markup fragment
+               MarkupStream stream = new MarkupStream(markup);
+               while (stream.hasMore())
                {
-                       return new MarkupFragment(markup, index);
+                       MarkupElement elem = stream.get();
+                       if (elem instanceof ComponentTag)
+                       {
+                               ComponentTag tag = stream.getTag();
+                               if (tag.isOpen() || tag.isOpenClose())
+                               {
+                                       if (tag.getId().equals("_header_"))
+                                       {
+                                               return 
stream.getMarkupFragment();
+                                       }
+                                       if (tag.getId().equals("_head"))
+                                       {
+                                               if (tag.getMarkupClass() == 
null)
+                                               {
+                                                       return 
stream.getMarkupFragment();
+                                               }
+                                       }
+                               }
+                       }
+
+                       stream.next();
                }
 
                return null;

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.html
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.html?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.html
 (original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.html
 Sat Nov 14 09:37:44 2009
@@ -44,6 +44,11 @@
                </p>
                <table><tr><td><pre><span class="markup" 
wicket:id="markup">markup goes here</span></pre></td></tr></table>
        </span>
+       
+       <span>
+               <h2>Stacktrace</h2>
+               <table><tr><td><pre><span class="markup" 
wicket:id="stacktrace">stacktrace goes here</span></pre></td></tr></table>
+       </span>
 
        <p>
          <a href="#" wicket:id="displayPageViewLink">display page view</a>

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.java
 (original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/pages/ExceptionErrorPage.java
 Sat Nov 14 09:37:44 2009
@@ -16,9 +16,13 @@
  */
 package org.apache.wicket.markup.html.pages;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.wicket.Page;
+import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.markup.MarkupException;
 import org.apache.wicket.markup.MarkupStream;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -28,7 +32,7 @@
 import org.apache.wicket.markup.html.debug.PageView;
 import org.apache.wicket.markup.html.link.Link;
 import org.apache.wicket.protocol.http.WebResponse;
-import org.apache.wicket.util.string.Strings;
+import org.apache.wicket.util.string.AppendingStringBuffer;
 
 
 /**
@@ -56,7 +60,9 @@
                this.throwable = throwable;
 
                // Add exception label
-               add(new MultiLineLabel("exception", 
Strings.toString(throwable)));
+               add(new MultiLineLabel("exception", 
getErrorMessage(throwable)));
+
+               add(new MultiLineLabel("stacktrace", getStackTrace(throwable)));
 
                // Get values
                String resource = "";
@@ -105,6 +111,140 @@
        }
 
        /**
+        * Converts a Throwable to a string.
+        * 
+        * @param throwable
+        *            The throwable
+        * @return The string
+        */
+       public String getErrorMessage(final Throwable throwable)
+       {
+               if (throwable != null)
+               {
+                       List<Throwable> al = convertToList(throwable);
+
+                       AppendingStringBuffer sb = new 
AppendingStringBuffer(256);
+
+                       // first print the last cause
+                       int length = al.size() - 1;
+                       Throwable cause = al.get(length);
+                       if (throwable instanceof WicketRuntimeException)
+                       {
+                               String msg = throwable.getMessage();
+                               if (throwable instanceof MarkupException)
+                               {
+                                       MarkupStream stream = 
((MarkupException)throwable).getMarkupStream();
+                                       if (stream != null)
+                                       {
+                                               String text = "\n" + 
stream.toString();
+                                               if (msg.endsWith(text))
+                                               {
+                                                       msg = msg.substring(0, 
msg.length() - text.length());
+                                               }
+                                       }
+                               }
+
+                               sb.append("WicketMessage: ");
+                               sb.append(msg);
+                               sb.append("\n\n");
+                       }
+                       return sb.toString();
+               }
+               else
+               {
+                       return "[Unknown]";
+               }
+       }
+
+       /**
+        * Converts a Throwable to a string.
+        * 
+        * @param throwable
+        *            The throwable
+        * @return The string
+        */
+       public String getStackTrace(final Throwable throwable)
+       {
+               if (throwable != null)
+               {
+                       List<Throwable> al = convertToList(throwable);
+
+                       AppendingStringBuffer sb = new 
AppendingStringBuffer(256);
+
+                       // first print the last cause
+                       int length = al.size() - 1;
+                       Throwable cause = al.get(length);
+
+                       sb.append("Root cause:\n\n");
+                       outputThrowable(cause, sb, false);
+
+                       if (length > 0)
+                       {
+                               sb.append("\n\nComplete stack:\n\n");
+                               for (int i = 0; i < length; i++)
+                               {
+                                       outputThrowable(al.get(i), sb, true);
+                                       sb.append("\n");
+                               }
+                       }
+                       return sb.toString();
+               }
+               else
+               {
+                       return "<Null Throwable>";
+               }
+       }
+
+       /**
+        * @param throwable
+        * @return xxx
+        */
+       private List<Throwable> convertToList(final Throwable throwable)
+       {
+               List<Throwable> al = new ArrayList<Throwable>();
+               Throwable cause = throwable;
+               al.add(cause);
+               while (cause.getCause() != null && cause != cause.getCause())
+               {
+                       cause = cause.getCause();
+                       al.add(cause);
+               }
+               return al;
+       }
+
+       /**
+        * Outputs the throwable and its stacktrace to the stringbuffer. If 
stopAtWicketSerlvet is true
+        * then the output will stop when the org.apache.wicket servlet is 
reached. sun.reflect.
+        * packages are filtered out.
+        * 
+        * @param cause
+        * @param sb
+        * @param stopAtWicketServlet
+        */
+       private void outputThrowable(Throwable cause, AppendingStringBuffer sb,
+               boolean stopAtWicketServlet)
+       {
+               sb.append(cause);
+               sb.append("\n");
+               StackTraceElement[] trace = cause.getStackTrace();
+               for (int i = 0; i < trace.length; i++)
+               {
+                       String traceString = trace[i].toString();
+                       if (!(traceString.startsWith("sun.reflect.") && i > 1))
+                       {
+                               sb.append("     at ");
+                               sb.append(traceString);
+                               sb.append("\n");
+                               if (stopAtWicketServlet &&
+                                       
(traceString.startsWith("org.apache.wicket.protocol.http.WicketServlet") || 
traceString.startsWith("org.apache.wicket.protocol.http.WicketFilter")))
+                               {
+                                       return;
+                               }
+                       }
+               }
+       }
+
+       /**
         * @see org.apache.wicket.markup.html.WebPage#configureResponse()
         */
        @Override

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java
 (original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Fragment.java
 Sat Nov 14 09:37:44 2009
@@ -20,6 +20,7 @@
 import org.apache.wicket.MarkupContainer;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.IMarkupFragment;
+import org.apache.wicket.markup.MarkupElement;
 import org.apache.wicket.markup.MarkupException;
 import org.apache.wicket.markup.MarkupNotFoundException;
 import org.apache.wicket.markup.MarkupStream;
@@ -203,13 +204,29 @@
         */
        private void renderFragment(final MarkupStream providerMarkupStream, 
final ComponentTag openTag)
        {
-               // remember the current position in the markup. Will have to 
come back
-               // to it.
+               // remember the current position in the markup. Will have to 
come back to it.
                int currentIndex = providerMarkupStream.getCurrentIndex();
 
                // Find the markup fragment
-               int index = providerMarkupStream.findComponentIndex(null, 
markupId);
-               if (index == -1)
+               while (providerMarkupStream.hasMore())
+               {
+                       MarkupElement elem = providerMarkupStream.get();
+                       if (elem instanceof ComponentTag)
+                       {
+                               ComponentTag tag = 
providerMarkupStream.getTag();
+                               if (tag.isOpen() || tag.isOpenClose())
+                               {
+                                       if (tag.getId().equals(markupId))
+                                       {
+                                               break;
+                                       }
+                               }
+                       }
+
+                       providerMarkupStream.nextOpenTag();
+               }
+
+               if (providerMarkupStream.hasMore() == false)
                {
                        throw new MarkupException("Markup of component class `" 
+
                                
providerMarkupStream.getContainerClass().getName() +
@@ -217,9 +234,6 @@
                                toString());
                }
 
-               // Set the markup stream position to where the fragment begins
-               providerMarkupStream.setCurrentIndex(index);
-
                try
                {
                        // Get the fragments open tag
@@ -245,27 +259,6 @@
        }
 
        /**
-        * Position the markup stream at the child component relative to the 
<b>provider</b> markup
-        * 
-        * @param path
-        * @return The markup stream for the given component.
-        */
-       public MarkupStream findComponentIndex(final String path)
-       {
-               MarkupStream markupStream = getAssociatedMarkupStream(true);
-               int index = markupStream.findComponentIndex(markupId, path);
-               if (index == -1)
-               {
-                       throw new MarkupException("Markup of component class `" 
+
-                               markupStream.getContainerClass().getName() +
-                               "` does not contain a fragment with wicket:id 
`" + markupId + "`. Context: " +
-                               toString());
-               }
-               markupStream.setCurrentIndex(index);
-               return markupStream;
-       }
-
-       /**
         * @see org.apache.wicket.MarkupContainer#hasAssociatedMarkup()
         */
        @Override
@@ -365,13 +358,13 @@
                        return null;
                }
 
-               markup = markup.find(null, markupId, 0);
+               markup = markup.find(markupId, 0);
 
                if (child == null)
                {
                        return markup;
                }
 
-               return markup.find(null, child.getId(), 0);
+               return markup.find(child.getId(), 0);
        }
 }

Modified: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Panel.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Panel.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Panel.java
 (original)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/panel/Panel.java
 Sat Nov 14 09:37:44 2009
@@ -156,7 +156,7 @@
                }
 
                // Find <wicket:panel>
-               int index = markup.findComponentIndex(null, "_panel", 0);
+               int index = markup.findComponentIndex("_panel", 0);
                if (index == -1)
                {
                        throw new MarkupNotFoundException(
@@ -171,6 +171,12 @@
                }
 
                // Find the markup for the child component
-               return markup.find(null, child.getId(), index);
+               IMarkupFragment childMarkup = markup.find(child.getId(), index);
+               if (childMarkup != null)
+               {
+                       return childMarkup;
+               }
+
+               return findMarkupInAssociatedFileHeader(markup, child);
        }
 }

Modified: 
wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/MarkupParserTest.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/MarkupParserTest.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/MarkupParserTest.java
 (original)
+++ 
wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/MarkupParserTest.java
 Sat Nov 14 09:37:44 2009
@@ -407,14 +407,11 @@
 
                ComponentTag t = (ComponentTag)markup.get(0);
                assertEquals(t.getId(), "span");
-               assertEquals(t.getPath(), null);
 
                t = (ComponentTag)markup.get(1);
                assertEquals(t.getId(), "img");
-               assertEquals(t.getPath(), "span");
 
                t = (ComponentTag)markup.get(2);
                assertEquals(t.getId(), "span2");
-               assertEquals(t.getPath(), "span");
        }
 }

Modified: 
wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/html/panel/InlinePanelPage_5.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/html/panel/InlinePanelPage_5.java?rev=836148&r1=836147&r2=836148&view=diff
==============================================================================
--- 
wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/html/panel/InlinePanelPage_5.java
 (original)
+++ 
wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/html/panel/InlinePanelPage_5.java
 Sat Nov 14 09:37:44 2009
@@ -80,7 +80,7 @@
                                return markup;
                        }
 
-                       return markup.find(null, child.getId(), 0);
+                       return markup.find(child.getId(), 0);
                }
        }
 }


Reply via email to