From 2f2a3670b792bd366f8fd9ad69985d0dd5a75ac6 Mon Sep 17 00:00:00 2001 From: anhefti Date: Wed, 3 Nov 2021 10:31:15 +0100 Subject: [PATCH] SEBSERV-191 backend implementation --- .../gbl/model/session/ClientEvent.java | 4 + .../servicelayer/PaginationService.java | 24 ++ .../servicelayer/PaginationServiceImpl.java | 14 + .../exam/SEBClientEventAdminService.java | 38 +++ .../exam/SEBClientEventExporter.java | 32 +++ .../impl/SEBClientEventAdminServiceImpl.java | 250 ++++++++++++++++++ .../exam/impl/SEBClientEventCSVExporter.java | 49 ++++ ...EBClientEventExportTransactionHandler.java | 113 ++++++++ .../weblayer/api/ClientEventController.java | 37 +-- 9 files changed, 532 insertions(+), 29 deletions(-) create mode 100644 src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/SEBClientEventAdminService.java create mode 100644 src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/SEBClientEventExporter.java create mode 100644 src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventAdminServiceImpl.java create mode 100644 src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventCSVExporter.java create mode 100644 src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventExportTransactionHandler.java diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientEvent.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientEvent.java index 535c07c2..886bd5ed 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientEvent.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientEvent.java @@ -68,6 +68,10 @@ public class ClientEvent implements Entity, IndicatorValueHolder { } } + public enum ExportType { + CSV + } + @JsonProperty(Domain.CLIENT_EVENT.ATTR_ID) public final Long id; 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 e01725aa..0d05a0fe 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 @@ -77,6 +77,30 @@ public interface PaginationService { final String tableName, final Supplier>> delegate); + /** Fetches a paged batch of objects + * + * NOTE: Paging always depends on SQL level. It depends on the collection given by the SQL select statement + * that is executed within MyBatis by using the MyBatis page service. + * Be aware that if the delegate that is given here applies an additional filter to the filtering done + * on SQL level, this will lead to paging with not fully filled pages or even to empty pages if the filter + * filters a lot of the entries given by the SQL statement away. + * So we recommend to apply as much of the filtering as possible on the SQL level and only if necessary and + * not avoidable, apply a additional filter on software-level that eventually filter one or two entities + * for a page. + * + * @param pageNumber the current page number + * @param pageSize the (full) size of the page + * @param sort the name of the sort column with a leading '-' for descending sort order + * @param tableName the name of the SQL table on which the pagination is applying to + * @param delegate a collection supplier the does the underling SQL query with specified pagination attributes + * @return Result refers to a Collection of specified type of objects or to an exception on error case */ + Result> fetch( + final int pageNumber, + final int pageSize, + final String sort, + final String tableName, + final Supplier>> delegate); + /** Use this to build a current Page from a given list of objects. * * @param the Type if list entities 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 8da775b7..9bb99708 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 @@ -147,6 +147,20 @@ public class PaginationServiceImpl implements PaginationService { }); } + @Override + public Result> fetch( + final int pageNumber, + final int pageSize, + final String sort, + final String tableName, + final Supplier>> delegate) { + + return Result.tryCatch(() -> { + setPagination(pageNumber, pageSize, sort, tableName); + return delegate.get().getOrThrow(); + }); + } + private String verifySortColumnName(final String sort, final String columnName) { if (StringUtils.isBlank(sort)) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/SEBClientEventAdminService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/SEBClientEventAdminService.java new file mode 100644 index 00000000..8acb9081 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/SEBClientEventAdminService.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.webservice.servicelayer.exam; + +import java.io.OutputStream; +import java.util.Collection; +import java.util.function.Predicate; + +import org.springframework.scheduling.annotation.Async; + +import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig; +import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; +import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; +import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType; +import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; + +public interface SEBClientEventAdminService { + + Result deleteAllClientEvents(Collection ids); + + @Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME) + void exportSEBClientLogs( + OutputStream output, + FilterMap filterMap, + String sort, + final Predicate predicate, + ExportType exportType, + boolean includeConnectionDetails, + boolean includeExamDetails); + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/SEBClientEventExporter.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/SEBClientEventExporter.java new file mode 100644 index 00000000..15f7fe23 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/SEBClientEventExporter.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.webservice.servicelayer.exam; + +import java.io.OutputStream; + +import ch.ethz.seb.sebserver.gbl.model.exam.Exam; +import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord; + +public interface SEBClientEventExporter { + + ExportType exportType(); + + void streamHeader( + OutputStream output, + boolean includeConnectionDetails, + boolean includeExamDetails); + + void streamData( + OutputStream output, + ClientEventRecord eventData, + ClientConnectionRecord connectionData, + Exam examData); +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventAdminServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventAdminServiceImpl.java new file mode 100644 index 00000000..be6b95bd --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventAdminServiceImpl.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.webservice.servicelayer.exam.impl; + +import java.io.OutputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import ch.ethz.seb.sebserver.gbl.api.APIMessage; +import ch.ethz.seb.sebserver.gbl.api.EntityType; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; +import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport.ErrorEntry; +import ch.ethz.seb.sebserver.gbl.model.exam.Exam; +import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; +import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType; +import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; +import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord; +import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; +import ch.ethz.seb.sebserver.webservice.servicelayer.exam.SEBClientEventAdminService; +import ch.ethz.seb.sebserver.webservice.servicelayer.exam.SEBClientEventExporter; + +@Lazy +@Service +@WebServiceProfile +public class SEBClientEventAdminServiceImpl implements SEBClientEventAdminService { + + private static final Logger log = LoggerFactory.getLogger(SEBClientEventAdminServiceImpl.class); + + private final PaginationService paginationService; + private final ClientEventDAO clientEventDAO; + private final SEBClientEventExportTransactionHandler sebClientEventExportTransactionHandler; + private final EnumMap exporter; + + public SEBClientEventAdminServiceImpl( + final PaginationService paginationService, + final ClientEventDAO clientEventDAO, + final SEBClientEventExportTransactionHandler sebClientEventExportTransactionHandler, + final Collection exporter) { + + this.paginationService = paginationService; + this.clientEventDAO = clientEventDAO; + this.sebClientEventExportTransactionHandler = sebClientEventExportTransactionHandler; + + this.exporter = new EnumMap<>(ExportType.class); + exporter.forEach(exp -> this.exporter.putIfAbsent(exp.exportType(), exp)); + } + + @Override + public Result deleteAllClientEvents(final Collection ids) { + return Result.tryCatch(() -> { + + if (ids == null || ids.isEmpty()) { + return EntityProcessingReport.ofEmptyError(); + } + + final Set sources = ids.stream() + .map(id -> new EntityKey(id, EntityType.CLIENT_EVENT)) + .collect(Collectors.toSet()); + + final Result> delete = this.clientEventDAO.delete(sources); + if (delete.hasError()) { + return new EntityProcessingReport( + Collections.emptyList(), + Collections.emptyList(), + Arrays.asList(new ErrorEntry(null, APIMessage.ErrorMessage.UNEXPECTED.of(delete.getError())))); + } else { + return new EntityProcessingReport( + sources, + delete.get(), + Collections.emptyList()); + } + }); + } + + @Override + public void exportSEBClientLogs( + final OutputStream output, + final FilterMap filterMap, + final String sort, + final Predicate predicate, + final ExportType exportType, + final boolean includeConnectionDetails, + final boolean includeExamDetails) { + + new exportRunner( + this.exporter.get(exportType), + includeConnectionDetails, + includeExamDetails, + new Pager(filterMap, sort, predicate), + output) + .run(); + + } + + private class exportRunner { + + private final SEBClientEventExporter exporter; + private final boolean includeConnectionDetails; + private final boolean includeExamDetails; + private final Iterator> pager; + private final OutputStream output; + + private final Map examCache; + private final Map connectionCache; + + public exportRunner( + final SEBClientEventExporter exporter, + final boolean includeConnectionDetails, + final boolean includeExamDetails, + final Iterator> pager, + final OutputStream output) { + + this.exporter = exporter; + this.includeConnectionDetails = includeConnectionDetails; + this.includeExamDetails = includeExamDetails; + this.pager = pager; + this.output = output; + + this.connectionCache = includeConnectionDetails ? new HashMap<>() : null; + this.examCache = includeExamDetails ? new HashMap<>() : null; + } + + public void run() { + + // first stream header line + this.exporter.streamHeader(this.output, this.includeConnectionDetails, this.includeExamDetails); + + // then batch with the pager and stream line per line + while (this.pager.hasNext()) { + this.pager.next().forEach(rec -> { + this.exporter.streamData( + this.output, + rec, + this.includeConnectionDetails ? getConnection(rec.getClientConnectionId()) : null, + this.includeExamDetails ? getExam(rec.getClientConnectionId()) : null); + }); + } + } + + private ClientConnectionRecord getConnection(final Long connectionId) { + if (!this.connectionCache.containsKey(connectionId)) { + SEBClientEventAdminServiceImpl.this.sebClientEventExportTransactionHandler + .clientConnectionById(connectionId) + .map(e -> this.connectionCache.put(connectionId, e)) + .onError(error -> log.error("Failed to get ClientConnectionRecord for id: {}", + connectionId, + error)); + } + + return this.connectionCache.get(connectionId); + } + + private Exam getExam(final Long connectionId) { + final ClientConnectionRecord connection = getConnection(connectionId); + final Long examId = connection.getExamId(); + if (!this.examCache.containsKey(examId)) { + SEBClientEventAdminServiceImpl.this.sebClientEventExportTransactionHandler + .examById(examId) + .map(e -> this.examCache.put(examId, e)) + .onError(error -> log.error("Failed to get Exam for id: {}", + examId, + error)); + } + + return this.examCache.get(examId); + } + } + + private class Pager implements Iterator> { + + private final FilterMap filterMap; + private final String sort; + private final Predicate predicate; + + private int pageNumber = 0; + private final int pageSize = 100; + + private Collection nextRecords; + + public Pager( + final FilterMap filterMap, + final String sort, + final Predicate predicate) { + + this.filterMap = filterMap; + this.sort = sort; + this.predicate = predicate; + + fetchNext(); + } + + @Override + public boolean hasNext() { + return this.nextRecords != null && !this.nextRecords.isEmpty(); + } + + @Override + public Collection next() { + final Collection result = this.nextRecords; + fetchNext(); + return result; + } + + private void fetchNext() { + try { + + this.nextRecords = SEBClientEventAdminServiceImpl.this.paginationService.fetch( + this.pageNumber, + this.pageSize, + this.sort, + ClientEventRecordDynamicSqlSupport.clientEventRecord.name(), + () -> SEBClientEventAdminServiceImpl.this.sebClientEventExportTransactionHandler + .allMatching(this.filterMap, this.predicate)) + .getOrThrow(); + + this.pageNumber++; + + } catch (final Exception e) { + log.error("Failed to fetch next batch: ", e); + this.nextRecords = null; + } + } + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventCSVExporter.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventCSVExporter.java new file mode 100644 index 00000000..a3290593 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventCSVExporter.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.webservice.servicelayer.exam.impl; + +import java.io.OutputStream; + +import ch.ethz.seb.sebserver.gbl.model.exam.Exam; +import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord; +import ch.ethz.seb.sebserver.webservice.servicelayer.exam.SEBClientEventExporter; + +public class SEBClientEventCSVExporter implements SEBClientEventExporter { + + @Override + public ExportType exportType() { + return ExportType.CSV; + } + + @Override + public void streamHeader( + final OutputStream output, + final boolean includeConnectionDetails, + final boolean includeExamDetails) { + + // TODO + } + + @Override + public void streamData( + final OutputStream output, + final ClientEventRecord eventData, + final ClientConnectionRecord connectionData, + final Exam examData) { + + // TODO + } + + private String toCSVString(final String text) { + + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventExportTransactionHandler.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventExportTransactionHandler.java new file mode 100644 index 00000000..6e24f501 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/SEBClientEventExportTransactionHandler.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.webservice.servicelayer.exam.impl; + +import static org.mybatis.dynamic.sql.SqlBuilder.equalTo; +import static org.mybatis.dynamic.sql.SqlBuilder.isEqualToWhenPresent; + +import java.util.Collection; +import java.util.function.Predicate; + +import org.mybatis.dynamic.sql.SqlBuilder; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import ch.ethz.seb.sebserver.gbl.model.exam.Exam; +import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; +import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; +import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType; +import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; +import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientConnectionRecordDynamicSqlSupport; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientConnectionRecordMapper; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordMapper; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; + +@Lazy +@Component +@WebServiceProfile +public class SEBClientEventExportTransactionHandler { + + private final ClientEventRecordMapper clientEventRecordMapper; + private final ClientConnectionRecordMapper clientConnectionRecordMapper; + private final ExamDAO examDAO; + + public SEBClientEventExportTransactionHandler( + final ClientEventRecordMapper clientEventRecordMapper, + final ClientConnectionRecordMapper clientConnectionRecordMapper, + final ExamDAO examDAO) { + + this.clientEventRecordMapper = clientEventRecordMapper; + this.clientConnectionRecordMapper = clientConnectionRecordMapper; + this.examDAO = examDAO; + } + + @Transactional(readOnly = true) + public Result> allMatching( + final FilterMap filterMap, + final Predicate predicate) { + + return Result.tryCatch(() -> this.clientEventRecordMapper + .selectByExample() + .leftJoin(ClientConnectionRecordDynamicSqlSupport.clientConnectionRecord) + .on( + ClientConnectionRecordDynamicSqlSupport.id, + equalTo(ClientEventRecordDynamicSqlSupport.clientConnectionId)) + .where( + ClientConnectionRecordDynamicSqlSupport.institutionId, + isEqualToWhenPresent(filterMap.getInstitutionId())) + .and( + ClientConnectionRecordDynamicSqlSupport.examId, + isEqualToWhenPresent(filterMap.getClientEventExamId())) + .and( + ClientConnectionRecordDynamicSqlSupport.examUserSessionId, + SqlBuilder.isLikeWhenPresent(filterMap.getSQLWildcard(ClientConnection.FILTER_ATTR_SESSION_ID))) + .and( + ClientEventRecordDynamicSqlSupport.clientConnectionId, + isEqualToWhenPresent(filterMap.getClientEventConnectionId())) + .and( + ClientEventRecordDynamicSqlSupport.type, + isEqualToWhenPresent(filterMap.getClientEventTypeId())) + .and( + ClientEventRecordDynamicSqlSupport.type, + SqlBuilder.isNotEqualTo(EventType.LAST_PING.id)) + .and( + ClientEventRecordDynamicSqlSupport.clientTime, + SqlBuilder.isGreaterThanOrEqualToWhenPresent(filterMap.getClientEventClientTimeFrom())) + .and( + ClientEventRecordDynamicSqlSupport.clientTime, + SqlBuilder.isLessThanOrEqualToWhenPresent(filterMap.getClientEventClientTimeTo())) + .and( + ClientEventRecordDynamicSqlSupport.serverTime, + SqlBuilder.isGreaterThanOrEqualToWhenPresent(filterMap.getClientEventServerTimeFrom())) + .and( + ClientEventRecordDynamicSqlSupport.serverTime, + SqlBuilder.isLessThanOrEqualToWhenPresent(filterMap.getClientEventServerTimeTo())) + .and( + ClientEventRecordDynamicSqlSupport.text, + SqlBuilder.isLikeWhenPresent(filterMap.getClientEventText())) + .build() + .execute()); + } + + @Transactional(readOnly = true) + public Result clientConnectionById(final Long id) { + return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectByPrimaryKey(id)); + } + + public Result examById(final Long id) { + return this.examDAO.byPK(id); + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java index 349c42eb..947ca057 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java @@ -8,13 +8,9 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.EnumSet; import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; @@ -28,13 +24,10 @@ import org.springframework.web.bind.annotation.RestController; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType; -import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType; import ch.ethz.seb.sebserver.gbl.model.EntityDependency; -import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; -import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport.ErrorEntry; import ch.ethz.seb.sebserver.gbl.model.GrantEntity; import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; @@ -53,6 +46,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.exam.SEBClientEventAdminService; import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService; @WebServiceProfile @@ -62,6 +56,7 @@ public class ClientEventController extends ReadonlyEntityController sources = ids.stream() - .map(id -> new EntityKey(id, EntityType.CLIENT_EVENT)) - .collect(Collectors.toSet()); - - final Result> delete = this.clientEventDAO.delete(sources); - - if (delete.hasError()) { - return new EntityProcessingReport( - Collections.emptyList(), - Collections.emptyList(), - Arrays.asList(new ErrorEntry(null, APIMessage.ErrorMessage.UNEXPECTED.of(delete.getError())))); - } else { - return new EntityProcessingReport( - sources, - delete.get(), - Collections.emptyList()); - } + return this.sebClientEventAdminService + .deleteAllClientEvents(ids) + .getOrThrow(); } @Override