diff --git a/config/alfresco/rule-services-context.xml b/config/alfresco/rule-services-context.xml index 5823c48478..8bb5509bfa 100644 --- a/config/alfresco/rule-services-context.xml +++ b/config/alfresco/rule-services-context.xml @@ -98,6 +98,12 @@ + + + {http://www.alfresco.org/model/system/1.0}noContent + {http://www.alfresco.org/model/system/1.0}temporary + + diff --git a/source/java/org/alfresco/repo/rule/ruletrigger/CreateNodeRuleTrigger.java b/source/java/org/alfresco/repo/rule/ruletrigger/CreateNodeRuleTrigger.java index 6bf75532dc..6e0dead3f5 100644 --- a/source/java/org/alfresco/repo/rule/ruletrigger/CreateNodeRuleTrigger.java +++ b/source/java/org/alfresco/repo/rule/ruletrigger/CreateNodeRuleTrigger.java @@ -96,16 +96,19 @@ public class CreateNodeRuleTrigger extends RuleTriggerAbstractBase new JavaBehaviour(this, POLICY)); } - // Register interest in the addition and removal of the sys:noContent aspect - this.policyComponent.bindClassBehaviour( - NodeServicePolicies.OnAddAspectPolicy.QNAME, - ContentModel.ASPECT_NO_CONTENT, - new JavaBehaviour(this, "onAddAspect", NotificationFrequency.EVERY_EVENT)); - this.policyComponent.bindClassBehaviour( - NodeServicePolicies.OnRemoveAspectPolicy.QNAME, - ContentModel.ASPECT_NO_CONTENT, - new JavaBehaviour(this, "onRemoveAspect", NotificationFrequency.EVERY_EVENT)); - } + for (QName ignoreAspect : getIgnoredAspects()) + { + // Register interest in the addition and removal of the sys:noContent aspect + this.policyComponent.bindClassBehaviour( + NodeServicePolicies.OnAddAspectPolicy.QNAME, + ignoreAspect, + new JavaBehaviour(this, "onAddAspect", NotificationFrequency.EVERY_EVENT)); + this.policyComponent.bindClassBehaviour( + NodeServicePolicies.OnRemoveAspectPolicy.QNAME, + ignoreAspect, + new JavaBehaviour(this, "onRemoveAspect", NotificationFrequency.EVERY_EVENT)); + } + } /** * {@inheritDoc} @@ -186,6 +189,10 @@ public class CreateNodeRuleTrigger extends RuleTriggerAbstractBase " (this was triggered on removal of the noContent aspect)"); } - triggerRules(parentNodeRef, nodeRef); + // Do not trigger rules for rule and action type nodes + if (ignoreTrigger(nodeRef) == false) + { + triggerRules(parentNodeRef, nodeRef); + } } } diff --git a/source/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerAbstractBase.java b/source/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerAbstractBase.java index 778f7f08b1..fb4f34f371 100644 --- a/source/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerAbstractBase.java +++ b/source/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerAbstractBase.java @@ -18,7 +18,9 @@ */ package org.alfresco.repo.rule.ruletrigger; +import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.alfresco.model.ContentModel; @@ -43,8 +45,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger { /** the types (hardcoded) to ignore generally */ private static final Set IGNORE_TYPES; - /** the aspects (hardcoded) to ignore generally */ - private static final Set IGNORE_ASPECTS; + static { IGNORE_TYPES = new HashSet(13); @@ -54,15 +55,13 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger // Workaround to prevent rules running on cm:rating nodes (which happened for 'liked' folders ALF-8308 & ALF-8382) IGNORE_TYPES.add(ContentModel.TYPE_RATING); IGNORE_TYPES.add(ContentModel.TYPE_SYSTEM_FOLDER); - - IGNORE_ASPECTS = new HashSet(13); - IGNORE_ASPECTS.add(ContentModel.ASPECT_TEMPORARY); } /** * A list of the rule types that are interested in this trigger */ private Set ruleTypes = new HashSet(); + private Set ignoredAspects = Collections.emptySet(); protected PolicyComponent policyComponent; protected NodeService nodeService; @@ -183,7 +182,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger * @param actionedUponNodeRef actioned upon node reference * @return boolean true if the trigger should be ignored, false otherwise */ - private boolean ignoreTrigger(NodeRef actionedUponNodeRef) + protected boolean ignoreTrigger(NodeRef actionedUponNodeRef) { boolean result = false; QName typeQName = nodeService.getType(actionedUponNodeRef); @@ -191,7 +190,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger { result = true; } - for (QName aspectToIgnore : IGNORE_ASPECTS) + for (QName aspectToIgnore : getIgnoredAspects()) { if (nodeService.hasAspect(actionedUponNodeRef, aspectToIgnore)) { @@ -200,4 +199,28 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger } return result; } + + public Set getIgnoredAspects() + { + return ignoredAspects; + } + + /** + * Converting String Aspects from Spring context to QNames + * + * @param ignoredAspects List of ignoredAspects + */ + public void setIgnoredAspectsStr(List ignoredAspects) + { + this.ignoredAspects = new HashSet<>(13); + + // MNT-9885 fix. + // Converts String Aspects to QNames and adds it to ignoredAspects. + // If afterDictionaryInit#DictionaryListener is used for setting up ignored Aspects from Spring context the + // registerRuleTrigger#CreateNodeRuleTrigger is initialized before afterDictionaryInit#DictionaryListener + for (String ignoredAspectStr : ignoredAspects) + { + this.ignoredAspects.add(QName.createQName(ignoredAspectStr)); + } + } } diff --git a/source/test-java/org/alfresco/repo/rule/RuleServiceImplTest.java b/source/test-java/org/alfresco/repo/rule/RuleServiceImplTest.java index 4a1b8c326c..6f3d5505c3 100644 --- a/source/test-java/org/alfresco/repo/rule/RuleServiceImplTest.java +++ b/source/test-java/org/alfresco/repo/rule/RuleServiceImplTest.java @@ -1340,4 +1340,78 @@ public class RuleServiceImplTest extends BaseRuleTest assertFalse("The folder should be deleted.", nodeService.exists(parentFolderNodeRef)); txn.commit(); } + + /** + * MNT-9885. Testing rule trigger after removing Temporary Aspect from the node. + * + * @throws Exception + */ + public void testRuleTriggerWithTemporaryFiles() throws Exception + { + UserTransaction txn = transactionService.getUserTransaction(); + txn.begin(); + + NodeRef parentNodeRef = this.nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, + QName.createQName("parentnode" + GUID.generate()), ContentModel.TYPE_FOLDER).getChildRef(); + + QName actionedQName = QName.createQName("actioneduponnode" + GUID.generate()); + // New child node + NodeRef actionedUponNodeRef = this.nodeService.createNode(parentNodeRef, ContentModel.ASSOC_CHILDREN, + actionedQName, ContentModel.TYPE_CONTENT).getChildRef(); + + // Add Temporary Aspect to the child Node + this.nodeService.addAspect(actionedUponNodeRef, ContentModel.ASPECT_TEMPORARY, null); + + // Write some content to the child node + ContentWriter writer = this.contentService.getWriter(actionedUponNodeRef, ContentModel.PROP_CONTENT, true); + writer.setMimetype("text/plain"); + writer.putContent("TestContent"); + + // Create rule for Versionable Aspect + Rule testRule = new Rule(); + testRule.setRuleTypes(Collections.singletonList(RuleType.INBOUND)); + testRule.setTitle("RuleServiceTest" + GUID.generate()); + testRule.setDescription(DESCRIPTION); + testRule.applyToChildren(true); + + Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME); + action.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE); + testRule.setAction(action); + + this.ruleService.saveRule(parentNodeRef, testRule); + assertNotNull("Rule was not saved", testRule.getNodeRef()); + + // Search rules + List rules = this.ruleService.getRules(parentNodeRef, true, testRule.getRuleTypes().get(0)); + assertNotNull("No rules found", rules); + assertTrue("Created rule is not found", new HashSet<>(rules).contains(testRule)); + + txn.commit(); + + // Remove Temporary Aspect from child node + txn = transactionService.getUserTransaction(); + txn.begin(); + + assertTrue("Node has Temporary aspect: ", this.nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_TEMPORARY)); + assertFalse("Node with Temporary aspect has versionable aspect: ", this.nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_VERSIONABLE)); + + // Removing Tempporary aspect + this.nodeService.removeAspect(actionedUponNodeRef, ContentModel.ASPECT_TEMPORARY); + + txn.commit(); + + // Add rule for parent Node + ((RuntimeRuleService) ruleService).addRulePendingExecution(parentNodeRef, actionedUponNodeRef, testRule); + ((RuntimeRuleService) ruleService).executePendingRules(); + + assertTrue("Pending rule was not executed", + this.nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_VERSIONABLE)); + assertFalse("Node has temporary aspect", + this.nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_TEMPORARY)); + assertTrue("Node has versionable aspect", + this.nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_VERSIONABLE)); + + this.nodeService.deleteNode(actionedUponNodeRef); + this.nodeService.deleteNode(parentNodeRef); + } }