diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java index 67a6f028..b49186eb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java @@ -197,6 +197,26 @@ public class APIMessage implements Serializable { return ErrorMessage.FIELD_VALIDATION.of(fieldName, args); } + public static String toHTML(final String errorMessage, final List messages) { + final StringBuilder builder = new StringBuilder(); + builder.append("Failure: ").append(errorMessage).append("

"); + builder.append("Detail Messages:

"); + messages.stream() + .forEach(message -> { + builder + .append("  code : ") + .append(message.messageCode) + .append("
") + .append("  system message : ") + .append(HtmlUtils.htmlEscape(message.systemMessage)) + .append("
") + .append("  details : ") + .append(HtmlUtils.htmlEscape(StringUtils.abbreviate(message.details, 100))) + .append("

"); + }); + return builder.toString(); + } + public static String toHTML(final Collection messages) { final StringBuilder builder = new StringBuilder(); builder.append("Messages:

"); diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java index dc51c3ef..ae402f4e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java @@ -407,4 +407,11 @@ public final class Utils { org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE); return headers; } + + public static final String getErrorCauseMessage(final Exception e) { + if (e == null || e.getCause() == null) { + return Constants.EMPTY_NOTE; + } + return e.getCause().getClass().getName() + " : " + e.getCause().getMessage(); + } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java index 87a45257..4c0acc5a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java @@ -19,6 +19,7 @@ import org.springframework.stereotype.Component; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; 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; @@ -96,131 +97,138 @@ public class ConfigTemplateAttributeForm implements TemplateComposer { final EntityKey templateKey = pageContext.getParentEntityKey(); final Long templateId = Long.valueOf(templateKey.modelId); - final ConfigurationNode template = this.restService - .getBuilder(GetExamConfigNode.class) - .withURIVariable(API.PARAM_MODEL_ID, templateKey.modelId) - .call() - .get(pageContext::notifyError); + try { - final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(template); - final boolean modifyGrant = entityGrant.m(); + final ConfigurationNode template = this.restService + .getBuilder(GetExamConfigNode.class) + .withURIVariable(API.PARAM_MODEL_ID, templateKey.modelId) + .call() + .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error)) + .getOrThrow(); - // the attribute - final TemplateAttribute attribute = this.restService.getBuilder(GetTemplateAttribute.class) - .withURIVariable(API.PARAM_PARENT_MODEL_ID, templateKey.modelId) - .withURIVariable(API.PARAM_MODEL_ID, attributeKey.modelId) - .call() - .getOrThrow(); + final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(template); + final boolean modifyGrant = entityGrant.m(); - // the follow-up configuration - final Configuration configuration = this.restService.getBuilder(GetConfigurations.class) - .withQueryParam(Configuration.FILTER_ATTR_CONFIGURATION_NODE_ID, templateKey.getModelId()) - .withQueryParam(Configuration.FILTER_ATTR_FOLLOWUP, Constants.TRUE_STRING) - .call() - .map(Utils::toSingleton) - .onError(pageContext::notifyError) - .getOrThrow(); + // the attribute + final TemplateAttribute attribute = this.restService.getBuilder(GetTemplateAttribute.class) + .withURIVariable(API.PARAM_PARENT_MODEL_ID, templateKey.modelId) + .withURIVariable(API.PARAM_MODEL_ID, attributeKey.modelId) + .call() + .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error)) + .getOrThrow(); - // the default page layout with title - final Composite content = widgetFactory.defaultPageLayout( - pageContext.getParent(), - FORM_TITLE); + // the follow-up configuration + final Configuration configuration = this.restService.getBuilder(GetConfigurations.class) + .withQueryParam(Configuration.FILTER_ATTR_CONFIGURATION_NODE_ID, templateKey.getModelId()) + .withQueryParam(Configuration.FILTER_ATTR_FOLLOWUP, Constants.TRUE_STRING) + .call() + .map(Utils::toSingleton) + .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION, error)) + .getOrThrow(); - final PageContext formContext = pageContext.copyOf(content); + // the default page layout with title + final Composite content = widgetFactory.defaultPageLayout( + pageContext.getParent(), + FORM_TITLE); - final boolean hasView = attribute.getOrientation() != null; + final PageContext formContext = pageContext.copyOf(content); - this.pageService.formBuilder( - formContext, 4) - .readonly(true) // TODO change this for next version - .addField(FormBuilder.text( - Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME, - FORM_NAME_TEXT_KEY, - attribute::getName)) - .addField(FormBuilder.text( - Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE, - FORM_TYPE_TEXT_KEY, - () -> this.resourceService.getAttributeTypeName(attribute))) - .addFieldIf( - () -> hasView, - () -> FormBuilder.singleSelection( - Domain.ORIENTATION.ATTR_VIEW_ID, - FORM_VIEW_TEXT_KEY, - attribute.getViewModelId(), - () -> this.resourceService.getViewResources(templateKey.modelId))) - .addFieldIf( - () -> hasView, - () -> FormBuilder.text( - Domain.ORIENTATION.ATTR_GROUP_ID, - FORM_GROUP_TEXT_KEY, - attribute.getGroupId())) - .build(); + final boolean hasView = attribute.getOrientation() != null; - widgetFactory.labelLocalized( - content, - CustomVariant.TEXT_H2, - FORM_VALUE_TEXT_KEY); + this.pageService.formBuilder( + formContext, 4) + .readonly(true) // TODO change this for next version + .addField(FormBuilder.text( + Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME, + FORM_NAME_TEXT_KEY, + attribute::getName)) + .addField(FormBuilder.text( + Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE, + FORM_TYPE_TEXT_KEY, + () -> this.resourceService.getAttributeTypeName(attribute))) + .addFieldIf( + () -> hasView, + () -> FormBuilder.singleSelection( + Domain.ORIENTATION.ATTR_VIEW_ID, + FORM_VIEW_TEXT_KEY, + attribute.getViewModelId(), + () -> this.resourceService.getViewResources(templateKey.modelId))) + .addFieldIf( + () -> hasView, + () -> FormBuilder.text( + Domain.ORIENTATION.ATTR_GROUP_ID, + FORM_GROUP_TEXT_KEY, + attribute.getGroupId())) + .build(); - final Composite grid = new Composite(content, SWT.NONE); - grid.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); - grid.setLayout(new GridLayout(6, true)); + widgetFactory.labelLocalized( + content, + CustomVariant.TEXT_H2, + FORM_VALUE_TEXT_KEY); - final PageContext valueContext = formContext.copyOf(grid); + final Composite grid = new Composite(content, SWT.NONE); + grid.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + grid.setLayout(new GridLayout(6, true)); - final Orientation defaultOrientation = getDefaultOrientation(attribute); - final AttributeMapping attributeMapping = this.examConfigurationService - .getAttributes(attribute, defaultOrientation) - .getOrThrow(); - final ViewContext viewContext = this.examConfigurationService.createViewContext( - valueContext, - configuration, - new View(-1L, "template", 10, 0, templateId), - attributeMapping, - 1, false); + final PageContext valueContext = formContext.copyOf(grid); - final InputFieldBuilder inputFieldBuilder = this.examConfigurationService.getInputFieldBuilder( - attribute.getConfigAttribute(), - defaultOrientation); + final Orientation defaultOrientation = getDefaultOrientation(attribute); + final AttributeMapping attributeMapping = this.examConfigurationService + .getAttributes(attribute, defaultOrientation) + .getOrThrow(); + final ViewContext viewContext = this.examConfigurationService.createViewContext( + valueContext, + configuration, + new View(-1L, "template", 10, 0, templateId), + attributeMapping, + 1, false); - final InputField createInputField = inputFieldBuilder.createInputField( - content, - attribute.getConfigAttribute(), - viewContext); + final InputFieldBuilder inputFieldBuilder = this.examConfigurationService.getInputFieldBuilder( + attribute.getConfigAttribute(), + defaultOrientation); - viewContext.registerInputField(createInputField); + final InputField createInputField = inputFieldBuilder.createInputField( + content, + attribute.getConfigAttribute(), + viewContext); - this.examConfigurationService.initInputFieldValues( - configuration.id, - Arrays.asList(viewContext)); + viewContext.registerInputField(createInputField); - this.pageService.pageActionBuilder(formContext.clearEntityKeys()) + this.examConfigurationService.initInputFieldValues( + configuration.id, + Arrays.asList(viewContext)); - .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_SET_DEFAULT) - .withEntityKey(attributeKey) - .withParentEntityKey(templateKey) - .withExec(this.examConfigurationService::resetToDefaults) - .ignoreMoveAwayFromEdit() - .publishIf(() -> modifyGrant) + this.pageService.pageActionBuilder(formContext.clearEntityKeys()) - .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW) - .withEntityKey(attributeKey) - .withParentEntityKey(templateKey) - .withExec(this.examConfigurationService::removeFromView) - .ignoreMoveAwayFromEdit() - .publishIf(() -> modifyGrant && hasView) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_SET_DEFAULT) + .withEntityKey(attributeKey) + .withParentEntityKey(templateKey) + .withExec(this.examConfigurationService::resetToDefaults) + .ignoreMoveAwayFromEdit() + .publishIf(() -> modifyGrant) - .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_ATTACH_DEFAULT_VIEW) - .withEntityKey(attributeKey) - .withParentEntityKey(templateKey) - .withExec(this.examConfigurationService::attachToDefaultView) - .ignoreMoveAwayFromEdit() - .publishIf(() -> modifyGrant && !hasView) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW) + .withEntityKey(attributeKey) + .withParentEntityKey(templateKey) + .withExec(this.examConfigurationService::removeFromView) + .ignoreMoveAwayFromEdit() + .publishIf(() -> modifyGrant && hasView) - .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_EDIT_TEMPLATE) - .withEntityKey(templateKey) - .ignoreMoveAwayFromEdit() - .publish(); + .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_ATTACH_DEFAULT_VIEW) + .withEntityKey(attributeKey) + .withParentEntityKey(templateKey) + .withExec(this.examConfigurationService::attachToDefaultView) + .ignoreMoveAwayFromEdit() + .publishIf(() -> modifyGrant && !hasView) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_EDIT_TEMPLATE) + .withEntityKey(templateKey) + .ignoreMoveAwayFromEdit() + .publish(); + + } catch (final Exception e) { + pageContext.notifyUnexpectedError(e); + } } private Orientation getDefaultOrientation(final TemplateAttribute attribute) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java index 72d0fa9c..f8532e02 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java @@ -9,13 +9,12 @@ package ch.ethz.seb.sebserver.gui.content; import org.eclipse.swt.widgets.Composite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; @@ -53,8 +52,6 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @GuiProfile public class ConfigTemplateForm implements TemplateComposer { - private static final Logger log = LoggerFactory.getLogger(ConfigTemplateForm.class); - private static final LocTextKey FORM_TITLE_NEW = new LocTextKey("sebserver.configtemplate.form.title.new"); private static final LocTextKey FORM_TITLE = @@ -118,14 +115,8 @@ public class ConfigTemplateForm implements TemplateComposer { .getBuilder(GetExamConfigNode.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .get(pageContext::notifyError); - - if (examConfig == null) { - log.error("Failed to get ConfigurationNode for Template. " - + "Error was notified to the User. " - + "See previous logs for more infomation"); - return; - } + .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error)) + .getOrThrow(); final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(examConfig); final boolean writeGrant = entityGrant.w(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java index 4db1dcb0..784cff24 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java @@ -87,6 +87,10 @@ public class ExamForm implements TemplateComposer { private static final Logger log = LoggerFactory.getLogger(ExamForm.class); + public static final LocTextKey EXAM_FORM_TITLE_KEY = + new LocTextKey("sebserver.exam.form.title"); + public static final LocTextKey EXAM_FORM_TITLE_IMPORT_KEY = + new LocTextKey("sebserver.exam.form.title.import"); private static final LocTextKey CONFIG_EMPTY_LIST_MESSAGE = new LocTextKey("sebserver.exam.configuration.list.empty"); private static final LocTextKey INDICATOR_EMPTY_LIST_MESSAGE = @@ -145,6 +149,9 @@ public class ExamForm implements TemplateComposer { private final static LocTextKey CONSISTENCY_MESSAGE_MISSING_SEB_RESTRICTION = new LocTextKey("sebserver.exam.consistency.missing-seb-restriction"); + private final static LocTextKey SEB_RESTRICTION_ERROR = + new LocTextKey("sebserver.error.exam.seb.restriction"); + private final Map consistencyMessageMapping; private final static LocTextKey CONFIRM_MESSAGE_REMOVE_CONFIG = @@ -199,15 +206,8 @@ public class ExamForm implements TemplateComposer { final Exam exam = (importFromQuizData ? createExamFromQuizData(pageContext) : getExistingExam(pageContext)) - .get(pageContext::notifyError); - - if (exam == null) { - log.error( - "Failed to get Exam. " - + "Error was notified to the User. " - + "See previous logs for more infomation"); - return; - } + .onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error)) + .getOrThrow(); // new PageContext with actual EntityKey final PageContext formContext = pageContext.withEntityKey(exam.getEntityKey()); @@ -221,10 +221,9 @@ public class ExamForm implements TemplateComposer { } // the default page layout with title - final LocTextKey titleKey = new LocTextKey( - importFromQuizData - ? "sebserver.exam.form.title.import" - : "sebserver.exam.form.title"); + final LocTextKey titleKey = importFromQuizData + ? EXAM_FORM_TITLE_IMPORT_KEY + : EXAM_FORM_TITLE_KEY; final Composite content = this.widgetFactory.defaultPageLayout( formContext.getParent(), titleKey); @@ -579,7 +578,10 @@ public class ExamForm implements TemplateComposer { } private PageAction setSebRestriction(final PageAction action, final boolean sebRestriction) { - return setSebRestriction(action, sebRestriction, t -> action.pageContext().notifyError(t)); + return setSebRestriction( + action, + sebRestriction, + error -> action.pageContext().notifyError(SEB_RESTRICTION_ERROR, error)); } private PageAction setSebRestriction( @@ -685,7 +687,7 @@ public class ExamForm implements TemplateComposer { .getBuilder(DeleteExamConfigMapping.class) .withURIVariable(API.PARAM_MODEL_ID, examConfigMappingKey.modelId) .call() - .onError(error -> action.pageContext().notifyError(error)); + .onError(error -> action.pageContext().notifyRemoveError(EntityType.EXAM_CONFIGURATION_MAP, error)); return action; } @@ -693,8 +695,7 @@ public class ExamForm implements TemplateComposer { final EntityKey entityKey = pageContext.getEntityKey(); return this.restService.getBuilder(GetExam.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) - .call() - .onError(error -> pageContext.notifyError(error)); + .call(); } private Result createExamFromQuizData(final PageContext pageContext) { @@ -705,7 +706,7 @@ public class ExamForm implements TemplateComposer { .withQueryParam(QuizData.QUIZ_ATTR_LMS_SETUP_ID, parentEntityKey.modelId) .call() .map(quizzData -> new Exam(quizzData)) - .onError(error -> pageContext.notifyError(error)); + .onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error)); } private String indicatorTypeName(final Indicator indicator) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamToConfigBindPopup.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamToConfigBindPopup.java index afa89535..afdd45e0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamToConfigBindPopup.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamToConfigBindPopup.java @@ -18,6 +18,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; @@ -170,7 +171,8 @@ final class ExamToConfigBindPopup { .getBuilder(GetExam.class) .withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId) .call() - .get(this.pageContext::notifyError) + .onError(error -> this.pageContext.notifyLoadError(EntityType.EXAM, error)) + .getOrThrow() : null; // get data or create new. Handle error if happen @@ -180,7 +182,10 @@ final class ExamToConfigBindPopup { .getBuilder(GetExamConfigMapping.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .get(this.pageContext::notifyError); + .onError(error -> this.pageContext.notifyLoadError( + EntityType.EXAM_CONFIGURATION_MAP, + error)) + .getOrThrow(); // new PageContext with actual EntityKey final PageContext formContext = this.pageContext.withEntityKey(examConfigurationMap.getEntityKey()); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/IndicatorForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/IndicatorForm.java index 72d810af..9e5c2683 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/IndicatorForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/IndicatorForm.java @@ -9,12 +9,11 @@ package ch.ethz.seb.sebserver.gui.content; import org.eclipse.swt.widgets.Composite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; @@ -41,8 +40,6 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @GuiProfile public class IndicatorForm implements TemplateComposer { - private static final Logger log = LoggerFactory.getLogger(IndicatorForm.class); - private static final LocTextKey NEW_INDICATOR_TILE_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.form.title.new"); private static final LocTextKey INDICATOR_TILE_TEXT_KEY = @@ -82,7 +79,8 @@ public class IndicatorForm implements TemplateComposer { .getBuilder(GetExam.class) .withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId) .call() - .get(pageContext::notifyError); + .onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error)) + .getOrThrow(); // get data or create new. Handle error if happen final Indicator indicator = (isNew) @@ -91,14 +89,8 @@ public class IndicatorForm implements TemplateComposer { .getBuilder(GetIndicator.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .get(pageContext::notifyError); - - if (indicator == null) { - log.error("Failed to get Indicator. " - + "Error was notified to the User. " - + "See previous logs for more infomation"); - return; - } + .onError(error -> pageContext.notifyLoadError(EntityType.INDICATOR, error)) + .getOrThrow(); // new PageContext with actual EntityKey final PageContext formContext = pageContext.withEntityKey(indicator.getEntityKey()); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java index 297c02ec..995dbf34 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java @@ -9,8 +9,6 @@ package ch.ethz.seb.sebserver.gui.content; import org.eclipse.swt.widgets.Composite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @@ -44,6 +42,11 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @GuiProfile public class InstitutionForm implements TemplateComposer { + private static final LocTextKey TITLE_TEXT_KEY = + new LocTextKey("sebserver.institution.form.title"); + private static final LocTextKey NEW_TITLE_TEXT_KEY = + new LocTextKey("sebserver.institution.form.title.new"); + private static final LocTextKey FORM_LOGO_IMAGE_TEXT_KEY = new LocTextKey("sebserver.institution.form.logoImage"); private static final LocTextKey FORM_URL_SUFFIX_TEXT_KEY = @@ -51,8 +54,6 @@ public class InstitutionForm implements TemplateComposer { private static final LocTextKey FORM_NAME_TEXT_KEY = new LocTextKey("sebserver.institution.form.name"); - private static final Logger log = LoggerFactory.getLogger(InstitutionForm.class); - private final PageService pageService; private final RestService restService; private final CurrentUser currentUser; @@ -80,14 +81,8 @@ public class InstitutionForm implements TemplateComposer { .getBuilder(GetInstitution.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .get(pageContext::notifyError); - - if (institution == null) { - log.error("Failed to get Institution. " - + "Error was notified to the User. " - + "See previous logs for more infomation"); - return; - } + .onError(error -> pageContext.notifyLoadError(EntityType.INSTITUTION, error)) + .getOrThrow(); final EntityGrantCheck instGrant = this.currentUser.entityGrantCheck(institution); final boolean writeGrant = instGrant.w(); @@ -98,16 +93,10 @@ public class InstitutionForm implements TemplateComposer { // new PageContext with actual EntityKey final PageContext formContext = pageContext.withEntityKey(institution.getEntityKey()); - if (log.isDebugEnabled()) { - log.debug("Institution Form for Institution {}", institution.name); - } - // the default page layout with interactive title - final LocTextKey titleKey = new LocTextKey( - (isNew) - ? "sebserver.institution.form.title.new" - : "sebserver.institution.form.title", - institution.name); + final LocTextKey titleKey = isNew + ? NEW_TITLE_TEXT_KEY + : TITLE_TEXT_KEY; final Composite content = widgetFactory.defaultPageLayout( formContext.getParent(), titleKey); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java index 35e142bb..28e73d6c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java @@ -13,13 +13,12 @@ import java.util.function.Function; import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.widgets.Composite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; @@ -61,7 +60,10 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @GuiProfile public class LmsSetupForm implements TemplateComposer { - private static final Logger log = LoggerFactory.getLogger(LmsSetupForm.class); + private static final LocTextKey TITLE_TEXT_KEY = + new LocTextKey("sebserver.lmssetup.form.title"); + private static final LocTextKey NEW_TITLE_TEXT_KEY = + new LocTextKey("sebserver.lmssetup.form.title.new"); private static final LocTextKey FORM_SECRET_LMS_TEXT_KEY = new LocTextKey("sebserver.lmssetup.form.secret.lms"); @@ -120,23 +122,15 @@ public class LmsSetupForm implements TemplateComposer { .getBuilder(GetLmsSetup.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .get(pageContext::notifyError); - - if (lmsSetup == null) { - log.error( - "Failed to get LmsSetup. " - + "Error was notified to the User. " - + "See previous logs for more infomation"); - return; - } + .onError(error -> pageContext.notifyLoadError(EntityType.LMS_SETUP, error)) + .getOrThrow(); // new PageContext with actual EntityKey final PageContext formContext = pageContext.withEntityKey(lmsSetup.getEntityKey()); // the default page layout with title - final LocTextKey titleKey = new LocTextKey( - isNotNew.getAsBoolean() - ? "sebserver.lmssetup.form.title" - : "sebserver.lmssetup.form.title.new"); + final LocTextKey titleKey = isNotNew.getAsBoolean() + ? TITLE_TEXT_KEY + : NEW_TITLE_TEXT_KEY; final Composite content = widgetFactory.defaultPageLayout( formContext.getParent(), titleKey); @@ -302,7 +296,7 @@ public class LmsSetupForm implements TemplateComposer { API.PARAM_MODEL_ID, action.pageContext().getAttribute(AttributeKeys.ENTITY_ID)) .call() - .onError(t -> action.pageContext().notifyError(t)); + .onError(error -> action.pageContext().notifyActivationError(EntityType.LMS_SETUP, error)); return testLmsSetup; } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java index 21ee21c6..560008b3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java @@ -11,13 +11,12 @@ package ch.ethz.seb.sebserver.gui.content; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.client.service.UrlLauncher; import org.eclipse.swt.widgets.Composite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig; @@ -49,8 +48,6 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @GuiProfile public class SebClientConfigForm implements TemplateComposer { - private static final Logger log = LoggerFactory.getLogger(LmsSetupForm.class); - private static final LocTextKey FORM_TITLE_NEW = new LocTextKey("sebserver.clientconfig.form.title.new"); private static final LocTextKey FORM_TITLE = @@ -106,14 +103,8 @@ public class SebClientConfigForm implements TemplateComposer { .getBuilder(GetClientConfig.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .get(pageContext::notifyError); - - if (clientConfig == null) { - log.error("Failed to get SebClientConfig. " - + "Error was notified to the User. " - + "See previous logs for more infomation"); - return; - } + .onError(error -> pageContext.notifyLoadError(EntityType.SEB_CLIENT_CONFIGURATION, error)) + .getOrThrow(); final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(clientConfig); final boolean writeGrant = entityGrant.w(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImportPopup.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImportPopup.java index b8ec3924..f3ebdce5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImportPopup.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImportPopup.java @@ -20,6 +20,7 @@ import org.eclipse.swt.widgets.Control; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.APIMessage; +import ch.ethz.seb.sebserver.gbl.api.EntityType; 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; @@ -177,13 +178,16 @@ final class SebExamConfigImportPopup { } else { formHandle .getContext() - .notifyError(error); + .notifyImportError(EntityType.CONFIGURATION_NODE, error); } }); return true; } - formHandle.getContext().notifyError(configuration.getError()); + formHandle.getContext().notifyError( + SebExamConfigPropForm.FORM_TITLE, + configuration.getError()); + return true; } } else { @@ -195,7 +199,7 @@ final class SebExamConfigImportPopup { return false; } catch (final Exception e) { - formHandle.getContext().notifyError(e); + formHandle.getContext().notifyError(SebExamConfigPropForm.FORM_TITLE, e); return true; } } 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 4db98c0b..84c44208 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 @@ -18,8 +18,6 @@ import org.eclipse.rap.rwt.client.service.UrlLauncher; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @@ -71,8 +69,6 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant; @GuiProfile public class SebExamConfigPropForm implements TemplateComposer { - private static final Logger log = LoggerFactory.getLogger(SebExamConfigPropForm.class); - static final LocTextKey FORM_TITLE_NEW = new LocTextKey("sebserver.examconfig.form.title.new"); static final LocTextKey FORM_TITLE = @@ -139,13 +135,8 @@ public class SebExamConfigPropForm implements TemplateComposer { .getBuilder(GetExamConfigNode.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .get(pageContext::notifyError); - if (examConfig == null) { - log.error("Failed to get ConfigurationNode. " - + "Error was notified to the User. " - + "See previous logs for more infomation"); - return; - } + .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error)) + .getOrThrow(); final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(examConfig); final boolean writeGrant = entityGrant.w(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java index 78dcbdaf..d94b36e4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java @@ -102,7 +102,7 @@ public class SebExamConfigSettingsForm implements TemplateComposer { final ConfigurationNode configNode = this.restService.getBuilder(GetExamConfigNode.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .onError(pageContext::notifyError) + .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error)) .getOrThrow(); final Configuration configuration = this.restService.getBuilder(GetConfigurations.class) @@ -110,12 +110,12 @@ public class SebExamConfigSettingsForm implements TemplateComposer { .withQueryParam(Configuration.FILTER_ATTR_FOLLOWUP, Constants.TRUE_STRING) .call() .map(Utils::toSingleton) - .onError(pageContext::notifyError) + .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION, error)) .getOrThrow(); final AttributeMapping attributes = this.examConfigurationService .getAttributes(configNode.templateId) - .onError(pageContext::notifyError) + .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_ATTRIBUTE, error)) .getOrThrow(); final boolean readonly = pageContext.isReadonly() || configNode.status == ConfigurationStatus.IN_USE; @@ -195,11 +195,11 @@ public class SebExamConfigSettingsForm implements TemplateComposer { .publish(); } catch (final RuntimeException e) { - log.error("Unexpected error while trying to fetch exam configuration data and create views", e); + pageContext.notifyUnexpectedError(e); throw e; } catch (final Exception e) { log.error("Unexpected error while trying to fetch exam configuration data and create views", e); - pageContext.notifyError(e); + pageContext.notifyError(SebExamConfigPropForm.FORM_TITLE, e); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountChangePasswordForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountChangePasswordForm.java index b09826ee..ee00b517 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountChangePasswordForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountChangePasswordForm.java @@ -15,6 +15,7 @@ import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange; @@ -46,6 +47,7 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; * password that is also required must match the administrators current password. */ public class UserAccountChangePasswordForm implements TemplateComposer { + private static final String FORM_TITLE_KEY = "sebserver.useraccount.form.pwchange.title"; private static final LocTextKey FORM_PASSWORD_NEW_TEXT_KEY = new LocTextKey("sebserver.useraccount.form.password.new"); private static final LocTextKey FORM_PASSWORD_NEW_CONFIRM_TEXT_KEY = @@ -79,11 +81,12 @@ public class UserAccountChangePasswordForm implements TemplateComposer { .getBuilder(GetUserAccount.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .get(pageContext::notifyError); + .onError(error -> pageContext.notifyLoadError(EntityType.USER, error)) + .getOrThrow(); final Composite content = widgetFactory.defaultPageLayout( pageContext.getParent(), - new LocTextKey("sebserver.useraccount.form.pwchange.title", userInfo.username)); + new LocTextKey(FORM_TITLE_KEY, userInfo.username)); final boolean ownAccount = this.currentUser.get().uuid.equals(entityKey.getModelId()); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java index 96a87a7e..2b1d5b9b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java @@ -12,8 +12,6 @@ import java.util.function.BooleanSupplier; import org.apache.tomcat.util.buf.StringUtils; import org.eclipse.swt.widgets.Composite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @@ -56,23 +54,26 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @GuiProfile public class UserAccountForm implements TemplateComposer { - private static final Logger log = LoggerFactory.getLogger(UserAccountForm.class); + static final LocTextKey TITLE_TEXT_KEY = + new LocTextKey("sebserver.useraccount.form.title"); + static final LocTextKey NEW_TITLE_TEXT_KEY = + new LocTextKey("sebserver.useraccount.form.title.new"); - private static final LocTextKey FORM_PASSWORD_CONFIRM_TEXT_KEY = + static final LocTextKey FORM_PASSWORD_CONFIRM_TEXT_KEY = new LocTextKey("sebserver.useraccount.form.password.confirm"); - private static final LocTextKey FORM_PASSWORD_TEXT_KEY = + static final LocTextKey FORM_PASSWORD_TEXT_KEY = new LocTextKey("sebserver.useraccount.form.password"); - private static final LocTextKey FORM_ROLES_TEXT_KEY = + static final LocTextKey FORM_ROLES_TEXT_KEY = new LocTextKey("sebserver.useraccount.form.roles"); - private static final LocTextKey FORM_TIMEZONE_TEXT_KEY = + static final LocTextKey FORM_TIMEZONE_TEXT_KEY = new LocTextKey("sebserver.useraccount.form.timezone"); - private static final LocTextKey FORM_MAIL_TEXT_KEY = + static final LocTextKey FORM_MAIL_TEXT_KEY = new LocTextKey("sebserver.useraccount.form.mail"); - private static final LocTextKey FORM_USERNAME_TEXT_KEY = + static final LocTextKey FORM_USERNAME_TEXT_KEY = new LocTextKey("sebserver.useraccount.form.username"); - private static final LocTextKey FORM_NAME_TEXT_KEY = + static final LocTextKey FORM_NAME_TEXT_KEY = new LocTextKey("sebserver.useraccount.form.name"); - private static final LocTextKey FORM_INSTITUTION_TEXT_KEY = + static final LocTextKey FORM_INSTITUTION_TEXT_KEY = new LocTextKey("sebserver.useraccount.form.institution"); private final PageService pageService; @@ -110,15 +111,8 @@ public class UserAccountForm implements TemplateComposer { .getBuilder(GetUserAccount.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .get(pageContext::notifyError); - - if (userAccount == null) { - log.error( - "Failed to get UserAccount. " - + "Error was notified to the User. " - + "See previous logs for more infomation"); - return; - } + .onError(error -> pageContext.notifyLoadError(EntityType.USER, error)) + .getOrThrow(); final boolean roleBasedEditGrant = Privilege.hasRoleBasedUserAccountEditGrant(userAccount, currentUser.get()); // new PageContext with actual EntityKey @@ -138,16 +132,10 @@ public class UserAccountForm implements TemplateComposer { .map(inst -> inst.active) .getOr(false); - if (log.isDebugEnabled()) { - log.debug("UserAccount Form for user {}", userAccount.getName()); - } - // the default page layout with title - final LocTextKey titleKey = new LocTextKey( - isNotNew.getAsBoolean() - ? "sebserver.useraccount.form.title" - : "sebserver.useraccount.form.title.new", - userAccount.getUsername()); + final LocTextKey titleKey = isNotNew.getAsBoolean() + ? TITLE_TEXT_KEY + : NEW_TITLE_TEXT_KEY; final Composite content = widgetFactory.defaultPageLayout( formContext.getParent(), titleKey); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java index 05388028..8571e490 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java @@ -14,7 +14,9 @@ import java.util.function.Predicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.APIMessage; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Utils; @@ -133,8 +135,16 @@ public class FormHandle { fieldAccessor -> showValidationError(fieldAccessor, fve))); return true; } else { - log.error("Unexpected error while trying to post form: ", error); - this.pageContext.notifyError(error); + log.error("Unexpected error while trying to post form: {}", error.getMessage()); + final EntityType resultType = this.post.getResultType(); + if (resultType != null) { + this.pageContext.notifySaveError(resultType, error); + } else { + this.pageContext.notifyError( + new LocTextKey(PageContext.GENERIC_SAVE_ERROR_TEXT_KEY, Constants.EMPTY_NOTE), + error); + } + return false; } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java index 08b95780..55950fa3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java @@ -286,6 +286,10 @@ public class ResourceService { .collect(Collectors.toList()); } + public static LocTextKey getEntityTypeNameKey(final EntityType type) { + return new LocTextKey(ENTITY_TYPE_PREFIX + type.name()); + } + public String getEntityTypeName(final EntityType type) { if (type == null) { return Constants.EMPTY_NOTE; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/AbstractTableFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/AbstractTableFieldBuilder.java index 3f761668..1383a786 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/AbstractTableFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/AbstractTableFieldBuilder.java @@ -233,6 +233,9 @@ public abstract class AbstractTableFieldBuilder implements InputFieldBuilder { } ConfigurationAttribute attr = tableContext.getAttribute(value.attributeId); + if (attr == null) { + return false; + } while (attr.parentId != null) { if (attribute.id.equals(attr.parentId)) { return true; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java index d4fefefc..1cafeb3b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java @@ -28,6 +28,7 @@ import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.JSONMapper; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; @@ -373,7 +374,7 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService { } } catch (final Exception e) { - this.pageContext.notifyError(e); + this.pageContext.notifySaveError(EntityType.CONFIGURATION_VALUE, e); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageContext.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageContext.java index 0b5f2ed3..15f3b616 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageContext.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageContext.java @@ -15,7 +15,9 @@ import org.eclipse.swt.widgets.Shell; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gui.service.ResourceService; import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; @@ -44,6 +46,17 @@ public interface PageContext { } + /** The resource-bundle key of the generic load entity error message. */ + public static final String GENERIC_LOAD_ERROR_TEXT_KEY = "sebserver.error.get.entity"; + public static final String GENERIC_REMOVE_ERROR_TEXT_KEY = "sebserver.error.remove.entity"; + public static final String GENERIC_SAVE_ERROR_TEXT_KEY = "sebserver.error.save.entity"; + public static final String GENERIC_ACTIVATE_ERROR_TEXT_KEY = "sebserver.error.activate.entity"; + public static final String GENERIC_IMPORT_ERROR_TEXT_KEY = "sebserver.error.import"; + public static final LocTextKey SUCCESS_MSG_TITLE = + new LocTextKey("sebserver.page.message"); + public static final LocTextKey UNEXPECTED_ERROR_KEY = + new LocTextKey("sebserver.error.action.unexpected.message"); + /** Get the I18nSupport service * * @return the I18nSupport service */ @@ -187,14 +200,74 @@ public interface PageContext { * * @param errorMessage the error message to display * @param error the error as Exception */ - void notifyError(String errorMessage, Exception error); + void notifyError(LocTextKey errorMessage, Exception error); - /** Shows an error message to the user with the message of the given Exception. - * This mainly is used for debugging so far + /** Notify a generic load error to the user by pop-up * - * @param error the Exception to display - * @return adaption to be used with functional approaches */ - T notifyError(Exception error); + * @param entityType the type of the entity + * @param error the original error */ + default void notifyLoadError(final EntityType entityType, final Exception error) { + notifyError( + new LocTextKey( + GENERIC_LOAD_ERROR_TEXT_KEY, + getI18nSupport().getText(ResourceService.getEntityTypeNameKey(entityType))), + error); + } + + /** Notify a generic remove error to the user by pop-up + * + * @param entityType the type of the entity + * @param error the original error */ + default void notifyRemoveError(final EntityType entityType, final Exception error) { + notifyError( + new LocTextKey( + GENERIC_REMOVE_ERROR_TEXT_KEY, + getI18nSupport().getText(ResourceService.getEntityTypeNameKey(entityType))), + error); + } + + /** Notify a generic save error to the user by pop-up + * + * @param entityType the type of the entity + * @param error the original error */ + default void notifySaveError(final EntityType entityType, final Exception error) { + notifyError( + new LocTextKey( + GENERIC_SAVE_ERROR_TEXT_KEY, + getI18nSupport().getText(ResourceService.getEntityTypeNameKey(entityType))), + error); + } + + /** Notify a generic activation error to the user by pop-up + * + * @param entityType the type of the entity + * @param error the original error */ + default void notifyActivationError(final EntityType entityType, final Exception error) { + notifyError( + new LocTextKey( + GENERIC_ACTIVATE_ERROR_TEXT_KEY, + getI18nSupport().getText(ResourceService.getEntityTypeNameKey(entityType))), + error); + } + + /** Notify a generic import error to the user by pop-up + * + * @param entityType the type of the entity + * @param error the original error */ + default void notifyImportError(final EntityType entityType, final Exception error) { + notifyError( + new LocTextKey( + GENERIC_IMPORT_ERROR_TEXT_KEY, + getI18nSupport().getText(ResourceService.getEntityTypeNameKey(entityType))), + error); + } + + /** Notify a generic unexpected error to the user by pop-up + * + * @param error the original error */ + default void notifyUnexpectedError(final Exception error) { + notifyError(UNEXPECTED_ERROR_KEY, error); + } /** Publish and shows a message to the user with the given localized title and * localized message. The message text can also be HTML text as far as RWT supports it. diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java index 6f687954..7c1fa296 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java @@ -313,12 +313,13 @@ public interface PageService { final Class> restCallType) { this.exec = action -> { + final PageContext pageContext = action.pageContext(); restService.getBuilder(restCallType) .withURIVariable( API.PARAM_MODEL_ID, action.pageContext().getAttribute(AttributeKeys.ENTITY_ID)) .call() - .onError(t -> action.pageContext().notifyError(t)); + .onError(pageContext::notifyUnexpectedError); return action; }; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageAction.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageAction.java index 948500c3..518e9a76 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageAction.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageAction.java @@ -20,6 +20,7 @@ import org.slf4j.LoggerFactory; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.page.PageContext; @@ -32,11 +33,8 @@ public final class PageAction { private static final Logger log = LoggerFactory.getLogger(PageAction.class); - public static final LocTextKey SUCCESS_MSG_TITLE = new LocTextKey("sebserver.page.message"); - public final ActionDefinition definition; private final Supplier confirm; - final LocTextKey successMessage; private final Supplier> selectionSupplier; private final LocTextKey noSelectionMessage; private PageContext pageContext; @@ -44,6 +42,8 @@ public final class PageAction { final boolean fireActionEvent; final boolean ignoreMoveAwayFromEdit; + final LocTextKey successMessage; + public PageAction( final ActionDefinition definition, final Supplier confirm, @@ -76,6 +76,14 @@ public final class PageAction { } } + public String getName() { + if (this.definition != null) { + return this.definition.name(); + } + + return Constants.EMPTY_NOTE; + } + public EntityKey getEntityKey() { return this.pageContext.getEntityKey(); } @@ -144,7 +152,9 @@ public final class PageAction { final PageAction apply = this.exec.apply(this); if (this.successMessage != null) { - apply.pageContext.publishPageMessage(SUCCESS_MSG_TITLE, this.successMessage); + apply.pageContext.publishPageMessage( + PageContext.SUCCESS_MSG_TITLE, + this.successMessage); } return Result.of(apply); @@ -153,13 +163,23 @@ public final class PageAction { return Result.ofError(pme); } catch (final RestCallError restCallError) { if (!restCallError.isFieldValidationError()) { - log.error("Failed to execute action: {}", PageAction.this, restCallError); - PageAction.this.pageContext.notifyError("action.error.unexpected.message", restCallError); + log.error("Failed to execute action: {} | error: {} | cause: {}", + PageAction.this.getName(), + restCallError.getMessage(), + Utils.getErrorCauseMessage(restCallError)); + PageAction.this.pageContext.notifyError( + PageContext.UNEXPECTED_ERROR_KEY, + restCallError); } return Result.ofError(restCallError); } catch (final Exception e) { - log.error("Failed to execute action: {}", PageAction.this, e); - PageAction.this.pageContext.notifyError("action.error.unexpected.message", e); + log.error("Failed to execute action: {} | error: {} | cause: {}", + PageAction.this.getName(), + e.getMessage(), + Utils.getErrorCauseMessage(e)); + PageAction.this.pageContext.notifyError( + PageContext.UNEXPECTED_ERROR_KEY, + e); return Result.ofError(e); } } @@ -179,6 +199,31 @@ public final class PageAction { return this; } + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("PageAction [definition="); + builder.append(this.definition); + builder.append(", confirm="); + builder.append(this.confirm); + builder.append(", selectionSupplier="); + builder.append(this.selectionSupplier); + builder.append(", noSelectionMessage="); + builder.append(this.noSelectionMessage); + builder.append(", pageContext="); + builder.append(this.pageContext); + builder.append(", exec="); + builder.append(this.exec); + builder.append(", fireActionEvent="); + builder.append(this.fireActionEvent); + builder.append(", ignoreMoveAwayFromEdit="); + builder.append(this.ignoreMoveAwayFromEdit); + builder.append(", successMessage="); + builder.append(this.successMessage); + builder.append("]"); + return builder.toString(); + } + public static PageAction applySingleSelection(final PageAction action) { return action.withEntityKey(action.getSingleSelection()); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageContextImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageContextImpl.java index f94f741d..c8f4ab8f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageContextImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageContextImpl.java @@ -280,13 +280,17 @@ public class PageContextImpl implements PageContext { } @Override - public void notifyError(final String errorMessage, final Exception error) { + public void notifyError(final LocTextKey message, final Exception error) { + final String errorMessage = message != null + ? this.i18nSupport.getText(message) + : error.getMessage(); + if (error instanceof APIMessageError) { final List errorMessages = ((APIMessageError) error).getErrorMessages(); final MessageBox messageBox = new Message( getShell(), this.i18nSupport.getText("sebserver.error.unexpected"), - APIMessage.toHTML(errorMessages), + APIMessage.toHTML(errorMessage, errorMessages), SWT.ERROR); messageBox.setMarkupEnabled(true); messageBox.open(null); @@ -301,12 +305,6 @@ public class PageContextImpl implements PageContext { messageBox.open(null); } - @Override - public T notifyError(final Exception error) { - notifyError(error.getMessage(), error); - return null; - } - @Override public String toString() { return "PageContextImpl [root=" + this.root + ", parent=" + this.parent + ", attributes=" + this.attributes diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java index b248ad67..dc026c18 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java @@ -55,6 +55,8 @@ public class PageServiceImpl implements PageService { private static final LocTextKey MSG_GO_AWAY_FROM_EDIT = new LocTextKey("sebserver.overall.action.goAwayFromEditPageConfirm"); + private static final LocTextKey LOGOUT_ERROR_MESSAGE = + new LocTextKey("sebserver.error.logout"); private static final String ATTR_PAGE_STATE = "PAGE_STATE"; private static final ListenerComparator LIST_COMPARATOR = new ListenerComparator(); @@ -234,7 +236,9 @@ public class PageServiceImpl implements PageService { if (!logoutSuccessful) { log.error("Failed to logout. See logfiles for more information"); - pageContext.notifyError(new RuntimeException("Failed to logout. See logfiles for more information")); + pageContext.notifyError( + LOGOUT_ERROR_MESSAGE, + new RuntimeException("Failed to logout. See logfiles for more information")); } } catch (final Exception e) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java index e4d3d518..42221ac7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java @@ -94,6 +94,14 @@ public abstract class RestCall { return this; } + public EntityType getResultType() { + if (this.typeKey != null) { + return this.typeKey.entityType; + } + + return null; + } + protected Result exchange(final RestCallBuilder builder) { log.debug("Call webservice API on {} for {}", this.path, builder); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java index e9e7cc2e..34d2b7cd 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java @@ -393,7 +393,7 @@ public class EntityTable { .call() .map(this::createTableRowsFromPage) .map(this.navigator::update) - .onError(this.pageContext::notifyError); + .onError(this.pageContext::notifyUnexpectedError); this.composite.getParent().layout(true, true); PageService.updateScrolledComposite(this.composite); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionService.java index 7ec04439..97526a77 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionService.java @@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction; import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; /** Service to address bulk actions like activation or deletion where the action * or state-change of one Entity has an effect on other entities that that has diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java index 77122779..f7e8d56c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java @@ -21,12 +21,12 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ActivatableEntityDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.EntityDAO; /** Defines overall DAO support for bulk-actions like activate, deactivate, delete... - * * * @param The type of the Entity of a concrete BulkActionSupportDAO */ public interface BulkActionSupportDAO { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkAction.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/BulkAction.java similarity index 97% rename from src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkAction.java rename to src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/BulkAction.java index 3b08634c..9c567acd 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkAction.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/BulkAction.java @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction; +package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl; import java.util.Arrays; import java.util.Collection; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionEvent.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/BulkActionEvent.java similarity index 77% rename from src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionEvent.java rename to src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/BulkActionEvent.java index d37a7e93..ca3387b5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionEvent.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/BulkActionEvent.java @@ -6,10 +6,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction; +package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl; import org.springframework.context.ApplicationEvent; +/** Defines a bulk-action event fired after a bulk-action happened */ public class BulkActionEvent extends ApplicationEvent { private static final long serialVersionUID = 1102149193640832829L; @@ -18,6 +19,9 @@ public class BulkActionEvent extends ApplicationEvent { super(source); } + /** Get the wrapped BulkAction instance + * + * @return the wrapped BulkAction instance */ public BulkAction getBulkAction() { return (BulkAction) this.source; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/BulkActionServiceImpl.java similarity index 95% rename from src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionServiceImpl.java rename to src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/BulkActionServiceImpl.java index 7a5e75dd..2dc81b87 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/impl/BulkActionServiceImpl.java @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction; +package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl; import java.util.Arrays; import java.util.Collection; @@ -28,6 +28,8 @@ import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; @Service diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/.gitignore b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/.gitignore new file mode 100644 index 00000000..c6a822f3 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/.gitignore @@ -0,0 +1 @@ +/ExamDAO.java diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/AdditionalAttributesDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/AdditionalAttributesDAO.java index 9aa4e831..cdfdac8a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/AdditionalAttributesDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/AdditionalAttributesDAO.java @@ -14,22 +14,50 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.AdditionalAttributeRecord; +/** Defines functionality to access additional attributes. + * + * Additional attributes are name/value pairs associated with a specified entity but stored + * in a separated data-base table. */ public interface AdditionalAttributesDAO { + /** Use this to get all additional attribute records for a specific entity. + * + * @param type the entity type + * @param entityId the entity identifier (primary key) + * @return Result refer to the collection of additional attribute records or to an error if happened */ Result> getAdditionalAttributes( EntityType type, Long entityId); + /** Use this to save an additional attribute for a specific entity. + * If the additional attribute with specified name already exists for the specified entity + * this updates just the value for this additional attribute. Otherwise create a new instance + * of additional attribute with the given data + * + * @param type the entity type + * @param entityId the entity identifier (primary key) + * @param name the name of the attribute + * @param value the value of the attribute */ void saveAdditionalAttribute( EntityType type, Long entityId, String name, String value); + /** Use this to delete an additional attribute by identifier (primary-key) + * + * @param id identifier (primary-key) */ void delete(Long id); + /** Use this to delete an additional attribute by its entity identifier and name. + * + * @param entityId the entity identifier (primary-key) + * @param name the name of the additional attribute */ void delete(Long entityId, String name); + /** Use this to delete all additional attributes for a given entity. + * + * @param entityId the entity identifier (primary-key) */ void deleteAll(Long entityId); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientEventDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientEventDAO.java index ca97ca9c..f913def5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientEventDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientEventDAO.java @@ -17,6 +17,11 @@ import ch.ethz.seb.sebserver.gbl.util.Result; public interface ClientEventDAO extends EntityDAO { + /** Use this to get all matching ExtendedClientEvent from persistent storage. + * + * @param filterMap the FilterMap containing all the filter criteria + * @param predicate an additional predicate to filter the list + * @return Result refer to all matching ExtendedClientEvent from persistent storage or to an error if happened. */ Result> allMatchingExtended( FilterMap filterMap, Predicate predicate); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationAttributeDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationAttributeDAO.java index fe583a4f..698f6906 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationAttributeDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationAttributeDAO.java @@ -18,9 +18,14 @@ public interface ConfigurationAttributeDAO extends EntityDAO> getAllRootAttributes(); + /** Use this to get all ConfigurationAttribute that are children of a specified ConfigurationAttribute. + * + * @param parentId the identifier of the ConfigurationAttribute to get the children for + * @return Result refer to a collection of child ConfigurationAttribute or to an error if happened */ Result> allChildAttributes(final Long parentId); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationNodeDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationNodeDAO.java index ee707c30..313e3e42 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationNodeDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationNodeDAO.java @@ -17,6 +17,12 @@ public interface ConfigurationNodeDAO extends EntityDAO, BulkActionSupportDAO { + /** Use this to create a copy from an existing configuration. + * + * @param institutionId the institution identifier of the existing configuration + * @param newOwner the owner of the created copy + * @param copyInfo the ConfigCreationInfo containing additional copy information + * @return Result refer to the configuration copy root node or to an error if happened */ Result createCopy( Long institutionId, String newOwner, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationValueDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationValueDAO.java index 3d69d416..a56d0da4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationValueDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationValueDAO.java @@ -59,6 +59,13 @@ public interface ConfigurationValueDAO extends EntityDAO saveTableValues(ConfigurationTableValues value); + /** Use this to (re)set the default value(s) for a configuration attributes of a given configuration entry. + * This uses also the ExamConfigInitService to initialize table values + * + * @param institutionId the institution identifier of the configuration + * @param configurationId the configuration identifier + * @param attributeId the configuration attribute identifier + * @return Result refer to a set of all keys of default values or to an error if happened */ Result> setDefaultValues( Long institutionId, Long configurationId, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java index 25fe737f..d7abff76 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java @@ -41,22 +41,68 @@ public interface ExamDAO extends ActivatableEntityDAO, BulkActionSup * @return a Result containing the Exam by a given ClientConnection id or refer to an error if happened */ Result byClientConnection(Long connectionId); + /** Use this to get identifiers of all exams in a specified state for a specified institution. + * + * @param institutionId the institution identifier. May be null for all institutions + * @param status the ExamStatus + * @return Result refer to collection of exam identifiers or to an error if happened */ Result> getExamIdsForStatus(Long institutionId, ExamStatus status); + /** This is used to get all Exams to check if they have to set into running state in the meanwhile. + * Gets all exams in the upcoming status for run-check + * + * @return Result refer to a collection of exams or to an error if happened */ Result> allForRunCheck(); + /** This is used to get all Exams to check if they have to set into finished state in the meanwhile. + * Gets all exams in the running status for end-check + * + * @return Result refer to a collection of exams or to an error if happened */ Result> allForEndCheck(); - Result placeLock(Long examId, String update); + /** This is used to place an internal (write)lock for the specified exam. + * The exam will be marked as locked on the persistence level to prevent other running web-service instances + * to write concurrently to the specified exam while it is been updated by an internal batch process. + * + * @param examId the exam identifier + * @param updateId an update identifier + * @return Result refer to the specified exam or to an error if happened */ + Result placeLock(Long examId, String updateId); - Result releaseLock(Long examId, String update); + /** This is used to release an internal (write)lock for the specified exam. + * The exam will be marked as not locked on the persistence level. + * + * @param examId the exam identifier + * @param updateId an update identifier + * @return Result refer to the specified exam or to an error if happened */ + Result releaseLock(Long examId, String updateId); + /** This is used to force release an internal (write)lock for the specified exam. + * The exam will be marked as not locked on the persistence level even if it is currently locked by another process + * + * @param examId the exam identifier + * @param updateId an update identifier + * @return Result refer to the specified exam or to an error if happened */ Result forceUnlock(Long examId); + /** Indicates if the exam with specified identifier has an internal write lock. + * + * @param examId the exam identifier + * @return Result refer to the lock-check-result or to an error if happened */ Result isLocked(Long examId); - Result upToDate(Long examId, String lastUpdate); + /** Use this to check of the exam with the specified identifier is up to date + * + * @param examId the exam identifier + * @param updateId the update identifier of the exam + * @return Result refer to the up-to-date result or to an error if happened */ + Result upToDate(Long examId, String updateId); - Result setSebRestriction(Long id, boolean sebRestriction); + /** This is used to set the seb-restriction flag for a specified exam. + * + * @param examId the exam identifier + * @param sebRestriction the seb-restriction flag value + * @return Result refer to the updated Exam or to an error if happened */ + Result setSebRestriction(Long examId, boolean sebRestriction); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/LmsSetupDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/LmsSetupDAO.java index 0faeb327..c065f0ac 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/LmsSetupDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/LmsSetupDAO.java @@ -24,5 +24,9 @@ public interface LmsSetupDAO extends ActivatableEntityDAO, B * @return the configured ClientCredentials for a given LmsSetup */ Result getLmsAPIAccessCredentials(String lmsSetupId); + /** Use this to get additional proxy data for specified LMS Setup. + * + * @param lmsSetupId the LMS Setup identifier + * @return Result refer to the proxy data or to an error if happened */ Result getLmsAPIAccessProxyData(String lmsSetupId); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java index 12e91b75..3a7ed791 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java @@ -41,7 +41,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationReco import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationNodeRecord; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationValueDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationValueDAOImpl.java index 0ba5a028..ded200c7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationValueDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationValueDAOImpl.java @@ -17,6 +17,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Function; @@ -33,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional; import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; @@ -51,6 +53,7 @@ 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.ResourceNotFoundException; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler; +import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigInitService; @Lazy @Component @@ -63,17 +66,20 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO { private final ConfigurationAttributeRecordMapper configurationAttributeRecordMapper; private final ConfigurationRecordMapper configurationRecordMapper; private final ConfigurationDAOBatchService configurationDAOBatchService; + private final ExamConfigInitService examConfigInitService; protected ConfigurationValueDAOImpl( final ConfigurationValueRecordMapper configurationValueRecordMapper, final ConfigurationAttributeRecordMapper configurationAttributeRecordMapper, final ConfigurationRecordMapper configurationRecordMapper, - final ConfigurationDAOBatchService configurationDAOBatchService) { + final ConfigurationDAOBatchService configurationDAOBatchService, + final ExamConfigInitService examConfigInitService) { this.configurationValueRecordMapper = configurationValueRecordMapper; this.configurationAttributeRecordMapper = configurationAttributeRecordMapper; this.configurationRecordMapper = configurationRecordMapper; this.configurationDAOBatchService = configurationDAOBatchService; + this.examConfigInitService = examConfigInitService; } @Override @@ -388,10 +394,12 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO { .map(r -> new EntityKey(r.getId(), EntityType.CONFIGURATION_VALUE)) .collect(Collectors.toSet())); - // if there are table values, delete them first + // if there are table values, delete them first and init defaults if (tableValues != null && !tableValues.isEmpty()) { this.delete(tableValues) .getOrThrow(); + + initTableValues(institutionId, configurationId, attributeId); } } @@ -413,7 +421,7 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO { return tableValues; } else { if (values.size() > 1) { - throw new IllegalStateException("Expacted one but get: " + values.size()); + throw new IllegalStateException("Expected one but get: " + values.size()); } final ConfigurationAttributeRecord attribute = this.configurationAttributeRecordMapper @@ -439,6 +447,41 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO { }); } + private void initTableValues(final Long institutionId, final Long configurationId, final Long attributeId) { + // get table init values and save + final List childAttributes = this.configurationAttributeRecordMapper.selectIdsByExample() + .where( + ConfigurationAttributeRecordDynamicSqlSupport.parentId, + isEqualTo(attributeId)) + .build() + .execute(); + // get all attributes and map the names to id's + final Map attributeMap = this.configurationAttributeRecordMapper + .selectByExample() + .build() + .execute() + .stream() + .map(ConfigurationAttributeDAOImpl::toDomainModel) + .map(Result::get) + .filter(Objects::nonNull) + .collect(Collectors.toMap( + attr -> attr.name, + Function.identity())); + + this.examConfigInitService + .getAdditionalDefaultValues(institutionId, configurationId, attributeMap::get) + .stream() + .filter(attrValue -> childAttributes.contains(attrValue.attributeId)) + .forEach(attrValue -> this.configurationValueRecordMapper + .insert(new ConfigurationValueRecord( + null, + attrValue.institutionId, + attrValue.configurationId, + attrValue.attributeId, + attrValue.listIndex, + attrValue.value))); + } + // get all attributes of the table (columns) mapped to attribute id private Result> getAttributeMapping( final ConfigurationAttributeRecord attributeRecord) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java index 5a959687..e3a8685e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java @@ -47,7 +47,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationNodeRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ExamConfigurationMapRecord; 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.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java index 763fb460..9bdd4435 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java @@ -44,7 +44,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientConnectionR import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport; 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.servicelayer.bulkaction.BulkAction; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException; @@ -170,6 +170,12 @@ public class ExamDAOImpl implements ExamDAO { public Result save(final Exam exam) { return Result.tryCatch(() -> { + // check internal persistent write-lock + final ExamRecord oldRecord = this.examRecordMapper.selectByPrimaryKey(exam.id); + if (BooleanUtils.isTrue(BooleanUtils.toBooleanObject(oldRecord.getUpdating()))) { + throw new IllegalStateException("Exam is currently locked: " + String.valueOf(exam)); + } + final ExamRecord examRecord = new ExamRecord( exam.id, null, null, null, null, @@ -376,7 +382,7 @@ public class ExamDAOImpl implements ExamDAO { @Override @Transactional(propagation = Propagation.REQUIRES_NEW) - public Result placeLock(final Long examId, final String update) { + public Result placeLock(final Long examId, final String updateId) { return Result.tryCatch(() -> { final ExamRecord examRec = this.recordById(examId) @@ -391,7 +397,7 @@ public class ExamDAOImpl implements ExamDAO { examId, null, null, null, null, null, null, null, null, null, null, BooleanUtils.toInteger(true), - update, + updateId, null); this.examRecordMapper.updateByPrimaryKeySelective(newRecord); @@ -404,7 +410,7 @@ public class ExamDAOImpl implements ExamDAO { @Override @Transactional(propagation = Propagation.REQUIRES_NEW) - public Result releaseLock(final Long examId, final String update) { + public Result releaseLock(final Long examId, final String updateId) { return Result.tryCatch(() -> { final ExamRecord examRec = this.recordById(examId) @@ -412,7 +418,7 @@ public class ExamDAOImpl implements ExamDAO { // consistency check if (BooleanUtils.isFalse(BooleanUtils.toBooleanObject(examRec.getUpdating())) - || !update.equals(examRec.getLastupdate())) { + || !updateId.equals(examRec.getLastupdate())) { throw new IllegalStateException("Exam to end update is not in expected state: " + examRec); } @@ -421,7 +427,7 @@ public class ExamDAOImpl implements ExamDAO { examId, null, null, null, null, null, null, null, null, null, null, BooleanUtils.toInteger(false), - update, + updateId, null); this.examRecordMapper.updateByPrimaryKeySelective(newRecord); @@ -461,13 +467,13 @@ public class ExamDAOImpl implements ExamDAO { @Override @Transactional(readOnly = true) - public Result upToDate(final Long examId, final String lastUpdate) { + public Result upToDate(final Long examId, final String updateId) { return this.recordById(examId) .map(rec -> { - if (lastUpdate == null) { + if (updateId == null) { return rec.getLastupdate() == null; } else { - return lastUpdate.equals(rec.getLastupdate()); + return updateId.equals(rec.getLastupdate()); } }); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/IndicatorDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/IndicatorDAOImpl.java index 23da5eb4..4225b41a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/IndicatorDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/IndicatorDAOImpl.java @@ -40,7 +40,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ThresholdRecordDy import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ThresholdRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.IndicatorRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ThresholdRecord; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; 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.IndicatorDAO; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/InstitutionDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/InstitutionDAOImpl.java index 417d2b3f..f4086148 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/InstitutionDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/InstitutionDAOImpl.java @@ -36,7 +36,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordDynamicSqlSupport; 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.servicelayer.bulkaction.BulkAction; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; 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.InstitutionDAO; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/LmsSetupDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/LmsSetupDAOImpl.java index dd4cbfda..a667928a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/LmsSetupDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/LmsSetupDAOImpl.java @@ -37,7 +37,7 @@ import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordDynamicSqlSupport; 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.servicelayer.bulkaction.BulkAction; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService; import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentials; import ch.ethz.seb.sebserver.webservice.servicelayer.client.ProxyData; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/SebClientConfigDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/SebClientConfigDAOImpl.java index 3d313aa4..a310aadd 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/SebClientConfigDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/SebClientConfigDAOImpl.java @@ -40,7 +40,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.SebClientConfigRe import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.SebClientConfigRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.AdditionalAttributeRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.SebClientConfigRecord; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService; import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentials; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserDAOImpl.java index 9e519cf3..d414d259 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserDAOImpl.java @@ -55,7 +55,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordMapper; 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.servicelayer.authorization.impl.SEBServerUser; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; 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.TransactionHandler; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxCourseRestriction.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxCourseRestriction.java index 6638187a..4e3eb2d9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxCourseRestriction.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxCourseRestriction.java @@ -199,20 +199,15 @@ public class OpenEdxCourseRestriction { final HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); return () -> { - try { - final OpenEdxCourseRestrictionData body = this.restTemplate.exchange( - url, - HttpMethod.PUT, - new HttpEntity<>(toJson(restriction), httpHeaders), - OpenEdxCourseRestrictionData.class) - .getBody(); + final OpenEdxCourseRestrictionData body = this.restTemplate.exchange( + url, + HttpMethod.PUT, + new HttpEntity<>(toJson(restriction), httpHeaders), + OpenEdxCourseRestrictionData.class) + .getBody(); - if (log.isDebugEnabled()) { - log.debug("Successfully PUT SEB Client restriction on course: {} : {}", courseId, body); - } - } catch (final Exception e) { - log.error("Unexpected error while trying to call API for PUT. Course: ", courseId, e); - return false; + if (log.isDebugEnabled()) { + log.debug("Successfully PUT SEB Client restriction on course: {} : {}", courseId, body); } return true; @@ -223,23 +218,18 @@ public class OpenEdxCourseRestriction { final String url = this.lmsSetup.lmsApiUrl + getSebRestrictionUrl(courseId); return () -> { - try { - final ResponseEntity exchange = this.restTemplate.exchange( - url, - HttpMethod.DELETE, - new HttpEntity<>(new HttpHeaders()), - Object.class); + final ResponseEntity exchange = this.restTemplate.exchange( + url, + HttpMethod.DELETE, + new HttpEntity<>(new HttpHeaders()), + Object.class); - if (exchange.getStatusCode() == HttpStatus.NO_CONTENT) { - if (log.isDebugEnabled()) { - log.debug("Successfully PUT SEB Client restriction on course: {}", courseId); - } - } else { - log.error("Unexpected response for deletion: {}", exchange); - return false; + if (exchange.getStatusCode() == HttpStatus.NO_CONTENT) { + if (log.isDebugEnabled()) { + log.debug("Successfully PUT SEB Client restriction on course: {}", courseId); } - } catch (final Exception e) { - log.error("Unexpected error while trying to call API for DELETE. Course: ", courseId, e); + } else { + log.error("Unexpected response for deletion: {}", exchange); return false; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ClientConfigService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ClientConfigService.java index f46fe11a..4696d2b0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ClientConfigService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ClientConfigService.java @@ -19,7 +19,7 @@ import org.springframework.security.oauth2.provider.ClientDetails; import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig; import ch.ethz.seb.sebserver.gbl.util.Result; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionEvent; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkActionEvent; public interface ClientConfigService { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java index 62b001b4..872ad3ee 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java @@ -42,8 +42,8 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.WebserviceInfo; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionEvent; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkActionEvent; import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService; import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentials; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java index 44bf835d..6b801ffa 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java @@ -26,8 +26,8 @@ import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ActivatableEntityDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java index c8b18989..6cc6b391 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java @@ -44,8 +44,8 @@ import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService; +import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.EntityDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 3286dfe1..696f2f51 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -81,6 +81,14 @@ sebserver.dialog.confirm.title=Confirmation sebserver.dialog.confirm.deactivation=Note that there are {0} other entities that belongs to this entity.
Those will also be deactivated by deactivating this entity.

Are You sure to deactivate this entity? sebserver.dialog.confirm.deactivation.noDependencies=Are You sure you want to deactivate? +sebserver.error.action.unexpected.message=

Failed to process action. There was an unexpected error.
Please try again or contact a system-administrator if this error persists +sebserver.error.get.entity=

Failed to load {0}.
Please try again or contact a system-administrator if this error persists +sebserver.error.remove.entity=

Failed to remove {0}.
Please try again or contact a system-administrator if this error persists +sebserver.error.activate.entity=

Failed to activate/deactivate {0}.
Please try again or contact a system-administrator if this error persists +sebserver.error.save.entity=

Failed to save {0}.
Please try again or contact a system-administrator if this error persists +sebserver.error.exam.seb.restriction=

Failed to automatically set Safe Exam Browser restriction on/off for this exam on the corresponding LMS.
Please check the LMS Setup and try again or contact a system-administrator if this error persists +sebserver.error.import=

Failed to import {0}.
Please try again or contact a system-administrator if this error persists +sebserver.error.logout=

Failed to logout properly.
Please try again or contact a system-administrator if this error persists ################################ # Login Page ################################