diff --git a/Kitodo-DataEditor/src/test/resources/ruleset.xsd b/Kitodo-DataEditor/src/test/resources/ruleset.xsd index 31a60d2d99c..4c6048ed387 100644 --- a/Kitodo-DataEditor/src/test/resources/ruleset.xsd +++ b/Kitodo-DataEditor/src/test/resources/ruleset.xsd @@ -354,7 +354,8 @@ This can be used if a certain metadata entry must not be changed at a certain point in time. (If no changes are to be made to the metadata in its whole, this should be mapped via the authorization management, not via the ruleset.) With "excluded", a metadata entry can be hidden. It is not deleted, - it is simply not displayed. With "multiline", a larger input box can be requested for a metadata key. + it is simply not displayed. With "filterable" an input field is rendered for checkbox lists to filter + the list of available values. With "multiline", a larger input box can be requested for a metadata key. This makes sense for entries that contain a lot of text, for example an abstract. Settings must be nested in order to define properties of subkeys. diff --git a/Kitodo/rulesets/ruleset.xsd b/Kitodo/rulesets/ruleset.xsd index 31a60d2d99c..4c6048ed387 100644 --- a/Kitodo/rulesets/ruleset.xsd +++ b/Kitodo/rulesets/ruleset.xsd @@ -354,7 +354,8 @@ This can be used if a certain metadata entry must not be changed at a certain point in time. (If no changes are to be made to the metadata in its whole, this should be mapped via the authorization management, not via the ruleset.) With "excluded", a metadata entry can be hidden. It is not deleted, - it is simply not displayed. With "multiline", a larger input box can be requested for a metadata key. + it is simply not displayed. With "filterable" an input field is rendered for checkbox lists to filter + the list of available values. With "multiline", a larger input box can be requested for a metadata key. This makes sense for entries that contain a lot of text, for example an abstract. Settings must be nested in order to define properties of subkeys. diff --git a/Kitodo/src/main/java/org/kitodo/production/forms/WorkflowForm.java b/Kitodo/src/main/java/org/kitodo/production/forms/WorkflowForm.java index 3fdb5ea6c6f..28c98619e9d 100644 --- a/Kitodo/src/main/java/org/kitodo/production/forms/WorkflowForm.java +++ b/Kitodo/src/main/java/org/kitodo/production/forms/WorkflowForm.java @@ -90,7 +90,7 @@ public WorkflowForm() { /** * Get list of workflow statues for select list. * - * @return list of SelectItem objects + * @return array of SelectItem objects */ public WorkflowStatus[] getWorkflowStatuses() { return WorkflowStatus.values(); @@ -160,7 +160,10 @@ public String saveAndRedirect() { } else { return this.stayOnCurrentPage; } - } catch (IOException | DAOException | DataException e) { + } catch (DataException e) { + Helper.setErrorMessage(e.getLocalizedMessage(), logger, e); + return this.stayOnCurrentPage; + } catch (IOException | DAOException e) { Helper.setErrorMessage("errorDiagramFile", new Object[] {this.workflow.getTitle() }, logger, e); return this.stayOnCurrentPage; } catch (WorkflowException e) { @@ -226,7 +229,11 @@ public String cancel() { */ public void archive() { this.workflow.setStatus(WorkflowStatus.ARCHIVED); - saveWorkflow(); + try { + saveWorkflow(); + } catch (DataException e) { + Helper.setErrorMessage(e.getLocalizedMessage(), logger, e); + } } /** @@ -326,12 +333,8 @@ private String encodeXMLDiagramName(String xmlDiagramName) { return xmlDiagramName; } - private void saveWorkflow() { - try { - ServiceManager.getWorkflowService().save(this.workflow, true); - } catch (DataException e) { - Helper.setErrorMessage(e.getLocalizedMessage(), logger, e); - } + private void saveWorkflow() throws DataException { + ServiceManager.getWorkflowService().saveWorkflow(this.workflow); } /** @@ -535,7 +538,7 @@ public void setMigration(boolean migration) { /** * Get language. * - * @return language of the currently logged in user + * @return language of the currently logged-in user */ public String getLanguage() { return ServiceManager.getUserService().getCurrentUser().getLanguage(); diff --git a/Kitodo/src/main/java/org/kitodo/production/services/data/WorkflowService.java b/Kitodo/src/main/java/org/kitodo/production/services/data/WorkflowService.java index 9be28308c35..dde4bf7156f 100644 --- a/Kitodo/src/main/java/org/kitodo/production/services/data/WorkflowService.java +++ b/Kitodo/src/main/java/org/kitodo/production/services/data/WorkflowService.java @@ -147,4 +147,28 @@ public List getAvailableWorkflows() { public List getAllActiveWorkflows() { return dao.getAllActive(); } + + private List getByTitle(String title) { + return dao.getByQuery("FROM Workflow WHERE title = :title", Collections.singletonMap("title", title)); + } + + /** + * Save given workflow if it is an existing workflow (e.g. if it does have an ID) + * or if it is a new workflow and no workflow with the same name exists. + * + * @param workflow the object to save + * + * @throws DataException if the given workflow is a new workflow and a workflow with the same name already exists + */ + public void saveWorkflow(Workflow workflow) throws DataException { + if (Objects.nonNull(workflow.getId())) { + save(workflow, true); + } else { + if (getByTitle(workflow.getTitle()).isEmpty()) { + save(workflow, true); + } else { + throw new DataException(Helper.getTranslation("duplicateWorkflowTitle", workflow.getTitle())); + } + } + } } diff --git a/Kitodo/src/main/resources/messages/errors_de.properties b/Kitodo/src/main/resources/messages/errors_de.properties index dcd4eaed90e..0cf35795532 100644 --- a/Kitodo/src/main/resources/messages/errors_de.properties +++ b/Kitodo/src/main/resources/messages/errors_de.properties @@ -45,6 +45,7 @@ docketNotFound=Die angegebene Datei konnte nicht gefunden werden. docketTitleDuplicated=Der Laufzettel mit den gleichen Titel existiert schon. docTypeNotFound=docType ''{0}'' wurde nicht im selektierten Regelsatz gefunden duplicatedTitles=Es wurden dublette Ausgabe-Bezeichnungen gefunden. Dies erzeugt gegebenenfalls dublette Vorgangstitel! +duplicateWorkflowTitle=Ein Workflow mit dem Titel "{0}" existiert bereits. emptySourceFolder=Der Quellordner zur Bildgenerierung ist leer errorDataIncomplete=Unvollst\u00E4ndige Daten\: errorDatabaseReading=Fehler beim Datenbanklesen von ''{0}'' with ID {1}. diff --git a/Kitodo/src/main/resources/messages/errors_en.properties b/Kitodo/src/main/resources/messages/errors_en.properties index d6cce6df241..3721e7af141 100644 --- a/Kitodo/src/main/resources/messages/errors_en.properties +++ b/Kitodo/src/main/resources/messages/errors_en.properties @@ -46,6 +46,7 @@ docketNotFound=The specified file could not be found. docketTitleDuplicated=The docket with the same title exists already. docTypeNotFound=docType ''{0}'' could not be found in selected ruleset duplicatedTitles=Duplicate issue designations were found. This may produce duplicate process titles! +duplicateWorkflowTitle=Workflow with title "{0}" already exists. emptySourceFolder=The source folder is empty errorDataIncomplete=Incomplete data\: errorDatabaseReading=Error on reading database for ''{0}'' with ID {1}. diff --git a/Kitodo/src/test/java/org/kitodo/production/services/data/WorkflowServiceIT.java b/Kitodo/src/test/java/org/kitodo/production/services/data/WorkflowServiceIT.java index 8cf1ff933e8..9e16eb8a672 100644 --- a/Kitodo/src/test/java/org/kitodo/production/services/data/WorkflowServiceIT.java +++ b/Kitodo/src/test/java/org/kitodo/production/services/data/WorkflowServiceIT.java @@ -12,6 +12,7 @@ package org.kitodo.production.services.data; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; @@ -22,11 +23,13 @@ import org.kitodo.MockDatabase; import org.kitodo.SecurityTestUtils; import org.kitodo.data.database.beans.Workflow; +import org.kitodo.data.exceptions.DataException; +import org.kitodo.production.helper.Helper; import org.kitodo.production.services.ServiceManager; public class WorkflowServiceIT { - private WorkflowService workflowService = ServiceManager.getWorkflowService(); + private final WorkflowService workflowService = ServiceManager.getWorkflowService(); @BeforeAll public static void prepareDatabase() throws Exception { @@ -62,4 +65,14 @@ public void shouldGetAvailableWorkflows() throws Exception { SecurityTestUtils.cleanSecurityContext(); } + + @Test + public void shouldNotSaveNewWorkflowWithExistingTitle() { + Workflow workflow = new Workflow("test"); + String expectedExceptionMessage = Helper.getTranslation("duplicateWorkflowTitle", "test"); + DataException dataException = assertThrows(DataException.class, + () -> workflowService.saveWorkflow(workflow), + "Expected DataException to be thrown when saving a new workflow with an existing title"); + assertEquals(expectedExceptionMessage, dataException.getMessage()); + } }