diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/LinkBuilder.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/LinkBuilder.java
index 4007952227..721838da08 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/LinkBuilder.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/LinkBuilder.java
@@ -1,29 +1,43 @@
package sonia.scm.api.rest.resources;
+import com.google.common.collect.ImmutableList;
+
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
+/**
+ * This class is used to create links for JAX-RS resources. Create a new instance specifying all resource classes used
+ * to process the request. Than for each of these classes call builder.method(...).parameters(...) for each
+ * of these classes consecutively. The builder itself is immutable, so that each instance is reusable and you get a new
+ * builder for each method.
+ *
+ *
+ * LinkBuilder builder = new LinkBuilder(uriInfo, MainResource.class, SubResource.class);
+ * Link link = builder
+ * .method("sub")
+ * .parameters("param")
+ * .method("x")
+ * .parameters("param_1", "param_2")
+ * .create();
+ *
+ */
class LinkBuilder {
private final UriInfo uriInfo;
private final Class[] classes;
- private final List calls;
+ private final ImmutableList calls;
LinkBuilder(UriInfo uriInfo, Class... classes) {
- this(uriInfo, classes, Collections.emptyList());
+ this(uriInfo, classes, ImmutableList.of());
}
- private LinkBuilder(UriInfo uriInfo, Class[] classes, List calls) {
+ private LinkBuilder(UriInfo uriInfo, Class[] classes, ImmutableList calls) {
this.uriInfo = uriInfo;
this.classes = classes;
this.calls = calls;
}
-
public Parameters method(String method) {
if (calls.size() >= classes.length) {
throw new IllegalStateException("no more classes for methods");
@@ -31,6 +45,44 @@ class LinkBuilder {
return new Parameters(method);
}
+ public Link create() {
+ if (calls.size() < classes.length) {
+ throw new IllegalStateException("not enough methods for all classes");
+ }
+
+ URI baseUri = uriInfo.getBaseUri();
+ URI relativeUri = createRelativeUri();
+ URI absoluteUri = baseUri.resolve(relativeUri);
+ return new Link(absoluteUri);
+ }
+
+ private LinkBuilder add(String method, String[] parameters) {
+ return new LinkBuilder(uriInfo, classes, appendNewCall(method, parameters));
+ }
+
+ private ImmutableList appendNewCall(String method, String[] parameters) {
+ return ImmutableList. builder().addAll(calls).add(createNewCall(method, parameters)).build();
+ }
+
+ private Call createNewCall(String method, String[] parameters) {
+ return new Call(LinkBuilder.this.classes[calls.size()], method, parameters);
+ }
+
+ private URI createRelativeUri() {
+ UriBuilder uriBuilder = userUriBuilder();
+ calls.forEach(call -> uriBuilder.path(call.clazz, call.method));
+ String[] concatenatedParameters = calls
+ .stream()
+ .map(call -> call.parameters)
+ .flatMap(Arrays::stream)
+ .toArray(String[]::new);
+ return uriBuilder.build((Object[]) concatenatedParameters);
+ }
+
+ private UriBuilder userUriBuilder() {
+ return UriBuilder.fromResource(classes[0]);
+ }
+
class Parameters {
private final String method;
@@ -44,41 +96,10 @@ class LinkBuilder {
}
}
- private LinkBuilder add(String method, String[] parameters) {
- List newCalls = new ArrayList<>(this.calls);
- newCalls.add(new Call(LinkBuilder.this.classes[calls.size()], method, parameters));
- return new LinkBuilder(uriInfo, classes, newCalls);
- }
-
- public Link create() {
- if (calls.size() < classes.length) {
- throw new IllegalStateException("not enough methods for all classes");
- }
-
- URI baseUri = uriInfo.getBaseUri();
- URI relativeUri = createRelativeUri();
- URI absoluteUri = baseUri.resolve(relativeUri);
- return new Link(absoluteUri);
- }
-
- private URI createRelativeUri() {
- UriBuilder uriBuilder = userUriBuilder();
- calls.forEach(call -> uriBuilder.path(call.clazz, call.method));
- String[] concatenatedParameters = calls
- .stream()
- .map(call -> call.parameters)
- .flatMap(Arrays::stream)
- .toArray(String[]::new);
- return uriBuilder.build(concatenatedParameters);
- }
-
- private UriBuilder userUriBuilder() {
- return UriBuilder.fromResource(classes[0]);
- }
-
private static class Call {
private final Class clazz;
private final String method;
+
private final String[] parameters;
private Call(Class clazz, String method, String[] parameters) {