From 9bc8dfaf8bcf10d404ae4bf297beedc103d6bd25 Mon Sep 17 00:00:00 2001 From: anhefti Date: Tue, 5 Nov 2019 13:55:05 +0100 Subject: [PATCH] new import implementation with creating new configuration --- .../gui/content/SebExamConfigImport.java | 162 ++++++++++++++---- .../gui/content/SebExamConfigList.java | 5 + .../gui/content/SebExamConfigPropForm.java | 4 +- .../gui/content/action/ActionDefinition.java | 7 +- .../ch/ethz/seb/sebserver/gui/form/Form.java | 9 + ... => ImportExamConfigOnExistingConfig.java} | 4 +- .../seb/examconfig/ImportNewExamConfig.java | 40 +++++ .../servicelayer/dao/ConfigurationDAO.java | 37 ++++ .../impl/ConfigurationDAOBatchService.java | 19 ++ .../dao/impl/ConfigurationDAOImpl.java | 8 + .../sebconfig/SebExamConfigService.java | 4 +- .../impl/SebExamConfigServiceImpl.java | 14 +- .../api/ConfigurationNodeController.java | 97 ++++++++--- 13 files changed, 338 insertions(+), 72 deletions(-) rename src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/{ImportExamConfig.java => ImportExamConfigOnExistingConfig.java} (88%) create mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportNewExamConfig.java diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImport.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImport.java index 81f266f0..4a587e97 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImport.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImport.java @@ -9,32 +9,41 @@ package ch.ethz.seb.sebserver.gui.content; import java.io.InputStream; -import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Predicate; import java.util.function.Supplier; +import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; +import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gui.form.Form; import ch.ethz.seb.sebserver.gui.form.FormBuilder; import ch.ethz.seb.sebserver.gui.form.FormHandle; +import ch.ethz.seb.sebserver.gui.service.ResourceService; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer; import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageService; import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog; import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; -import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportExamConfig; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportExamConfigOnExistingConfig; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportNewExamConfig; import ch.ethz.seb.sebserver.gui.widget.FileUploadSelection; public final class SebExamConfigImport { - static Function importConfigFunction(final PageService pageService) { + static Function importFunction( + final PageService pageService, + final boolean newConfig) { + return action -> { final ModalInputDialog> dialog = @@ -45,13 +54,15 @@ public final class SebExamConfigImport { final ImportFormContext importFormContext = new ImportFormContext( pageService, - action.pageContext()); + action.pageContext(), + newConfig); dialog.open( SebExamConfigPropForm.FORM_IMPORT_TEXT_KEY, - (Consumer>) formHandle -> doImport( + (Predicate>) formHandle -> doImport( pageService, - formHandle), + formHandle, + newConfig), importFormContext::cancelUpload, importFormContext); @@ -59,39 +70,90 @@ public final class SebExamConfigImport { }; } - private static final void doImport( + private static final boolean doImport( final PageService pageService, - final FormHandle formHandle) { + final FormHandle formHandle, + final boolean newConfig) { - final Form form = formHandle.getForm(); - final EntityKey entityKey = formHandle.getContext().getEntityKey(); - final Control fieldControl = form.getFieldControl(API.IMPORT_FILE_ATTR_NAME); - final PageContext context = formHandle.getContext(); - if (fieldControl != null && fieldControl instanceof FileUploadSelection) { - final FileUploadSelection fileUpload = (FileUploadSelection) fieldControl; - final InputStream inputStream = fileUpload.getInputStream(); - if (inputStream != null) { - final Configuration configuration = pageService.getRestService() - .getBuilder(ImportExamConfig.class) - .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) - .withHeader( - API.IMPORT_PASSWORD_ATTR_NAME, - form.getFieldValue(API.IMPORT_PASSWORD_ATTR_NAME)) - .withBody(inputStream) - .call() - .get(e -> { - fileUpload.close(); - return context.notifyError(e); - }); + try { + final Form form = formHandle.getForm(); + final EntityKey entityKey = formHandle.getContext().getEntityKey(); + final Control fieldControl = form.getFieldControl(API.IMPORT_FILE_ATTR_NAME); + final PageContext context = formHandle.getContext(); - if (configuration != null) { - context.publishInfo(SebExamConfigPropForm.FORM_IMPORT_CONFIRM_TEXT_KEY); - } - } else { - formHandle.getContext().publishPageMessage( - new LocTextKey("sebserver.error.unexpected"), - new LocTextKey("Please selecte a valid SEB Exam Configuration File")); + // Ad-hoc field validation + formHandle.process(name -> true, field -> field.resetError()); + final String fieldValue = form.getFieldValue(Domain.CONFIGURATION_NODE.ATTR_NAME); + if (StringUtils.isBlank(fieldValue)) { + form.setFieldError( + Domain.CONFIGURATION_NODE.ATTR_NAME, + pageService + .getI18nSupport() + .getText(new LocTextKey("sebserver.form.validation.fieldError.notNull"))); + return false; + } else if (fieldValue.length() < 3 || fieldValue.length() > 255) { + form.setFieldError( + Domain.CONFIGURATION_NODE.ATTR_NAME, + pageService + .getI18nSupport() + .getText(new LocTextKey("sebserver.form.validation.fieldError.size", + null, + null, + null, + 3, + 255))); + return false; } + + if (fieldControl != null && fieldControl instanceof FileUploadSelection) { + final FileUploadSelection fileUpload = (FileUploadSelection) fieldControl; + final InputStream inputStream = fileUpload.getInputStream(); + if (inputStream != null) { + final RestCall.RestCallBuilder restCall = (newConfig) + ? pageService.getRestService() + .getBuilder(ImportNewExamConfig.class) + : pageService.getRestService() + .getBuilder(ImportExamConfigOnExistingConfig.class); + + restCall + .withHeader( + API.IMPORT_PASSWORD_ATTR_NAME, + form.getFieldValue(API.IMPORT_PASSWORD_ATTR_NAME)) + .withBody(inputStream); + + if (newConfig) { + restCall + .withHeader( + Domain.CONFIGURATION_NODE.ATTR_NAME, + form.getFieldValue(Domain.CONFIGURATION_NODE.ATTR_NAME)) + .withHeader( + Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION, + form.getFieldValue(Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION)) + .withHeader( + Domain.CONFIGURATION_NODE.ATTR_TEMPLATE_ID, + form.getFieldValue(Domain.CONFIGURATION_NODE.ATTR_TEMPLATE_ID)); + } else { + restCall.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId); + } + + final Result configuration = restCall + .call(); + + if (!configuration.hasError()) { + context.publishInfo(SebExamConfigPropForm.FORM_IMPORT_CONFIRM_TEXT_KEY); + return true; + } + } else { + formHandle.getContext().publishPageMessage( + new LocTextKey("sebserver.error.unexpected"), + new LocTextKey("Please selecte a valid SEB Exam Configuration File")); + } + } + + return false; + } catch (final Exception e) { + formHandle.getContext().notifyError(e); + return true; } } @@ -99,17 +161,25 @@ public final class SebExamConfigImport { private final PageService pageService; private final PageContext pageContext; + private final boolean newConfig; private Form form = null; - protected ImportFormContext(final PageService pageService, final PageContext pageContext) { + protected ImportFormContext( + final PageService pageService, + final PageContext pageContext, + final boolean newConfig) { + this.pageService = pageService; this.pageContext = pageContext; + this.newConfig = newConfig; } @Override public Supplier> compose(final Composite parent) { + final ResourceService resourceService = this.pageService.getResourceService(); + final FormHandle formHandle = this.pageService.formBuilder( this.pageContext.copyOf(parent), 4) .readonly(false) @@ -118,6 +188,26 @@ public final class SebExamConfigImport { SebExamConfigPropForm.FORM_IMPORT_SELECT_TEXT_KEY, null, API.SEB_FILE_EXTENSION)) + + .addFieldIf( + () -> this.newConfig, + () -> FormBuilder.text( + Domain.CONFIGURATION_NODE.ATTR_NAME, + SebExamConfigPropForm.FORM_NAME_TEXT_KEY)) + .addFieldIf( + () -> this.newConfig, + () -> FormBuilder.text( + Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION, + SebExamConfigPropForm.FORM_DESCRIPTION_TEXT_KEY) + .asArea()) + .addFieldIf( + () -> this.newConfig, + () -> FormBuilder.singleSelection( + Domain.CONFIGURATION_NODE.ATTR_TEMPLATE_ID, + SebExamConfigPropForm.FORM_TEMPLATE_TEXT_KEY, + null, + resourceService::getExamConfigTemplateResources)) + .addField(FormBuilder.text( API.IMPORT_PASSWORD_ATTR_NAME, SebExamConfigPropForm.FORM_IMPORT_PASSWORD_TEXT_KEY, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java index 01320235..1eb99445 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java @@ -207,6 +207,11 @@ public class SebExamConfigList implements TemplateComposer { PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) .publishIf(() -> examConfigGrant.im() && configTable.hasAnyContent()) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG) + .withExec(SebExamConfigImport.importFunction(this.pageService, true)) + .noEventPropagation() + .publishIf(() -> examConfigGrant.im()) + // Exam Configuration template actions... .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_NEW) .publishIf(examConfigGrant::iw) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java index 465dbbbe..6e9fb3ba 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java @@ -246,9 +246,9 @@ public class SebExamConfigPropForm implements TemplateComposer { .noEventPropagation() .publishIf(() -> modifyGrant && isReadonly) - .newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_CONFIG) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_EXISTING_CONFIG) .withEntityKey(entityKey) - .withExec(SebExamConfigImport.importConfigFunction(this.pageService)) + .withExec(SebExamConfigImport.importFunction(this.pageService, false)) .noEventPropagation() .publishIf(() -> modifyGrant && isReadonly && !isAttachedToExam) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java index c936ac4a..31079c88 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java @@ -368,6 +368,10 @@ public enum ActionDefinition { ImageIcon.SHOW, PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW, ActionCategory.FORM), + SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG( + new LocTextKey("sebserver.examconfig.action.import-config"), + ImageIcon.IMPORT, + ActionCategory.VARIA), SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST( new LocTextKey("sebserver.examconfig.action.list.modify.properties"), @@ -407,10 +411,11 @@ public enum ActionDefinition { new LocTextKey("sebserver.examconfig.action.get-config-key"), ImageIcon.SECURE, ActionCategory.FORM), - SEB_EXAM_CONFIG_IMPORT_CONFIG( + SEB_EXAM_CONFIG_IMPORT_TO_EXISTING_CONFIG( new LocTextKey("sebserver.examconfig.action.import-config"), ImageIcon.IMPORT, ActionCategory.FORM), + SEB_EXAM_CONFIG_COPY_CONFIG( new LocTextKey("sebserver.examconfig.action.copy"), ImageIcon.COPY, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java index 500295c8..9169c23a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java @@ -227,6 +227,15 @@ public final class Form implements FormBinding { .isPresent(); } + public void setFieldError(final String fieldName, final String errorMessage) { + final List list = this.formFields.get(fieldName); + if (list != null) { + list + .stream() + .forEach(ffa -> ffa.setError(errorMessage)); + } + } + public void process( final Predicate nameFilter, final Consumer processor) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportExamConfig.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportExamConfigOnExistingConfig.java similarity index 88% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportExamConfig.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportExamConfigOnExistingConfig.java index 2619aff8..cd87d748 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportExamConfig.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportExamConfigOnExistingConfig.java @@ -24,9 +24,9 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class ImportExamConfig extends RestCall { +public class ImportExamConfigOnExistingConfig extends RestCall { - public ImportExamConfig() { + public ImportExamConfigOnExistingConfig() { super(new TypeKey<>( CallType.UNDEFINED, EntityType.CONFIGURATION, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportNewExamConfig.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportNewExamConfig.java new file mode 100644 index 00000000..0b5ce311 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ImportNewExamConfig.java @@ -0,0 +1,40 @@ +/* + * 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.gui.service.remote.webservice.api.seb.examconfig; + +import org.springframework.context.annotation.Lazy; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.core.type.TypeReference; + +import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; + +@Lazy +@Component +@GuiProfile +public class ImportNewExamConfig extends RestCall { + + public ImportNewExamConfig() { + super(new TypeKey<>( + CallType.UNDEFINED, + EntityType.CONFIGURATION, + new TypeReference() { + }), + HttpMethod.POST, + MediaType.APPLICATION_OCTET_STREAM, + API.CONFIGURATION_NODE_ENDPOINT + API.CONFIGURATION_IMPORT_PATH_SEGMENT); + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationDAO.java index a5107ea6..2c0e96df 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationDAO.java @@ -13,6 +13,7 @@ import java.util.Set; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; import ch.ethz.seb.sebserver.gbl.util.Result; public interface ConfigurationDAO extends EntityDAO { @@ -48,6 +49,31 @@ public interface ConfigurationDAO extends EntityDAO undo(Long configurationNodeId); + /** Restores the attribute values to the default values that have been set for the specified configuration + * on initialization. This are the base default values if the configuration has no template or the default + * values from the template if there is one assigned to the configuration. + * + * In fact. this just gets the initial configuration values and reset the current values with that one + * + * @param configurationNodeId the ConfigurationNode identifier + * @return the Configuration instance for which the attribute values have been reset */ + Result restoreToDefaultValues(final Long configurationNodeId); + + /** Restores the attribute values to the default values that have been set for the specified configuration + * on initialization. This are the base default values if the configuration has no template or the default + * values from the template if there is one assigned to the configuration. + * + * In fact. this just gets the initial configuration values and reset the current values with that one + * + * @param configuration the Configuration that defines the ConfigurationNode identifier + * @return the Configuration instance for which the attribute values have been reset */ + default Result restoreToDefaultValues(final Configuration configuration) { + if (configuration == null) { + return Result.ofError(new NullPointerException("configuration")); + } + return restoreToDefaultValues(configuration.configurationNodeId); + } + /** Restores the current follow-up Configuration to the values of a given Configuration * in the history of the specified ConfigurationNode. * @@ -62,6 +88,17 @@ public interface ConfigurationDAO extends EntityDAO getFollowupConfiguration(Long configNodeId); + /** Use this to get the follow-up configuration for a specified configuration node. + * + * @param configNode ConfigurationNode to get the current follow-up configuration from + * @return the current follow-up configuration */ + default Result getFollowupConfiguration(final ConfigurationNode configurationNode) { + if (configurationNode == null) { + return Result.ofError(new NullPointerException("configurationNode")); + } + return getFollowupConfiguration(configurationNode.id); + } + /** Use this to get the last version of a configuration that is not the follow-up. * * @param configNodeId ConfigurationNode identifier to get the last version of configuration from diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOBatchService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOBatchService.java index edd6997e..6e575327 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOBatchService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOBatchService.java @@ -266,6 +266,25 @@ class ConfigurationDAOBatchService { .flatMap(rec -> restoreToVersion(configurationNodeId, rec.getId())); } + Result restoreToDefaultValues(final Long configurationNodeId) { + return Result.tryCatch(() -> { + // get initial version that contains the default values either from base or from template + return this.batchConfigurationRecordMapper.selectIdsByExample() + .where( + ConfigurationRecordDynamicSqlSupport.configurationNodeId, + isEqualTo(configurationNodeId)) + .and( + ConfigurationRecordDynamicSqlSupport.version, + isEqualTo(INITIAL_VERSION_NAME)) + .build() + .execute() + .stream() + .collect(Utils.toSingleton()); + + }) + .flatMap(configId -> restoreToVersion(configurationNodeId, configId)); + } + Result restoreToVersion(final Long configurationNodeId, final Long configId) { return Result.tryCatch(() -> { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOImpl.java index fc11b7f6..2e52d0d4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOImpl.java @@ -193,6 +193,14 @@ public class ConfigurationDAOImpl implements ConfigurationDAO { .onError(TransactionHandler::rollback); } + @Override + @Transactional + public Result restoreToDefaultValues(final Long configurationNodeId) { + return this.configurationDAOBatchService + .restoreToDefaultValues(configurationNodeId) + .onError(TransactionHandler::rollback); + } + @Override @Transactional public Result restoreToVersion(final Long configurationNodeId, final Long configId) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebExamConfigService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebExamConfigService.java index 201d14a8..c5825bd9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebExamConfigService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebExamConfigService.java @@ -118,10 +118,10 @@ public interface SebExamConfigService { * * Then parses the XML and adds each attribute to the new Configuration. * - * @param configNodeId The identifier of the configuration node on which the import should take place + * @param config The Configuration to import the attribute values to * @param input The InputStream to get the SEB config file as byte-stream * @param password A password is only needed if the file is in an encrypted format * @return The newly created Configuration instance */ - Result importFromSEBFile(Long configNodeId, InputStream input, CharSequence password); + Result importFromSEBFile(Configuration config, InputStream input, CharSequence password); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigServiceImpl.java index be807c44..10eb2883 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigServiceImpl.java @@ -330,16 +330,12 @@ public class SebExamConfigServiceImpl implements SebExamConfigService { @Override public Result importFromSEBFile( - final Long configNodeId, + final Configuration config, final InputStream input, final CharSequence password) { return Result.tryCatch(() -> { - final Configuration newConfig = this.configurationDAO - .saveToHistory(configNodeId) - .getOrThrow(); - Future streamDecrypted = null; InputStream cryptIn = null; PipedInputStream plainIn = null; @@ -363,16 +359,16 @@ public class SebExamConfigServiceImpl implements SebExamConfigService { // parse XML and import this.examConfigIO.importPlainXML( unzippedIn, - newConfig.institutionId, - newConfig.id); + config.institutionId, + config.id); - return newConfig; + return config; } catch (final Exception e) { log.error("Unexpected error while trying to import SEB Exam Configuration: ", e); log.debug("Make an undo on the ConfigurationNode to rollback the changes"); this.configurationDAO - .undo(configNodeId) + .undo(config.configurationNodeId) .getOrThrow(); if (streamDecrypted != null) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java index 341f0d04..51f6a706 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java @@ -20,6 +20,7 @@ import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; import org.mybatis.dynamic.sql.SqlTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,12 +40,14 @@ import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType; +import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM; import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCopyInfo; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType; import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute; import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType; @@ -222,11 +225,50 @@ public class ConfigurationNodeController extends EntityController( - Arrays.asList(APIMessage.ErrorMessage.UNEXPECTED.of(e.getMessage())), - Utils.createJsonContentHeader(), - HttpStatus.BAD_REQUEST); - } + return doImport(password, request, newConfig); } @RequestMapping( @@ -444,4 +474,31 @@ public class ConfigurationNodeController extends EntityController( + Arrays.asList(APIMessage.ErrorMessage.UNEXPECTED.of(e.getMessage())), + Utils.createJsonContentHeader(), + HttpStatus.BAD_REQUEST); + } + } + }