diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/Page.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/Page.java index a1735129..ce796449 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/Page.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/Page.java @@ -11,11 +11,14 @@ package ch.ethz.seb.sebserver.gbl.model; import java.util.Collection; import java.util.List; +import javax.validation.constraints.Size; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import ch.ethz.seb.sebserver.gbl.util.Utils; +import io.swagger.v3.oas.annotations.media.Schema; /** Data class that defines a Page that corresponds with the SEB Server API page JSON object * @@ -30,24 +33,36 @@ public final class Page { public static final String ATTR_COMPLETE = "complete"; public static final String ATTR_CONTENT = "content"; + @Schema(description = "The number of available pages for the specified page size.") @JsonProperty(ATTR_NUMBER_OF_PAGES) - public final Integer numberOfPages; + public final int numberOfPages; + + @Schema(description = "The actual page number. Starting with 1.") + @Size(min = 1) @JsonProperty(ATTR_PAGE_NUMBER) - public final Integer pageNumber; + public final int pageNumber; + + @Schema(description = "The the actual size of a page") + @Size(min = 1) @JsonProperty(ATTR_PAGE_SIZE) - public final Integer pageSize; + public final int pageSize; + + @Schema(description = "The page sort column name", nullable = true) @JsonProperty(ATTR_SORT) public final String sort; - @JsonProperty(ATTR_COMPLETE) - public final boolean complete; + @Schema(description = "The actual content objects of the page. Might be empty.", nullable = false) @JsonProperty(ATTR_CONTENT) public final List content; + @JsonProperty(ATTR_COMPLETE) + public final boolean complete; + @JsonCreator public Page( - @JsonProperty(ATTR_NUMBER_OF_PAGES) final Integer numberOfPages, - @JsonProperty(ATTR_PAGE_NUMBER) final Integer pageNumber, + @JsonProperty(value = ATTR_NUMBER_OF_PAGES, required = true) final int numberOfPages, + @JsonProperty(value = ATTR_PAGE_NUMBER, required = true) final int pageNumber, + @JsonProperty(value = ATTR_PAGE_SIZE, required = true) final int pageSize, @JsonProperty(ATTR_SORT) final String sort, @JsonProperty(ATTR_CONTENT) final Collection content, @JsonProperty(ATTR_COMPLETE) final boolean complet) { @@ -55,35 +70,36 @@ public final class Page { this.numberOfPages = numberOfPages; this.pageNumber = pageNumber; this.content = Utils.immutableListOf(content); - this.pageSize = content.size(); + this.pageSize = pageSize; this.sort = sort; this.complete = complet; } public Page( - final Integer numberOfPages, - final Integer pageNumber, + final int numberOfPages, + final int pageNumber, + final int pageSize, final String sort, final Collection content) { this.numberOfPages = numberOfPages; this.pageNumber = pageNumber; this.content = Utils.immutableListOf(content); - this.pageSize = content.size(); + this.pageSize = pageSize; this.sort = sort; this.complete = true; } public int getNumberOfPages() { - return (this.numberOfPages != null) ? this.numberOfPages : 1; + return this.numberOfPages; } public int getPageNumber() { - return (this.pageNumber != null) ? this.pageNumber : 0; + return this.pageNumber; } public int getPageSize() { - return (this.pageSize != null) ? this.pageSize : -1; + return this.pageSize; } public boolean isComplete() { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/RemoteListPageSupplier.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/RemoteListPageSupplier.java index 30a57d37..dabb8d4c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/table/RemoteListPageSupplier.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/RemoteListPageSupplier.java @@ -100,21 +100,21 @@ public class RemoteListPageSupplier implements PageSupplier { : new ArrayList<>(collection); if (list.isEmpty()) { - return new Page<>(0, this.pageNumber, this.column, list); + return new Page<>(0, this.pageNumber, this.pageSize, this.column, list); } if (this.pageSize <= 0) { - return new Page<>(1, 1, this.column, list); + return new Page<>(1, 1, list.size(), this.column, list); } final int numOfPages = list.size() / this.pageSize; if (numOfPages <= 0) { - return new Page<>(1, 1, this.column, list); + return new Page<>(1, 1, this.pageSize, this.column, list); } final List subList = list.subList(this.pageNumber * this.pageSize, this.pageNumber * this.pageSize + this.pageSize); - return new Page<>(numOfPages, this.pageNumber, this.column, subList); + return new Page<>(numOfPages, this.pageNumber, this.pageSize, this.column, subList); }); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/StaticListPageSupplier.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/StaticListPageSupplier.java index 515fb406..94b1b7fd 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/table/StaticListPageSupplier.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/StaticListPageSupplier.java @@ -94,16 +94,16 @@ public class StaticListPageSupplier implements PageSupplier { public Result> getPage() { return Result.tryCatch(() -> { if (this.list.isEmpty()) { - return new Page<>(0, this.pageNumber, this.column, this.list); + return new Page<>(0, this.pageNumber, this.pageSize, this.column, this.list); } if (this.pageSize <= 0) { - return new Page<>(1, 1, this.column, this.list); + return new Page<>(1, 1, this.list.size(), this.column, this.list); } int numOfPages = this.list.size() / this.pageSize; if (numOfPages <= 0) { - return new Page<>(1, 1, this.column, this.list); + return new Page<>(1, 1, this.pageSize, this.column, this.list); } if (this.list.size() % this.pageSize > 0) { numOfPages++; @@ -119,7 +119,7 @@ public class StaticListPageSupplier implements PageSupplier { } final List subList = this.list.subList(from, to); - return new Page<>(numOfPages, this.pageNumber, this.column, subList); + return new Page<>(numOfPages, this.pageNumber, this.pageSize, this.column, subList); }); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationService.java index eb4d8e71..b59eb955 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationService.java @@ -139,6 +139,7 @@ public interface PaginationService { return new Page<>( (numberOfPages > 0) ? numberOfPages : 1, _pageNumber, + _pageSize, sort, sorted.subList(start, end)); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java index 1503ec37..2a2ae5e3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java @@ -143,6 +143,7 @@ public class PaginationServiceImpl implements PaginationService { return new Page<>( page.getPages(), page.getPageNum(), + getPageSize(pageSize), sort, list); }); @@ -166,6 +167,7 @@ public class PaginationServiceImpl implements PaginationService { return new Page<>( page.getPages(), page.getPageNum(), + getPageSize(pageSize), sort, list); }); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/QuizLookupService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/QuizLookupService.java index 1d386429..6b728bad 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/QuizLookupService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/QuizLookupService.java @@ -78,7 +78,7 @@ public interface QuizLookupService { return lookupResult -> { final List quizzes = lookupResult.quizData; if (quizzes.isEmpty()) { - return new Page<>(0, 1, sortAttribute, Collections.emptyList(), lookupResult.completed); + return new Page<>(0, 1, pageSize, sortAttribute, Collections.emptyList(), lookupResult.completed); } int start = (pageNumber - 1) * pageSize; @@ -95,6 +95,7 @@ public interface QuizLookupService { return new Page<>( (quizzes.size() <= pageSize) ? 1 : quizzes.size() / pageSize + 1, start / pageSize + 1, + pageSize, sortAttribute, quizzes.subList(start, end)); } @@ -107,6 +108,7 @@ public interface QuizLookupService { ? quizzes.size() / pageSize + 1 : quizzes.size() / pageSize, pageNumber, + pageSize, sortAttribute, quizzes.subList(start, end), lookupResult.completed); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java index d8f02488..7e47c800 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java @@ -21,6 +21,7 @@ import org.springframework.core.annotation.Order; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.lang.Nullable; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; @@ -48,7 +49,7 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler { @Override protected ResponseEntity handleExceptionInternal( final Exception ex, - final Object body, + @Nullable final Object body, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java index 80794cf3..15263f08 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java @@ -434,11 +434,14 @@ public class ConfigurationNodeController extends EntityController subList = attrs.subList(start, end); + return new Page<>( numOfPages, this.paginationService.getPageNumber(pageNumber), + (pageSize != null) ? pageSize : subList.size(), sort, - attrs.subList(start, end)); + subList); } @RequestMapping( diff --git a/src/test/java/ch/ethz/seb/sebserver/gbl/model/ModelObjectJSONGenerator.java b/src/test/java/ch/ethz/seb/sebserver/gbl/model/ModelObjectJSONGenerator.java index 6d7b05fd..0d6fbd2f 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gbl/model/ModelObjectJSONGenerator.java +++ b/src/test/java/ch/ethz/seb/sebserver/gbl/model/ModelObjectJSONGenerator.java @@ -242,7 +242,8 @@ public class ModelObjectJSONGenerator { System.out.println(domainObject.getClass().getSimpleName() + ":"); System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject)); - domainObject = new Page<>(3, 1, "columnName", Arrays.asList("Entry1", "Entry1", "Entry1", "Entry1", "Entry1")); + domainObject = + new Page<>(3, 1, 5, "columnName", Arrays.asList("Entry1", "Entry1", "Entry1", "Entry1", "Entry1")); System.out.println(domainObject.getClass().getSimpleName() + ":"); System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject)); diff --git a/src/test/java/ch/ethz/seb/sebserver/gbl/model/institution/InstitutionTest.java b/src/test/java/ch/ethz/seb/sebserver/gbl/model/institution/InstitutionTest.java index ece1852b..d6e43c3e 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gbl/model/institution/InstitutionTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/gbl/model/institution/InstitutionTest.java @@ -40,7 +40,7 @@ public class InstitutionTest { @Test public void pageOfInstituions() throws Exception { - final Page page = new Page<>(2, 1, "name", Arrays.asList( + final Page page = new Page<>(2, 1, 3, "name", Arrays.asList( new Institution(1L, "InstOne", "one", "", "", true), new Institution(2L, "InstTwo", "two", "", "", true), new Institution(3L, "InstThree", "three", "", "", true))); @@ -49,7 +49,7 @@ public class InstitutionTest { //final ObjectWriter writerWithDefaultPrettyPrinter = jsonMapper.writerWithDefaultPrettyPrinter(); String json = jsonMapper.writeValueAsString(page); assertEquals( - "{\"number_of_pages\":2,\"page_number\":1,\"sort\":\"name\",\"content\":[{\"id\":1,\"name\":\"InstOne\",\"urlSuffix\":\"one\",\"logoImage\":\"\",\"themeName\":\"\",\"active\":true},{\"id\":2,\"name\":\"InstTwo\",\"urlSuffix\":\"two\",\"logoImage\":\"\",\"themeName\":\"\",\"active\":true},{\"id\":3,\"name\":\"InstThree\",\"urlSuffix\":\"three\",\"logoImage\":\"\",\"themeName\":\"\",\"active\":true}],\"complete\":true,\"page_size\":3}", + "{\"number_of_pages\":2,\"page_number\":1,\"page_size\":3,\"sort\":\"name\",\"content\":[{\"id\":1,\"name\":\"InstOne\",\"urlSuffix\":\"one\",\"logoImage\":\"\",\"themeName\":\"\",\"active\":true},{\"id\":2,\"name\":\"InstTwo\",\"urlSuffix\":\"two\",\"logoImage\":\"\",\"themeName\":\"\",\"active\":true},{\"id\":3,\"name\":\"InstThree\",\"urlSuffix\":\"three\",\"logoImage\":\"\",\"themeName\":\"\",\"active\":true}],\"complete\":true}", json); final List namesList = page.content.stream() diff --git a/src/test/java/ch/ethz/seb/sebserver/gbl/model/user/UserInfoTest.java b/src/test/java/ch/ethz/seb/sebserver/gbl/model/user/UserInfoTest.java index e5a8d915..a6b4d1ea 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gbl/model/user/UserInfoTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/gbl/model/user/UserInfoTest.java @@ -25,7 +25,7 @@ public class UserInfoTest { @Test public void pageOfUserAccount() throws Exception { - final Page page = new Page<>(2, 1, "name", Arrays.asList( + final Page page = new Page<>(2, 1, 3, "name", Arrays.asList( new UserInfo("id1", 1L, new DateTime(0, DateTimeZone.UTC), "user1", "", "user1", "user1@inst2.none", true, Locale.ENGLISH, DateTimeZone.UTC, @@ -43,7 +43,7 @@ public class UserInfoTest { //final ObjectWriter writerWithDefaultPrettyPrinter = jsonMapper.writerWithDefaultPrettyPrinter(); final String json = jsonMapper.writeValueAsString(page); assertEquals( - "{\"number_of_pages\":2,\"page_number\":1,\"sort\":\"name\",\"content\":[{\"uuid\":\"id1\",\"institutionId\":1,\"creationDate\":\"1970-01-01T00:00:00.000Z\",\"name\":\"user1\",\"surname\":\"\",\"username\":\"user1\",\"email\":\"user1@inst2.none\",\"active\":true,\"language\":\"en\",\"timezone\":\"UTC\",\"userRoles\":[\"EXAM_ADMIN\"]},{\"uuid\":\"id2\",\"institutionId\":3,\"creationDate\":\"1970-01-01T00:00:00.000Z\",\"name\":\"user2\",\"surname\":\"\",\"username\":\"user2\",\"email\":\"user2@inst2.none\",\"active\":true,\"language\":\"en\",\"timezone\":\"UTC\",\"userRoles\":[\"EXAM_ADMIN\"]},{\"uuid\":\"id3\",\"institutionId\":4,\"creationDate\":\"1970-01-01T00:00:00.000Z\",\"name\":\"user3\",\"surname\":\"\",\"username\":\"user3\",\"email\":\"user3@inst2.none\",\"active\":false,\"language\":\"de\",\"timezone\":\"UTC\",\"userRoles\":[\"EXAM_ADMIN\"]}],\"complete\":true,\"page_size\":3}", + "{\"number_of_pages\":2,\"page_number\":1,\"page_size\":3,\"sort\":\"name\",\"content\":[{\"uuid\":\"id1\",\"institutionId\":1,\"creationDate\":\"1970-01-01T00:00:00.000Z\",\"name\":\"user1\",\"surname\":\"\",\"username\":\"user1\",\"email\":\"user1@inst2.none\",\"active\":true,\"language\":\"en\",\"timezone\":\"UTC\",\"userRoles\":[\"EXAM_ADMIN\"]},{\"uuid\":\"id2\",\"institutionId\":3,\"creationDate\":\"1970-01-01T00:00:00.000Z\",\"name\":\"user2\",\"surname\":\"\",\"username\":\"user2\",\"email\":\"user2@inst2.none\",\"active\":true,\"language\":\"en\",\"timezone\":\"UTC\",\"userRoles\":[\"EXAM_ADMIN\"]},{\"uuid\":\"id3\",\"institutionId\":4,\"creationDate\":\"1970-01-01T00:00:00.000Z\",\"name\":\"user3\",\"surname\":\"\",\"username\":\"user3\",\"email\":\"user3@inst2.none\",\"active\":false,\"language\":\"de\",\"timezone\":\"UTC\",\"userRoles\":[\"EXAM_ADMIN\"]}],\"complete\":true}", json); } diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/InstitutionAPITest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/InstitutionAPITest.java index 83820aba..b2efcac0 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/InstitutionAPITest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/InstitutionAPITest.java @@ -400,7 +400,7 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester { }); assertNotNull(institutions); - assertTrue(institutions.pageSize == 1); + assertTrue(institutions.content.size() == 1); assertEquals("[3]", getOrderedUUIDs(institutions.content)); } diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/UserAPITest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/UserAPITest.java index 272101d9..3bd00abd 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/UserAPITest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/UserAPITest.java @@ -308,7 +308,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { assertNotNull(userInfos); assertTrue(userInfos.numberOfPages == 2); assertNotNull(userInfos.content); - assertTrue(userInfos.pageSize == 1); + assertTrue(userInfos.pageSize == 3); assertTrue(userInfos.content.size() == 1); assertEquals("[user7]", getOrderedUUIDs(userInfos.content)); @@ -329,6 +329,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { assertTrue(userInfos.pageNumber == 2); assertNotNull(userInfos.content); assertTrue(userInfos.content.size() == 1); + assertTrue(userInfos.pageSize == 3); assertEquals("[user7]", getOrderedUUIDs(userInfos.content)); // first page descending sort order @@ -1050,7 +1051,8 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { }); assertNotNull(usersPage); - assertTrue(usersPage.pageSize == 3); + assertTrue(usersPage.content.size() == 3); + assertTrue(usersPage.pageSize == 10); assertEquals("[user1, user2, user5]", getOrderedUUIDs(usersPage.content)); // all inactive of the own institution @@ -1064,7 +1066,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { }); assertNotNull(usersPage); - assertTrue(usersPage.pageSize == 0); + assertTrue(usersPage.content.size() == 0); assertEquals("[]", getOrderedUUIDs(usersPage.content)); // all active of institution 2 @@ -1080,7 +1082,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { }); assertNotNull(usersPage); - assertTrue(usersPage.pageSize == 3); + assertTrue(usersPage.content.size() == 3); assertEquals("[user3, user4, user7]", getOrderedUUIDs(usersPage.content)); // all inactive of institution 2 @@ -1096,7 +1098,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { }); assertNotNull(usersPage); - assertTrue(usersPage.pageSize == 1); + assertTrue(usersPage.content.size() == 1); assertEquals("[user6]", getOrderedUUIDs(usersPage.content)); }