Skip to content

Commit

Permalink
SEBSERV-481 do sorting und most filtering on DB
Browse files Browse the repository at this point in the history
  • Loading branch information
anhefti committed Nov 20, 2023
1 parent 89adc8c commit 8b15fdd
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ public void compose(final PageContext pageContext) {
this.pageService.entityTableBuilder(restService.getRestCall(GetFinishedExamClientConnectionPage.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize)
.withDefaultSort(Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID)
.withStaticFilter(ClientConnection.FILTER_ATTR_EXAM_ID, examKey.modelId)

.withColumn(new ColumnDefinition<ClientConnectionData>(
Expand All @@ -162,8 +163,7 @@ public void compose(final PageContext pageContext) {
ClientConnection.ATTR_INFO,
TABLE_COLUMN_INFO,
c -> c.clientConnection.getInfo())
.withFilter(this.infoFilter)
.sortable())
.withFilter(this.infoFilter))

.withColumn(new ColumnDefinition<ClientConnectionData>(
Domain.CLIENT_CONNECTION.ATTR_STATUS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.Map;
import java.util.function.Supplier;

import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -397,6 +398,25 @@ private void initSortColumnMapping() {
UserActivityLogRecordDynamicSqlSupport.userActivityLogRecord.tableNameAtRuntime(),
Domain.USER_ACTIVITY_LOG.ATTR_ID);

// Client Connection Table

final Map<String, String> ccTableMap = new HashMap<>();
ccTableMap.put(
ClientConnection.FILTER_ATTR_SESSION_ID,
ClientConnectionRecordDynamicSqlSupport.examUserSessionId.name());
ccTableMap.put(
ClientConnection.FILTER_ATTR_STATUS,
ClientConnectionRecordDynamicSqlSupport.status.name());
ccTableMap.put(
ClientConnection.FILTER_ATTR_INFO,
ClientConnectionRecordDynamicSqlSupport.clientVersion.name());

this.sortColumnMapping.put(
ClientConnectionRecordDynamicSqlSupport.clientConnectionRecord.tableNameAtRuntime(),
ccTableMap);
this.defaultSortColumn.put(
ClientConnectionRecordDynamicSqlSupport.clientConnectionRecord.tableNameAtRuntime(),
ClientConnection.FILTER_ATTR_SESSION_ID);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public Result<Collection<ClientConnection>> allMatching(
final Predicate<ClientConnection> predicate) {

return Result.tryCatch(() -> {
final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<ClientConnectionRecord>>>.QueryExpressionWhereBuilder whereClause =
QueryExpressionDSL<MyBatis3SelectModelAdapter<List<ClientConnectionRecord>>>.QueryExpressionWhereBuilder whereClause =
(filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN))
? this.clientConnectionRecordMapper
.selectByExample()
Expand All @@ -130,6 +130,23 @@ public Result<Collection<ClientConnection>> allMatching(
.where(
ClientConnectionRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(filterMap.getInstitutionId()));

if (filterMap.contains(ClientConnection.FILTER_ATTR_INFO)) {
whereClause = whereClause
.and(
ClientConnectionRecordDynamicSqlSupport.clientVersion,
isLike(filterMap.getSQLWildcard(ClientConnection.FILTER_ATTR_INFO)),
or(
ClientConnectionRecordDynamicSqlSupport.clientOsName,
isLike(filterMap.getSQLWildcard(ClientConnection.FILTER_ATTR_INFO)),
or(
ClientConnectionRecordDynamicSqlSupport.clientAddress,
isLike(filterMap.getSQLWildcard(ClientConnection.FILTER_ATTR_INFO))
)
)
);
}

return whereClause
.and(
ClientConnectionRecordDynamicSqlSupport.connectionToken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@

package ch.ethz.seb.sebserver.webservice.weblayer.api;

import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -106,21 +101,7 @@ public Page<ClientConnection> getPage(
final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString());
populateFilterMap(filterMap, institutionId, sort);

if (StringUtils.isNotBlank(sort) || filterMap.containsAny(EXT_FILTER)) {

final Collection<ClientConnection> allConnections = getAll(filterMap)
.getOrThrow();

return this.paginationService.buildPageFromList(
pageNumber,
pageSize,
sort,
allConnections,
pageClientConnectionFunction(filterMap, sort));

} else {
return super.getPage(institutionId, pageNumber, pageSize, sort, allRequestParams, request);
}
return super.getPage(institutionId, pageNumber, pageSize, sort, allRequestParams, request);
}

@RequestMapping(
Expand All @@ -145,7 +126,7 @@ public Page<ClientConnectionData> getClientConnectionDataPage(
final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString());
populateFilterMap(filterMap, institutionId, sort);

if (StringUtils.isNotBlank(sort) || filterMap.containsAny(EXT_FILTER)) {
if (StringUtils.isNotBlank(sort) && sort.contains(ClientConnectionData.ATTR_INDICATOR_VALUE)) {

final Collection<ClientConnectionData> allConnections = getAllData(filterMap)
.getOrThrow();
Expand All @@ -155,7 +136,7 @@ public Page<ClientConnectionData> getClientConnectionDataPage(
pageSize,
sort,
allConnections,
pageClientConnectionDataFunction(filterMap, sort));
c -> c.stream().sorted(new IndicatorValueComparator(sort)).collect(Collectors.toList()));
} else {

return this.paginationService.getPage(
Expand Down Expand Up @@ -227,42 +208,6 @@ private Result<Collection<ClientConnectionData>> getAllData(final FilterMap filt
.collect(Collectors.toList()));
}

private Function<Collection<ClientConnection>, List<ClientConnection>> pageClientConnectionFunction(
final FilterMap filterMap,
final String sort) {

return connections -> {

final List<ClientConnection> filtered = connections
.stream()
.filter(getClientConnectionFilter(filterMap))
.collect(Collectors.toList());

if (StringUtils.isNotBlank(sort)) {
filtered.sort(new ClientConnectionComparator(sort));
}
return filtered;
};
}

private Function<Collection<ClientConnectionData>, List<ClientConnectionData>> pageClientConnectionDataFunction(
final FilterMap filterMap,
final String sort) {

return connections -> {

final List<ClientConnectionData> filtered = connections
.stream()
.filter(getClientConnectionDataFilter(filterMap))
.collect(Collectors.toList());

if (StringUtils.isNotBlank(sort)) {
filtered.sort(new ClientConnectionDataComparator(sort));
}
return filtered;
};
}

private Predicate<ClientConnection> getClientConnectionFilter(final FilterMap filterMap) {
final String infoFilter = filterMap.getString(ClientConnection.FILTER_ATTR_INFO);
Predicate<ClientConnection> filter = Utils.truePredicate();
Expand All @@ -277,57 +222,25 @@ private Predicate<ClientConnectionData> getClientConnectionDataFilter(final Filt
return ccd -> clientConnectionFilter.test(ccd.clientConnection);
}

private static final class ClientConnectionComparator implements Comparator<ClientConnection> {
private static final class IndicatorValueComparator implements Comparator<ClientConnectionData> {

final String sortColumn;
//final ClientConnectionComparator clientConnectionComparator;
final String sort;
final Long iValuePK;
final boolean descending;

ClientConnectionComparator(final String sort) {
this.sortColumn = PageSortOrder.decode(sort);
IndicatorValueComparator(final String sort) {
this.sort = sort;
iValuePK = Long.valueOf(StringUtils.split(sort, Constants.UNDERLINE)[1]);
this.descending = PageSortOrder.getSortOrder(sort) == PageSortOrder.DESCENDING;
}

@Override
public int compare(final ClientConnection cc1, final ClientConnection cc2) {
int result = 0;
if (Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID.equals(this.sortColumn)) {
result = ObjectUtils.compare(cc1.userSessionId, cc2.userSessionId);
} else if (ClientConnection.ATTR_INFO.equals(this.sortColumn)) {
result = ObjectUtils.compare(cc1.getInfo(), cc2.getInfo());
} else if (Domain.CLIENT_CONNECTION.ATTR_STATUS.equals(this.sortColumn)) {
result = ObjectUtils.compare(cc1.getStatus(), cc2.getStatus());
} else {
result = ObjectUtils.compare(cc1.userSessionId, cc2.userSessionId);
}
return (this.descending) ? -result : result;
}
}

private static final class ClientConnectionDataComparator implements Comparator<ClientConnectionData> {

final ClientConnectionComparator clientConnectionComparator;

ClientConnectionDataComparator(final String sort) {
this.clientConnectionComparator = new ClientConnectionComparator(sort);
}

@Override
public int compare(final ClientConnectionData cc1, final ClientConnectionData cc2) {
if (this.clientConnectionComparator.sortColumn.startsWith(ClientConnectionData.ATTR_INDICATOR_VALUE)) {
try {
final Long iValuePK = Long.valueOf(StringUtils.split(
this.clientConnectionComparator.sortColumn,
Constants.UNDERLINE)[1]);
final Double indicatorValue1 = cc1.getIndicatorValue(iValuePK);
final Double indicatorValue2 = cc2.getIndicatorValue(iValuePK);
final int result = indicatorValue1.compareTo(indicatorValue2);
return (this.clientConnectionComparator.descending) ? -result : result;
} catch (final Exception e) {
return this.clientConnectionComparator.compare(cc1.clientConnection, cc2.clientConnection);
}
}

return this.clientConnectionComparator.compare(cc1.clientConnection, cc2.clientConnection);
final Double v1 = cc1.getIndicatorValue(iValuePK);
final Double v2 = cc2.getIndicatorValue(iValuePK);
final int result = ObjectUtils.compare(v1, v2);
return (this.descending) ? -result : result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ public ExamMonitoringController(

/** This is called by Spring to initialize the WebDataBinder and is used here to
* initialize the default value binding for the institutionId request-parameter
* that has the current users insitutionId as default.
*
* that has the current users institutionId as default.
* <p>
* See also UserService.addUsersInstitutionDefaultPropertySupport */
@InitBinder
public void initBinder(final WebDataBinder binder) {
Expand All @@ -133,9 +133,9 @@ public void initBinder(final WebDataBinder binder) {
}

/** Get a page of all currently running exams
*
* <p>
* GET /{api}/{entity-type-endpoint-name}
*
* <p>
* GET /admin-api/v1/monitoring
* GET /admin-api/v1/monitoring?page_number=2&page_size=10&sort=-name
* GET /admin-api/v1/monitoring?name=seb&active=true
Expand Down Expand Up @@ -193,9 +193,9 @@ public Page<Exam> getPage(
}

/** Get a page of all currently finished exams
*
* <p>
* GET /{api}/{entity-type-endpoint-name}
*
* <p>
* GET /admin-api/v1/monitoring
* GET /admin-api/v1/monitoring?page_number=2&page_size=10&sort=-name
* GET /admin-api/v1/monitoring?name=seb&active=true
Expand Down Expand Up @@ -589,13 +589,12 @@ private Predicate<ClientConnectionData> createMonitoringFilter(
}

final Set<Long> _filterClientGroups = filterClientGroups;
final Predicate<ClientConnectionData> filter = ccd -> {
return ccd -> {
if (ccd == null) {
return false;
}
return stateFilter.test(ccd) && ccd.filter(_filterClientGroups);
};
return filter;
}

}

0 comments on commit 8b15fdd

Please sign in to comment.