RM-263: Issue when we set disposition schedule based on Publication Date

* refactored the way disposition properties work
  * now additional disposition date properties are sprung in and registered in the disposition service
  * each disposition property bean looks after updating the disposition asof date when the date property changes
  * defaults to null date if can not be calculated
  * unit test for new method and this issue
  * also updated build scripts to successfully run unit test .. will gradually add in other unit tests as their reliability is improved



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.0@36222 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2012-05-09 23:35:37 +00:00
parent 0e5c86e86c
commit 3498ea59a1
13 changed files with 708 additions and 120 deletions

View File

@@ -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

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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<QName> periodProperties;
public void setPropertyList(List<String> propertyList)
{
periodProperties = new ArrayList<QName>(propertyList.size());
for (String property : propertyList)
{
periodProperties.add(QName.createQName(property));
}
}
public List<QName> getPeriodProperties()
{
return periodProperties;
}
}

View File

@@ -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<DispositionProperty> 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<QName> getDispositionPeriodProperties();
}

View File

@@ -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<QName, DispositionProperty> dispositionProperties = new HashMap<QName, DispositionProperty>(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<DispositionProperty> getDispositionProperties()
{
return dispositionProperties.values();
}
/** ========= Disposition Schedule Methods ========= */
/**
@@ -606,21 +631,5 @@ public class DispositionServiceImpl implements DispositionService, RecordsManage
}
return result;
}
public List<QName> getDispositionPeriodProperties()
{
DispositionPeriodProperties dpp = (DispositionPeriodProperties)applicationContext.getBean(DispositionPeriodProperties.BEAN_NAME);
if (dpp == null)
{
return Collections.emptyList();
}
else
{
return dpp.getPeriodProperties();
}
}
}

View File

@@ -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<QName, Serializable> before,
final Map<QName, Serializable> 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<Void>()
{
@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<QName, Serializable> before, Map<QName, Serializable> 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;
}
}

View File

@@ -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<String, Object> createPeriodPropertiesModel(String baseUrl)
{
// iterate over all period properties and get the label from their type definition
List<QName> periodProperties = dispositionService.getDispositionPeriodProperties();
List<Map<String, String>> items = new ArrayList<Map<String, String>>(periodProperties.size());
for (QName periodProperty : periodProperties)
Collection<DispositionProperty> dispositionProperties = dispositionService.getDispositionProperties();
List<Map<String, String>> items = new ArrayList<Map<String, String>>(dispositionProperties.size());
for (DispositionProperty dispositionProperty : dispositionProperties)
{
PropertyDefinition propDef = this.ddService.getProperty(periodProperty);
PropertyDefinition propDef = dispositionProperty.getPropertyDefinition();
QName propName = dispositionProperty.getQName();
if (propDef != null)
{
@@ -259,10 +262,10 @@ public class ListOfValuesGet extends DeclarativeWebScript
String propTitle = propDef.getTitle();
if (propTitle == null || propTitle.length() == 0)
{
propTitle = StringUtils.capitalize(periodProperty.getLocalName());
propTitle = StringUtils.capitalize(propName.getLocalName());
}
item.put("label", propTitle);
item.put("value", periodProperty.toPrefixString(this.namespaceService));
item.put("value", propName.toPrefixString(this.namespaceService));
items.add(item);
}
}