Implementing FreezeService

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@43521 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Tuna Aksoy
2012-11-09 22:02:42 +00:00
parent 2aa179b3be
commit 191b50faed
12 changed files with 899 additions and 640 deletions

View File

@@ -35,3 +35,4 @@ rm.action.node-not-transfer=Node is not a transfer object.
rm.action.undo-not-last=Can not undo cut off, because last disposition action was not cut off. rm.action.undo-not-last=Can not undo cut off, because last disposition action was not cut off.
rm.action.records_only_undeclared=Only records can be undeclared. rm.action.records_only_undeclared=Only records can be undeclared.
rm.action.event-not-undone=The event {0} can not be undone, because it is not defined on the disposition lifecycle. rm.action.event-not-undone=The event {0} can not be undone, because it is not defined on the disposition lifecycle.
rm.action.empty-set-of-noderefs=The set of nodeRefs is empty.

View File

@@ -399,6 +399,7 @@
<bean id="freeze" class="org.alfresco.module.org_alfresco_module_rm.action.impl.FreezeAction" parent="rmAction" depends-on="rmExtendRetentionPeriodOrFreezeCapability"> <bean id="freeze" class="org.alfresco.module.org_alfresco_module_rm.action.impl.FreezeAction" parent="rmAction" depends-on="rmExtendRetentionPeriodOrFreezeCapability">
<property name="capability" ref="rmExtendRetentionPeriodOrFreezeCapability" /> <property name="capability" ref="rmExtendRetentionPeriodOrFreezeCapability" />
<property name="freezeService" ref="freezeService" />
</bean> </bean>
<!-- Unfreeze record --> <!-- Unfreeze record -->
@@ -426,6 +427,7 @@
<bean id="unfreeze" class="org.alfresco.module.org_alfresco_module_rm.action.impl.UnfreezeAction" parent="rmAction" depends-on="rmUnfreezeCapability"> <bean id="unfreeze" class="org.alfresco.module.org_alfresco_module_rm.action.impl.UnfreezeAction" parent="rmAction" depends-on="rmUnfreezeCapability">
<property name="capability" ref="rmUnfreezeCapability" /> <property name="capability" ref="rmUnfreezeCapability" />
<property name="freezeService" ref="freezeService" />
</bean> </bean>
<!-- Relinquish Hold Action--> <!-- Relinquish Hold Action-->
@@ -443,6 +445,7 @@
<bean id="relinquishHold" class="org.alfresco.module.org_alfresco_module_rm.action.impl.RelinquishHoldAction" parent="rmAction" depends-on="rmUnfreezeCapability"> <bean id="relinquishHold" class="org.alfresco.module.org_alfresco_module_rm.action.impl.RelinquishHoldAction" parent="rmAction" depends-on="rmUnfreezeCapability">
<property name="capability" ref="rmUnfreezeCapability" /> <property name="capability" ref="rmUnfreezeCapability" />
<property name="freezeService" ref="freezeService" />
</bean> </bean>
<!-- Edit hold reason --> <!-- Edit hold reason -->
@@ -470,6 +473,7 @@
<bean id="editHoldReason" class="org.alfresco.module.org_alfresco_module_rm.action.impl.EditHoldReasonAction" parent="rmAction" depends-on="rmViewUpdateReasonsForFreezeCapability"> <bean id="editHoldReason" class="org.alfresco.module.org_alfresco_module_rm.action.impl.EditHoldReasonAction" parent="rmAction" depends-on="rmViewUpdateReasonsForFreezeCapability">
<property name="capability" ref="rmViewUpdateReasonsForFreezeCapability" /> <property name="capability" ref="rmViewUpdateReasonsForFreezeCapability" />
<property name="freezeService" ref="freezeService" />
</bean> </bean>
<!-- Edit review as of date --> <!-- Edit review as of date -->

View File

@@ -722,6 +722,7 @@
<property name="policyComponent" ref="policyComponent" /> <property name="policyComponent" ref="policyComponent" />
<property name="recordsManagementService" ref="RecordsManagementService" /> <property name="recordsManagementService" ref="RecordsManagementService" />
<property name="nodeService" ref="nodeService" /> <property name="nodeService" ref="nodeService" />
<property name="dictionaryService" ref="dictionaryService" />
</bean> </bean>
<!-- Records Management Audit Service --> <!-- Records Management Audit Service -->

View File

@@ -366,7 +366,10 @@ public abstract class RMActionExecuterAbstractBase extends ActionExecuterAbstra
* @param len Length to pad to * @param len Length to pad to
* *
* @return padded string or the original if already at >=len characters * @return padded string or the original if already at >=len characters
*
* @deprecated As of 2.1, replaced by {@link org.apache.commons.lang.StringUtils.leftPad}
*/ */
@Deprecated
protected String padString(String s, int len) protected String padString(String s, int len)
{ {
String result = s; String result = s;

View File

@@ -25,9 +25,11 @@ import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase;
import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.apache.commons.lang.StringUtils;
import org.springframework.extensions.surf.util.I18NUtil; import org.springframework.extensions.surf.util.I18NUtil;
/** /**
@@ -43,25 +45,36 @@ public class EditHoldReasonAction extends RMActionExecuterAbstractBase
/** Parameter names */ /** Parameter names */
public static final String PARAM_REASON = "reason"; public static final String PARAM_REASON = "reason";
/** Freeze Service */
private FreezeService freezeService;
/**
* Set freeze service
*
* @param freezeService freeze service
*/
public void setFreezeService(FreezeService freezeService)
{
this.freezeService = freezeService;
}
/** /**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/ */
@Override @Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef) protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{ {
QName nodeType = this.nodeService.getType(actionedUponNodeRef); if (freezeService.isHold(actionedUponNodeRef))
if (this.dictionaryService.isSubClass(nodeType, TYPE_HOLD) == true)
{ {
// Get the property values // Get the property values
String reason = (String) action.getParameterValue(PARAM_REASON); String reason = (String) action.getParameterValue(PARAM_REASON);
if (reason == null || reason.length() == 0) if (StringUtils.isBlank(reason))
{ {
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_HOLD_EDIT_REASON_NONE)); throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_HOLD_EDIT_REASON_NONE));
} }
// Set the hold reason // Update hold reason
nodeService.setProperty(actionedUponNodeRef, PROP_HOLD_REASON, reason); freezeService.updateReason(actionedUponNodeRef, reason);
} }
else else
{ {
@@ -115,5 +128,4 @@ public class EditHoldReasonAction extends RMActionExecuterAbstractBase
} }
} }
} }

View File

@@ -38,6 +38,7 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.apache.commons.lang.StringUtils;
/** /**
* Files a record into a particular record folder * Files a record into a particular record folder
@@ -79,7 +80,7 @@ public class FileAction extends RMActionExecuterAbstractBase
// Calculate the filed date and record identifier // Calculate the filed date and record identifier
String year = Integer.toString(fileCalendar.get(Calendar.YEAR)); String year = Integer.toString(fileCalendar.get(Calendar.YEAR));
QName nodeDbid = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-dbid"); QName nodeDbid = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-dbid");
String recordId = year + "-" + padString(recordProperties.get(nodeDbid).toString(), 10); String recordId = year + "-" + StringUtils.leftPad(recordProperties.get(nodeDbid).toString(), 10, "0");
recordProperties.put(RecordsManagementModel.PROP_IDENTIFIER, recordId); recordProperties.put(RecordsManagementModel.PROP_IDENTIFIER, recordId);
} }

View File

@@ -19,24 +19,16 @@
package org.alfresco.module.org_alfresco_module_rm.action.impl; package org.alfresco.module.org_alfresco_module_rm.action.impl;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil; import org.springframework.extensions.surf.util.I18NUtil;
/** /**
@@ -49,14 +41,21 @@ public class FreezeAction extends RMActionExecuterAbstractBase
private static final String MSG_FREEZE_NO_REASON = "rm.action.freeze-no-reason"; private static final String MSG_FREEZE_NO_REASON = "rm.action.freeze-no-reason";
private static final String MSG_FREEZE_ONLY_RECORDS_FOLDERS = "rm.action.freeze-only-records-folders"; private static final String MSG_FREEZE_ONLY_RECORDS_FOLDERS = "rm.action.freeze-only-records-folders";
/** Logger */
private static Log logger = LogFactory.getLog(FreezeAction.class);
/** Parameter names */ /** Parameter names */
public static final String PARAM_REASON = "reason"; public static final String PARAM_REASON = "reason";
/** Hold node reference key */ /** Freeze Service */
private static final String KEY_HOLD_NODEREF = "holdNodeRef"; private FreezeService freezeService;
/**
* Set freeze service
*
* @param freezeService freeze service
*/
public void setFreezeService(FreezeService freezeService)
{
this.freezeService = freezeService;
}
/** /**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
@@ -64,109 +63,12 @@ public class FreezeAction extends RMActionExecuterAbstractBase
@Override @Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef) protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{ {
final boolean isRecord = recordsManagementService.isRecord(actionedUponNodeRef); freezeService.freeze((String) action.getParameterValue(PARAM_REASON), actionedUponNodeRef);
final boolean isFolder = this.recordsManagementService.isRecordFolder(actionedUponNodeRef);
if (isRecord || isFolder)
{
// Get the property values
String reason = (String)action.getParameterValue(PARAM_REASON);
if (reason == null || reason.length() == 0)
{
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_FREEZE_NO_REASON));
}
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Freezing node ").append(actionedUponNodeRef);
if (isFolder)
{
msg.append(" (folder)");
}
msg.append(" with reason '").append(reason).append("'");
logger.debug(msg.toString());
}
// Get the root rm node
NodeRef root = this.recordsManagementService.getFilePlan(actionedUponNodeRef);
// Get the hold object
NodeRef holdNodeRef = (NodeRef)AlfrescoTransactionSupport.getResource(KEY_HOLD_NODEREF);
if (holdNodeRef == null)
{
// Calculate a transfer name
QName nodeDbid = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-dbid");
Long dbId = (Long)this.nodeService.getProperty(actionedUponNodeRef, nodeDbid);
String transferName = padString(dbId.toString(), 10);
// Create the hold object
Map<QName, Serializable> holdProps = new HashMap<QName, Serializable>(2);
holdProps.put(ContentModel.PROP_NAME, transferName);
holdProps.put(PROP_HOLD_REASON, reason);
final QName transferQName = QName.createQName(RM_URI, transferName);
holdNodeRef = this.nodeService.createNode(root,
ASSOC_HOLDS,
transferQName,
TYPE_HOLD,
holdProps).getChildRef();
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Created hold object ").append(holdNodeRef)
.append(" with transfer name ").append(transferQName);
logger.debug(msg.toString());
}
// Bind the hold node reference to the transaction
AlfrescoTransactionSupport.bindResource(KEY_HOLD_NODEREF, holdNodeRef);
}
// Link the record to the hold
this.nodeService.addChild( holdNodeRef,
actionedUponNodeRef,
ASSOC_FROZEN_RECORDS,
ASSOC_FROZEN_RECORDS);
// Apply the freeze aspect
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2);
props.put(PROP_FROZEN_AT, new Date());
props.put(PROP_FROZEN_BY, AuthenticationUtil.getFullyAuthenticatedUser());
this.nodeService.addAspect(actionedUponNodeRef, ASPECT_FROZEN, props);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Frozen aspect applied to ").append(actionedUponNodeRef);
logger.debug(msg.toString());
}
// Mark all the folders contents as frozen
if (isFolder)
{
List<NodeRef> records = this.recordsManagementService.getRecords(actionedUponNodeRef);
for (NodeRef record : records)
{
this.nodeService.addAspect(record, ASPECT_FROZEN, props);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Frozen aspect applied to ").append(record);
logger.debug(msg.toString());
}
}
}
}
else
{
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_FREEZE_ONLY_RECORDS_FOLDERS));
}
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#getProtectedAspects()
*/
@Override @Override
public Set<QName> getProtectedAspects() public Set<QName> getProtectedAspects()
{ {
@@ -175,6 +77,9 @@ public class FreezeAction extends RMActionExecuterAbstractBase
return qnames; return qnames;
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#getProtectedProperties()
*/
@Override @Override
public Set<QName> getProtectedProperties() public Set<QName> getProtectedProperties()
{ {
@@ -184,6 +89,9 @@ public class FreezeAction extends RMActionExecuterAbstractBase
return qnames; return qnames;
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#isExecutableImpl(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, boolean)
*/
@Override @Override
protected boolean isExecutableImpl(NodeRef filePlanComponent, Map<String, Serializable> parameters, boolean throwException) protected boolean isExecutableImpl(NodeRef filePlanComponent, Map<String, Serializable> parameters, boolean throwException)
{ {
@@ -221,5 +129,4 @@ public class FreezeAction extends RMActionExecuterAbstractBase
} }
} }
} }

View File

@@ -20,20 +20,15 @@ package org.alfresco.module.org_alfresco_module_rm.action.impl;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase;
import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.Action;
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.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil; import org.springframework.extensions.surf.util.I18NUtil;
/** /**
@@ -43,50 +38,31 @@ import org.springframework.extensions.surf.util.I18NUtil;
*/ */
public class RelinquishHoldAction extends RMActionExecuterAbstractBase public class RelinquishHoldAction extends RMActionExecuterAbstractBase
{ {
/** Logger */
private static Log logger = LogFactory.getLog(RelinquishHoldAction.class);
/** I18N */ /** I18N */
private static final String MSG_NOT_HOLD_TYPE = "rm.action.not-hold-type"; private static final String MSG_NOT_HOLD_TYPE = "rm.action.not-hold-type";
/** Freeze Service */
private FreezeService freezeService;
/**
* Set freeze service
*
* @param freezeService freeze service
*/
public void setFreezeService(FreezeService freezeService)
{
this.freezeService = freezeService;
}
/** /**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/ */
@Override @Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef) protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{ {
QName nodeType = this.nodeService.getType(actionedUponNodeRef); if (freezeService.isHold(actionedUponNodeRef))
if (this.dictionaryService.isSubClass(nodeType, TYPE_HOLD) == true)
{ {
final NodeRef holdBeingRelinquished = actionedUponNodeRef; freezeService.relinquish(actionedUponNodeRef);
List<ChildAssociationRef> frozenNodeAssocs = nodeService.getChildAssocs(holdBeingRelinquished, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Relinquishing hold ").append(holdBeingRelinquished)
.append(" which has ").append(frozenNodeAssocs.size()).append(" frozen node(s).");
logger.debug(msg.toString());
}
for (ChildAssociationRef assoc : frozenNodeAssocs)
{
final NodeRef nextFrozenNode = assoc.getChildRef();
// Remove the freeze if this is the only hold that references the node
removeFreeze(nextFrozenNode, holdBeingRelinquished);
}
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Deleting hold object ").append(holdBeingRelinquished)
.append(" with name ").append(nodeService.getProperty(holdBeingRelinquished, ContentModel.PROP_NAME));
logger.debug(msg.toString());
}
// Delete the hold node
this.nodeService.deleteNode(holdBeingRelinquished);
} }
else else
{ {
@@ -95,78 +71,8 @@ public class RelinquishHoldAction extends RMActionExecuterAbstractBase
} }
/** /**
* Removes a freeze from a node * @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#getProtectedAspects()
*
* @param nodeRef node reference
*/ */
private void removeFreeze(NodeRef nodeRef, NodeRef holdBeingRelinquished)
{
// We should only remove the frozen aspect if there are no other 'holds' in effect for this node.
// One complication to consider is that holds can be placed on records or on folders.
// Therefore if the nodeRef here is a record, we need to go up the containment hierarchy looking
// for holds at each level.
// Get all the holds and remove this node from them.
List<ChildAssociationRef> parentAssocs = this.nodeService.getParentAssocs(nodeRef, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
// If the nodeRef is a record, there could also be applicable holds as parents of the folder(s).
if (recordsManagementService.isRecord(nodeRef))
{
List<NodeRef> parentFolders = recordsManagementService.getRecordFolders(nodeRef);
for (NodeRef folder : parentFolders)
{
List<ChildAssociationRef> moreAssocs = nodeService.getParentAssocs(folder, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
parentAssocs.addAll(moreAssocs);
}
}
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removing freeze from ").append(nodeRef).append(" which has ")
.append(parentAssocs.size()).append(" holds");
logger.debug(msg.toString());
}
boolean otherHoldsAreInEffect = false;
for (ChildAssociationRef chAssRef : parentAssocs)
{
if (!chAssRef.getParentRef().equals(holdBeingRelinquished))
{
otherHoldsAreInEffect = true;
break;
}
}
if (!otherHoldsAreInEffect)
{
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removing frozen aspect from ").append(nodeRef);
logger.debug(msg.toString());
}
// Remove the aspect
this.nodeService.removeAspect(nodeRef, ASPECT_FROZEN);
}
// Remove the freezes on the child records as long as there is no other hold referencing them
if (this.recordsManagementService.isRecordFolder(nodeRef) == true)
{
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append(nodeRef).append(" is a record folder");
logger.debug(msg.toString());
}
for (NodeRef record : recordsManagementService.getRecords(nodeRef))
{
removeFreeze(record, holdBeingRelinquished);
}
}
}
@Override @Override
public Set<QName> getProtectedAspects() public Set<QName> getProtectedAspects()
{ {
@@ -175,6 +81,9 @@ public class RelinquishHoldAction extends RMActionExecuterAbstractBase
return qnames; return qnames;
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#isExecutableImpl(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, boolean)
*/
@Override @Override
protected boolean isExecutableImpl(NodeRef filePlanComponent, Map<String, Serializable> parameters, boolean throwException) protected boolean isExecutableImpl(NodeRef filePlanComponent, Map<String, Serializable> parameters, boolean throwException)
{ {
@@ -196,5 +105,4 @@ public class RelinquishHoldAction extends RMActionExecuterAbstractBase
} }
} }
} }

View File

@@ -37,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.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.apache.commons.lang.StringUtils;
import org.springframework.extensions.surf.util.I18NUtil; import org.springframework.extensions.surf.util.I18NUtil;
/** /**
@@ -111,7 +112,7 @@ public class TransferAction extends RMDispositionActionExecuterAbstractBase
// Calculate a transfer name // Calculate a transfer name
QName nodeDbid = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-dbid"); QName nodeDbid = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-dbid");
Long dbId = (Long)this.nodeService.getProperty(dispositionLifeCycleNodeRef, nodeDbid); Long dbId = (Long)this.nodeService.getProperty(dispositionLifeCycleNodeRef, nodeDbid);
String transferName = padString(dbId.toString(), 10); String transferName = StringUtils.leftPad(dbId.toString(), 10, "0");
// Create the transfer object // Create the transfer object
Map<QName, Serializable> transferProps = new HashMap<QName, Serializable>(2); Map<QName, Serializable> transferProps = new HashMap<QName, Serializable>(2);

View File

@@ -20,19 +20,14 @@ package org.alfresco.module.org_alfresco_module_rm.action.impl;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase;
import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.Action;
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.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/** /**
* Unfreeze Action * Unfreeze Action
@@ -41,107 +36,31 @@ import org.apache.commons.logging.LogFactory;
*/ */
public class UnfreezeAction extends RMActionExecuterAbstractBase public class UnfreezeAction extends RMActionExecuterAbstractBase
{ {
/** Logger */ /** Freeze Service */
private static Log logger = LogFactory.getLog(UnfreezeAction.class); private FreezeService freezeService;
/** /**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, * Set freeze service
* org.alfresco.service.cmr.repository.NodeRef) *
* @param freezeService freeze service
*/
public void setFreezeService(FreezeService freezeService)
{
this.freezeService = freezeService;
}
/**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/ */
@Override @Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef) protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{ {
if (this.nodeService.hasAspect(actionedUponNodeRef, ASPECT_FROZEN) == true) freezeService.unFreeze(actionedUponNodeRef);
{
final boolean isFolder = this.recordsManagementService.isRecordFolder(actionedUponNodeRef);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Unfreezing node ").append(actionedUponNodeRef);
if (isFolder)
{
msg.append(" (folder)");
}
logger.debug(msg.toString());
}
// Remove freeze from node
removeFreeze(actionedUponNodeRef);
// Remove freeze from records if a record folder
if (isFolder)
{
List<NodeRef> records = this.recordsManagementService.getRecords(actionedUponNodeRef);
for (NodeRef record : records)
{
removeFreeze(record);
}
}
}
} }
/** /**
* Removes a freeze from a node * @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#getProtectedAspects()
*
* @param nodeRef
* node reference
*/ */
private void removeFreeze(NodeRef nodeRef)
{
// Get all the holds and remove this node from them
List<ChildAssociationRef> assocs = this.nodeService.getParentAssocs(nodeRef, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removing freeze from node ").append(nodeRef)
.append("which has ").append(assocs.size()).append(" holds");
logger.debug(msg.toString());
}
for (ChildAssociationRef assoc : assocs)
{
// Remove the frozen node as a child
NodeRef holdNodeRef = assoc.getParentRef();
this.nodeService.removeChild(holdNodeRef, nodeRef);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removed frozen node from hold ").append(holdNodeRef);
logger.debug(msg.toString());
}
// Check to see if we should delete the hold
List<ChildAssociationRef> holdAssocs = this.nodeService.getChildAssocs(holdNodeRef, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
if (holdAssocs.size() == 0)
{
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Hold node ").append(holdNodeRef)
.append(" with name ").append(nodeService.getProperty(holdNodeRef, ContentModel.PROP_NAME))
.append(" has no frozen nodes. Hence deleting it.");
logger.debug(msg.toString());
}
// Delete the hold object
this.nodeService.deleteNode(holdNodeRef);
}
}
// Remove the aspect
this.nodeService.removeAspect(nodeRef, ASPECT_FROZEN);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removed frozen aspect from ").append(nodeRef);
logger.debug(msg.toString());
}
}
@Override @Override
public Set<QName> getProtectedAspects() public Set<QName> getProtectedAspects()
{ {
@@ -150,6 +69,9 @@ public class UnfreezeAction extends RMActionExecuterAbstractBase
return qnames; return qnames;
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#isExecutableImpl(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, boolean)
*/
@Override @Override
protected boolean isExecutableImpl(NodeRef filePlanComponent, Map<String, Serializable> parameters, boolean throwException) protected boolean isExecutableImpl(NodeRef filePlanComponent, Map<String, Serializable> parameters, boolean throwException)
{ {

View File

@@ -18,6 +18,9 @@
*/ */
package org.alfresco.module.org_alfresco_module_rm.freeze; package org.alfresco.module.org_alfresco_module_rm.freeze;
import java.util.Set;
import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Freeze Service Interface * Freeze Service Interface
@@ -39,7 +42,7 @@ public interface FreezeService
* @param nodeRef hold node reference * @param nodeRef hold node reference
* @return boolean true if hold, false otherwise * @return boolean true if hold, false otherwise
*/ */
// TODO boolean isHold(NodeRef nodeRef); boolean isHold(NodeRef nodeRef);
/** /**
* Indicates whether the passed node reference is frozen. * Indicates whether the passed node reference is frozen.
@@ -47,7 +50,7 @@ public interface FreezeService
* @param nodeRef node reference * @param nodeRef node reference
* @return boolean true if frozen, false otherwise * @return boolean true if frozen, false otherwise
*/ */
// TODO boolean isFrozen(NodeRef nodeRef); boolean isFrozen(NodeRef nodeRef);
/** /**
* Get the 'root' frozen node references in a hold. * Get the 'root' frozen node references in a hold.
@@ -55,7 +58,7 @@ public interface FreezeService
* @param hold hold node reference * @param hold hold node reference
* @return Set<NodeRef> frozen node references * @return Set<NodeRef> frozen node references
*/ */
// TODO Set<NodeRef> getFrozen(NodeRef hold); Set<NodeRef> getFrozen(NodeRef hold);
/** /**
* Freezes a node with the provided reason, creating a hold node reference. * Freezes a node with the provided reason, creating a hold node reference.
@@ -64,7 +67,7 @@ public interface FreezeService
* @param nodeRef node reference * @param nodeRef node reference
* @return NodeRef hold node reference * @return NodeRef hold node reference
*/ */
// TODO NodeRef freeze(String reason, NodeRef nodeRef); NodeRef freeze(String reason, NodeRef nodeRef);
/** /**
* Freezes a node, adding it an existing hold. * Freezes a node, adding it an existing hold.
@@ -72,24 +75,24 @@ public interface FreezeService
* @param hold hold node reference * @param hold hold node reference
* @param nodeRef node reference * @param nodeRef node reference
*/ */
// TODO void freeze(NodeRef hold, NodeRef nodeRef); void freeze(NodeRef hold, NodeRef nodeRef);
/** /**
* Freezes a collection of nodes with the given reason, creating a hold. * Freezes a collection of nodes with the given reason, creating a hold.
* *
* @param reason freeze reason * @param reason freeze reason
* @param Set<NodeRef> set of nodes to freeze * @param nodeRefs set of nodes to freeze
* @return NodeRef hold node reference * @return NodeRef hold node reference
*/ */
// TODO NodeRef freeze(String reason, Set<NodeRef> nodeRef); NodeRef freeze(String reason, Set<NodeRef> nodeRefs);
/** /**
* Freeze a collection of nodes, adding them to an existing hold. * Freeze a collection of nodes, adding them to an existing hold.
* *
* @param hold hold node reference * @param hold hold node reference
* @param nodeRef set of nodes to freeze * @param nodeRefs set of nodes to freeze
*/ */
// TODO void freeze(NodeRef hold, Set<NodeRef> nodeRef); void freeze(NodeRef hold, Set<NodeRef> nodeRefs);
/** /**
* Unfreeze a frozen node. * Unfreeze a frozen node.
@@ -99,7 +102,7 @@ public interface FreezeService
* *
* @param nodeRef node reference * @param nodeRef node reference
*/ */
// TODO void unFreeze(NodeRef nodeRef); void unFreeze(NodeRef nodeRef);
/** /**
* Unfreeze a collection of nodes. * Unfreeze a collection of nodes.
@@ -107,16 +110,16 @@ public interface FreezeService
* The unfrozen nodes are automatically removed from the hold(s) the are in. If the hold(s) is * The unfrozen nodes are automatically removed from the hold(s) the are in. If the hold(s) is
* subsequently empty, the hold is automatically deleted. * subsequently empty, the hold is automatically deleted.
* *
* @param Set<NodeRef> set of nodes to unfreeze * @param nodeRefs set of nodes to unfreeze
*/ */
// TODO void unFreeze(Set<NodeRef> nodeRef); void unFreeze(Set<NodeRef> nodeRefs);
/** /**
* Unfreezes all nodes within a hold and deletes the hold. * Unfreezes all nodes within a hold and deletes the hold.
* *
* @param hold hold node reference * @param hold hold node reference
*/ */
// TODO void relinquish(NodeRef hold); void relinquish(NodeRef hold);
/** /**
* Gets the freeze reason for a hold. * Gets the freeze reason for a hold.
@@ -124,7 +127,7 @@ public interface FreezeService
* @param hold hold node reference * @param hold hold node reference
* @return String freeze reason * @return String freeze reason
*/ */
// TODO String getReason(NodeRef hold); String getReason(NodeRef hold);
/** /**
* Updates the freeze reason for a given hold. * Updates the freeze reason for a given hold.
@@ -132,5 +135,5 @@ public interface FreezeService
* @param hold hold node reference * @param hold hold node reference
* @param reason updated reason * @param reason updated reason
*/ */
// TODO void updateReason(NodeRef hold, String reason); void updateReason(NodeRef hold, String reason);
} }

View File

@@ -18,20 +18,38 @@
*/ */
package org.alfresco.module.org_alfresco_module_rm.freeze; package org.alfresco.module.org_alfresco_module_rm.freeze;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent; 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;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.cmr.dictionary.DictionaryService;
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.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/** /**
* Freeze Service Implementation * Freeze Service Implementation
@@ -42,6 +60,16 @@ public class FreezeServiceImpl implements FreezeService,
RecordsManagementModel, RecordsManagementModel,
NodeServicePolicies.BeforeDeleteNodePolicy NodeServicePolicies.BeforeDeleteNodePolicy
{ {
/** Logger */
private static Log logger = LogFactory.getLog(FreezeServiceImpl.class);
/** I18N */
private static final String MSG_FREEZE_ONLY_RECORDS_FOLDERS = "rm.action.freeze-only-records-folders";
private static final String MSG_EMPTY_SET_OF_NODEREFS = "rm.action.empty-set-of-noderefs";
/** Hold node reference key */
private static final String KEY_HOLD_NODEREF = "holdNodeRef";
/** Policy Component */ /** Policy Component */
private PolicyComponent policyComponent; private PolicyComponent policyComponent;
@@ -51,6 +79,9 @@ public class FreezeServiceImpl implements FreezeService,
/** Records Management Service */ /** Records Management Service */
private RecordsManagementService recordsManagementService; private RecordsManagementService recordsManagementService;
/** Dictionary Service */
private DictionaryService dictionaryService;
/** /**
* @param policyComponent policy component * @param policyComponent policy component
*/ */
@@ -75,6 +106,14 @@ public class FreezeServiceImpl implements FreezeService,
this.recordsManagementService = recordsManagementService; this.recordsManagementService = recordsManagementService;
} }
/**
* @param dictionaryService dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/** /**
* Init service * Init service
*/ */
@@ -109,10 +148,9 @@ public class FreezeServiceImpl implements FreezeService,
// check children // check children
checkChildren(nodeService.getChildAssocs(nodeRef)); checkChildren(nodeService.getChildAssocs(nodeRef));
} }
return null; return null;
}}); }
});
} }
/** /**
@@ -139,4 +177,462 @@ public class FreezeServiceImpl implements FreezeService,
} }
} }
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#isHold(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public boolean isHold(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
return dictionaryService.isSubClass(nodeService.getType(nodeRef), TYPE_HOLD);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#isFrozen(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public boolean isFrozen(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
return nodeService.hasAspect(nodeRef, ASPECT_FROZEN);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getFrozen(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public Set<NodeRef> getFrozen(NodeRef hold)
{
ParameterCheck.mandatory("hold", hold);
Set<NodeRef> frozenNodes = new HashSet<NodeRef>();
List<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(hold, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
if (childAssocs != null && !childAssocs.isEmpty())
{
for (ChildAssociationRef childAssociationRef : childAssocs)
{
frozenNodes.add(childAssociationRef.getChildRef());
}
}
return frozenNodes;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#freeze(java.lang.String, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public NodeRef freeze(String reason, NodeRef nodeRef)
{
ParameterCheck.mandatoryString("reason", reason);
ParameterCheck.mandatory("nodeRef", nodeRef);
// Check if the actionedUponNodeRef is a valid file plan component
boolean isRecord = recordsManagementService.isRecord(nodeRef);
boolean isFolder = recordsManagementService.isRecordFolder(nodeRef);
if (!(isRecord || isFolder))
{
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_FREEZE_ONLY_RECORDS_FOLDERS));
}
// Log a message about freezing the node with the reason
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Freezing node '").append(nodeRef).append("'");
if (isFolder)
{
msg.append(" (folder)");
}
msg.append(" with reason '").append(reason).append("'.");
logger.debug(msg.toString());
}
// Create the hold object
NodeRef holdNodeRef = createHold(nodeRef, reason);
// Freeze the node and add it to the hold
freeze(holdNodeRef, nodeRef);
return holdNodeRef;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#freeze(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void freeze(NodeRef hold, NodeRef nodeRef)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("nodeRef", nodeRef);
// Link the record to the hold
nodeService.addChild(hold, nodeRef, ASSOC_FROZEN_RECORDS, ASSOC_FROZEN_RECORDS);
// Apply the freeze aspect
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2);
props.put(PROP_FROZEN_AT, new Date());
props.put(PROP_FROZEN_BY, AuthenticationUtil.getFullyAuthenticatedUser());
nodeService.addAspect(nodeRef, ASPECT_FROZEN, props);
// Log a message about applying the the frozen aspect
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Frozen aspect applied to '").append(nodeRef).append("'.");
logger.debug(msg.toString());
}
// Mark all the folders contents as frozen
if (recordsManagementService.isRecordFolder(nodeRef))
{
List<NodeRef> records = recordsManagementService.getRecords(nodeRef);
for (NodeRef record : records)
{
nodeService.addAspect(record, ASPECT_FROZEN, props);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Frozen aspect applied to '").append(record).append("'.");
logger.debug(msg.toString());
}
}
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#freeze(java.lang.String, java.util.Set)
*/
@Override
public NodeRef freeze(String reason, Set<NodeRef> nodeRefs)
{
ParameterCheck.mandatoryString("reason", reason);
ParameterCheck.mandatory("nodeRefs", nodeRefs);
if (nodeRefs.isEmpty())
{
throw new AlfrescoRuntimeException(MSG_EMPTY_SET_OF_NODEREFS);
}
// FIXME: Can we assume that the nodeRefs are in the same filePlan???
NodeRef nodeRef = nodeRefs.iterator().next();
NodeRef hold = createHold(nodeRef, reason);
freeze(hold, nodeRefs);
return hold;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#freeze(org.alfresco.service.cmr.repository.NodeRef, java.util.Set)
*/
@Override
public void freeze(NodeRef hold, Set<NodeRef> nodeRefs)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("nodeRefs", nodeRefs);
for (NodeRef nodeRef : nodeRefs)
{
freeze(hold, nodeRef);
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#unFreeze(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void unFreeze(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
if (nodeService.hasAspect(nodeRef, ASPECT_FROZEN))
{
boolean isRecordFolder = recordsManagementService.isRecordFolder(nodeRef);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Unfreezing node '").append(nodeRef).append("'");
if (isRecordFolder)
{
msg.append(" (folder)");
}
msg.append(".");
logger.debug(msg.toString());
}
// Remove freeze from node
removeFreeze(nodeRef);
// Remove freeze from records if a record folder
if (isRecordFolder)
{
List<NodeRef> records = recordsManagementService.getRecords(nodeRef);
for (NodeRef record : records)
{
removeFreeze(record);
}
}
}
else
{
StringBuilder msg = new StringBuilder();
msg.append("The node '").append(nodeRef).append("' was not frozen. So it cannot be unfrozen!");
logger.info(msg.toString());
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#unFreeze(java.util.Set)
*/
@Override
public void unFreeze(Set<NodeRef> nodeRefs)
{
ParameterCheck.mandatory("nodeRefs", nodeRefs);
for (NodeRef nodeRef : nodeRefs)
{
unFreeze(nodeRef);
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#relinquish(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void relinquish(NodeRef hold)
{
ParameterCheck.mandatory("hold", hold);
final NodeRef holdBeingRelinquished = hold;
List<ChildAssociationRef> frozenNodeAssocs = nodeService.getChildAssocs(holdBeingRelinquished, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Relinquishing hold ").append(holdBeingRelinquished)
.append(" which has ").append(frozenNodeAssocs.size()).append(" frozen node(s).");
logger.debug(msg.toString());
}
for (ChildAssociationRef assoc : frozenNodeAssocs)
{
final NodeRef nextFrozenNode = assoc.getChildRef();
// Remove the freeze if this is the only hold that references the node
removeFreeze(nextFrozenNode, holdBeingRelinquished);
}
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Deleting hold object ").append(holdBeingRelinquished)
.append(" with name ").append(nodeService.getProperty(holdBeingRelinquished, ContentModel.PROP_NAME));
logger.debug(msg.toString());
}
// Delete the hold node
this.nodeService.deleteNode(holdBeingRelinquished);
}
/**
* Removes a freeze from a node
*
* @param nodeRef node reference
*/
private void removeFreeze(NodeRef nodeRef, NodeRef holdBeingRelinquished)
{
// We should only remove the frozen aspect if there are no other 'holds' in effect for this node.
// One complication to consider is that holds can be placed on records or on folders.
// Therefore if the nodeRef here is a record, we need to go up the containment hierarchy looking
// for holds at each level.
// Get all the holds and remove this node from them.
List<ChildAssociationRef> parentAssocs = this.nodeService.getParentAssocs(nodeRef, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
// If the nodeRef is a record, there could also be applicable holds as parents of the folder(s).
if (recordsManagementService.isRecord(nodeRef))
{
List<NodeRef> parentFolders = recordsManagementService.getRecordFolders(nodeRef);
for (NodeRef folder : parentFolders)
{
List<ChildAssociationRef> moreAssocs = nodeService.getParentAssocs(folder, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
parentAssocs.addAll(moreAssocs);
}
}
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removing freeze from ").append(nodeRef).append(" which has ")
.append(parentAssocs.size()).append(" holds");
logger.debug(msg.toString());
}
boolean otherHoldsAreInEffect = false;
for (ChildAssociationRef chAssRef : parentAssocs)
{
if (!chAssRef.getParentRef().equals(holdBeingRelinquished))
{
otherHoldsAreInEffect = true;
break;
}
}
if (!otherHoldsAreInEffect)
{
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removing frozen aspect from ").append(nodeRef);
logger.debug(msg.toString());
}
// Remove the aspect
this.nodeService.removeAspect(nodeRef, ASPECT_FROZEN);
}
// Remove the freezes on the child records as long as there is no other hold referencing them
if (this.recordsManagementService.isRecordFolder(nodeRef) == true)
{
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append(nodeRef).append(" is a record folder");
logger.debug(msg.toString());
}
for (NodeRef record : recordsManagementService.getRecords(nodeRef))
{
removeFreeze(record, holdBeingRelinquished);
}
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getReason(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public String getReason(NodeRef hold)
{
ParameterCheck.mandatory("hold", hold);
return (String) nodeService.getProperty(hold, PROP_HOLD_REASON);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#updateReason(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
*/
@Override
public void updateReason(NodeRef hold, String reason)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatoryString("reason", reason);
nodeService.setProperty(hold, PROP_HOLD_REASON, reason);
}
/**
* Creates a hold using the given nodeRef and reason
*
* @param nodeRef the nodeRef which will be frozen
* @param reason the reason why the record will be frozen
* @return NodeRef of the created hold
*/
private NodeRef createHold(NodeRef nodeRef, String reason)
{
NodeRef holdNodeRef = null;
// Calculate a transfer name
QName nodeDbid = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-dbid");
Long dbId = (Long) nodeService.getProperty(nodeRef, nodeDbid);
String transferName = StringUtils.leftPad(dbId.toString(), 10, "0");
// Create the hold object
Map<QName, Serializable> holdProps = new HashMap<QName, Serializable>(2);
holdProps.put(ContentModel.PROP_NAME, transferName);
holdProps.put(PROP_HOLD_REASON, reason);
// Get the root rm node
NodeRef root = recordsManagementService.getFilePlan(nodeRef);
final QName transferQName = QName.createQName(RM_URI, transferName);
holdNodeRef = nodeService.createNode(root, ASSOC_HOLDS, transferQName, TYPE_HOLD, holdProps).getChildRef();
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Created hold object ").append(holdNodeRef)
.append(" with transfer name ").append(transferQName);
logger.debug(msg.toString());
}
// Bind the hold node reference to the transaction
AlfrescoTransactionSupport.bindResource(KEY_HOLD_NODEREF, holdNodeRef);
return holdNodeRef;
}
/**
* Removes a freeze from a node. The unfrozen node is automatically removed from the hold(s) it is in.
* If the hold is subsequently empty, the hold is automatically deleted.
*
* @param nodeRef node reference
*/
private void removeFreeze(NodeRef nodeRef)
{
// Get all the holds and remove this node from them
List<ChildAssociationRef> assocs = nodeService.getParentAssocs(nodeRef, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removing freeze from node '").append(nodeRef)
.append("' which has '").append(assocs.size()).append("' holds.");
logger.debug(msg.toString());
}
for (ChildAssociationRef assoc : assocs)
{
// Remove the frozen node as a child
NodeRef holdNodeRef = assoc.getParentRef();
nodeService.removeChild(holdNodeRef, nodeRef);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removed frozen node from hold '").append(holdNodeRef).append("'.");
logger.debug(msg.toString());
}
// Check to see if we should delete the hold
List<ChildAssociationRef> holdAssocs = nodeService.getChildAssocs(holdNodeRef, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
if (holdAssocs != null && holdAssocs.isEmpty())
{
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Hold node '").append(holdNodeRef)
.append("' with name '").append(nodeService.getProperty(holdNodeRef, ContentModel.PROP_NAME))
.append("' has no frozen nodes. Hence deleting it.");
logger.debug(msg.toString());
}
// Delete the hold object
nodeService.deleteNode(holdNodeRef);
}
}
// Remove the aspect
this.nodeService.removeAspect(nodeRef, ASPECT_FROZEN);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removed frozen aspect from ").append(nodeRef);
logger.debug(msg.toString());
}
}
} }