SEBSERV-17 #implementation of ExamDAO and improvements for bulk actions

This commit is contained in:
anhefti 2019-01-16 10:47:12 +01:00
parent 1ba0345178
commit 2f8b796b86
16 changed files with 349 additions and 271 deletions

View file

@ -27,15 +27,15 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
@WebServiceProfile @WebServiceProfile
public class BulkActionService { public class BulkActionService {
private final Map<EntityType, BulkActionSupport> supporter; private final Map<EntityType, BulkActionSupportDAO<?>> supporter;
private final UserActivityLogDAO userActivityLogDAO; private final UserActivityLogDAO userActivityLogDAO;
public BulkActionService( public BulkActionService(
final Collection<BulkActionSupport> supporter, final Collection<BulkActionSupportDAO<?>> supporter,
final UserActivityLogDAO userActivityLogDAO) { final UserActivityLogDAO userActivityLogDAO) {
this.supporter = new HashMap<>(); this.supporter = new HashMap<>();
for (final BulkActionSupport support : supporter) { for (final BulkActionSupportDAO<?> support : supporter) {
this.supporter.put(support.entityType(), support); this.supporter.put(support.entityType(), support);
} }
this.userActivityLogDAO = userActivityLogDAO; this.userActivityLogDAO = userActivityLogDAO;
@ -43,7 +43,7 @@ public class BulkActionService {
public void collectDependencies(final BulkAction action) { public void collectDependencies(final BulkAction action) {
checkProcessing(action); checkProcessing(action);
for (final BulkActionSupport sup : this.supporter.values()) { for (final BulkActionSupportDAO<?> sup : this.supporter.values()) {
action.dependencies.addAll(sup.getDependencies(action)); action.dependencies.addAll(sup.getDependencies(action));
} }
action.alreadyProcessed = true; action.alreadyProcessed = true;
@ -52,7 +52,7 @@ public class BulkActionService {
public void doBulkAction(final BulkAction action) { public void doBulkAction(final BulkAction action) {
checkProcessing(action); checkProcessing(action);
final BulkActionSupport supportForSource = this.supporter.get(action.sourceType); final BulkActionSupportDAO<?> supportForSource = this.supporter.get(action.sourceType);
if (supportForSource == null) { if (supportForSource == null) {
action.alreadyProcessed = true; action.alreadyProcessed = true;
return; return;
@ -62,10 +62,10 @@ public class BulkActionService {
if (!action.dependencies.isEmpty()) { if (!action.dependencies.isEmpty()) {
// process dependencies first... // process dependencies first...
final List<BulkActionSupport> dependancySupporter = final List<BulkActionSupportDAO<?>> dependancySupporter =
getDependancySupporter(action); getDependancySupporter(action);
for (final BulkActionSupport support : dependancySupporter) { for (final BulkActionSupportDAO<?> support : dependancySupporter) {
action.result.addAll(support.processBulkAction(action)); action.result.addAll(support.processBulkAction(action));
} }
} }
@ -111,12 +111,12 @@ public class BulkActionService {
} }
} }
private List<BulkActionSupport> getDependancySupporter(final BulkAction action) { private List<BulkActionSupportDAO<?>> getDependancySupporter(final BulkAction action) {
switch (action.type) { switch (action.type) {
case ACTIVATE: case ACTIVATE:
case DEACTIVATE: case DEACTIVATE:
case HARD_DELETE: { case HARD_DELETE: {
final List<BulkActionSupport> dependantSupporterInHierarchicalOrder = final List<BulkActionSupportDAO<?>> dependantSupporterInHierarchicalOrder =
getDependantSupporterInHierarchicalOrder(action); getDependantSupporterInHierarchicalOrder(action);
Collections.reverse(dependantSupporterInHierarchicalOrder); Collections.reverse(dependantSupporterInHierarchicalOrder);
return dependantSupporterInHierarchicalOrder; return dependantSupporterInHierarchicalOrder;
@ -126,7 +126,7 @@ public class BulkActionService {
} }
} }
private List<BulkActionSupport> getDependantSupporterInHierarchicalOrder(final BulkAction action) { private List<BulkActionSupportDAO<?>> getDependantSupporterInHierarchicalOrder(final BulkAction action) {
switch (action.sourceType) { switch (action.sourceType) {
case INSTITUTION: case INSTITUTION:
return Arrays.asList( return Arrays.asList(

View file

@ -1,50 +0,0 @@
/*
* Copyright (c) 2019 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.bulkaction;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityKeyAndName;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.util.Result;
public interface BulkActionSupport {
/** Get the entity type for a concrete EntityDAO implementation.
*
* @return The EntityType for a concrete EntityDAO implementation */
EntityType entityType();
Set<EntityKey> getDependencies(BulkAction bulkAction);
Result<Collection<Entity>> bulkLoadEntities(Collection<EntityKey> keys);
@Transactional(readOnly = true)
default Result<Collection<EntityKeyAndName>> bulkLoadEntityNames(final Collection<EntityKey> keys) {
return Result.tryCatch(() -> {
return bulkLoadEntities(keys)
.getOrThrow()
.stream()
.map(entity -> new EntityKeyAndName(
EntityType.INSTITUTION,
entity.getModelId(),
entity.getName()))
.collect(Collectors.toList());
});
}
Collection<Result<EntityKey>> processBulkAction(BulkAction bulkAction);
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2019 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.bulkaction;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityKeyAndName;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ActivatableEntityDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.EntityDAO;
public interface BulkActionSupportDAO<T extends Entity> {
Logger log = LoggerFactory.getLogger(BulkActionSupportDAO.class);
/** Get the entity type for a concrete EntityDAO implementation.
*
* @return The EntityType for a concrete EntityDAO implementation */
EntityType entityType();
Set<EntityKey> getDependencies(BulkAction bulkAction);
Result<Collection<T>> bulkLoadEntities(Collection<EntityKey> keys);
@Transactional(readOnly = true)
default Result<Collection<EntityKeyAndName>> bulkLoadEntityNames(final Collection<EntityKey> keys) {
return Result.tryCatch(() -> {
return bulkLoadEntities(keys)
.getOrThrow()
.stream()
.map(entity -> new EntityKeyAndName(
EntityType.INSTITUTION,
entity.getModelId(),
entity.getName()))
.collect(Collectors.toList());
});
}
@Transactional
default Collection<Result<EntityKey>> processBulkAction(final BulkAction bulkAction) {
final Set<EntityKey> all = bulkAction.extractKeys(entityType());
switch (bulkAction.type) {
case ACTIVATE:
return (this instanceof ActivatableEntityDAO)
? ((ActivatableEntityDAO<?>) this).setActive(all, true)
: Collections.emptyList();
case DEACTIVATE:
return (this instanceof ActivatableEntityDAO)
? ((ActivatableEntityDAO<?>) this).setActive(all, false)
: Collections.emptyList();
case HARD_DELETE:
return (this instanceof EntityDAO)
? ((EntityDAO<?>) this).delete(all)
: Collections.emptyList();
}
// should never happen
throw new UnsupportedOperationException("Unsupported Bulk Action: " + bulkAction);
}
@Transactional(readOnly = true)
default Set<EntityKey> getDependencies(
final BulkAction bulkAction,
final Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction) {
return bulkAction.sources
.stream()
.map(selectionFunction) // apply select function for each source key
.peek(result -> result.onErrorDo(error -> log.error("Unexpected error: ", error)))
.flatMap(Result::skipOnError) // handle and skip results with error
.flatMap(Collection::stream) // Flatten stream of Collection in to one stream
.collect(Collectors.toSet());
}
}

View file

@ -8,12 +8,12 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao; package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors;
import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
@ -73,7 +73,7 @@ public interface EntityDAO<T extends Entity> {
* happened */ * happened */
Collection<Result<EntityKey>> delete(Set<EntityKey> all); Collection<Result<EntityKey>> delete(Set<EntityKey> all);
/** Utility method to extract an expected single resource entry form a Collection of specified type. /** Context based utility method to extract an expected single resource entry form a Collection of specified type.
* Gets a Result refer to an expected single resource entry form a Collection of specified type or refer * Gets a Result refer to an expected single resource entry form a Collection of specified type or refer
* to a ResourceNotFoundException if specified collection is null or empty or refer to a * to a ResourceNotFoundException if specified collection is null or empty or refer to a
* unexpected RuntimeException if there are more then the expected single element in the given collection * unexpected RuntimeException if there are more then the expected single element in the given collection
@ -95,28 +95,27 @@ public interface EntityDAO<T extends Entity> {
return Result.of(resources.iterator().next()); return Result.of(resources.iterator().next());
} }
default List<Long> extractIdsFromKeys( /** Context based utility method to extract a list of id's (PK) from a collection of various EntityKey
final Collection<EntityKey> keys, * This uses the EntityType defined by this instance to filter all EntityKey by the given type and
final Collection<Result<EntityKey>> result) { * convert the matching EntityKey's to id's (PK's)
*
* Use this if you need to transform a Collection of EntityKey into a extracted List of id's of a specified
* EntityType
*
* @param keys Collection of EntityKey of various types
* @return List of id's (PK's) from the given key collection that match the concrete EntityType */
default List<Long> extractIdsFromKeys(final Collection<EntityKey> keys) {
if (keys == null) { if (keys == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
final EntityType entityType = entityType(); final EntityType entityType = entityType();
final List<Long> ids = new ArrayList<>(); return keys
.stream()
for (final EntityKey key : keys) { .filter(key -> key.entityType == entityType)
if (key.entityType == entityType) { .map(key -> Long.valueOf(key.entityId))
try { .collect(Collectors.toList());
ids.add(Long.valueOf(key.entityId));
} catch (final Exception e) {
result.add(Result.ofError(new IllegalArgumentException("Invalid id for EntityKey: " + key)));
}
}
}
return ids;
} }
} }

View file

@ -13,8 +13,9 @@ import java.util.Collection;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
public interface ExamDAO extends ActivatableEntityDAO<Exam> { public interface ExamDAO extends ActivatableEntityDAO<Exam>, BulkActionSupportDAO<Exam> {
Result<Exam> importFromQuizData(QuizData quizData); Result<Exam> importFromQuizData(QuizData quizData);

View file

@ -12,8 +12,9 @@ import java.util.Collection;
import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
public interface InstitutionDAO extends ActivatableEntityDAO<Institution> { public interface InstitutionDAO extends ActivatableEntityDAO<Institution>, BulkActionSupportDAO<Institution> {
Result<Collection<Institution>> allMatching(String name, Boolean active); Result<Collection<Institution>> allMatching(String name, Boolean active);

View file

@ -15,8 +15,9 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; 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.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
public interface LmsSetupDAO extends ActivatableEntityDAO<LmsSetup> { public interface LmsSetupDAO extends ActivatableEntityDAO<LmsSetup>, BulkActionSupportDAO<LmsSetup> {
@Transactional(readOnly = true) @Transactional(readOnly = true)
default Result<Collection<LmsSetup>> allOfInstitution(final Long institutionId, final Boolean active) { default Result<Collection<LmsSetup>> allOfInstitution(final Long institutionId, final Boolean active) {

View file

@ -19,11 +19,12 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserMod; import ch.ethz.seb.sebserver.gbl.model.user.UserMod;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
/** The Data Access Object for all User related data like get user data within UserInfo, /** The Data Access Object for all User related data like get user data within UserInfo,
* save and modify user related data within UserMod and get internal user principal data * save and modify user related data within UserMod and get internal user principal data
* within SEBServerUser. */ * within SEBServerUser. */
public interface UserDAO extends ActivatableEntityDAO<UserInfo> { public interface UserDAO extends ActivatableEntityDAO<UserInfo>, BulkActionSupportDAO<UserInfo> {
/** Use this to get UserInfo by users UUID /** Use this to get UserInfo by users UUID
* *
@ -87,6 +88,6 @@ public interface UserDAO extends ActivatableEntityDAO<UserInfo> {
* *
* @param uuid The UUID of the user * @param uuid The UUID of the user
* @return a Collection containing EntityKey's of all entities that belongs to a given User */ * @return a Collection containing EntityKey's of all entities that belongs to a given User */
Collection<EntityKey> getAllUserData(String uuid); Collection<EntityKey> getAllUserRelatedData(String uuid);
} }

View file

@ -8,8 +8,7 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl; package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo; import static org.mybatis.dynamic.sql.SqlBuilder.*;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualToWhenPresent;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -17,6 +16,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -29,7 +29,6 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
@ -42,14 +41,13 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamic
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ExamRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ExamRecord;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
@Lazy @Lazy
@Component @Component
public class ExamDAOImpl implements ExamDAO, BulkActionSupport { public class ExamDAOImpl implements ExamDAO {
private final ExamRecordMapper examRecordMapper; private final ExamRecordMapper examRecordMapper;
private final LmsAPIService lmsAPIService; private final LmsAPIService lmsAPIService;
@ -162,20 +160,6 @@ public class ExamDAOImpl implements ExamDAO, BulkActionSupport {
}); });
} }
@Override
@Transactional
public Collection<Result<EntityKey>> setActive(final Set<EntityKey> all, final boolean active) {
// TODO Auto-generated method stub
return Collections.emptyList();
}
@Override
@Transactional
public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) {
// TODO Auto-generated method stub
return Collections.emptyList();
}
@Override @Override
@Transactional @Transactional
public Result<Exam> importFromQuizData(final QuizData quizData) { public Result<Exam> importFromQuizData(final QuizData quizData) {
@ -184,24 +168,105 @@ public class ExamDAOImpl implements ExamDAO, BulkActionSupport {
} }
@Override @Override
@Transactional(readOnly = true) @Transactional
public Set<EntityKey> getDependencies(final BulkAction bulkAction) { public Collection<Result<EntityKey>> setActive(final Set<EntityKey> all, final boolean active) {
// TODO Auto-generated method stub final List<Long> ids = extractIdsFromKeys(all);
return Collections.emptySet(); final ExamRecord examRecord = new ExamRecord(null, null, null, null, null,
} null, null, null, BooleanUtils.toInteger(active));
@Override try {
@Transactional(readOnly = true)
public Result<Collection<Entity>> bulkLoadEntities(final Collection<EntityKey> keys) { this.examRecordMapper.updateByExampleSelective(examRecord)
// TODO Auto-generated method stub .where(ExamRecordDynamicSqlSupport.id, isIn(ids))
return Result.ofTODO(); .build()
.execute();
return ids.stream()
.map(id -> Result.of(new EntityKey(id, EntityType.EXAM)))
.collect(Collectors.toList());
} catch (final Exception e) {
return ids.stream()
.map(id -> Result.<EntityKey> ofError(new RuntimeException(
"Activation failed on unexpected exception for Exam of id: " + id, e)))
.collect(Collectors.toList());
}
} }
@Override @Override
@Transactional @Transactional
public Collection<Result<EntityKey>> processBulkAction(final BulkAction bulkAction) { public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) {
// TODO Auto-generated method stub final List<Long> ids = extractIdsFromKeys(all);
return Collections.emptyList();
try {
this.examRecordMapper.deleteByExample()
.where(ExamRecordDynamicSqlSupport.id, isIn(ids))
.build()
.execute();
return ids.stream()
.map(id -> Result.of(new EntityKey(id, EntityType.EXAM)))
.collect(Collectors.toList());
} catch (final Exception e) {
return ids.stream()
.map(id -> Result.<EntityKey> ofError(new RuntimeException(
"Deletion failed on unexpected exception for Exam of id: " + id, e)))
.collect(Collectors.toList());
}
}
@Override
@Transactional(readOnly = true)
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
// define the select function in case of source type
final Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction =
(bulkAction.sourceType == EntityType.INSTITUTION)
? this::allIdsOfInstitution
: (bulkAction.sourceType == EntityType.LMS_SETUP)
? this::allIdsOfLmsSetup
: key -> Result.of(Collections.emptyList()); // else : empty select function
return getDependencies(bulkAction, selectionFunction);
}
@Override
@Transactional(readOnly = true)
public Result<Collection<Exam>> bulkLoadEntities(final Collection<EntityKey> keys) {
return Result.tryCatch(() -> {
final List<Long> ids = extractIdsFromKeys(keys);
return this.examRecordMapper.selectByExample()
.where(ExamRecordDynamicSqlSupport.id, isIn(ids))
.build()
.execute();
}).flatMap(this::toDomainModel);
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> {
return this.examRecordMapper.selectIdsByExample()
.where(ExamRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.entityId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.LMS_SETUP))
.collect(Collectors.toList());
});
}
private Result<Collection<EntityKey>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) {
return Result.tryCatch(() -> {
return this.examRecordMapper.selectIdsByExample()
.where(ExamRecordDynamicSqlSupport.lmsSetupId,
isEqualTo(Long.valueOf(lmsSetupKey.entityId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.LMS_SETUP))
.collect(Collectors.toList());
});
} }
private Result<ExamRecord> recordById(final Long id) { private Result<ExamRecord> recordById(final Long id) {

View file

@ -11,7 +11,6 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualToWhenPresent; import static org.mybatis.dynamic.sql.SqlBuilder.isEqualToWhenPresent;
import static org.mybatis.dynamic.sql.SqlBuilder.isIn; import static org.mybatis.dynamic.sql.SqlBuilder.isIn;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -27,7 +26,6 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
@ -37,14 +35,13 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecord
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.InstitutionRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.InstitutionRecord;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler;
@Lazy @Lazy
@Component @Component
public class InstitutionDAOImpl implements InstitutionDAO, BulkActionSupport { public class InstitutionDAOImpl implements InstitutionDAO {
private final InstitutionRecordMapper institutionRecordMapper; private final InstitutionRecordMapper institutionRecordMapper;
@ -126,9 +123,7 @@ public class InstitutionDAOImpl implements InstitutionDAO, BulkActionSupport {
@Override @Override
@Transactional @Transactional
public Collection<Result<EntityKey>> setActive(final Set<EntityKey> all, final boolean active) { public Collection<Result<EntityKey>> setActive(final Set<EntityKey> all, final boolean active) {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(all);
final List<Long> ids = extractIdsFromKeys(all, result);
final InstitutionRecord institutionRecord = new InstitutionRecord( final InstitutionRecord institutionRecord = new InstitutionRecord(
null, null, null, BooleanUtils.toInteger(active), null); null, null, null, BooleanUtils.toInteger(active), null);
@ -152,8 +147,7 @@ public class InstitutionDAOImpl implements InstitutionDAO, BulkActionSupport {
@Override @Override
@Transactional @Transactional
public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) { public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(all);
final List<Long> ids = extractIdsFromKeys(all, result);
try { try {
this.institutionRecordMapper.deleteByExample() this.institutionRecordMapper.deleteByExample()
@ -181,10 +175,9 @@ public class InstitutionDAOImpl implements InstitutionDAO, BulkActionSupport {
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public Result<Collection<Entity>> bulkLoadEntities(final Collection<EntityKey> keys) { public Result<Collection<Institution>> bulkLoadEntities(final Collection<EntityKey> keys) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(keys);
final List<Long> ids = extractIdsFromKeys(keys, result);
return this.institutionRecordMapper.selectByExample() return this.institutionRecordMapper.selectByExample()
.where(InstitutionRecordDynamicSqlSupport.id, isIn(ids)) .where(InstitutionRecordDynamicSqlSupport.id, isIn(ids))
@ -197,25 +190,6 @@ public class InstitutionDAOImpl implements InstitutionDAO, BulkActionSupport {
}); });
} }
@Override
@Transactional
public Collection<Result<EntityKey>> processBulkAction(final BulkAction bulkAction) {
final Set<EntityKey> all = bulkAction.extractKeys(EntityType.INSTITUTION);
switch (bulkAction.type) {
case ACTIVATE:
return setActive(all, true);
case DEACTIVATE:
return setActive(all, false);
case HARD_DELETE:
return delete(all);
}
// should never happen
throw new UnsupportedOperationException("Unsupported Bulk Action: " + bulkAction);
}
private Result<InstitutionRecord> recordById(final Long id) { private Result<InstitutionRecord> recordById(final Long id) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
final InstitutionRecord record = this.institutionRecordMapper.selectByPrimaryKey(id); final InstitutionRecord record = this.institutionRecordMapper.selectByPrimaryKey(id);

View file

@ -11,10 +11,8 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
import static ch.ethz.seb.sebserver.gbl.util.Utils.toSQLWildcard; import static ch.ethz.seb.sebserver.gbl.util.Utils.toSQLWildcard;
import static org.mybatis.dynamic.sql.SqlBuilder.*; import static org.mybatis.dynamic.sql.SqlBuilder.*;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -23,13 +21,10 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter; import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter;
import org.mybatis.dynamic.sql.select.QueryExpressionDSL; import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
@ -39,16 +34,13 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordDyn
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.LmsSetupRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.LmsSetupRecord;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler;
@Lazy @Lazy
@Component @Component
public class LmsSetupDAOImpl implements LmsSetupDAO, BulkActionSupport { public class LmsSetupDAOImpl implements LmsSetupDAO {
private static final Logger log = LoggerFactory.getLogger(LmsSetupDAOImpl.class);
private final LmsSetupRecordMapper lmsSetupRecordMapper; private final LmsSetupRecordMapper lmsSetupRecordMapper;
@ -105,9 +97,15 @@ public class LmsSetupDAOImpl implements LmsSetupDAO, BulkActionSupport {
final String _lmsType = (lmsType != null) ? lmsType.name() : null; final String _lmsType = (lmsType != null) ? lmsType.name() : null;
return this.lmsSetupRecordMapper return this.lmsSetupRecordMapper
.selectByExample() .selectByExample()
.where(LmsSetupRecordDynamicSqlSupport.institutionId, isEqualToWhenPresent(institutionId)) .where(
.and(LmsSetupRecordDynamicSqlSupport.name, isLikeWhenPresent(toSQLWildcard(name))) LmsSetupRecordDynamicSqlSupport.institutionId,
.and(LmsSetupRecordDynamicSqlSupport.lmsType, isEqualToWhenPresent(_lmsType)) isEqualToWhenPresent(institutionId))
.and(
LmsSetupRecordDynamicSqlSupport.name,
isLikeWhenPresent(toSQLWildcard(name)))
.and(
LmsSetupRecordDynamicSqlSupport.lmsType,
isEqualToWhenPresent(_lmsType))
.and( .and(
LmsSetupRecordDynamicSqlSupport.active, LmsSetupRecordDynamicSqlSupport.active,
isEqualToWhenPresent(BooleanUtils.toIntegerObject(active))) isEqualToWhenPresent(BooleanUtils.toIntegerObject(active)))
@ -139,9 +137,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO, BulkActionSupport {
@Override @Override
@Transactional @Transactional
public Collection<Result<EntityKey>> setActive(final Set<EntityKey> all, final boolean active) { public Collection<Result<EntityKey>> setActive(final Set<EntityKey> all, final boolean active) {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(all);
final List<Long> ids = extractIdsFromKeys(all, result);
final LmsSetupRecord lmsSetupRecord = new LmsSetupRecord( final LmsSetupRecord lmsSetupRecord = new LmsSetupRecord(
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
BooleanUtils.toIntegerObject(active)); BooleanUtils.toIntegerObject(active));
@ -166,9 +162,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO, BulkActionSupport {
@Override @Override
@Transactional @Transactional
public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) { public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(all);
final List<Long> ids = extractIdsFromKeys(all, result);
try { try {
this.lmsSetupRecordMapper.deleteByExample() this.lmsSetupRecordMapper.deleteByExample()
@ -192,23 +186,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO, BulkActionSupport {
public Set<EntityKey> getDependencies(final BulkAction bulkAction) { public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
// all of institution // all of institution
if (bulkAction.sourceType == EntityType.INSTITUTION) { if (bulkAction.sourceType == EntityType.INSTITUTION) {
final Set<EntityKey> result = new HashSet<>(); return getDependencies(bulkAction, this::allIdsOfInstitution);
for (final EntityKey sourceKey : bulkAction.sources) {
try {
result.addAll(this.lmsSetupRecordMapper.selectIdsByExample()
.where(LmsSetupRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(sourceKey.entityId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.LMS_SETUP))
.collect(Collectors.toList()));
} catch (final Exception e) {
log.error("Unexpected error: ", e);
return Collections.emptySet();
}
}
return result;
} }
return Collections.emptySet(); return Collections.emptySet();
@ -216,10 +194,9 @@ public class LmsSetupDAOImpl implements LmsSetupDAO, BulkActionSupport {
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public Result<Collection<Entity>> bulkLoadEntities(final Collection<EntityKey> keys) { public Result<Collection<LmsSetup>> bulkLoadEntities(final Collection<EntityKey> keys) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(keys);
final List<Long> ids = extractIdsFromKeys(keys, result);
return this.lmsSetupRecordMapper.selectByExample() return this.lmsSetupRecordMapper.selectByExample()
.where(LmsSetupRecordDynamicSqlSupport.id, isIn(ids)) .where(LmsSetupRecordDynamicSqlSupport.id, isIn(ids))
@ -232,22 +209,17 @@ public class LmsSetupDAOImpl implements LmsSetupDAO, BulkActionSupport {
}); });
} }
@Override private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
@Transactional return Result.tryCatch(() -> {
public Collection<Result<EntityKey>> processBulkAction(final BulkAction bulkAction) { return this.lmsSetupRecordMapper.selectIdsByExample()
final Set<EntityKey> all = bulkAction.extractKeys(EntityType.LMS_SETUP); .where(LmsSetupRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.entityId)))
switch (bulkAction.type) { .build()
case ACTIVATE: .execute()
return setActive(all, true); .stream()
case DEACTIVATE: .map(id -> new EntityKey(id, EntityType.LMS_SETUP))
return setActive(all, false); .collect(Collectors.toList());
case HARD_DELETE: });
return delete(all);
}
// should never happen
throw new UnsupportedOperationException("Unsupported Bulk Action: " + bulkAction);
} }
private Result<LmsSetupRecord> recordById(final Long id) { private Result<LmsSetupRecord> recordById(final Long id) {

View file

@ -10,7 +10,6 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
import static org.mybatis.dynamic.sql.SqlBuilder.isIn; import static org.mybatis.dynamic.sql.SqlBuilder.isIn;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -181,9 +180,7 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
@Override @Override
@Transactional @Transactional
public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) { public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(all);
final List<Long> ids = extractIdsFromKeys(all, result);
try { try {
this.userLogRecordMapper.deleteByExample() this.userLogRecordMapper.deleteByExample()
@ -231,11 +228,14 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
return (institutionId == null) return (institutionId == null)
? this.userLogRecordMapper.selectByExample() ? this.userLogRecordMapper.selectByExample()
.where(UserActivityLogRecordDynamicSqlSupport.userUuid, .where(
UserActivityLogRecordDynamicSqlSupport.userUuid,
SqlBuilder.isEqualToWhenPresent(userId)) SqlBuilder.isEqualToWhenPresent(userId))
.and(UserActivityLogRecordDynamicSqlSupport.timestamp, .and(
UserActivityLogRecordDynamicSqlSupport.timestamp,
SqlBuilder.isGreaterThanOrEqualToWhenPresent(from)) SqlBuilder.isGreaterThanOrEqualToWhenPresent(from))
.and(UserActivityLogRecordDynamicSqlSupport.timestamp, .and(
UserActivityLogRecordDynamicSqlSupport.timestamp,
SqlBuilder.isLessThanWhenPresent(to)) SqlBuilder.isLessThanWhenPresent(to))
.build() .build()
.execute() .execute()
@ -247,15 +247,20 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
: this.userLogRecordMapper.selectByExample() : this.userLogRecordMapper.selectByExample()
.join(UserRecordDynamicSqlSupport.userRecord) .join(UserRecordDynamicSqlSupport.userRecord)
.on(UserRecordDynamicSqlSupport.uuid, .on(
UserRecordDynamicSqlSupport.uuid,
SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid)) SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid))
.where(UserActivityLogRecordDynamicSqlSupport.userUuid, .where(
UserActivityLogRecordDynamicSqlSupport.userUuid,
SqlBuilder.isEqualToWhenPresent(userId)) SqlBuilder.isEqualToWhenPresent(userId))
.and(UserRecordDynamicSqlSupport.institutionId, .and(
UserRecordDynamicSqlSupport.institutionId,
SqlBuilder.isEqualToWhenPresent(institutionId)) SqlBuilder.isEqualToWhenPresent(institutionId))
.and(UserActivityLogRecordDynamicSqlSupport.timestamp, .and(
UserActivityLogRecordDynamicSqlSupport.timestamp,
SqlBuilder.isGreaterThanOrEqualToWhenPresent(from)) SqlBuilder.isGreaterThanOrEqualToWhenPresent(from))
.and(UserActivityLogRecordDynamicSqlSupport.timestamp, .and(
UserActivityLogRecordDynamicSqlSupport.timestamp,
SqlBuilder.isLessThanWhenPresent(to)) SqlBuilder.isLessThanWhenPresent(to))
.build() .build()
.execute() .execute()
@ -295,7 +300,8 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
public Result<Integer> overwriteUserReferences(final String userUuid, final boolean deactivate) { public Result<Integer> overwriteUserReferences(final String userUuid, final boolean deactivate) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
final List<UserActivityLogRecord> records = this.userLogRecordMapper.selectByExample() final List<UserActivityLogRecord> records = this.userLogRecordMapper.selectByExample()
.where(UserActivityLogRecordDynamicSqlSupport.userUuid, .where(
UserActivityLogRecordDynamicSqlSupport.userUuid,
SqlBuilder.isEqualTo(userUuid)) SqlBuilder.isEqualTo(userUuid))
.build() .build()
.execute(); .execute();
@ -317,7 +323,8 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
public Result<Integer> deleteUserEnities(final String userUuid) { public Result<Integer> deleteUserEnities(final String userUuid) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
return this.userLogRecordMapper.deleteByExample() return this.userLogRecordMapper.deleteByExample()
.where(UserActivityLogRecordDynamicSqlSupport.userUuid, .where(
UserActivityLogRecordDynamicSqlSupport.userUuid,
SqlBuilder.isEqualToWhenPresent(userUuid)) SqlBuilder.isEqualToWhenPresent(userUuid))
.build() .build()
.execute(); .execute();

View file

@ -11,10 +11,8 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
import static ch.ethz.seb.sebserver.gbl.util.Utils.toSQLWildcard; import static ch.ethz.seb.sebserver.gbl.util.Utils.toSQLWildcard;
import static org.mybatis.dynamic.sql.SqlBuilder.*; import static org.mybatis.dynamic.sql.SqlBuilder.*;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
@ -39,7 +37,6 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.WebSecurityConfig; import ch.ethz.seb.sebserver.WebSecurityConfig;
import ch.ethz.seb.sebserver.gbl.model.APIMessage.APIMessageException; import ch.ethz.seb.sebserver.gbl.model.APIMessage.APIMessageException;
import ch.ethz.seb.sebserver.gbl.model.APIMessage.ErrorMessage; import ch.ethz.seb.sebserver.gbl.model.APIMessage.ErrorMessage;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.user.UserFilter; import ch.ethz.seb.sebserver.gbl.model.user.UserFilter;
@ -55,13 +52,12 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.RoleRecord;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.UserRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.UserRecord;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
@Lazy @Lazy
@Component @Component
public class UserDaoImpl implements UserDAO, BulkActionSupport { public class UserDaoImpl implements UserDAO {
private static final Logger log = LoggerFactory.getLogger(UserDaoImpl.class); private static final Logger log = LoggerFactory.getLogger(UserDaoImpl.class);
private static final UserFilter ALL_ACTIVE_ONLY_FILTER = new UserFilter(null, null, null, null, true, null); private static final UserFilter ALL_ACTIVE_ONLY_FILTER = new UserFilter(null, null, null, null, true, null);
@ -195,9 +191,7 @@ public class UserDaoImpl implements UserDAO, BulkActionSupport {
@Override @Override
@Transactional @Transactional
public Collection<Result<EntityKey>> setActive(final Set<EntityKey> all, final boolean active) { public Collection<Result<EntityKey>> setActive(final Set<EntityKey> all, final boolean active) {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(all);
final List<Long> ids = extractIdsFromKeys(all, result);
final UserRecord userRecord = new UserRecord( final UserRecord userRecord = new UserRecord(
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
BooleanUtils.toIntegerObject(active)); BooleanUtils.toIntegerObject(active));
@ -222,9 +216,7 @@ public class UserDaoImpl implements UserDAO, BulkActionSupport {
@Override @Override
@Transactional @Transactional
public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) { public Collection<Result<EntityKey>> delete(final Set<EntityKey> all) {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(all);
final List<Long> ids = extractIdsFromKeys(all, result);
try { try {
this.userRecordMapper.deleteByExample() this.userRecordMapper.deleteByExample()
@ -245,9 +237,9 @@ public class UserDaoImpl implements UserDAO, BulkActionSupport {
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public Collection<EntityKey> getAllUserData(final String uuid) { public Collection<EntityKey> getAllUserRelatedData(final String uuid) {
// TODO // TODO get
return Collections.emptyList(); return Collections.emptyList();
} }
@ -257,23 +249,7 @@ public class UserDaoImpl implements UserDAO, BulkActionSupport {
public Set<EntityKey> getDependencies(final BulkAction bulkAction) { public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
// all of institution // all of institution
if (bulkAction.sourceType == EntityType.INSTITUTION) { if (bulkAction.sourceType == EntityType.INSTITUTION) {
final Set<EntityKey> result = new HashSet<>(); return getDependencies(bulkAction, this::allIdsOfInstitution);
for (final EntityKey sourceKey : bulkAction.sources) {
try {
result.addAll(this.userRecordMapper.selectIdsByExample()
.where(UserRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(sourceKey.entityId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.LMS_SETUP))
.collect(Collectors.toList()));
} catch (final Exception e) {
log.error("Unexpected error: ", e);
return Collections.emptySet();
}
}
return result;
} }
return Collections.emptySet(); return Collections.emptySet();
@ -281,10 +257,9 @@ public class UserDaoImpl implements UserDAO, BulkActionSupport {
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public Result<Collection<Entity>> bulkLoadEntities(final Collection<EntityKey> keys) { public Result<Collection<UserInfo>> bulkLoadEntities(final Collection<EntityKey> keys) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
final Collection<Result<EntityKey>> result = new ArrayList<>(); final List<Long> ids = extractIdsFromKeys(keys);
final List<Long> ids = extractIdsFromKeys(keys, result);
return this.userRecordMapper.selectByExample() return this.userRecordMapper.selectByExample()
.where(InstitutionRecordDynamicSqlSupport.id, isIn(ids)) .where(InstitutionRecordDynamicSqlSupport.id, isIn(ids))
@ -298,40 +273,21 @@ public class UserDaoImpl implements UserDAO, BulkActionSupport {
} }
@Override @Override
@Transactional public List<Long> extractIdsFromKeys(final Collection<EntityKey> keys) {
public Collection<Result<EntityKey>> processBulkAction(final BulkAction bulkAction) {
final Set<EntityKey> all = bulkAction.extractKeys(EntityType.USER);
switch (bulkAction.type) {
case ACTIVATE:
return setActive(all, true);
case DEACTIVATE:
return setActive(all, false);
case HARD_DELETE:
return delete(all);
}
// should never happen
throw new UnsupportedOperationException("Unsupported Bulk Action: " + bulkAction);
}
@Override
public List<Long> extractIdsFromKeys(
final Collection<EntityKey> keys,
final Collection<Result<EntityKey>> result) {
if (keys == null || keys.isEmpty() || keys.iterator().next().isIdPK) { if (keys == null || keys.isEmpty() || keys.iterator().next().isIdPK) {
return UserDAO.super.extractIdsFromKeys(keys, result); return UserDAO.super.extractIdsFromKeys(keys);
} else { } else {
final List<String> uuids = keys.stream() final List<String> uuids = keys.stream()
.map(key -> key.entityId) .map(key -> key.entityId)
.collect(Collectors.toList()); .collect(Collectors.toList());
try { try {
return this.userRecordMapper.selectIdsByExample() return this.userRecordMapper.selectIdsByExample()
.where(UserRecordDynamicSqlSupport.uuid, isIn(uuids)) .where(UserRecordDynamicSqlSupport.uuid, isIn(uuids))
.build() .build()
.execute(); .execute();
} catch (final Exception e) { } catch (final Exception e) {
log.error("Unexpected error: ", e); log.error("Unexpected error: ", e);
return Collections.emptyList(); return Collections.emptyList();
@ -339,6 +295,19 @@ public class UserDaoImpl implements UserDAO, BulkActionSupport {
} }
} }
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> {
return this.userRecordMapper.selectIdsByExample()
.where(UserRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.entityId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.USER))
.collect(Collectors.toList());
});
}
private Result<UserRecord> updateUser(final UserMod userMod) { private Result<UserRecord> updateUser(final UserMod userMod) {
return recordByUUID(userMod.uuid) return recordByUUID(userMod.uuid)
.map(record -> { .map(record -> {

View file

@ -17,4 +17,8 @@ public interface LmsAPIService {
Result<LmsAPITemplate> createLmsAPITemplate(LmsSetup lmsSetup); Result<LmsAPITemplate> createLmsAPITemplate(LmsSetup lmsSetup);
Result<byte[]> createSEBStartConfiguration(Long lmsSetupId);
Result<byte[]> createSEBStartConfiguration(LmsSetup lmsSetup);
} }

View file

@ -45,4 +45,25 @@ public class LmsAPIServiceImpl implements LmsAPIService {
} }
} }
@Override
public Result<byte[]> createSEBStartConfiguration(final Long lmsSetupId) {
return this.lmsSetupDAO
.byId(lmsSetupId)
.flatMap(this::createSEBStartConfiguration);
}
@Override
public Result<byte[]> createSEBStartConfiguration(final LmsSetup lmsSetup) {
// TODO implementation of creation of SEB start configuration for specified LmsSetup
// A SEB start configuration should at least contain the SEB-Client-Credentials to access the SEB Server API
// and the SEB Server URL
//
// To Clarify : The format of a SEB start configuration
// To Clarify : How the file should be encrypted (use case) maybe we need another encryption-secret for this that can be given by
// an administrator on SEB start configuration creation time
return Result.ofTODO();
}
} }

View file

@ -13,6 +13,7 @@ import java.util.stream.Collectors;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -38,6 +39,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionServic
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
@WebServiceProfile @WebServiceProfile
@RestController @RestController
@ -48,17 +50,20 @@ public class LmsSetupController {
private final AuthorizationGrantService authorizationGrantService; private final AuthorizationGrantService authorizationGrantService;
private final UserActivityLogDAO userActivityLogDAO; private final UserActivityLogDAO userActivityLogDAO;
private final BulkActionService bulkActionService; private final BulkActionService bulkActionService;
private final LmsAPIService lmsAPIService;
public LmsSetupController( public LmsSetupController(
final LmsSetupDAO lmsSetupDAO, final LmsSetupDAO lmsSetupDAO,
final AuthorizationGrantService authorizationGrantService, final AuthorizationGrantService authorizationGrantService,
final UserActivityLogDAO userActivityLogDAO, final UserActivityLogDAO userActivityLogDAO,
final BulkActionService bulkActionService) { final BulkActionService bulkActionService,
final LmsAPIService lmsAPIService) {
this.lmsSetupDAO = lmsSetupDAO; this.lmsSetupDAO = lmsSetupDAO;
this.authorizationGrantService = authorizationGrantService; this.authorizationGrantService = authorizationGrantService;
this.userActivityLogDAO = userActivityLogDAO; this.userActivityLogDAO = userActivityLogDAO;
this.bulkActionService = bulkActionService; this.bulkActionService = bulkActionService;
this.lmsAPIService = lmsAPIService;
} }
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
@ -118,6 +123,21 @@ public class LmsSetupController {
.getOrThrow(); .getOrThrow();
} }
@RequestMapping(
path = "/create_seb_config/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) // TODO check if this is the right format
public byte[] createSEBConfig(@PathVariable final Long id) {
this.authorizationGrantService.checkHasAnyPrivilege(
EntityType.LMS_SETUP,
PrivilegeType.WRITE);
return this.lmsAPIService
.createSEBStartConfiguration(id)
.getOrThrow();
}
@RequestMapping(path = "/create", method = RequestMethod.PUT) @RequestMapping(path = "/create", method = RequestMethod.PUT)
public LmsSetup create(@Valid @RequestBody final LmsSetup lmsSetup) { public LmsSetup create(@Valid @RequestBody final LmsSetup lmsSetup) {
return save(lmsSetup, PrivilegeType.WRITE) return save(lmsSetup, PrivilegeType.WRITE)