SEBSERV-10 GUI implementation

This commit is contained in:
anhefti 2020-07-14 15:25:42 +02:00
parent e5025e1c47
commit f61b142cc7
60 changed files with 1172 additions and 351 deletions

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gbl.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class EntityDependency implements Comparable<EntityDependency> {
@JsonProperty(value = "parent", required = true)
public final EntityKey parent;
@JsonProperty(value = "self", required = true)
public final EntityKey self;
@JsonProperty(value = "name", required = true)
public final String name;
@JsonProperty(value = "description", required = false)
public final String description;
public EntityDependency(
@JsonProperty(value = "parent", required = true) final EntityKey parent,
@JsonProperty(value = "self", required = true) final EntityKey self,
@JsonProperty(value = "name", required = true) final String name,
@JsonProperty(value = "description", required = false) final String description) {
this.parent = parent;
this.self = self;
this.name = name;
this.description = description;
}
public EntityKey getParent() {
return this.parent;
}
public EntityKey getSelf() {
return this.self;
}
public String getName() {
return this.name;
}
public String getDescription() {
return this.description;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.parent == null) ? 0 : this.parent.hashCode());
result = prime * result + ((this.self == null) ? 0 : this.self.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final EntityDependency other = (EntityDependency) obj;
if (this.parent == null) {
if (other.parent != null)
return false;
} else if (!this.parent.equals(other.parent))
return false;
if (this.self == null) {
if (other.self != null)
return false;
} else if (!this.self.equals(other.self))
return false;
return true;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("EntityDependency [parent=");
builder.append(this.parent);
builder.append(", self=");
builder.append(this.self);
builder.append(", name=");
builder.append(this.name);
builder.append(", description=");
builder.append(this.description);
builder.append("]");
return builder.toString();
}
@Override
public int compareTo(final EntityDependency other) {
if (other == null) {
return -1;
}
final int compareTo = this.self.entityType.name().compareTo(other.self.entityType.name());
if (compareTo == 0) {
return this.self.modelId.compareTo(other.self.modelId);
} else {
return compareTo;
}
}
}

View file

@ -78,13 +78,11 @@ public class ConfigTemplateAttributeForm implements TemplateComposer {
protected ConfigTemplateAttributeForm(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
final ExamConfigurationService examConfigurationService) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.restService = pageService.getRestService();
this.currentUser = pageService.getCurrentUser();
this.resourceService = pageService.getResourceService();
this.examConfigurationService = examConfigurationService;

View file

@ -80,6 +80,7 @@ public class ConfigTemplateForm implements TemplateComposer {
private final PageService pageService;
private final RestService restService;
private final CurrentUser currentUser;
private final SEBExamConfigCreationPopup sebxamConfigCreationPopup;
private final I18nSupport i18nSupport;
private final ResourceService resourceService;
private final ExamConfigurationService examConfigurationService;
@ -91,16 +92,16 @@ public class ConfigTemplateForm implements TemplateComposer {
protected ConfigTemplateForm(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
final SEBExamConfigCreationPopup sebxamConfigCreationPopup,
final ExamConfigurationService examConfigurationService) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.restService = pageService.getRestService();
this.currentUser = pageService.getCurrentUser();
this.i18nSupport = pageService.getI18nSupport();
this.resourceService = pageService.getResourceService();
this.examConfigurationService = examConfigurationService;
this.sebxamConfigCreationPopup = sebxamConfigCreationPopup;
}
@ -292,8 +293,7 @@ public class ConfigTemplateForm implements TemplateComposer {
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_CREATE_CONFIG)
.withEntityKey(entityKey)
.withExec(SEBExamConfigCreationPopup.configCreationFunction(
this.pageService,
.withExec(this.sebxamConfigCreationPopup.configCreationFunction(
pageContext
.withAttribute(
PageContext.AttributeKeys.CREATE_FROM_TEMPLATE,

View file

@ -72,13 +72,11 @@ public class ConfigTemplateList implements TemplateComposer {
protected ConfigTemplateList(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.restService = pageService.getRestService();
this.currentUser = pageService.getCurrentUser();
this.resourceService = pageService.getResourceService();
this.pageSize = pageSize;

View file

@ -162,6 +162,8 @@ public class ExamForm implements TemplateComposer {
private final PageService pageService;
private final ResourceService resourceService;
private final ExamSEBRestrictionSettings examSEBRestrictionSettings;
private final ExamToConfigBindingForm examToConfigBindingForm;
private final DownloadService downloadService;
private final String downloadFileName;
private final WidgetFactory widgetFactory;
@ -169,12 +171,15 @@ public class ExamForm implements TemplateComposer {
protected ExamForm(
final PageService pageService,
final ResourceService resourceService,
final ExamSEBRestrictionSettings examSEBRestrictionSettings,
final ExamToConfigBindingForm examToConfigBindingForm,
final DownloadService downloadService,
@Value("${sebserver.gui.seb.exam.config.download.filename}") final String downloadFileName) {
this.pageService = pageService;
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
this.examSEBRestrictionSettings = examSEBRestrictionSettings;
this.examToConfigBindingForm = examToConfigBindingForm;
this.downloadService = downloadService;
this.downloadFileName = downloadFileName;
this.widgetFactory = pageService.getWidgetFactory();
@ -393,7 +398,7 @@ public class ExamForm implements TemplateComposer {
.newAction(ActionDefinition.EXAM_MODIFY_SEB_RESTRICTION_DETAILS)
.withEntityKey(entityKey)
.withExec(ExamSEBRestrictionSettings.settingsFunction(this.pageService))
.withExec(this.examSEBRestrictionSettings.settingsFunction(this.pageService))
.withAttribute(
ExamSEBRestrictionSettings.PAGE_CONTEXT_ATTR_LMS_TYPE,
this.restService.getBuilder(GetLmsSetup.class)
@ -406,13 +411,13 @@ public class ExamForm implements TemplateComposer {
.newAction(ActionDefinition.EXAM_ENABLE_SEB_RESTRICTION)
.withEntityKey(entityKey)
.withExec(action -> ExamSEBRestrictionSettings.setSEBRestriction(action, true, this.restService))
.withExec(action -> this.examSEBRestrictionSettings.setSEBRestriction(action, true, this.restService))
.publishIf(() -> sebRestrictionAvailable && readonly && modifyGrant && !importFromQuizData
&& BooleanUtils.isFalse(isRestricted))
.newAction(ActionDefinition.EXAM_DISABLE_SEB_RESTRICTION)
.withEntityKey(entityKey)
.withExec(action -> ExamSEBRestrictionSettings.setSEBRestriction(action, false, this.restService))
.withExec(action -> this.examSEBRestrictionSettings.setSEBRestriction(action, false, this.restService))
.publishIf(() -> sebRestrictionAvailable && readonly && modifyGrant && !importFromQuizData
&& BooleanUtils.isTrue(isRestricted));
@ -471,7 +476,7 @@ public class ExamForm implements TemplateComposer {
.newAction(ActionDefinition.EXAM_CONFIGURATION_NEW)
.withParentEntityKey(entityKey)
.withExec(ExamToConfigBindingForm.bindFunction(this.pageService))
.withExec(this.examToConfigBindingForm.bindFunction())
.noEventPropagation()
.publishIf(() -> modifyGrant && editable && !configurationTable.hasAnyContent())
@ -590,7 +595,7 @@ public class ExamForm implements TemplateComposer {
// when okay and the exam sebRestriction is true
if (applySEBRestriction) {
ExamSEBRestrictionSettings.setSEBRestriction(
this.examSEBRestrictionSettings.setSEBRestriction(
processFormSave,
true,
this.restService,

View file

@ -95,11 +95,10 @@ public class ExamList implements TemplateComposer {
protected ExamList(
final PageService pageService,
final ResourceService resourceService,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
this.pageService = pageService;
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
this.pageSize = pageSize;
this.institutionFilter = new TableFilterAttribute(

View file

@ -20,6 +20,8 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.widgets.Composite;
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;
@ -28,6 +30,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Chapters;
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBRestriction;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Tuple;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.gui.form.Form;
@ -47,6 +50,9 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetCourseCha
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetSEBRestriction;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveSEBRestriction;
@Lazy
@Component
@GuiProfile
public class ExamSEBRestrictionSettings {
private final static LocTextKey SEB_RESTRICTION_ERROR =
@ -73,7 +79,7 @@ public class ExamSEBRestrictionSettings {
static final String PAGE_CONTEXT_ATTR_LMS_TYPE = "ATTR_LMS_TYPE";
static Function<PageAction, PageAction> settingsFunction(final PageService pageService) {
Function<PageAction, PageAction> settingsFunction(final PageService pageService) {
return action -> {
@ -104,7 +110,7 @@ public class ExamSEBRestrictionSettings {
};
}
private static boolean doCreate(
private boolean doCreate(
final PageService pageService,
final PageContext pageContext,
final FormHandle<?> formHandle) {
@ -160,7 +166,7 @@ public class ExamSEBRestrictionSettings {
.hasError();
}
private static final class SEBRestrictionPropertiesForm
private final class SEBRestrictionPropertiesForm
implements ModalInputDialogComposer<FormHandle<?>> {
private final PageService pageService;
@ -290,7 +296,7 @@ public class ExamSEBRestrictionSettings {
}
private static LmsType getLmsType(final PageContext pageContext) {
private LmsType getLmsType(final PageContext pageContext) {
try {
return LmsType.valueOf(pageContext.getAttribute(PAGE_CONTEXT_ATTR_LMS_TYPE));
} catch (final Exception e) {
@ -298,7 +304,7 @@ public class ExamSEBRestrictionSettings {
}
}
public static PageAction setSEBRestriction(
public PageAction setSEBRestriction(
final PageAction action,
final boolean activateRestriction,
final RestService restService) {
@ -310,7 +316,7 @@ public class ExamSEBRestrictionSettings {
error -> action.pageContext().notifyError(SEB_RESTRICTION_ERROR, error));
}
public static PageAction setSEBRestriction(
public PageAction setSEBRestriction(
final PageAction action,
final boolean activateRestriction,
final RestService restService,

View file

@ -16,6 +16,8 @@ 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.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
@ -24,6 +26,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.Form;
@ -45,7 +48,10 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.NewExamConfi
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExamConfigMapping;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
final class ExamToConfigBindingForm {
@Lazy
@Component
@GuiProfile
public class ExamToConfigBindingForm {
private static final Logger log = LoggerFactory.getLogger(ExamToConfigBindingForm.class);
@ -66,8 +72,13 @@ final class ExamToConfigBindingForm {
private final static LocTextKey CONFIG_ACTION_NO_CONFIG_MESSAGE =
new LocTextKey("sebserver.exam.configuration.action.noconfig.message");
static Function<PageAction, PageAction> bindFunction(final PageService pageService) {
private final PageService pageService;
protected ExamToConfigBindingForm(final PageService pageService) {
this.pageService = pageService;
}
Function<PageAction, PageAction> bindFunction() {
return action -> {
final PageContext pageContext = action.pageContext();
@ -75,7 +86,7 @@ final class ExamToConfigBindingForm {
final boolean isNew = entityKey == null;
if (isNew) {
final boolean noConfigsAvailable = pageService.getResourceService()
final boolean noConfigsAvailable = this.pageService.getResourceService()
.examConfigurationSelectionResources()
.isEmpty();
@ -87,15 +98,15 @@ final class ExamToConfigBindingForm {
final ModalInputDialog<FormHandle<ExamConfigurationMap>> dialog =
new ModalInputDialog<FormHandle<ExamConfigurationMap>>(
action.pageContext().getParent().getShell(),
pageService.getWidgetFactory())
this.pageService.getWidgetFactory())
.setLargeDialogWidth();
final BindFormContext bindFormContext = new BindFormContext(
pageService,
this.pageService,
action.pageContext());
final Predicate<FormHandle<ExamConfigurationMap>> doBind = formHandle -> doCreate(
pageService,
this.pageService,
pageContext,
formHandle);
@ -114,7 +125,7 @@ final class ExamToConfigBindingForm {
};
}
private static boolean doCreate(
private boolean doCreate(
final PageService pageService,
final PageContext pageContext,
final FormHandle<ExamConfigurationMap> formHandle) {
@ -143,7 +154,7 @@ final class ExamToConfigBindingForm {
.hasError();
}
private static final class BindFormContext implements ModalInputDialogComposer<FormHandle<ExamConfigurationMap>> {
private final class BindFormContext implements ModalInputDialogComposer<FormHandle<ExamConfigurationMap>> {
private final PageService pageService;
private final PageContext pageContext;
@ -244,7 +255,7 @@ final class ExamToConfigBindingForm {
}
}
private static void updateFormValuesFromConfigSelection(final Form form, final ResourceService resourceService) {
private void updateFormValuesFromConfigSelection(final Form form, final ResourceService resourceService) {
final String configId = form.getFieldValue(Domain.EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID);
if (StringUtils.isBlank(configId)) {
form.setFieldValue(Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION, null);

View file

@ -71,12 +71,10 @@ public class IndicatorForm implements TemplateComposer {
private final ResourceService resourceService;
private final I18nSupport i18nSupport;
protected IndicatorForm(
final PageService pageService,
final ResourceService resourceService) {
protected IndicatorForm(final PageService pageService) {
this.pageService = pageService;
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
this.i18nSupport = pageService.getI18nSupport();
}

View file

@ -57,14 +57,11 @@ public class InstitutionForm implements TemplateComposer {
private final RestService restService;
private final CurrentUser currentUser;
protected InstitutionForm(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser) {
protected InstitutionForm(final PageService pageService) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.restService = pageService.getRestService();
this.currentUser = pageService.getCurrentUser();
}
@Override

View file

@ -66,13 +66,11 @@ public class InstitutionList implements TemplateComposer {
protected InstitutionList(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.restService = pageService.getRestService();
this.currentUser = pageService.getCurrentUser();
this.pageSize = pageSize;
this.activityFilter = new TableFilterAttribute(
@ -87,8 +85,8 @@ public class InstitutionList implements TemplateComposer {
final Composite content = this.pageService
.getWidgetFactory()
.defaultPageLayout(
pageContext.getParent(),
TITLE_TEXT_KEY);
pageContext.getParent(),
TITLE_TEXT_KEY);
final PageActionBuilder pageActionBuilder =
this.pageService.pageActionBuilder(pageContext.clearEntityKeys());

View file

@ -104,12 +104,10 @@ public class LmsSetupForm implements TemplateComposer {
private final PageService pageService;
private final ResourceService resourceService;
protected LmsSetupForm(
final PageService pageService,
final ResourceService resourceService) {
protected LmsSetupForm(final PageService pageService) {
this.pageService = pageService;
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
}
@Override

View file

@ -75,11 +75,10 @@ public class LmsSetupList implements TemplateComposer {
protected LmsSetupList(
final PageService pageService,
final ResourceService resourceService,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
this.pageService = pageService;
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
this.pageSize = pageSize;
this.institutionFilter = new TableFilterAttribute(

View file

@ -95,7 +95,6 @@ public class MonitoringClientConnection implements TemplateComposer {
protected MonitoringClientConnection(
final ServerPushService serverPushService,
final PageService pageService,
final ResourceService resourceService,
final InstructionProcessor instructionProcessor,
final SEBClientLogDetailsPopup sebClientLogDetailsPopup,
@Value("${sebserver.gui.webservice.poll-interval:500}") final long pollInterval,
@ -103,8 +102,8 @@ public class MonitoringClientConnection implements TemplateComposer {
this.serverPushService = serverPushService;
this.pageService = pageService;
this.resourceService = resourceService;
this.i18nSupport = resourceService.getI18nSupport();
this.resourceService = pageService.getResourceService();
this.i18nSupport = this.resourceService.getI18nSupport();
this.instructionProcessor = instructionProcessor;
this.pollInterval = pollInterval;
this.sebClientLogDetailsPopup = sebClientLogDetailsPopup;

View file

@ -85,13 +85,12 @@ public class MonitoringRunningExam implements TemplateComposer {
protected MonitoringRunningExam(
final ServerPushService serverPushService,
final PageService pageService,
final ResourceService resourceService,
final InstructionProcessor instructionProcessor,
@Value("${sebserver.gui.webservice.poll-interval:1000}") final long pollInterval) {
this.serverPushService = serverPushService;
this.pageService = pageService;
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
this.instructionProcessor = instructionProcessor;
this.pollInterval = pollInterval;
}

View file

@ -62,11 +62,10 @@ public class MonitoringRunningExamList implements TemplateComposer {
protected MonitoringRunningExamList(
final PageService pageService,
final ResourceService resourceService,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
this.pageService = pageService;
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
this.pageSize = pageSize;
this.typeFilter = new TableFilterAttribute(

View file

@ -117,12 +117,11 @@ public class QuizLookupList implements TemplateComposer {
protected QuizLookupList(
final PageService pageService,
final ResourceService resourceService,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
this.pageService = pageService;
this.widgetFactory = pageService.getWidgetFactory();
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
this.pageSize = pageSize;
this.institutionFilter = new TableFilterAttribute(

View file

@ -115,14 +115,12 @@ public class SEBClientConfigForm implements TemplateComposer {
protected SEBClientConfigForm(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
final DownloadService downloadService,
@Value("${sebserver.gui.seb.client.config.download.filename}") final String downloadFileName) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.restService = pageService.getRestService();
this.currentUser = pageService.getCurrentUser();
this.downloadService = downloadService;
this.downloadFileName = downloadFileName;
}

View file

@ -83,13 +83,11 @@ public class SEBClientConfigList implements TemplateComposer {
protected SEBClientConfigList(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.restService = pageService.getRestService();
this.currentUser = pageService.getCurrentUser();
this.resourceService = pageService.getResourceService();
this.pageSize = pageSize;

View file

@ -8,6 +8,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.model.Domain;
@ -28,11 +34,6 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnection;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
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;
@Lazy
@Component
@ -86,12 +87,10 @@ public class SEBClientLogDetailsPopup {
private final I18nSupport i18nSupport;
private final WidgetFactory widgetFactory;
public SEBClientLogDetailsPopup(
final PageService pageService,
final WidgetFactory widgetFactory) {
public SEBClientLogDetailsPopup(final PageService pageService) {
this.pageService = pageService;
this.widgetFactory = widgetFactory;
this.widgetFactory = pageService.getWidgetFactory();
this.resourceService = pageService.getResourceService();
this.restService = pageService.getRestService();
this.i18nSupport = pageService.getI18nSupport();
@ -124,7 +123,7 @@ public class SEBClientLogDetailsPopup {
WidgetFactory.CustomVariant.TEXT_H3,
DETAILS_EVENT_TILE_TEXT_KEY);
PageContext formContext = pc.copyOf(content);
final PageContext formContext = pc.copyOf(content);
this.pageService.formBuilder(formContext)
.withDefaultSpanInput(6)

View file

@ -14,6 +14,8 @@ import java.util.function.Supplier;
import org.apache.commons.lang3.BooleanUtils;
import org.eclipse.swt.widgets.Composite;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Domain;
@ -21,6 +23,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCreationInfo;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
@ -35,7 +38,10 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.CopyConfiguration;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig;
final class SEBExamConfigCreationPopup {
@Lazy
@Component
@GuiProfile
public class SEBExamConfigCreationPopup {
static final LocTextKey FORM_COPY_TEXT_KEY =
new LocTextKey("sebserver.examconfig.action.copy.dialog");
@ -44,10 +50,13 @@ final class SEBExamConfigCreationPopup {
static final LocTextKey FORM_CREATE_FROM_TEMPLATE_TEXT_KEY =
new LocTextKey("sebserver.configtemplate.action.create-config.dialog");
static Function<PageAction, PageAction> configCreationFunction(
final PageService pageService,
final PageContext pageContext) {
private final PageService pageService;
protected SEBExamConfigCreationPopup(final PageService pageService) {
this.pageService = pageService;
}
Function<PageAction, PageAction> configCreationFunction(final PageContext pageContext) {
final boolean copyAsTemplate = BooleanUtils.toBoolean(
pageContext.getAttribute(PageContext.AttributeKeys.COPY_AS_TEMPLATE));
final boolean createFromTemplate = BooleanUtils.toBoolean(
@ -58,17 +67,17 @@ final class SEBExamConfigCreationPopup {
final ModalInputDialog<FormHandle<ConfigCreationInfo>> dialog =
new ModalInputDialog<FormHandle<ConfigCreationInfo>>(
action.pageContext().getParent().getShell(),
pageService.getWidgetFactory())
this.pageService.getWidgetFactory())
.setLargeDialogWidth();
final CreationFormContext formContext = new CreationFormContext(
pageService,
this.pageService,
pageContext,
copyAsTemplate,
createFromTemplate);
final Predicate<FormHandle<ConfigCreationInfo>> doCopy = formHandle -> doCreate(
pageService,
this.pageService,
pageContext,
copyAsTemplate,
createFromTemplate,
@ -90,7 +99,7 @@ final class SEBExamConfigCreationPopup {
};
}
private static boolean doCreate(
private boolean doCreate(
final PageService pageService,
final PageContext pageContext,
final boolean copyAsTemplate,
@ -130,7 +139,7 @@ final class SEBExamConfigCreationPopup {
return true;
}
private static final class CreationFormContext implements ModalInputDialogComposer<FormHandle<ConfigCreationInfo>> {
private final class CreationFormContext implements ModalInputDialogComposer<FormHandle<ConfigCreationInfo>> {
private final PageService pageService;
private final PageContext pageContext;
@ -188,7 +197,5 @@ final class SEBExamConfigCreationPopup {
return () -> formHandle;
}
}
}

View file

@ -103,19 +103,24 @@ public class SEBExamConfigForm implements TemplateComposer {
private final PageService pageService;
private final RestService restService;
private final SEBExamConfigCreationPopup sebExamConfigCreationPopup;
private final SEBExamConfigImportPopup sebExamConfigImportPopup;
private final CurrentUser currentUser;
private final DownloadService downloadService;
private final String downloadFileName;
protected SEBExamConfigForm(
final PageService pageService,
final CurrentUser currentUser,
final SEBExamConfigCreationPopup sebExamConfigCreationPopup,
final SEBExamConfigImportPopup sebExamConfigImportPopup,
final DownloadService downloadService,
@Value("${sebserver.gui.seb.exam.config.download.filename}") final String downloadFileName) {
this.pageService = pageService;
this.restService = pageService.getRestService();
this.currentUser = currentUser;
this.sebExamConfigCreationPopup = sebExamConfigCreationPopup;
this.sebExamConfigImportPopup = sebExamConfigImportPopup;
this.currentUser = pageService.getCurrentUser();
this.downloadService = downloadService;
this.downloadFileName = downloadFileName;
}
@ -228,8 +233,7 @@ public class SEBExamConfigForm implements TemplateComposer {
.newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG)
.withEntityKey(entityKey)
.withExec(SEBExamConfigCreationPopup.configCreationFunction(
this.pageService,
.withExec(this.sebExamConfigCreationPopup.configCreationFunction(
actionContext
.withEntityKey(entityKey)
.withAttribute(
@ -243,8 +247,7 @@ public class SEBExamConfigForm implements TemplateComposer {
.newAction(ActionDefinition.SEA_EXAM_CONFIG_COPY_CONFIG_AS_TEMPLATE)
.withEntityKey(entityKey)
.withExec(SEBExamConfigCreationPopup.configCreationFunction(
this.pageService,
.withExec(this.sebExamConfigCreationPopup.configCreationFunction(
pageContext.withAttribute(
PageContext.AttributeKeys.COPY_AS_TEMPLATE,
Constants.TRUE_STRING)))
@ -272,7 +275,7 @@ public class SEBExamConfigForm implements TemplateComposer {
.newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_EXISTING_CONFIG)
.withEntityKey(entityKey)
.withExec(SEBExamConfigImportPopup.importFunction(this.pageService, false))
.withExec(this.sebExamConfigImportPopup.importFunction(false))
.noEventPropagation()
.publishIf(() -> modifyGrant && isReadonly && !isAttachedToExam)

View file

@ -19,6 +19,8 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
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.APIMessage;
@ -27,6 +29,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Tuple;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
@ -49,34 +52,39 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.Im
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportNewExamConfig;
import ch.ethz.seb.sebserver.gui.widget.FileUploadSelection;
final class SEBExamConfigImportPopup {
@Lazy
@Component
@GuiProfile
public class SEBExamConfigImportPopup {
private static final Logger log = LoggerFactory.getLogger(SEBExamConfigImportPopup.class);
private final static PageMessageException MISSING_PASSWORD = new PageMessageException(
new LocTextKey("sebserver.examconfig.action.import.missing-password"));
static Function<PageAction, PageAction> importFunction(
final PageService pageService,
final boolean newConfig) {
private final PageService pageService;
protected SEBExamConfigImportPopup(final PageService pageService) {
this.pageService = pageService;
}
public Function<PageAction, PageAction> importFunction(final boolean newConfig) {
return action -> {
final ModalInputDialog<FormHandle<ConfigurationNode>> dialog =
new ModalInputDialog<FormHandle<ConfigurationNode>>(
action.pageContext().getParent().getShell(),
pageService.getWidgetFactory())
this.pageService.getWidgetFactory())
.setLargeDialogWidth();
final ImportFormContext importFormContext = new ImportFormContext(
pageService,
this.pageService,
action.pageContext(),
newConfig);
dialog.open(
SEBExamConfigForm.FORM_IMPORT_TEXT_KEY,
(Predicate<FormHandle<ConfigurationNode>>) formHandle -> doImport(
pageService,
formHandle,
newConfig),
importFormContext::cancelUpload,
@ -86,8 +94,7 @@ final class SEBExamConfigImportPopup {
};
}
private static boolean doImport(
final PageService pageService,
private boolean doImport(
final FormHandle<ConfigurationNode> formHandle,
final boolean newConfig) {
@ -104,14 +111,14 @@ final class SEBExamConfigImportPopup {
if (StringUtils.isBlank(fieldValue)) {
form.setFieldError(
Domain.CONFIGURATION_NODE.ATTR_NAME,
pageService
this.pageService
.getI18nSupport()
.getText(new LocTextKey("sebserver.form.validation.fieldError.notNull")));
return false;
} else if (fieldValue.length() < 3 || fieldValue.length() > 255) {
form.setFieldError(
Domain.CONFIGURATION_NODE.ATTR_NAME,
pageService
this.pageService
.getI18nSupport()
.getText(new LocTextKey("sebserver.form.validation.fieldError.size",
null,
@ -123,7 +130,7 @@ final class SEBExamConfigImportPopup {
} else {
// check if name already exists
try {
if (pageService.getRestService()
if (this.pageService.getRestService()
.getBuilder(GetExamConfigNodeNames.class)
.call()
.getOrThrow()
@ -134,7 +141,7 @@ final class SEBExamConfigImportPopup {
form.setFieldError(
Domain.CONFIGURATION_NODE.ATTR_NAME,
pageService
this.pageService
.getI18nSupport()
.getText(new LocTextKey(
"sebserver.form.validation.fieldError.name.notunique")));
@ -151,9 +158,9 @@ final class SEBExamConfigImportPopup {
final InputStream inputStream = fileUpload.getInputStream();
if (inputStream != null) {
final RestCall<Configuration>.RestCallBuilder restCall = (newConfig)
? pageService.getRestService()
? this.pageService.getRestService()
.getBuilder(ImportNewExamConfig.class)
: pageService.getRestService()
: this.pageService.getRestService()
.getBuilder(ImportExamConfigOnExistingConfig.class);
restCall
@ -184,11 +191,11 @@ final class SEBExamConfigImportPopup {
context.publishInfo(SEBExamConfigForm.FORM_IMPORT_CONFIRM_TEXT_KEY);
if (newConfig) {
final PageAction action = pageService.pageActionBuilder(context)
final PageAction action = this.pageService.pageActionBuilder(context)
.newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG)
.create();
pageService.firePageEvent(
this.pageService.firePageEvent(
new ActionEvent(action),
action.pageContext());
}
@ -233,7 +240,7 @@ final class SEBExamConfigImportPopup {
}
}
private static final class ImportFormContext implements ModalInputDialogComposer<FormHandle<ConfigurationNode>> {
private final class ImportFormContext implements ModalInputDialogComposer<FormHandle<ConfigurationNode>> {
private final PageService pageService;
private final PageContext pageContext;

View file

@ -28,7 +28,6 @@ import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodePage;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
@ -68,20 +67,19 @@ public class SEBExamConfigList implements TemplateComposer {
private final TableFilterAttribute statusFilter;
private final PageService pageService;
private final RestService restService;
private final SEBExamConfigImportPopup sebExamConfigImportPopup;
private final CurrentUser currentUser;
private final ResourceService resourceService;
private final int pageSize;
protected SEBExamConfigList(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
final SEBExamConfigImportPopup sebExamConfigImportPopup,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.sebExamConfigImportPopup = sebExamConfigImportPopup;
this.currentUser = pageService.getCurrentUser();
this.resourceService = pageService.getResourceService();
this.pageSize = pageSize;
@ -109,7 +107,7 @@ public class SEBExamConfigList implements TemplateComposer {
// exam configuration table
final EntityTable<ConfigurationNode> configTable =
this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigNodePage.class))
this.pageService.entityTableBuilder(GetExamConfigNodePage.class)
.withStaticFilter(
Domain.CONFIGURATION_NODE.ATTR_TYPE,
ConfigurationType.EXAM_CONFIG.name())
@ -172,7 +170,7 @@ public class SEBExamConfigList implements TemplateComposer {
.newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG)
.withSelect(
configTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUTION),
SEBExamConfigImportPopup.importFunction(this.pageService, true),
this.sebExamConfigImportPopup.importFunction(true),
EMPTY_SELECTION_TEXT_KEY)
.noEventPropagation()
.publishIf(examConfigGrant::im);

View file

@ -46,8 +46,8 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigHistory;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SEBExamConfigUndo;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigHistory;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@ -73,18 +73,19 @@ public class SEBSettingsForm implements TemplateComposer {
private final PageService pageService;
private final RestService restService;
private final SEBExamConfigCreationPopup sebExamConfigCreationPopup;
private final CurrentUser currentUser;
private final ExamConfigurationService examConfigurationService;
protected SEBSettingsForm(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
final SEBExamConfigCreationPopup sebExamConfigCreationPopup,
final ExamConfigurationService examConfigurationService) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.restService = pageService.getRestService();
this.sebExamConfigCreationPopup = sebExamConfigCreationPopup;
this.currentUser = pageService.getCurrentUser();
this.examConfigurationService = examConfigurationService;
}
@ -192,8 +193,7 @@ public class SEBSettingsForm implements TemplateComposer {
.newAction(ActionDefinition.SEA_EXAM_CONFIG_COPY_CONFIG_AS_TEMPLATE)
.withEntityKey(entityKey)
.withExec(SEBExamConfigCreationPopup.configCreationFunction(
this.pageService,
.withExec(this.sebExamConfigCreationPopup.configCreationFunction(
pageContext
.withAttribute(
PageContext.AttributeKeys.COPY_AS_TEMPLATE,

View file

@ -44,8 +44,7 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
* If the current user is the owner of the User-Account the password is required and must
* match the users current password.
* If the current user is an administrator that has to reset another users password the
* password that is also required must match the administrators current password.
**/
* 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";
@ -61,14 +60,11 @@ public class UserAccountChangePasswordForm implements TemplateComposer {
private final CurrentUser currentUser;
private final I18nSupport i18nSupport;
protected UserAccountChangePasswordForm(
final PageService pageService,
final RestService restService,
final CurrentUser currentUser) {
protected UserAccountChangePasswordForm(final PageService pageService) {
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.restService = pageService.getRestService();
this.currentUser = pageService.getCurrentUser();
this.i18nSupport = pageService.getI18nSupport();
}

View file

@ -0,0 +1,188 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gui.content;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.apache.commons.lang3.BooleanUtils;
import org.eclipse.swt.widgets.Composite;
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.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.gui.form.Form;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
import ch.ethz.seb.sebserver.gui.form.FormHandle;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard;
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardAction;
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardPage;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserDependency;
@Lazy
@Component
@GuiProfile
public class UserAccountDeletePopup {
private final static String ARG_WITH_CONFIGS = "WITH_CONFIGS";
private final static String ARG_WITH_EXAMS = "WITH_EXAMS";
private final static LocTextKey FORM_TITLE =
new LocTextKey("sebserver.useraccount.delete.form.title");
private final static LocTextKey FORM_INFO =
new LocTextKey("sebserver.useraccount.delete.form.info");
private final static LocTextKey FORM_NAME =
new LocTextKey("sebserver.useraccount.delete.form.accountName");
private final static LocTextKey FORM_CONFIGS =
new LocTextKey("sebserver.useraccount.delete.form.deleteAlsoConfigs");
private final static LocTextKey FORM_EXAMS =
new LocTextKey("sebserver.useraccount.delete.form.deleteAlsoExams");
private final static LocTextKey ACTION_DELETE =
new LocTextKey("sebserver.useraccount.delete.form.action.delete");
private final static LocTextKey ACTION_REPORT =
new LocTextKey("sebserver.useraccount.delete.form.action.report");
private final PageService pageService;
protected UserAccountDeletePopup(final PageService pageService) {
this.pageService = pageService;
}
public Function<PageAction, PageAction> deleteWizardFunction(final PageContext pageContext) {
return action -> {
final ModelInputWizard<PageContext> wizard =
new ModelInputWizard<PageContext>(
action.pageContext().getParent().getShell(),
this.pageService.getWidgetFactory())
.setLargeDialogWidth();
final String page1Id = "DELETE_PAGE";
final String page2Id = "REPORT_PAGE";
final Predicate<PageContext> callback = pc -> doDelete(this.pageService, pc);
final BiFunction<PageContext, Composite, Supplier<PageContext>> composePage1 =
(formHandle, content) -> composeDeleteDialog(content, pageContext);
final BiFunction<PageContext, Composite, Supplier<PageContext>> composePage2 =
(formHandle, content) -> composeReportDialog(content, pageContext);
final WizardPage<PageContext> page1 = new WizardPage<>(
page1Id,
true,
composePage1,
new WizardAction<>(ACTION_DELETE, callback),
new WizardAction<>(ACTION_REPORT, page2Id));
final WizardPage<PageContext> page2 = new WizardPage<>(
page2Id,
false,
composePage2,
new WizardAction<>(ACTION_DELETE, callback));
wizard.open(FORM_TITLE, Utils.EMPTY_EXECUTION, page1, page2);
return action;
};
}
private boolean doDelete(
final PageService pageService,
final PageContext pageContext) {
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
final boolean withExams = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_EXAMS));
return true;
}
private Supplier<PageContext> composeDeleteDialog(
final Composite parent,
final PageContext pageContext) {
final EntityKey entityKey = pageContext.getEntityKey();
final UserInfo userInfo = this.pageService.getRestService()
.getBuilder(GetUserAccount.class)
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
.call()
.get();
final FormHandle<?> formHandle = this.pageService.formBuilder(
pageContext.copyOf(parent))
.readonly(false)
.addField(FormBuilder.text(
"USE_NAME",
FORM_NAME,
userInfo.toName().name)
.readonly(true))
.addField(FormBuilder.checkbox(
ARG_WITH_CONFIGS,
FORM_CONFIGS))
.addField(FormBuilder.checkbox(
ARG_WITH_EXAMS,
FORM_EXAMS))
.build();
final Form form = formHandle.getForm();
return () -> pageContext
.withAttribute(ARG_WITH_CONFIGS, form.getFieldValue(ARG_WITH_CONFIGS))
.withAttribute(ARG_WITH_EXAMS, form.getFieldValue(ARG_WITH_EXAMS));
}
private Supplier<PageContext> composeReportDialog(
final Composite parent,
final PageContext pageContext) {
// get selection
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
final boolean withExams = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_EXAMS));
// get dependencies
final EntityKey entityKey = pageContext.getEntityKey();
final RestCall<Set<EntityDependency>>.RestCallBuilder restCallBuilder = this.pageService.getRestService()
.getBuilder(GetUserDependency.class)
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId);
if (withConfigs) {
restCallBuilder.withQueryParam(
API.PARAM_BULK_ACTION_INCLUDES,
EntityType.CONFIGURATION_NODE.name());
}
if (withExams) {
restCallBuilder.withQueryParam(
API.PARAM_BULK_ACTION_INCLUDES,
EntityType.EXAM.name());
}
// final EntityTable<ConfigurationNode> configTable =
// this.pageService.entityTableBuilder(GetUserDependency.class)
// .
final Set<EntityDependency> dependencies = restCallBuilder.call().getOrThrow();
// TODO get dependencies in case of selection and show all in a list (type / name)
return () -> pageContext;
}
}

View file

@ -86,15 +86,17 @@ public class UserAccountForm implements TemplateComposer {
private final PageService pageService;
private final ResourceService resourceService;
private final UserAccountDeletePopup userAccountDeletePopup;
private final boolean multilingual;
protected UserAccountForm(
final PageService pageService,
final ResourceService resourceService,
final UserAccountDeletePopup userAccountDeletePopup,
@Value("${sebserver.gui.multilingual:false}") final Boolean multilingual) {
this.pageService = pageService;
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
this.userAccountDeletePopup = userAccountDeletePopup;
this.multilingual = BooleanUtils.toBoolean(multilingual);
}
@ -266,6 +268,11 @@ public class UserAccountForm implements TemplateComposer {
.withSimpleRestCall(restService, ActivateUserAccount.class)
.publishIf(() -> writeGrant && readonly && institutionActive && !userAccount.isActive())
.newAction(ActionDefinition.USER_ACCOUNT_DELETE)
.withEntityKey(entityKey)
.withExec(this.userAccountDeletePopup.deleteWizardFunction(pageContext))
.publishIf(() -> (writeGrant || ownAccount) && readonly && institutionActive)
.newAction(ActionDefinition.USER_ACCOUNT_SAVE)
.withEntityKey(entityKey)
.withExec(action -> formHandle.handleFormPost(formHandle.doAPIPost()
@ -289,4 +296,5 @@ public class UserAccountForm implements TemplateComposer {
.withExec(this.pageService.backToCurrentFunction())
.publishIf(() -> !readonly);
}
}

View file

@ -96,12 +96,11 @@ public class UserAccountList implements TemplateComposer {
protected UserAccountList(
final PageService pageService,
final ResourceService resourceService,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize,
@Value("${sebserver.gui.multilingual:false}") final Boolean ml) {
this.pageService = pageService;
this.resourceService = resourceService;
this.resourceService = pageService.getResourceService();
this.pageSize = pageSize;
this.multilingual = BooleanUtils.isTrue(ml);

View file

@ -130,6 +130,11 @@ public enum ActionDefinition {
ImageIcon.SWITCH,
PageStateDefinitionImpl.USER_ACCOUNT_LIST,
ActionCategory.USER_ACCOUNT_LIST),
USER_ACCOUNT_DELETE(
new LocTextKey("sebserver.useraccount.action.delete"),
ImageIcon.DELETE,
PageStateDefinitionImpl.USER_ACCOUNT_LIST,
ActionCategory.USER_ACCOUNT_LIST),
USER_ACCOUNT_CHANGE_PASSWORD(
new LocTextKey("sebserver.useraccount.action.change.password"),

View file

@ -280,6 +280,15 @@ public interface PageService {
* @return a FormBuilder instance for the given PageContext and with number of rows */
FormBuilder formBuilder(PageContext pageContext, int rows);
/** Get an new TableBuilder for specified page based RestCall.
*
* @param apiCall the SEB Server API RestCall that feeds the table with data
* @param <T> the type of the Entity of the table
* @return TableBuilder of specified type */
default <T extends Entity> TableBuilder<T> entityTableBuilder(final Class<? extends RestCall<Page<T>>> apiCall) {
return entityTableBuilder(this.getRestService().getRestCall(apiCall));
}
/** Get an new TableBuilder for specified page based RestCall.
*
* @param apiCall the SEB Server API RestCall that feeds the table with data

View file

@ -38,11 +38,11 @@ public class ModalInputDialog<T> extends Dialog {
public static final int LARGE_DIALOG_WIDTH = 600;
public static final int VERY_LARGE_DIALOG_WIDTH = 800;
private static final LocTextKey CANCEL_TEXT_KEY =
public static final LocTextKey CANCEL_TEXT_KEY =
new LocTextKey("sebserver.overall.action.cancel");
private static final LocTextKey OK_TEXT_KEY =
public static final LocTextKey OK_TEXT_KEY =
new LocTextKey("sebserver.overall.action.ok");
private static final LocTextKey CLOSE_TEXT_KEY =
public static final LocTextKey CLOSE_TEXT_KEY =
new LocTextKey("sebserver.overall.action.close");
private final WidgetFactory widgetFactory;

View file

@ -0,0 +1,234 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gui.service.page.impl;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Shell;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
public class ModelInputWizard<T> extends Dialog {
private static final long serialVersionUID = -3314062148477979319L;
private final WidgetFactory widgetFactory;
private int dialogWidth = ModalInputDialog.DEFAULT_DIALOG_WIDTH;
private int dialogHeight = ModalInputDialog.DEFAULT_DIALOG_HEIGHT;
private int buttonWidth = ModalInputDialog.DEFAULT_DIALOG_BUTTON_WIDTH;
public ModelInputWizard(
final Shell parent,
final WidgetFactory widgetFactory) {
super(parent, SWT.BORDER | SWT.TITLE | SWT.APPLICATION_MODAL | SWT.CLOSE);
this.widgetFactory = widgetFactory;
}
public ModelInputWizard<T> setDialogWidth(final int dialogWidth) {
this.dialogWidth = dialogWidth;
return this;
}
public ModelInputWizard<T> setLargeDialogWidth() {
this.dialogWidth = ModalInputDialog.LARGE_DIALOG_WIDTH;
return this;
}
public ModelInputWizard<T> setVeryLargeDialogWidth() {
this.dialogWidth = ModalInputDialog.VERY_LARGE_DIALOG_WIDTH;
return this;
}
public ModelInputWizard<T> setDialogHeight(final int dialogHeight) {
this.dialogHeight = dialogHeight;
return this;
}
public ModelInputWizard<T> setButtonWidth(final int buttonWidth) {
this.buttonWidth = buttonWidth;
return this;
}
@SafeVarargs
public final void open(
final LocTextKey title,
final Runnable cancelCallback,
final WizardPage<T>... pages) {
// Create the selection dialog window
final Shell shell = new Shell(getParent(), getStyle());
shell.setText(getText());
shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
shell.setText(this.widgetFactory.getI18nSupport().getText(title));
shell.setLayout(new GridLayout(1, true));
final GridData gridData2 = new GridData(SWT.FILL, SWT.TOP, false, false);
shell.setLayoutData(gridData2);
// the content composite
final Composite main = new Composite(shell, SWT.NONE);
main.setLayout(new GridLayout());
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.widthHint = this.dialogWidth;
main.setLayoutData(gridData);
final Composite actionComp = new Composite(shell, SWT.NONE);
actionComp.setLayout(new GridLayout());
actionComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final Composite actionsComp = new Composite(actionComp, SWT.NONE);
actionsComp.setLayout(new RowLayout(SWT.HORIZONTAL));
actionComp.setLayoutData(new GridData(SWT.TRAIL, SWT.FILL, true, true));
final List<WizardPage<T>> pageList = Utils.immutableListOf(pages);
createPage(null, pageList, null, main, actionsComp);
if (cancelCallback != null) {
final Button cancel = this.widgetFactory.buttonLocalized(actionsComp, ModalInputDialog.CANCEL_TEXT_KEY);
final RowData data = new RowData();
data.width = this.buttonWidth;
cancel.setLayoutData(data);
cancel.addListener(SWT.Selection, event -> {
if (cancelCallback != null) {
cancelCallback.run();
}
shell.close();
});
}
gridData.heightHint = calcDialogHeight(main);
finishUp(shell);
}
private void createPage(
final String pageId,
final List<WizardPage<T>> pages,
final T valueFromPrevPage,
final Composite contentComp,
final Composite actionsComp) {
final Optional<WizardPage<T>> newPage = (pageId != null)
? pages.stream()
.filter(p -> pageId.equals(p.id))
.findFirst()
: pages.stream()
.filter(page -> page.isStart)
.findFirst();
if (newPage.isEmpty()) {
return;
}
final WizardPage<T> page = newPage.get();
PageService.clearComposite(contentComp);
PageService.clearComposite(actionsComp);
final Supplier<T> valueSupplier = page.contentCompose.apply(valueFromPrevPage, contentComp);
if (page.actions != null) {
for (final WizardAction<T> action : page.actions) {
final Button actionButton = this.widgetFactory.buttonLocalized(actionsComp, action.name);
final RowData data = new RowData();
data.width = this.buttonWidth;
actionButton.setLayoutData(data);
actionButton.addListener(SWT.Selection, event -> {
if (valueSupplier != null) {
final T result = valueSupplier.get();
if (action.toPage != null) {
createPage(action.toPage, pages, result, contentComp, actionsComp);
} else {
action.callback.test(result);
this.shell.close();
}
} else {
this.shell.close();
}
});
}
}
}
private void finishUp(final Shell shell) {
shell.pack();
final Rectangle bounds = shell.getBounds();
final Rectangle bounds2 = super.getParent().getDisplay().getBounds();
bounds.x = (bounds2.width - bounds.width) / 2;
bounds.y = (bounds2.height - bounds.height) / 2;
shell.setBounds(bounds);
shell.open();
}
private int calcDialogHeight(final Composite main) {
final int actualHeight = main.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
final int displayHeight = main.getDisplay().getClientArea().height;
final int availableHeight = (displayHeight < actualHeight + 100)
? displayHeight - 100
: actualHeight;
return Math.min(availableHeight, this.dialogHeight);
}
public static final class WizardPage<T> {
public final String id;
public final boolean isStart;
public final BiFunction<T, Composite, Supplier<T>> contentCompose;
public final List<WizardAction<T>> actions;
@SafeVarargs
public WizardPage(
final String id,
final boolean isStart,
final BiFunction<T, Composite, Supplier<T>> contentCompose,
final WizardAction<T>... actions) {
this.id = id;
this.isStart = isStart;
this.contentCompose = contentCompose;
this.actions = Utils.asImmutableList(actions);
}
}
public static final class WizardAction<T> {
public final LocTextKey name;
public final String toPage;
public final Predicate<T> callback;
public WizardAction(final LocTextKey name, final String toPage) {
this.name = name;
this.toPage = toPage;
this.callback = null;
}
public WizardAction(final LocTextKey name, final Predicate<T> callback) {
this.name = name;
this.toPage = null;
this.callback = callback;
}
}
}

View file

@ -19,20 +19,20 @@ import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetExamDependencies extends RestCall<Set<EntityKey>> {
public class GetExamDependencies extends RestCall<Set<EntityDependency>> {
public GetExamDependencies() {
super(new TypeKey<>(
CallType.GET_DEPENDENCIES,
EntityType.EXAM,
new TypeReference<Set<EntityKey>>() {
new TypeReference<Set<EntityDependency>>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,

View file

@ -19,20 +19,20 @@ import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetInstitutionDependency extends RestCall<Set<EntityKey>> {
public class GetInstitutionDependency extends RestCall<Set<EntityDependency>> {
public GetInstitutionDependency() {
super(new TypeKey<>(
CallType.GET_DEPENDENCIES,
EntityType.INSTITUTION,
new TypeReference<Set<EntityKey>>() {
new TypeReference<Set<EntityDependency>>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,

View file

@ -19,20 +19,20 @@ import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetLmsSetupDependencies extends RestCall<Set<EntityKey>> {
public class GetLmsSetupDependencies extends RestCall<Set<EntityDependency>> {
public GetLmsSetupDependencies() {
super(new TypeKey<>(
CallType.GET_DEPENDENCIES,
EntityType.LMS_SETUP,
new TypeReference<Set<EntityKey>>() {
new TypeReference<Set<EntityDependency>>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,

View file

@ -19,20 +19,20 @@ import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetUserDependency extends RestCall<Set<EntityKey>> {
public class GetUserDependency extends RestCall<Set<EntityDependency>> {
public GetUserDependency() {
super(new TypeKey<>(
CallType.GET_DEPENDENCIES,
EntityType.USER,
new TypeReference<Set<EntityKey>>() {
new TypeReference<Set<EntityDependency>>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,

View file

@ -80,8 +80,8 @@ public class EntityTable<ROW extends Entity> {
final PageService pageService;
final WidgetFactory widgetFactory;
final RestCall<Page<ROW>> restCall;
final Function<RestCall<Page<ROW>>.RestCallBuilder, RestCall<Page<ROW>>.RestCallBuilder> restCallAdapter;
final PageSupplier<ROW> pageSupplier;
final Function<PageSupplier.Builder<ROW>, PageSupplier.Builder<ROW>> pageSupplierAdapter;
final I18nSupport i18nSupport;
final PageContext pageContext;
@ -109,7 +109,7 @@ public class EntityTable<ROW extends Entity> {
final int type,
final PageContext pageContext,
final RestCall<Page<ROW>> restCall,
final Function<RestCall<Page<ROW>>.RestCallBuilder, RestCall<Page<ROW>>.RestCallBuilder> restCallAdapter,
final Function<PageSupplier.Builder<ROW>, PageSupplier.Builder<ROW>> pageSupplierAdapter,
final PageService pageService,
final List<ColumnDefinition<ROW>> columns,
final int pageSize,
@ -132,8 +132,8 @@ public class EntityTable<ROW extends Entity> {
this.i18nSupport = pageService.getI18nSupport();
this.pageContext = pageContext;
this.widgetFactory = pageService.getWidgetFactory();
this.restCall = restCall;
this.restCallAdapter = (restCallAdapter != null) ? restCallAdapter : Function.identity();
this.pageSupplier = new RestCallPageSupplier<>(restCall);
this.pageSupplierAdapter = (pageSupplierAdapter != null) ? pageSupplierAdapter : Function.identity();
this.columns = Utils.immutableListOf(columns);
this.emptyMessage = emptyMessage;
this.hideNavigation = hideNavigation;
@ -233,8 +233,8 @@ public class EntityTable<ROW extends Entity> {
}
public EntityType getEntityType() {
if (this.restCall != null) {
return this.restCall.getEntityType();
if (this.pageSupplier != null) {
return this.pageSupplier.getEntityType();
}
return null;
@ -471,13 +471,13 @@ public class EntityTable<ROW extends Entity> {
this.table.removeAll();
// get page data and create rows
this.restCall.newBuilder()
this.pageSupplier.newBuilder()
.withPaging(pageNumber, pageSize)
.withSorting(sortColumn, sortOrder)
.withQueryParams((this.filter != null) ? this.filter.getFilterParameter() : null)
.withQueryParams(this.staticQueryParams)
.apply(this.restCallAdapter)
.call()
.apply(this.pageSupplierAdapter)
.getPage()
.map(this::createTableRowsFromPage)
.map(this.navigator::update)
.onError(this.pageContext::notifyUnexpectedError);

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gui.table;
import java.util.function.Function;
import org.springframework.util.MultiValueMap;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
import ch.ethz.seb.sebserver.gbl.util.Result;
public interface PageSupplier<T> {
EntityType getEntityType();
Builder<T> newBuilder();
public interface Builder<T> {
public Builder<T> withPaging(final int pageNumber, final int pageSize);
public Builder<T> withSorting(final String column, final PageSortOrder order);
public Builder<T> withQueryParams(final MultiValueMap<String, String> params);
public Builder<T> withQueryParam(String name, String value);
public Builder<T> withURIVariable(String name, String id);
public Builder<T> apply(final Function<Builder<T>, Builder<T>> f);
public Result<Page<T>> getPage();
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gui.table;
import java.util.function.Function;
import org.springframework.util.MultiValueMap;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
public class RestCallPageSupplier<T> implements PageSupplier<T> {
private final RestCall<Page<T>> restCall;
protected RestCallPageSupplier(final RestCall<Page<T>> restCall) {
this.restCall = restCall;
}
@Override
public EntityType getEntityType() {
return this.restCall.getEntityType();
}
@Override
public Builder<T> newBuilder() {
final RestCall<Page<T>>.RestCallBuilder restCallBuilder = this.restCall.newBuilder();
return new Builder<>() {
@Override
public Builder<T> withPaging(final int pageNumber, final int pageSize) {
restCallBuilder.withPaging(pageNumber, pageSize);
return this;
}
@Override
public Builder<T> withSorting(final String column, final PageSortOrder order) {
restCallBuilder.withSorting(column, order);
return this;
}
@Override
public Builder<T> withQueryParams(final MultiValueMap<String, String> params) {
restCallBuilder.withQueryParams(params);
return this;
}
@Override
public Builder<T> withQueryParam(final String name, final String value) {
restCallBuilder.withQueryParam(name, value);
return this;
}
@Override
public Builder<T> withURIVariable(final String name, final String id) {
restCallBuilder.withURIVariable(name, id);
return this;
}
@Override
public Builder<T> apply(final Function<Builder<T>, Builder<T>> f) {
return f.apply(this);
}
@Override
public Result<Page<T>> getPage() {
return restCallBuilder.call();
}
};
}
}

View file

@ -42,7 +42,7 @@ public class TableBuilder<ROW extends Entity> {
private int pageSize = -1;
private int type = SWT.NONE;
private boolean hideNavigation = false;
private Function<RestCall<Page<ROW>>.RestCallBuilder, RestCall<Page<ROW>>.RestCallBuilder> restCallAdapter;
private Function<PageSupplier.Builder<ROW>, PageSupplier.Builder<ROW>> restCallAdapter;
private BiConsumer<TableItem, ROW> rowDecorator;
private Consumer<Set<ROW>> selectionListener;
private boolean markupEnabled = false;
@ -94,7 +94,7 @@ public class TableBuilder<ROW extends Entity> {
}
public TableBuilder<ROW> withRestCallAdapter(
final Function<RestCall<Page<ROW>>.RestCallBuilder, RestCall<Page<ROW>>.RestCallBuilder> adapter) {
final Function<PageSupplier.Builder<ROW>, PageSupplier.Builder<ROW>> adapter) {
this.restCallAdapter = adapter;
return this;

View file

@ -19,6 +19,7 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
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;
@ -42,7 +43,7 @@ public interface BulkActionSupportDAO<T extends Entity> {
* @param bulkAction the BulkAction to get keys of dependencies for the concrete type of this BulkActionSupportDAO
* @return Collection of Result. Each Result refers to the EntityKey of processed entity or to an error if
* happened */
Set<EntityKey> getDependencies(BulkAction bulkAction);
Set<EntityDependency> getDependencies(BulkAction bulkAction);
/** This processed a given BulkAction for all entities of the concrete type of this BulkActionSupportDAO
* that are defined by this given BulkAction.
@ -104,16 +105,16 @@ public interface BulkActionSupportDAO<T extends Entity> {
/** Get dependency keys of all source entities of a given BulkAction
* This method simply goes through all source EntityKeys of the given BulkAction
* and applies the selection functions for each, collecting the resulting dependency EntityKeys
* and applies the selection functions for each, collecting the resulting dependency EntityDependency
* into one Set of all dependency keys for all source keys
*
*
* @param bulkAction The BulkAction that defines the source keys
* @param selectionFunction a selection functions that gives all dependency keys for a given source key
* @return Set of EntityKey instances that define all entities that depends on the given bulk action */
default Set<EntityKey> getDependencies(
* @return Set of EntityDependency instances that define all entities that depends on the given bulk action */
default Set<EntityDependency> getDependencies(
final BulkAction bulkAction,
final Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction) {
final Function<EntityKey, Result<Collection<EntityDependency>>> selectionFunction) {
return bulkAction.sources
.stream()

View file

@ -19,6 +19,7 @@ import java.util.stream.Collectors;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
import ch.ethz.seb.sebserver.gbl.util.Result;
@ -40,7 +41,7 @@ public final class BulkAction {
* Null means all dependencies are included (ignore) and empty means no dependencies are included */
public final EnumSet<EntityType> includeDependencies;
/** A Set of EntityKey containing collected depending entities during dependency collection and processing phase */
final Set<EntityKey> dependencies;
final Set<EntityDependency> dependencies;
/** A Set of EntityKey containing collected bulk action processing results during processing phase */
final Set<Result<EntityKey>> result;
/** Indicates if this BulkAction has already been processed and is not valid anymore */
@ -81,7 +82,7 @@ public final class BulkAction {
return this.includeDependencies == null || this.includeDependencies.contains(type);
}
public Set<EntityKey> getDependencies() {
public Set<EntityDependency> getDependencies() {
return Collections.unmodifiableSet(this.dependencies);
}
@ -93,7 +94,8 @@ public final class BulkAction {
if (!this.dependencies.isEmpty()) {
return Collections.unmodifiableSet(new HashSet<>(this.dependencies
.stream()
.filter(key -> key.entityType == type)
.filter(dependency -> dependency.self.entityType == type)
.map(dependency -> dependency.self)
.collect(Collectors.toList())));
}

View file

@ -29,6 +29,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport.ErrorEntry;
@ -184,13 +185,13 @@ public class BulkActionServiceImpl implements BulkActionService {
return;
}
for (final EntityKey key : action.dependencies) {
for (final EntityDependency dependency : action.dependencies) {
this.userActivityLogDAO.log(
activityType,
key.entityType,
key.modelId,
"Bulk Action - Dependency : " + toLogMessage(key));
dependency.self.entityType,
dependency.self.modelId,
"Bulk Action - Dependency : " + toLogMessage(dependency));
}
for (final EntityKey key : action.sources) {
@ -214,6 +215,18 @@ public class BulkActionServiceImpl implements BulkActionService {
return entityAsString;
}
private String toLogMessage(final EntityDependency dependency) {
String entityAsString;
try {
entityAsString = this.jsonMapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(dependency);
} catch (final JsonProcessingException e) {
entityAsString = dependency.toString();
}
return entityAsString;
}
private List<BulkActionSupportDAO<?>> getDependencySupporter(final BulkAction action) {
switch (action.type) {
case ACTIVATE:

View file

@ -26,6 +26,7 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
@ -181,7 +182,7 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
}
@Override
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
// only for deletion
if (bulkAction.type == BulkActionType.ACTIVATE || bulkAction.type == BulkActionType.DEACTIVATE) {
return Collections.emptySet();
@ -192,7 +193,7 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
}
// define the select function in case of source type
Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction;
Function<EntityKey, Result<Collection<EntityDependency>>> selectionFunction;
switch (bulkAction.sourceType) {
case INSTITUTION:
selectionFunction = this::allIdsOfInstitution;
@ -317,20 +318,24 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
});
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectByExample()
.where(
ClientConnectionRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.parseLong(institutionKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.CLIENT_CONNECTION))
.map(rec -> new EntityDependency(
institutionKey,
new EntityKey(rec.getId(), EntityType.CLIENT_CONNECTION),
rec.getExamUserSessionId(),
rec.getClientAddress()))
.collect(Collectors.toList()));
}
private Result<Collection<EntityKey>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectByExample()
.leftJoin(ExamRecordDynamicSqlSupport.examRecord)
.on(
ExamRecordDynamicSqlSupport.id,
@ -341,12 +346,16 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.CLIENT_CONNECTION))
.map(rec -> new EntityDependency(
lmsSetupKey,
new EntityKey(rec.getId(), EntityType.CLIENT_CONNECTION),
rec.getExamUserSessionId(),
rec.getClientAddress()))
.collect(Collectors.toList()));
}
private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfUser(final EntityKey userKey) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectByExample()
.leftJoin(ExamRecordDynamicSqlSupport.examRecord)
.on(
ExamRecordDynamicSqlSupport.id,
@ -357,19 +366,27 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.CLIENT_CONNECTION))
.map(rec -> new EntityDependency(
userKey,
new EntityKey(rec.getId(), EntityType.CLIENT_CONNECTION),
rec.getExamUserSessionId(),
rec.getClientAddress()))
.collect(Collectors.toList()));
}
private Result<Collection<EntityKey>> allIdsOfExam(final EntityKey examKey) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfExam(final EntityKey examKey) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper.selectByExample()
.where(
ClientConnectionRecordDynamicSqlSupport.examId,
isEqualTo(Long.parseLong(examKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.CLIENT_CONNECTION))
.map(rec -> new EntityDependency(
examKey,
new EntityKey(rec.getId(), EntityType.CLIENT_CONNECTION),
rec.getExamUserSessionId(),
rec.getClientAddress()))
.collect(Collectors.toList()));
}

View file

@ -27,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCreationInfo;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
@ -134,14 +135,14 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
@Override
@Transactional(readOnly = true)
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
// only if included
if (!bulkAction.includesDependencyType(EntityType.CONFIGURATION_NODE)) {
return Collections.emptySet();
}
// define the select function in case of source type
Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction =
Function<EntityKey, Result<Collection<EntityDependency>>> selectionFunction =
key -> Result.of(Collections.emptyList());
if (bulkAction.sourceType == EntityType.INSTITUTION) {
@ -254,27 +255,35 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
});
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.configurationNodeRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.configurationNodeRecordMapper.selectByExample()
.where(
ConfigurationNodeRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.CONFIGURATION_NODE))
.map(rec -> new EntityDependency(
institutionKey,
new EntityKey(rec.getId(), EntityType.CONFIGURATION_NODE),
rec.getName(),
rec.getDescription()))
.collect(Collectors.toList()));
}
private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) {
return Result.tryCatch(() -> this.configurationNodeRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfUser(final EntityKey userKey) {
return Result.tryCatch(() -> this.configurationNodeRecordMapper.selectByExample()
.where(
ConfigurationNodeRecordDynamicSqlSupport.owner,
isEqualTo(userKey.modelId))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.CONFIGURATION_NODE))
.map(rec -> new EntityDependency(
userKey,
new EntityKey(rec.getId(), EntityType.CONFIGURATION_NODE),
rec.getName(),
rec.getDescription()))
.collect(Collectors.toList()));
}

View file

@ -30,6 +30,7 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
@ -280,7 +281,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
@Override
@Transactional(readOnly = true)
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
// only deletion here
if (bulkAction.type == BulkActionType.ACTIVATE || bulkAction.type == BulkActionType.DEACTIVATE) {
return Collections.emptySet();
@ -291,7 +292,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
}
// define the select function in case of source type
Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction;
Function<EntityKey, Result<Collection<EntityDependency>>> selectionFunction;
switch (bulkAction.sourceType) {
case INSTITUTION:
selectionFunction = this::allIdsOfInstitution;
@ -361,6 +362,14 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
});
}
private Result<Collection<ExamConfigurationMap>> toDomainModel(
final Collection<ExamConfigurationMapRecord> records) {
return Result.tryCatch(() -> records
.stream()
.map(model -> this.toDomainModel(model).getOrThrow())
.collect(Collectors.toList()));
}
private Result<ExamConfigurationMap> toDomainModel(final ExamConfigurationMapRecord record) {
return Result.tryCatch(() -> {
@ -420,81 +429,93 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
});
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.examConfigurationMapRecordMapper.selectIdsByExample()
.where(
ExamConfigurationMapRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.EXAM_CONFIGURATION_MAP))
.collect(Collectors.toList()));
private Result<Collection<EntityDependency>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> toDependencies(
this.examConfigurationMapRecordMapper.selectByExample()
.where(
ExamConfigurationMapRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.modelId)))
.build()
.execute(),
institutionKey));
}
private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) {
private Result<Collection<EntityDependency>> allIdsOfUser(final EntityKey userKey) {
return Result.tryCatch(() -> {
final List<Long> examsIds = this.examRecordMapper.selectByExample()
final List<Long> examsIds = this.examRecordMapper.selectIdsByExample()
.where(
ExamRecordDynamicSqlSupport.owner,
isEqualTo(userKey.modelId))
.build()
.execute()
.stream()
.map(r -> r.getId())
.collect(Collectors.toList());
.execute();
return this.examConfigurationMapRecordMapper.selectIdsByExample()
.where(
ExamConfigurationMapRecordDynamicSqlSupport.examId,
isIn(examsIds))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.EXAM_CONFIGURATION_MAP))
.collect(Collectors.toList());
return toDependencies(
this.examConfigurationMapRecordMapper.selectByExample()
.where(
ExamConfigurationMapRecordDynamicSqlSupport.examId,
isIn(examsIds))
.build()
.execute(),
userKey);
});
}
private Result<Collection<EntityKey>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) {
return Result.tryCatch(() -> this.examConfigurationMapRecordMapper.selectIdsByExample()
.leftJoin(ExamRecordDynamicSqlSupport.examRecord)
.on(
ExamRecordDynamicSqlSupport.id,
equalTo(ExamConfigurationMapRecordDynamicSqlSupport.examId))
private Result<Collection<EntityDependency>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) {
return Result.tryCatch(() -> toDependencies(
this.examConfigurationMapRecordMapper.selectByExample()
.leftJoin(ExamRecordDynamicSqlSupport.examRecord)
.on(
ExamRecordDynamicSqlSupport.id,
equalTo(ExamConfigurationMapRecordDynamicSqlSupport.examId))
.where(
ExamRecordDynamicSqlSupport.lmsSetupId,
isEqualTo(Long.valueOf(lmsSetupKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.EXAM_CONFIGURATION_MAP))
.collect(Collectors.toList()));
.where(
ExamRecordDynamicSqlSupport.lmsSetupId,
isEqualTo(Long.valueOf(lmsSetupKey.modelId)))
.build()
.execute(),
lmsSetupKey));
}
private Result<Collection<EntityKey>> allIdsOfExam(final EntityKey examKey) {
return Result.tryCatch(() -> this.examConfigurationMapRecordMapper.selectIdsByExample()
.where(
ExamConfigurationMapRecordDynamicSqlSupport.examId,
isEqualTo(Long.valueOf(examKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.EXAM_CONFIGURATION_MAP))
.collect(Collectors.toList()));
private Result<Collection<EntityDependency>> allIdsOfExam(final EntityKey examKey) {
return Result.tryCatch(() -> toDependencies(
this.examConfigurationMapRecordMapper.selectByExample()
.where(
ExamConfigurationMapRecordDynamicSqlSupport.examId,
isEqualTo(Long.valueOf(examKey.modelId)))
.build()
.execute(),
examKey));
}
private Result<Collection<EntityKey>> allIdsOfConfig(final EntityKey configKey) {
return Result.tryCatch(() -> this.examConfigurationMapRecordMapper.selectIdsByExample()
.where(
ExamConfigurationMapRecordDynamicSqlSupport.configurationNodeId,
isEqualTo(Long.valueOf(configKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.EXAM_CONFIGURATION_MAP))
.collect(Collectors.toList()));
private Result<Collection<EntityDependency>> allIdsOfConfig(final EntityKey configKey) {
return Result.tryCatch(() -> toDependencies(
this.examConfigurationMapRecordMapper.selectByExample()
.where(
ExamConfigurationMapRecordDynamicSqlSupport.configurationNodeId,
isEqualTo(Long.valueOf(configKey.modelId)))
.build()
.execute(),
configKey));
}
private Collection<EntityDependency> toDependencies(
final List<ExamConfigurationMapRecord> records,
final EntityKey parent) {
return this.toDomainModel(records)
.map(models -> models
.stream()
.map(model -> getDependency(model, parent))
.collect(Collectors.toList()))
.getOrThrow();
}
private EntityDependency getDependency(final ExamConfigurationMap model, final EntityKey parent) {
return new EntityDependency(
parent,
new EntityKey(model.getId(), EntityType.EXAM_CONFIGURATION_MAP),
model.getExamName() + " / " + model.getConfigName(),
model.getExamDescription() + " / " + model.getConfigDescription());
}
private String getEncryptionPassword(final ExamConfigurationMap examConfigurationMap) {

View file

@ -32,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
@ -587,14 +588,14 @@ public class ExamDAOImpl implements ExamDAO {
@Override
@Transactional(readOnly = true)
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
// only if included
if (!bulkAction.includesDependencyType(EntityType.EXAM)) {
return Collections.emptySet();
}
// define the select function in case of source type
Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction;
Function<EntityKey, Result<Collection<EntityDependency>>> selectionFunction;
switch (bulkAction.sourceType) {
case INSTITUTION:
selectionFunction = this::allIdsOfInstitution;
@ -636,37 +637,34 @@ public class ExamDAOImpl implements ExamDAO {
.execute());
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.examRecordMapper.selectIdsByExample()
.where(ExamRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.EXAM))
.collect(Collectors.toList()));
private Result<Collection<EntityDependency>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> toDependencies(
this.examRecordMapper.selectByExample()
.where(ExamRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.modelId)))
.build()
.execute(),
institutionKey));
}
private Result<Collection<EntityKey>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) {
return Result.tryCatch(() -> this.examRecordMapper.selectIdsByExample()
.where(ExamRecordDynamicSqlSupport.lmsSetupId,
isEqualTo(Long.valueOf(lmsSetupKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.EXAM))
.collect(Collectors.toList()));
private Result<Collection<EntityDependency>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) {
return Result.tryCatch(() -> toDependencies(
this.examRecordMapper.selectByExample()
.where(ExamRecordDynamicSqlSupport.lmsSetupId,
isEqualTo(Long.valueOf(lmsSetupKey.modelId)))
.build()
.execute(),
lmsSetupKey));
}
private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) {
return Result.tryCatch(() -> this.examRecordMapper.selectIdsByExample()
.where(ExamRecordDynamicSqlSupport.owner,
isEqualTo(userKey.modelId))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.EXAM))
.collect(Collectors.toList()));
private Result<Collection<EntityDependency>> allIdsOfUser(final EntityKey userKey) {
return Result.tryCatch(() -> toDependencies(
this.examRecordMapper.selectByExample()
.where(ExamRecordDynamicSqlSupport.owner,
isEqualTo(userKey.modelId))
.build()
.execute(),
userKey));
}
private Result<ExamRecord> recordById(final Long id) {
@ -681,6 +679,26 @@ public class ExamDAOImpl implements ExamDAO {
});
}
private Collection<EntityDependency> toDependencies(
final List<ExamRecord> records,
final EntityKey parent) {
return this.toDomainModel(records)
.map(models -> models
.stream()
.map(model -> getDependency(model, parent))
.collect(Collectors.toList()))
.getOrThrow();
}
private EntityDependency getDependency(final Exam exam, final EntityKey parent) {
return new EntityDependency(
parent,
new EntityKey(exam.getId(), EntityType.EXAM),
exam.getName(),
exam.getDescription());
}
private Result<Exam> toDomainModelCached(final ExamRecord record) {
return Result.tryCatch(() -> this.lmsAPIService
.getLmsAPITemplate(record.getLmsSetupId())

View file

@ -27,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
@ -220,7 +221,7 @@ public class IndicatorDAOImpl implements IndicatorDAO {
@Override
@Transactional(readOnly = true)
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
// only for deletion
if (bulkAction.type == BulkActionType.ACTIVATE || bulkAction.type == BulkActionType.DEACTIVATE) {
return Collections.emptySet();
@ -231,7 +232,7 @@ public class IndicatorDAOImpl implements IndicatorDAO {
}
// define the select function in case of source type
Function<EntityKey, Result<Collection<EntityKey>>> selectionFunction;
Function<EntityKey, Result<Collection<EntityDependency>>> selectionFunction;
switch (bulkAction.sourceType) {
case INSTITUTION:
selectionFunction = this::allIdsOfInstitution;
@ -252,8 +253,8 @@ public class IndicatorDAOImpl implements IndicatorDAO {
return getDependencies(bulkAction, selectionFunction);
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.indicatorRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.indicatorRecordMapper.selectByExample()
.leftJoin(ExamRecordDynamicSqlSupport.examRecord)
.on(
ExamRecordDynamicSqlSupport.id,
@ -264,12 +265,16 @@ public class IndicatorDAOImpl implements IndicatorDAO {
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.INDICATOR))
.map(rec -> new EntityDependency(
institutionKey,
new EntityKey(rec.getId(), EntityType.INDICATOR),
rec.getName(),
rec.getType()))
.collect(Collectors.toList()));
}
private Result<Collection<EntityKey>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) {
return Result.tryCatch(() -> this.indicatorRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfLmsSetup(final EntityKey lmsSetupKey) {
return Result.tryCatch(() -> this.indicatorRecordMapper.selectByExample()
.leftJoin(ExamRecordDynamicSqlSupport.examRecord)
.on(
ExamRecordDynamicSqlSupport.id,
@ -280,12 +285,16 @@ public class IndicatorDAOImpl implements IndicatorDAO {
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.INDICATOR))
.map(rec -> new EntityDependency(
lmsSetupKey,
new EntityKey(rec.getId(), EntityType.INDICATOR),
rec.getName(),
rec.getType()))
.collect(Collectors.toList()));
}
private Result<Collection<EntityKey>> allIdsOfUser(final EntityKey userKey) {
return Result.tryCatch(() -> this.indicatorRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfUser(final EntityKey userKey) {
return Result.tryCatch(() -> this.indicatorRecordMapper.selectByExample()
.leftJoin(ExamRecordDynamicSqlSupport.examRecord)
.on(
ExamRecordDynamicSqlSupport.id,
@ -296,19 +305,27 @@ public class IndicatorDAOImpl implements IndicatorDAO {
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.INDICATOR))
.map(rec -> new EntityDependency(
userKey,
new EntityKey(rec.getId(), EntityType.INDICATOR),
rec.getName(),
rec.getType()))
.collect(Collectors.toList()));
}
private Result<Collection<EntityKey>> allIdsOfExam(final EntityKey examKey) {
return Result.tryCatch(() -> this.indicatorRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfExam(final EntityKey examKey) {
return Result.tryCatch(() -> this.indicatorRecordMapper.selectByExample()
.where(
IndicatorRecordDynamicSqlSupport.examId,
isEqualTo(Long.parseLong(examKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.INDICATOR))
.map(rec -> new EntityDependency(
examKey,
new EntityKey(rec.getId(), EntityType.INDICATOR),
rec.getName(),
rec.getType()))
.collect(Collectors.toList()));
}

View file

@ -29,6 +29,7 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
@ -231,7 +232,7 @@ public class InstitutionDAOImpl implements InstitutionDAO {
@Override
@Transactional(readOnly = true)
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
// NOTE since Institution is the top most Entity, there are no other Entity for that an Institution depends on.
return Collections.emptySet();
}

View file

@ -26,11 +26,12 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.client.ProxyData;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
@ -137,7 +138,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
checkUniqueName(lmsSetup);
LmsSetupRecord savedRecord = recordById(lmsSetup.id)
final LmsSetupRecord savedRecord = recordById(lmsSetup.id)
.getOrThrow();
final ClientCredentials lmsCredentials = createAPIClientCredentials(lmsSetup);
@ -250,7 +251,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
@Override
@Transactional(readOnly = true)
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
// all of institution
if (bulkAction.sourceType == EntityType.INSTITUTION) {
return getDependencies(bulkAction, this::allIdsOfInstitution);
@ -306,14 +307,18 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
});
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.lmsSetupRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.lmsSetupRecordMapper.selectByExample()
.where(LmsSetupRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.LMS_SETUP))
.map(rec -> new EntityDependency(
institutionKey,
new EntityKey(rec.getId(), EntityType.LMS_SETUP),
rec.getName(),
rec.getLmsUrl()))
.collect(Collectors.toList()));
}

View file

@ -31,10 +31,11 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig.ConfigPurpose;
@ -300,7 +301,7 @@ public class SEBClientConfigDAOImpl implements SEBClientConfigDAO {
@Override
@Transactional(readOnly = true)
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
// all of institution
if (bulkAction.sourceType == EntityType.INSTITUTION) {
return getDependencies(bulkAction, this::allIdsOfInstitution);
@ -326,14 +327,18 @@ public class SEBClientConfigDAOImpl implements SEBClientConfigDAO {
.map(SebClientConfigRecord::getEncryptSecret);
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.sebClientConfigRecordMapper.selectIdsByExample()
private Result<Collection<EntityDependency>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.sebClientConfigRecordMapper.selectByExample()
.where(SebClientConfigRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.modelId)))
.build()
.execute()
.stream()
.map(id -> new EntityKey(id, EntityType.SEB_CLIENT_CONFIGURATION))
.map(rec -> new EntityDependency(
institutionKey,
new EntityKey(rec.getId(), EntityType.SEB_CLIENT_CONFIGURATION),
rec.getName(),
StringUtils.EMPTY))
.collect(Collectors.toList()));
}

View file

@ -42,6 +42,7 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.user.UserAccount;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
@ -363,7 +364,7 @@ public class UserDAOImpl implements UserDAO {
@Override
@Transactional(readOnly = true)
public Set<EntityKey> getDependencies(final BulkAction bulkAction) {
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
// all of institution
if (bulkAction.sourceType == EntityType.INSTITUTION &&
(bulkAction.type == BulkActionType.DEACTIVATE || bulkAction.type == BulkActionType.HARD_DELETE)) {
@ -409,14 +410,18 @@ public class UserDAOImpl implements UserDAO {
}
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
private Result<Collection<EntityDependency>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> this.userRecordMapper.selectByExample()
.where(UserRecordDynamicSqlSupport.institutionId,
isEqualTo(Long.valueOf(institutionKey.modelId)))
.build()
.execute()
.stream()
.map(rec -> new EntityKey(rec.getUuid(), EntityType.USER))
.map(rec -> new EntityDependency(
institutionKey,
new EntityKey(rec.getUuid(), EntityType.USER),
rec.getName(),
rec.getSurname()))
.collect(Collectors.toList()));
}

View file

@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
@ -53,7 +53,7 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
}
@Override
public Collection<EntityKey> getDependencies(
public Collection<EntityDependency> getDependencies(
final String modelId,
final BulkActionType bulkActionType,
final List<String> includes) {

View file

@ -25,7 +25,7 @@ import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
@ -115,7 +115,7 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
}
@Override
public Collection<EntityKey> getDependencies(
public Collection<EntityDependency> getDependencies(
final String modelId,
final BulkActionType bulkActionType,
final List<String> includes) {

View file

@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
@ -111,7 +111,7 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat
}
@Override
public Collection<EntityKey> getDependencies(
public Collection<EntityDependency> getDependencies(
final String modelId,
final BulkActionType bulkActionType,
final List<String> includes) {

View file

@ -37,6 +37,7 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityName;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
@ -209,7 +210,7 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Collection<EntityKey> getDependencies(
public Collection<EntityDependency> getDependencies(
@PathVariable final String modelId,
@RequestParam(name = API.PARAM_BULK_ACTION_TYPE, required = true) final BulkActionType bulkActionType,
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) {

View file

@ -255,6 +255,16 @@ sebserver.useraccount.form.password.new.tooltip=The new password for the user ac
sebserver.useraccount.form.password.new.confirm=Confirm New Password
sebserver.useraccount.form.password.new.confirm.tooltip=Please confirm the password
sebserver.useraccount.delete.form.title=Delete User Account
sebserver.useraccount.delete.form.info=Delete this User Account with all dependencies.
sebserver.useraccount.delete.form.accountName=Name
sebserver.useraccount.delete.form.deleteAlsoConfigs=Include all Exam Configurations
sebserver.useraccount.delete.form.deleteAlsoConfigs.tooltip=This includes all Exam Configuration which this uses has created and is owner of
sebserver.useraccount.delete.form.deleteAlsoExams=Include all Exams
sebserver.useraccount.delete.form.deleteAlsoExams.tooltip=This includes all Exams which the user has imported and is owner of.<br/>This also includes all Client Connections and all SEB Client Logs that where created within an Exam that is part of this deletion.
sebserver.useraccount.delete.form.action.delete=Delete
sebserver.useraccount.delete.form.action.report=Show Report
################################
# LMS Setup
################################

View file

@ -49,6 +49,7 @@ import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.Domain.SEB_CLIENT_CONFIGURATION;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityName;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
@ -2216,7 +2217,7 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
.findFirst()
.get();
List<EntityKey> dependencies = restService.getBuilder(GetUserDependency.class)
List<EntityDependency> dependencies = restService.getBuilder(GetUserDependency.class)
.withURIVariable(API.PARAM_MODEL_ID, user.getModelId())
.withQueryParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.HARD_DELETE.name())
.call()
@ -2238,27 +2239,27 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
+ "EXAM_CONFIGURATION_MAP, "
+ "INDICATOR, "
+ "INDICATOR]",
dependencies.stream().map(EntityKey::getEntityType).collect(Collectors.toList()).toString());
dependencies.stream().map(dep -> dep.self.entityType).collect(Collectors.toList()).toString());
// check that the user is owner of all depending exams and configurations
dependencies.stream()
.filter(key -> key.entityType == EntityType.EXAM)
.filter(key -> key.self.entityType == EntityType.EXAM)
.forEach(key -> {
assertEquals(
user.modelId,
restService.getBuilder(GetExam.class)
.withURIVariable(API.PARAM_MODEL_ID, key.getModelId())
.withURIVariable(API.PARAM_MODEL_ID, key.self.getModelId())
.call()
.getOrThrow().owner);
});
dependencies.stream()
.filter(key -> key.entityType == EntityType.CONFIGURATION_NODE)
.filter(key -> key.self.entityType == EntityType.CONFIGURATION_NODE)
.forEach(key -> {
assertEquals(
user.modelId,
restService.getBuilder(GetExamConfigNode.class)
.withURIVariable(API.PARAM_MODEL_ID, key.getModelId())
.withURIVariable(API.PARAM_MODEL_ID, key.self.getModelId())
.call()
.getOrThrow().owner);
});
@ -2283,7 +2284,7 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
+ "EXAM_CONFIGURATION_MAP, "
+ "INDICATOR, "
+ "INDICATOR]",
dependencies.stream().map(EntityKey::getEntityType).collect(Collectors.toList()).toString());
dependencies.stream().map(dep -> dep.self.entityType).collect(Collectors.toList()).toString());
// only with configuration dependencies
dependencies = restService.getBuilder(GetUserDependency.class)
@ -2301,7 +2302,7 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
+ "CONFIGURATION_NODE, "
+ "CONFIGURATION_NODE, "
+ "CONFIGURATION_NODE]",
dependencies.stream().map(EntityKey::getEntityType).collect(Collectors.toList()).toString());
dependencies.stream().map(dep -> dep.self.entityType).collect(Collectors.toList()).toString());
// only with exam and configuration dependencies
dependencies = restService.getBuilder(GetUserDependency.class)
@ -2328,7 +2329,7 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
+ "EXAM_CONFIGURATION_MAP, "
+ "INDICATOR, "
+ "INDICATOR]",
dependencies.stream().map(EntityKey::getEntityType).collect(Collectors.toList()).toString());
dependencies.stream().map(dep -> dep.self.entityType).collect(Collectors.toList()).toString());
}
@Test

View file

@ -14,6 +14,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import org.springframework.http.HttpMethod;
@ -27,6 +28,7 @@ import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityName;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
@ -404,21 +406,23 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
@Test
public void testDependency() throws Exception {
final Collection<EntityKey> dependencies = new RestAPITestHelper()
final Collection<EntityDependency> dependencies = new RestAPITestHelper()
.withAccessToken(getSebAdminAccess())
.withPath(API.INSTITUTION_ENDPOINT)
.withPath("1")
.withPath(API.DEPENDENCY_PATH_SEGMENT)
.withAttribute(API.PARAM_BULK_ACTION_TYPE, BulkActionType.DEACTIVATE.name())
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<Collection<EntityKey>>() {
.getAsObject(new TypeReference<Collection<EntityDependency>>() {
});
final List<EntityKey> depKeys = dependencies.stream().map(dep -> dep.self).collect(Collectors.toList());
assertNotNull(dependencies);
assertTrue(dependencies.size() == 3);
assertTrue(dependencies.contains(new EntityKey("user1", EntityType.USER)));
assertTrue(dependencies.contains(new EntityKey("user2", EntityType.USER)));
assertTrue(dependencies.contains(new EntityKey("user5", EntityType.USER)));
assertTrue(depKeys.contains(new EntityKey("user1", EntityType.USER)));
assertTrue(depKeys.contains(new EntityKey("user2", EntityType.USER)));
assertTrue(depKeys.contains(new EntityKey("user5", EntityType.USER)));
}
static void assertContainsInstitution(final String name, final Collection<Institution> institutions) {