diff --git a/build.gradle b/build.gradle
index fa8d7850bb..8cedbff55b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -50,7 +50,7 @@ subprojects {
sourceJavaDir = 'source/java'
sourceWebDir = 'source/web'
testJavaDir = 'test/java'
- testResourceDir = 'test/resource'
+ testResourceDir = 'test/resources'
configDir = 'config'
configModuleDir = "config/alfresco/module/${moduleid}"
moduleProperties = 'module.properties'
@@ -98,13 +98,6 @@ subprojects {
}
/** --- Compile tasks --- */
-
- task fetchWarFile(type:Copy) {
- from configurations.testRuntime
- into '.'
- include '*.war'
- rename { String filename -> warFile }
- }
// make sure that the dependancies have been unpacked before compiling the Java
compileJava.doFirst {
@@ -114,6 +107,13 @@ subprojects {
jar.archiveName = jarFile
/** --- Dependancy tasks --- */
+
+ task fetchWarFile(type:Copy) {
+ from configurations.testRuntime
+ into '.'
+ include '*.war'
+ rename { String filename -> warFile }
+ }
task explodeDeps << {
@@ -122,6 +122,7 @@ subprojects {
explodedConfigDir = file("${explodedDepsDir}/config")
warFileObj = file(warFile)
+ // if the WAR file still isn't there raise an error
if (warFileObj.exists() == true) {
logger.lifecycle "${warFile} was found. Checking dependancies ..."
diff --git a/rm-server/.classpath b/rm-server/.classpath
index a600d64633..7003c32d17 100644
--- a/rm-server/.classpath
+++ b/rm-server/.classpath
@@ -281,5 +281,269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rm-server/build.gradle b/rm-server/build.gradle
index 604ed54019..93079a2730 100644
--- a/rm-server/build.gradle
+++ b/rm-server/build.gradle
@@ -7,18 +7,19 @@ dependencies {
testRuntime files(explodedConfigDir)
testRuntime files(configDir)
+ testRuntime files(testResourceDir)
testRuntime group: 'org.alfresco.enterprise', name: 'alfresco', version: alfrescoBaseVersion, type: 'war'
}
test {
- //makes the standard streams (err and out) visible at console when running tests
+
+ include '**/DispositionServiceImplTest.class'
+
testLogging.showStandardStreams = true
- //tweaking memory settings for the forked vm that runs tests
jvmArgs '-Xms256M', '-Xmx1024M', '-XX:MaxPermSize=256M'
- //listening to test execution events
beforeTest { descriptor ->
logger.lifecycle("Running test: " + descriptor)
}
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml
index e475dac07e..087efb6696 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml
@@ -96,6 +96,9 @@
+
+
+
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-disposition-properties-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-disposition-properties-context.xml
new file mode 100644
index 0000000000..dd4dde9bcd
--- /dev/null
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-disposition-properties-context.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
index b79e0f3e54..c3045171d9 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
@@ -205,6 +205,8 @@
@@ -1000,17 +1001,4 @@
-
-
-
-
-
- {http://www.alfresco.org/model/recordsmanagement/1.0}cutOffDate
- {http://www.alfresco.org/model/recordsmanagement/1.0}dispositionAsOf
- {http://www.alfresco.org/model/recordsmanagement/1.0}dateFiled
- {http://www.alfresco.org/model/recordsmanagement/1.0}publicationDate
-
-
-
-
\ No newline at end of file
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMActionExecuterAbstractBase.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMActionExecuterAbstractBase.java
index 9ab72d3ae2..6623bf9dc0 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMActionExecuterAbstractBase.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMActionExecuterAbstractBase.java
@@ -492,25 +492,28 @@ public abstract class RMActionExecuterAbstractBase extends ActionExecuterAbstra
Period period = nextDispositionActionDefinition.getPeriod();
if (period != null)
{
- // Use NOW as the default context date
- Date contextDate = new Date();
+ Date contextDate = null;
// Get the period properties value
QName periodProperty = nextDispositionActionDefinition.getPeriodProperty();
if (periodProperty != null)
{
- contextDate = (Date)this.nodeService.getProperty(nodeRef, periodProperty);
-
- if (contextDate == null)
- {
- // TODO For now we will use NOW to resolve MOB-1184
- //throw new AlfrescoRuntimeException("Date used to calculate disposition action asOf date is not set for property " + periodProperty.toString());
- contextDate = new Date();
- }
+ // doesn't matter if the period property isn't set ... the asOfDate will get updated later
+ // when the value of the period property is set
+ contextDate = (Date)this.nodeService.getProperty(nodeRef, periodProperty);
+ }
+ else
+ {
+ // for now use 'NOW' as the default context date
+ // TODO set the default period property ... cut off date or last disposition date depending on context
+ contextDate = new Date();
}
// Calculate the as of date
- asOfDate = period.getNextDate(contextDate);
+ if (contextDate != null)
+ {
+ asOfDate = period.getNextDate(contextDate);
+ }
}
// Set the property values
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionPeriodProperties.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionPeriodProperties.java
deleted file mode 100644
index 2479e6f06f..0000000000
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionPeriodProperties.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2005-2011 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.disposition;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.alfresco.service.namespace.QName;
-
-/**
- * Spring bean to allow configuration of properties used for calculating
- * dates in disposition schedules.
- *
- * @author Gavin Cornwell
- */
-public class DispositionPeriodProperties
-{
- public static final String BEAN_NAME = "DispositionPeriodProperties";
-
- private List periodProperties;
-
- public void setPropertyList(List propertyList)
- {
- periodProperties = new ArrayList(propertyList.size());
- for (String property : propertyList)
- {
- periodProperties.add(QName.createQName(property));
- }
- }
-
- public List getPeriodProperties()
- {
- return periodProperties;
- }
-}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java
index 0d02d2a336..f40f283a55 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java
@@ -19,9 +19,11 @@
package org.alfresco.module.org_alfresco_module_rm.disposition;
import java.io.Serializable;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
+import org.alfresco.module.org_alfresco_module_rm.disposition.property.DispositionProperty;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
@@ -33,6 +35,23 @@ import org.alfresco.service.namespace.QName;
*/
public interface DispositionService
{
+ /** ========= Disposition Property Methods ========= */
+
+ /**
+ * Register a disposition property.
+ *
+ * @param dispositionProperty disposition property
+ */
+ void registerDispositionProperty(DispositionProperty dispositionProperty);
+
+ /**
+ * Returns the list of disposition period properties
+ *
+ * @return list of disposition period properties
+ */
+ Collection getDispositionProperties();
+
+
/** ========= Disposition Schedule Methods ========= */
/**
@@ -175,14 +194,5 @@ public interface DispositionService
* @return DispositionAction last completed disposition action, null if none
*/
DispositionAction getLastCompletedDispostionAction(NodeRef nodeRef);
-
- /** ========= ========= */
-
- /**
- * Returns the list of disposition period properties
- *
- * @return list of disposition period properties
- */
- List getDispositionPeriodProperties();
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java
index baddd47d32..248ff3078e 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java
@@ -20,14 +20,16 @@ package org.alfresco.module.org_alfresco_module_rm.disposition;
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Collection;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry;
+import org.alfresco.module.org_alfresco_module_rm.disposition.property.DispositionProperty;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -75,6 +77,9 @@ public class DispositionServiceImpl implements DispositionService, RecordsManage
/** Application context */
private ApplicationContext applicationContext;
+ /** Disposition properties */
+ private Map dispositionProperties = new HashMap(4);
+
/**
* Set node service
*
@@ -149,6 +154,26 @@ public class DispositionServiceImpl implements DispositionService, RecordsManage
this.dispositionSelectionStrategy = dispositionSelectionStrategy;
}
+ /** ========= Disposition Property Methods ========= */
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#registerDispositionProperty(org.alfresco.module.org_alfresco_module_rm.disposition.property.DispositionProperty)
+ */
+ @Override
+ public void registerDispositionProperty(DispositionProperty dispositionProperty)
+ {
+ dispositionProperties.put(dispositionProperty.getQName(), dispositionProperty);
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getDispositionProperties()
+ */
+ @Override
+ public Collection getDispositionProperties()
+ {
+ return dispositionProperties.values();
+ }
+
/** ========= Disposition Schedule Methods ========= */
/**
@@ -606,21 +631,5 @@ public class DispositionServiceImpl implements DispositionService, RecordsManage
}
return result;
}
-
-
- public List getDispositionPeriodProperties()
- {
- DispositionPeriodProperties dpp = (DispositionPeriodProperties)applicationContext.getBean(DispositionPeriodProperties.BEAN_NAME);
-
- if (dpp == null)
- {
- return Collections.emptyList();
- }
- else
- {
- return dpp.getPeriodProperties();
- }
- }
-
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java
new file mode 100644
index 0000000000..75216c4356
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java
@@ -0,0 +1,223 @@
+/**
+ *
+ */
+package org.alfresco.module.org_alfresco_module_rm.disposition.property;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Map;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction;
+import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
+import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.policy.JavaBehaviour;
+import org.alfresco.repo.policy.PolicyComponent;
+import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.dictionary.PropertyDefinition;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.Period;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * @author Roy Wetherall
+ */
+public class DispositionProperty implements NodeServicePolicies.OnUpdatePropertiesPolicy,
+ RecordsManagementModel
+{
+ /** Property QName */
+ private QName propertyName;
+
+ private JavaBehaviour behaviour;
+
+ /** Namespace service */
+ private NamespaceService namespaceService;
+
+ /** Disposition service */
+ private DispositionService dispositionService;
+
+ /** Policy component */
+ private PolicyComponent policyComponent;
+
+ /** Dictionary service */
+ private DictionaryService dictionaryService;
+
+ /** Node service */
+ private NodeService nodeService;
+
+ /**
+ * @param namespaceService namespace service
+ */
+ public void setNamespaceService(NamespaceService namespaceService)
+ {
+ this.namespaceService = namespaceService;
+ }
+
+ /**
+ * @param dispositionService disposition service
+ */
+ public void setDispositionService(DispositionService dispositionService)
+ {
+ this.dispositionService = dispositionService;
+ }
+
+ /**
+ * @param policyComponent policy component
+ */
+ public void setPolicyComponent(PolicyComponent policyComponent)
+ {
+ this.policyComponent = policyComponent;
+ }
+
+ /**
+ * @param dictionaryService dictionary service
+ */
+ public void setDictionaryService(DictionaryService dictionaryService)
+ {
+ this.dictionaryService = dictionaryService;
+ }
+
+ /**
+ * @param nodeService node service
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * @param propertyName property name (as string)
+ */
+ public void setName(String propertyName)
+ {
+ this.propertyName = QName.createQName(propertyName, namespaceService);
+ }
+
+ /**
+ * @return property QName
+ */
+ public QName getQName()
+ {
+ return this.propertyName;
+ }
+
+ /**
+ * @return property definition
+ */
+ public PropertyDefinition getPropertyDefinition()
+ {
+ return dictionaryService.getProperty(propertyName);
+ }
+
+ /**
+ * Bean initialisation method
+ */
+ public void init()
+ {
+ // register with disposition service
+ dispositionService.registerDispositionProperty(this);
+
+ // register interest in the update properties policy for disposition
+ behaviour = new JavaBehaviour(this, "onUpdateProperties", NotificationFrequency.TRANSACTION_COMMIT);
+ policyComponent.bindClassBehaviour(
+ NodeServicePolicies.OnUpdatePropertiesPolicy.QNAME,
+ ASPECT_DISPOSITION_LIFECYCLE,
+ behaviour);
+ }
+
+ @Override
+ public void onUpdateProperties(
+ final NodeRef nodeRef,
+ final Map before,
+ final Map after)
+ {
+ if (nodeService.exists(nodeRef) == true)
+ {
+ // has the property we care about changed?
+ if (isPropertyUpdated(before, after) == true)
+ {
+ behaviour.disable();
+ try
+ {
+ AuthenticationUtil.runAs(new RunAsWork()
+ {
+ @Override
+ public Void doWork() throws Exception
+ {
+ Date updatedDateValue = (Date)after.get(propertyName);
+ if (updatedDateValue != null)
+ {
+ DispositionAction dispositionAction = dispositionService.getNextDispositionAction(nodeRef);
+ if (dispositionAction != null)
+ {
+ DispositionActionDefinition daDefinition = dispositionAction.getDispositionActionDefinition();
+ if (daDefinition != null)
+ {
+ // check whether the next disposition action matches this disposition property
+ if (propertyName.equals(daDefinition.getPeriodProperty()) == true)
+ {
+ Period period = daDefinition.getPeriod();
+ Date updatedAsOf = period.getNextDate(updatedDateValue);
+
+ // update asOf date on the disposition action based on the new property value
+ NodeRef daNodeRef = dispositionAction.getNodeRef();
+ nodeService.setProperty(daNodeRef, PROP_DISPOSITION_AS_OF, updatedAsOf);
+ }
+ }
+ }
+ }
+ else
+ {
+ // throw an exception if the property is being 'cleared'
+ if (before.get(propertyName) != null)
+ {
+ throw new AlfrescoRuntimeException(
+ "Error updating property " + propertyName.toPrefixString(namespaceService) +
+ " to null, because property is being used to determine a disposition date.");
+ }
+ }
+
+ return null;
+ }
+
+ }, AuthenticationUtil.getSystemUserName());
+ }
+ finally
+ {
+ behaviour.enable();
+ }
+ }
+ }
+ }
+
+ private boolean isPropertyUpdated(Map before, Map after)
+ {
+ boolean result = false;
+
+ Serializable beforeValue = before.get(propertyName);
+ Serializable afterValue = after.get(propertyName);
+
+ if (beforeValue == null && afterValue != null)
+ {
+ result = true;
+ }
+ else if (beforeValue != null && afterValue == null)
+ {
+ result = true;
+ }
+ else if (beforeValue != null && afterValue != null &&
+ beforeValue.equals(afterValue) == false)
+ {
+ result = true;
+ }
+
+ return result;
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/ListOfValuesGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/ListOfValuesGet.java
index c313aded0c..6e7aef11cb 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/ListOfValuesGet.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/ListOfValuesGet.java
@@ -19,6 +19,7 @@
package org.alfresco.module.org_alfresco_module_rm.script;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -30,6 +31,7 @@ import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction
import org.alfresco.module.org_alfresco_module_rm.audit.AuditEvent;
import org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
+import org.alfresco.module.org_alfresco_module_rm.disposition.property.DispositionProperty;
import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEvent;
import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -247,11 +249,12 @@ public class ListOfValuesGet extends DeclarativeWebScript
protected Map createPeriodPropertiesModel(String baseUrl)
{
// iterate over all period properties and get the label from their type definition
- List periodProperties = dispositionService.getDispositionPeriodProperties();
- List