diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/POSTMapper.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/POSTMapper.java index d02b7900..3fccdbab 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/POSTMapper.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/POSTMapper.java @@ -232,11 +232,15 @@ public class POSTMapper { return Collections.emptyList(); } - return thresholdStrings.stream() + return thresholdStrings + .stream() .map(ts -> { try { final String[] split = StringUtils.split(ts, Constants.EMBEDDED_LIST_SEPARATOR); - return new Threshold(Double.parseDouble(split[0]), split[1], null); + return new Threshold(Double.parseDouble( + split[0]), + (split.length > 1) ? split[1] : null, + (split.length > 2) ? split[2] : null); } catch (final Exception e) { return null; } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateForm.java index 4d9e8b4b..bfb41a6a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateForm.java @@ -61,6 +61,8 @@ public class ExamTemplateForm implements TemplateComposer { new LocTextKey("sebserver.examtemplate.form.name"); private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY = new LocTextKey("sebserver.examtemplate.form.description"); + private static final LocTextKey FORM_DEFAULT_TEXT_KEY = + new LocTextKey("sebserver.examtemplate.form.default"); private static final LocTextKey FORM_TYPE_TEXT_KEY = new LocTextKey("sebserver.examtemplate.form.examType"); private static final LocTextKey FORM_CONFIG_TEMPLATE_TEXT_KEY = @@ -149,6 +151,11 @@ public class ExamTemplateForm implements TemplateComposer { examTemplate.description) .asArea()) + .addField(FormBuilder.checkbox( + Domain.EXAM_TEMPLATE.ATTR_INSTITUTIONAL_DEFAULT, + FORM_DEFAULT_TEXT_KEY, + String.valueOf(examTemplate.getInstitutionalDefault()))) + .addField(FormBuilder.singleSelection( Domain.EXAM_TEMPLATE.ATTR_EXAM_TYPE, FORM_TYPE_TEXT_KEY, @@ -159,11 +166,10 @@ public class ExamTemplateForm implements TemplateComposer { .addFieldIf( () -> !examConfigTemplateResources.isEmpty(), () -> FormBuilder.singleSelection( - Domain.CONFIGURATION_NODE.ATTR_TEMPLATE_ID, + Domain.EXAM_TEMPLATE.ATTR_CONFIGURATION_TEMPLATE_ID, FORM_CONFIG_TEMPLATE_TEXT_KEY, String.valueOf(examTemplate.configTemplateId), - this.resourceService::getExamConfigTemplateResources) - .readonly(!isNew)) + this.resourceService::getExamConfigTemplateResources)) .addField(FormBuilder.multiComboSelection( Domain.EXAM_TEMPLATE.ATTR_SUPPORTER, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateList.java index 255f281b..760526b2 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateList.java @@ -24,6 +24,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; import ch.ethz.seb.sebserver.gui.service.ResourceService; +import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageService; @@ -53,9 +54,16 @@ public class ExamTemplateList implements TemplateComposer { new LocTextKey("sebserver.examtemplate.list.column.name"); public final static LocTextKey COLUMN_TITLE_EXAM_TYPE_KEY = new LocTextKey("sebserver.examtemplate.list.column.examType"); + public final static LocTextKey COLUMN_TITLE_DEFAULT_KEY = + new LocTextKey("sebserver.examtemplate.list.column.default"); public final static LocTextKey EMPTY_LIST_TEXT_KEY = new LocTextKey("sebserver.examtemplate.list.empty"); + public final static LocTextKey COLUMN_TITLE_DEFAULT_TRUE_KEY = + new LocTextKey("sebserver.examtemplate.list.column.default.true"); + public final static LocTextKey COLUMN_TITLE_DEFAULT_FALSE_KEY = + new LocTextKey("sebserver.examtemplate.list.column.default.false"); + public static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUTION = new LocTextKey("sebserver.examtemplate.list.action.no.modify.privilege"); public final static LocTextKey EMPTY_SELECTION_TEXT_KEY = @@ -94,6 +102,7 @@ public class ExamTemplateList implements TemplateComposer { final WidgetFactory widgetFactory = this.pageService.getWidgetFactory(); final CurrentUser currentUser = this.resourceService.getCurrentUser(); final RestService restService = this.resourceService.getRestService(); + final I18nSupport i18nSupport = this.pageService.getI18nSupport(); // content page layout with title final Composite content = widgetFactory.defaultPageLayout( @@ -142,6 +151,13 @@ public class ExamTemplateList implements TemplateComposer { .withFilter(this.typeFilter) .sortable()) + .withColumn(new ColumnDefinition( + Domain.EXAM_TEMPLATE.ATTR_INSTITUTIONAL_DEFAULT, + COLUMN_TITLE_DEFAULT_KEY, + et -> (et.institutionalDefault) + ? i18nSupport.getText(COLUMN_TITLE_DEFAULT_TRUE_KEY) + : i18nSupport.getText(COLUMN_TITLE_DEFAULT_FALSE_KEY))) + .withDefaultAction(actionBuilder .newAction(ActionDefinition.EXAM_TEMPLATE_VIEW_FROM_LIST) .create()) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorTemplateForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorTemplateForm.java index cc5bffb2..70e8aed4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorTemplateForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorTemplateForm.java @@ -135,7 +135,7 @@ public class IndicatorTemplateForm implements TemplateComposer { Domain.EXAM.ATTR_INSTITUTION_ID, String.valueOf(examTemplate.getInstitutionId())) .putStaticValue( - Domain.INDICATOR.ATTR_EXAM_ID, + IndicatorTemplate.ATTR_EXAM_TEMPLATE_ID, parentEntityKey.getModelId()) .addField(FormBuilder.text( Domain.EXAM_TEMPLATE.ATTR_NAME, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java index c8ed002a..0dea660c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java @@ -768,7 +768,6 @@ public class WidgetFactory { final Image image = type.getImage(parent.getDisplay()); imageButton.setImage(image); if (listener != null) { - imageButton.addListener(SWT.MouseDown, listener); imageButton.addListener(SWT.Selection, listener); } setARIARole(imageButton, AriaRole.button); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java index fbcd0840..30feb53f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java @@ -12,6 +12,7 @@ import java.util.Collection; import org.springframework.cache.annotation.CacheEvict; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.GrantEntity; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; @@ -145,4 +146,11 @@ public interface ExamDAO extends ActivatableEntityDAO, BulkActionSup * @return Result refer to the updated Exam or to an error if happened */ Result setSEBRestriction(Long examId, boolean sebRestriction); + /** This deletes the exam template reference of all exams that has a given + * template reference. + * + * @param examTemplateId The exam template reference identifier + * @return Result refer to the collection of entity keys of all involved exams or to an error when happened */ + Result> deleteTemplateReferences(Long examTemplateId); + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java index 614caf27..e4df65d9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java @@ -721,6 +721,53 @@ public class ExamDAOImpl implements ExamDAO { .execute()); } + @Override + @Transactional + public Result> deleteTemplateReferences(final Long examTemplateId) { + return Result.tryCatch(() -> { + + final List records = this.examRecordMapper.selectByExample() + .where( + ExamRecordDynamicSqlSupport.examTemplateId, + isEqualTo(examTemplateId)) + .build() + .execute(); + + if (records == null || records.isEmpty()) { + return Collections.emptyList(); + } + + final ArrayList result = new ArrayList<>(); + for (final ExamRecord rec : records) { + + try { + this.examRecordMapper.updateByPrimaryKey(new ExamRecord( + rec.getId(), + rec.getInstitutionId(), + rec.getLmsSetupId(), + rec.getExternalId(), + rec.getOwner(), + rec.getSupporter(), + rec.getType(), + rec.getQuitPassword(), + rec.getBrowserKeys(), + rec.getStatus(), + rec.getLmsSebRestriction(), + rec.getUpdating(), + rec.getLastupdate(), + rec.getActive(), + null)); + + result.add(new EntityKey(rec.getId(), EntityType.EXAM)); + } catch (final Exception e) { + log.error("Failed to delete template references for exam: {}", rec, e); + } + } + + return result; + }); + } + private Result> allIdsOfInstitution(final EntityKey institutionKey) { return Result.tryCatch(() -> toDependencies( this.examRecordMapper.selectByExample() diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamTemplateDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamTemplateDAOImpl.java index cdde3fc1..4f78548c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamTemplateDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamTemplateDAOImpl.java @@ -44,6 +44,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.IndicatorRecordDy import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ExamTemplateRecord; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.AdditionalAttributesDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamTemplateDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException; @@ -56,15 +57,18 @@ public class ExamTemplateDAOImpl implements ExamTemplateDAO { private final ExamTemplateRecordMapper examTemplateRecordMapper; private final AdditionalAttributesDAO additionalAttributesDAO; + private final ExamDAO examDAO; private final JSONMapper jsonMapper; public ExamTemplateDAOImpl( final ExamTemplateRecordMapper examTemplateRecordMapper, final AdditionalAttributesDAO additionalAttributesDAO, + final ExamDAO examDAO, final JSONMapper jsonMapper) { this.examTemplateRecordMapper = examTemplateRecordMapper; this.additionalAttributesDAO = additionalAttributesDAO; + this.examDAO = examDAO; this.jsonMapper = jsonMapper; } @@ -195,8 +199,8 @@ public class ExamTemplateDAOImpl implements ExamTemplateDAO { : null; final ExamTemplateRecord newRecord = new ExamTemplateRecord( + data.id, null, - data.institutionId, data.configTemplateId, data.name, data.description, @@ -233,8 +237,21 @@ public class ExamTemplateDAOImpl implements ExamTemplateDAO { public Result> delete(final Set all) { return Result.tryCatch(() -> { + log.info("Delete exam templates: {}", all); + final List ids = extractListOfPKs(all); + ids.stream() + .forEach(id -> { + final Collection deletedReferences = this.examDAO + .deleteTemplateReferences(id) + .getOrThrow(); + + if (deletedReferences != null && !deletedReferences.isEmpty()) { + log.info("Deleted template references for exams: {}", deletedReferences); + } + }); + this.examTemplateRecordMapper.deleteByExample() .where(ExamTemplateRecordDynamicSqlSupport.id, isIn(ids)) .build() diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamTemplateController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamTemplateController.java index c12e6f82..07d2d35a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamTemplateController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamTemplateController.java @@ -174,6 +174,9 @@ public class ExamTemplateController extends EntityController indicators = new ArrayList<>(examTemplate.indicatorTemplates); indicators.add(newIndicator); final ExamTemplate newExamTemplate = new ExamTemplate( diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 9a85a6a8..5a02c853 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1614,7 +1614,10 @@ sebserver.examtemplate.list.column.name=Name sebserver.examtemplate.list.column.name.tooltip=The name of the exam template

Use the filter above to narrow down to a specific name
{0} sebserver.examtemplate.list.column.examType=Exam Type sebserver.examtemplate.list.column.examType.tooltip=The exam type defined by the exam template

Use the filter above to select a specific exam type
{0} - +sebserver.examtemplate.list.column.default=Default Template +sebserver.examtemplate.list.column.default.tooltip=Indicates the current default exam template for the institution
{0} +sebserver.examtemplate.list.column.default.true=Yes +sebserver.examtemplate.list.column.default.flase=No sebserver.examtemplate.info.pleaseSelect=At first please select an Exam Template from the list @@ -1624,6 +1627,8 @@ sebserver.examtemplate.form.name=Name sebserver.examtemplate.form.name.tooltip=The name of the exam template sebserver.examtemplate.form.description=Description sebserver.examtemplate.form.description.tooltip=The description of the exam template +sebserver.examtemplate.form.default=Institutional Default +sebserver.examtemplate.form.default.tooltip=Set this to mark this as the default exam template for the institution.
Only one exam template at the time can be marked as default. Please be aware that an existing default exam template will be reset if this is set as default. sebserver.examtemplate.form.examType=Exam Type sebserver.examtemplate.form.examType.tooltip=The exam type group identifier for if the exam template sebserver.examtemplate.form.examConfigTemplate=Configuration Template @@ -1635,7 +1640,7 @@ sebserver.examtemplate.form.action.save=Save sebserver.examtemplate.form.action.edit=Edit Template Settings sebserver.examtemplate.indicator.list.actions= -sebserver.examtemplate.indicator.list.title=Indicators +sebserver.examtemplate.indicator.list.title=Indicator Templates sebserver.examtemplate.indicator.list.title.tooltip=A list of indicators that will automatically be created when importing a exam with this template sebserver.examtemplate.indicator.list.column.type=Type sebserver.examtemplate.indicator.list.column.type.tooltip=The type of indicator @@ -1646,10 +1651,11 @@ sebserver.examtemplate.indicator.list.column.thresholds.tooltip=The thresholds o sebserver.examtemplate.indicator.list.empty=There is currently no indicator defined for this exam template. Please create a new one sebserver.examtemplate.indicator.list.pleaseSelect=At first please select an indicator from the list +sebserver.examtemplate.indicator.action.save=Save Indicator Template sebserver.examtemplate.indicator.list.actions= -sebserver.examtemplate.indicator.action.list.new=New Indicator -sebserver.examtemplate.indicator.action.list.modify=Edit Indicator -sebserver.examtemplate.indicator.action.list.delete=Delete Indicator +sebserver.examtemplate.indicator.action.list.new=Add Indicator Template +sebserver.examtemplate.indicator.action.list.modify=Edit Indicator Template +sebserver.examtemplate.indicator.action.list.delete=Delete Indicator Template diff --git a/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java b/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java index 3060e82a..7f5f7cba 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java @@ -38,6 +38,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.core.io.ClassPathResource; import org.springframework.test.context.jdbc.Sql; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.util.StreamUtils; import ch.ethz.seb.sebserver.gbl.Constants; @@ -59,9 +61,11 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType; import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap; +import ch.ethz.seb.sebserver.gbl.model.exam.ExamTemplate; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold; +import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; @@ -105,13 +109,22 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfi import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingsPage; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamNames; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamPage; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamTemplate; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamTemplatePage; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamTemplates; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicator; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicatorPage; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicatorTemplate; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicatorTemplatePage; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.NewExamConfigMapping; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.NewExamTemplate; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.NewIndicator; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.NewIndicatorTemplate; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExam; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExamConfigMapping; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExamTemplate; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveIndicator; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveIndicatorTemplate; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.ActivateInstitution; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionNames; @@ -2567,4 +2580,117 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { // TODO how to mockup an Open edX response } + @Test + @Order(22) + // ************************************* + // Use Case 22: Login as TestInstAdmin and create new Exam Template + // - login as TestInstAdmin : 987654321 + // - check exam template list is empty + // - create new exam template with existing configuration template + // - check exam template list contains created exam template + // - add indicator templates to the exam template + public void testUsecase22_CreateExamTemplate() { + final RestServiceImpl restService = createRestServiceForUser( + "TestInstAdmin", + "987654321", + new GetExamTemplatePage(), + new GetExamTemplate(), + new GetExamTemplates(), + new NewExamTemplate(), + new NewExamConfig(), + new SaveExamTemplate(), + new GetIndicatorTemplatePage(), + new NewIndicatorTemplate(), + new SaveIndicatorTemplate(), + new GetIndicatorTemplate()); + + Page examTemplatePage = restService + .getBuilder(GetExamTemplatePage.class) + .call() + .getOrThrow(); + + assertTrue(examTemplatePage.isEmpty()); + + // create new exam config template + final ConfigurationNode configTemplate = restService + .getBuilder(NewExamConfig.class) + .withFormParam(Domain.CONFIGURATION_NODE.ATTR_NAME, "templateTest") + .withFormParam(Domain.CONFIGURATION_NODE.ATTR_TYPE, ConfigurationType.TEMPLATE.name()) + .call() + .getOrThrow(); + + assertNotNull(configTemplate); + assertEquals("templateTest", configTemplate.name); + + // create exam template with config template reference + final ExamTemplate examTemplate = restService + .getBuilder(NewExamTemplate.class) + .withFormParam(Domain.EXAM_TEMPLATE.ATTR_NAME, "examTemplate") + .withFormParam(Domain.EXAM_TEMPLATE.ATTR_CONFIGURATION_TEMPLATE_ID, configTemplate.getModelId()) + .withFormParam(Domain.EXAM_TEMPLATE.ATTR_INSTITUTIONAL_DEFAULT, "true") + .withFormParam(Domain.EXAM_TEMPLATE.ATTR_EXAM_TYPE, ExamType.MANAGED.name()) + .call() + .getOrThrow(); + + assertNotNull(examTemplate); + assertEquals("examTemplate", examTemplate.name); + assertTrue(examTemplate.institutionalDefault); + assertEquals(configTemplate.institutionId, examTemplate.institutionId); + assertEquals(configTemplate.id, examTemplate.configTemplateId); + + // get list again and check entry + examTemplatePage = restService + .getBuilder(GetExamTemplatePage.class) + .call() + .getOrThrow(); + + assertFalse(examTemplatePage.isEmpty()); + final ExamTemplate templateFromList = examTemplatePage.getContent().iterator().next(); + assertNotNull(templateFromList); + assertEquals("examTemplate", templateFromList.name); + assertTrue(templateFromList.institutionalDefault); + assertEquals(configTemplate.institutionId, templateFromList.institutionId); + assertEquals(configTemplate.id, templateFromList.configTemplateId); + + // create new indicator template + final MultiValueMap thresholds = new LinkedMultiValueMap<>(); + thresholds.add(Domain.THRESHOLD.REFERENCE_NAME, "1|000001"); + thresholds.add(Domain.THRESHOLD.REFERENCE_NAME, "2|000002"); + thresholds.add(Domain.THRESHOLD.REFERENCE_NAME, "3|000003"); + final IndicatorTemplate indicatorTemplate = restService + .getBuilder(NewIndicatorTemplate.class) + .withFormParam(IndicatorTemplate.ATTR_EXAM_TEMPLATE_ID, examTemplate.getModelId()) + .withFormParam(Domain.INDICATOR.ATTR_NAME, "Errors") + .withFormParam(Domain.INDICATOR.ATTR_TYPE, IndicatorType.ERROR_COUNT.name) + .withFormParam(Domain.INDICATOR.ATTR_COLOR, "000001") + .withFormParams(thresholds) + .call() + .getOrThrow(); + + assertNotNull(indicatorTemplate); + assertEquals(examTemplate.id, indicatorTemplate.examTemplateId); + assertEquals("Errors", indicatorTemplate.name); + assertTrue(indicatorTemplate.thresholds.size() == 3); + + // get indicator list for template + final Page indicatorList = restService + .getBuilder(GetIndicatorTemplatePage.class) + .withURIVariable(API.PARAM_PARENT_MODEL_ID, examTemplate.getModelId()) + .call() + .getOrThrow(); + + assertNotNull(indicatorList); + assertFalse(indicatorList.isEmpty()); + assertTrue(indicatorList.content.size() == 1); + + // TODO save exam template + + // TODO edit indicator template + + // TODO remove indicator template + + // TODO delete exam template + + } + }