RM-1358 - Added ghost on destroy option to destroy disposition action

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@66862 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Mark Hibbins
2014-04-06 22:08:32 +00:00
parent 3235fc0973
commit 5e21c31b37
11 changed files with 379 additions and 88 deletions

View File

@@ -7,43 +7,57 @@
<bean id="org_alfresco_module_rm_RMv22ReportTemplatePatch" <bean id="org_alfresco_module_rm_RMv22ReportTemplatePatch"
parent="rm.parentModulePatch" parent="rm.parentModulePatch"
class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22ReportTemplatePatch"> class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22ReportTemplatePatch">
<property name="description" value="Patches new versions of the report templates."/> <property name="description" value="Patches new versions of the report templates."/>
<property name="fixesToSchema" value="1000"/> <property name="fixesToSchema" value="1000"/>
<property name="targetSchema" value="1001"/> <property name="targetSchema" value="1001"/>
<property name="nodeService" ref="NodeService"/> <property name="nodeService" ref="NodeService"/>
<property name="contentService" ref="ContentService"/> <property name="contentService" ref="ContentService"/>
</bean> </bean>
<bean id="org_alfresco_module_rm_RMv22CapabilityPatch" <bean id="org_alfresco_module_rm_RMv22CapabilityPatch"
parent="rm.parentModulePatch" parent="rm.parentModulePatch"
class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22CapabilityPatch"> class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22CapabilityPatch">
<property name="description" value="Patches the existing RM data for the RM v2.2 updated capabilities."/> <property name="description" value="Patches the existing RM data for the RM v2.2 updated capabilities."/>
<property name="fixesToSchema" value="1001"/> <property name="fixesToSchema" value="1001"/>
<property name="targetSchema" value="1002"/> <property name="targetSchema" value="1002"/>
<property name="filePlanService" ref="FilePlanService"/> <property name="filePlanService" ref="FilePlanService"/>
<property name="filePlanRoleService" ref="FilePlanRoleService"/> <property name="filePlanRoleService" ref="FilePlanRoleService"/>
<property name="capabilityService" ref="CapabilityService"/> <property name="capabilityService" ref="CapabilityService"/>
</bean> </bean>
<bean id="rm.dodModelSeparationModulePatch" <bean id="rm.dodModelSeparationModulePatch"
parent="rm.parentModulePatch" parent="rm.parentModulePatch"
class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22DODModelSeparationModulePatch"> class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22DODModelSeparationModulePatch">
<property name="description" value="DOD model separation module patch"/> <property name="description" value="DOD model separation module patch"/>
<property name="fixesToSchema" value="1002"/> <property name="fixesToSchema" value="1002"/>
<property name="targetSchema" value="1003"/> <property name="targetSchema" value="1003"/>
<property name="qnameDAO" ref="qnameDAO"/> <property name="qnameDAO" ref="qnameDAO"/>
<property name="patchDAO" ref="patchDAO"/> <property name="patchDAO" ref="patchDAO"/>
<property name="nodeDAO" ref="nodeDAO"/> <property name="nodeDAO" ref="nodeDAO"/>
</bean> </bean>
<bean id="rm.dodCompliantSitePatch" <bean id="rm.dodCompliantSitePatch"
parent="rm.parentModulePatch" parent="rm.parentModulePatch"
class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22DODCompliantSitePatch"> class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22DODCompliantSitePatch">
<property name="description" value="DOD compliant module patch"/> <property name="description" value="DOD compliant module patch"/>
<property name="fixesToSchema" value="1003"/> <property name="fixesToSchema" value="1003"/>
<property name="targetSchema" value="1004"/> <property name="targetSchema" value="1004"/>
<property name="qnameDAO" ref="qnameDAO"/> <property name="qnameDAO" ref="qnameDAO"/>
</bean> </bean>
<bean id="rm.ghostOnDestroyDispositionActionPatch"
parent="rm.parentModulePatch"
class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22GhostOnDestroyDispositionActionPatch">
<property name="description" value="Patches the existing RM destroy disposition actions to add the RM v2.2 ghost on destroy property"/>
<property name="fixesToSchema" value="1004"/>
<property name="targetSchema" value="1005"/>
<property name="dispositionService" ref="DispositionService"/>
<property name="filePlanService" ref="FilePlanService"/>
<property name="nodeService" ref="NodeService"/>
<property name="ghostingEnabled">
<value>${rm.ghosting.enabled}</value>
</property>
</bean>
</beans> </beans>

View File

@@ -6,10 +6,11 @@
"index": ${action.index}, "index": ${action.index},
"name": "${action.name}", "name": "${action.name}",
"label": "${action.label}", "label": "${action.label}",
<#if (action.name == "destroy") && action.ghostOnDestroy??>"ghostOnDestroy": "${action.ghostOnDestroy}",</#if>
<#if action.description??>"description": "${action.description}",</#if> <#if action.description??>"description": "${action.description}",</#if>
<#if action.period??>"period": "${action.period}",</#if> <#if action.period??>"period": "${action.period}",</#if>
<#if action.periodProperty??>"periodProperty": "${action.periodProperty}",</#if> <#if action.periodProperty??>"periodProperty": "${action.periodProperty}",</#if>
<#if action.location??>"location": "${action.location}",</#if> <#if action.location??>"location": "${action.location}",</#if>
<#if action.events??>"events": [<#list action.events as event>"${event}"<#if event_has_next>,</#if></#list>],</#if> <#if action.events??>"events": [<#list action.events as event>"${event}"<#if event_has_next>,</#if></#list>],</#if>
"eligibleOnFirstCompleteEvent": ${action.eligibleOnFirstCompleteEvent?string} "eligibleOnFirstCompleteEvent": ${action.eligibleOnFirstCompleteEvent?string}
} }

View File

@@ -18,6 +18,7 @@ import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileNotFoundException; import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@@ -84,12 +85,18 @@ public abstract class CopyMoveFileToBaseAction extends RMActionExecuterAbstractB
(!ACTION_FILETO.equals(action.getActionDefinitionName()) || !recordService.isFiled(actionedUponNodeRef)) && (!ACTION_FILETO.equals(action.getActionDefinitionName()) || !recordService.isFiled(actionedUponNodeRef)) &&
(!(ACTION_FILETO.equals(action.getActionDefinitionName()) && RecordsManagementModel.TYPE_UNFILED_RECORD_CONTAINER.equals(nodeService.getType(actionedUponNodeRef))))) (!(ACTION_FILETO.equals(action.getActionDefinitionName()) && RecordsManagementModel.TYPE_UNFILED_RECORD_CONTAINER.equals(nodeService.getType(actionedUponNodeRef)))))
{ {
boolean targetIsUnfiledRecord = boolean targetIsUnfiledRecord;
!ACTION_FILETO.equals(action.getActionDefinitionName()) && ( if (ACTION_FILETO.equals(action.getActionDefinitionName()))
((ContentModel.TYPE_CONTENT.equals(nodeService.getType(actionedUponNodeRef)) || RecordsManagementModel.TYPE_NON_ELECTRONIC_DOCUMENT.equals(nodeService.getType(actionedUponNodeRef))) && {
!recordService.isFiled(actionedUponNodeRef)) || targetIsUnfiledRecord = false;
RecordsManagementModel.TYPE_UNFILED_RECORD_CONTAINER.equals(nodeService.getType(actionedUponNodeRef)) }
); else
{
QName actionedUponType = nodeService.getType(actionedUponNodeRef);
targetIsUnfiledRecord = (dictionaryService.isSubClass(actionedUponType, ContentModel.TYPE_CONTENT) && !recordService
.isFiled(actionedUponNodeRef))
|| RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER.equals(actionedUponType);
}
// first look to see if the destination record folder has been specified // first look to see if the destination record folder has been specified
NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER);

View File

@@ -27,6 +27,8 @@ import org.alfresco.model.ContentModel;
import org.alfresco.model.RenditionModel; import org.alfresco.model.RenditionModel;
import org.alfresco.module.org_alfresco_module_rm.action.RMDispositionActionExecuterAbstractBase; import org.alfresco.module.org_alfresco_module_rm.action.RMDispositionActionExecuterAbstractBase;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService; import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.repo.content.cleanup.EagerContentStoreCleaner; import org.alfresco.repo.content.cleanup.EagerContentStoreCleaner;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
@@ -35,6 +37,7 @@ import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.apache.commons.lang.StringUtils;
/** /**
* Destroy action. * Destroy action.
@@ -123,8 +126,7 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase
{ {
executeRecordLevelDisposition(action, record); executeRecordLevelDisposition(action, record);
} }
if (isGhostOnDestroySetForAction(action, recordFolder))
if (ghostingEnabled)
{ {
nodeService.addAspect(recordFolder, ASPECT_GHOSTED, Collections.<QName, Serializable> emptyMap()); nodeService.addAspect(recordFolder, ASPECT_GHOSTED, Collections.<QName, Serializable> emptyMap());
} }
@@ -139,32 +141,22 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase
*/ */
@Override @Override
protected void executeRecordLevelDisposition(Action action, NodeRef record) protected void executeRecordLevelDisposition(Action action, NodeRef record)
{
doDestroy(record);
}
/**
* Do the content destroy
*
* @param nodeRef
*/
private void doDestroy(NodeRef nodeRef)
{ {
// Clear the content // Clear the content
clearAllContent(nodeRef); clearAllContent(record);
// Clear thumbnail content // Clear thumbnail content
clearThumbnails(nodeRef); clearThumbnails(record);
if (ghostingEnabled) if (isGhostOnDestroySetForAction(action, record))
{ {
// Add the ghosted aspect // Add the ghosted aspect
nodeService.addAspect(nodeRef, ASPECT_GHOSTED, null); nodeService.addAspect(record, ASPECT_GHOSTED, null);
} }
else else
{ {
// If ghosting is not enabled, delete the node // If ghosting is not enabled, delete the node
nodeService.deleteNode(nodeRef); nodeService.deleteNode(record);
} }
} }
@@ -237,4 +229,36 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase
eagerContentStoreCleaner.registerOrphanedContentUrl(contentData.getContentUrl(), true); eagerContentStoreCleaner.registerOrphanedContentUrl(contentData.getContentUrl(), true);
} }
} }
/**
* Return true if the ghost on destroy property is set against the
* definition for the passed action on the specified node
*
* @param action
* @param nodeRef
* @return
*/
private boolean isGhostOnDestroySetForAction(Action action, NodeRef nodeRef)
{
boolean ghostOnDestroy = this.ghostingEnabled;
String actionDefinitionName = action.getActionDefinitionName();
if (!StringUtils.isEmpty(actionDefinitionName))
{
DispositionSchedule dispositionSchedule = this.dispositionService.getDispositionSchedule(nodeRef);
if (dispositionSchedule != null)
{
DispositionActionDefinition actionDefinition = dispositionSchedule
.getDispositionActionDefinitionByName(actionDefinitionName);
if (actionDefinition != null)
{
String ghostOnDestroyProperty = actionDefinition.getGhostOnDestroy();
if (ghostOnDestroyProperty != null)
{
ghostOnDestroy = "ghost".equals(actionDefinition.getGhostOnDestroy());
}
}
}
}
return ghostOnDestroy;
}
} }

View File

@@ -38,75 +38,86 @@ public interface DispositionActionDefinition
* @return NodeRef of disposition action definition * @return NodeRef of disposition action definition
*/ */
NodeRef getNodeRef(); NodeRef getNodeRef();
/** /**
* Get disposition action id * Get disposition action id
* *
* @return String id * @return String id
*/ */
String getId(); String getId();
/** /**
* Get the index of the action within the disposition instructions * Get the index of the action within the disposition instructions
* *
* @return int disposition action index * @return int disposition action index
*/ */
int getIndex(); int getIndex();
/** /**
* Get the name of disposition action * Get the name of disposition action
* *
* @return String name * @return String name
*/ */
String getName(); String getName();
/** /**
* Get the display label of the disposition action * Get the display label of the disposition action
* *
* @return String name's display label * @return String name's display label
*/ */
String getLabel(); String getLabel();
/** /**
* Get the description of the disposition action * Get the description of the disposition action
* *
* @return String description * @return String description
*/ */
String getDescription(); String getDescription();
/** /**
* Get the period for the disposition action * Get the period for the disposition action
* *
* @return Period disposition period * @return Period disposition period
*/ */
Period getPeriod(); Period getPeriod();
/** /**
* Property to which the period is relative to * Property to which the period is relative to
* *
* @return QName property name * @return QName property name
*/ */
QName getPeriodProperty(); QName getPeriodProperty();
/** /**
* List of events for the disposition * List of events for the disposition
* *
* @return List<RecordsManagementEvent> list of events * @return List<RecordsManagementEvent> list of events
*/ */
List<RecordsManagementEvent> getEvents(); List<RecordsManagementEvent> getEvents();
/** /**
* Indicates whether the disposition action is eligible when the earliest event is complete, otherwise * Indicates whether the disposition action is eligible when the earliest
* all events must be complete before eligibility. * event is complete, otherwise all events must be complete before
* eligibility.
* *
* @return boolean true if eligible on first action complete, false otherwise * @return boolean true if eligible on first action complete, false
* otherwise
*/ */
boolean eligibleOnFirstCompleteEvent(); boolean eligibleOnFirstCompleteEvent();
/** /**
* Get the location of the disposition (can be null) * Get the location of the disposition (can be null)
* *
* @return String disposition location * @return String disposition location
*/ */
String getLocation(); String getLocation();
/**
* Get the ghost on destroy from the disposition
*
* @return boolean the gost on destroy flag (on applicable to destroy
* actions)
*/
String getGhostOnDestroy();
} }

View File

@@ -63,6 +63,9 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** Action index */ /** Action index */
private int index; private int index;
/** Ghost on detroy */
private String ghostOnDestroy;
/** /**
* Constructor * Constructor
* *
@@ -83,6 +86,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getNodeRef() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getNodeRef()
*/ */
@Override
public NodeRef getNodeRef() public NodeRef getNodeRef()
{ {
return this.dispositionActionNodeRef; return this.dispositionActionNodeRef;
@@ -91,6 +95,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getIndex() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getIndex()
*/ */
@Override
public int getIndex() public int getIndex()
{ {
return this.index; return this.index;
@@ -99,6 +104,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getId() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getId()
*/ */
@Override
public String getId() public String getId()
{ {
return this.dispositionActionNodeRef.getId(); return this.dispositionActionNodeRef.getId();
@@ -107,6 +113,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getDescription() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getDescription()
*/ */
@Override
public String getDescription() public String getDescription()
{ {
if (description == null) if (description == null)
@@ -119,6 +126,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getName() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getName()
*/ */
@Override
public String getName() public String getName()
{ {
if (name == null) if (name == null)
@@ -131,6 +139,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getLabel() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getLabel()
*/ */
@Override
public String getLabel() public String getLabel()
{ {
if (label == null) if (label == null)
@@ -152,6 +161,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getPeriod() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getPeriod()
*/ */
@Override
public Period getPeriod() public Period getPeriod()
{ {
return (Period)nodeService.getProperty(this.dispositionActionNodeRef, PROP_DISPOSITION_PERIOD); return (Period)nodeService.getProperty(this.dispositionActionNodeRef, PROP_DISPOSITION_PERIOD);
@@ -160,6 +170,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getPeriodProperty() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getPeriodProperty()
*/ */
@Override
public QName getPeriodProperty() public QName getPeriodProperty()
{ {
QName result = null; QName result = null;
@@ -174,6 +185,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getEvents() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getEvents()
*/ */
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<RecordsManagementEvent> getEvents() public List<RecordsManagementEvent> getEvents()
{ {
@@ -198,6 +210,7 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#eligibleOnFirstCompleteEvent() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#eligibleOnFirstCompleteEvent()
*/ */
@Override
public boolean eligibleOnFirstCompleteEvent() public boolean eligibleOnFirstCompleteEvent()
{ {
boolean result = true; boolean result = true;
@@ -212,8 +225,23 @@ public class DispositionActionDefinitionImpl implements DispositionActionDefinit
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getLocation() * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getLocation()
*/ */
@Override
public String getLocation() public String getLocation()
{ {
return (String)nodeService.getProperty(this.dispositionActionNodeRef, PROP_DISPOSITION_LOCATION); return (String)nodeService.getProperty(this.dispositionActionNodeRef, PROP_DISPOSITION_LOCATION);
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition#getGhostOnDestroy()
*/
@Override
public String getGhostOnDestroy()
{
if (ghostOnDestroy == null)
{
ghostOnDestroy = (String) nodeService.getProperty(this.dispositionActionNodeRef,
PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY);
}
return ghostOnDestroy;
}
} }

View File

@@ -89,6 +89,7 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
QName PROP_DISPOSITION_EVENT = QName.createQName(RM_URI, "dispositionEvent"); QName PROP_DISPOSITION_EVENT = QName.createQName(RM_URI, "dispositionEvent");
QName PROP_DISPOSITION_EVENT_COMBINATION = QName.createQName(RM_URI, "dispositionEventCombination"); QName PROP_DISPOSITION_EVENT_COMBINATION = QName.createQName(RM_URI, "dispositionEventCombination");
QName PROP_DISPOSITION_LOCATION = QName.createQName(RM_URI, "dispositionLocation"); QName PROP_DISPOSITION_LOCATION = QName.createQName(RM_URI, "dispositionLocation");
QName PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY = QName.createQName(RM_URI, "dispositionActionGhostOnDestroy");
// Records folder // Records folder
QName TYPE_RECORD_FOLDER = QName.createQName(RM_URI, "recordFolder"); QName TYPE_RECORD_FOLDER = QName.createQName(RM_URI, "recordFolder");

View File

@@ -0,0 +1,175 @@
/*
* Copyright (C) 2005-2013 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.patch.v22;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
/**
* Sets the ghost on destroy property for existing destroy disposition actions
* to the value specified in the global properties file
*
* @author Mark Hibbins
* @since 2.2
*/
public class RMv22GhostOnDestroyDispositionActionPatch extends AbstractModulePatch
{
/** Disposition service */
private DispositionService dispositionService;
/** File plan service */
private FilePlanService filePlanService;
/** Node service */
private NodeService nodeService;
/** Ghost on destroy setting */
private boolean ghostingEnabled;
/**
* @param dispositionService disposition service
*/
public void setDispositionService(DispositionService dispositionService)
{
this.dispositionService = dispositionService;
}
/**
* @param filePlanService file plan service
*/
public void setFilePlanService(FilePlanService filePlanService)
{
this.filePlanService = filePlanService;
}
/**
* @param nodeService file plan service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param ghostingEnabled Ghost on destroy setting from
* alfresco-global.properties
*/
public void setGhostingEnabled(boolean ghostingEnabled)
{
this.ghostingEnabled = ghostingEnabled;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch#applyInternal()
*/
@Override
public void applyInternal()
{
Set<NodeRef> filePlans = filePlanService.getFilePlans();
for (NodeRef filePlan : filePlans)
{
processFilePlan(filePlan);
}
}
/**
* Apply the patch to each file plan
*
* @param filePlan
*/
private void processFilePlan(NodeRef filePlan)
{
Set<DispositionSchedule> dispositionSchedules = new HashSet<DispositionSchedule>();
getDispositionSchedules(filePlan, dispositionSchedules);
for (DispositionSchedule dispositionSchedule : dispositionSchedules)
{
processDispositionSchedule(dispositionSchedule);
}
}
/**
* Add the disposition schedule associated with the node ref to the passed
* set of disposition schedule then call this method recursively for this
* node's children
*
* @param nodeRef
* @param dispositionSchedules
*/
private void getDispositionSchedules(NodeRef nodeRef, Set<DispositionSchedule> dispositionSchedules)
{
DispositionSchedule dispositionSchedule = this.dispositionService.getDispositionSchedule(nodeRef);
if (dispositionSchedule != null)
{
dispositionSchedules.add(dispositionSchedule);
}
List<ChildAssociationRef> children = nodeService.getChildAssocs(nodeRef);
for (ChildAssociationRef childAssoc : children)
{
getDispositionSchedules(childAssoc.getChildRef(), dispositionSchedules);
}
}
/**
* Patch the specified disposition schedule. To do this add the host on
* destroy to any action definition that doesn't already have it defined and
* set the value to the value set in the global properties file. Leave any
* action definitions that have this property already defined untouched.
*
* @param dispositionSchedule
*/
private void processDispositionSchedule(DispositionSchedule dispositionSchedule)
{
List<DispositionActionDefinition> actionDefinitions = dispositionSchedule.getDispositionActionDefinitions();
for(DispositionActionDefinition actionDefinition : actionDefinitions)
{
String actionName = (String) nodeService.getProperty(actionDefinition.getNodeRef(),
RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME);
if ("destroy".equals(actionName))
{
// we only want to add the ghost on destroy property to action
// definitions that do not already have it defined
String ghostOnDestroyValue = (String) nodeService.getProperty(actionDefinition.getNodeRef(),
RecordsManagementModel.PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY);
if (ghostOnDestroyValue == null)
{
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
props.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY,
this.ghostingEnabled ? "ghost" : "destroy");
this.dispositionService.updateDispositionActionDefinition(actionDefinition, props);
}
}
}
}
}

View File

@@ -140,6 +140,11 @@ public class DispositionAbstractBase extends AbstractRmWebScript
model.put("location", actionDef.getLocation()); model.put("location", actionDef.getLocation());
} }
if (actionDef.getGhostOnDestroy() != null)
{
model.put("ghostOnDestroy", actionDef.getGhostOnDestroy());
}
List<RecordsManagementEvent> events = actionDef.getEvents(); List<RecordsManagementEvent> events = actionDef.getEvents();
if (events != null && events.size() > 0) if (events != null && events.size() > 0)
{ {

View File

@@ -29,14 +29,14 @@ import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionD
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONTokener; import org.json.JSONTokener;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/** /**
* Implementation for Java backed webscript to create a new dispositon action definition. * Implementation for Java backed webscript to create a new dispositon action definition.
@@ -141,6 +141,18 @@ public class DispositionActionDefinitionPost extends DispositionAbstractBase
props.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, (Serializable)eventsList); props.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, (Serializable)eventsList);
} }
if (json.has("name") && "destroy".equals(json.getString("name")))
{
if (json.has("ghostOnDestroy"))
{
props.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY, "ghost");
}
else
{
props.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY, "delete");
}
}
// add the action definition to the schedule // add the action definition to the schedule
return this.dispositionService.addDispositionActionDefinition(schedule, props); return this.dispositionService.addDispositionActionDefinition(schedule, props);
} }

View File

@@ -29,17 +29,18 @@ import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionD
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONTokener; import org.json.JSONTokener;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/** /**
* Implementation for Java backed webscript to update an existing dispositon action definition. * Implementation for Java backed webscript to update an existing dispositon
* action definition.
* *
* @author Gavin Cornwell * @author Gavin Cornwell
*/ */
@@ -53,17 +54,17 @@ public class DispositionActionDefinitionPut extends DispositionAbstractBase
{ {
// parse the request to retrieve the schedule object // parse the request to retrieve the schedule object
DispositionSchedule schedule = parseRequestForSchedule(req); DispositionSchedule schedule = parseRequestForSchedule(req);
// parse the request to retrieve the action definition object // parse the request to retrieve the action definition object
DispositionActionDefinition actionDef = parseRequestForActionDefinition(req, schedule); DispositionActionDefinition actionDef = parseRequestForActionDefinition(req, schedule);
// retrieve the rest of the post body and update the action definition // retrieve the rest of the post body and update the action definition
JSONObject json = null; JSONObject json = null;
try try
{ {
json = new JSONObject(new JSONTokener(req.getContent().getContent())); json = new JSONObject(new JSONTokener(req.getContent().getContent()));
actionDef = updateActionDefinition(actionDef, json); actionDef = updateActionDefinition(actionDef, json);
} }
catch (IOException iox) catch (IOException iox)
{ {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, throw new WebScriptException(Status.STATUS_BAD_REQUEST,
@@ -74,13 +75,13 @@ public class DispositionActionDefinitionPut extends DispositionAbstractBase
throw new WebScriptException(Status.STATUS_BAD_REQUEST, throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"Could not parse JSON from req.", je); "Could not parse JSON from req.", je);
} }
// create model object with just the action data // create model object with just the action data
Map<String, Object> model = new HashMap<String, Object>(1); Map<String, Object> model = new HashMap<String, Object>(1);
model.put("action", createActionDefModel(actionDef, req.getURL())); model.put("action", createActionDefModel(actionDef, req.getURL()));
return model; return model;
} }
/** /**
* Updates a dispositionActionDefinition node in the repo. * Updates a dispositionActionDefinition node in the repo.
* *
@@ -94,40 +95,40 @@ public class DispositionActionDefinitionPut extends DispositionAbstractBase
{ {
// create the properties for the action definition // create the properties for the action definition
Map<QName, Serializable> props = new HashMap<QName, Serializable>(8); Map<QName, Serializable> props = new HashMap<QName, Serializable>(8);
if (json.has("name")) if (json.has("name"))
{ {
props.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, json.getString("name")); props.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, json.getString("name"));
} }
if (json.has("description")) if (json.has("description"))
{ {
props.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, json.getString("description")); props.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, json.getString("description"));
} }
if (json.has("period")) if (json.has("period"))
{ {
props.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, json.getString("period")); props.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, json.getString("period"));
} }
if (json.has("periodProperty")) if (json.has("periodProperty"))
{ {
QName periodProperty = QName.createQName(json.getString("periodProperty"), this.namespaceService); QName periodProperty = QName.createQName(json.getString("periodProperty"), this.namespaceService);
props.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, periodProperty); props.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, periodProperty);
} }
if (json.has("eligibleOnFirstCompleteEvent")) if (json.has("eligibleOnFirstCompleteEvent"))
{ {
props.put(RecordsManagementModel.PROP_DISPOSITION_EVENT_COMBINATION, props.put(RecordsManagementModel.PROP_DISPOSITION_EVENT_COMBINATION,
json.getBoolean("eligibleOnFirstCompleteEvent") ? "or" : "and"); json.getBoolean("eligibleOnFirstCompleteEvent") ? "or" : "and");
} }
if (json.has("location")) if (json.has("location"))
{ {
props.put(RecordsManagementModel.PROP_DISPOSITION_LOCATION, props.put(RecordsManagementModel.PROP_DISPOSITION_LOCATION,
json.getString("location")); json.getString("location"));
} }
if (json.has("events")) if (json.has("events"))
{ {
JSONArray events = json.getJSONArray("events"); JSONArray events = json.getJSONArray("events");
@@ -138,8 +139,20 @@ public class DispositionActionDefinitionPut extends DispositionAbstractBase
} }
props.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, (Serializable)eventsList); props.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, (Serializable)eventsList);
} }
if (json.has("name") && "destroy".equals(json.getString("name")))
{
if (json.has("ghostOnDestroy"))
{
props.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY, "ghost");
}
else
{
props.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY, "delete");
}
}
// update the action definition // update the action definition
return this.dispositionService.updateDispositionActionDefinition(actionDef, props); return this.dispositionService.updateDispositionActionDefinition(actionDef, props);
} }
} }