diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationAspectProperties.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationAspectProperties.java index ca9c6863b3..f13e25037e 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationAspectProperties.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationAspectProperties.java @@ -19,8 +19,11 @@ package org.alfresco.module.org_alfresco_module_rm.classification; import java.util.Date; +import java.util.HashSet; import java.util.Set; +import com.google.common.collect.ImmutableSet; + /** * A data transfer object for properties from the classification aspect. * @@ -36,7 +39,7 @@ public class ClassificationAspectProperties /** The name of the agency responsible for the classification of this content. */ private String classificationAgency; /** A non-empty set of ids of reasons for classifying the content in this way. */ - private Set classificationReasonIds; + private Set classificationReasonIds = new HashSet<>(); /** If provided, this is the date of the next downgrade evaluation. */ private Date downgradeDate; /** If provided, this is the event at which the next downgrade evaluation will take place. */ @@ -47,8 +50,8 @@ public class ClassificationAspectProperties private Date declassificationDate; /** If provided, this is the event at which the next declassification evaluation will take place. */ private String declassificationEvent; - /** This is an optional list of exemption category ids. */ - private Set exemptionCategoryIds; + /** An optional list of exemption category ids. */ + private Set exemptionCategoryIds = new HashSet<>(); /** @return The security clearance needed to access the content. */ public String getClassificationLevelId() @@ -85,10 +88,14 @@ public class ClassificationAspectProperties { return classificationReasonIds; } - /** @param classificationReasonIds A non-empty set of ids of reasons for classifying the content in this way. */ + /** + * Store an immutable copy of the given set of classification reason ids. + * + * @param classificationReasonIds A non-empty set of ids of reasons for classifying the content in this way. + */ public void setClassificationReasonIds(Set classificationReasonIds) { - this.classificationReasonIds = classificationReasonIds; + this.classificationReasonIds = ImmutableSet.copyOf(classificationReasonIds); } /** @return If provided, this is the date of the next downgrade evaluation. */ public Date getDowngradeDate() @@ -145,9 +152,13 @@ public class ClassificationAspectProperties { return exemptionCategoryIds; } - /** @param exemptionCategoryIds This is an optional list of exemption category ids. */ + /** + * Store an immutable copy of the given set of exemption category ids. + * + * @param exemptionCategoryIds This is an optional list of exemption category ids. + */ public void setExemptionCategoryIds(Set exemptionCategoryIds) { - this.exemptionCategoryIds = exemptionCategoryIds; + this.exemptionCategoryIds = ImmutableSet.copyOf(exemptionCategoryIds); } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java index ece40db5f1..383894208b 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java @@ -177,6 +177,15 @@ public class ContentClassificationServiceImpl extends ServiceBaseImpl HashSet classificationReasons = new HashSet<>(propertiesDTO.getClassificationReasonIds()); propertiesMap.put(PROP_CLASSIFICATION_REASONS, classificationReasons); + propertiesMap.put(PROP_DOWNGRADE_DATE, propertiesDTO.getDowngradeDate()); + propertiesMap.put(PROP_DOWNGRADE_EVENT, propertiesDTO.getDowngradeEvent()); + propertiesMap.put(PROP_DOWNGRADE_INSTRUCTIONS, propertiesDTO.getDowngradeInstructions()); + propertiesMap.put(PROP_DECLASSIFICATION_DATE, propertiesDTO.getDeclassificationDate()); + propertiesMap.put(PROP_DECLASSIFICATION_EVENT, propertiesDTO.getDeclassificationEvent()); + + HashSet declassificationExemptions = new HashSet<>(propertiesDTO.getExemptionCategoryIds()); + propertiesMap.put(PROP_DECLASSIFICATION_EXEMPTIONS, declassificationExemptions); + return propertiesMap; } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/clf/aspect/ClassifiedAspect.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/clf/aspect/ClassifiedAspect.java index ee81a503ed..7fe1638fef 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/clf/aspect/ClassifiedAspect.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/clf/aspect/ClassifiedAspect.java @@ -115,6 +115,11 @@ public class ClassifiedAspect extends BaseBehaviourBean implements NodeServicePo * Validates the consistency of the properties. */ @Override + @Behaviour + ( + kind = BehaviourKind.CLASS, + notificationFrequency = NotificationFrequency.EVERY_EVENT + ) public void onAddAspect(final NodeRef nodeRef, final QName aspectTypeQName) { AuthenticationUtil.runAs(new RunAsWork() diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/classification/ClassifyTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/classification/ClassifyTest.java index 8b2134b35b..a73374a9d5 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/classification/ClassifyTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/classification/ClassifyTest.java @@ -19,9 +19,11 @@ package org.alfresco.module.org_alfresco_module_rm.test.integration.classification; import java.util.Collections; +import java.util.Date; import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationAspectProperties; import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.LevelIdNotFound; +import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.MissingDowngradeInstructions; import org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; @@ -210,4 +212,42 @@ public class ClassifyTest extends BaseRMTestCase } }); } + + /** + * Downgrade instructions are mandatory when downgrade date is set. + *

+ * RM-2409

+     * Given I am a cleared user
+     * And I am classifying the content for the first time
+     * And I enter a downgrade date and/or event
+     * When I attempt to save the classification information
+     * Then I will be informed that downgrade instructions are mandatory when the downgrade date and/or event are set
+     * And the save will not be successful
+     * 
+ */ + public void testMissingDowngradeInstructions() throws Exception + { + doBehaviourDrivenTest(new BehaviourDrivenTest(MissingDowngradeInstructions.class) + { + private NodeRef record; + + public void given() throws Exception + { + record = utils.createRecord(rmFolder, RECORD_NAME); + } + + public void when() throws Exception + { + propertiesDTO.setDowngradeDate(new Date()); + assertNull("Downgrade instructions should be null.", propertiesDTO.getDowngradeInstructions()); + contentClassificationService.classifyContent(propertiesDTO, record); + } + + public void after() + { + assertFalse("Record should not have been classified.", + nodeService.hasAspect(record, ClassifiedContentModel.ASPECT_CLASSIFIED)); + } + }); + } } diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImplUnitTest.java index fd12fd04f4..dc91746ae2 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImplUnitTest.java @@ -115,11 +115,18 @@ public class ContentClassificationServiceImplUnitTest implements ClassifiedConte propertiesCaptor.capture()); // Check the properties that were received. Map properties = propertiesCaptor.getValue(); - HashSet expectedPropertyKeys = Sets.newHashSet(ClassifiedContentModel.PROP_INITIAL_CLASSIFICATION, - ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION, - ClassifiedContentModel.PROP_CLASSIFICATION_AGENCY, - ClassifiedContentModel.PROP_CLASSIFIED_BY, - ClassifiedContentModel.PROP_CLASSIFICATION_REASONS); + HashSet expectedPropertyKeys = Sets.newHashSet( + PROP_INITIAL_CLASSIFICATION, + PROP_CURRENT_CLASSIFICATION, + PROP_CLASSIFICATION_AGENCY, + PROP_CLASSIFIED_BY, + PROP_CLASSIFICATION_REASONS, + PROP_DOWNGRADE_DATE, + PROP_DOWNGRADE_EVENT, + PROP_DOWNGRADE_INSTRUCTIONS, + PROP_DECLASSIFICATION_DATE, + PROP_DECLASSIFICATION_EVENT, + PROP_DECLASSIFICATION_EXEMPTIONS); assertEquals("Aspect created with unexpected set of keys.", expectedPropertyKeys, properties.keySet()); assertEquals("Unexpected initial classification.", level.getId(), properties.get(ClassifiedContentModel.PROP_INITIAL_CLASSIFICATION)); assertEquals("Unexpected current classification.", level.getId(), properties.get(ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION));