Hold Service Improvements:

* HoldService API explanded beyound immediate use case needs to form a more complete API, plus some tweaks to method names
 * unit test (via Mockito) added .. still some todo's (see RM-1326)
 * integration test added .. to test behaviour interactions (see RM-1326)
 * method level permissions added to Hold service .. should see filtering of results based on permissions
 * added behaviour to HoldService to unfreeze records and record folders when hold is deleted (same as old relinquish action)
 * deprecation of dupliacte methods found in FreezeService
 * fix up use of deprecated methods throughout code .. note that warnings have only been hidden in actions that are soon to be deprecated too



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@64834 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-03-19 05:02:04 +00:00
parent e6f1c48f53
commit e0cdb0d2d0
30 changed files with 1495 additions and 894 deletions

View File

@@ -41,6 +41,7 @@ public class EditHoldReasonAction extends RMActionExecuterAbstractBase
/**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/
@SuppressWarnings("deprecation")
@Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{

View File

@@ -50,6 +50,7 @@ public class FreezeAction extends RMActionExecuterAbstractBase
/**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/
@SuppressWarnings("deprecation")
@Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{

View File

@@ -37,6 +37,7 @@ public class RelinquishHoldAction extends RMActionExecuterAbstractBase
/**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/
@SuppressWarnings("deprecation")
@Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{

View File

@@ -32,6 +32,7 @@ public class UnfreezeAction extends RMActionExecuterAbstractBase
/**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/
@SuppressWarnings("deprecation")
@Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{

View File

@@ -159,4 +159,8 @@ public interface RMPermissionModel
String MAP_CLASSIFICATION_GUIDE_METADATA = "MapClassificationGuideMetadata";
String MANAGE_ACCESS_CONTROLS = "ManageAccessControls";
final String CREATE_HOLD = "CreateHold";
final String ADD_TO_HOLD = "AddToHold";
final String REMOVE_FROM_HOLD = "RemoveFromHold";
}

View File

@@ -161,6 +161,10 @@ public class CreateCapability extends DeclarativeCapability
{
return AccessDecisionVoter.ACCESS_GRANTED;
}
if (capabilityService.getCapability(RMPermissionModel.ADD_TO_HOLD).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
{
return AccessDecisionVoter.ACCESS_GRANTED;
}
if (((ChangeOrDeleteReferencesCapability)capabilityService.getCapability(RMPermissionModel.CHANGE_OR_DELETE_REFERENCES)).evaluate(destination, linkee) == AccessDecisionVoter.ACCESS_GRANTED)
{
return AccessDecisionVoter.ACCESS_GRANTED;

View File

@@ -30,7 +30,6 @@ import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
@@ -157,14 +156,6 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
return (RecordFolderService)applicationContext.getBean("RecordFolderService");
}
/**
* @return freeze service
*/
protected FreezeService getFreezeService()
{
return (FreezeService)applicationContext.getBean("FreezeService");
}
/**
* @return transfer service
*/
@@ -218,7 +209,7 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
{
result = FilePlanComponentKind.HOLD_CONTAINER;
}
else if (getFreezeService().isHold(nodeRef))
else if (isHold(nodeRef))
{
result = FilePlanComponentKind.HOLD;
}

View File

@@ -1,260 +0,0 @@
/*
* Copyright (C) 2005-2014 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.fileplan.hold;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
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.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
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;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Hold service implementation
*
* @author Tuna Aksoy
* @since 2.2
*/
public class HoldServiceImpl implements HoldService, RecordsManagementModel
{
/** Logger */
private static Log logger = LogFactory.getLog(HoldServiceImpl.class);
/** File Plan Service */
private FilePlanService filePlanService;
/** Node Service */
private NodeService nodeService;
/** Record Service */
private RecordService recordService;
/** Record Folder Service */
private RecordFolderService recordFolderService;
/**
* Set the file plan service
*
* @param filePlanService the file plan service
*/
public void setFilePlanService(FilePlanService filePlanService)
{
this.filePlanService = filePlanService;
}
/**
* Set the node service
*
* @param nodeService the node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Set the record service
*
* @param recordService the record service
*/
public void setRecordService(RecordService recordService)
{
this.recordService = recordService;
}
/**
* Set the record folder service
*
* @param recordFolderService the record folder service
*/
public void setRecordFolderService(RecordFolderService recordFolderService)
{
this.recordFolderService = recordFolderService;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.fileplan.hold.HoldService#getHolds(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public List<NodeRef> getHolds(NodeRef filePlan)
{
ParameterCheck.mandatory("filePlan", filePlan);
NodeRef holdContainer = filePlanService.getHoldContainer(filePlan);
List<ChildAssociationRef> holdsAssocs = nodeService.getChildAssocs(holdContainer, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
List<NodeRef> holds = new ArrayList<NodeRef>(holdsAssocs.size());
for (ChildAssociationRef holdAssoc : holdsAssocs)
{
holds.add(holdAssoc.getChildRef());
}
return holds;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.fileplan.hold.HoldService#getHolds(org.alfresco.service.cmr.repository.NodeRef, boolean)
*/
@Override
public List<NodeRef> getHolds(NodeRef nodeRef, boolean includedInHold)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
List<NodeRef> result = new ArrayList<NodeRef>();
List<ChildAssociationRef> holdsAssocs = nodeService.getParentAssocs(nodeRef, ASSOC_FROZEN_RECORDS, ASSOC_FROZEN_RECORDS);
List<NodeRef> holdsNotIncludingNodeRef = new ArrayList<NodeRef>(holdsAssocs.size());
for (ChildAssociationRef holdAssoc : holdsAssocs)
{
holdsNotIncludingNodeRef.add(holdAssoc.getParentRef());
}
result.addAll(holdsNotIncludingNodeRef);
if (!includedInHold)
{
NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
List<NodeRef> allHolds = getHolds(filePlan);
@SuppressWarnings("unchecked")
List<NodeRef> holdsIncludingNodeRef = ListUtils.subtract(allHolds, holdsNotIncludingNodeRef);
result.clear();
result.addAll(holdsIncludingNodeRef);
}
return result;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.fileplan.hold.HoldService#addToHoldContainer(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void addToHoldContainer(NodeRef hold, NodeRef nodeRef)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("nodeRef", nodeRef);
List<NodeRef> holds = new ArrayList<NodeRef>(1);
holds.add(hold);
addToHoldContainers(Collections.unmodifiableList(holds), nodeRef);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.fileplan.hold.HoldService#addToHoldContainers(java.util.List, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void addToHoldContainers(List<NodeRef> holds, NodeRef nodeRef)
{
ParameterCheck.mandatoryCollection("holds", holds);
ParameterCheck.mandatory("nodeRef", nodeRef);
for (NodeRef hold : holds)
{
// Link the record to the hold
nodeService.addChild(hold, nodeRef, ASSOC_FROZEN_RECORDS, ASSOC_FROZEN_RECORDS);
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2);
// Apply the freeze aspect
props.put(PROP_FROZEN_AT, new Date());
props.put(PROP_FROZEN_BY, AuthenticationUtil.getFullyAuthenticatedUser());
if (!nodeService.hasAspect(nodeRef, ASPECT_FROZEN))
{
nodeService.addAspect(nodeRef, ASPECT_FROZEN, props);
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 (recordFolderService.isRecordFolder(nodeRef))
{
List<NodeRef> records = recordService.getRecords(nodeRef);
for (NodeRef record : records)
{
// no need to freeze if already frozen!
if (!nodeService.hasAspect(record, ASPECT_FROZEN))
{
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.fileplan.hold.HoldService#removeFromHoldContainer(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void removeFromHoldContainer(NodeRef hold, NodeRef nodeRef)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("nodeRef", nodeRef);
List<NodeRef> holds = new ArrayList<NodeRef>(1);
holds.add(hold);
removeFromHoldContainers(Collections.unmodifiableList(holds), nodeRef);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.fileplan.hold.HoldService#removeFromHoldContainers(java.util.List, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void removeFromHoldContainers(List<NodeRef> holds, NodeRef nodeRef)
{
ParameterCheck.mandatory("holds", holds);
ParameterCheck.mandatory("nodeRef", nodeRef);
for (NodeRef hold : holds)
{
nodeService.removeChild(hold, nodeRef);
}
List<NodeRef> holdList = getHolds(nodeRef, true);
if (holdList.size() == 0)
{
nodeService.removeAspect(nodeRef, ASPECT_FROZEN);
}
}
}

View File

@@ -21,160 +21,118 @@ package org.alfresco.module.org_alfresco_module_rm.freeze;
import java.util.Date;
import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.fileplan.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Freeze Service Interface
*
* TODO
* Implementation used to consolidate freeze behaviours in 2.0.
* When implementing consider application of freeze to 'any' node references, not just records and record folders.
* (Consider implications for security and capabilities)
*
* @author Roy Wetherall
* @since 2.0
*/
public interface FreezeService
{
/**
* Indicates whether the passed node reference is frozen.
*
* @param nodeRef node reference
* @return boolean true if frozen, false otherwise
*/
boolean isFrozen(NodeRef nodeRef);
/**
* Checks whether or not the given node has frozen children
*
* @param nodeRef The nodeRef for which will be checked if it has frozen children
* @return true if the given nodeRef has frozen children, false otherwise
*/
boolean hasFrozenChildren(NodeRef nodeRef);
/**
* Gets the date of the freeze for the given node, null if the node is not frozen
*
* @param nodeRef The nodeRef for which the date check will be performed
* @return Date The of the freeze or null
*/
Date getFreezeDate(NodeRef nodeRef);
/**
* Gets the initiator of the freeze for the given node, null if the node is not frozen
*
* @param nodeRef The nodeRef for which the initiator check will be performed
* @return String The initiator of the freeze or null
*/
String getFreezeInitiator(NodeRef nodeRef);
/**
* Indicates whether the passed node reference is a hold. A hold is a container for a group of frozen object and contains the freeze
* reason.
*
* @param nodeRef hold node reference
* @return boolean true if hold, false otherwise
* @deprecated as of 2.2, use {@link HoldService#isHold(NodeRef)} instead.
*/
boolean isHold(NodeRef nodeRef);
@Deprecated
boolean isHold(NodeRef nodeRef);
/**
* Indicates whether the passed node reference is frozen.
*
* @param nodeRef node reference
* @return boolean true if frozen, false otherwise
*/
boolean isFrozen(NodeRef nodeRef);
/**
* Get the 'root' frozen node references in a hold.
*
* @param hold hold node reference
* @return Set<NodeRef> frozen node references
* @deprecated as of 2.2, use {@link HoldService#getHeld(NodeRef)} instead.
*/
@Deprecated
Set<NodeRef> getFrozen(NodeRef hold);
/**
* Freezes a node with the provided reason, creating a hold node reference.
*
* @param reason freeze reason
* @param nodeRef node reference
* @return NodeRef hold node reference
* @deprecated as of 2.2, use {@link HoldService#createHold(NodeRef, String, String, String)} and {@link HoldService#addToHold(NodeRef, NodeRef)} instead.
*/
@Deprecated
NodeRef freeze(String reason, NodeRef nodeRef);
/**
* Freezes a node, adding it an existing hold.
*
* @param hold hold node reference
* @param nodeRef node reference
*
* @deprecated as of 2.2, use {@link HoldService#addToHoldContainer(NodeRef, NodeRef)} instead
* @deprecated as of 2.2, use {@link HoldService#addToHold(NodeRef, NodeRef)} instead.
*/
@Deprecated
void freeze(NodeRef hold, NodeRef nodeRef);
/**
* Freezes a collection of nodes with the given reason, creating a hold.
*
* @param reason freeze reason
* @param nodeRefs set of nodes to freeze
* @return NodeRef hold node reference
* @deprecated as of 2.2, use {@link HoldService#createHold(NodeRef, String, String, String)} and {@link HoldService#addToHold(NodeRef, List<NodeRef>)} instead.
*/
@Deprecated
NodeRef freeze(String reason, Set<NodeRef> nodeRefs);
/**
* Freeze a collection of nodes, adding them to an existing hold.
*
* @param hold hold node reference
* @param nodeRefs set of nodes to freeze
* @deprecated as of 2.2, use {@link HoldService#addToHold(NodeRef, List<NodeRef>)} instead.
*/
@Deprecated
void freeze(NodeRef hold, Set<NodeRef> nodeRefs);
/**
* Unfreeze a frozen node.
* <p>
* 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
* @deprecated as of 2.2, use {@link HoldService#removeFromHold(NodeRef, NodeRef)} instead.
*/
@Deprecated
void unFreeze(NodeRef nodeRef);
/**
* Unfreeze a collection of nodes.
* <p>
* 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.
*
* @param nodeRefs set of nodes to unfreeze
* @deprecated as of 2.2, use {@link HoldService#removeFromHolds(java.util.List, NodeRef)} instead.
*/
@Deprecated
void unFreeze(Set<NodeRef> nodeRefs);
/**
* Unfreezes all nodes within a hold and deletes the hold.
*
* @param hold hold node reference
* @deprecated as of 2.2, use {@link HoldService#deleteHold(NodeRef)} instead.
*/
@Deprecated
void relinquish(NodeRef hold);
/**
* Gets the freeze reason for a hold.
*
* @param hold hold node reference
* @return String freeze reason
* @deprecated as of 2.2, use {@link HoldService#getHoldReason(NodeRef)} instead.
*/
@Deprecated
String getReason(NodeRef hold);
/**
* Updates the freeze reason for a given hold.
*
* @param hold hold node reference
* @param reason updated reason
* @deprecated as of 2.2, use {@link HoldService#setHoldReason(NodeRef, String)} instead.
*/
@Deprecated
void updateReason(NodeRef hold, String reason);
/**
* Gets the hold node references for a given file plan
* or an empty set if there is not any hold node available
*
* @param filePlan file plan for which the hold nodes will be retrieved
* @return Set<NodeRef> hold node references
*
* @deprecated as of 2.2, use {@link HoldService#getHolds(NodeRef)} instead
* @deprecated as of 2.2, use {@link HoldService#getHolds(NodeRef)} instead.
*/
@Deprecated
Set<NodeRef> getHolds(NodeRef filePlan);
/**
* Checks whether or not the given node has frozen children
*
* @param nodeRef The nodeRef for which will be checked if it has frozen children
* @return true if the given nodeRef has frozen children, false otherwise
*/
boolean hasFrozenChildren(NodeRef nodeRef);
/**
* Gets the date of the freeze for the given node, null if the node is not frozen
*
* @param nodeRef The nodeRef for which the date check will be performed
* @return Date The of the freeze or null
*/
Date getFreezeDate(NodeRef nodeRef);
/**
* Gets the initiator of the freeze for the given node, null if the node is not frozen
*
* @param nodeRef The nodeRef for which the initiator check will be performed
* @return String The initiator of the freeze or null
*/
String getFreezeInitiator(NodeRef nodeRef);
}

View File

@@ -19,25 +19,21 @@
package org.alfresco.module.org_alfresco_module_rm.freeze;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
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.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.fileplan.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.lang.StringUtils;
@@ -57,15 +53,13 @@ public class FreezeServiceImpl extends ServiceBaseImpl
RecordsManagementModel
{
/** Logger */
@SuppressWarnings("unused")
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_FREEZE_ONLY_RECORDS_FOLDERS = "rm.action.freeze-only-records-folders";
private static final String MSG_HOLD_NAME = "rm.hold.name";
/** Hold node reference key */
private static final String KEY_HOLD_NODEREF = "holdNodeRef";
/** Record service */
protected RecordService recordService;
@@ -110,25 +104,6 @@ public class FreezeServiceImpl extends ServiceBaseImpl
this.holdService = holdService;
}
/**
* @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);
QName type = nodeService.getType(nodeRef);
if (nodeService.exists(nodeRef) && (TYPE_HOLD.equals(type)) || dictionaryService.isSubClass(type, TYPE_HOLD))
{
return true;
}
else
{
return false;
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#isFrozen(org.alfresco.service.cmr.repository.NodeRef)
*/
@@ -140,250 +115,6 @@ public class FreezeServiceImpl extends ServiceBaseImpl
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);
// FIXME: Should we consider only records and record folders or 'any'
// node references
// Check if the actionedUponNodeRef is a valid file plan component
boolean isRecord = recordService.isRecord(nodeRef);
boolean isFolder = recordFolderService.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);
holdService.addToHoldContainer(hold, nodeRef);
}
/**
* @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.mandatoryCollection("nodeRefs", 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.mandatoryCollection("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 = recordFolderService.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 = recordService.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.mandatoryCollection("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);
List<ChildAssociationRef> frozenNodeAssocs = nodeService.getChildAssocs(hold, ASSOC_FROZEN_RECORDS,
RegexQNamePattern.MATCH_ALL);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Relinquishing hold '").append(hold).append("' which has '").append(frozenNodeAssocs.size())
.append("' frozen node(s).");
logger.debug(msg.toString());
}
for (ChildAssociationRef assoc : frozenNodeAssocs)
{
// Remove the freeze if this is the only hold that references the
// node
removeFreeze(assoc.getChildRef(), hold);
}
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Deleting hold object '").append(hold).append("' with name '").append(
nodeService.getProperty(hold, ContentModel.PROP_NAME)).append("'.");
logger.debug(msg.toString());
}
// Delete the hold node
nodeService.deleteNode(hold);
}
/**
* @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);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getHold(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public Set<NodeRef> getHolds(NodeRef filePlan)
{
ParameterCheck.mandatory("filePlan", filePlan);
return new HashSet<NodeRef>(holdService.getHolds(filePlan));
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#hasFrozenChildren(org.alfresco.service.cmr.repository.NodeRef)
*/
@@ -403,8 +134,8 @@ public class FreezeServiceImpl extends ServiceBaseImpl
}
return false;
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getFreezeDate(org.alfresco.service.cmr.repository.NodeRef)
*/
@@ -438,10 +169,153 @@ public class FreezeServiceImpl extends ServiceBaseImpl
return null;
}
/**
* Deprecated Method Implementations
*/
/**
* Helper Methods
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getFrozen(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
@Deprecated
public Set<NodeRef> getFrozen(NodeRef hold)
{
return new HashSet<NodeRef>(holdService.getHeld(hold));
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#freeze(java.lang.String,
* org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
@Deprecated
public NodeRef freeze(String reason, NodeRef nodeRef)
{
NodeRef hold = createHold(nodeRef, reason);
holdService.addToHold(hold, nodeRef);
return hold;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#freeze(org.alfresco.service.cmr.repository.NodeRef,
* org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
@Deprecated
public void freeze(NodeRef hold, NodeRef nodeRef)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("nodeRef", nodeRef);
holdService.addToHold(hold, nodeRef);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#freeze(java.lang.String,
* java.util.Set)
*/
@Override
@Deprecated
public NodeRef freeze(String reason, Set<NodeRef> nodeRefs)
{
NodeRef hold = null;
if (!nodeRefs.isEmpty())
{
List<NodeRef> list = new ArrayList<NodeRef>(nodeRefs);
hold = createHold(list.get(0), reason);
holdService.addToHold(hold, list);
}
return hold;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#freeze(org.alfresco.service.cmr.repository.NodeRef,
* java.util.Set)
*/
@Override
@Deprecated
public void freeze(NodeRef hold, Set<NodeRef> nodeRefs)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatoryCollection("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
@Deprecated
public void unFreeze(NodeRef nodeRef)
{
List<NodeRef> holds = holdService.heldBy(nodeRef, true);
for (NodeRef hold : holds)
{
holdService.removeFromHold(hold, nodeRef);
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#unFreeze(java.util.Set)
*/
@Override
@Deprecated
public void unFreeze(Set<NodeRef> nodeRefs)
{
ParameterCheck.mandatoryCollection("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
@Deprecated
public void relinquish(NodeRef hold)
{
holdService.deleteHold(hold);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getReason(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
@Deprecated
public String getReason(NodeRef hold)
{
return holdService.getHoldReason(hold);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#updateReason(org.alfresco.service.cmr.repository.NodeRef,
* java.lang.String)
*/
@Override
@Deprecated
public void updateReason(NodeRef hold, String reason)
{
holdService.setHoldReason(hold, reason);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getHold(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public Set<NodeRef> getHolds(NodeRef filePlan)
{
ParameterCheck.mandatory("filePlan", filePlan);
return new HashSet<NodeRef>(holdService.getHolds(filePlan));
}
/**
* Creates a hold using the given nodeRef and reason
@@ -453,177 +327,14 @@ public class FreezeServiceImpl extends ServiceBaseImpl
private NodeRef createHold(NodeRef nodeRef, String reason)
{
// get the hold container
final NodeRef root = filePlanService.getFilePlan(nodeRef);
NodeRef holdContainer = filePlanService.getHoldContainer(root);
final NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
NodeRef holdContainer = filePlanService.getHoldContainer(filePlan);
// calculate the hold name
int nextCount = getNextCount(holdContainer);
String holdName = I18NUtil.getMessage(MSG_HOLD_NAME) + " " + StringUtils.leftPad(Integer.toString(nextCount), 10, "0");
// Create the properties for the hold object
Map<QName, Serializable> holdProps = new HashMap<QName, Serializable>(2);
holdProps.put(ContentModel.PROP_NAME, holdName);
holdProps.put(PROP_HOLD_REASON, reason);
// create the hold object
QName holdQName = QName.createQName(RM_URI, holdName);
final NodeRef holdNodeRef = nodeService.createNode(holdContainer, ContentModel.ASSOC_CONTAINS, holdQName, TYPE_HOLD, holdProps).getChildRef();
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Created hold object '").append(holdNodeRef).append("' with name '").append(holdQName).append("'.");
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 '").append(nodeRef).append("' 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
nodeService.removeAspect(nodeRef, ASPECT_FROZEN);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Removed frozen aspect from '").append(nodeRef).append("'.");
logger.debug(msg.toString());
}
}
/**
* Removes a freeze from a node from the given hold
*
* @param nodeRef node reference
* @param hold hold
*/
private void removeFreeze(NodeRef nodeRef, NodeRef hold)
{
// 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 = 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 (recordService.isRecord(nodeRef))
{
List<NodeRef> parentFolders = recordFolderService.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(hold))
{
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
nodeService.removeAspect(nodeRef, ASPECT_FROZEN);
}
// Remove the freezes on the child records as long as there is no other
// hold referencing them
if (recordFolderService.isRecordFolder(nodeRef))
{
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append(nodeRef).append(" is a record folder");
logger.debug(msg.toString());
}
for (NodeRef record : recordService.getRecords(nodeRef))
{
removeFreeze(record, hold);
}
}
}
// create hold
return holdService.createHold(filePlan, holdName, reason, null);
}
}

View File

@@ -16,7 +16,7 @@
* 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.fileplan.hold;
package org.alfresco.module.org_alfresco_module_rm.hold;
import java.util.List;
@@ -30,6 +30,15 @@ import org.alfresco.service.cmr.repository.NodeRef;
*/
public interface HoldService
{
/**
* Indicates whether the passed node reference is a hold. A hold is a container for a group of frozen object and contains the freeze
* reason.
*
* @param nodeRef hold node reference
* @return boolean true if hold, false otherwise
*/
boolean isHold(NodeRef nodeRef);
/**
* Gets the list of all the holds within the holds container in the given file plan
*
@@ -38,6 +47,13 @@ public interface HoldService
*/
List<NodeRef> getHolds(NodeRef filePlan);
/**
*
* @param name
* @return
*/
NodeRef getHold(NodeRef filePlan, String name);
/**
* Gets the list of all the holds within the holds container for the given node reference
*
@@ -46,15 +62,59 @@ public interface HoldService
* <code>false</code> to get a list of node references which will not have the given node reference
* @return List of hold node references
*/
List<NodeRef> getHolds(NodeRef nodeRef, boolean includedInHold);
List<NodeRef> heldBy(NodeRef nodeRef, boolean includedInHold);
/**
*
* @param ndoeRef
* @return
*/
List<NodeRef> getHeld(NodeRef hold);
/**
*
* @param filePlan
* @param name
* @param reason
* @param description
* @return
*/
NodeRef createHold(NodeRef filePlan, String name, String reason, String description);
/**
*
* @param hold
* @return
*/
String getHoldReason(NodeRef hold);
/**
*
* @param hold
* @param reason
*/
void setHoldReason(NodeRef hold, String reason);
/**
*
* @param hold
*/
void deleteHold(NodeRef hold);
/**
* Adds the record to the given hold
*
* @param hold The {@link NodeRef} of the hold
* @param nodeRef The {@link NodeRef} of the record / record folder which will be added to the given hold
*/
void addToHoldContainer(NodeRef hold, NodeRef nodeRef);
void addToHold(NodeRef hold, NodeRef nodeRef);
/**
*
* @param hold
* @param nodeRefs
*/
void addToHold(NodeRef hold, List<NodeRef> nodeRefs);
/**
* Adds the record to the given list of holds
@@ -62,7 +122,7 @@ public interface HoldService
* @param holds The list of {@link NodeRef}s of the holds
* @param nodeRef The {@link NodeRef} of the record / record folder which will be added to the given holds
*/
void addToHoldContainers(List<NodeRef> holds, NodeRef nodeRef);
void addToHolds(List<NodeRef> holds, NodeRef nodeRef);
/**
* Removes the record from the given hold
@@ -70,7 +130,14 @@ public interface HoldService
* @param hold The {@link NodeRef} of the hold
* @param nodeRef The {@link NodeRef} of the record / record folder which will be removed from the given hold
*/
void removeFromHoldContainer(NodeRef hold, NodeRef nodeRef);
void removeFromHold(NodeRef hold, NodeRef nodeRef);
/**
*
* @param hold
* @param nodeRefs
*/
void removeFromHold(NodeRef hold, List<NodeRef> nodeRefs);
/**
* Removes the record from the given list of hold
@@ -78,5 +145,17 @@ public interface HoldService
* @param holds The list {@link NodeRef}s of the holds
* @param nodeRef The {@link NodeRef} of the record / record folder which will be removed from the given holds
*/
void removeFromHoldContainers(List<NodeRef> holds, NodeRef nodeRef);
void removeFromHolds(List<NodeRef> holds, NodeRef nodeRef);
/**
*
* @param nodeRef
*/
void removeFromAllHolds(NodeRef nodeRef);
/**
*
* @param nodeRefs
*/
void removeFromAllHolds(List<NodeRef> nodeRefs);
}

View File

@@ -0,0 +1,558 @@
/*
* Copyright (C) 2005-2014 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.hold;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
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.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
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.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Hold service implementation
*
* @author Tuna Aksoy
* @since 2.2
*/
@BehaviourBean
public class HoldServiceImpl extends ServiceBaseImpl
implements HoldService,
NodeServicePolicies.BeforeDeleteNodePolicy,
RecordsManagementModel
{
/** Logger */
private static Log logger = LogFactory.getLog(HoldServiceImpl.class);
/** File Plan Service */
private FilePlanService filePlanService;
/** Record Service */
private RecordService recordService;
/** Record folder service */
private RecordFolderService recordFolderService;
/**
* Set the file plan service
*
* @param filePlanService the file plan service
*/
public void setFilePlanService(FilePlanService filePlanService)
{
this.filePlanService = filePlanService;
}
/**
* Set the node service
*
* @param nodeService the node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Set the record service
*
* @param recordService the record service
*/
public void setRecordService(RecordService recordService)
{
this.recordService = recordService;
}
/**
* Set the record folder service
*
* @param recordFolderService the record folder service
*/
public void setRecordFolderService(RecordFolderService recordFolderService)
{
this.recordFolderService = recordFolderService;
}
/**
* Behaviour unfreezes node's that will no longer he held after delete.
*
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
*/
@Behaviour(kind=BehaviourKind.CLASS, type="rma:hold", notificationFrequency=NotificationFrequency.EVERY_EVENT)
@Override
public void beforeDeleteNode(final NodeRef hold)
{
if (nodeService.exists(hold) && isHold(hold))
{
RunAsWork<Void> work = new RunAsWork<Void>()
{
@Override
public Void doWork()
{
List<NodeRef> frozenNodes = getHeld(hold);
for (NodeRef frozenNode : frozenNodes)
{
List<NodeRef> otherHolds = heldBy(frozenNode, true);
if (otherHolds.size() == 1)
{
// remove the freeze aspect from the node
nodeService.removeAspect(frozenNode, ASPECT_FROZEN);
if (isRecordFolder(frozenNode))
{
List<NodeRef> records = recordService.getRecords(frozenNode);
for (NodeRef record : records)
{
if (nodeService.hasAspect(record, ASPECT_FROZEN))
{
List<NodeRef> recordsOtherHolds = heldBy(record, true);
if (recordsOtherHolds.size() == 1)
{
// remove the freeze aspect from the node
nodeService.removeAspect(record, ASPECT_FROZEN);
}
}
}
}
}
}
return null;
}
};
// run as system user
runAsSystem(work);
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#getHolds(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public List<NodeRef> getHolds(NodeRef filePlan)
{
ParameterCheck.mandatory("filePlan", filePlan);
// get the root hold container
NodeRef holdContainer = filePlanService.getHoldContainer(filePlan);
// get the children of the root hold container
List<ChildAssociationRef> holdsAssocs = nodeService.getChildAssocs(holdContainer, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
List<NodeRef> holds = new ArrayList<NodeRef>(holdsAssocs.size());
for (ChildAssociationRef holdAssoc : holdsAssocs)
{
NodeRef hold = holdAssoc.getChildRef();
if (isHold(hold))
{
// add to list of holds
holds.add(hold);
}
}
return holds;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#heldBy(org.alfresco.service.cmr.repository.NodeRef, boolean)
*/
@SuppressWarnings("unchecked")
@Override
public List<NodeRef> heldBy(NodeRef nodeRef, boolean includedInHold)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
List<NodeRef> result = null;
// get all the immediate parent holds
Set<NodeRef> holdsNotIncludingNodeRef = getParentHolds(nodeRef);
// check whether the record is held by vitue of it's record folder
if (isRecord(nodeRef))
{
List<NodeRef> recordFolders = recordFolderService.getRecordFolders(nodeRef);
for (NodeRef recordFolder : recordFolders)
{
holdsNotIncludingNodeRef.addAll(getParentHolds(recordFolder));
}
}
if (!includedInHold)
{
// invert list to get list of holds that do not contain this node
NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
List<NodeRef> allHolds = getHolds(filePlan);
result = ListUtils.subtract(allHolds, new ArrayList<NodeRef>(holdsNotIncludingNodeRef));
}
else
{
result = new ArrayList<NodeRef>(holdsNotIncludingNodeRef);
}
return result;
}
/**
* Helper method to get holds that are direct parents of the given node.
*
* @param nodeRef node reference
* @return Set<{@link NodeRef}> set of parent holds
*/
private Set<NodeRef> getParentHolds(NodeRef nodeRef)
{
List<ChildAssociationRef> holdsAssocs = nodeService.getParentAssocs(nodeRef, ASSOC_FROZEN_RECORDS, ASSOC_FROZEN_RECORDS);
Set<NodeRef> holds = new HashSet<NodeRef>(holdsAssocs.size());
for (ChildAssociationRef holdAssoc : holdsAssocs)
{
holds.add(holdAssoc.getParentRef());
}
return holds;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#getHold(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
*/
@Override
public NodeRef getHold(NodeRef filePlan, String name)
{
ParameterCheck.mandatory("filePlan", filePlan);
ParameterCheck.mandatory("name", name);
// get the root hold container
NodeRef holdContainer = filePlanService.getHoldContainer(filePlan);
// get the hold by name
NodeRef hold = nodeService.getChildByName(holdContainer, ContentModel.ASSOC_CONTAINS, name);
if (hold != null && !isHold(hold))
{
throw new AlfrescoRuntimeException("Can not get hold, because the named node reference isn't a hold.");
}
return hold;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#getHeld(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public List<NodeRef> getHeld(NodeRef hold)
{
ParameterCheck.mandatory("hold", hold);
List<NodeRef> children = new ArrayList<NodeRef>();
if (nodeService.exists(hold) && isHold(hold))
{
List<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(hold, ASSOC_FROZEN_RECORDS, RegexQNamePattern.MATCH_ALL);
if (childAssocs != null && !childAssocs.isEmpty())
{
for (ChildAssociationRef childAssociationRef : childAssocs)
{
children.add(childAssociationRef.getChildRef());
}
}
}
return children;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#createHold(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public NodeRef createHold(NodeRef filePlan, String name, String reason, String description)
{
ParameterCheck.mandatory("filePlan", filePlan);
ParameterCheck.mandatory("name", name);
ParameterCheck.mandatory("reason", reason);
// get the root hold container
NodeRef holdContainer = filePlanService.getHoldContainer(filePlan);
// create map of properties
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(3);
properties.put(ContentModel.PROP_NAME, name);
properties.put(PROP_HOLD_REASON, reason);
if (description != null && !description.isEmpty())
{
properties.put(ContentModel.PROP_DESCRIPTION, description);
}
// create assoc name
QName assocName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name);
// create hold
ChildAssociationRef childAssocRef = nodeService.createNode(holdContainer, ContentModel.ASSOC_CONTAINS, assocName, TYPE_HOLD, properties);
return childAssocRef.getChildRef();
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#getHoldReason(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public String getHoldReason(NodeRef hold)
{
ParameterCheck.mandatory("hold", hold);
String reason = null;
if (nodeService.exists(hold) && isHold(hold))
{
// get the reason
reason = (String)nodeService.getProperty(hold, PROP_HOLD_REASON);
}
return reason;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#setHoldReason(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
*/
@Override
public void setHoldReason(NodeRef hold, String reason)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("reason", reason);
if (nodeService.exists(hold) && isHold(hold))
{
nodeService.setProperty(hold, PROP_HOLD_REASON, reason);
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#deleteHold(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void deleteHold(NodeRef hold)
{
ParameterCheck.mandatory("hold", hold);
if (nodeService.exists(hold) && isHold(hold))
{
// delete the hold node
nodeService.deleteNode(hold);
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#addToHold(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void addToHold(NodeRef hold, NodeRef nodeRef)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("nodeRef", nodeRef);
List<NodeRef> holds = new ArrayList<NodeRef>(1);
holds.add(hold);
addToHolds(Collections.unmodifiableList(holds), nodeRef);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#addToHold(org.alfresco.service.cmr.repository.NodeRef, java.util.List)
*/
@Override
public void addToHold(NodeRef hold, List<NodeRef> nodeRefs)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("nodeRefs", nodeRefs);
for (NodeRef nodeRef : nodeRefs)
{
addToHold(hold, nodeRef);
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#addToHolds(java.util.List, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void addToHolds(List<NodeRef> holds, NodeRef nodeRef)
{
ParameterCheck.mandatoryCollection("holds", holds);
ParameterCheck.mandatory("nodeRef", nodeRef);
for (NodeRef hold : holds)
{
// Link the record to the hold
nodeService.addChild(hold, nodeRef, ASSOC_FROZEN_RECORDS, ASSOC_FROZEN_RECORDS);
// gather freeze properties
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2);
props.put(PROP_FROZEN_AT, new Date());
props.put(PROP_FROZEN_BY, AuthenticationUtil.getFullyAuthenticatedUser());
if (!nodeService.hasAspect(nodeRef, ASPECT_FROZEN))
{
// add freeze aspect
nodeService.addAspect(nodeRef, ASPECT_FROZEN, props);
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 (isRecordFolder(nodeRef))
{
List<NodeRef> records = recordService.getRecords(nodeRef);
for (NodeRef record : records)
{
// no need to freeze if already frozen!
if (!nodeService.hasAspect(record, ASPECT_FROZEN))
{
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.hold.HoldService#removeFromHold(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void removeFromHold(NodeRef hold, NodeRef nodeRef)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("nodeRef", nodeRef);
List<NodeRef> holds = new ArrayList<NodeRef>(1);
holds.add(hold);
removeFromHolds(Collections.unmodifiableList(holds), nodeRef);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#removeFromHold(org.alfresco.service.cmr.repository.NodeRef, java.util.List)
*/
@Override
public void removeFromHold(NodeRef hold, List<NodeRef> nodeRefs)
{
ParameterCheck.mandatory("hold", hold);
ParameterCheck.mandatory("nodeRefs", nodeRefs);
for (NodeRef nodeRef : nodeRefs)
{
removeFromHold(hold, nodeRef);
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#removeFromHolds(java.util.List, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void removeFromHolds(List<NodeRef> holds, final NodeRef nodeRef)
{
ParameterCheck.mandatory("holds", holds);
ParameterCheck.mandatory("nodeRef", nodeRef);
for (NodeRef hold : holds)
{
nodeService.removeChild(hold, nodeRef);
}
// check to see if this node can be unfrozen
List<NodeRef> holdList = heldBy(nodeRef, true);
if (holdList.size() == 0)
{
// run as system as we can't be sure if have remove aspect rights on node
runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork()
{
// remove frozen aspect
nodeService.removeAspect(nodeRef, ASPECT_FROZEN);
return null;
}
});
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#removeFromAllHolds(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void removeFromAllHolds(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
// remove the node from all the holds it's held by
List<NodeRef> holds = heldBy(nodeRef, true);
for (NodeRef hold : holds)
{
// remove node from hold
removeFromHold(hold, nodeRef);
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#removeFromAllHolds(java.util.List)
*/
@Override
public void removeFromAllHolds(List<NodeRef> nodeRefs)
{
ParameterCheck.mandatory("nodeRefs", nodeRefs);
for (NodeRef nodeRef : nodeRefs)
{
removeFromAllHolds(nodeRef);
}
}
}

View File

@@ -50,8 +50,7 @@ import org.springframework.extensions.surf.util.I18NUtil;
*/
public class RecordFolderServiceImpl extends ServiceBaseImpl
implements RecordFolderService,
RecordsManagementModel//,
//NodeServicePolicies.OnCreateChildAssociationPolicy
RecordsManagementModel
{
/** Logger */
private static Log logger = LogFactory.getLog(RecordFolderServiceImpl.class);
@@ -113,16 +112,6 @@ public class RecordFolderServiceImpl extends ServiceBaseImpl
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService#isRecordFolder(NodeRef)
*/
@Override
public boolean isRecordFolder(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
return instanceOf(nodeRef, TYPE_RECORD_FOLDER);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService#isRecordFolderDeclared(NodeRef)
*/

View File

@@ -24,7 +24,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.fileplan.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.json.JSONArray;
import org.json.JSONException;

View File

@@ -36,6 +36,6 @@ public class HoldPost extends BaseHold
@Override
void doAction(List<NodeRef> holds, NodeRef nodeRef)
{
getHoldService().addToHoldContainers(holds, nodeRef);
getHoldService().addToHolds(holds, nodeRef);
}
}

View File

@@ -36,6 +36,6 @@ public class HoldPut extends BaseHold
@Override
void doAction(List<NodeRef> holds, NodeRef nodeRef)
{
getHoldService().removeFromHoldContainers(holds, nodeRef);
getHoldService().removeFromHolds(holds, nodeRef);
}
}

View File

@@ -27,7 +27,7 @@ import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.fileplan.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
@@ -102,7 +102,7 @@ public class HoldsGet extends DeclarativeWebScript
else
{
boolean includedInHold = getIncludedInHold(req);
holds.addAll(holdService.getHolds(itemNodeRef, includedInHold));
holds.addAll(holdService.heldBy(itemNodeRef, includedInHold));
}
List<Hold> holdObjects = new ArrayList<Hold>(holds.size());

View File

@@ -20,6 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.util;
import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
@@ -60,6 +61,20 @@ public class ServiceBaseImpl implements RecordsManagementModel
{
this.dictionaryService = dictionaryService;
}
/**
* Indicates whether the given node is a record folder or not.
* <p>
* Exposed in the RecordFolder service.
*
* @param nodeRef node reference
* @return boolean true if record folder, false otherwise
*/
public boolean isRecordFolder(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
return instanceOf(nodeRef, TYPE_RECORD_FOLDER);
}
/**
* Indicates whether the given node reference is a record or not.
@@ -73,6 +88,28 @@ public class ServiceBaseImpl implements RecordsManagementModel
return nodeService.hasAspect(nodeRef, ASPECT_RECORD);
}
/**
* Indicates whether the given node reference is a hold or not.
* <p>
* Exposed publically in the {@link HoldService}
*
* @param nodeRef node reference
* @return boolean true if rma:hold or sub-type, false otherwise
*/
public boolean isHold(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
if (nodeService.exists(nodeRef) && instanceOf(nodeRef, TYPE_HOLD))
{
return true;
}
else
{
return false;
}
}
/**
* Gets the file plan that a given file plan component resides within.
@@ -185,4 +222,30 @@ public class ServiceBaseImpl implements RecordsManagementModel
result.add(nodeService.getType(nodeRef));
return result;
}
/**
* Helper method that executed work as system user.
* <p>
* Useful when testing using mocks.
*
* @param runAsWork work to execute as system user
* @return
*/
public <R> R runAsSystem(RunAsWork<R> runAsWork)
{
return AuthenticationUtil.runAsSystem(runAsWork);
}
/**
* Helper method that executed work as given user.
* <p>
* Useful when testing using mocks.
*
* @param runAsWork work to execute as given user
* @return
*/
public <R> R runAs(RunAsWork<R> runAsWork, String uid)
{
return AuthenticationUtil.runAs(runAsWork, uid);
}
}