SEBSERV-10 back-end implementation
This commit is contained in:
		
							parent
							
								
									d7f79fb3cc
								
							
						
					
					
						commit
						2a0afe902a
					
				
					 17 changed files with 349 additions and 32 deletions
				
			
		|  | @ -27,6 +27,7 @@ public final class API { | ||||||
|     public static final String PARAM_PARENT_MODEL_ID = "parentModelId"; |     public static final String PARAM_PARENT_MODEL_ID = "parentModelId"; | ||||||
|     public static final String PARAM_ENTITY_TYPE = "entityType"; |     public static final String PARAM_ENTITY_TYPE = "entityType"; | ||||||
|     public static final String PARAM_BULK_ACTION_TYPE = "bulkActionType"; |     public static final String PARAM_BULK_ACTION_TYPE = "bulkActionType"; | ||||||
|  |     public static final String PARAM_BULK_ACTION_INCLUDES = "bulkActionIncludes"; | ||||||
|     public static final String PARAM_VIEW_ID = "viewId"; |     public static final String PARAM_VIEW_ID = "viewId"; | ||||||
|     public static final String PARAM_INSTRUCTION_TYPE = "instructionType"; |     public static final String PARAM_INSTRUCTION_TYPE = "instructionType"; | ||||||
|     public static final String PARAM_INSTRUCTION_ATTRIBUTES = "instructionAttributes"; |     public static final String PARAM_INSTRUCTION_ATTRIBUTES = "instructionAttributes"; | ||||||
|  |  | ||||||
|  | @ -28,6 +28,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; | ||||||
|  *                       /               |              \           \ |  *                       /               |              \           \ | ||||||
|  *                  LMS Setup            |          User-Account   Client Configuration |  *                  LMS Setup            |          User-Account   Client Configuration | ||||||
|  *                      |                | |  *                      |                | | ||||||
|  |  *                      |  ______________+______________/ | ||||||
|  |  *                      |/               |/ | ||||||
|  *                    Exam       Exam Configuration |  *                    Exam       Exam Configuration | ||||||
|  *                      |\              / |  *                      |\              / | ||||||
|  *                      | Exam Config Mapping |  *                      | Exam Config Mapping | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
|  | import java.util.EnumSet; | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
| import java.util.LinkedHashSet; | import java.util.LinkedHashSet; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
|  | @ -35,6 +36,9 @@ public final class BulkAction { | ||||||
|     public final EntityType sourceType; |     public final EntityType sourceType; | ||||||
|     /** A Set of EntityKey defining all source-entities of the BulkAction */ |     /** A Set of EntityKey defining all source-entities of the BulkAction */ | ||||||
|     public final Set<EntityKey> sources; |     public final Set<EntityKey> sources; | ||||||
|  |     /** A Set defining the types of dependencies to include into the bulk action | ||||||
|  |      * Null means all dependencies are included (ignore) and empty means no dependencies are included */ | ||||||
|  |     public final EnumSet<EntityType> includeDependencies; | ||||||
|     /** A Set of EntityKey containing collected depending entities during dependency collection and processing phase */ |     /** A Set of EntityKey containing collected depending entities during dependency collection and processing phase */ | ||||||
|     final Set<EntityKey> dependencies; |     final Set<EntityKey> dependencies; | ||||||
|     /** A Set of EntityKey containing collected bulk action processing results during processing phase */ |     /** A Set of EntityKey containing collected bulk action processing results during processing phase */ | ||||||
|  | @ -46,10 +50,19 @@ public final class BulkAction { | ||||||
|             final BulkActionType type, |             final BulkActionType type, | ||||||
|             final EntityType sourceType, |             final EntityType sourceType, | ||||||
|             final Collection<EntityKey> sources) { |             final Collection<EntityKey> sources) { | ||||||
|  |         this(type, sourceType, sources, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public BulkAction( | ||||||
|  |             final BulkActionType type, | ||||||
|  |             final EntityType sourceType, | ||||||
|  |             final Collection<EntityKey> sources, | ||||||
|  |             final EnumSet<EntityType> includeDependencies) { | ||||||
| 
 | 
 | ||||||
|         this.type = type; |         this.type = type; | ||||||
|         this.sourceType = sourceType; |         this.sourceType = sourceType; | ||||||
|         this.sources = Utils.immutableSetOf(sources); |         this.sources = Utils.immutableSetOf(sources); | ||||||
|  |         this.includeDependencies = includeDependencies; | ||||||
|         this.dependencies = new LinkedHashSet<>(); |         this.dependencies = new LinkedHashSet<>(); | ||||||
|         this.result = new HashSet<>(); |         this.result = new HashSet<>(); | ||||||
| 
 | 
 | ||||||
|  | @ -64,6 +77,10 @@ public final class BulkAction { | ||||||
|         this(type, sourceType, (sources != null) ? Arrays.asList(sources) : Collections.emptyList()); |         this(type, sourceType, (sources != null) ? Arrays.asList(sources) : Collections.emptyList()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public boolean includesDependencyType(final EntityType type) { | ||||||
|  |         return this.includeDependencies == null || this.includeDependencies.contains(type); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public Set<EntityKey> getDependencies() { |     public Set<EntityKey> getDependencies() { | ||||||
|         return Collections.unmodifiableSet(this.dependencies); |         return Collections.unmodifiableSet(this.dependencies); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -11,6 +11,8 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
|  | import java.util.EnumMap; | ||||||
|  | import java.util.EnumSet; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  | @ -37,6 +39,9 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; | ||||||
| @WebServiceProfile | @WebServiceProfile | ||||||
| public class BulkActionServiceImpl implements BulkActionService { | public class BulkActionServiceImpl implements BulkActionService { | ||||||
| 
 | 
 | ||||||
|  |     private final EnumMap<EntityType, EnumSet<EntityType>> directDependancyMap = | ||||||
|  |             new EnumMap<>(EntityType.class); | ||||||
|  | 
 | ||||||
|     private final Map<EntityType, BulkActionSupportDAO<?>> supporter; |     private final Map<EntityType, BulkActionSupportDAO<?>> supporter; | ||||||
|     private final UserActivityLogDAO userActivityLogDAO; |     private final UserActivityLogDAO userActivityLogDAO; | ||||||
|     private final ApplicationEventPublisher applicationEventPublisher; |     private final ApplicationEventPublisher applicationEventPublisher; | ||||||
|  | @ -55,6 +60,20 @@ public class BulkActionServiceImpl implements BulkActionService { | ||||||
|         this.userActivityLogDAO = userActivityLogDAO; |         this.userActivityLogDAO = userActivityLogDAO; | ||||||
|         this.applicationEventPublisher = applicationEventPublisher; |         this.applicationEventPublisher = applicationEventPublisher; | ||||||
|         this.jsonMapper = jsonMapper; |         this.jsonMapper = jsonMapper; | ||||||
|  | 
 | ||||||
|  |         this.directDependancyMap.put(EntityType.INSTITUTION, EnumSet.of( | ||||||
|  |                 EntityType.LMS_SETUP, | ||||||
|  |                 EntityType.SEB_CLIENT_CONFIGURATION, | ||||||
|  |                 EntityType.CONFIGURATION_NODE, | ||||||
|  |                 EntityType.USER)); | ||||||
|  |         this.directDependancyMap.put(EntityType.LMS_SETUP, EnumSet.of( | ||||||
|  |                 EntityType.EXAM)); | ||||||
|  |         this.directDependancyMap.put(EntityType.EXAM, EnumSet.of( | ||||||
|  |                 EntityType.EXAM_CONFIGURATION_MAP, | ||||||
|  |                 EntityType.INDICATOR, | ||||||
|  |                 EntityType.CLIENT_CONNECTION)); | ||||||
|  |         this.directDependancyMap.put(EntityType.CONFIGURATION_NODE, | ||||||
|  |                 EnumSet.noneOf(EntityType.class)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -172,6 +191,8 @@ public class BulkActionServiceImpl implements BulkActionService { | ||||||
|                 return dependantSupporterInHierarchicalOrder |                 return dependantSupporterInHierarchicalOrder | ||||||
|                         .stream() |                         .stream() | ||||||
|                         .filter(Objects::nonNull) |                         .filter(Objects::nonNull) | ||||||
|  |                         .filter(dao -> action.includeDependencies == null || | ||||||
|  |                                 action.includeDependencies.contains(dao.entityType())) | ||||||
|                         .collect(Collectors.toList()); |                         .collect(Collectors.toList()); | ||||||
|             } |             } | ||||||
|             default: |             default: | ||||||
|  | @ -191,13 +212,13 @@ public class BulkActionServiceImpl implements BulkActionService { | ||||||
|                         this.supporter.get(EntityType.EXAM_CONFIGURATION_MAP), |                         this.supporter.get(EntityType.EXAM_CONFIGURATION_MAP), | ||||||
|                         this.supporter.get(EntityType.CLIENT_CONNECTION), |                         this.supporter.get(EntityType.CLIENT_CONNECTION), | ||||||
|                         this.supporter.get(EntityType.CONFIGURATION_NODE)); |                         this.supporter.get(EntityType.CONFIGURATION_NODE)); | ||||||
| //            case USER: |             case USER: | ||||||
| //                return Arrays.asList( |                 return Arrays.asList( | ||||||
| //                        this.supporter.get(EntityType.EXAM_CONFIGURATION_MAP), |                         this.supporter.get(EntityType.EXAM), | ||||||
| //                        this.supporter.get(EntityType.EXAM), |                         this.supporter.get(EntityType.INDICATOR), | ||||||
| //                        this.supporter.get(EntityType.INDICATOR), |                         this.supporter.get(EntityType.CLIENT_CONNECTION), | ||||||
| //                        this.supporter.get(EntityType.CLIENT_CONNECTION), |                         this.supporter.get(EntityType.CONFIGURATION_NODE), | ||||||
| //                        this.supporter.get(EntityType.CONFIGURATION_NODE)); |                         this.supporter.get(EntityType.EXAM_CONFIGURATION_MAP)); | ||||||
|             case LMS_SETUP: |             case LMS_SETUP: | ||||||
|                 return Arrays.asList( |                 return Arrays.asList( | ||||||
|                         this.supporter.get(EntityType.EXAM), |                         this.supporter.get(EntityType.EXAM), | ||||||
|  | @ -218,6 +239,15 @@ public class BulkActionServiceImpl implements BulkActionService { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void checkProcessing(final BulkAction action) { |     private void checkProcessing(final BulkAction action) { | ||||||
|  |         // complete this.directDependancyMap if needed | ||||||
|  |         if (action.includeDependencies != null) { | ||||||
|  |             this.directDependancyMap.entrySet().stream() | ||||||
|  |                     .forEach(entry -> { | ||||||
|  |                         if (action.includeDependencies.contains(entry.getKey())) { | ||||||
|  |                             action.includeDependencies.addAll(entry.getValue()); | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |         } | ||||||
|         if (action.alreadyProcessed) { |         if (action.alreadyProcessed) { | ||||||
|             throw new IllegalStateException("Given BulkAction has already been processed. Use a new one"); |             throw new IllegalStateException("Given BulkAction has already been processed. Use a new one"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -17,8 +17,11 @@ import org.springframework.cache.annotation.Cacheable; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; | import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; | ||||||
| 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 ClientConnectionDAO extends EntityDAO<ClientConnection, ClientConnection> { | public interface ClientConnectionDAO extends | ||||||
|  |         EntityDAO<ClientConnection, ClientConnection>, | ||||||
|  |         BulkActionSupportDAO<ClientConnection> { | ||||||
| 
 | 
 | ||||||
|     String CONNECTION_TOKENS_CACHE = "CONNECTION_TOKENS_CACHE"; |     String CONNECTION_TOKENS_CACHE = "CONNECTION_TOKENS_CACHE"; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,13 +8,14 @@ | ||||||
| 
 | 
 | ||||||
| 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.isEqualToWhenPresent; | import static org.mybatis.dynamic.sql.SqlBuilder.*; | ||||||
| import static org.mybatis.dynamic.sql.SqlBuilder.isIn; |  | ||||||
| 
 | 
 | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  | import java.util.Collections; | ||||||
| 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; | ||||||
| 
 | 
 | ||||||
|  | @ -23,6 +24,7 @@ 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.api.API.BulkActionType; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; | import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; | import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; | ||||||
|  | @ -34,7 +36,11 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientConnectionR | ||||||
| import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientConnectionRecordMapper; | 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.ClientEventRecordDynamicSqlSupport; | ||||||
| import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordMapper; | import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordMapper; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientInstructionRecordDynamicSqlSupport; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientInstructionRecordMapper; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport; | ||||||
| import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord; | import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; | ||||||
|  | @ -49,13 +55,16 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO { | ||||||
| 
 | 
 | ||||||
|     private final ClientConnectionRecordMapper clientConnectionRecordMapper; |     private final ClientConnectionRecordMapper clientConnectionRecordMapper; | ||||||
|     private final ClientEventRecordMapper clientEventRecordMapper; |     private final ClientEventRecordMapper clientEventRecordMapper; | ||||||
|  |     private final ClientInstructionRecordMapper clientInstructionRecordMapper; | ||||||
| 
 | 
 | ||||||
|     protected ClientConnectionDAOImpl( |     protected ClientConnectionDAOImpl( | ||||||
|             final ClientConnectionRecordMapper clientConnectionRecordMapper, |             final ClientConnectionRecordMapper clientConnectionRecordMapper, | ||||||
|             final ClientEventRecordMapper clientEventRecordMapper) { |             final ClientEventRecordMapper clientEventRecordMapper, | ||||||
|  |             final ClientInstructionRecordMapper clientInstructionRecordMapper) { | ||||||
| 
 | 
 | ||||||
|         this.clientConnectionRecordMapper = clientConnectionRecordMapper; |         this.clientConnectionRecordMapper = clientConnectionRecordMapper; | ||||||
|         this.clientEventRecordMapper = clientEventRecordMapper; |         this.clientEventRecordMapper = clientEventRecordMapper; | ||||||
|  |         this.clientInstructionRecordMapper = clientInstructionRecordMapper; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -171,6 +180,39 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO { | ||||||
|                 .onError(TransactionHandler::rollback); |                 .onError(TransactionHandler::rollback); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public Set<EntityKey> getDependencies(final BulkAction bulkAction) { | ||||||
|  |         // only for deletion | ||||||
|  |         if (bulkAction.type == BulkActionType.ACTIVATE || bulkAction.type == BulkActionType.DEACTIVATE) { | ||||||
|  |             return Collections.emptySet(); | ||||||
|  |         } | ||||||
|  |         // only if included | ||||||
|  |         if (!bulkAction.includesDependencyType(EntityType.CLIENT_CONNECTION)) { | ||||||
|  |             return Collections.emptySet(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // define the select function in case of source type | ||||||
|  |         Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction; | ||||||
|  |         switch (bulkAction.sourceType) { | ||||||
|  |             case INSTITUTION: | ||||||
|  |                 selectionFunction = this::allIdsOfInstitution; | ||||||
|  |                 break; | ||||||
|  |             case LMS_SETUP: | ||||||
|  |                 selectionFunction = this::allIdsOfLmsSetup; | ||||||
|  |             case USER: | ||||||
|  |                 selectionFunction = this::allIdsOfUser; | ||||||
|  |                 break; | ||||||
|  |             case EXAM: | ||||||
|  |                 selectionFunction = this::allIdsOfExam; | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 selectionFunction = key -> Result.of(Collections.emptyList()); //empty select function | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return getDependencies(bulkAction, selectionFunction); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     @Transactional |     @Transactional | ||||||
|     public Result<Collection<EntityKey>> delete(final Set<EntityKey> all) { |     public Result<Collection<EntityKey>> delete(final Set<EntityKey> all) { | ||||||
|  | @ -186,6 +228,23 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO { | ||||||
|                     .build() |                     .build() | ||||||
|                     .execute(); |                     .execute(); | ||||||
| 
 | 
 | ||||||
|  |             // then delete all related client instructions | ||||||
|  |             final List<String> connectionTokens = this.clientConnectionRecordMapper.selectByExample() | ||||||
|  |                     .where( | ||||||
|  |                             ClientConnectionRecordDynamicSqlSupport.id, | ||||||
|  |                             SqlBuilder.isIn(ids)) | ||||||
|  |                     .build() | ||||||
|  |                     .execute() | ||||||
|  |                     .stream() | ||||||
|  |                     .map(r -> r.getConnectionToken()) | ||||||
|  |                     .collect(Collectors.toList()); | ||||||
|  |             this.clientInstructionRecordMapper.deleteByExample() | ||||||
|  |                     .where( | ||||||
|  |                             ClientInstructionRecordDynamicSqlSupport.connectionToken, | ||||||
|  |                             SqlBuilder.isIn(connectionTokens)) | ||||||
|  |                     .build() | ||||||
|  |                     .execute(); | ||||||
|  | 
 | ||||||
|             // then delete all requested client-connections |             // then delete all requested client-connections | ||||||
|             this.clientConnectionRecordMapper.deleteByExample() |             this.clientConnectionRecordMapper.deleteByExample() | ||||||
|                     .where( |                     .where( | ||||||
|  | @ -256,7 +315,62 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO { | ||||||
|                     record.getVirtualClientAddress(), |                     record.getVirtualClientAddress(), | ||||||
|                     record.getCreationTime()); |                     record.getCreationTime()); | ||||||
|         }); |         }); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) { | ||||||
|  |         return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectIdsByExample() | ||||||
|  |                 .where( | ||||||
|  |                         ClientConnectionRecordDynamicSqlSupport.institutionId, | ||||||
|  |                         isEqualTo(Long.parseLong(institutionKey.modelId))) | ||||||
|  |                 .build() | ||||||
|  |                 .execute() | ||||||
|  |                 .stream() | ||||||
|  |                 .map(id -> new EntityKey(id, EntityType.EXAM)) | ||||||
|  |                 .collect(Collectors.toList())); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Result<Collection<EntityKey>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) { | ||||||
|  |         return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectIdsByExample() | ||||||
|  |                 .leftJoin(ExamRecordDynamicSqlSupport.examRecord) | ||||||
|  |                 .on( | ||||||
|  |                         ExamRecordDynamicSqlSupport.id, | ||||||
|  |                         equalTo(ClientConnectionRecordDynamicSqlSupport.examId)) | ||||||
|  |                 .where( | ||||||
|  |                         ExamRecordDynamicSqlSupport.lmsSetupId, | ||||||
|  |                         isEqualTo(Long.parseLong(lmsSetupKey.modelId))) | ||||||
|  |                 .build() | ||||||
|  |                 .execute() | ||||||
|  |                 .stream() | ||||||
|  |                 .map(id -> new EntityKey(id, EntityType.EXAM)) | ||||||
|  |                 .collect(Collectors.toList())); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) { | ||||||
|  |         return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectIdsByExample() | ||||||
|  |                 .leftJoin(ExamRecordDynamicSqlSupport.examRecord) | ||||||
|  |                 .on( | ||||||
|  |                         ExamRecordDynamicSqlSupport.id, | ||||||
|  |                         equalTo(ClientConnectionRecordDynamicSqlSupport.examId)) | ||||||
|  |                 .where( | ||||||
|  |                         ExamRecordDynamicSqlSupport.owner, | ||||||
|  |                         isEqualTo(userKey.modelId)) | ||||||
|  |                 .build() | ||||||
|  |                 .execute() | ||||||
|  |                 .stream() | ||||||
|  |                 .map(id -> new EntityKey(id, EntityType.EXAM)) | ||||||
|  |                 .collect(Collectors.toList())); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Result<Collection<EntityKey>> allIdsOfExam(final EntityKey examKey) { | ||||||
|  |         return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectIdsByExample() | ||||||
|  |                 .where( | ||||||
|  |                         ClientConnectionRecordDynamicSqlSupport.examId, | ||||||
|  |                         isEqualTo(Long.parseLong(examKey.modelId))) | ||||||
|  |                 .build() | ||||||
|  |                 .execute() | ||||||
|  |                 .stream() | ||||||
|  |                 .map(id -> new EntityKey(id, EntityType.EXAM)) | ||||||
|  |                 .collect(Collectors.toList())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ 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.api.API.BulkActionType; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException; | import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; | import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||||
|  | @ -134,11 +135,24 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO { | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(readOnly = true) |     @Transactional(readOnly = true) | ||||||
|     public Set<EntityKey> getDependencies(final BulkAction bulkAction) { |     public Set<EntityKey> getDependencies(final BulkAction bulkAction) { | ||||||
|  |         // only if included | ||||||
|  |         if (!bulkAction.includesDependencyType(EntityType.CONFIGURATION_NODE)) { | ||||||
|  |             return Collections.emptySet(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         // define the select function in case of source type |         // define the select function in case of source type | ||||||
|         final Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction = |         Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction = | ||||||
|                 (bulkAction.sourceType == EntityType.INSTITUTION) |                 key -> Result.of(Collections.emptyList()); | ||||||
|                         ? this::allIdsOfInstitution | 
 | ||||||
|                         : key -> Result.of(Collections.emptyList()); // else : empty select function |         if (bulkAction.sourceType == EntityType.INSTITUTION) { | ||||||
|  |             selectionFunction = this::allIdsOfInstitution; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // in case of user deletion with configuration dependency inclusion | ||||||
|  |         if (bulkAction.sourceType == EntityType.USER && | ||||||
|  |                 bulkAction.type == BulkActionType.HARD_DELETE) { | ||||||
|  |             selectionFunction = this::allIdsOfUser; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         return getDependencies(bulkAction, selectionFunction); |         return getDependencies(bulkAction, selectionFunction); | ||||||
|     } |     } | ||||||
|  | @ -252,6 +266,18 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO { | ||||||
|                 .collect(Collectors.toList())); |                 .collect(Collectors.toList())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) { | ||||||
|  |         return Result.tryCatch(() -> this.configurationNodeRecordMapper.selectIdsByExample() | ||||||
|  |                 .where( | ||||||
|  |                         ConfigurationNodeRecordDynamicSqlSupport.owner, | ||||||
|  |                         isEqualTo(userKey.modelId)) | ||||||
|  |                 .build() | ||||||
|  |                 .execute() | ||||||
|  |                 .stream() | ||||||
|  |                 .map(id -> new EntityKey(id, EntityType.CONFIGURATION_NODE)) | ||||||
|  |                 .collect(Collectors.toList())); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private Result<ConfigurationNodeRecord> recordById(final Long id) { |     private Result<ConfigurationNodeRecord> recordById(final Long id) { | ||||||
|         return Result.tryCatch(() -> { |         return Result.tryCatch(() -> { | ||||||
|             final ConfigurationNodeRecord record = this.configurationNodeRecordMapper |             final ConfigurationNodeRecord record = this.configurationNodeRecordMapper | ||||||
|  |  | ||||||
|  | @ -28,8 +28,8 @@ import org.springframework.transaction.annotation.Transactional; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType; | import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException; | import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage; | import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage; | ||||||
| import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService; |  | ||||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; | import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||||
|  | import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||||
| 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.Exam.ExamType; | import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType; | ||||||
|  | @ -281,9 +281,14 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO { | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(readOnly = true) |     @Transactional(readOnly = true) | ||||||
|     public Set<EntityKey> getDependencies(final BulkAction bulkAction) { |     public Set<EntityKey> getDependencies(final BulkAction bulkAction) { | ||||||
|  |         // only deletion here | ||||||
|         if (bulkAction.type == BulkActionType.ACTIVATE || bulkAction.type == BulkActionType.DEACTIVATE) { |         if (bulkAction.type == BulkActionType.ACTIVATE || bulkAction.type == BulkActionType.DEACTIVATE) { | ||||||
|             return Collections.emptySet(); |             return Collections.emptySet(); | ||||||
|         } |         } | ||||||
|  |         // only if included | ||||||
|  |         if (!bulkAction.includesDependencyType(EntityType.EXAM_CONFIGURATION_MAP)) { | ||||||
|  |             return Collections.emptySet(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // define the select function in case of source type |         // define the select function in case of source type | ||||||
|         Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction; |         Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction; | ||||||
|  | @ -291,6 +296,9 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO { | ||||||
|             case INSTITUTION: |             case INSTITUTION: | ||||||
|                 selectionFunction = this::allIdsOfInstitution; |                 selectionFunction = this::allIdsOfInstitution; | ||||||
|                 break; |                 break; | ||||||
|  |             case USER: | ||||||
|  |                 selectionFunction = this::allIdsOfUser; | ||||||
|  |                 break; | ||||||
|             case LMS_SETUP: |             case LMS_SETUP: | ||||||
|                 selectionFunction = this::allIdsOfLmsSetup; |                 selectionFunction = this::allIdsOfLmsSetup; | ||||||
|                 break; |                 break; | ||||||
|  | @ -424,6 +432,30 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO { | ||||||
|                 .collect(Collectors.toList())); |                 .collect(Collectors.toList())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) { | ||||||
|  |         return Result.tryCatch(() -> { | ||||||
|  |             final List<Long> examsIds = this.examRecordMapper.selectByExample() | ||||||
|  |                     .where( | ||||||
|  |                             ExamRecordDynamicSqlSupport.owner, | ||||||
|  |                             isEqualTo(userKey.modelId)) | ||||||
|  |                     .build() | ||||||
|  |                     .execute() | ||||||
|  |                     .stream() | ||||||
|  |                     .map(r -> r.getId()) | ||||||
|  |                     .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |             return this.examConfigurationMapRecordMapper.selectIdsByExample() | ||||||
|  |                     .where( | ||||||
|  |                             ExamConfigurationMapRecordDynamicSqlSupport.examId, | ||||||
|  |                             isIn(examsIds)) | ||||||
|  |                     .build() | ||||||
|  |                     .execute() | ||||||
|  |                     .stream() | ||||||
|  |                     .map(id -> new EntityKey(id, EntityType.EXAM_CONFIGURATION_MAP)) | ||||||
|  |                     .collect(Collectors.toList()); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private Result<Collection<EntityKey>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) { |     private Result<Collection<EntityKey>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) { | ||||||
|         return Result.tryCatch(() -> this.examConfigurationMapRecordMapper.selectIdsByExample() |         return Result.tryCatch(() -> this.examConfigurationMapRecordMapper.selectIdsByExample() | ||||||
|                 .leftJoin(ExamRecordDynamicSqlSupport.examRecord) |                 .leftJoin(ExamRecordDynamicSqlSupport.examRecord) | ||||||
|  |  | ||||||
|  | @ -588,6 +588,10 @@ public class ExamDAOImpl implements ExamDAO { | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(readOnly = true) |     @Transactional(readOnly = true) | ||||||
|     public Set<EntityKey> getDependencies(final BulkAction bulkAction) { |     public Set<EntityKey> getDependencies(final BulkAction bulkAction) { | ||||||
|  |         // only if included | ||||||
|  |         if (!bulkAction.includesDependencyType(EntityType.EXAM)) { | ||||||
|  |             return Collections.emptySet(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // define the select function in case of source type |         // define the select function in case of source type | ||||||
|         Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction; |         Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction; | ||||||
|  | @ -598,6 +602,9 @@ public class ExamDAOImpl implements ExamDAO { | ||||||
|             case LMS_SETUP: |             case LMS_SETUP: | ||||||
|                 selectionFunction = this::allIdsOfLmsSetup; |                 selectionFunction = this::allIdsOfLmsSetup; | ||||||
|                 break; |                 break; | ||||||
|  |             case USER: | ||||||
|  |                 selectionFunction = this::allIdsOfUser; | ||||||
|  |                 break; | ||||||
|             default: |             default: | ||||||
|                 selectionFunction = key -> Result.of(Collections.emptyList()); //empty select function |                 selectionFunction = key -> Result.of(Collections.emptyList()); //empty select function | ||||||
|                 break; |                 break; | ||||||
|  | @ -651,6 +658,17 @@ public class ExamDAOImpl implements ExamDAO { | ||||||
|                 .collect(Collectors.toList())); |                 .collect(Collectors.toList())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) { | ||||||
|  |         return Result.tryCatch(() -> this.examRecordMapper.selectIdsByExample() | ||||||
|  |                 .where(ExamRecordDynamicSqlSupport.owner, | ||||||
|  |                         isEqualTo(userKey.modelId)) | ||||||
|  |                 .build() | ||||||
|  |                 .execute() | ||||||
|  |                 .stream() | ||||||
|  |                 .map(id -> new EntityKey(id, EntityType.EXAM)) | ||||||
|  |                 .collect(Collectors.toList())); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private Result<ExamRecord> recordById(final Long id) { |     private Result<ExamRecord> recordById(final Long id) { | ||||||
|         return Result.tryCatch(() -> { |         return Result.tryCatch(() -> { | ||||||
|             final ExamRecord record = this.examRecordMapper.selectByPrimaryKey(id); |             final ExamRecord record = this.examRecordMapper.selectByPrimaryKey(id); | ||||||
|  |  | ||||||
|  | @ -221,9 +221,14 @@ public class IndicatorDAOImpl implements IndicatorDAO { | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(readOnly = true) |     @Transactional(readOnly = true) | ||||||
|     public Set<EntityKey> getDependencies(final BulkAction bulkAction) { |     public Set<EntityKey> getDependencies(final BulkAction bulkAction) { | ||||||
|  |         // only for deletion | ||||||
|         if (bulkAction.type == BulkActionType.ACTIVATE || bulkAction.type == BulkActionType.DEACTIVATE) { |         if (bulkAction.type == BulkActionType.ACTIVATE || bulkAction.type == BulkActionType.DEACTIVATE) { | ||||||
|             return Collections.emptySet(); |             return Collections.emptySet(); | ||||||
|         } |         } | ||||||
|  |         // only if included | ||||||
|  |         if (!bulkAction.includesDependencyType(EntityType.INDICATOR)) { | ||||||
|  |             return Collections.emptySet(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // define the select function in case of source type |         // define the select function in case of source type | ||||||
|         Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction; |         Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction; | ||||||
|  | @ -233,6 +238,8 @@ public class IndicatorDAOImpl implements IndicatorDAO { | ||||||
|                 break; |                 break; | ||||||
|             case LMS_SETUP: |             case LMS_SETUP: | ||||||
|                 selectionFunction = this::allIdsOfLmsSetup; |                 selectionFunction = this::allIdsOfLmsSetup; | ||||||
|  |             case USER: | ||||||
|  |                 selectionFunction = this::allIdsOfUser; | ||||||
|                 break; |                 break; | ||||||
|             case EXAM: |             case EXAM: | ||||||
|                 selectionFunction = this::allIdsOfExam; |                 selectionFunction = this::allIdsOfExam; | ||||||
|  | @ -277,6 +284,22 @@ public class IndicatorDAOImpl implements IndicatorDAO { | ||||||
|                 .collect(Collectors.toList())); |                 .collect(Collectors.toList())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) { | ||||||
|  |         return Result.tryCatch(() -> this.indicatorRecordMapper.selectIdsByExample() | ||||||
|  |                 .leftJoin(ExamRecordDynamicSqlSupport.examRecord) | ||||||
|  |                 .on( | ||||||
|  |                         ExamRecordDynamicSqlSupport.id, | ||||||
|  |                         equalTo(IndicatorRecordDynamicSqlSupport.examId)) | ||||||
|  |                 .where( | ||||||
|  |                         ExamRecordDynamicSqlSupport.owner, | ||||||
|  |                         isEqualTo(userKey.modelId)) | ||||||
|  |                 .build() | ||||||
|  |                 .execute() | ||||||
|  |                 .stream() | ||||||
|  |                 .map(id -> new EntityKey(id, EntityType.EXAM)) | ||||||
|  |                 .collect(Collectors.toList())); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private Result<Collection<EntityKey>> allIdsOfExam(final EntityKey examKey) { |     private Result<Collection<EntityKey>> allIdsOfExam(final EntityKey examKey) { | ||||||
|         return Result.tryCatch(() -> this.indicatorRecordMapper.selectIdsByExample() |         return Result.tryCatch(() -> this.indicatorRecordMapper.selectIdsByExample() | ||||||
|                 .where( |                 .where( | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| package ch.ethz.seb.sebserver.webservice.weblayer.api; | package ch.ethz.seb.sebserver.webservice.weblayer.api; | ||||||
| 
 | 
 | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import org.mybatis.dynamic.sql.SqlTable; | import org.mybatis.dynamic.sql.SqlTable; | ||||||
| import org.springframework.web.bind.annotation.RequestMapping; | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
|  | @ -52,7 +53,10 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Collection<EntityKey> getDependencies(final String modelId, final BulkActionType bulkActionType) { |     public Collection<EntityKey> getDependencies( | ||||||
|  |             final String modelId, | ||||||
|  |             final BulkActionType bulkActionType, | ||||||
|  |             final List<String> includes) { | ||||||
|         throw new UnsupportedOperationException(); |         throw new UnsupportedOperationException(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| package ch.ethz.seb.sebserver.webservice.weblayer.api; | package ch.ethz.seb.sebserver.webservice.weblayer.api; | ||||||
| 
 | 
 | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||||
| 
 | 
 | ||||||
|  | @ -114,7 +115,10 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Collection<EntityKey> getDependencies(final String modelId, final BulkActionType bulkActionType) { |     public Collection<EntityKey> getDependencies( | ||||||
|  |             final String modelId, | ||||||
|  |             final BulkActionType bulkActionType, | ||||||
|  |             final List<String> includes) { | ||||||
|         throw new UnsupportedOperationException(); |         throw new UnsupportedOperationException(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| package ch.ethz.seb.sebserver.webservice.weblayer.api; | package ch.ethz.seb.sebserver.webservice.weblayer.api; | ||||||
| 
 | 
 | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import org.mybatis.dynamic.sql.SqlTable; | import org.mybatis.dynamic.sql.SqlTable; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
|  | @ -110,7 +111,10 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Collection<EntityKey> getDependencies(final String modelId, final BulkActionType bulkActionType) { |     public Collection<EntityKey> getDependencies( | ||||||
|  |             final String modelId, | ||||||
|  |             final BulkActionType bulkActionType, | ||||||
|  |             final List<String> includes) { | ||||||
|         throw new UnsupportedOperationException(); |         throw new UnsupportedOperationException(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.webservice.weblayer.api; | package ch.ethz.seb.sebserver.webservice.weblayer.api; | ||||||
| 
 | 
 | ||||||
|  | import java.util.List; | ||||||
| import java.util.Objects; | import java.util.Objects; | ||||||
| 
 | 
 | ||||||
| import javax.validation.Valid; | import javax.validation.Valid; | ||||||
|  | @ -87,7 +88,9 @@ public class ConfigurationValueController extends EntityController<Configuration | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public EntityProcessingReport hardDelete(final String modelId) { |     public EntityProcessingReport hardDelete( | ||||||
|  |             final String modelId, | ||||||
|  |             final List<String> includes) { | ||||||
|         throw new UnsupportedOperationException(); |         throw new UnsupportedOperationException(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,7 +10,9 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api; | ||||||
| 
 | 
 | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  | import java.util.EnumSet; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Objects; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
| 
 | 
 | ||||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||||
|  | @ -209,7 +211,8 @@ public abstract class EntityController<T extends Entity, M extends Entity> { | ||||||
|             produces = MediaType.APPLICATION_JSON_UTF8_VALUE) |             produces = MediaType.APPLICATION_JSON_UTF8_VALUE) | ||||||
|     public Collection<EntityKey> getDependencies( |     public Collection<EntityKey> getDependencies( | ||||||
|             @PathVariable final String modelId, |             @PathVariable final String modelId, | ||||||
|             @RequestParam(name = API.PARAM_BULK_ACTION_TYPE, required = true) final BulkActionType bulkActionType) { |             @RequestParam(name = API.PARAM_BULK_ACTION_TYPE, required = true) final BulkActionType bulkActionType, | ||||||
|  |             @RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) { | ||||||
| 
 | 
 | ||||||
|         this.entityDAO |         this.entityDAO | ||||||
|                 .byModelId(modelId) |                 .byModelId(modelId) | ||||||
|  | @ -218,7 +221,8 @@ public abstract class EntityController<T extends Entity, M extends Entity> { | ||||||
|         final BulkAction bulkAction = new BulkAction( |         final BulkAction bulkAction = new BulkAction( | ||||||
|                 bulkActionType, |                 bulkActionType, | ||||||
|                 this.entityDAO.entityType(), |                 this.entityDAO.entityType(), | ||||||
|                 Arrays.asList(new EntityKey(modelId, this.entityDAO.entityType()))); |                 Arrays.asList(new EntityKey(modelId, this.entityDAO.entityType())), | ||||||
|  |                 convertToEntityType(includes)); | ||||||
| 
 | 
 | ||||||
|         this.bulkActionService.collectDependencies(bulkAction); |         this.bulkActionService.collectDependencies(bulkAction); | ||||||
|         return bulkAction.getDependencies(); |         return bulkAction.getDependencies(); | ||||||
|  | @ -320,24 +324,48 @@ public abstract class EntityController<T extends Entity, M extends Entity> { | ||||||
|             path = API.MODEL_ID_VAR_PATH_SEGMENT, |             path = API.MODEL_ID_VAR_PATH_SEGMENT, | ||||||
|             method = RequestMethod.DELETE, |             method = RequestMethod.DELETE, | ||||||
|             produces = MediaType.APPLICATION_JSON_UTF8_VALUE) |             produces = MediaType.APPLICATION_JSON_UTF8_VALUE) | ||||||
|     public EntityProcessingReport hardDelete(@PathVariable final String modelId) { |     public EntityProcessingReport hardDelete( | ||||||
|  |             @PathVariable final String modelId, | ||||||
|  |             @RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) { | ||||||
| 
 | 
 | ||||||
|         return this.entityDAO.byModelId(modelId) |         return this.entityDAO.byModelId(modelId) | ||||||
|                 .flatMap(this::checkWriteAccess) |                 .flatMap(this::checkWriteAccess) | ||||||
|                 .flatMap(this::validForDelete) |                 .flatMap(this::validForDelete) | ||||||
|                 .flatMap(this::bulkDelete) |                 .flatMap(entity -> bulkDelete(entity, convertToEntityType(includes))) | ||||||
|                 .flatMap(this::notifyDeleted) |                 .flatMap(this::notifyDeleted) | ||||||
|                 .flatMap(pair -> this.logBulkAction(pair.b)) |                 .flatMap(pair -> this.logBulkAction(pair.b)) | ||||||
|                 .getOrThrow(); |                 .getOrThrow(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     protected Result<Pair<T, EntityProcessingReport>> bulkDelete(final T entity) { |     protected EnumSet<EntityType> convertToEntityType(final List<String> includes) { | ||||||
|         return Result.tryCatch(() -> new Pair<>( |         final EnumSet<EntityType> includeDependencies = (includes != null) | ||||||
|                 entity, |                 ? EnumSet.copyOf(includes.stream().map(name -> { | ||||||
|                 this.bulkActionService.createReport(new BulkAction( |                     try { | ||||||
|  |                         return EntityType.valueOf(name); | ||||||
|  |                     } catch (final Exception e) { | ||||||
|  |                         return null; | ||||||
|  |                     } | ||||||
|  |                 }) | ||||||
|  |                         .filter(Objects::nonNull) | ||||||
|  |                         .collect(Collectors.toSet())) | ||||||
|  |                 : null; | ||||||
|  |         return includeDependencies; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected Result<Pair<T, EntityProcessingReport>> bulkDelete( | ||||||
|  |             final T entity, | ||||||
|  |             final EnumSet<EntityType> includeDependencies) { | ||||||
|  | 
 | ||||||
|  |         final BulkAction bulkAction = new BulkAction( | ||||||
|                 BulkActionType.HARD_DELETE, |                 BulkActionType.HARD_DELETE, | ||||||
|                 entity.entityType(), |                 entity.entityType(), | ||||||
|                         new EntityName(entity.getModelId(), entity.entityType(), entity.getName()))) |                 Arrays.asList(new EntityName(entity.getModelId(), entity.entityType(), entity.getName())), | ||||||
|  |                 includeDependencies); | ||||||
|  | 
 | ||||||
|  |         return Result.tryCatch(() -> new Pair<>( | ||||||
|  |                 entity, | ||||||
|  |                 this.bulkActionService | ||||||
|  |                         .createReport(bulkAction) | ||||||
|                         .getOrThrow())); |                         .getOrThrow())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,6 +8,8 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.webservice.weblayer.api; | package ch.ethz.seb.sebserver.webservice.weblayer.api; | ||||||
| 
 | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||||
| 
 | 
 | ||||||
| import org.mybatis.dynamic.sql.SqlTable; | import org.mybatis.dynamic.sql.SqlTable; | ||||||
|  | @ -162,13 +164,15 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon | ||||||
|             path = API.MODEL_ID_VAR_PATH_SEGMENT, |             path = API.MODEL_ID_VAR_PATH_SEGMENT, | ||||||
|             method = RequestMethod.DELETE, |             method = RequestMethod.DELETE, | ||||||
|             produces = MediaType.APPLICATION_JSON_UTF8_VALUE) |             produces = MediaType.APPLICATION_JSON_UTF8_VALUE) | ||||||
|     public EntityProcessingReport hardDelete(@PathVariable final String modelId) { |     public EntityProcessingReport hardDelete( | ||||||
|  |             @PathVariable final String modelId, | ||||||
|  |             @RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) { | ||||||
| 
 | 
 | ||||||
|         return this.entityDAO.byModelId(modelId) |         return this.entityDAO.byModelId(modelId) | ||||||
|                 .flatMap(this::checkWriteAccess) |                 .flatMap(this::checkWriteAccess) | ||||||
|                 .flatMap(entity -> this.examConfigUpdateService.processExamConfigurationMappingChange( |                 .flatMap(entity -> this.examConfigUpdateService.processExamConfigurationMappingChange( | ||||||
|                         entity, |                         entity, | ||||||
|                         this::bulkDelete)) |                         e -> bulkDelete(e, convertToEntityType(includes)))) | ||||||
|                 .flatMap(this::notifyDeleted) |                 .flatMap(this::notifyDeleted) | ||||||
|                 .flatMap(pair -> this.logBulkAction(pair.b)) |                 .flatMap(pair -> this.logBulkAction(pair.b)) | ||||||
|                 .getOrThrow(); |                 .getOrThrow(); | ||||||
|  |  | ||||||
|  | @ -8,6 +8,8 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.webservice.weblayer.api; | package ch.ethz.seb.sebserver.webservice.weblayer.api; | ||||||
| 
 | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||||
| import javax.validation.Valid; | import javax.validation.Valid; | ||||||
| 
 | 
 | ||||||
|  | @ -59,7 +61,9 @@ public abstract class ReadonlyEntityController<T extends Entity, M extends Entit | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public EntityProcessingReport hardDelete(final String modelId) { |     public EntityProcessingReport hardDelete( | ||||||
|  |             final String modelId, | ||||||
|  |             final List<String> includes) { | ||||||
|         throw new UnsupportedOperationException(ONLY_READ_ACCESS); |         throw new UnsupportedOperationException(ONLY_READ_ACCESS); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti