Add ability to clone to UriComponentsBuilder hierarchy

Issue: SPR-12494
This commit is contained in:
Rossen Stoyanchev
2014-12-05 12:14:16 -05:00
parent 2fccf3ff44
commit 189ec75789
4 changed files with 127 additions and 14 deletions

View File

@@ -54,7 +54,7 @@ import org.springframework.web.util.HierarchicalUriComponents.PathComponent;
* @see #fromPath(String)
* @see #fromUri(URI)
*/
public class UriComponentsBuilder {
public class UriComponentsBuilder implements Cloneable {
private static final Pattern QUERY_PARAM_PATTERN = Pattern.compile("([^&=]+)(=?)([^&]+)?");
@@ -98,7 +98,7 @@ public class UriComponentsBuilder {
private String port;
private CompositePathComponentBuilder pathBuilder = new CompositePathComponentBuilder();
private CompositePathComponentBuilder pathBuilder;
private final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
@@ -112,6 +112,22 @@ public class UriComponentsBuilder {
* @see #fromUri(URI)
*/
protected UriComponentsBuilder() {
this.pathBuilder = new CompositePathComponentBuilder();
}
/**
* Create a deep copy of the given UriComponentsBuilder.
* @param other the other builder to copy from
*/
protected UriComponentsBuilder(UriComponentsBuilder other) {
this.scheme = other.scheme;
this.ssp = other.ssp;
this.userInfo = other.userInfo;
this.host = other.host;
this.port = other.port;
this.pathBuilder = (CompositePathComponentBuilder) other.pathBuilder.clone();
this.queryParams.putAll(other.queryParams);
this.fragment = other.fragment;
}
@@ -627,16 +643,23 @@ public class UriComponentsBuilder {
return this;
}
@Override
protected Object clone() {
return new UriComponentsBuilder(this);
}
private interface PathComponentBuilder {
private interface PathComponentBuilder extends Cloneable {
PathComponent build();
Object clone();
}
private static class CompositePathComponentBuilder implements PathComponentBuilder {
private final LinkedList<PathComponentBuilder> componentBuilders = new LinkedList<PathComponentBuilder>();
private final LinkedList<PathComponentBuilder> builders = new LinkedList<PathComponentBuilder>();
public CompositePathComponentBuilder() {
}
@@ -651,7 +674,7 @@ public class UriComponentsBuilder {
FullPathComponentBuilder fpBuilder = getLastBuilder(FullPathComponentBuilder.class);
if (psBuilder == null) {
psBuilder = new PathSegmentComponentBuilder();
this.componentBuilders.add(psBuilder);
this.builders.add(psBuilder);
if (fpBuilder != null) {
fpBuilder.removeTrailingSlash();
}
@@ -669,7 +692,7 @@ public class UriComponentsBuilder {
}
if (fpBuilder == null) {
fpBuilder = new FullPathComponentBuilder();
this.componentBuilders.add(fpBuilder);
this.builders.add(fpBuilder);
}
fpBuilder.append(path);
}
@@ -677,8 +700,8 @@ public class UriComponentsBuilder {
@SuppressWarnings("unchecked")
private <T> T getLastBuilder(Class<T> builderClass) {
if (!this.componentBuilders.isEmpty()) {
PathComponentBuilder last = this.componentBuilders.getLast();
if (!this.builders.isEmpty()) {
PathComponentBuilder last = this.builders.getLast();
if (builderClass.isInstance(last)) {
return (T) last;
}
@@ -688,9 +711,9 @@ public class UriComponentsBuilder {
@Override
public PathComponent build() {
int size = this.componentBuilders.size();
int size = this.builders.size();
List<PathComponent> components = new ArrayList<PathComponent>(size);
for (PathComponentBuilder componentBuilder : this.componentBuilders) {
for (PathComponentBuilder componentBuilder : this.builders) {
PathComponent pathComponent = componentBuilder.build();
if (pathComponent != null) {
components.add(pathComponent);
@@ -704,6 +727,15 @@ public class UriComponentsBuilder {
}
return new HierarchicalUriComponents.PathComponentComposite(components);
}
@Override
public Object clone() {
CompositePathComponentBuilder compositeBuilder = new CompositePathComponentBuilder();
for (PathComponentBuilder builder : this.builders) {
compositeBuilder.builders.add((PathComponentBuilder) builder.clone());
}
return compositeBuilder;
}
}
@@ -737,6 +769,13 @@ public class UriComponentsBuilder {
this.path.deleteCharAt(index);
}
}
@Override
public Object clone() {
FullPathComponentBuilder builder = new FullPathComponentBuilder();
builder.append(this.path.toString());
return builder;
}
}
@@ -757,6 +796,13 @@ public class UriComponentsBuilder {
return (this.pathSegments.isEmpty() ? null :
new HierarchicalUriComponents.PathSegmentComponent(this.pathSegments));
}
@Override
public Object clone() {
PathSegmentComponentBuilder builder = new PathSegmentComponentBuilder();
builder.pathSegments.addAll(this.pathSegments);
return builder;
}
}
}