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 bc00ac46..b007a558 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 @@ -18,17 +18,11 @@ import ch.ethz.seb.sebserver.gbl.util.Utils; public final class Page { - public enum SortOrder { - ASCENDING, - DESCENDING - } - public static final String ATTR_NAMES_ONLY = "names_only"; public static final String ATTR_NUMBER_OF_PAGES = "number_of_pages"; public static final String ATTR_PAGE_NUMBER = "page_number"; public static final String ATTR_PAGE_SIZE = "page_size"; - public static final String ATTR_SORT_BY = "sort_by"; - public static final String ATTR_SORT_ORDER = "sort_order"; + public static final String ATTR_SORT = "sort"; public static final String ATTR_CONTENT = "content"; @JsonProperty(ATTR_NUMBER_OF_PAGES) @@ -37,10 +31,8 @@ public final class Page { public final Integer pageNumber; @JsonProperty(ATTR_PAGE_SIZE) public final Integer pageSize; - @JsonProperty(ATTR_SORT_BY) - public final String sortBy; - @JsonProperty(ATTR_SORT_ORDER) - public final SortOrder sortOrder; + @JsonProperty(ATTR_SORT) + public final String sort; @JsonProperty(ATTR_CONTENT) public final List content; @@ -49,16 +41,14 @@ public final class Page { public Page( @JsonProperty(ATTR_NUMBER_OF_PAGES) final Integer numberOfPages, @JsonProperty(ATTR_PAGE_NUMBER) final Integer pageNumber, - @JsonProperty(ATTR_SORT_BY) final String sortBy, - @JsonProperty(ATTR_SORT_ORDER) final SortOrder sortOrder, + @JsonProperty(ATTR_SORT) final String sort, @JsonProperty(ATTR_CONTENT) final Collection content) { this.numberOfPages = numberOfPages; this.pageNumber = pageNumber; this.content = Utils.immutableListOf(content); this.pageSize = content.size(); - this.sortBy = sortBy; - this.sortOrder = sortOrder; + this.sort = sort; } public Integer getNumberOfPages() { @@ -73,16 +63,15 @@ public final class Page { return this.pageSize; } - public String getSortBy() { - return this.sortBy; - } - - public SortOrder getSortOrder() { - return this.sortOrder; - } - public Collection getContent() { return this.content; } + @Override + public String toString() { + return "Page [numberOfPages=" + this.numberOfPages + ", pageNumber=" + this.pageNumber + ", pageSize=" + + this.pageSize + + ", sort=" + this.sort + ", content=" + this.content + "]"; + } + } 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 3e8f0605..c5c6971f 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 @@ -35,6 +35,32 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamic @WebServiceProfile public class PaginationService { + public enum SortOrder { + ASCENDING("+"), + DESCENDING("-"); + + public final String prefix; + + private SortOrder(final String prefix) { + this.prefix = prefix; + } + + public static SortOrder getSortOrder(final String sort) { + return (sort != null && sort.startsWith(DESCENDING.prefix)) + ? SortOrder.DESCENDING + : SortOrder.ASCENDING; + } + + public static String getSortColumn(final String sort) { + return (sort == null) + ? null + : (sort.startsWith(SortOrder.ASCENDING.prefix) || sort.startsWith(SortOrder.DESCENDING.prefix)) + ? sort.substring(1) + : sort; + } + + } + private final int defaultPageSize; private final int maxPageSize; @@ -77,19 +103,15 @@ public class PaginationService { if (PageHelper.getLocalPage() != null) { return; } - setPagination(1, this.maxPageSize, null, Page.SortOrder.ASCENDING, null); + setPagination(1, this.maxPageSize, null, null); } public void setDefaultLimit() { - setPagination(1, this.maxPageSize, null, Page.SortOrder.ASCENDING, null); + setPagination(1, this.maxPageSize, null, null); } - public void setDefaultLimit(final String sortBy, final SqlTable table) { - setPagination(1, this.maxPageSize, sortBy, Page.SortOrder.ASCENDING, table); - } - - public void setDefaultLimit(final String sortBy, final Page.SortOrder sortOrder, final SqlTable table) { - setPagination(1, this.maxPageSize, sortBy, sortOrder, table); + public void setDefaultLimit(final String sort, final SqlTable table) { + setPagination(1, this.maxPageSize, sort, table); } public int getPageNumber(final Integer pageNumber) { @@ -109,20 +131,23 @@ public class PaginationService { public com.github.pagehelper.Page setPagination( final Integer pageNumber, final Integer pageSize, - final String sortBy, - final Page.SortOrder sortOrder, + final String sort, final SqlTable table) { final com.github.pagehelper.Page startPage = PageHelper.startPage(getPageNumber(pageNumber), getPageSize(pageSize), true, true, false); if (table != null) { - final String sortColumnName = verifySortColumnName(sortBy, table); + final String sortColumnName = verifySortColumnName(sort, table); if (StringUtils.isNoneBlank(sortColumnName)) { - if (sortOrder == Page.SortOrder.DESCENDING) { - PageHelper.orderBy(sortColumnName + " DESC"); - } else { - PageHelper.orderBy(sortColumnName); + switch (SortOrder.getSortOrder(sort)) { + case DESCENDING: { + PageHelper.orderBy(sortColumnName + " DESC"); + break; + } + default: { + PageHelper.orderBy(sortColumnName); + } } } } @@ -133,28 +158,31 @@ public class PaginationService { public Result> getPage( final Integer pageNumber, final Integer pageSize, - final String sortBy, - final Page.SortOrder sortOrder, + final String sort, final SqlTable table, final Supplier>> delegate) { return Result.tryCatch(() -> { final com.github.pagehelper.Page page = - setPagination(pageNumber, pageSize, sortBy, sortOrder, table); + setPagination(pageNumber, pageSize, sort, table); final Collection pageList = delegate.get().getOrThrow(); - return new Page<>(page.getPages(), page.getPageNum(), sortBy, sortOrder, pageList); + return new Page<>(page.getPages(), page.getPageNum(), sort, pageList); }); } - private String verifySortColumnName(final String sortBy, final SqlTable table) { + private String verifySortColumnName(final String sort, final SqlTable table) { - if (StringUtils.isBlank(sortBy)) { + if (StringUtils.isBlank(sort)) { return this.defaultSortColumn.get(table.name()); } final Map mapping = this.sortColumnMapping.get(table.name()); if (mapping != null) { - return mapping.get(sortBy); + final String sortColumn = SortOrder.getSortColumn(sort); + if (StringUtils.isBlank(sortColumn)) { + return this.defaultSortColumn.get(table.name()); + } + return mapping.get(sortColumn); } return this.defaultSortColumn.get(table.name()); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java index 44f66aef..d10109a5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java @@ -12,7 +12,6 @@ import java.util.Collection; import java.util.Set; import ch.ethz.seb.sebserver.gbl.model.Page; -import ch.ethz.seb.sebserver.gbl.model.Page.SortOrder; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; @@ -21,23 +20,14 @@ import ch.ethz.seb.sebserver.gbl.util.Result; public interface LmsAPITemplate { - enum OrderBy { - NAME, - FROM, - TO - } - LmsSetup lmsSetup(); LmsSetupTestResult testLmsSetup(); - Collection getQuizzes(String name, Long from, OrderBy orderBy, SortOrder sortOrder); - - Page getQuizzesPage( + Page getQuizzes( String name, Long from, - OrderBy orderBy, - SortOrder sortOrder, + String sort, int pageNumber, int pageSize); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java index 6648842e..6bace421 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java @@ -10,19 +10,20 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import ch.ethz.seb.sebserver.gbl.model.Page; -import ch.ethz.seb.sebserver.gbl.model.Page.SortOrder; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService.SortOrder; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; public class MockupLmsAPITemplate implements LmsAPITemplate { @@ -78,12 +79,21 @@ public class MockupLmsAPITemplate implements LmsAPITemplate { } } - @Override public Collection getQuizzes( final String name, final Long from, - final OrderBy orderBy, - final SortOrder sortOrder) { + final String sort) { + + final int orderFactor = (SortOrder.getSortOrder(sort) == SortOrder.DESCENDING) + ? -1 + : 1; + + final String _sort = SortOrder.getSortColumn(sort); + final Comparator comp = (_sort != null) + ? (_sort.equals(QuizData.FILTER_ATTR_START_TIME)) + ? (q1, q2) -> q1.startTime.compareTo(q2.startTime) * orderFactor + : (q1, q2) -> q1.name.compareTo(q2.name) * orderFactor + : (q1, q2) -> q1.name.compareTo(q2.name) * orderFactor; return this.mockups.stream() .filter(mockup -> (name != null) @@ -91,22 +101,22 @@ public class MockupLmsAPITemplate implements LmsAPITemplate { : true && (from != null) ? mockup.startTime.getMillis() >= from : true) + .sorted(comp) .collect(Collectors.toList()); } @Override - public Page getQuizzesPage( + public Page getQuizzes( final String name, final Long from, - final OrderBy orderBy, - final SortOrder sortOrder, + final String sort, final int pageNumber, final int pageSize) { final int startIndex = pageNumber * pageSize; final int endIndex = startIndex + pageSize; int index = 0; - final Collection quizzes = getQuizzes(name, from, orderBy, sortOrder); + final Collection quizzes = getQuizzes(name, from, sort); final int numberOfPages = quizzes.size() / pageSize; final Iterator iterator = quizzes.iterator(); final List pageContent = new ArrayList<>(); @@ -118,7 +128,7 @@ public class MockupLmsAPITemplate implements LmsAPITemplate { index++; } - return new Page<>(numberOfPages, pageNumber, orderBy.name(), sortOrder, pageContent); + return new Page<>(numberOfPages, pageNumber, sort, pageContent); } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java index c593b842..88d26bc4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java @@ -67,15 +67,13 @@ public abstract class ActivatableEntityController this.activatableEntityDAO.all(institutionId, true)).getOrThrow(); } @@ -92,15 +90,13 @@ public abstract class ActivatableEntityController this.activatableEntityDAO.all(institutionId, false)).getOrThrow(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java index 25d3c9f1..f099653d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java @@ -98,8 +98,7 @@ public abstract class EntityController allRequestParams) { checkReadPrivilege(institutionId); @@ -111,8 +110,7 @@ public abstract class EntityController getAll(filterMap)).getOrThrow(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java index 80265708..2f2288bd 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java @@ -36,7 +36,6 @@ import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.gbl.model.Page; -import ch.ethz.seb.sebserver.gbl.model.Page.SortOrder; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; @@ -44,6 +43,7 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService; +import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService.SortOrder; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; @@ -109,8 +109,7 @@ public class ExamAdministrationController extends ActivatableEntityController allRequestParams) { checkReadPrivilege(institutionId); @@ -118,10 +117,10 @@ public class ExamAdministrationController extends ActivatableEntityController exams = new ArrayList<>( this.examDAO.allMatching(new FilterMap(allRequestParams)).getOrThrow()); - if (!StringUtils.isBlank(sortBy)) { + if (!StringUtils.isBlank(sort)) { + final String sortBy = SortOrder.getSortColumn(sort); if (sortBy.equals(QuizData.QUIZ_ATTR_NAME)) { Collections.sort(exams, (exam1, exam2) -> exam1.name.compareTo(exam2.name)); } @@ -145,15 +145,14 @@ public class ExamAdministrationController extends ActivatableEntityController( exams.size() / pSize, pageNum, - sortBy, - sortOrder, + sort, exams.subList(pageNum * pSize, pageNum * pSize + pSize)); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizImportController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizImportController.java index b6184776..0beeead9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizImportController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizImportController.java @@ -17,16 +17,13 @@ import org.springframework.web.bind.annotation.RestController; import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP; import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.gbl.model.Page; -import ch.ethz.seb.sebserver.gbl.model.Page.SortOrder; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; -import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; -import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate.OrderBy; @WebServiceProfile @RestController @@ -58,8 +55,7 @@ public class QuizImportController { @RequestParam(name = QuizData.FILTER_ATTR_START_TIME, required = false) final String startTime, @RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber, @RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize, - @RequestParam(name = Page.ATTR_SORT_BY, required = false) final String orderBy, - @RequestParam(name = Page.ATTR_SORT_ORDER, required = false) final String sortOrder) { + @RequestParam(name = Page.ATTR_SORT, required = false) final String sort) { final LmsAPITemplate lmsAPITemplate = this.lmsAPIService .createLmsAPITemplate(lmsSetupId) @@ -70,13 +66,10 @@ public class QuizImportController { PrivilegeType.READ_ONLY, lmsAPITemplate.lmsSetup().institutionId); - return lmsAPITemplate.getQuizzesPage( + return lmsAPITemplate.getQuizzes( nameLike, Utils.dateTimeStringToTimestamp(startTime, null), - Result.tryCatch(() -> OrderBy.valueOf(orderBy)) - .getOrElse(OrderBy.NAME), - Result.tryCatch(() -> SortOrder.valueOf(sortOrder)) - .getOrElse(SortOrder.ASCENDING), + sort, (pageNumber != null) ? pageNumber : 1, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserActivityLogController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserActivityLogController.java index bc7d4e71..c4664973 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserActivityLogController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserActivityLogController.java @@ -70,15 +70,13 @@ public class UserActivityLogController { @RequestParam(name = UserActivityLog.FILTER_ATTR_ENTITY_TYPES, required = false) final String entityTypes, @RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber, @RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize, - @RequestParam(name = Page.ATTR_SORT_BY, required = false) final String sortBy, - @RequestParam(name = Page.ATTR_SORT_ORDER, required = false) final Page.SortOrder sortOrder) { + @RequestParam(name = Page.ATTR_SORT, required = false) final String sort) { checkBaseReadPrivilege(institutionId); return this.paginationService.getPage( pageNumber, pageSize, - sortBy, - sortOrder, + sort, UserRecordDynamicSqlSupport.userRecord, () -> _getAll(institutionId, userId, from, to, activityTypes, entityTypes)).getOrThrow(); } 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 9060f393..a8d6d34f 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 @@ -244,7 +244,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { public void getPageNoFilterNoPageAttributesDescendingOrder() throws Exception { final String token = getSebAdminAccess(); final Page userInfos = this.jsonMapper.readValue( - this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?sort_order=DESCENDING") + this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?sort=-") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + token)) .andExpect(status().isOk()) @@ -323,7 +323,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { userInfos = this.jsonMapper.readValue( this.mockMvc .perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT - + "?page_number=1&page_size=3&sort_order=DESCENDING&institutionId=2") + + "?page_number=1&page_size=3&sort=-&institutionId=2") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + token)) .andExpect(status().isOk())