Repository: wicket
Updated Branches:
  refs/heads/wicket-6.x 13e5d202c -> c6f3efb72


WICKET-6278 improved support for void elements


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

Branch: refs/heads/wicket-6.x
Commit: c6f3efb72f830088f4fa22f7d9a27a5a2b1f3136
Parents: 13e5d20
Author: Sven Meier <svenme...@apache.org>
Authored: Thu Nov 17 16:53:27 2016 +0100
Committer: Sven Meier <svenme...@apache.org>
Committed: Thu Nov 17 17:01:56 2016 +0100

----------------------------------------------------------------------
 .../apache/wicket/util/tester/TagTester.java    | 319 +++++++------------
 .../wicket/util/tester/TagTesterTest.java       |  12 +-
 2 files changed, 132 insertions(+), 199 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/c6f3efb7/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java 
b/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java
index 3220cae..310530b 100644
--- a/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java
+++ b/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java
@@ -17,8 +17,9 @@
 package org.apache.wicket.util.tester;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
+import java.util.Stack;
 import java.util.regex.Pattern;
 
 import org.apache.wicket.WicketRuntimeException;
@@ -359,6 +360,11 @@ public class TagTester
         */
        public String getValue()
        {
+               if (openTag == closeTag)
+               {
+                       return null;
+               }
+               
                int openPos = openTag.getPos() + openTag.getLength();
                int closePos = closeTag.getPos();
 
@@ -370,85 +376,40 @@ public class TagTester
         * that it will return the first tag which matches the criteria.
         *
         * @param markup
-        *            the markup to look for the tag to create the 
<code>TagTester</code> from
-        *            the value which the attribute must have
+        *            the markup to look for the tag to create the 
<code>TagTester</code> from the value
+        *            which the attribute must have
         * @return the <code>TagTester</code> which matches the tag by name in 
the markup
         */
-       public static TagTester createTagByAttribute(String markup, String 
tagName)
+       public static TagTester createTagByName(String markup, final String 
tagName)
        {
-               TagTester tester = null;
-
-               if (Strings.isEmpty(markup) == false && 
Strings.isEmpty(tagName) == false)
-               {
-                       try
-                       {
-                               // remove the CDATA and
-                               // the id attribute of the component because it 
is often the same as the element's id
-                               markup = 
AJAX_COMPONENT_CDATA_OPEN.matcher(markup).replaceAll("<component>");
-                               markup = 
AJAX_COMPONENT_CDATA_CLOSE.matcher(markup).replaceAll("</component>");
-
-                               XmlPullParser parser = new XmlPullParser();
-                               parser.parse(markup);
-
-                               XmlTag elm;
-                               XmlTag openTag = null;
-                               XmlTag closeTag = null;
-                               int level = 0;
-                               while ((elm = parser.nextTag()) != null && 
closeTag == null)
-                               {
-                                       XmlTag xmlTag = elm;
-
-                                       String xmlTagName = xmlTag.getName();
-                                       if (openTag == null && 
xmlTagName.equalsIgnoreCase(tagName))
-                                       {
-                                               if (xmlTag.isOpen())
-                                               {
-                                                       openTag = xmlTag;
-                                               }
-                                               else if (xmlTag.isOpenClose())
-                                               {
-                                                       openTag = xmlTag;
-                                                       closeTag = xmlTag;
-                                               }
-                                       }
-                                       else if (openTag != null)
-                                       {
-                                               String openTagName = 
openTag.getName();
-                                               if (xmlTag.isOpen() && 
xmlTagName.equals(openTagName))
-                                               {
-                                                       level++;
-                                               }
-
-                                               if (xmlTag.isClose())
-                                               {
-                                                       if 
(xmlTagName.equals(openTagName))
-                                                       {
-                                                               if (level == 0)
-                                                               {
-                                                                       
closeTag = xmlTag;
-                                                                       
closeTag.setOpenTag(openTag);
-                                                               }
-                                                               else
-                                                               {
-                                                                       level--;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               if (openTag != null && closeTag != null)
-                               {
-                                       tester = new TagTester(parser, openTag, 
closeTag);
-                               }
-                       }
-                       catch (Exception e)
-                       {
-                               throw new WicketRuntimeException(e);
+               List<TagTester> tester = createTags(markup, new 
Predicate<XmlTag>() {
+                       @Override
+                       public boolean apply(XmlTag xmlTag) {
+                               return 
xmlTag.getName().equalsIgnoreCase(tagName);
                        }
+               }, true);
+               if ((tester == null) || (tester.size() == 0))
+               {
+                       return null;
                }
+               return tester.get(0);
+       }
 
-               return tester;
+       /**
+        * Static factory method for creating a <code>TagTester</code> based on 
a tag name. Please note
+        * that it will return the first tag which matches the criteria.
+        *
+        * @param markup
+        *            the markup to look for the tag to create the 
<code>TagTester</code> from
+        *            the value which the attribute must have
+        * @return the <code>TagTester</code> which matches the tag by name in 
the markup
+        * 
+        * @deprecated use {@link #createTagByName(String, String)} instead
+        */
+       @Deprecated
+       public static TagTester createTagByAttribute(String markup, String 
tagName)
+       {
+               return createTagByName(markup, tagName);
        }
 
        /**
@@ -468,91 +429,12 @@ public class TagTester
         */
        public static TagTester createTagByAttribute(String markup, String 
attribute, String value)
        {
-               TagTester tester = null;
-
-               if (Strings.isEmpty(markup) == false && 
Strings.isEmpty(attribute) == false &&
-                       Strings.isEmpty(value) == false)
+               List<TagTester> tester = createTagsByAttribute(markup, 
attribute, value, true);
+               if ((tester == null) || (tester.size() == 0))
                {
-                       try
-                       {
-                               // remove the CDATA and
-                               // the id attribute of the component because it 
is often the same as the element's id
-                               markup = 
AJAX_COMPONENT_CDATA_OPEN.matcher(markup).replaceAll("<component>");
-                               markup = 
AJAX_COMPONENT_CDATA_CLOSE.matcher(markup).replaceAll("</component>");
-
-                               XmlPullParser parser = new XmlPullParser();
-                               parser.parse(markup);
-
-                               XmlTag elm;
-                               XmlTag openTag = null;
-                               XmlTag closeTag = null;
-                               int level = 0;
-                               while ((elm = parser.nextTag()) != null && 
closeTag == null)
-                               {
-                                       XmlTag xmlTag = elm;
-
-                                       if (openTag == null)
-                                       {
-                                               IValueMap attributeMap = 
xmlTag.getAttributes();
-
-                                               for (Map.Entry<String, Object> 
entry : attributeMap.entrySet())
-                                               {
-                                                       String attr = 
entry.getKey();
-                                                       if 
(attr.equals(attribute) && value.equals(entry.getValue()))
-                                                       {
-                                                               if 
(xmlTag.isOpen())
-                                                               {
-                                                                       openTag 
= xmlTag;
-                                                               }
-                                                               else if 
(xmlTag.isOpenClose())
-                                                               {
-                                                                       openTag 
= xmlTag;
-                                                                       
closeTag = xmlTag;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                                       else
-                                       {
-                                               if (xmlTag.isOpen() && 
xmlTag.getName().equals(openTag.getName()))
-                                               {
-                                                       level++;
-                                               }
-
-                                               if (xmlTag.isClose())
-                                               {
-                                                       if 
(xmlTag.getName().equals(openTag.getName()))
-                                                       {
-                                                               if (level == 0)
-                                                               {
-                                                                       
closeTag = xmlTag;
-                                                                       
closeTag.setOpenTag(openTag);
-                                                               }
-                                                               else
-                                                               {
-                                                                       level--;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               if (openTag != null && closeTag != null)
-                               {
-                                       tester = new TagTester(parser, openTag, 
closeTag);
-                               }
-                               else if (openTag != null)
-                               {
-                                       tester = new TagTester(parser, openTag, 
openTag);
-                               }
-                       }
-                       catch (Exception e)
-                       {
-                               throw new WicketRuntimeException(e);
-                       }
+                       return null;
                }
-
-               return tester;
+               return tester.get(0);
        }
 
        /**
@@ -570,14 +452,10 @@ public class TagTester
         * @return the <code>TagTester</code> which matches the tag in the 
markup, that has the given
         *         value on the given attribute
         */
+       @Deprecated
        public static TagTester createTagsByAttribute(String markup, String 
attribute, String value)
        {
-               List<TagTester> tester = createTagsByAttribute(markup, 
attribute, value, true);
-               if ((tester == null) || (tester.size() == 0))
-               {
-                       return null;
-               }
-               return tester.get(0);
+               return createTagByAttribute(markup, attribute, value);
        }
 
        /**
@@ -597,13 +475,25 @@ public class TagTester
         * @return the <code>TagTester</code> which matches the tag in the 
markup, that has the given
         *         value on the given attribute
         */
-       public static List<TagTester> createTagsByAttribute(String markup, 
String attribute,
-               String value, boolean stopAfterFirst)
+       public static List<TagTester> createTagsByAttribute(String markup, 
final String attribute,
+               final String value, boolean stopAfterFirst)
+       {
+               if (Strings.isEmpty(attribute) || Strings.isEmpty(value)) {
+                       return Collections.emptyList();
+               }
+               
+               return createTags(markup, new Predicate<XmlTag>() {
+                       public boolean apply(XmlTag xmlTag) {
+                               return 
value.equals(xmlTag.getAttributes().get(attribute));
+                       }
+                       }, stopAfterFirst);
+       }
+       
+       private static List<TagTester> createTags(String markup, 
Predicate<XmlTag> accept, boolean stopAfterFirst)
        {
                List<TagTester> testers = new ArrayList<TagTester>();
 
-               if ((Strings.isEmpty(markup) == false) && 
(Strings.isEmpty(attribute) == false) &&
-                       (Strings.isEmpty(value) == false))
+               if ((Strings.isEmpty(markup) == false))
                {
                        try
                        {
@@ -615,70 +505,74 @@ public class TagTester
                                XmlPullParser parser = new XmlPullParser();
                                parser.parse(markup);
 
-                               XmlTag elm;
                                XmlTag openTag = null;
                                XmlTag closeTag = null;
-                               int level = 0;
-                               while ((elm = parser.nextTag()) != null)
+
+                               // temporary Tag-Hierarchy after openTag
+                               Stack<XmlTag> stack = new Stack<XmlTag>();
+
+                               while (true)
                                {
-                                       XmlTag xmlTag = elm;
+                                       XmlTag xmlTag = parser.nextTag();
+                                       if (xmlTag == null)
+                                       {
+                                               break;
+                                       }
+                                       
                                        if (openTag == null)
                                        {
-                                               IValueMap attributeMap = 
xmlTag.getAttributes();
-                                               for (Map.Entry<String, Object> 
entry : attributeMap.entrySet())
+                                               if (accept.apply(xmlTag))
                                                {
-                                                       if 
(entry.getKey().equals(attribute) && value.equals(entry.getValue()))
+                                                       if (xmlTag.isOpen())
                                                        {
-                                                               if 
(xmlTag.isOpen())
-                                                               {
-                                                                       openTag 
= xmlTag;
-                                                               }
-                                                               else if 
(xmlTag.isOpenClose())
-                                                               {
-                                                                       openTag 
= xmlTag;
-                                                                       
closeTag = xmlTag;
-                                                               }
+                                                               openTag = 
xmlTag;
+                                                       }
+                                                       else if 
(xmlTag.isOpenClose())
+                                                       {
+                                                               openTag = 
xmlTag;
+                                                               closeTag = 
xmlTag;
                                                        }
                                                }
                                        }
                                        else
                                        {
-                                               if (xmlTag.isOpen() && 
xmlTag.getName().equals(openTag.getName()))
+                                               if (xmlTag.isOpen() && 
!xmlTag.isOpenClose())
                                                {
-                                                       level++;
+                                                       stack.push(xmlTag);
                                                }
-
                                                if (xmlTag.isClose())
                                                {
-                                                       if 
(xmlTag.getName().equals(openTag.getName()))
+                                                       XmlTag foundTag = 
findOpenTag(xmlTag, stack);
+                                                       if (foundTag == null)
                                                        {
-                                                               if (level == 0)
+                                                               if 
(xmlTag.getName().equals(openTag.getName()))
                                                                {
                                                                        
closeTag = xmlTag;
                                                                        
closeTag.setOpenTag(openTag);
                                                                }
+                                                               else if 
(HtmlHandler.requiresCloseTag(openTag.getName()) == false)
+                                                               {
+                                                                       // no 
closeTag for current openTag (allowed)
+                                                                       
closeTag = openTag;
+                                                               }
                                                                else
                                                                {
-                                                                       level--;
+                                                                       // no 
closeTag for current openTag (invalid structure)
+                                                                       // thus 
reset state
+                                                                       openTag 
= null;
+                                                                       
closeTag = null;
                                                                }
                                                        }
                                                }
                                        }
 
-                                       if ((openTag != null) && (closeTag != 
null) && (level == 0))
+                                       if ((openTag != null) && (closeTag != 
null))
                                        {
                                                TagTester tester = new 
TagTester(parser, openTag, closeTag);
                                                testers.add(tester);
                                                openTag = null;
                                                closeTag = null;
                                        }
-                                       else if (openTag != null && 
!HtmlHandler.requiresCloseTag(openTag.getName()))
-                                       {
-                                               TagTester tester = new 
TagTester(parser, openTag, openTag);
-                                               testers.add(tester);
-                                               openTag = null;
-                                               closeTag = null;
-                                       }
 
                                        if (stopAfterFirst && (closeTag != 
null))
                                        {
@@ -694,4 +588,33 @@ public class TagTester
 
                return testers;
        }
-}
+
+       /**
+        * find the correct openTag to the given closeTag and remove all 
unclosed openTags between both
+        * in given array {@code stack}
+        * 
+        * @param closeTag
+        *            tag to search for corresponding openTag
+        * @param stack
+        *            array of unclosed openTags
+        * @return corresponding openTag or {@code null}
+        */
+       private static XmlTag findOpenTag(XmlTag closeTag, Stack<XmlTag> stack)
+       {
+               while (stack.size() > 0)
+               {
+                       XmlTag popped = stack.pop();
+                       if (popped.getName().equals(closeTag.getName()))
+                       {
+                               return popped;
+                       }
+               }
+               return null;
+       }
+
+       // Remove when migration to Java 8 is completed
+       private interface Predicate<T>
+       {
+               boolean apply(T t);
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/c6f3efb7/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java 
b/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java
index e7863a8..8834e4a 100644
--- a/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java
@@ -38,7 +38,17 @@ public class TagTesterTest extends Assert
                        "<ajax-response><component id='comp1'><![CDATA[<div 
class='cls' id='compId'></div>]]></component></ajax-response>";
 
        // WICKET-5874
-       private static final String NON_CLOSED_INPUT = "<p><input 
wicket:id=\"wicketId\" type=\"text\"></p>";
+       private static final String NON_CLOSED_INPUT = "<p 
wicket:id=\"p\"><input wicket:id=\"wicketId\" type=\"text\"></p>";
+
+       /**
+        * WICKET-6278
+        */
+       @Test
+       public void tagNoRequiredClose() {
+               TagTester tester = 
TagTester.createTagByAttribute(NON_CLOSED_INPUT, "wicket:id", "p");
+
+               assertEquals("<input wicket:id=\"wicketId\" type=\"text\">", 
tester.getValue());
+       }
 
        /**
         * https://issues.apache.org/jira/browse/WICKET-5874

Reply via email to