separated clientConnection and clientConnectionData page filter and sort

This commit is contained in:
anhefti 2022-03-28 17:29:26 +02:00
parent 3744e10406
commit 085ec45fb1
3 changed files with 153 additions and 32 deletions

View file

@ -17,8 +17,10 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.util.Utils;
@JsonIgnoreProperties(ignoreUnknown = true)
@ -100,6 +102,26 @@ public class ClientConnectionData implements GrantEntity {
return this.missingPing || this.pendingNotification;
}
@JsonIgnore
public Double getIndicatorValue(final Long indicatorId) {
return this.indicatorValues
.stream()
.filter(indicatorValue -> indicatorValue.getIndicatorId().equals(indicatorId))
.findFirst()
.map(iv -> iv.getValue())
.orElse(Double.NaN);
}
@JsonIgnore
public String getIndicatorDisplayValue(final Indicator indicator) {
return this.indicatorValues
.stream()
.filter(indicatorValue -> indicatorValue.getIndicatorId().equals(indicator.id))
.findFirst()
.map(iv -> IndicatorValue.getDisplayValue(iv, indicator.type))
.orElse(Constants.EMPTY_NOTE);
}
public ClientConnection getClientConnection() {
return this.clientConnection;
}

View file

@ -10,14 +10,12 @@ package ch.ethz.seb.sebserver.gui.content.monitoring;
import java.util.Collection;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import org.eclipse.swt.widgets.Composite;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
@ -26,7 +24,6 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
@ -162,7 +159,7 @@ public class FinishedExam implements TemplateComposer {
tableBuilder.withColumn(new ColumnDefinition<>(
indicator.name,
new LocTextKey(indicator.name),
indicatorValueFunction(indicator)));
cc -> cc.getIndicatorDisplayValue(indicator)));
});
final EntityTable<ClientConnectionData> table = tableBuilder.compose(pageContext.copyOf(content));
@ -175,15 +172,4 @@ public class FinishedExam implements TemplateComposer {
.publishIf(isExamSupporter, false);
}
public Function<ClientConnectionData, String> indicatorValueFunction(final Indicator indicator) {
return clientConnectionData -> {
return clientConnectionData.indicatorValues
.stream()
.filter(indicatorValue -> indicatorValue.getIndicatorId().equals(indicator.id))
.findFirst()
.map(iv -> IndicatorValue.getDisplayValue(iv, indicator.type))
.orElse(Constants.EMPTY_NOTE);
};
}
}

View file

@ -82,6 +82,73 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
this.sebClientConnectionService = sebClientConnectionService;
}
/** The generic endpoint to get a Page of domain-entities of a specific type.
* </p>
* GET /{api}/{domain-entity-name}
* </p>
* For example for the "exam" domain-entity
* GET /admin-api/v1/exam
* GET /admin-api/v1/exam?page_number=2&page_size=10&sort=-name
* GET /admin-api/v1/exam?name=seb&active=true
* </p>
* Sorting: the sort parameter to sort the list of entities before paging
* the sort parameter is the name of the entity-model attribute to sort with a leading '-' sign for
* descending sort order. Note that not all entity-model attribute are suited for sorting while the most
* are.
* </p>
* Filter: The filter attributes accepted by this API depend on the actual entity model (domain object)
* and are of the form [domain-attribute-name]=[filter-value]. E.g.: name=abc or type=EXAM. Usually
* filter attributes of text type are treated as SQL wildcard with %[text]% to filter all text containing
* a given text-snippet.
*
* @param institutionId The institution identifier of the request.
* Default is the institution identifier of the institution of the current user
* @param pageNumber the number of the page that is requested
* @param pageSize the size of the page that is requested
* @param sort the sort parameter to sort the list of entities before paging
* the sort parameter is the name of the entity-model attribute to sort with a leading '-' sign for
* descending sort order.
* @param allRequestParams a MultiValueMap of all request parameter that is used for filtering.
* @return Page of domain-model-entities of specified type */
@Override
@RequestMapping(
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public Page<ClientConnection> getPage(
@RequestParam(
name = API.PARAM_INSTITUTION_ID,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@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, required = false) final String sort,
@RequestParam final MultiValueMap<String, String> allRequestParams,
final HttpServletRequest request) {
// at least current user must have read access for specified entity type within its own institution
checkReadPrivilege(institutionId);
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);
}
}
@RequestMapping(
path = API.SEB_CLIENT_CONNECTION_DATA_ENDPOINT,
method = RequestMethod.GET,
@ -114,7 +181,7 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
pageSize,
sort,
allConnections,
pageFunction(filterMap, sort));
pageClientConnectionDataFunction(filterMap, sort));
} else {
return this.paginationService.getPage(
@ -138,18 +205,6 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
.getOrThrow();
}
// @Override
// protected Result<Collection<ClientConnection>> getAll(final FilterMap filterMap) {
// final String infoFilter = filterMap.getString(ClientConnection.FILTER_ATTR_INFO);
// if (StringUtils.isNotBlank(infoFilter)) {
// return super.getAll(filterMap)
// .map(all -> all.stream().filter(c -> c.getInfo() == null || c.getInfo().contains(infoFilter))
// .collect(Collectors.toList()));
// }
//
// return super.getAll(filterMap);
// }
@Override
public Collection<EntityDependency> getDependencies(
final String modelId,
@ -198,15 +253,35 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
.collect(Collectors.toList()));
}
private Function<Collection<ClientConnectionData>, List<ClientConnectionData>> pageFunction(
private Function<Collection<ClientConnection>, List<ClientConnection>> pageClientConnectionFunction(
final FilterMap filterMap,
final String sort) {
return connections -> {
final List<ClientConnectionData> filtered = connections.stream()
.filter(getFilter(filterMap))
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));
}
@ -214,7 +289,16 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
};
}
private Predicate<ClientConnectionData> getFilter(final FilterMap filterMap) {
private Predicate<ClientConnection> getClientConnectionFilter(final FilterMap filterMap) {
final String infoFilter = filterMap.getString(ClientConnection.FILTER_ATTR_INFO);
Predicate<ClientConnection> filter = Utils.truePredicate();
if (StringUtils.isNotBlank(infoFilter)) {
filter = c -> c.getInfo() == null || c.getInfo().contains(infoFilter);
}
return filter;
}
private Predicate<ClientConnectionData> getClientConnectionDataFilter(final FilterMap filterMap) {
final String infoFilter = filterMap.getString(ClientConnection.FILTER_ATTR_INFO);
Predicate<ClientConnectionData> filter = Utils.truePredicate();
if (StringUtils.isNotBlank(infoFilter)) {
@ -223,6 +307,35 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
return filter;
}
private static final class ClientConnectionComparator implements Comparator<ClientConnection> {
final String sortColumn;
final boolean descending;
ClientConnectionComparator(final String sort) {
this.sortColumn = PageSortOrder.decode(sort);
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 = cc1.userSessionId
.compareTo(cc2.userSessionId);
} else if (ClientConnection.ATTR_INFO.equals(this.sortColumn)) {
result = cc1.getInfo().compareTo(cc2.getInfo());
} else if (Domain.CLIENT_CONNECTION.ATTR_STATUS.equals(this.sortColumn)) {
result = cc1.getStatus()
.compareTo(cc2.getStatus());
} else {
result = cc1.userSessionId
.compareTo(cc2.userSessionId);
}
return (this.descending) ? -result : result;
}
}
private static final class ClientConnectionDataComparator implements Comparator<ClientConnectionData> {
final String sortColumn;