mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
RM-1039: Can't move folder to Category with disposition schedule.
* improve general reliability of record folder move * fix up some issues with the way composite capabilities where being evaluated * use capabilities to enforce conditions of move .. not behavior .. this improves the visibility of the move action in the UI * unit test * reproduced and fixed up UI issue .. was showing No Items red banner in a very specific edge case git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@56373 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -91,25 +91,35 @@ public class CompositeCapability extends DeclarativeCapability
|
||||
{
|
||||
int result = AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
|
||||
if (targetCapability != null)
|
||||
// Check we are dealing with a file plan component
|
||||
if (filePlanService.isFilePlanComponent(source) == true &&
|
||||
filePlanService.isFilePlanComponent(target) == true)
|
||||
{
|
||||
result = super.evaluate(source, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check each capability using 'OR' logic
|
||||
for (Capability capability : capabilities)
|
||||
// Check the kind of the object, the permissions and the conditions
|
||||
if (checkKinds(source) == true && checkPermissions(source) == true && checkConditions(source) == true)
|
||||
{
|
||||
int capabilityResult = capability.evaluate(source, target);
|
||||
if (capabilityResult != AccessDecisionVoter.ACCESS_DENIED)
|
||||
if (targetCapability != null)
|
||||
{
|
||||
result = AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
if (isUndetermined() == false && capabilityResult == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
{
|
||||
result = AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
break;
|
||||
result = targetCapability.evaluate(target);
|
||||
}
|
||||
|
||||
if (AccessDecisionVoter.ACCESS_DENIED != result)
|
||||
{
|
||||
// Check each capability using 'OR' logic
|
||||
for (Capability capability : capabilities)
|
||||
{
|
||||
result = capability.evaluate(source, target);
|
||||
if (result == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = AccessDecisionVoter.ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -327,14 +327,10 @@ public class DeclarativeCapability extends AbstractCapability
|
||||
@Override
|
||||
public int evaluate(NodeRef source, NodeRef target)
|
||||
{
|
||||
int result = AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
if (targetCapability != null)
|
||||
int result = evaluate(source);
|
||||
if (targetCapability != null && result != AccessDecisionVoter.ACCESS_DENIED)
|
||||
{
|
||||
result = evaluate(source);
|
||||
if (result != AccessDecisionVoter.ACCESS_DENIED)
|
||||
{
|
||||
result = targetCapability.evaluate(target);
|
||||
}
|
||||
result = targetCapability.evaluate(target);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -208,21 +208,34 @@ public class DispositionServiceImpl implements
|
||||
{
|
||||
if (nodeService.exists(nodeRef) == true)
|
||||
{
|
||||
// get this disposition instructions for the node
|
||||
DispositionSchedule di = getDispositionSchedule(nodeRef);
|
||||
if (di != null)
|
||||
{
|
||||
List<DispositionActionDefinition> dispositionActionDefinitions = di.getDispositionActionDefinitions();
|
||||
if (dispositionActionDefinitions.isEmpty() == false)
|
||||
{
|
||||
// get the first disposition action definition
|
||||
DispositionActionDefinition nextDispositionActionDefinition = dispositionActionDefinitions.get(0);
|
||||
|
||||
// initialise the details of the next disposition action
|
||||
initialiseDispositionAction(nodeRef, nextDispositionActionDefinition);
|
||||
}
|
||||
refreshDispositionAction(nodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method used to refresh the dispostion action details of the given node.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
*/
|
||||
public void refreshDispositionAction(NodeRef nodeRef)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
// get this disposition instructions for the node
|
||||
DispositionSchedule di = getDispositionSchedule(nodeRef);
|
||||
if (di != null)
|
||||
{
|
||||
List<DispositionActionDefinition> dispositionActionDefinitions = di.getDispositionActionDefinitions();
|
||||
if (dispositionActionDefinitions.isEmpty() == false)
|
||||
{
|
||||
// get the first disposition action definition
|
||||
DispositionActionDefinition nextDispositionActionDefinition = dispositionActionDefinitions.get(0);
|
||||
|
||||
// initialise the details of the next disposition action
|
||||
initialiseDispositionAction(nodeRef, nextDispositionActionDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** ========= Disposition Property Methods ========= */
|
||||
@@ -733,33 +746,37 @@ public class DispositionServiceImpl implements
|
||||
if (result == false)
|
||||
{
|
||||
DispositionAction da = new DispositionActionImpl(serviceRegistry, nextDa);
|
||||
boolean firstComplete = da.getDispositionActionDefinition().eligibleOnFirstCompleteEvent();
|
||||
|
||||
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(nextDa, ASSOC_EVENT_EXECUTIONS, RegexQNamePattern.MATCH_ALL);
|
||||
for (ChildAssociationRef assoc : assocs)
|
||||
DispositionActionDefinition dad = da.getDispositionActionDefinition();
|
||||
if (dad != null)
|
||||
{
|
||||
NodeRef eventExecution = assoc.getChildRef();
|
||||
Boolean isCompleteValue = (Boolean)this.nodeService.getProperty(eventExecution, PROP_EVENT_EXECUTION_COMPLETE);
|
||||
boolean isComplete = false;
|
||||
if (isCompleteValue != null)
|
||||
boolean firstComplete = dad.eligibleOnFirstCompleteEvent();
|
||||
|
||||
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(nextDa, ASSOC_EVENT_EXECUTIONS, RegexQNamePattern.MATCH_ALL);
|
||||
for (ChildAssociationRef assoc : assocs)
|
||||
{
|
||||
isComplete = isCompleteValue.booleanValue();
|
||||
|
||||
// implement AND and OR combination of event completions
|
||||
if (isComplete == true)
|
||||
NodeRef eventExecution = assoc.getChildRef();
|
||||
Boolean isCompleteValue = (Boolean)this.nodeService.getProperty(eventExecution, PROP_EVENT_EXECUTION_COMPLETE);
|
||||
boolean isComplete = false;
|
||||
if (isCompleteValue != null)
|
||||
{
|
||||
result = true;
|
||||
if (firstComplete == true)
|
||||
isComplete = isCompleteValue.booleanValue();
|
||||
|
||||
// implement AND and OR combination of event completions
|
||||
if (isComplete == true)
|
||||
{
|
||||
break;
|
||||
result = true;
|
||||
if (firstComplete == true)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
if (firstComplete == false)
|
||||
else
|
||||
{
|
||||
break;
|
||||
result = false;
|
||||
if (firstComplete == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,31 +25,36 @@ import java.util.Map;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionServiceImpl;
|
||||
import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService;
|
||||
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.RecordFolderServiceImpl;
|
||||
import org.alfresco.repo.copy.CopyBehaviourCallback;
|
||||
import org.alfresco.repo.copy.CopyDetails;
|
||||
import org.alfresco.repo.copy.DefaultCopyBehaviourCallback;
|
||||
import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback;
|
||||
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
|
||||
import org.alfresco.repo.policy.BehaviourFilter;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.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.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
/**
|
||||
* Class containing behaviour for the vitalRecordDefinition aspect.
|
||||
*
|
||||
* @author neilm
|
||||
*/
|
||||
public class RecordCopyBehaviours implements RecordsManagementModel
|
||||
public class RecordCopyBehaviours implements RecordsManagementModel,
|
||||
ApplicationContextAware
|
||||
{
|
||||
/** The policy component */
|
||||
private PolicyComponent policyComponent;
|
||||
@@ -63,6 +68,18 @@ public class RecordCopyBehaviours implements RecordsManagementModel
|
||||
/** List of aspects to remove during move and copy */
|
||||
private List<QName> unwantedAspects = new ArrayList<QName>(5);
|
||||
|
||||
/** Application context */
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the policy component
|
||||
*
|
||||
@@ -193,7 +210,7 @@ public class RecordCopyBehaviours implements RecordsManagementModel
|
||||
{
|
||||
if (!oldChildAssocRef.getParentRef().equals(newChildAssocRef.getParentRef()))
|
||||
{
|
||||
final NodeRef oldNodeRef = oldChildAssocRef.getChildRef();
|
||||
//final NodeRef oldNodeRef = oldChildAssocRef.getChildRef();
|
||||
final NodeRef newNodeRef = newChildAssocRef.getChildRef();
|
||||
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
@@ -201,26 +218,37 @@ public class RecordCopyBehaviours implements RecordsManagementModel
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
final RecordsManagementService rmService = rmServiceRegistry.getRecordsManagementService();
|
||||
final DispositionService rmDispositionService = rmServiceRegistry.getDispositionService();
|
||||
final RecordService rmRecordService = rmServiceRegistry.getRecordService();
|
||||
|
||||
if (rmDispositionService.getDispositionSchedule(oldNodeRef) != null || rmService.isCutoff(oldNodeRef))
|
||||
{
|
||||
throw new UnsupportedOperationException("Moving a record folder that has a disposition schedule or is cutoff is not suported.");
|
||||
}
|
||||
else
|
||||
final RecordFolderServiceImpl recordFolderService = (RecordFolderServiceImpl)applicationContext.getBean("recordFolderService");
|
||||
final DispositionServiceImpl dispositionService = (DispositionServiceImpl)applicationContext.getBean("dispositionService");
|
||||
|
||||
behaviourFilter.disableBehaviour();
|
||||
try
|
||||
{
|
||||
// Remove unwanted aspects
|
||||
removeUnwantedAspects(nodeService, newNodeRef);
|
||||
|
||||
|
||||
// reinitialise the record folder
|
||||
recordFolderService.initialiseRecordFolder(newNodeRef);
|
||||
|
||||
// reinitialise the record folder disposition action details
|
||||
dispositionService.refreshDispositionAction(newNodeRef);
|
||||
|
||||
// Sort out the child records
|
||||
for (NodeRef record : rmService.getRecords(newNodeRef))
|
||||
{
|
||||
// Remove unwanted aspects
|
||||
removeUnwantedAspects(nodeService, record);
|
||||
|
||||
// Re-initiate the records in the new folder.
|
||||
rmRecordService.file(record);
|
||||
}
|
||||
}
|
||||
|
||||
finally
|
||||
{
|
||||
behaviourFilter.enableBehaviour();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
@@ -428,5 +456,5 @@ public class RecordCopyBehaviours implements RecordsManagementModel
|
||||
result = "0" + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -891,7 +891,6 @@ public class RecordServiceImpl implements RecordService,
|
||||
@Override
|
||||
public void file(NodeRef record)
|
||||
{
|
||||
|
||||
ParameterCheck.mandatory("item", record);
|
||||
|
||||
// we only support filling of content items
|
||||
|
@@ -28,5 +28,5 @@ package org.alfresco.module.org_alfresco_module_rm.recordfolder;
|
||||
*/
|
||||
public interface RecordFolderService
|
||||
{
|
||||
|
||||
// TODO see RecordManagementService for Record Folder methods that need moving into this interface
|
||||
}
|
||||
|
Reference in New Issue
Block a user