diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationException.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationException.java
index af33df5a8d..70e3f7d603 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationException.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationException.java
@@ -130,4 +130,17 @@ public class ClassificationException extends AlfrescoRuntimeException
super("Operation not permitted on node " + nodeRef + ", error message: " + message);
}
}
+
+ /** A downgrade date or event has been specified, but there are no corresponding instructions. */
+ public static class MissingDowngradeInstructions extends ClassificationException
+ {
+ /** serial version uid */
+ private static final long serialVersionUID = -1561288436418050014L;
+
+ public MissingDowngradeInstructions(NodeRef nodeRef)
+ {
+ super("A downgrade date or event has been specified, but there are no corresponding instructions for "
+ + nodeRef);
+ }
+ }
}
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 702e847064..ee81a503ed 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
@@ -18,18 +18,19 @@
*/
package org.alfresco.module.org_alfresco_module_rm.model.clf.aspect;
-import static org.alfresco.module.org_alfresco_module_rm.classification.ClassificationSchemeService.Reclassification;
-import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.ASPECT_CLASSIFIED;
-import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION;
-import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.PROP_LAST_RECLASSIFICATION_ACTION;
-import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.PROP_LAST_RECLASSIFY_AT;
-import static org.alfresco.module.org_alfresco_module_rm.util.RMCollectionUtils.Difference;
import static org.alfresco.module.org_alfresco_module_rm.util.RMCollectionUtils.diffKey;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Map;
+
+import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.MissingDowngradeInstructions;
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationLevel;
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationSchemeService;
+import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationSchemeService.Reclassification;
import org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
+import org.alfresco.module.org_alfresco_module_rm.util.RMCollectionUtils.Difference;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.annotation.Behaviour;
@@ -40,10 +41,6 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
-import java.io.Serializable;
-import java.util.Date;
-import java.util.Map;
-
/**
* clf:classification behaviour bean
*
@@ -53,8 +50,8 @@ import java.util.Map;
(
defaultType = "clf:classified"
)
-public class ClassifiedAspect extends BaseBehaviourBean
- implements NodeServicePolicies.OnUpdatePropertiesPolicy
+public class ClassifiedAspect extends BaseBehaviourBean implements NodeServicePolicies.OnUpdatePropertiesPolicy,
+ NodeServicePolicies.OnAddAspectPolicy, ClassifiedContentModel
{
private ClassificationSchemeService classificationSchemeService;
@@ -64,9 +61,13 @@ public class ClassifiedAspect extends BaseBehaviourBean
}
/**
+ * Behaviour associated with updating the classified aspect properties.
+ *
* Ensures that on reclassification of content (in other words a change in the value of the
* {@link ClassifiedContentModel#PROP_CURRENT_CLASSIFICATION clf:currentClassification} property)
* that various metadata are correctly updated as a side-effect.
+ *
+ * Validates the consistency of the properties.
*/
@Override
@Behaviour
@@ -100,8 +101,48 @@ public class ClassifiedAspect extends BaseBehaviourBean
nodeService.setProperty(nodeRef, PROP_LAST_RECLASSIFY_AT, new Date());
}
}
+
+ checkConsistencyOfProperties(nodeRef);
+
return null;
}
}, AuthenticationUtil.getSystemUserName());
}
+
+ /**
+ * Behaviour associated with updating the classified aspect properties.
+ *
+ * Validates the consistency of the properties.
+ */
+ @Override
+ public void onAddAspect(final NodeRef nodeRef, final QName aspectTypeQName)
+ {
+ AuthenticationUtil.runAs(new RunAsWork()
+ {
+ public Void doWork()
+ {
+ checkConsistencyOfProperties(nodeRef);
+ return null;
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+
+ /**
+ * Check the consistency of the classification properties and throw an exception if they are invalid.
+ *
+ * @param nodeRef The classified node.
+ */
+ protected void checkConsistencyOfProperties(NodeRef nodeRef) throws MissingDowngradeInstructions
+ {
+ if (nodeService.hasAspect(nodeRef, ASPECT_CLASSIFIED))
+ {
+ Serializable downgradeDate = nodeService.getProperty(nodeRef, PROP_DOWNGRADE_DATE);
+ Serializable downgradeEvent = nodeService.getProperty(nodeRef, PROP_DOWNGRADE_EVENT);
+ Serializable downgradeInstructions = nodeService.getProperty(nodeRef, PROP_DOWNGRADE_INSTRUCTIONS);
+ if (downgradeInstructions == null && (downgradeDate != null || downgradeEvent != null))
+ {
+ throw new MissingDowngradeInstructions(nodeRef);
+ }
+ }
+ }
}
diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/clf/aspect/ClassifiedAspectUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/clf/aspect/ClassifiedAspectUnitTest.java
new file mode 100644
index 0000000000..e407e8682c
--- /dev/null
+++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/clf/aspect/ClassifiedAspectUnitTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.model.clf.aspect;
+
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import java.util.Date;
+
+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.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+/**
+ * Unit tests for the {@link ClassifiedAspect}.
+ *
+ * @author Tom Page
+ * @since 3.0.a
+ */
+public class ClassifiedAspectUnitTest implements ClassifiedContentModel
+{
+ private static final NodeRef NODE_REF = new NodeRef("node://Ref/");
+
+ @InjectMocks ClassifiedAspect classifiedAspect;
+ @Mock NodeService mockNodeService;
+
+ @Before
+ public void setUp()
+ {
+ initMocks(this);
+ }
+
+ /** Check that providing an event and instructions is valid. */
+ @Test
+ public void testCheckConsistencyOfProperties_success()
+ {
+ when(mockNodeService.hasAspect(NODE_REF, ASPECT_CLASSIFIED)).thenReturn(true);
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_DATE)).thenReturn(null);
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_EVENT)).thenReturn("Event");
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_INSTRUCTIONS)).thenReturn("Instructions");
+
+ classifiedAspect.checkConsistencyOfProperties(NODE_REF);
+ }
+
+ /** Check that omitting all downgrade fields is valid. */
+ @Test
+ public void testCheckConsistencyOfProperties_notSpecified()
+ {
+ when(mockNodeService.hasAspect(NODE_REF, ASPECT_CLASSIFIED)).thenReturn(true);
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_DATE)).thenReturn(null);
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_EVENT)).thenReturn(null);
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_INSTRUCTIONS)).thenReturn(null);
+
+ classifiedAspect.checkConsistencyOfProperties(NODE_REF);
+ }
+
+ /** Check that a date without instructions throws an exception. */
+ @Test(expected = MissingDowngradeInstructions.class)
+ public void testCheckConsistencyOfProperties_dateMissingInstructions()
+ {
+ when(mockNodeService.hasAspect(NODE_REF, ASPECT_CLASSIFIED)).thenReturn(true);
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_DATE)).thenReturn(new Date(123));
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_EVENT)).thenReturn(null);
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_INSTRUCTIONS)).thenReturn(null);
+
+ classifiedAspect.checkConsistencyOfProperties(NODE_REF);
+ }
+
+ /** Check that an event without instructions throws an exception. */
+ @Test(expected = MissingDowngradeInstructions.class)
+ public void testCheckConsistencyOfProperties_eventMissingInstructions()
+ {
+ when(mockNodeService.hasAspect(NODE_REF, ASPECT_CLASSIFIED)).thenReturn(true);
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_DATE)).thenReturn(null);
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_EVENT)).thenReturn("Event");
+ when(mockNodeService.getProperty(NODE_REF, PROP_DOWNGRADE_INSTRUCTIONS)).thenReturn(null);
+
+ classifiedAspect.checkConsistencyOfProperties(NODE_REF);
+ }
+}