>> P.S. I would also like URI buildMap(MultivaluedMap<String,?> values).
> Why ?
To support limited and unlimited placeholders.
I agree with draft-gregorio-uritemplate-03.txt<
http://tools.ietf.org/html/draft-gregorio-uritemplate-03> that a parameter value (as passed to UriBuilder.build*) should provide content to a URI, but not structure. That is, the UriBuilder.build* methods should %-escape any non-unreserved characters in a parameter value. In the following example, the resulting URI would always have a single path segment, regardless of any ‘/’ chars in the value passed to build().
UriBuilder.fromPath("{foo}").build("abc/123/def") -> "abc%2F123%2Fdef"
However, @Path templates can have “limited” and “unlimited” placeholders. %-escaping all non-unreserved chars provides good support for limited placeholder. build(MultivaluedMap) would provide good support for unlimited placeholders – multiple segments could be created by passing multiple values for the placeholder. In the following example, “foo” is mapped to 2 values so 2 path segments are created.
MultivaluedMap<String,String> values = …;
values.add("foo", "abc/123");
values.add("foo", "def");
UriBuilder.fromResource( @Path(value="{foo}", limited=false)).buildFromMap(values) -> "abc%2F123/def"
Possible javadoc text:
public abstract URI buildFromMap(MultivaluedMap<String,?> values)
Build a URI, replacing any placeholders with the values from the supplied map.
Each value is converted to a String using its toString method
then any non-unreserved characters are %-escaped (as per quote(String)).
For an unlimited placeholder (a trailing placeholder in an @Path annotation
with limited=false) multiple values are concatenated separated by ‘/’ characters.
For other (limited) placeholders multiple values are concatenated without
any separator.
For example:
@Path("{foo}")
public class Resource1 {…}
@Path(value="{foo}", limited=false)
public class Resource2 {…}
MultivaluedMap<String,String> values = …;
values.add("foo", "abc/123");
values.add("foo", "def");
URI u1 = UriBuilder.fromResource(Resource1.class).buildFromMap(values);
// builds "abc%2F123def"
URI u2 = UriBuilder.fromResource(Resource2.class).buildFromMap(values);
// builds "abc%2F123/def"
buildFromMap(MultivaluedMap) would also be useful for suppling multiple values for a query parameter – once the URI template syntax supports that. For instance, a template “stats?op=average{&n=number*}” could build “stats?op=average&n=23&n=3&n=98”.
P.S. It would be convenient to have a concrete implementation of MultivaluedMap in the API. Perhaps MultivaluedHashMap<K,V>.
James Manger