- Action/Rule decoupling work

- Updated web services, SDK and web client where appropraite
- Patch added to migrate existing rules
- Entire rule service can now be disabled programmatically
- Rule service is now disabled during the patching process
- StoreEnum and languageEnum types removed from web service interfaces
- Multiple rule types now supported in the repo (but not in the UI)
- Removed owning node ref from action and rule .. now calculated from methods on the rule service

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3464 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2006-08-07 15:53:45 +00:00
parent df21ad9f8b
commit df7f1062df
33 changed files with 964 additions and 555 deletions

View File

@@ -17,6 +17,7 @@
package org.alfresco.repo.rule;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -163,33 +164,40 @@ public class BaseRuleTest extends BaseSpringTest
Map<String, Serializable> actionProps = new HashMap<String, Serializable>();
actionProps.put(ACTION_PROP_NAME_1, ACTION_PROP_VALUE_1);
// Create the rule
Rule rule = this.ruleService.createRule(this.ruleType.getName());
rule.setTitle(TITLE);
rule.setDescription(DESCRIPTION);
rule.applyToChildren(isAppliedToChildren);
List<String> ruleTypes = new ArrayList<String>(1);
ruleTypes.add(this.ruleType.getName());
// Create the action
Action action = this.actionService.createAction(CONDITION_DEF_NAME);
action.setParameterValues(conditionProps);
ActionCondition actionCondition = this.actionService.createActionCondition(CONDITION_DEF_NAME);
actionCondition.setParameterValues(conditionProps);
rule.addActionCondition(actionCondition);
action.addActionCondition(actionCondition);
Action action = this.actionService.createAction(CONDITION_DEF_NAME);
action.setParameterValues(conditionProps);
rule.addAction(action);
// Create the rule
Rule rule = new Rule();
rule.setRuleTypes(ruleTypes);
rule.setTitle(TITLE);
rule.setDescription(DESCRIPTION);
rule.applyToChildren(isAppliedToChildren);
rule.setAction(action);
return rule;
}
protected void checkRule(RuleImpl rule, String id)
protected void checkRule(Rule rule)
{
// Check the basic details of the rule
assertEquals(id, rule.getId());
assertEquals(this.ruleType.getName(), rule.getRuleTypeName());
assertEquals(this.ruleType.getName(), rule.getRuleTypes().get(0));
assertEquals(TITLE, rule.getTitle());
assertEquals(DESCRIPTION, rule.getDescription());
Action ruleAction = rule.getAction();
assertNotNull(ruleAction);
// Check conditions
List<ActionCondition> ruleConditions = rule.getActionConditions();
List<ActionCondition> ruleConditions = ruleAction.getActionConditions();
assertNotNull(ruleConditions);
assertEquals(1, ruleConditions.size());
assertEquals(CONDITION_DEF_NAME, ruleConditions.get(0)
@@ -202,11 +210,8 @@ public class BaseRuleTest extends BaseSpringTest
assertEquals(COND_PROP_VALUE_1, condParams.get(COND_PROP_NAME_1));
// Check the actions
List<Action> ruleActions = rule.getActions();
assertNotNull(ruleActions);
assertEquals(1, ruleActions.size());
assertEquals(ACTION_DEF_NAME, ruleActions.get(0).getActionDefinitionName());
Map<String, Serializable> actionParams = ruleActions.get(0).getParameterValues();
assertEquals(ACTION_DEF_NAME, ruleAction.getActionDefinitionName());
Map<String, Serializable> actionParams = ruleAction.getParameterValues();
assertNotNull(actionParams);
assertEquals(1, actionParams.size());
assertTrue(actionParams.containsKey(ACTION_PROP_NAME_1));

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.rule;
import java.io.Serializable;
import org.alfresco.repo.action.CompositeActionImpl;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.rule.Rule;
import org.alfresco.util.ParameterCheck;
/**
* Rule implementation class.
* <p>
* Encapsulates all the information about a rule. Can be creted or editied and
* then passed to the rule service to create/update a rule instance.
*
* @author Roy Wetherall
*/
public class RuleImpl extends CompositeActionImpl implements Serializable, Rule
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 3544385898889097524L;
/**
* The rule type name
*/
private String ruleTypeName;
/**
* Indicates whether the rule is applied to all the children of the associated node
* rather than just the node itself.
*/
private boolean isAppliedToChildren = false;
/**
* Constructor
*
* @param ruleTypeName the rule type name
*/
public RuleImpl(String id, String ruleTypeName, NodeRef owningNodeRef)
{
super(id, owningNodeRef);
ParameterCheck.mandatory("ruleTypeName", ruleTypeName);
this.ruleTypeName = ruleTypeName;
}
/**
* @see org.alfresco.service.cmr.rule.Rule#isAppliedToChildren()
*/
public boolean isAppliedToChildren()
{
return this.isAppliedToChildren;
}
/**
*@see org.alfresco.service.cmr.rule.Rule#applyToChildren(boolean)
*/
public void applyToChildren(boolean isAppliedToChildren)
{
this.isAppliedToChildren = isAppliedToChildren;
}
/**
* @see org.alfresco.service.cmr.rule.Rule#getRuleTypeName()
*/
public String getRuleTypeName()
{
return this.ruleTypeName;
}
}

View File

@@ -10,12 +10,15 @@ import org.alfresco.service.namespace.QName;
public interface RuleModel
{
/** Rule model constants */
static final String RULE_MODEL_URI = "http://www.alfresco.org/model/rule/1.0";
static final String RULE_MODEL_PREFIX = "rule";
static final QName TYPE_RULE = QName.createQName(RULE_MODEL_URI, "rule");
static final QName PROP_RULE_TYPE = QName.createQName(RULE_MODEL_URI, "ruleType");
static final QName TYPE_RULE_CONTENT = QName.createQName(RULE_MODEL_URI, "rulecontent");
static final QName PROP_APPLY_TO_CHILDREN = QName.createQName(RULE_MODEL_URI, "applyToChildren");
static final QName ASPECT_RULES = QName.createQName(RULE_MODEL_URI, "rules");
static final QName ASSOC_RULE_FOLDER = QName.createQName(RULE_MODEL_URI, "ruleFolder");
static final String RULE_MODEL_URI = "http://www.alfresco.org/model/rule/1.0";
static final String RULE_MODEL_PREFIX = "rule";
static final QName TYPE_RULE = QName.createQName(RULE_MODEL_URI, "rule");
static final QName PROP_RULE_TYPE = QName.createQName(RULE_MODEL_URI, "ruleType");
static final QName PROP_APPLY_TO_CHILDREN = QName.createQName(RULE_MODEL_URI, "applyToChildren");
static final QName PROP_EXECUTE_ASYNC = QName.createQName(RULE_MODEL_URI, "executeAsynchronously");
static final QName ASSOC_ACTION = QName.createQName(RULE_MODEL_URI, "action");
static final QName ASPECT_RULES = QName.createQName(RULE_MODEL_URI, "rules");
static final QName ASSOC_RULE_FOLDER = QName.createQName(RULE_MODEL_URI, "ruleFolder");
}

View File

@@ -81,7 +81,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.StopWatch;
/**
* @author Roy Wetherall
* @author Roy Wetherall
*/
public class RuleServiceCoverageTest extends TestCase
{
@@ -109,6 +109,7 @@ public class RuleServiceCoverageTest extends TestCase
private ActionService actionService;
private ContentTransformerRegistry transformerRegistry;
private CopyService copyService;
private AuthenticationComponent authenticationComponent;
/**
* Category related values
@@ -147,9 +148,10 @@ public class RuleServiceCoverageTest extends TestCase
this.actionService = serviceRegistry.getActionService();
this.transactionService = serviceRegistry.getTransactionService();
this.transformerRegistry = (ContentTransformerRegistry)applicationContext.getBean("contentTransformerRegistry");
this.authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
AuthenticationComponent authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
//authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
authenticationComponent.setSystemUserAsCurrentUser();
this.testStoreRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
this.rootNodeRef = this.nodeService.getRootNode(this.testStoreRef);
@@ -159,11 +161,7 @@ public class RuleServiceCoverageTest extends TestCase
this.rootNodeRef,
ContentModel.ASSOC_CHILDREN,
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_CONTAINER).getChildRef();
// Create and authenticate the user used in the tests
//TestWithUserUtils.createUser(USER_NAME, PWD, this.rootNodeRef, this.nodeService, this.authenticationService);
//TestWithUserUtils.authenticateUser(USER_NAME, PWD, this.rootNodeRef, this.authenticationService);
ContentModel.TYPE_CONTAINER).getChildRef();
}
private Rule createRule(
@@ -173,11 +171,14 @@ public class RuleServiceCoverageTest extends TestCase
String conditionName,
Map<String, Serializable> conditionParams)
{
Rule rule = this.ruleService.createRule(ruleTypeName);
Rule rule = new Rule();
rule.setRuleType(ruleTypeName);
Action action = this.actionService.createAction(actionName, actionParams);
ActionCondition condition = this.actionService.createActionCondition(conditionName, conditionParams);
rule.addActionCondition(condition);
Action action = this.actionService.createAction(actionName, actionParams);
rule.addAction(action);
action.addActionCondition(condition);
rule.setAction(action);
return rule;
}
@@ -226,8 +227,8 @@ public class RuleServiceCoverageTest extends TestCase
/**
* Check async rule execution
*/
public void testAsyncRuleExecution()
{
public void testAsyncRuleExecution()
{
final NodeRef newNodeRef = TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<NodeRef>()
@@ -323,9 +324,9 @@ public class RuleServiceCoverageTest extends TestCase
params2.put(ContentModel.PROP_APPROVE_MOVE.toString(), false);
// Test that rule can be updated and execute correctly
rule.removeAllActions();
//rule.removeAllActions();
Action action2 = this.actionService.createAction(AddFeaturesActionExecuter.NAME, params2);
rule.addAction(action2);
rule.setAction(action2);
this.ruleService.saveRule(this.nodeRef, rule);
NodeRef newNodeRef2 = this.nodeService.createNode(
@@ -427,15 +428,15 @@ public class RuleServiceCoverageTest extends TestCase
getContentProperties()).getChildRef();
addContentToNode(contentToCopy);
// Create the rule and add to folder
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
params.put("aspect-name", ContentModel.ASPECT_TEMPLATABLE);
params.put("aspect-name", ContentModel.ASPECT_TEMPLATABLE);
Rule rule = createRule(
RuleType.INBOUND,
AddFeaturesActionExecuter.NAME,
params,
NoConditionEvaluator.NAME,
null);
null);
rule.applyToChildren(true);
this.ruleService.saveRule(copyToFolder, rule);
@@ -1232,9 +1233,9 @@ public class RuleServiceCoverageTest extends TestCase
// Test begins with
Map<String, Serializable> condParamsBegins = new HashMap<String, Serializable>(1);
condParamsBegins.put(ComparePropertyValueEvaluator.PARAM_VALUE, "bob*");
rule.removeAllActionConditions();
rule.getAction().removeAllActionConditions();
ActionCondition condition1 = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME, condParamsBegins);
rule.addActionCondition(condition1);
rule.getAction().addActionCondition(condition1);
this.ruleService.saveRule(this.nodeRef, rule);
Map<QName, Serializable> propsx = new HashMap<QName, Serializable>();
propsx.put(ContentModel.PROP_NAME, "mybobbins.doc");
@@ -1264,9 +1265,9 @@ public class RuleServiceCoverageTest extends TestCase
// Test ends with
Map<String, Serializable> condParamsEnds = new HashMap<String, Serializable>(1);
condParamsEnds.put(ComparePropertyValueEvaluator.PARAM_VALUE, "*s.doc");
rule.removeAllActionConditions();
rule.getAction().removeAllActionConditions();
ActionCondition condition2 = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME, condParamsEnds);
rule.addActionCondition(condition2);
rule.getAction().addActionCondition(condition2);
this.ruleService.saveRule(this.nodeRef, rule);
Map<QName, Serializable> propsa = new HashMap<QName, Serializable>();
propsa.put(ContentModel.PROP_NAME, "bobbins.document");

View File

@@ -18,7 +18,6 @@ package org.alfresco.repo.rule;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -30,6 +29,7 @@ import org.alfresco.repo.action.ActionModel;
import org.alfresco.repo.action.RuntimeActionService;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionListener;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.action.ActionServiceException;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -41,8 +41,6 @@ import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.rule.RuleServiceException;
import org.alfresco.service.cmr.rule.RuleType;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.DynamicNamespacePrefixResolver;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.GUID;
@@ -125,7 +123,12 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
/**
* The rule transaction listener
*/
private TransactionListener ruleTransactionListener = new RuleTransactionListener(this);
private TransactionListener ruleTransactionListener = new RuleTransactionListener(this);
/**
* Indicates whether the rules are disabled for the curren thread
*/
private ThreadLocal<Boolean> rulesDisabled = new ThreadLocal<Boolean>();
/**
* Set the permission-safe node service
@@ -229,6 +232,30 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
return this.ruleTypes.get(name);
}
/**
* @see org.alfresco.service.cmr.rule.RuleService#enableRules()
*/
public void enableRules()
{
this.rulesDisabled.remove();
}
/**
* @see org.alfresco.service.cmr.rule.RuleService#disableRules()
*/
public void disableRules()
{
this.rulesDisabled.set(Boolean.TRUE);
}
/**
* @see org.alfresco.service.cmr.rule.RuleService#isEnabled()
*/
public boolean isEnabled()
{
return (this.rulesDisabled.get() == null);
}
/**
* @see org.alfresco.service.cmr.rule.RuleService#rulesEnabled(NodeRef)
*/
@@ -331,7 +358,7 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
{
// Create the rule and add to the list
NodeRef ruleNodeRef = ruleChildAssocRef.getChildRef();
Rule rule = createRule(nodeRef, ruleNodeRef);
Rule rule = getRule(ruleNodeRef);
allRules.add(rule);
}
@@ -339,7 +366,7 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
for (Rule rule : allRules)
{
if ((rules.contains(rule) == false) &&
(ruleTypeName == null || ruleTypeName.equals(rule.getRuleTypeName()) == true))
(ruleTypeName == null || rule.getRuleTypes().contains(ruleTypeName) == true))
{
rules.add(rule);
}
@@ -459,7 +486,7 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
// Filter the rule list by rule type
for (Rule rule : allInheritedRules)
{
if (rule.getRuleTypeName().equals(ruleTypeName) == true)
if (rule.getRuleTypes().contains(ruleTypeName) == true)
{
inheritedRules.add(rule);
}
@@ -470,75 +497,31 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
return inheritedRules;
}
/**
* @see org.alfresco.repo.rule.RuleService#getRule(String)
*/
public Rule getRule(NodeRef nodeRef, String ruleId)
{
Rule rule = null;
if (this.runtimeNodeService.exists(nodeRef) == true)
{
NodeRef ruleNodeRef = getRuleNodeRefFromId(nodeRef, ruleId);
if (ruleNodeRef != null)
{
rule = createRule(nodeRef, ruleNodeRef);
}
}
return rule;
}
/**
* Gets the rule node ref from the action id
*
* @param nodeRef the node reference
* @param actionId the rule id
* @return the rule node reference
*/
private NodeRef getRuleNodeRefFromId(NodeRef nodeRef, String ruleId)
{
NodeRef result = null;
if (this.runtimeNodeService.hasAspect(nodeRef, RuleModel.ASPECT_RULES) == true)
{
NodeRef ruleFolder = getSavedRuleFolderRef(nodeRef);
if (ruleFolder != null)
{
DynamicNamespacePrefixResolver namespacePrefixResolver = new DynamicNamespacePrefixResolver();
namespacePrefixResolver.registerNamespace(NamespaceService.SYSTEM_MODEL_PREFIX, NamespaceService.SYSTEM_MODEL_1_0_URI);
List<NodeRef> nodeRefs = searchService.selectNodes(
ruleFolder,
"*[@sys:" + ContentModel.PROP_NODE_UUID.getLocalName() + "='" + ruleId + "']",
null,
namespacePrefixResolver,
false);
if (nodeRefs.size() != 0)
{
result = nodeRefs.get(0);
}
}
}
return result;
}
/**
* Create the rule object from the rule node reference
*
* @param ruleNodeRef the rule node reference
* @return the rule
*/
private Rule createRule(NodeRef owningNodeRef, NodeRef ruleNodeRef)
public Rule getRule(NodeRef ruleNodeRef)
{
// Get the rule properties
Map<QName, Serializable> props = this.runtimeNodeService.getProperties(ruleNodeRef);
// Create the rule
String ruleTypeName = (String)props.get(RuleModel.PROP_RULE_TYPE);
Rule rule = new RuleImpl(ruleNodeRef.getId(), ruleTypeName, owningNodeRef);
// Set the other rule properties
Rule rule = new Rule(ruleNodeRef);
// Set the owning node ref
//rule.setOwningNodeRef((NodeRef)props.get(RuleModel.PROP_OWNING_NODEREF));
// Set the title and description
rule.setTitle((String)props.get(ContentModel.PROP_TITLE));
rule.setDescription((String)props.get(ContentModel.PROP_DESCRIPTION));
// Set the rule types
rule.setRuleTypes((List<String>)props.get(RuleModel.PROP_RULE_TYPE));
// Set the applied to children value
boolean isAppliedToChildren = false;
Boolean value = (Boolean)props.get(RuleModel.PROP_APPLY_TO_CHILDREN);
if (value != null)
@@ -546,69 +529,125 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
isAppliedToChildren = value.booleanValue();
}
rule.applyToChildren(isAppliedToChildren);
// Set the execute asynchronously value
boolean executeAsync = false;
Boolean value2 = (Boolean)props.get(RuleModel.PROP_EXECUTE_ASYNC);
if (value2 != null)
{
executeAsync = value2.booleanValue();
}
rule.setExecuteAsynchronously(executeAsync);
// Populate the composite action details
runtimeActionService.populateCompositeAction(ruleNodeRef, rule);
// Get the action node reference
List<ChildAssociationRef> actions = this.nodeService.getChildAssocs(ruleNodeRef, RuleModel.ASSOC_ACTION, RuleModel.ASSOC_ACTION);
if (actions.size() == 0)
{
throw new RuleServiceException("Rule exists without a specified action");
}
else if (actions.size() > 1)
{
throw new RuleServiceException("Rule exists with more than one specified action");
}
NodeRef actionNodeRef = actions.get(0).getChildRef();
// Here we need to create the action from the action node reference
Action action = runtimeActionService.createAction(actionNodeRef);
rule.setAction(action);
return rule;
}
/**
* @see org.alfresco.repo.rule.RuleService#createRule(org.alfresco.repo.rule.RuleType)
*/
public Rule createRule(String ruleTypeName)
{
// Create the new rule, giving it a unique rule id
String id = GUID.generate();
return new RuleImpl(id, ruleTypeName, null);
}
/**
* @see org.alfresco.repo.rule.RuleService#saveRule(org.alfresco.repo.ref.NodeRef, org.alfresco.repo.rule.Rule)
*/
public void saveRule(NodeRef nodeRef, Rule rule)
{
if (this.nodeService.exists(nodeRef) == false)
{
throw new RuleServiceException("The node does not exist.");
}
NodeRef ruleNodeRef = getRuleNodeRefFromId(nodeRef, rule.getId());
if (ruleNodeRef == null)
{
if (this.nodeService.hasAspect(nodeRef, RuleModel.ASPECT_RULES) == false)
{
// Add the actionable aspect
this.nodeService.addAspect(nodeRef, RuleModel.ASPECT_RULES, null);
}
Map<QName, Serializable> props = new HashMap<QName, Serializable>(3);
props.put(RuleModel.PROP_RULE_TYPE, rule.getRuleTypeName());
props.put(ActionModel.PROP_DEFINITION_NAME, rule.getActionDefinitionName());
props.put(ContentModel.PROP_NODE_UUID, rule.getId());
// Create the action node
ruleNodeRef = this.nodeService.createNode(
getSavedRuleFolderRef(nodeRef),
ContentModel.ASSOC_CONTAINS,
QName.createQName(RuleModel.RULE_MODEL_URI, ASSOC_NAME_RULES_PREFIX + GUID.generate()),
RuleModel.TYPE_RULE,
props).getChildRef();
// Update the created details
((RuleImpl)rule).setCreator((String)this.nodeService.getProperty(ruleNodeRef, ContentModel.PROP_CREATOR));
((RuleImpl)rule).setCreatedDate((Date)this.nodeService.getProperty(ruleNodeRef, ContentModel.PROP_CREATED));
}
disableRules();
try
{
if (this.nodeService.exists(nodeRef) == false)
{
throw new RuleServiceException("The node does not exist.");
}
NodeRef ruleNodeRef = rule.getNodeRef();
if (ruleNodeRef == null)
{
if (this.nodeService.hasAspect(nodeRef, RuleModel.ASPECT_RULES) == false)
{
// Add the actionable aspect
this.nodeService.addAspect(nodeRef, RuleModel.ASPECT_RULES, null);
}
// Create the action node
ruleNodeRef = this.nodeService.createNode(
getSavedRuleFolderRef(nodeRef),
ContentModel.ASSOC_CONTAINS,
QName.createQName(RuleModel.RULE_MODEL_URI, ASSOC_NAME_RULES_PREFIX + GUID.generate()),
RuleModel.TYPE_RULE).getChildRef();
// Set the rule node reference and the owning node reference
rule.setNodeRef(ruleNodeRef);
}
// Update the properties of the rule
this.nodeService.setProperty(ruleNodeRef, ContentModel.PROP_TITLE, rule.getTitle());
this.nodeService.setProperty(ruleNodeRef, ContentModel.PROP_DESCRIPTION, rule.getDescription());
this.nodeService.setProperty(ruleNodeRef, RuleModel.PROP_RULE_TYPE, (Serializable)rule.getRuleTypes());
this.nodeService.setProperty(ruleNodeRef, RuleModel.PROP_APPLY_TO_CHILDREN, rule.isAppliedToChildren());
this.nodeService.setProperty(ruleNodeRef, RuleModel.PROP_EXECUTE_ASYNC, rule.getExecuteAsynchronously());
// Save the rule's action
saveAction(ruleNodeRef, rule);
}
finally
{
enableRules();
}
}
private void saveAction(NodeRef ruleNodeRef, Rule rule)
{
// Get the action definition from the rule
Action action = rule.getAction();
if (action == null)
{
throw new RuleServiceException("An action must be specified when defining a rule.");
}
// Update the properties of the rule
this.nodeService.setProperty(ruleNodeRef, RuleModel.PROP_APPLY_TO_CHILDREN, rule.isAppliedToChildren());
// Save the remainder of the rule as a composite action
runtimeActionService.saveActionImpl(nodeRef, ruleNodeRef, rule);
// Get the current action node reference
NodeRef actionNodeRef = null;
List<ChildAssociationRef> actions = this.nodeService.getChildAssocs(ruleNodeRef, RuleModel.ASSOC_ACTION, RuleModel.ASSOC_ACTION);
if (actions.size() == 1)
{
// We need to check that the action is the same
actionNodeRef = actions.get(0).getChildRef();
if (actionNodeRef.getId().equals(action.getId()) == false)
{
// Delete the old action
this.nodeService.deleteNode(actionNodeRef);
actionNodeRef = null;
}
}
else if (actions.size() > 1)
{
throw new RuleServiceException("The rule has become corrupt. More than one action is associated with the rule.");
}
// Create the new action node reference
if (actionNodeRef == null)
{
actionNodeRef = this.runtimeActionService.createActionNodeRef(action, ruleNodeRef, RuleModel.ASSOC_ACTION, RuleModel.ASSOC_ACTION);
}
// Update the action node
this.runtimeActionService.saveActionImpl(actionNodeRef, action);
}
/**
* @see org.alfresco.repo.rule.RuleService#removeRule(org.alfresco.repo.ref.NodeRef, org.alfresco.repo.rule.RuleImpl)
* @see org.alfresco.repo.rule.RuleService#removeRule(org.alfresco.repo.ref.NodeRef, org.alfresco.service.cmr.rule.Rule)
*/
public void removeRule(NodeRef nodeRef, Rule rule)
{
@@ -618,7 +657,7 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
disableRules(nodeRef);
try
{
NodeRef ruleNodeRef = getRuleNodeRefFromId(nodeRef, rule.getId());
NodeRef ruleNodeRef = rule.getNodeRef();
if (ruleNodeRef != null)
{
this.nodeService.removeChild(getSavedRuleFolderRef(nodeRef), ruleNodeRef);
@@ -669,7 +708,8 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
public void addRulePendingExecution(NodeRef actionableNodeRef, NodeRef actionedUponNodeRef, Rule rule, boolean executeAtEnd)
{
// First check to see if the node has been disabled
if (this.disabledNodeRefs.contains(rule.getOwningNodeRef()) == false &&
if (this.rulesDisabled.get() == null &&
this.disabledNodeRefs.contains(this.getOwningNodeRef(rule)) == false &&
this.disabledRules.contains(rule) == false)
{
PendingRuleData pendingRuleData = new PendingRuleData(actionableNodeRef, actionedUponNodeRef, rule, executeAtEnd);
@@ -697,7 +737,7 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
{
if (logger.isDebugEnabled() == true)
{
logger.debug("The rule '" + rule.getTitle() + "' or the node '" + rule.getOwningNodeRef().getId() + "' has been disabled.");
logger.debug("The rule '" + rule.getTitle() + "' or the node '" + this.getOwningNodeRef(rule).getId() + "' has been disabled.");
}
}
}
@@ -717,22 +757,12 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
{
AlfrescoTransactionSupport.bindResource(KEY_RULES_EXECUTED, new HashSet<ExecutedRuleData>());
}
try
List<PendingRuleData> executeAtEndRules = new ArrayList<PendingRuleData>();
executePendingRulesImpl(executeAtEndRules);
for (PendingRuleData data : executeAtEndRules)
{
List<PendingRuleData> executeAtEndRules = new ArrayList<PendingRuleData>();
executePendingRulesImpl(executeAtEndRules);
for (PendingRuleData data : executeAtEndRules)
{
executePendingRule(data);
}
}
finally
{
//AlfrescoTransactionSupport.unbindResource(KEY_RULES_EXECUTED);
//if (logger.isDebugEnabled() == true)
//{
// logger.debug("Unbinding resource");
// }
executePendingRule(data);
}
}
@@ -785,8 +815,14 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
if (executedRules == null || canExecuteRule(executedRules, actionedUponNodeRef, rule) == true)
{
Action action = rule.getAction();
if (action == null)
{
throw new RuleServiceException("Attempting to execute a rule that does not have a rule specified.");
}
// Evaluate the condition
if (this.actionService.evaluateAction(rule, actionedUponNodeRef) == true)
if (this.actionService.evaluateAction(action, actionedUponNodeRef) == true)
{
// Add the rule to the executed rule list
// (do this before this is executed to prevent rules being added to the pending list)
@@ -797,7 +833,8 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
}
// Execute the rule
this.actionService.executeAction(rule, actionedUponNodeRef);
boolean executeAsync = rule.getExecuteAsynchronously();
this.actionService.executeAction(action, actionedUponNodeRef, true, executeAsync);
}
}
}
@@ -1014,4 +1051,70 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
}
}
}
/**
* @see org.alfresco.service.cmr.rule.RuleService#getOwningNodeRef(org.alfresco.service.cmr.rule.Rule)
*/
public NodeRef getOwningNodeRef(Rule rule)
{
NodeRef result = null;
NodeRef ruleNodeRef = rule.getNodeRef();
if (ruleNodeRef != null)
{
result = getOwningNodeRefRuleImpl(ruleNodeRef);
}
return result;
}
/**
* @param ruleNodeRef
* @return
*/
private NodeRef getOwningNodeRefRuleImpl(NodeRef ruleNodeRef)
{
// Get the system folder parent
NodeRef systemFolder = this.nodeService.getPrimaryParent(ruleNodeRef).getParentRef();
// Get the owning node ref
return this.nodeService.getPrimaryParent(systemFolder).getParentRef();
}
/**
* @see org.alfresco.service.cmr.rule.RuleService#getOwningNodeRef(org.alfresco.service.cmr.action.Action)
*/
public NodeRef getOwningNodeRef(Action action)
{
NodeRef result = null;
NodeRef actionNodeRef = action.getNodeRef();
if (actionNodeRef != null)
{
result = getOwningNodeRefActionImpl(actionNodeRef);
}
return result;
}
/**
* @param actionNodeRef
*/
private NodeRef getOwningNodeRefActionImpl(NodeRef actionNodeRef)
{
NodeRef result = null;
NodeRef parentNodeRef = this.nodeService.getPrimaryParent(actionNodeRef).getParentRef();
if (parentNodeRef != null)
{
QName parentType = this.nodeService.getType(parentNodeRef);
if (RuleModel.TYPE_RULE.equals(parentType) == true)
{
result = getOwningNodeRefRuleImpl(parentNodeRef);
}
else if (ActionModel.TYPE_COMPOSITE_ACTION.equals(parentType) == true)
{
result = getOwningNodeRefActionImpl(parentNodeRef);
}
}
return result;
}
}

View File

@@ -60,17 +60,6 @@ public class RuleServiceImplTest extends BaseRuleTest
}
}
/**
* Test createRule
*/
public void testCreateRule()
{
Rule newRule = this.ruleService.createRule("ruleType1");
assertNotNull(newRule);
assertNotNull(newRule.getId());
assertEquals("ruleType1", newRule.getRuleTypeName());
}
/**
* Test addRule
*
@@ -78,17 +67,21 @@ public class RuleServiceImplTest extends BaseRuleTest
public void testAddRule()
{
Rule newRule = createTestRule();
String ruleId = newRule.getId();
this.ruleService.saveRule(this.nodeRef, newRule);
this.ruleService.saveRule(this.nodeRef, newRule);
assertNotNull(newRule.getNodeRef());
Rule savedRule = this.ruleService.getRule(this.nodeRef, ruleId);
// Check the owning node reference
assertNotNull(this.ruleService.getOwningNodeRef(newRule));
assertEquals(this.nodeRef, this.ruleService.getOwningNodeRef(newRule));
Rule savedRule = this.ruleService.getRule(newRule.getNodeRef());
assertNotNull(savedRule);
assertFalse(savedRule.isAppliedToChildren());
savedRule.applyToChildren(true);
this.ruleService.saveRule(this.nodeRef, savedRule);
Rule savedRule2 = this.ruleService.getRule(this.nodeRef, ruleId);
Rule savedRule2 = this.ruleService.getRule(savedRule.getNodeRef());
assertNotNull(savedRule2);
assertTrue(savedRule2.isAppliedToChildren());
}
@@ -100,9 +93,9 @@ public class RuleServiceImplTest extends BaseRuleTest
assertNotNull(rules1);
assertEquals(0, rules1.size());
Rule newRule = this.ruleService.createRule(ruleType.getName());
Rule newRule = createTestRule(); //this.ruleService.createRule(ruleType.getName());
this.ruleService.saveRule(this.nodeRef, newRule);
Rule newRule2 = this.ruleService.createRule(ruleType.getName());
Rule newRule2 = createTestRule(); //this.ruleService.createRule(ruleType.getName());
this.ruleService.saveRule(this.nodeRef, newRule2);
List<Rule> rules2 = this.ruleService.getRules(this.nodeRef);
@@ -113,8 +106,7 @@ public class RuleServiceImplTest extends BaseRuleTest
List<Rule> rules3 = this.ruleService.getRules(this.nodeRef);
assertNotNull(rules3);
assertEquals(0, rules3.size());
assertEquals(0, rules3.size());
}
/**
@@ -145,16 +137,15 @@ public class RuleServiceImplTest extends BaseRuleTest
Rule rule = rules.get(0);
assertEquals("title", rule.getTitle());
assertEquals("description", rule.getDescription());
assertNotNull(rule.getCreatedDate());
assertNotNull(rule.getModifiedDate());
assertNotNull(this.nodeService.getProperty(rule.getNodeRef(), ContentModel.PROP_CREATED));
assertNotNull(this.nodeService.getProperty(rule.getNodeRef(), ContentModel.PROP_CREATOR));
// Check that the condition action have been retireved correctly
List<ActionCondition> conditions = rule.getActionConditions();
Action action = rule.getAction();
assertNotNull(action);
List<ActionCondition> conditions = action.getActionConditions();
assertNotNull(conditions);
assertEquals(1, conditions.size());
List<Action> actions = rule.getActions();
assertNotNull(actions);
assertEquals(1, actions.size());
assertEquals(1, conditions.size());
}
/**
@@ -232,7 +223,9 @@ public class RuleServiceImplTest extends BaseRuleTest
int count = 0;
for (Rule rule : allRules)
{
if (rule.getOwningNodeRef() == childWithRules)
NodeRef owningNodeRef = this.ruleService.getOwningNodeRef(rule);
assertNotNull(owningNodeRef);
if (owningNodeRef.equals(childWithRules) == true)
{
count++;
}
@@ -547,17 +540,19 @@ public class RuleServiceImplTest extends BaseRuleTest
actionProps.put(ImageTransformActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CHILDREN);
actionProps.put(ImageTransformActionExecuter.PARAM_ASSOC_QNAME, ContentModel.ASSOC_CHILDREN);
Rule rule = this.ruleService.createRule(this.ruleType.getName());
Rule rule = new Rule();
rule.setRuleType(this.ruleType.getName());
rule.setTitle("Convert from *.jpg to *.gif");
rule.setExecuteAsynchronously(true);
ActionCondition actionCondition = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
actionCondition.setParameterValues(conditionProps);
rule.addActionCondition(actionCondition);
Action action = this.actionService.createAction(ImageTransformActionExecuter.NAME);
action.setParameterValues(actionProps);
rule.addAction(action);
ActionCondition actionCondition = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
actionCondition.setParameterValues(conditionProps);
action.addActionCondition(actionCondition);
rule.setAction(action);
// Create the next rule
@@ -569,17 +564,19 @@ public class RuleServiceImplTest extends BaseRuleTest
actionProps2.put(ImageTransformActionExecuter.PARAM_DESTINATION_FOLDER, nodeRef);
actionProps2.put(ImageTransformActionExecuter.PARAM_ASSOC_QNAME, ContentModel.ASSOC_CHILDREN);
Rule rule2 = this.ruleService.createRule(this.ruleType.getName());
Rule rule2 = new Rule();
rule2.setRuleType(this.ruleType.getName());
rule2.setTitle("Convert from *.gif to *.jpg");
rule2.setExecuteAsynchronously(true);
ActionCondition actionCondition2 = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
actionCondition2.setParameterValues(conditionProps2);
rule2.addActionCondition(actionCondition2);
Action action2 = this.actionService.createAction(ImageTransformActionExecuter.NAME);
action2.setParameterValues(actionProps2);
rule2.addAction(action2);
ActionCondition actionCondition2 = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
actionCondition2.setParameterValues(conditionProps2);
action2.addActionCondition(actionCondition2);
rule2.setAction(action2);
// Save the rules
this.ruleService.saveRule(nodeRef, rule);

View File

@@ -41,11 +41,6 @@ public class RuleTypeImpl extends CommonResourceAbstractBase implements RuleType
*/
private static Log logger = LogFactory.getLog(RuleTypeImpl.class);
/**
* The action service
*/
private ActionService actionService;
/**
* The rule service
*/
@@ -67,16 +62,6 @@ public class RuleTypeImpl extends CommonResourceAbstractBase implements RuleType
}
}
/**
* Set the action service
*
* @param actionService the action service
*/
public void setActionService(ActionService actionService)
{
this.actionService = actionService;
}
/**
* Set the rule service
*
@@ -116,29 +101,36 @@ public class RuleTypeImpl extends CommonResourceAbstractBase implements RuleType
*/
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef)
{
if (this.ruleService.hasRules(nodeRef) == true)
if (this.ruleService.isEnabled() == true)
{
List<Rule> rules = this.ruleService.getRules(
nodeRef,
true,
this.name);
for (Rule rule : rules)
{
if (this.ruleService.hasRules(nodeRef) == true)
{
List<Rule> rules = this.ruleService.getRules(
nodeRef,
true,
this.name);
for (Rule rule : rules)
{
if (logger.isDebugEnabled() == true)
{
NodeRef ruleNodeRef = rule.getNodeRef();
if (nodeRef != null)
{
logger.debug("Triggering rule " + ruleNodeRef.toString());
}
}
// Queue the rule to be executed at the end of the transaction (but still in the transaction)
((RuntimeRuleService)this.ruleService).addRulePendingExecution(nodeRef, actionedUponNodeRef, rule);
}
}
else
{
if (logger.isDebugEnabled() == true)
{
logger.debug("Triggering rule " + rule.getId());
logger.debug("This node has no rules to trigger.");
}
// Queue the rule to be executed at the end of the transaction (but still in the transaction)
((RuntimeRuleService)this.ruleService).addRulePendingExecution(nodeRef, actionedUponNodeRef, rule);
}
}
else
{
if (logger.isDebugEnabled() == true)
{
logger.debug("This node has no rules to trigger.");
}
}
}

View File

@@ -9,6 +9,7 @@
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<import uri="http://www.alfresco.org/model/action/1.0" prefix="act"/>
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys"/>
</imports>
<namespaces>
@@ -20,17 +21,35 @@
<type name="rule:rule">
<title>Rule</title>
<parent>act:compositeaction</parent>
<properties>
<parent>sys:base</parent>
<properties>
<property name="rule:ruleType">
<type>d:text</type>
<mandatory>true</mandatory>
<multiple>true</multiple>
</property>
<property name="rule:applyToChildren">
<type>d:boolean</type>
<mandatory>true</mandatory>
</property>
</properties>
<property name="rule:executeAsynchronously">
<type>d:boolean</type>
<mandatory>true</mandatory>
</property>
</properties>
<associations>
<child-association name="rule:action">
<target>
<class>act:action</class>
<mandatory>true</mandatory>
<many>false</many>
</target>
</child-association>
</associations>
<mandatory-aspects>
<aspect>cm:titled</aspect>
<aspect>cm:auditable</aspect>
</mandatory-aspects>
</type>
</types>