From 38f05678c1d5f8c004d433c71f31c8e04681924b Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 14 Sep 2011 14:36:49 +0000 Subject: [PATCH] SPR-5973: UriComponents now encapsulates uri template variables --- .../web/util/UriComponents.java | 163 ++++++++---------- 1 file changed, 73 insertions(+), 90 deletions(-) diff --git a/org.springframework.web/src/main/java/org/springframework/web/util/UriComponents.java b/org.springframework.web/src/main/java/org/springframework/web/util/UriComponents.java index b57659c4c2..8827261dc6 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/util/UriComponents.java +++ b/org.springframework.web/src/main/java/org/springframework/web/util/UriComponents.java @@ -316,9 +316,26 @@ public final class UriComponents { * @param uriVariables the map of URI variables * @return the expanded uri components */ - public UriComponents expand(Map uriVariables) { - Assert.notNull(uriVariables, "'uriVariables' must not be null"); + public UriComponents expand(Map map) { + Assert.notNull(map, "'uriVariables' must not be null"); + return expandInternal(new MapTemplateVariables(map)); + } + + /** + * Replaces all URI template variables with the values from a given array. The array represent variable values. + * The order of variables is significant. + + * @param uriVariableValues URI variable values + * @return the expanded uri components + */ + public UriComponents expand(Object... uriVariableValues) { + Assert.notNull(uriVariableValues, "'uriVariableValues' must not be null"); + + return expandInternal(new VarArgsTemplateVariables(uriVariableValues)); + } + + private UriComponents expandInternal(UriTemplateVariables uriVariables) { String expandedScheme = expandUriComponent(this.scheme, uriVariables); String expandedUserInfo = expandUriComponent(this.userInfo, uriVariables); String expandedHost = expandUriComponent(this.host, uriVariables); @@ -340,7 +357,7 @@ public final class UriComponents { expandedQueryParams, expandedFragment, false); } - private static String expandUriComponent(String source, Map uriVariables) { + private static String expandUriComponent(String source, UriTemplateVariables uriVariables) { if (source == null) { return null; } @@ -352,71 +369,15 @@ public final class UriComponents { while (matcher.find()) { String match = matcher.group(1); String variableName = getVariableName(match); - Object variableValue = uriVariables.get(variableName); - String uriVariableValueString = getVariableValueAsString(variableValue); - String replacement = Matcher.quoteReplacement(uriVariableValueString); + Object variableValue = uriVariables.getValue(variableName); + String variableValueString = getVariableValueAsString(variableValue); + String replacement = Matcher.quoteReplacement(variableValueString); matcher.appendReplacement(sb, replacement); } matcher.appendTail(sb); return sb.toString(); } - /** - * Replaces all URI template variables with the values from a given array. The array represent variable values. - * The order of variables is significant. - - * @param uriVariableValues URI variable values - * @return the expanded uri components - */ - public UriComponents expand(Object... uriVariableValues) { - Assert.notNull(uriVariableValues, "'uriVariableValues' must not be null"); - - Iterator valueIterator = Arrays.asList(uriVariableValues).iterator(); - - String expandedScheme = expandUriComponent(this.scheme, valueIterator); - String expandedUserInfo = expandUriComponent(this.userInfo, valueIterator); - String expandedHost = expandUriComponent(this.host, valueIterator); - PathComponent expandedPath = path.expand(valueIterator); - MultiValueMap expandedQueryParams = - new LinkedMultiValueMap(this.queryParams.size()); - for (Map.Entry> entry : this.queryParams.entrySet()) { - String expandedName = expandUriComponent(entry.getKey(), valueIterator); - List expandedValues = new ArrayList(entry.getValue().size()); - for (String value : entry.getValue()) { - String expandedValue = expandUriComponent(value, valueIterator); - expandedValues.add(expandedValue); - } - expandedQueryParams.put(expandedName, expandedValues); - } - String expandedFragment = expandUriComponent(this.fragment, valueIterator); - - return new UriComponents(expandedScheme, expandedUserInfo, expandedHost, this.port, expandedPath, - expandedQueryParams, expandedFragment, false); - } - - private static String expandUriComponent(String source, Iterator valueIterator) { - if (source == null) { - return null; - } - if (source.indexOf('{') == -1) { - return source; - } - Matcher matcher = NAMES_PATTERN.matcher(source); - StringBuffer sb = new StringBuffer(); - while (matcher.find()) { - if (!valueIterator.hasNext()) { - throw new IllegalArgumentException("Not enough variable values available to expand [" + source + "]"); - } - Object variableValue = valueIterator.next(); - String uriVariableValueString = getVariableValueAsString(variableValue); - String replacement = Matcher.quoteReplacement(uriVariableValueString); - matcher.appendReplacement(sb, replacement); - } - matcher.appendTail(sb); - return sb.toString(); - } - - private static String getVariableName(String match) { int colonIdx = match.indexOf(':'); return colonIdx == -1 ? match : match.substring(0, colonIdx); @@ -426,10 +387,6 @@ public final class UriComponents { return variableValue != null ? variableValue.toString() : ""; } - - - - // other functionality /** @@ -722,9 +679,8 @@ public final class UriComponents { PathComponent encode(String encoding) throws UnsupportedEncodingException; - PathComponent expand(Map uriVariables); + PathComponent expand(UriTemplateVariables uriVariables); - PathComponent expand(Iterator valueIterator); } /** @@ -753,16 +709,11 @@ public final class UriComponents { return new FullPathComponent(encodedPath); } - public PathComponent expand(Map uriVariables) { + public PathComponent expand(UriTemplateVariables uriVariables) { String expandedPath = expandUriComponent(getPath(), uriVariables); return new FullPathComponent(expandedPath); } - public PathComponent expand(Iterator valueIterator) { - String expandedPath = expandUriComponent(getPath(), valueIterator); - return new FullPathComponent(expandedPath); - } - @Override public boolean equals(Object o) { if (this == o) { @@ -818,7 +769,7 @@ public final class UriComponents { return new PathSegmentComponent(encodedPathSegments); } - public PathComponent expand(Map uriVariables) { + public PathComponent expand(UriTemplateVariables uriVariables) { List pathSegments = getPathSegments(); List expandedPathSegments = new ArrayList(pathSegments.size()); for (String pathSegment : pathSegments) { @@ -828,16 +779,6 @@ public final class UriComponents { return new PathSegmentComponent(expandedPathSegments); } - public PathComponent expand(Iterator valueIterator) { - List pathSegments = getPathSegments(); - List expandedPathSegments = new ArrayList(pathSegments.size()); - for (String pathSegment : pathSegments) { - String expandedPathSegment = expandUriComponent(pathSegment, valueIterator); - expandedPathSegments.add(expandedPathSegment); - } - return new PathSegmentComponent(expandedPathSegments); - } - @Override public boolean equals(Object o) { if (this == o) { @@ -873,11 +814,7 @@ public final class UriComponents { return this; } - public PathComponent expand(Map uriVariables) { - return this; - } - - public PathComponent expand(Iterator valueIterator) { + public PathComponent expand(UriTemplateVariables uriVariables) { return this; } @@ -893,4 +830,50 @@ public final class UriComponents { }; + /** + * Defines the contract for URI Template variables + * + * @see UriComponents#expand + */ + private interface UriTemplateVariables { + + Object getValue(String name); + + + } + + /** + * URI template variables backed by a map. + */ + private static class MapTemplateVariables implements UriTemplateVariables { + + private final Map uriVariables; + + public MapTemplateVariables(Map uriVariables) { + this.uriVariables = uriVariables; + } + + public Object getValue(String name) { + return this.uriVariables.get(name); + } + } + + /** + * URI template variables backed by a variable argument array. + */ + private static class VarArgsTemplateVariables implements UriTemplateVariables { + private final Iterator valueIterator; + + public VarArgsTemplateVariables(Object... uriVariableValues) { + this.valueIterator = Arrays.asList(uriVariableValues).iterator(); + } + + public Object getValue(String name) { + if (!valueIterator.hasNext()) { + throw new IllegalArgumentException("Not enough variable values available to expand [" + name + "]"); + } + return valueIterator.next(); + } + } + }