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 new file mode 100644 index 0000000000..4007952227 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/LinkBuilder.java @@ -0,0 +1,90 @@ +package sonia.scm.api.rest.resources; + +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; + +class LinkBuilder { + private final UriInfo uriInfo; + private final Class[] classes; + private final List calls; + + LinkBuilder(UriInfo uriInfo, Class... classes) { + this(uriInfo, classes, Collections.emptyList()); + } + + private LinkBuilder(UriInfo uriInfo, Class[] classes, List 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"); + } + return new Parameters(method); + } + + class Parameters { + + private final String method; + + private Parameters(String method) { + this.method = method; + } + + public LinkBuilder parameters(String... parameters) { + return LinkBuilder.this.add(method, parameters); + } + } + + 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) { + this.clazz = clazz; + this.method = method; + this.parameters = parameters; + } + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/LinkMapBuilder.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/LinkMapBuilder.java deleted file mode 100644 index 59d8c65ff7..0000000000 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/LinkMapBuilder.java +++ /dev/null @@ -1,108 +0,0 @@ -package sonia.scm.api.rest.resources; - -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; -import java.net.URI; -import java.util.*; - -class LinkMapBuilder { - private final UriInfo uriInfo; - private final Class[] classes; - private final Map links = new LinkedHashMap<>(); - - LinkMapBuilder(UriInfo uriInfo, Class... classes) { - this.uriInfo = uriInfo; - this.classes = classes; - } - - Builder add(String linkName) { - return new ConcreteBuilder(linkName); - } - - interface Builder { - Parameters method(String method); - } - - interface Parameters { - Builder parameters(String... parameters); - } - - private class ConcreteBuilder implements Builder { - - private final String linkName; - private final List calls = new LinkedList<>(); - - private int callCount = 0; - - ConcreteBuilder(String linkName) { - this.linkName = linkName; - } - - public Parameters method(String method) { - return new ParametersImpl(method); - } - - private class ParametersImpl implements Parameters { - - private final String method; - - ParametersImpl(String method) { - this.method = method; - } - - public Builder parameters(String... parameters) { - return ConcreteBuilder.this.add(method, parameters); - } - } - - private Builder add(String method, String[] parameters) { - this.calls.add(new Call(LinkMapBuilder.this.classes[callCount], method, parameters)); - ++callCount; - if (callCount >= classes.length) { - links.put(linkName, createLink()); - return x -> { - throw new IllegalStateException("no more classes for methods"); - }; - } - return this; - } - - private Link createLink() { - 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]); - } - } - - Map getLinkMap() { - return Collections.unmodifiableMap(links); - } - - private static class Call { - private final Class clazz; - private final String method; - private final String[] parameters; - - private Call(Class clazz, String method, String[] parameters) { - this.clazz = clazz; - this.method = method; - this.parameters = parameters; - } - } -} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/User2UserDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/User2UserDtoMapper.java index 3b1b38e31f..13d958e3aa 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/User2UserDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/User2UserDtoMapper.java @@ -24,17 +24,15 @@ public abstract class User2UserDtoMapper { @AfterMapping void appendLinks(@MappingTarget UserDto target, @Context UriInfo uriInfo) { - LinkMapBuilder userLinkBuilder = new LinkMapBuilder(uriInfo, UserNewResource.class, UserSubResource.class); - LinkMapBuilder collectionLinkBuilder = new LinkMapBuilder(uriInfo, UserNewResource.class, UserCollectionResource.class); - userLinkBuilder.add("self").method("getUserSubResource").parameters(target.getName()).method("get").parameters(); + LinkBuilder userLinkBuilder = new LinkBuilder(uriInfo, UserNewResource.class, UserSubResource.class); + LinkBuilder collectionLinkBuilder = new LinkBuilder(uriInfo, UserNewResource.class, UserCollectionResource.class); + Map links = new HashMap<>(); + links.put("self", userLinkBuilder.method("getUserSubResource").parameters(target.getName()).method("get").parameters().create()); if (SecurityUtils.getSubject().hasRole(Role.ADMIN)) { - userLinkBuilder.add("delete").method("getUserSubResource").parameters(target.getName()).method("delete").parameters(); - userLinkBuilder.add("update").method("getUserSubResource").parameters(target.getName()).method("update").parameters(); - collectionLinkBuilder.add("create").method("getUserCollectionResource").parameters().method("create").parameters(); + links.put("delete", userLinkBuilder.method("getUserSubResource").parameters(target.getName()).method("delete").parameters().create()); + links.put("update", userLinkBuilder.method("getUserSubResource").parameters(target.getName()).method("update").parameters().create()); + links.put("create", collectionLinkBuilder.method("getUserCollectionResource").parameters().method("create").parameters().create()); } - Map join = new HashMap<>(); - join.putAll(userLinkBuilder.getLinkMap()); - join.putAll(collectionLinkBuilder.getLinkMap()); - target.setLinks(join); + target.setLinks(links); } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserCollectionResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserCollectionResource.java index 66860ba7cd..254e65b5cb 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserCollectionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserCollectionResource.java @@ -73,9 +73,8 @@ public class UserCollectionResource extends AbstractManagerResource