SPR-5973: Extract UriComponentTemplate out of UriTemplate

This commit is contained in:
Arjen Poutsma 2011-09-07 11:26:22 +00:00
parent 1d75e1b250
commit 420d11911b
3 changed files with 92 additions and 52 deletions

View File

@ -220,8 +220,8 @@ public class UriBuilder {
UriTemplate template; UriTemplate template;
if (scheme != null) { if (scheme != null) {
template = new UriTemplate(scheme, UriComponent.SCHEME); template = new UriComponentTemplate(scheme, UriComponent.SCHEME, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); uriBuilder.append(template.expandAsString(uriVariables));
uriBuilder.append(':'); uriBuilder.append(':');
} }
@ -229,14 +229,14 @@ public class UriBuilder {
uriBuilder.append("//"); uriBuilder.append("//");
if (StringUtils.hasLength(userInfo)) { if (StringUtils.hasLength(userInfo)) {
template = new UriTemplate(userInfo, UriComponent.USER_INFO); template = new UriComponentTemplate(userInfo, UriComponent.USER_INFO, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); uriBuilder.append(template.expandAsString(uriVariables));
uriBuilder.append('@'); uriBuilder.append('@');
} }
if (host != null) { if (host != null) {
template = new UriTemplate(host, UriComponent.HOST); template = new UriComponentTemplate(host, UriComponent.HOST, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); uriBuilder.append(template.expandAsString(uriVariables));
} }
if (port != -1) { if (port != -1) {
@ -256,20 +256,20 @@ public class UriBuilder {
else if (endsWithSlash && startsWithSlash) { else if (endsWithSlash && startsWithSlash) {
pathSegment = pathSegment.substring(1); pathSegment = pathSegment.substring(1);
} }
template = new UriTemplate(pathSegment, UriComponent.PATH_SEGMENT); template = new UriComponentTemplate(pathSegment, UriComponent.PATH_SEGMENT, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); uriBuilder.append(template.expandAsString(uriVariables));
} }
} }
if (queryBuilder.length() > 0) { if (queryBuilder.length() > 0) {
uriBuilder.append('?'); uriBuilder.append('?');
template = new UriTemplate(queryBuilder.toString(), UriComponent.QUERY); template = new UriComponentTemplate(queryBuilder.toString(), UriComponent.QUERY, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); uriBuilder.append(template.expandAsString(uriVariables));
} }
if (StringUtils.hasLength(fragment)) { if (StringUtils.hasLength(fragment)) {
uriBuilder.append('#'); uriBuilder.append('#');
template = new UriTemplate(fragment, UriComponent.FRAGMENT); template = new UriComponentTemplate(fragment, UriComponent.FRAGMENT, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); uriBuilder.append(template.expandAsString(uriVariables));
} }
return URI.create(uriBuilder.toString()); return URI.create(uriBuilder.toString());
@ -308,8 +308,8 @@ public class UriBuilder {
UriTemplate template; UriTemplate template;
if (scheme != null) { if (scheme != null) {
template = new UriTemplate(scheme, UriComponent.SCHEME); template = new UriComponentTemplate(scheme, UriComponent.SCHEME, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); uriBuilder.append(template.expandAsString(uriVariableValues));
uriBuilder.append(':'); uriBuilder.append(':');
} }
@ -317,14 +317,14 @@ public class UriBuilder {
uriBuilder.append("//"); uriBuilder.append("//");
if (StringUtils.hasLength(userInfo)) { if (StringUtils.hasLength(userInfo)) {
template = new UriTemplate(userInfo, UriComponent.USER_INFO); template = new UriComponentTemplate(userInfo, UriComponent.USER_INFO, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); uriBuilder.append(template.expandAsString(uriVariableValues));
uriBuilder.append('@'); uriBuilder.append('@');
} }
if (host != null) { if (host != null) {
template = new UriTemplate(host, UriComponent.HOST); template = new UriComponentTemplate(host, UriComponent.HOST, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); uriBuilder.append(template.expandAsString(uriVariableValues));
} }
if (port != -1) { if (port != -1) {
@ -344,21 +344,21 @@ public class UriBuilder {
else if (endsWithSlash && startsWithSlash) { else if (endsWithSlash && startsWithSlash) {
pathSegment = pathSegment.substring(1); pathSegment = pathSegment.substring(1);
} }
template = new UriTemplate(pathSegment, UriComponent.PATH_SEGMENT); template = new UriComponentTemplate(pathSegment, UriComponent.PATH_SEGMENT, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); uriBuilder.append(template.expandAsString(uriVariableValues));
} }
} }
if (queryBuilder.length() > 0) { if (queryBuilder.length() > 0) {
uriBuilder.append('?'); uriBuilder.append('?');
template = new UriTemplate(queryBuilder.toString(), UriComponent.QUERY); template = new UriComponentTemplate(queryBuilder.toString(), UriComponent.QUERY, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); uriBuilder.append(template.expandAsString(uriVariableValues));
} }
if (StringUtils.hasLength(fragment)) { if (StringUtils.hasLength(fragment)) {
uriBuilder.append('#'); uriBuilder.append('#');
template = new UriTemplate(fragment, UriComponent.FRAGMENT); template = new UriComponentTemplate(fragment, UriComponent.FRAGMENT, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); uriBuilder.append(template.expandAsString(uriVariableValues));
} }
return URI.create(uriBuilder.toString()); return URI.create(uriBuilder.toString());

View File

@ -0,0 +1,46 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed 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.springframework.web.util;
import org.springframework.util.Assert;
/**
* Subclass of {@link UriTemplate} that operates on URI components, rather than full URIs.
*
* @author Arjen Poutsma
* @since 3.1
*/
class UriComponentTemplate extends UriTemplate {
private final UriComponent uriComponent;
private boolean encodeUriVariableValues;
UriComponentTemplate(String uriTemplate, UriComponent uriComponent, boolean encodeUriVariableValues) {
super(uriTemplate);
Assert.notNull(uriComponent, "'uriComponent' must not be null");
this.uriComponent = uriComponent;
this.encodeUriVariableValues = encodeUriVariableValues;
}
@Override
protected String getVariableValueAsString(Object variableValue) {
String variableValueString = super.getVariableValueAsString(variableValue);
return encodeUriVariableValues ? UriUtils.encode(variableValueString, uriComponent, false) :
variableValueString;
}
}

View File

@ -56,8 +56,6 @@ public class UriTemplate implements Serializable {
private final String uriTemplate; private final String uriTemplate;
private final UriComponent uriComponent;
/** /**
* Construct a new {@link UriTemplate} with the given URI String. * Construct a new {@link UriTemplate} with the given URI String.
@ -68,19 +66,6 @@ public class UriTemplate implements Serializable {
this.uriTemplate = uriTemplate; this.uriTemplate = uriTemplate;
this.variableNames = parser.getVariableNames(); this.variableNames = parser.getVariableNames();
this.matchPattern = parser.getMatchPattern(); this.matchPattern = parser.getMatchPattern();
this.uriComponent = null;
}
/**
* Construct a new {@link UriTemplate} with the given URI String.
* @param uriTemplate the URI template string
*/
public UriTemplate(String uriTemplate, UriComponent uriComponent) {
Parser parser = new Parser(uriTemplate);
this.uriTemplate = uriTemplate;
this.variableNames = parser.getVariableNames();
this.matchPattern = parser.getMatchPattern();
this.uriComponent = uriComponent;
} }
/** /**
@ -110,7 +95,7 @@ public class UriTemplate implements Serializable {
* or if it does not contain values for all the variable names * or if it does not contain values for all the variable names
*/ */
public URI expand(Map<String, ?> uriVariables) { public URI expand(Map<String, ?> uriVariables) {
return encodeUri(expandAsString(false, uriVariables)); return encodeUri(expandAsString(uriVariables));
} }
/** /**
@ -125,13 +110,13 @@ public class UriTemplate implements Serializable {
* System.out.println(template.expand(uriVariables)); * System.out.println(template.expand(uriVariables));
* </pre> * </pre>
* will print: <blockquote><code>http://example.com/hotels/1/bookings/42</code></blockquote> * will print: <blockquote><code>http://example.com/hotels/1/bookings/42</code></blockquote>
* @param encodeUriVariableValues indicates whether uri template variables should be encoded or not *
* @param uriVariables the map of URI variables * @param uriVariables the map of URI variables
* @return the expanded URI * @return the expanded URI
* @throws IllegalArgumentException if <code>uriVariables</code> is <code>null</code>; * @throws IllegalArgumentException if <code>uriVariables</code> is <code>null</code>;
* or if it does not contain values for all the variable names * or if it does not contain values for all the variable names
*/ */
public String expandAsString(boolean encodeUriVariableValues, Map<String, ?> uriVariables) { public String expandAsString(Map<String, ?> uriVariables) {
Assert.notNull(uriVariables, "'uriVariables' must not be null"); Assert.notNull(uriVariables, "'uriVariables' must not be null");
Object[] values = new Object[this.variableNames.size()]; Object[] values = new Object[this.variableNames.size()];
for (int i = 0; i < this.variableNames.size(); i++) { for (int i = 0; i < this.variableNames.size(); i++) {
@ -141,7 +126,7 @@ public class UriTemplate implements Serializable {
} }
values[i] = uriVariables.get(name); values[i] = uriVariables.get(name);
} }
return expandAsString(encodeUriVariableValues, values); return expandAsString(values);
} }
/** /**
@ -159,7 +144,7 @@ public class UriTemplate implements Serializable {
* or if it does not contain sufficient variables * or if it does not contain sufficient variables
*/ */
public URI expand(Object... uriVariableValues) { public URI expand(Object... uriVariableValues) {
return encodeUri(expandAsString(false, uriVariableValues)); return encodeUri(expandAsString(uriVariableValues));
} }
/** /**
@ -171,13 +156,13 @@ public class UriTemplate implements Serializable {
* System.out.println(template.expand("1", "42)); * System.out.println(template.expand("1", "42));
* </pre> * </pre>
* will print: <blockquote><code>http://example.com/hotels/1/bookings/42</code></blockquote> * will print: <blockquote><code>http://example.com/hotels/1/bookings/42</code></blockquote>
* @param encodeVariableValues indicates whether uri template variables should be encoded or not *
* @param uriVariableValues the array of URI variables * @param uriVariableValues the array of URI variables
* @return the expanded URI * @return the expanded URI
* @throws IllegalArgumentException if <code>uriVariables</code> is <code>null</code> * @throws IllegalArgumentException if <code>uriVariables</code> is <code>null</code>
* or if it does not contain sufficient variables * or if it does not contain sufficient variables
*/ */
public String expandAsString(boolean encodeVariableValues, Object... uriVariableValues) { public String expandAsString(Object... uriVariableValues) {
Assert.notNull(uriVariableValues, "'uriVariableValues' must not be null"); Assert.notNull(uriVariableValues, "'uriVariableValues' must not be null");
if (uriVariableValues.length < this.variableNames.size()) { if (uriVariableValues.length < this.variableNames.size()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
@ -188,18 +173,27 @@ public class UriTemplate implements Serializable {
StringBuffer uriBuffer = new StringBuffer(); StringBuffer uriBuffer = new StringBuffer();
int i = 0; int i = 0;
while (matcher.find()) { while (matcher.find()) {
Object uriVariable = uriVariableValues[i++]; Object uriVariableValue = uriVariableValues[i++];
String uriVariableString = uriVariable != null ? uriVariable.toString() : ""; String uriVariableValueString = getVariableValueAsString(uriVariableValue);
if (encodeVariableValues && uriComponent != null) { String replacement = Matcher.quoteReplacement(uriVariableValueString);
uriVariableString = UriUtils.encode(uriVariableString, uriComponent, false);
}
String replacement = Matcher.quoteReplacement(uriVariableString);
matcher.appendReplacement(uriBuffer, replacement); matcher.appendReplacement(uriBuffer, replacement);
} }
matcher.appendTail(uriBuffer); matcher.appendTail(uriBuffer);
return uriBuffer.toString(); return uriBuffer.toString();
} }
/**
* Template method that returns the string representation of the given URI template value.
*
* <p>Defaults implementation simply calls {@link Object#toString()}, or returns an empty string for {@code null}.
*
* @param variableValue the URI template variable value
* @return the variable value as string
*/
protected String getVariableValueAsString(Object variableValue) {
return variableValue != null ? variableValue.toString() : "";
}
/** /**
* Indicate whether the given URI matches this template. * Indicate whether the given URI matches this template.
* @param uri the URI to match to * @param uri the URI to match to