diff --git a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/resourcelists/ResourceComparatorGenerator.java b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/resourcelists/ResourceComparatorGenerator.java index c3718566ca..3ca4194754 100644 --- a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/resourcelists/ResourceComparatorGenerator.java +++ b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/resourcelists/ResourceComparatorGenerator.java @@ -26,6 +26,7 @@ import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest; import org.eclipse.sw360.datahandler.thrift.packages.Package; import org.eclipse.sw360.datahandler.thrift.projects.Project; +import org.eclipse.sw360.datahandler.thrift.users.User; import org.eclipse.sw360.datahandler.thrift.search.SearchResult; import org.eclipse.sw360.datahandler.thrift.vulnerabilities.VulnerabilityDTO; import org.eclipse.sw360.datahandler.thrift.vulnerabilities.Vulnerability; @@ -34,6 +35,7 @@ public class ResourceComparatorGenerator { private static final Map> componentMap = generateComponentMap(); private static final Map> projectMap = generateProjectMap(); + private static final Map> userMap = generateUserMap(); private static final Map> releaseMap = generateReleaseMap(); private static final Map> packageMap = generatePackageMap(); private static final Map> searchResultMap = generateSearchResultMap(); @@ -61,6 +63,13 @@ private static Map> generateProjectMap() { return Collections.unmodifiableMap(projectMap); } + private static Map> generateUserMap() { + Map> userMap = new HashMap<>(); + userMap.put(User._Fields.FULLNAME, Comparator.comparing(User::getFullname, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER))); + userMap.put(User._Fields.EMAIL, Comparator.comparing(User::getEmail, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER))); + return Collections.unmodifiableMap(userMap); + } + private static Map> generateReleaseMap() { Map> releaseMap = new HashMap<>(); releaseMap.put(Release._Fields.NAME, Comparator.comparing(Release::getName, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER))); @@ -124,6 +133,8 @@ public Comparator generateComparator(String type) throws ResourceClassNotFoun return (Comparator)defaultComponentComparator(); case SW360Constants.TYPE_PROJECT: return (Comparator)defaultProjectComparator(); + case SW360Constants.TYPE_USER: + return (Comparator)defaultUserComparator(); case SW360Constants.TYPE_RELEASE: return (Comparator)defaultReleaseComparator(); case SW360Constants.TYPE_SEARCHRESULT: @@ -167,6 +178,15 @@ public Comparator generateComparator(String type, List properties) th } } return generateProjectComparatorWithFields(type, projectFields); + case SW360Constants.TYPE_USER: + List userFields = new ArrayList<>(); + for(String property:properties) { + User._Fields field = User._Fields.findByName(property); + if (field != null) { + userFields.add(field); + } + } + return generateUserComparatorWithFields(type, userFields); case SW360Constants.TYPE_RELEASE: List releaeFields = new ArrayList<>(); for(String property:properties) { @@ -244,6 +264,15 @@ public Comparator generateProjectComparatorWithFields(String type, List generateUserComparatorWithFields(String type, List fields) throws ResourceClassNotFoundException { + switch (type) { + case SW360Constants.TYPE_USER: + return (Comparator)userComparator(fields); + default: + throw new ResourceClassNotFoundException("No comparator for resource class with name " + type); + } + } + public Comparator generateReleaseComparatorWithFields(String type, List fields) throws ResourceClassNotFoundException { switch (type) { case SW360Constants.TYPE_RELEASE: @@ -323,6 +352,18 @@ private Comparator projectComparator(List fields) { return comparator; } + private Comparator userComparator(List fields) { + Comparator comparator = Comparator.comparing(x -> true); + for (User._Fields field:fields) { + Comparator fieldComparator = userMap.get(field); + if(fieldComparator != null) { + comparator = comparator.thenComparing(fieldComparator); + } + } + comparator = comparator.thenComparing(defaultUserComparator()); + return comparator; + } + private Comparator releaseComparator(List fields) { Comparator comparator = Comparator.comparing(x -> true); for (Release._Fields field:fields) { @@ -403,6 +444,10 @@ private Comparator defaultProjectComparator() { return projectMap.get(Project._Fields.NAME); } + private Comparator defaultUserComparator() { + return userMap.get(User._Fields.EMAIL); + } + private Comparator defaultReleaseComparator() { return releaseMap.get(Release._Fields.NAME); } diff --git a/rest/resource-server/src/docs/asciidoc/users.adoc b/rest/resource-server/src/docs/asciidoc/users.adoc index bc48542f5a..b3137a63be 100644 --- a/rest/resource-server/src/docs/asciidoc/users.adoc +++ b/rest/resource-server/src/docs/asciidoc/users.adoc @@ -19,6 +19,9 @@ The Users resource is used to get and list users. A `GET` request will list all of the service's users. +===== Request parameter +include::{snippets}/should_document_get_users/request-parameters.adoc[] + ===== Response structure include::{snippets}/should_document_get_users/response-fields.adoc[] diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/user/UserController.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/user/UserController.java index 1b5f460a9e..926ed33c9c 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/user/UserController.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/user/UserController.java @@ -18,6 +18,10 @@ import org.apache.thrift.TException; import org.eclipse.sw360.datahandler.common.CommonUtils; +import org.eclipse.sw360.datahandler.common.SW360Constants; +import org.eclipse.sw360.datahandler.resourcelists.ResourceClassNotFoundException; +import org.eclipse.sw360.datahandler.resourcelists.PaginationParameterException; +import org.eclipse.sw360.datahandler.resourcelists.PaginationResult; import org.eclipse.sw360.datahandler.thrift.users.User; import org.eclipse.sw360.rest.resourceserver.core.HalResource; import org.eclipse.sw360.rest.resourceserver.core.RestControllerHelper; @@ -35,8 +39,11 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import org.springframework.data.domain.Pageable; +import javax.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; import java.net.URI; +import java.net.URISyntaxException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; @@ -69,18 +76,29 @@ public class UserController implements RepresentationModelProcessor>> getUsers() { + public ResponseEntity>> getUsers( + Pageable pageable, + HttpServletRequest request + ) throws TException, URISyntaxException, PaginationParameterException, ResourceClassNotFoundException { List sw360Users = userService.getAllUsers(); + PaginationResult paginationResult = restControllerHelper.createPaginationResult(request, pageable, sw360Users, SW360Constants.TYPE_USER); List> userResources = new ArrayList<>(); - for (User sw360User : sw360Users) { + for (User sw360User : paginationResult.getResources()) { User embeddedUser = restControllerHelper.convertToEmbeddedGetUsers(sw360User); EntityModel userResource = EntityModel.of(embeddedUser); userResources.add(userResource); } - CollectionModel> resources = CollectionModel.of(userResources); - return new ResponseEntity<>(resources, HttpStatus.OK); + CollectionModel> resources; + if (sw360Users.size() == 0) { + resources = restControllerHelper.emptyPageResource(User.class, paginationResult); + } else { + resources = restControllerHelper.generatePagesResource(paginationResult, userResources); + } + + HttpStatus status = resources == null ? HttpStatus.NO_CONTENT : HttpStatus.OK; + return new ResponseEntity<>(resources, status); } // '/users/{xyz}' searches by email, as opposed to by id, as is customary, diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/UserSpecTest.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/UserSpecTest.java index 532106084e..3cf0d575b9 100644 --- a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/UserSpecTest.java +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/UserSpecTest.java @@ -41,6 +41,8 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; @RunWith(SpringJUnit4ClassRunner.class) public class UserSpecTest extends TestRestDocsSpecBase { @@ -109,11 +111,21 @@ public void should_document_get_users() throws Exception { String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); mockMvc.perform(get("/api/users") .header("Authorization", "Bearer " + accessToken) + .param("page", "0") + .param("page_entries", "5") + .param("sort", "email,desc") .accept(MediaTypes.HAL_JSON)) .andExpect(status().isOk()) .andDo(this.documentationHandler.document( + requestParameters( + parameterWithName("page").description("Page of users"), + parameterWithName("page_entries").description("Amount of users per page"), + parameterWithName("sort").description("Defines order of the users") + ), links( - linkWithRel("curies").description("Curies are used for online documentation") + linkWithRel("curies").description("Curies are used for online documentation"), + linkWithRel("first").description("Link to first page"), + linkWithRel("last").description("Link to last page") ), responseFields( subsectionWithPath("_embedded.sw360:users[]email").description("The user's email"), @@ -123,7 +135,12 @@ public void should_document_get_users() throws Exception { subsectionWithPath("_embedded.sw360:users[]givenName").description("The user's given name"), subsectionWithPath("_embedded.sw360:users[]lastName").description("The user's last name"), subsectionWithPath("_embedded.sw360:users").description("An array of <>"), - subsectionWithPath("_links").description("<> to other resources") + subsectionWithPath("_links").description("<> to other resources"), + fieldWithPath("page").description("Additional paging information"), + fieldWithPath("page.size").description("Number of users per page"), + fieldWithPath("page.totalElements").description("Total number of all existing users"), + fieldWithPath("page.totalPages").description("Total number of pages"), + fieldWithPath("page.number").description("Number of the current page") ))); }