mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Big honkin' merge from head. Sheesh!
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3617 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -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;
|
||||
@@ -155,6 +156,11 @@ public class BaseRuleTest extends BaseSpringTest
|
||||
}
|
||||
|
||||
protected Rule createTestRule(boolean isAppliedToChildren)
|
||||
{
|
||||
return createTestRule(isAppliedToChildren, TITLE);
|
||||
}
|
||||
|
||||
protected Rule createTestRule(boolean isAppliedToChildren, String title)
|
||||
{
|
||||
// Rule properties
|
||||
Map<String, Serializable> conditionProps = new HashMap<String, Serializable>();
|
||||
@@ -163,33 +169,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 +215,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));
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -10,12 +10,18 @@ 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 PROP_DISABLED = QName.createQName(RULE_MODEL_URI, "disabled");
|
||||
|
||||
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 QName ASPECT_IGNORE_INHERITED_RULES = QName.createQName(RULE_MODEL_URI, "ignoreInheritedRules");
|
||||
}
|
@@ -81,13 +81,11 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
/**
|
||||
* @author Roy Wetherall
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class RuleServiceCoverageTest extends TestCase
|
||||
{
|
||||
//private static final ContentData CONTENT_DATA_TEXT = new ContentData(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, "UTF-8");
|
||||
|
||||
/**
|
||||
/**
|
||||
* Application context used during the test
|
||||
*/
|
||||
static ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:alfresco/application-context.xml");
|
||||
@@ -109,6 +107,7 @@ public class RuleServiceCoverageTest extends TestCase
|
||||
private ActionService actionService;
|
||||
private ContentTransformerRegistry transformerRegistry;
|
||||
private CopyService copyService;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
|
||||
/**
|
||||
* Category related values
|
||||
@@ -147,9 +146,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 +159,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 +169,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 +225,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 +322,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(
|
||||
@@ -342,6 +341,46 @@ public class RuleServiceCoverageTest extends TestCase
|
||||
// System.out.println(NodeStoreInspector.dumpNodeStore(this.nodeService, this.testStoreRef));
|
||||
}
|
||||
|
||||
public void testDisableIndividualRules()
|
||||
{
|
||||
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
|
||||
params.put("aspect-name", ContentModel.ASPECT_CONFIGURABLE);
|
||||
|
||||
Rule rule = createRule(
|
||||
RuleType.INBOUND,
|
||||
AddFeaturesActionExecuter.NAME,
|
||||
params,
|
||||
NoConditionEvaluator.NAME,
|
||||
null);
|
||||
rule.setRuleDisabled(true);
|
||||
|
||||
this.ruleService.saveRule(this.nodeRef, rule);
|
||||
|
||||
NodeRef newNodeRef = this.nodeService.createNode(
|
||||
this.nodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(TEST_NAMESPACE, "children"),
|
||||
ContentModel.TYPE_CONTENT,
|
||||
getContentProperties()).getChildRef();
|
||||
addContentToNode(newNodeRef);
|
||||
assertFalse(this.nodeService.hasAspect(newNodeRef, ContentModel.ASPECT_CONFIGURABLE));
|
||||
|
||||
Rule rule2 = this.ruleService.getRule(rule.getNodeRef());
|
||||
rule2.setRuleDisabled(false);
|
||||
this.ruleService.saveRule(this.nodeRef, rule2);
|
||||
|
||||
// Re-try the test now the rule has been re-enabled
|
||||
NodeRef newNodeRef2 = this.nodeService.createNode(
|
||||
this.nodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(TEST_NAMESPACE, "children"),
|
||||
ContentModel.TYPE_CONTENT,
|
||||
getContentProperties()).getChildRef();
|
||||
addContentToNode(newNodeRef2);
|
||||
assertTrue(this.nodeService.hasAspect(newNodeRef2, ContentModel.ASPECT_CONFIGURABLE));
|
||||
|
||||
}
|
||||
|
||||
public void testDisableRule()
|
||||
{
|
||||
this.nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_LOCKABLE, null);
|
||||
@@ -427,15 +466,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 +1271,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 +1303,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");
|
||||
@@ -1547,4 +1586,62 @@ public class RuleServiceCoverageTest extends TestCase
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAsyncExecutionWithPotentialLoop()
|
||||
{
|
||||
if (this.transformerRegistry.getTransformer(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_TEXT_PLAIN) != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
|
||||
params.put(TransformActionExecuter.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
params.put(TransformActionExecuter.PARAM_DESTINATION_FOLDER, this.nodeRef);
|
||||
params.put(TransformActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS);
|
||||
params.put(TransformActionExecuter.PARAM_ASSOC_QNAME, QName.createQName(TEST_NAMESPACE, "transformed"));
|
||||
|
||||
Rule rule = createRule(
|
||||
RuleType.INBOUND,
|
||||
TransformActionExecuter.NAME,
|
||||
params,
|
||||
NoConditionEvaluator.NAME,
|
||||
null);
|
||||
rule.setExecuteAsynchronously(true);
|
||||
rule.setTitle("Transform document to text");
|
||||
|
||||
UserTransaction tx0 = transactionService.getUserTransaction();
|
||||
tx0.begin();
|
||||
this.ruleService.saveRule(this.nodeRef, rule);
|
||||
tx0.commit();
|
||||
|
||||
UserTransaction tx = transactionService.getUserTransaction();
|
||||
tx.begin();
|
||||
|
||||
Map<QName, Serializable> props =new HashMap<QName, Serializable>(1);
|
||||
props.put(ContentModel.PROP_NAME, "test.xls");
|
||||
|
||||
// Create the node at the root
|
||||
NodeRef newNodeRef = this.nodeService.createNode(
|
||||
this.nodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(TEST_NAMESPACE, "origional"),
|
||||
ContentModel.TYPE_CONTENT,
|
||||
props).getChildRef();
|
||||
|
||||
// Set some content on the origional
|
||||
ContentWriter contentWriter = this.contentService.getWriter(newNodeRef, ContentModel.PROP_CONTENT, true);
|
||||
contentWriter.setMimetype(MimetypeMap.MIMETYPE_EXCEL);
|
||||
File testFile = AbstractContentTransformerTest.loadQuickTestFile("xls");
|
||||
contentWriter.putContent(testFile);
|
||||
|
||||
tx.commit();
|
||||
|
||||
// Sleep to ensure work is done b4 execution is canceled
|
||||
Thread.sleep(10000);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
@@ -40,9 +40,6 @@ import org.alfresco.service.cmr.rule.Rule;
|
||||
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;
|
||||
@@ -90,11 +87,6 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
*/
|
||||
private ActionService actionService;
|
||||
|
||||
/**
|
||||
* The search service
|
||||
*/
|
||||
private SearchService searchService;
|
||||
|
||||
/**
|
||||
* The dictionary service
|
||||
*/
|
||||
@@ -125,7 +117,17 @@ 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 current thread
|
||||
*/
|
||||
private ThreadLocal<Boolean> rulesDisabled = new ThreadLocal<Boolean>();
|
||||
|
||||
/**
|
||||
* Global flag that indicates whether the
|
||||
*/
|
||||
private boolean globalRulesDisabled = false;
|
||||
|
||||
/**
|
||||
* Set the permission-safe node service
|
||||
@@ -167,16 +169,6 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
this.runtimeActionService = runtimeActionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the search service
|
||||
*
|
||||
* @param searchService the search service
|
||||
*/
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the dictionary service
|
||||
*
|
||||
@@ -186,6 +178,16 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the global rules disabled flag
|
||||
*
|
||||
* @param rulesDisabled true to disable allr ules, false otherwise
|
||||
*/
|
||||
public void setRulesDisabled(boolean rulesDisabled)
|
||||
{
|
||||
this.globalRulesDisabled = rulesDisabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the saved rule folder reference
|
||||
@@ -229,6 +231,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.globalRulesDisabled == false && this.rulesDisabled.get() == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleService#rulesEnabled(NodeRef)
|
||||
*/
|
||||
@@ -304,7 +330,7 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
|
||||
if (this.runtimeNodeService.exists(nodeRef) == true && checkNodeType(nodeRef) == true)
|
||||
{
|
||||
if (includeInherited == true)
|
||||
if (includeInherited == true && this.runtimeNodeService.hasAspect(nodeRef, RuleModel.ASPECT_IGNORE_INHERITED_RULES) == false)
|
||||
{
|
||||
// Get any inherited rules
|
||||
for (Rule rule : getInheritedRules(nodeRef, ruleTypeName, null))
|
||||
@@ -331,7 +357,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 +365,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);
|
||||
}
|
||||
@@ -414,131 +440,88 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
private List<Rule> getInheritedRules(NodeRef nodeRef, String ruleTypeName, Set<NodeRef> visitedNodeRefs)
|
||||
{
|
||||
List<Rule> inheritedRules = new ArrayList<Rule>();
|
||||
|
||||
// Create the visited nodes set if it has not already been created
|
||||
if (visitedNodeRefs == null)
|
||||
{
|
||||
visitedNodeRefs = new HashSet<NodeRef>();
|
||||
}
|
||||
|
||||
// This check prevents stack over flow when we have a cyclic node graph
|
||||
if (visitedNodeRefs.contains(nodeRef) == false)
|
||||
{
|
||||
visitedNodeRefs.add(nodeRef);
|
||||
|
||||
List<Rule> allInheritedRules = new ArrayList<Rule>();
|
||||
List<ChildAssociationRef> parents = this.runtimeNodeService.getParentAssocs(nodeRef);
|
||||
for (ChildAssociationRef parent : parents)
|
||||
{
|
||||
List<Rule> rules = getRules(parent.getParentRef(), false);
|
||||
for (Rule rule : rules)
|
||||
{
|
||||
// Add is we hanvn't already added and it should be applied to the children
|
||||
if (rule.isAppliedToChildren() == true && allInheritedRules.contains(rule) == false)
|
||||
{
|
||||
allInheritedRules.add(rule);
|
||||
}
|
||||
}
|
||||
|
||||
for (Rule rule : getInheritedRules(parent.getParentRef(), ruleTypeName, visitedNodeRefs))
|
||||
{
|
||||
// Ensure that we don't get any rule duplication (don't use a set cos we want to preserve order)
|
||||
if (allInheritedRules.contains(rule) == false)
|
||||
{
|
||||
allInheritedRules.add(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ruleTypeName == null)
|
||||
{
|
||||
inheritedRules = allInheritedRules;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Filter the rule list by rule type
|
||||
for (Rule rule : allInheritedRules)
|
||||
{
|
||||
if (rule.getRuleTypeName().equals(ruleTypeName) == true)
|
||||
{
|
||||
inheritedRules.add(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.runtimeNodeService.hasAspect(nodeRef, RuleModel.ASPECT_IGNORE_INHERITED_RULES) == false)
|
||||
{
|
||||
// Create the visited nodes set if it has not already been created
|
||||
if (visitedNodeRefs == null)
|
||||
{
|
||||
visitedNodeRefs = new HashSet<NodeRef>();
|
||||
}
|
||||
|
||||
// This check prevents stack over flow when we have a cyclic node graph
|
||||
if (visitedNodeRefs.contains(nodeRef) == false)
|
||||
{
|
||||
visitedNodeRefs.add(nodeRef);
|
||||
|
||||
List<Rule> allInheritedRules = new ArrayList<Rule>();
|
||||
List<ChildAssociationRef> parents = this.runtimeNodeService.getParentAssocs(nodeRef);
|
||||
for (ChildAssociationRef parent : parents)
|
||||
{
|
||||
// Add the inherited rule first
|
||||
for (Rule rule : getInheritedRules(parent.getParentRef(), ruleTypeName, visitedNodeRefs))
|
||||
{
|
||||
// Ensure that we don't get any rule duplication (don't use a set cos we want to preserve order)
|
||||
if (allInheritedRules.contains(rule) == false)
|
||||
{
|
||||
allInheritedRules.add(rule);
|
||||
}
|
||||
}
|
||||
|
||||
List<Rule> rules = getRules(parent.getParentRef(), false);
|
||||
for (Rule rule : rules)
|
||||
{
|
||||
// Add is we hanvn't already added and it should be applied to the children
|
||||
if (rule.isAppliedToChildren() == true && allInheritedRules.contains(rule) == false)
|
||||
{
|
||||
allInheritedRules.add(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ruleTypeName == null)
|
||||
{
|
||||
inheritedRules = allInheritedRules;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Filter the rule list by rule type
|
||||
for (Rule rule : allInheritedRules)
|
||||
{
|
||||
if (rule.getRuleTypes().contains(ruleTypeName) == true)
|
||||
{
|
||||
inheritedRules.add(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 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,141 @@ 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);
|
||||
|
||||
// Set the disabled value
|
||||
boolean ruleDisabled = false;
|
||||
Boolean value3 = (Boolean)props.get(RuleModel.PROP_DISABLED);
|
||||
if (value3 != null)
|
||||
{
|
||||
ruleDisabled = value3.booleanValue();
|
||||
}
|
||||
rule.setRuleDisabled(ruleDisabled);
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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);
|
||||
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());
|
||||
this.nodeService.setProperty(ruleNodeRef, RuleModel.PROP_DISABLED, rule.getRuleDisabled());
|
||||
|
||||
// Save the rule's action
|
||||
saveAction(ruleNodeRef, rule);
|
||||
}
|
||||
finally
|
||||
{
|
||||
enableRules();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleService#removeRule(org.alfresco.repo.ref.NodeRef, org.alfresco.repo.rule.RuleImpl)
|
||||
* Save the action related to the rule.
|
||||
*
|
||||
* @param ruleNodeRef the node reference representing the rule
|
||||
* @param rule the rule
|
||||
*/
|
||||
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.");
|
||||
}
|
||||
|
||||
// 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.service.cmr.rule.Rule)
|
||||
*/
|
||||
public void removeRule(NodeRef nodeRef, Rule rule)
|
||||
{
|
||||
@@ -618,7 +673,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);
|
||||
@@ -653,27 +708,34 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuntimeRuleService#addRulePendingExecution(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.rule.Rule)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addRulePendingExecution(NodeRef actionableNodeRef, NodeRef actionedUponNodeRef, Rule rule)
|
||||
{
|
||||
addRulePendingExecution(actionableNodeRef, actionedUponNodeRef, rule, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuntimeRuleService#addRulePendingExecution(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.rule.Rule, boolean)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
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.isEnabled() == true &&
|
||||
this.disabledNodeRefs.contains(this.getOwningNodeRef(rule)) == false &&
|
||||
this.disabledRules.contains(rule) == false)
|
||||
{
|
||||
PendingRuleData pendingRuleData = new PendingRuleData(actionableNodeRef, actionedUponNodeRef, rule, executeAtEnd);
|
||||
|
||||
Set<PendingRuleData> pendingRules =
|
||||
(Set<PendingRuleData>) AlfrescoTransactionSupport.getResource(KEY_RULES_PENDING);
|
||||
List<PendingRuleData> pendingRules =
|
||||
(List<PendingRuleData>) AlfrescoTransactionSupport.getResource(KEY_RULES_PENDING);
|
||||
if (pendingRules == null)
|
||||
{
|
||||
// bind pending rules to the current transaction
|
||||
pendingRules = new HashSet<PendingRuleData>();
|
||||
pendingRules = new ArrayList<PendingRuleData>();
|
||||
AlfrescoTransactionSupport.bindResource(KEY_RULES_PENDING, pendingRules);
|
||||
// bind the rule transaction listener
|
||||
AlfrescoTransactionSupport.bindListener(this.ruleTransactionListener);
|
||||
@@ -684,14 +746,17 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent hte same rule being executed more than one in the same transaction
|
||||
pendingRules.add(pendingRuleData);
|
||||
// Prevent the same rule being executed more than once in the same transaction
|
||||
if (pendingRules.contains(pendingRuleData) == false)
|
||||
{
|
||||
pendingRules.add(pendingRuleData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -707,23 +772,16 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
{
|
||||
logger.debug("Creating the executed rules list");
|
||||
}
|
||||
AlfrescoTransactionSupport.bindResource(KEY_RULES_EXECUTED, new HashSet<ExecutedRuleData>());
|
||||
try
|
||||
if (AlfrescoTransactionSupport.getResource(KEY_RULES_EXECUTED) == null)
|
||||
{
|
||||
AlfrescoTransactionSupport.bindResource(KEY_RULES_EXECUTED, new HashSet<ExecutedRuleData>());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,8 +792,8 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
private void executePendingRulesImpl(List<PendingRuleData> executeAtEndRules)
|
||||
{
|
||||
// get the transaction-local rules to execute
|
||||
Set<PendingRuleData> pendingRules =
|
||||
(Set<PendingRuleData>) AlfrescoTransactionSupport.getResource(KEY_RULES_PENDING);
|
||||
List<PendingRuleData> pendingRules =
|
||||
(List<PendingRuleData>) AlfrescoTransactionSupport.getResource(KEY_RULES_PENDING);
|
||||
// only execute if there are rules present
|
||||
if (pendingRules != null && !pendingRules.isEmpty())
|
||||
{
|
||||
@@ -776,22 +834,41 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
|
||||
if (executedRules == null || canExecuteRule(executedRules, actionedUponNodeRef, rule) == true)
|
||||
{
|
||||
// Evaluate the condition
|
||||
if (this.actionService.evaluateAction(rule, 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)
|
||||
executedRules.add(new ExecutedRuleData(actionedUponNodeRef, rule));
|
||||
if (logger.isDebugEnabled() == true)
|
||||
{
|
||||
logger.debug(" ... Adding rule (" + rule.getTitle() + ") and nodeRef (" + actionedUponNodeRef.getId() + ") to executed list");
|
||||
}
|
||||
|
||||
// Execute the rule
|
||||
this.actionService.executeAction(rule, actionedUponNodeRef);
|
||||
}
|
||||
executeRule(rule, actionedUponNodeRef, executedRules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuntimeRuleService#executeRule(org.alfresco.service.cmr.rule.Rule, org.alfresco.service.cmr.repository.NodeRef, java.util.Set)
|
||||
*/
|
||||
public void executeRule(Rule rule, NodeRef actionedUponNodeRef, Set<ExecutedRuleData> executedRules)
|
||||
{
|
||||
// Get the action associated with the rule
|
||||
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(action, actionedUponNodeRef) == true)
|
||||
{
|
||||
if (executedRules != null)
|
||||
{
|
||||
// Add the rule to the executed rule list
|
||||
// (do this before this is executed to prevent rules being added to the pending list)
|
||||
executedRules.add(new ExecutedRuleData(actionedUponNodeRef, rule));
|
||||
if (logger.isDebugEnabled() == true)
|
||||
{
|
||||
logger.debug(" ... Adding rule (" + rule.getTitle() + ") and nodeRef (" + actionedUponNodeRef.getId() + ") to executed list");
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the rule
|
||||
boolean executeAsync = rule.getExecuteAsynchronously();
|
||||
this.actionService.executeAction(action, actionedUponNodeRef, true, executeAsync);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the rule can be executed
|
||||
@@ -900,7 +977,7 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
private class ExecutedRuleData
|
||||
public class ExecutedRuleData
|
||||
{
|
||||
|
||||
protected NodeRef actionableNodeRef;
|
||||
@@ -1005,4 +1082,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;
|
||||
}
|
||||
}
|
||||
|
@@ -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,136 @@ 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());
|
||||
}
|
||||
|
||||
/** Ensure the rules are retrieved in the correct order **/
|
||||
public void testGetRulesOrder()
|
||||
{
|
||||
for (int index = 0; index < 10; index++)
|
||||
{
|
||||
Rule newRule = createTestRule(true, Integer.toString(index));
|
||||
this.ruleService.saveRule(this.nodeRef, newRule);
|
||||
}
|
||||
|
||||
// Check that they are all returned in the correct order
|
||||
List<Rule> rules = this.ruleService.getRules(this.nodeRef);
|
||||
int index = 0;
|
||||
for (Rule rule : rules)
|
||||
{
|
||||
assertEquals(Integer.toString(index), rule.getTitle());
|
||||
index++;
|
||||
}
|
||||
|
||||
// Create a child node
|
||||
NodeRef level1 = createNewNode(this.nodeRef);
|
||||
for (int index2 = 10; index2 < 20; index2++)
|
||||
{
|
||||
Rule newRule = createTestRule(true, Integer.toString(index2));
|
||||
this.ruleService.saveRule(level1, newRule);
|
||||
}
|
||||
|
||||
// Check that they are all returned in the correct order
|
||||
List<Rule> rules2 = this.ruleService.getRules(level1);
|
||||
int index2 = 0;
|
||||
for (Rule rule : rules2)
|
||||
{
|
||||
assertEquals(Integer.toString(index2), rule.getTitle());
|
||||
index2++;
|
||||
}
|
||||
|
||||
// Create a child node
|
||||
NodeRef level2 = createNewNode(level1);
|
||||
for (int index3 = 20; index3 < 30; index3++)
|
||||
{
|
||||
Rule newRule = createTestRule(true, Integer.toString(index3));
|
||||
this.ruleService.saveRule(level2, newRule);
|
||||
}
|
||||
|
||||
// Check that they are all returned in the correct order
|
||||
List<Rule> rules3 = this.ruleService.getRules(level2);
|
||||
int index3 = 0;
|
||||
for (Rule rule : rules3)
|
||||
{
|
||||
//System.out.println(rule.getTitle());
|
||||
assertEquals(Integer.toString(index3), rule.getTitle());
|
||||
index3++;
|
||||
}
|
||||
|
||||
// Update a couple of the rules
|
||||
Rule rule1 = rules3.get(2);
|
||||
rule1.setDescription("This has been changed");
|
||||
this.ruleService.saveRule(this.nodeRef, rule1);
|
||||
Rule rule2 = rules3.get(12);
|
||||
rule2.setDescription("This has been changed");
|
||||
this.ruleService.saveRule(level1, rule2);
|
||||
Rule rule3 = rules3.get(22);
|
||||
rule3.setDescription("This has been changed");
|
||||
this.ruleService.saveRule(level2, rule3);
|
||||
|
||||
// Check that they are all returned in the correct order
|
||||
List<Rule> rules4 = this.ruleService.getRules(level2);
|
||||
int index4 = 0;
|
||||
for (Rule rule : rules4)
|
||||
{
|
||||
assertEquals(Integer.toString(index4), rule.getTitle());
|
||||
index4++;
|
||||
}
|
||||
}
|
||||
|
||||
public void testIgnoreInheritedRules()
|
||||
{
|
||||
// Create the nodes and rules
|
||||
this.ruleService.saveRule(this.nodeRef, createTestRule(true, "rule1"));
|
||||
this.ruleService.saveRule(this.nodeRef, createTestRule(false, "rule2"));
|
||||
NodeRef nodeRef1 = createNewNode(this.nodeRef);
|
||||
this.ruleService.saveRule(nodeRef1, createTestRule(true, "rule3"));
|
||||
this.ruleService.saveRule(nodeRef1, createTestRule(false, "rule4"));
|
||||
NodeRef nodeRef2 = createNewNode(nodeRef1);
|
||||
this.ruleService.saveRule(nodeRef2, createTestRule(true, "rule5"));
|
||||
this.ruleService.saveRule(nodeRef2, createTestRule(false, "rule6"));
|
||||
|
||||
// Apply the ignore aspect
|
||||
this.nodeService.addAspect(nodeRef1, RuleModel.ASPECT_IGNORE_INHERITED_RULES, null);
|
||||
|
||||
// Get the rules
|
||||
List<Rule> rules1 = this.ruleService.getRules(nodeRef2);
|
||||
assertNotNull(rules1);
|
||||
assertEquals(3, rules1.size());
|
||||
assertEquals("rule3", rules1.get(0).getTitle());
|
||||
assertEquals("rule5", rules1.get(1).getTitle());
|
||||
assertEquals("rule6", rules1.get(2).getTitle());
|
||||
|
||||
// Apply the ignore aspect
|
||||
this.nodeService.addAspect(nodeRef2, RuleModel.ASPECT_IGNORE_INHERITED_RULES, null);
|
||||
|
||||
// Get the rules
|
||||
List<Rule> rules2 = this.ruleService.getRules(nodeRef2);
|
||||
assertNotNull(rules2);
|
||||
assertEquals(2, rules2.size());
|
||||
assertEquals("rule5", rules2.get(0).getTitle());
|
||||
assertEquals("rule6", rules2.get(1).getTitle());
|
||||
|
||||
// Remove the ignore aspect
|
||||
this.nodeService.removeAspect(nodeRef1, RuleModel.ASPECT_IGNORE_INHERITED_RULES);
|
||||
this.nodeService.removeAspect(nodeRef2, RuleModel.ASPECT_IGNORE_INHERITED_RULES);
|
||||
|
||||
// Get the rules
|
||||
List<Rule> rules3 = this.ruleService.getRules(nodeRef2);
|
||||
assertNotNull(rules3);
|
||||
assertEquals(4, rules3.size());
|
||||
assertEquals("rule1", rules3.get(0).getTitle());
|
||||
assertEquals("rule3", rules3.get(1).getTitle());
|
||||
assertEquals("rule5", rules3.get(2).getTitle());
|
||||
assertEquals("rule6", rules3.get(3).getTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,13 +288,12 @@ public class RuleServiceImplTest extends BaseRuleTest
|
||||
* @param parent the parent node
|
||||
* @param isActionable indicates whether the node is actionable or not
|
||||
*/
|
||||
private NodeRef createNewNode(NodeRef parent, boolean isActionable)
|
||||
private NodeRef createNewNode(NodeRef parent)
|
||||
{
|
||||
NodeRef newNodeRef = this.nodeService.createNode(parent,
|
||||
return this.nodeService.createNode(parent,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testnode"),
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
return newNodeRef;
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,21 +304,21 @@ public class RuleServiceImplTest extends BaseRuleTest
|
||||
{
|
||||
// Create the nodes and rules
|
||||
|
||||
NodeRef rootWithRules = createNewNode(this.rootNodeRef, true);
|
||||
NodeRef rootWithRules = createNewNode(this.rootNodeRef);
|
||||
Rule rule1 = createTestRule();
|
||||
this.ruleService.saveRule(rootWithRules, rule1);
|
||||
Rule rule2 = createTestRule(true);
|
||||
this.ruleService.saveRule(rootWithRules, rule2);
|
||||
|
||||
NodeRef nonActionableChild = createNewNode(rootWithRules, false);
|
||||
NodeRef nonActionableChild = createNewNode(rootWithRules);
|
||||
|
||||
NodeRef childWithRules = createNewNode(nonActionableChild, true);
|
||||
NodeRef childWithRules = createNewNode(nonActionableChild);
|
||||
Rule rule3 = createTestRule();
|
||||
this.ruleService.saveRule(childWithRules, rule3);
|
||||
Rule rule4 = createTestRule(true);
|
||||
this.ruleService.saveRule(childWithRules, rule4);
|
||||
|
||||
NodeRef rootWithRules2 = createNewNode(this.rootNodeRef, true);
|
||||
NodeRef rootWithRules2 = createNewNode(this.rootNodeRef);
|
||||
this.nodeService.addChild(
|
||||
rootWithRules2,
|
||||
childWithRules,
|
||||
@@ -220,7 +331,7 @@ public class RuleServiceImplTest extends BaseRuleTest
|
||||
|
||||
// Check that the rules are inherited in the correct way
|
||||
|
||||
List<? extends Rule> allRules = this.ruleService.getRules(childWithRules, true);
|
||||
List<? extends Rule> allRules = this.ruleService.getRules(childWithRules);
|
||||
assertNotNull(allRules);
|
||||
assertEquals(4, allRules.size());
|
||||
assertTrue(allRules.contains(rule2));
|
||||
@@ -232,7 +343,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++;
|
||||
}
|
||||
@@ -439,9 +552,9 @@ public class RuleServiceImplTest extends BaseRuleTest
|
||||
public void testCyclicGraphWithInheritedRules()
|
||||
throws Exception
|
||||
{
|
||||
NodeRef nodeRef1 = createNewNode(this.rootNodeRef, true);
|
||||
NodeRef nodeRef2 = createNewNode(nodeRef1, true);
|
||||
NodeRef nodeRef3 = createNewNode(nodeRef2, true);
|
||||
NodeRef nodeRef1 = createNewNode(this.rootNodeRef);
|
||||
NodeRef nodeRef2 = createNewNode(nodeRef1);
|
||||
NodeRef nodeRef3 = createNewNode(nodeRef2);
|
||||
try
|
||||
{
|
||||
this.nodeService.addChild(nodeRef3, nodeRef1, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}loop"));
|
||||
@@ -487,10 +600,10 @@ public class RuleServiceImplTest extends BaseRuleTest
|
||||
*/
|
||||
public void testRuleDuplication()
|
||||
{
|
||||
NodeRef nodeRef1 = createNewNode(this.rootNodeRef, true);
|
||||
NodeRef nodeRef2 = createNewNode(nodeRef1, true);
|
||||
NodeRef nodeRef3 = createNewNode(nodeRef2, true);
|
||||
NodeRef nodeRef4 = createNewNode(nodeRef1, true);
|
||||
NodeRef nodeRef1 = createNewNode(this.rootNodeRef);
|
||||
NodeRef nodeRef2 = createNewNode(nodeRef1);
|
||||
NodeRef nodeRef3 = createNewNode(nodeRef2);
|
||||
NodeRef nodeRef4 = createNewNode(nodeRef1);
|
||||
this.nodeService.addChild(nodeRef4, nodeRef3, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}test"));
|
||||
|
||||
Rule rule1 = createTestRule(true);
|
||||
@@ -534,7 +647,7 @@ public class RuleServiceImplTest extends BaseRuleTest
|
||||
|
||||
public void testCyclicAsyncRules() throws Exception
|
||||
{
|
||||
NodeRef nodeRef = createNewNode(this.rootNodeRef, true);
|
||||
NodeRef nodeRef = createNewNode(this.rootNodeRef);
|
||||
|
||||
// Create the first rule
|
||||
|
||||
@@ -547,17 +660,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 +684,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);
|
||||
|
@@ -21,7 +21,6 @@ import java.util.List;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.repo.action.CommonResourceAbstractBase;
|
||||
import org.alfresco.repo.rule.ruletrigger.RuleTrigger;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
@@ -41,11 +40,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 +61,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
|
||||
*
|
||||
@@ -114,31 +98,50 @@ public class RuleTypeImpl extends CommonResourceAbstractBase implements RuleType
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleType#triggerRuleType(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef)
|
||||
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef, boolean executeRuleImmediately)
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
// Only queue if the rule is not disabled
|
||||
if (rule.getRuleDisabled() == false)
|
||||
{
|
||||
if (executeRuleImmediately == false)
|
||||
{
|
||||
// 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
|
||||
{
|
||||
// Execute the rule now
|
||||
((RuntimeRuleService)this.ruleService).executeRule(rule, actionedUponNodeRef, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -129,7 +129,7 @@ public class RuleTypeImplTest extends BaseSpringTest
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef)
|
||||
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef, boolean executeRuleImmediately)
|
||||
{
|
||||
this.rulesTriggered = true;
|
||||
}
|
||||
|
@@ -16,6 +16,9 @@
|
||||
*/
|
||||
package org.alfresco.repo.rule;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.rule.RuleServiceImpl.ExecutedRuleData;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
@@ -25,6 +28,8 @@ import org.alfresco.service.cmr.rule.RuleType;
|
||||
*/
|
||||
public interface RuntimeRuleService
|
||||
{
|
||||
void executeRule(Rule rule, NodeRef actionedUponNodeRef, Set<ExecutedRuleData> executedRules);
|
||||
|
||||
void addRulePendingExecution(NodeRef actionableNodeRef, NodeRef actionedUponNodeRef, Rule rule);
|
||||
|
||||
void addRulePendingExecution(NodeRef actionableNodeRef, NodeRef actionedUponNodeRef, Rule rule, boolean executeAtEnd);
|
||||
|
@@ -9,28 +9,51 @@
|
||||
<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>
|
||||
<namespace uri="http://www.alfresco.org/model/rule/1.0" prefix="rule"/>
|
||||
</namespaces>
|
||||
|
||||
|
||||
<types>
|
||||
|
||||
<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>
|
||||
<property name="rule:disabled">
|
||||
<type>d:boolean</type>
|
||||
<mandatory>true</mandatory>
|
||||
<default>false</default>
|
||||
</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>
|
||||
@@ -49,6 +72,10 @@
|
||||
</child-association>
|
||||
</associations>
|
||||
</aspect>
|
||||
|
||||
<aspect name="rule:ignoreInheritedRules">
|
||||
<title>Ignore Inherited Rules</title>
|
||||
</aspect>
|
||||
|
||||
</aspects>
|
||||
|
||||
|
@@ -56,6 +56,12 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
||||
/** The dictionary service */
|
||||
protected DictionaryService dictionaryService;
|
||||
|
||||
/**
|
||||
* Indicates whether the rule should be executed immediately or at the end of the transaction.
|
||||
* By default this is false as all rules are executed at the end of the transaction.
|
||||
*/
|
||||
protected boolean executeRuleImmediately = false;
|
||||
|
||||
/**
|
||||
* Set the policy component
|
||||
*
|
||||
@@ -96,6 +102,17 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the values that indicates whether the rule should be executed immediately
|
||||
* or not.
|
||||
*
|
||||
* @param executeRuleImmediately true execute the rule immediaely, false otherwise
|
||||
*/
|
||||
public void setExecuteRuleImmediately(boolean executeRuleImmediately)
|
||||
{
|
||||
this.executeRuleImmediately = executeRuleImmediately;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registration of an interested rule type
|
||||
*/
|
||||
@@ -117,7 +134,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
||||
{
|
||||
for (RuleType ruleType : this.ruleTypes)
|
||||
{
|
||||
ruleType.triggerRuleType(nodeRef, actionedUponNodeRef);
|
||||
ruleType.triggerRuleType(nodeRef, actionedUponNodeRef, this.executeRuleImmediately);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -35,7 +35,6 @@ public class RuleTriggerTest extends BaseSpringTest
|
||||
{
|
||||
private static final String ON_CREATE_NODE_TRIGGER = "on-create-node-trigger";
|
||||
private static final String ON_UPDATE_NODE_TRIGGER = "on-update-node-trigger";
|
||||
private static final String ON_DELETE_NODE_TRIGGER = "on-delete-node-trigger";
|
||||
private static final String ON_CREATE_CHILD_ASSOCIATION_TRIGGER = "on-create-child-association-trigger";
|
||||
private static final String ON_DELETE_CHILD_ASSOCIATION_TRIGGER = "on-delete-child-association-trigger";
|
||||
private static final String ON_CREATE_ASSOCIATION_TRIGGER = "on-create-association-trigger";
|
||||
@@ -93,23 +92,23 @@ public class RuleTriggerTest extends BaseSpringTest
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
}
|
||||
|
||||
public void testOnDeleteNodeTrigger()
|
||||
{
|
||||
NodeRef nodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
|
||||
TestRuleType ruleType = createTestRuleType(ON_DELETE_NODE_TRIGGER);
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Try and trigger the type
|
||||
this.nodeService.deleteNode(nodeRef);
|
||||
|
||||
// Check to see if the rule type has been triggered
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
}
|
||||
// public void testOnDeleteNodeTrigger()
|
||||
// {
|
||||
// NodeRef nodeRef = this.nodeService.createNode(
|
||||
// this.rootNodeRef,
|
||||
// ContentModel.ASSOC_CHILDREN,
|
||||
// ContentModel.ASSOC_CHILDREN,
|
||||
// ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
//
|
||||
// TestRuleType ruleType = createTestRuleType(ON_DELETE_NODE_TRIGGER);
|
||||
// assertFalse(ruleType.rulesTriggered);
|
||||
//
|
||||
// // Try and trigger the type
|
||||
// this.nodeService.deleteNode(nodeRef);
|
||||
//
|
||||
// // Check to see if the rule type has been triggered
|
||||
// assertTrue(ruleType.rulesTriggered);
|
||||
// }
|
||||
|
||||
public void testOnCreateChildAssociationTrigger()
|
||||
{
|
||||
@@ -287,7 +286,7 @@ public class RuleTriggerTest extends BaseSpringTest
|
||||
return "displayLabel";
|
||||
}
|
||||
|
||||
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef)
|
||||
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef, boolean executeRuleImmediately)
|
||||
{
|
||||
// Indicate that the rules have been triggered
|
||||
this.rulesTriggered = true;
|
||||
|
Reference in New Issue
Block a user