Skip to content

Commit

Permalink
feat(rest) : Adding pagination for listing users endpoint.
Browse files Browse the repository at this point in the history
Signed-off-by: rudra-superrr <[email protected]>
  • Loading branch information
rudra-superrr committed Nov 2, 2023
1 parent 598226e commit c0db06a
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
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;

public class ResourceComparatorGenerator<T> {

private static final Map<Component._Fields, Comparator<Component>> componentMap = generateComponentMap();
private static final Map<Project._Fields, Comparator<Project>> projectMap = generateProjectMap();
private static final Map<User._Fields, Comparator<User>> userMap = generateUserMap();
private static final Map<Release._Fields, Comparator<Release>> releaseMap = generateReleaseMap();
private static final Map<Package._Fields, Comparator<Package>> packageMap = generatePackageMap();
private static final Map<SearchResult._Fields, Comparator<SearchResult>> searchResultMap = generateSearchResultMap();
Expand All @@ -59,6 +61,13 @@ private static Map<Project._Fields, Comparator<Project>> generateProjectMap() {
return Collections.unmodifiableMap(projectMap);
}

private static Map<User._Fields, Comparator<User>> generateUserMap() {
Map<User._Fields, Comparator<User>> 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<Release._Fields, Comparator<Release>> generateReleaseMap() {
Map<Release._Fields, Comparator<Release>> releaseMap = new HashMap<>();
releaseMap.put(Release._Fields.NAME, Comparator.comparing(Release::getName, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)));
Expand Down Expand Up @@ -114,6 +123,8 @@ public Comparator<T> generateComparator(String type) throws ResourceClassNotFoun
return (Comparator<T>)defaultComponentComparator();
case SW360Constants.TYPE_PROJECT:
return (Comparator<T>)defaultProjectComparator();
case SW360Constants.TYPE_USER:
return (Comparator<T>)defaultUserComparator();
case SW360Constants.TYPE_RELEASE:
return (Comparator<T>)defaultReleaseComparator();
case SW360Constants.TYPE_SEARCHRESULT:
Expand Down Expand Up @@ -155,6 +166,15 @@ public Comparator<T> generateComparator(String type, List<String> properties) th
}
}
return generateProjectComparatorWithFields(type, projectFields);
case SW360Constants.TYPE_USER:
List<User._Fields> 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<Release._Fields> releaeFields = new ArrayList<>();
for(String property:properties) {
Expand Down Expand Up @@ -223,6 +243,15 @@ public Comparator<T> generateProjectComparatorWithFields(String type, List<Proje
}
}

public Comparator<T> generateUserComparatorWithFields(String type, List<User._Fields> fields) throws ResourceClassNotFoundException {
switch (type) {
case SW360Constants.TYPE_USER:
return (Comparator<T>)userComparator(fields);
default:
throw new ResourceClassNotFoundException("No comparator for resource class with name " + type);
}
}

public Comparator<T> generateReleaseComparatorWithFields(String type, List<Release._Fields> fields) throws ResourceClassNotFoundException {
switch (type) {
case SW360Constants.TYPE_RELEASE:
Expand Down Expand Up @@ -292,6 +321,18 @@ private Comparator<Project> projectComparator(List<Project._Fields> fields) {
return comparator;
}

private Comparator<User> userComparator(List<User._Fields> fields) {
Comparator<User> comparator = Comparator.comparing(x -> true);
for (User._Fields field:fields) {
Comparator<User> fieldComparator = userMap.get(field);
if(fieldComparator != null) {
comparator = comparator.thenComparing(fieldComparator);
}
}
comparator = comparator.thenComparing(defaultUserComparator());
return comparator;
}

private Comparator<Release> releaseComparator(List<Release._Fields> fields) {
Comparator<Release> comparator = Comparator.comparing(x -> true);
for (Release._Fields field:fields) {
Expand Down Expand Up @@ -360,6 +401,10 @@ private Comparator<Project> defaultProjectComparator() {
return projectMap.get(Project._Fields.NAME);
}

private Comparator<User> defaultUserComparator() {
return userMap.get(User._Fields.EMAIL);
}

private Comparator<Release> defaultReleaseComparator() {
return releaseMap.get(Release._Fields.NAME);
}
Expand Down
3 changes: 3 additions & 0 deletions rest/resource-server/src/docs/asciidoc/users.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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[]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -69,18 +76,29 @@ public class UserController implements RepresentationModelProcessor<RepositoryLi
tags = {"Users"}
)
@RequestMapping(value = USERS_URL, method = RequestMethod.GET)
public ResponseEntity<CollectionModel<EntityModel<User>>> getUsers() {
public ResponseEntity<CollectionModel<EntityModel<User>>> getUsers(
Pageable pageable,
HttpServletRequest request
) throws TException, URISyntaxException, PaginationParameterException, ResourceClassNotFoundException {
List<User> sw360Users = userService.getAllUsers();

PaginationResult<User> paginationResult = restControllerHelper.createPaginationResult(request, pageable, sw360Users, SW360Constants.TYPE_USER);
List<EntityModel<User>> userResources = new ArrayList<>();
for (User sw360User : sw360Users) {
for (User sw360User : paginationResult.getResources()) {
User embeddedUser = restControllerHelper.convertToEmbeddedGetUsers(sw360User);
EntityModel<User> userResource = EntityModel.of(embeddedUser);
userResources.add(userResource);
}

CollectionModel<EntityModel<User>> resources = CollectionModel.of(userResources);
return new ResponseEntity<>(resources, HttpStatus.OK);
CollectionModel<EntityModel<User>> 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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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"),
Expand All @@ -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 <<resources-users, User resources>>"),
subsectionWithPath("_links").description("<<resources-index-links,Links>> to other resources")
subsectionWithPath("_links").description("<<resources-index-links,Links>> 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")
)));
}

Expand Down

0 comments on commit c0db06a

Please sign in to comment.