mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-BUG-FIX (5.1/Cloud) to HEAD (5.1/Cloud)
90837: Merged V4.2-BUG-FIX (4.2.5) to HEAD-BUG-FIX (5.0/Cloud) 90751: Merged V4.2.4 (4.2.4) to V4.2-BUG-FIX (4.2.5) 90739: Merged DEV to PATCHES/V4.2.4 (4.2.4) 60205: MNT-9885: Rules not firing on some content saved in Alfresco drive - Incorrect RuleTrigger behavior is fixed. Rules that were ignored for content with sys:temporary aspect are now fired when this aspect is removed. - Required Unit tests were added. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@94724 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -98,6 +98,12 @@
|
|||||||
<property name="authenticationComponent" ref="authenticationComponent"/>
|
<property name="authenticationComponent" ref="authenticationComponent"/>
|
||||||
<property name="dictionaryService" ref="dictionaryService"/>
|
<property name="dictionaryService" ref="dictionaryService"/>
|
||||||
<property name="ruleService" ref="ruleService"/>
|
<property name="ruleService" ref="ruleService"/>
|
||||||
|
<property name="ignoredAspectsStr">
|
||||||
|
<list>
|
||||||
|
<value>{http://www.alfresco.org/model/system/1.0}noContent</value>
|
||||||
|
<value>{http://www.alfresco.org/model/system/1.0}temporary</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="on-create-node-trigger" class="org.alfresco.repo.rule.ruletrigger.CreateNodeRuleTrigger" parent="rule-trigger-base">
|
<bean id="on-create-node-trigger" class="org.alfresco.repo.rule.ruletrigger.CreateNodeRuleTrigger" parent="rule-trigger-base">
|
||||||
|
@@ -96,16 +96,19 @@ public class CreateNodeRuleTrigger extends RuleTriggerAbstractBase
|
|||||||
new JavaBehaviour(this, POLICY));
|
new JavaBehaviour(this, POLICY));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register interest in the addition and removal of the sys:noContent aspect
|
for (QName ignoreAspect : getIgnoredAspects())
|
||||||
this.policyComponent.bindClassBehaviour(
|
{
|
||||||
NodeServicePolicies.OnAddAspectPolicy.QNAME,
|
// Register interest in the addition and removal of the sys:noContent aspect
|
||||||
ContentModel.ASPECT_NO_CONTENT,
|
this.policyComponent.bindClassBehaviour(
|
||||||
new JavaBehaviour(this, "onAddAspect", NotificationFrequency.EVERY_EVENT));
|
NodeServicePolicies.OnAddAspectPolicy.QNAME,
|
||||||
this.policyComponent.bindClassBehaviour(
|
ignoreAspect,
|
||||||
NodeServicePolicies.OnRemoveAspectPolicy.QNAME,
|
new JavaBehaviour(this, "onAddAspect", NotificationFrequency.EVERY_EVENT));
|
||||||
ContentModel.ASPECT_NO_CONTENT,
|
this.policyComponent.bindClassBehaviour(
|
||||||
new JavaBehaviour(this, "onRemoveAspect", NotificationFrequency.EVERY_EVENT));
|
NodeServicePolicies.OnRemoveAspectPolicy.QNAME,
|
||||||
}
|
ignoreAspect,
|
||||||
|
new JavaBehaviour(this, "onRemoveAspect", NotificationFrequency.EVERY_EVENT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@@ -186,6 +189,10 @@ public class CreateNodeRuleTrigger extends RuleTriggerAbstractBase
|
|||||||
" (this was triggered on removal of the noContent aspect)");
|
" (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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.rule.ruletrigger;
|
package org.alfresco.repo.rule.ruletrigger;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
@@ -43,8 +45,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
|||||||
{
|
{
|
||||||
/** the types (hardcoded) to ignore generally */
|
/** the types (hardcoded) to ignore generally */
|
||||||
private static final Set<QName> IGNORE_TYPES;
|
private static final Set<QName> IGNORE_TYPES;
|
||||||
/** the aspects (hardcoded) to ignore generally */
|
|
||||||
private static final Set<QName> IGNORE_ASPECTS;
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
IGNORE_TYPES = new HashSet<QName>(13);
|
IGNORE_TYPES = new HashSet<QName>(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)
|
// 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_RATING);
|
||||||
IGNORE_TYPES.add(ContentModel.TYPE_SYSTEM_FOLDER);
|
IGNORE_TYPES.add(ContentModel.TYPE_SYSTEM_FOLDER);
|
||||||
|
|
||||||
IGNORE_ASPECTS = new HashSet<QName>(13);
|
|
||||||
IGNORE_ASPECTS.add(ContentModel.ASPECT_TEMPORARY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of the rule types that are interested in this trigger
|
* A list of the rule types that are interested in this trigger
|
||||||
*/
|
*/
|
||||||
private Set<RuleType> ruleTypes = new HashSet<RuleType>();
|
private Set<RuleType> ruleTypes = new HashSet<RuleType>();
|
||||||
|
private Set<QName> ignoredAspects = Collections.emptySet();
|
||||||
|
|
||||||
protected PolicyComponent policyComponent;
|
protected PolicyComponent policyComponent;
|
||||||
protected NodeService nodeService;
|
protected NodeService nodeService;
|
||||||
@@ -183,7 +182,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
|||||||
* @param actionedUponNodeRef actioned upon node reference
|
* @param actionedUponNodeRef actioned upon node reference
|
||||||
* @return boolean true if the trigger should be ignored, false otherwise
|
* @return boolean true if the trigger should be ignored, false otherwise
|
||||||
*/
|
*/
|
||||||
private boolean ignoreTrigger(NodeRef actionedUponNodeRef)
|
protected boolean ignoreTrigger(NodeRef actionedUponNodeRef)
|
||||||
{
|
{
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
QName typeQName = nodeService.getType(actionedUponNodeRef);
|
QName typeQName = nodeService.getType(actionedUponNodeRef);
|
||||||
@@ -191,7 +190,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
|||||||
{
|
{
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
for (QName aspectToIgnore : IGNORE_ASPECTS)
|
for (QName aspectToIgnore : getIgnoredAspects())
|
||||||
{
|
{
|
||||||
if (nodeService.hasAspect(actionedUponNodeRef, aspectToIgnore))
|
if (nodeService.hasAspect(actionedUponNodeRef, aspectToIgnore))
|
||||||
{
|
{
|
||||||
@@ -200,4 +199,28 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<QName> getIgnoredAspects()
|
||||||
|
{
|
||||||
|
return ignoredAspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converting String Aspects from Spring context to QNames
|
||||||
|
*
|
||||||
|
* @param ignoredAspects List of ignoredAspects
|
||||||
|
*/
|
||||||
|
public void setIgnoredAspectsStr(List<String> 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1340,4 +1340,78 @@ public class RuleServiceImplTest extends BaseRuleTest
|
|||||||
assertFalse("The folder should be deleted.", nodeService.exists(parentFolderNodeRef));
|
assertFalse("The folder should be deleted.", nodeService.exists(parentFolderNodeRef));
|
||||||
txn.commit();
|
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<Rule> 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user