diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationLevelValidation.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationLevelValidation.java index 31abbda3f1..aa1c8e4253 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationLevelValidation.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationLevelValidation.java @@ -19,6 +19,7 @@ package org.alfresco.module.org_alfresco_module_rm.classification; import static java.util.Arrays.asList; +import static org.alfresco.module.org_alfresco_module_rm.util.RMCollectionUtils.getDuplicateElements; import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.IllegalAbbreviationChars; import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.IllegalConfiguration; @@ -60,6 +61,10 @@ public class ClassificationLevelValidation { throw new MissingConfiguration("Classification level ID is missing."); } + else if (levelId.equals(ClassificationLevelManager.UNCLASSIFIED_ID)) + { + throw new IllegalConfiguration("Unclassified ID abbreviation is reserved for system use."); + } else if (levelId.length() > ABBREVIATION_LENGTH_LIMIT) { throw new IllegalConfiguration("Illegal classification level abbreviation. Length " + @@ -86,6 +91,12 @@ public class ClassificationLevelValidation throw new MissingConfiguration("Classification level configuration is missing."); } + final List duplicateLevels = getDuplicateElements(levels); + if (!duplicateLevels.isEmpty()) + { + throw new IllegalConfiguration("Duplicate ID abbreviations are not allowed: " + duplicateLevels); + } + for (ClassificationLevel level : levels) { validateLevel(level); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtils.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtils.java new file mode 100644 index 0000000000..69d7dc08ae --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtils.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.util; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Various common helper methods for Collections. + * + * @author Neil Mc Erlean + * @since 3.0 + */ +// This class should all be moved to core Alfresco whenever possible and reused from there. +public final class RMCollectionUtils +{ + private RMCollectionUtils() { /* Intentionally empty. */} + + /** + * Gets the list of duplicate elements contained within the specified list, if any. + * @param l the list in which to find duplicates. + * @param the element type of the list. + * @return a list of duplicate elements. If there are no duplicates, returns an empty list. + */ + public static List getDuplicateElements(List l) + { + final Set uniqueElems = new HashSet<>(); + final List duplicateElems = new ArrayList<>(); + + for (T elem: l) + { + if (uniqueElems.contains(elem)) + { + if (!duplicateElems.contains(elem)) duplicateElems.add(elem); + } + else + { + uniqueElems.add(elem); + } + } + return duplicateElems; + } +} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationLevelValidationUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationLevelValidationUnitTest.java index 5dfbaf1c87..41354148ce 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationLevelValidationUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationLevelValidationUnitTest.java @@ -22,6 +22,7 @@ import static java.util.Arrays.asList; import static org.alfresco.module.org_alfresco_module_rm.classification.ClassificationLevelValidation.ILLEGAL_ABBREVIATION_CHARS; import static org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.expectedException; import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -49,6 +50,7 @@ public class ClassificationLevelValidationUnitTest validation.validateLevels(Collections.emptyList()); } + /** Ensures that null, empty or whitespace-only IDs are rejected. */ @Test public void nonEmptyAbbreviationsAreMandatory() { // A missing or empty level ID is illegal. @@ -62,12 +64,33 @@ public class ClassificationLevelValidationUnitTest } } + @Test(expected=IllegalConfiguration.class) + public void systemUnclassifiedAbbreviationIsReserved() + { + validation.validateLevel(new ClassificationLevel("U", "value.does.not.matter")); + } + @Test(expected=IllegalConfiguration.class) public void longAbbreviationsAreIllegal() { validation.validateLevel(new ClassificationLevel("12345678901", "value.does.not.matter")); } + @Test public void ensureUniquenessOfAbbreviationIds() + { + IllegalConfiguration e = expectedException(IllegalConfiguration.class, () -> + { + validation.validateLevels(asList(new ClassificationLevel("FOO", "value.does.not.matter"), + new ClassificationLevel("BAR", "value.does.not.matter"), + new ClassificationLevel("---", "value.does.not.matter"), + new ClassificationLevel("BAR", "value.does.not.matter"), + new ClassificationLevel("FOO", "value.does.not.matter"))); + return null; + }); + assertThat("Exception message did not identify the duplicate IDs", e.getMessage(), + allOf(containsString("FOO"), containsString("BAR"))); + } + /** * This test ensures that validation will catch any and all illegal characters in a * {@link ClassificationLevel#getId() level ID} and report them all. diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtilsUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtilsUnitTest.java new file mode 100644 index 0000000000..83ca2c61e4 --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtilsUnitTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005-2015 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.module.org_alfresco_module_rm.util; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import java.util.Collections; +import java.util.List; + +/** + * Unit tests for {@link RMCollectionUtils}. + * + * @author Neil Mc Erlean + * @since 3.0 + */ +public class RMCollectionUtilsUnitTest +{ + @Test public void getDuplicateElements() + { + List l = asList("A", "B", "C", "B", "A"); + assertEquals("Failed to identify duplicate elements", asList("B", "A"), RMCollectionUtils.getDuplicateElements(l)); + + assertEquals(Collections.emptyList(), RMCollectionUtils.getDuplicateElements(asList("A", "B", "C"))); + } +}