Updated Branches:
  refs/heads/5.3 6fa4b39eb -> a0987747d

FIXED - TAP5-2063: Add support for multivalued parameters in Link 
- apply Alejandro Scandroli's patch + test with modifications


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

Branch: refs/heads/5.3
Commit: a0987747db84756f8fc68ae65f9f902adff74618
Parents: 6fa4b39
Author: kaosko <[email protected]>
Authored: Sun Apr 14 00:07:12 2013 -0700
Committer: kaosko <[email protected]>
Committed: Sun Apr 14 00:07:12 2013 -0700

----------------------------------------------------------------------
 .../src/main/java/org/apache/tapestry5/Link.java   |   15 ++++-
 .../apache/tapestry5/corelib/components/Form.java  |   27 +++++---
 .../tapestry5/internal/services/LinkImpl.java      |   48 ++++++++++----
 .../tapestry5/internal/services/LinkImplTest.java  |   27 ++++++++
 4 files changed, 91 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0987747/tapestry-core/src/main/java/org/apache/tapestry5/Link.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/Link.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/Link.java
index e08dde0..aa4336d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/Link.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/Link.java
@@ -45,7 +45,13 @@ public interface Link
      * Returns the value of a specifically named query parameter, or 
<tt>null</tt> if no such query parameter is stored
      * in the link.
      *
-     * @return the string value of the named parameter
+     * <p>Use this method only when you are sure the parameter has only one 
value. If the parameter might have more than
+     * one value, use {@link #getParameterValues}.
+     *
+     * <p>If you use this method with a multivalued parameter, the value 
returned is equal to the first value in the
+     * array returned by <code>getParameterValues</code>.
+     *
+     * @return a string representing the single value of the named parameter
      */
     String getParameterValue(String name);
 
@@ -55,7 +61,6 @@ public interface Link
      *
      * @param parameterName the name of the parameter to store
      * @param value         the value to store, a null or blank value is 
allowed (as of Tapestry 5.3)
-     * @throws IllegalArgumentException if the link already has a parameter 
with the given name
      */
     void addParameter(String parameterName, String value);
 
@@ -155,4 +160,10 @@ public interface Link
      * @since 5.3
      */
     LinkSecurity getSecurity();
+
+    /**
+     * Returns the parameter values for the given name. Returns null if no 
such parameter is stored in the link.
+     */
+    String[] getParameterValues(String parameterName);
+
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0987747/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
----------------------------------------------------------------------
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
index 5a08e21..d183217 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
@@ -395,18 +395,25 @@ public class Form implements ClientElement, 
FormValidationControl
 
         for (String parameterName : link.getParameterNames())
         {
-            String value = link.getParameterValue(parameterName);
-            // The parameter value is expected to be encoded,
-            // but the input value shouldn't be encoded.
-            try
-            {
-                value = URLDecoder.decode(value, "UTF-8");
-            } catch (UnsupportedEncodingException e)
+            String[] values = link.getParameterValues(parameterName);
+
+            for (String value : values)
             {
-                logger.error("Enable to decode parameter value", e);
+                // The parameter value is expected to be encoded,
+                // but the input value shouldn't be encoded.
+                try
+                {
+                    value = URLDecoder.decode(value, "UTF-8");
+                }
+                catch (UnsupportedEncodingException e)
+                {
+                    logger.error(String.format(
+                            "Enable to decode parameter value for parameter %s 
in form %s",
+                            parameterName, form.getName()), e);
+                }
+                writer.element("input", "type", "hidden", "name", 
parameterName, "value", value);
+                writer.end();
             }
-            writer.element("input", "type", "hidden", "name", parameterName, 
"value", value);
-            writer.end();
         }
 
         writer.end(); // div

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0987747/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java
----------------------------------------------------------------------
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java
index 52f4403..4a5075e 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java
@@ -15,18 +15,19 @@
 package org.apache.tapestry5.internal.services;
 
 import org.apache.tapestry5.Link;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.services.BaseURLSource;
 import org.apache.tapestry5.services.ContextPathEncoder;
 import org.apache.tapestry5.services.Response;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
 
 public class LinkImpl implements Link
 {
-    private Map<String, String> parameters;
+       private Map<String, List<String>> parameters;
 
     private final String basePath;
 
@@ -63,20 +64,29 @@ public class LinkImpl implements Link
 
         for (String name : getParameterNames())
         {
-            copy.addParameter(name, parameters.get(name));
+            copy.addParameter(name, getParameterValues(name));
         }
 
         return copy;
     }
 
+    private void addParameter(String parameterName, String[] value)
+    {
+        assert InternalUtils.isNonBlank(parameterName);
+        if (parameters == null)
+            parameters = new TreeMap<String, List<String>>();
+
+        parameters.put(parameterName, Arrays.asList(value));
+    }
+
     public void addParameter(String parameterName, String value)
     {
         assert InternalUtils.isNonBlank(parameterName);
 
         if (parameters == null)
-            parameters = CollectionFactory.newMap();
+            parameters = new TreeMap<String, List<String>>();
 
-        parameters.put(parameterName, value == null ? "" : value);
+        InternalUtils.addToMapList(parameters, parameterName, value == null ? 
"" : value);
     }
 
     public String getBasePath()
@@ -103,7 +113,8 @@ public class LinkImpl implements Link
 
     public String getParameterValue(String name)
     {
-        return InternalUtils.get(parameters, name);
+        List<String> values = InternalUtils.get(parameters, name);
+        return values != null && !values.isEmpty() ? values.get(0) : null;
     }
 
     public void setAnchor(String anchor)
@@ -198,18 +209,21 @@ public class LinkImpl implements Link
 
             for (String name : getParameterNames())
             {
-                String value = parameters.get(name);
+                List<String> values = parameters.get(name);
 
-                builder.append(sep);
+                for (String value : values)
+                {
+                    builder.append(sep);
 
-                // We assume that the name is URL safe and that the value will 
already have been URL
-                // encoded if it is not known to be URL safe.
+                    // We assume that the name is URL safe and that the value 
will already have been URL
+                    // encoded if it is not known to be URL safe.
 
-                builder.append(name);
-                builder.append("=");
-                builder.append(value);
+                    builder.append(name);
+                    builder.append("=");
+                    builder.append(value);
 
-                sep = "&";
+                    sep = "&";
+                }
             }
         }
 
@@ -223,4 +237,10 @@ public class LinkImpl implements Link
         return this;
     }
 
+    public String[] getParameterValues(String parameterName)
+    {
+        List<String> values = InternalUtils.get(parameters, parameterName);
+        return values.toArray(new String[values.size()]);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0987747/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java
----------------------------------------------------------------------
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java
index 14948b1..5d861d6 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java
@@ -284,6 +284,33 @@ public class LinkImplTest extends InternalBaseTestCase
         verify();
     }
 
+    /**
+     * TAP5-2063
+     */
+    @Test
+    public void multivalued_parameter_support()
+    {
+        Response response = mockResponse();
+
+        String expectedURI = 
"/ctx?barney=&barney=foo&barney=bar&barney=baz&fred=flintstone";
+        train_encodeURL(response, expectedURI, expectedURI);
+
+        replay();
+
+        Link link = new LinkImpl("/ctx", false, LinkSecurity.INSECURE, 
response, null, null);
+
+        link.addParameter("fred", "flintstone");
+        link.addParameter("barney", null);
+        link.addParameter("barney", "foo");
+        link.addParameter("barney", "bar");
+        link.addParameter("barney", "baz");
+
+        assertEquals(link.toURI(), expectedURI);
+
+        verify();
+    }
+
+
     @Test
     public void force_link_to_secure()
     {

Reply via email to