mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Moving to root below branch label
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
215
source/java/org/alfresco/repo/rule/BaseRuleTest.java
Normal file
215
source/java/org/alfresco/repo/rule/BaseRuleTest.java
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* 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 java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
|
||||
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
|
||||
import org.alfresco.repo.configuration.ConfigurableService;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
|
||||
/**
|
||||
* Base class for rule service test.
|
||||
* <p>
|
||||
* This file contains a number of helpers to reduce the duplication in tests.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class BaseRuleTest extends BaseSpringTest
|
||||
{
|
||||
/**
|
||||
* Data used in the tests
|
||||
*/
|
||||
protected static final String RULE_TYPE_NAME = RuleType.INBOUND;
|
||||
|
||||
/**
|
||||
* Action used in tests
|
||||
*/
|
||||
protected static final String ACTION_DEF_NAME = AddFeaturesActionExecuter.NAME;
|
||||
protected static final String ACTION_PROP_NAME_1 = AddFeaturesActionExecuter.PARAM_ASPECT_NAME;
|
||||
protected static final QName ACTION_PROP_VALUE_1 = ContentModel.ASPECT_LOCKABLE;
|
||||
|
||||
/**
|
||||
* ActionCondition used in tests
|
||||
*/
|
||||
protected static final String CONDITION_DEF_NAME = ComparePropertyValueEvaluator.NAME;
|
||||
protected static final String COND_PROP_NAME_1 = ComparePropertyValueEvaluator.PARAM_VALUE;
|
||||
protected static final String COND_PROP_VALUE_1 = ".doc";
|
||||
|
||||
/**
|
||||
* Rule values used in tests
|
||||
*/
|
||||
protected static final String TITLE = "title";
|
||||
protected static final String DESCRIPTION = "description";
|
||||
|
||||
/**
|
||||
* Services
|
||||
*/
|
||||
protected NodeService nodeService;
|
||||
protected ContentService contentService;
|
||||
protected RuleService ruleService;
|
||||
protected ConfigurableService configService;
|
||||
protected AuthenticationComponent authenticationComponent;
|
||||
|
||||
/**
|
||||
* Rule type used in tests
|
||||
*/
|
||||
protected RuleType ruleType;
|
||||
|
||||
/**
|
||||
* Store and node references
|
||||
*/
|
||||
protected StoreRef testStoreRef;
|
||||
protected NodeRef rootNodeRef;
|
||||
protected NodeRef nodeRef;
|
||||
protected NodeRef configFolder;
|
||||
protected ActionService actionService;
|
||||
protected TransactionService transactionService;
|
||||
|
||||
/**
|
||||
* onSetUpInTransaction implementation
|
||||
*/
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
// Get the services
|
||||
this.nodeService = (NodeService) this.applicationContext
|
||||
.getBean("nodeService");
|
||||
this.contentService = (ContentService) this.applicationContext
|
||||
.getBean("contentService");
|
||||
this.ruleService = (RuleService) this.applicationContext
|
||||
.getBean("ruleService");
|
||||
this.configService = (ConfigurableService)this.applicationContext
|
||||
.getBean("configurableService");
|
||||
this.actionService = (ActionService)this.applicationContext.getBean("actionService");
|
||||
this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
|
||||
this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");
|
||||
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
// Get the rule type
|
||||
this.ruleType = this.ruleService.getRuleType(RULE_TYPE_NAME);
|
||||
|
||||
// Create the store and get the root node
|
||||
this.testStoreRef = this.nodeService.createStore(
|
||||
StoreRef.PROTOCOL_WORKSPACE, "Test_"
|
||||
+ System.currentTimeMillis());
|
||||
this.rootNodeRef = this.nodeService.getRootNode(this.testStoreRef);
|
||||
|
||||
// Create the node used for tests
|
||||
this.nodeRef = this.nodeService.createNode(rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testnode"),
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTearDownInTransaction()
|
||||
{
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
super.onTearDownInTransaction();
|
||||
}
|
||||
|
||||
protected void addRulesAspect()
|
||||
{
|
||||
// Make the node actionable
|
||||
this.configService.makeConfigurable(this.nodeRef);
|
||||
this.nodeService.addAspect(this.nodeRef, RuleModel.ASPECT_RULES, null);
|
||||
}
|
||||
|
||||
protected Rule createTestRule()
|
||||
{
|
||||
return createTestRule(false);
|
||||
}
|
||||
|
||||
protected Rule createTestRule(boolean isAppliedToChildren)
|
||||
{
|
||||
// Rule properties
|
||||
Map<String, Serializable> conditionProps = new HashMap<String, Serializable>();
|
||||
conditionProps.put(COND_PROP_NAME_1, COND_PROP_VALUE_1);
|
||||
|
||||
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);
|
||||
|
||||
ActionCondition actionCondition = this.actionService.createActionCondition(CONDITION_DEF_NAME);
|
||||
actionCondition.setParameterValues(conditionProps);
|
||||
rule.addActionCondition(actionCondition);
|
||||
|
||||
Action action = this.actionService.createAction(CONDITION_DEF_NAME);
|
||||
action.setParameterValues(conditionProps);
|
||||
rule.addAction(action);
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
protected void checkRule(RuleImpl rule, String id)
|
||||
{
|
||||
// Check the basic details of the rule
|
||||
assertEquals(id, rule.getId());
|
||||
assertEquals(this.ruleType.getName(), rule.getRuleTypeName());
|
||||
assertEquals(TITLE, rule.getTitle());
|
||||
assertEquals(DESCRIPTION, rule.getDescription());
|
||||
|
||||
// Check conditions
|
||||
List<ActionCondition> ruleConditions = rule.getActionConditions();
|
||||
assertNotNull(ruleConditions);
|
||||
assertEquals(1, ruleConditions.size());
|
||||
assertEquals(CONDITION_DEF_NAME, ruleConditions.get(0)
|
||||
.getActionConditionDefinitionName());
|
||||
Map<String, Serializable> condParams = ruleConditions.get(0)
|
||||
.getParameterValues();
|
||||
assertNotNull(condParams);
|
||||
assertEquals(1, condParams.size());
|
||||
assertTrue(condParams.containsKey(COND_PROP_NAME_1));
|
||||
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();
|
||||
assertNotNull(actionParams);
|
||||
assertEquals(1, actionParams.size());
|
||||
assertTrue(actionParams.containsKey(ACTION_PROP_NAME_1));
|
||||
assertEquals(ACTION_PROP_VALUE_1, actionParams.get(ACTION_PROP_NAME_1));
|
||||
}
|
||||
}
|
40
source/java/org/alfresco/repo/rule/RuleCache.java
Normal file
40
source/java/org/alfresco/repo/rule/RuleCache.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.util.List;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
|
||||
/**
|
||||
* Rule cache interface
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public interface RuleCache
|
||||
{
|
||||
List<Rule> getRules(NodeRef nodeRef);
|
||||
|
||||
List<Rule> getInheritedRules(NodeRef nodeRef);
|
||||
|
||||
void setRules(NodeRef nodeRef, List<Rule> rules);
|
||||
|
||||
void setInheritedRules(NodeRef nodeRef, List<Rule> rules);
|
||||
|
||||
void dirtyRules(NodeRef nodeRef);
|
||||
}
|
89
source/java/org/alfresco/repo/rule/RuleImpl.java
Normal file
89
source/java/org/alfresco/repo/rule/RuleImpl.java
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
21
source/java/org/alfresco/repo/rule/RuleModel.java
Normal file
21
source/java/org/alfresco/repo/rule/RuleModel.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package org.alfresco.repo.rule;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Interface containing rule model constants
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
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");
|
||||
}
|
1417
source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java
Normal file
1417
source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java
Normal file
File diff suppressed because it is too large
Load Diff
956
source/java/org/alfresco/repo/rule/RuleServiceImpl.java
Normal file
956
source/java/org/alfresco/repo/rule/RuleServiceImpl.java
Normal file
@@ -0,0 +1,956 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
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.ActionService;
|
||||
import org.alfresco.service.cmr.action.ActionServiceException;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.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;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Rule service implementation.
|
||||
* <p>
|
||||
* This service automatically binds to the transaction flush hooks. It will
|
||||
* therefore participate in any flushes that occur during the transaction as
|
||||
* well.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class RuleServiceImpl implements RuleService, RuntimeRuleService
|
||||
{
|
||||
/** key against which to store rules pending on the current transaction */
|
||||
private static final String KEY_RULES_PENDING = "RuleServiceImpl.PendingRules";
|
||||
|
||||
/** key against which to store executed rules on the current transaction */
|
||||
private static final String KEY_RULES_EXECUTED = "RuleServiceImpl.ExecutedRules";
|
||||
|
||||
/** qname of assoc to rules */
|
||||
private QName ASSOC_NAME_RULES = QName.createQName(RuleModel.RULE_MODEL_URI, "rules");
|
||||
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private static Log logger = LogFactory.getLog(RuleServiceImpl.class);
|
||||
|
||||
/**
|
||||
* The permission-safe node service
|
||||
*/
|
||||
private NodeService nodeService;
|
||||
|
||||
/**
|
||||
* The runtime node service (ignores permissions)
|
||||
*/
|
||||
private NodeService runtimeNodeService;
|
||||
|
||||
/**
|
||||
* The action service
|
||||
*/
|
||||
private ActionService actionService;
|
||||
|
||||
/**
|
||||
* The search service
|
||||
*/
|
||||
private SearchService searchService;
|
||||
|
||||
/**
|
||||
* The dictionary service
|
||||
*/
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
/**
|
||||
* The action service implementation which we need for some things.
|
||||
*/
|
||||
RuntimeActionService runtimeActionService;
|
||||
|
||||
/**
|
||||
* The rule cahce (set by default to an inactive rule cache)
|
||||
*/
|
||||
private RuleCache ruleCache = new InactiveRuleCache();
|
||||
|
||||
/**
|
||||
* List of disabled node refs. The rules associated with these nodes will node be added to the pending list, and
|
||||
* therefore not fired. This list is transient.
|
||||
*/
|
||||
private Set<NodeRef> disabledNodeRefs = new HashSet<NodeRef>(5);
|
||||
|
||||
/**
|
||||
* List of disabled rules. Any rules that appear in this list will not be added to the pending list and therefore
|
||||
* not fired.
|
||||
*/
|
||||
private Set<Rule> disabledRules = new HashSet<Rule>(5);
|
||||
|
||||
/**
|
||||
* All the rule type currently registered
|
||||
*/
|
||||
private Map<String, RuleType> ruleTypes = new HashMap<String, RuleType>();
|
||||
|
||||
/**
|
||||
* The rule transaction listener
|
||||
*/
|
||||
private TransactionListener ruleTransactionListener = new RuleTransactionListener(this);
|
||||
|
||||
/**
|
||||
* Set the permission-safe node service
|
||||
*
|
||||
* @param nodeService the permission-safe node service
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the direct node service
|
||||
*
|
||||
* @param nodeService the node service
|
||||
*/
|
||||
public void setRuntimeNodeService(NodeService runtimeNodeService)
|
||||
{
|
||||
this.runtimeNodeService = runtimeNodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the action service
|
||||
*
|
||||
* @param actionService the action service
|
||||
*/
|
||||
public void setActionService(ActionService actionService)
|
||||
{
|
||||
this.actionService = actionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the runtime action service
|
||||
*
|
||||
* @param actionRegistration the action service
|
||||
*/
|
||||
public void setRuntimeActionService(RuntimeActionService runtimeActionService)
|
||||
{
|
||||
this.runtimeActionService = runtimeActionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the search service
|
||||
*
|
||||
* @param searchService the search service
|
||||
*/
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rule cache
|
||||
*
|
||||
* @param ruleCache the rule cache
|
||||
*/
|
||||
public void setRuleCache(RuleCache ruleCache)
|
||||
{
|
||||
this.ruleCache = ruleCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the dictionary service
|
||||
*
|
||||
* @param dictionaryService the dictionary service
|
||||
*/
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the saved rule folder reference
|
||||
*
|
||||
* @param nodeRef the node reference
|
||||
* @return the node reference
|
||||
*/
|
||||
private NodeRef getSavedRuleFolderRef(NodeRef nodeRef)
|
||||
{
|
||||
NodeRef result = null;
|
||||
|
||||
List<ChildAssociationRef> assocs = this.runtimeNodeService.getChildAssocs(
|
||||
nodeRef,
|
||||
RegexQNamePattern.MATCH_ALL,
|
||||
RuleModel.ASSOC_RULE_FOLDER);
|
||||
if (assocs.size() > 1)
|
||||
{
|
||||
throw new ActionServiceException("There is more than one rule folder, which is invalid.");
|
||||
}
|
||||
else if (assocs.size() == 1)
|
||||
{
|
||||
result = assocs.get(0).getChildRef();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleService#getRuleTypes()
|
||||
*/
|
||||
public List<RuleType> getRuleTypes()
|
||||
{
|
||||
return new ArrayList<RuleType>(this.ruleTypes.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleService#getRuleType(java.lang.String)
|
||||
*/
|
||||
public RuleType getRuleType(String name)
|
||||
{
|
||||
return this.ruleTypes.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleService#rulesEnabled(NodeRef)
|
||||
*/
|
||||
public boolean rulesEnabled(NodeRef nodeRef)
|
||||
{
|
||||
return (this.disabledNodeRefs.contains(nodeRef) == false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleService#disableRules(NodeRef)
|
||||
*/
|
||||
public void disableRules(NodeRef nodeRef)
|
||||
{
|
||||
// Add the node to the set of disabled nodes
|
||||
this.disabledNodeRefs.add(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleService#enableRules(NodeRef)
|
||||
*/
|
||||
public void enableRules(NodeRef nodeRef)
|
||||
{
|
||||
// Remove the node from the set of disabled nodes
|
||||
this.disabledNodeRefs.remove(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleService#disableRule(org.alfresco.service.cmr.rule.Rule)
|
||||
*/
|
||||
public void disableRule(Rule rule)
|
||||
{
|
||||
this.disabledRules.add(rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleService#enableRule(org.alfresco.service.cmr.rule.Rule)
|
||||
*/
|
||||
public void enableRule(Rule rule)
|
||||
{
|
||||
this.disabledRules.remove(rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleService#hasRules(org.alfresco.repo.ref.NodeRef)
|
||||
*/
|
||||
public boolean hasRules(NodeRef nodeRef)
|
||||
{
|
||||
return getRules(nodeRef).size() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleService#getRules(org.alfresco.repo.ref.NodeRef)
|
||||
*/
|
||||
public List<Rule> getRules(NodeRef nodeRef)
|
||||
{
|
||||
return getRules(nodeRef, true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleService#getRules(org.alfresco.repo.ref.NodeRef, boolean)
|
||||
*/
|
||||
public List<Rule> getRules(NodeRef nodeRef, boolean includeInherited)
|
||||
{
|
||||
return getRules(nodeRef, includeInherited, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleService#getRulesByRuleType(org.alfresco.repo.ref.NodeRef, org.alfresco.repo.rule.RuleType)
|
||||
*/
|
||||
public List<Rule> getRules(NodeRef nodeRef, boolean includeInherited, String ruleTypeName)
|
||||
{
|
||||
List<Rule> rules = new ArrayList<Rule>();
|
||||
|
||||
if (this.runtimeNodeService.exists(nodeRef) == true && checkNodeType(nodeRef) == true)
|
||||
{
|
||||
if (includeInherited == true)
|
||||
{
|
||||
// Get any inherited rules
|
||||
for (Rule rule : getInheritedRules(nodeRef, ruleTypeName, null))
|
||||
{
|
||||
// Ensure rules are not duplicated in the list
|
||||
if (rules.contains(rule) == false)
|
||||
{
|
||||
rules.add(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.runtimeNodeService.hasAspect(nodeRef, RuleModel.ASPECT_RULES) == true)
|
||||
{
|
||||
NodeRef ruleFolder = getSavedRuleFolderRef(nodeRef);
|
||||
if (ruleFolder != null)
|
||||
{
|
||||
List<Rule> allRules = this.ruleCache.getRules(nodeRef);
|
||||
if (allRules == null)
|
||||
{
|
||||
allRules = new ArrayList<Rule>();
|
||||
|
||||
// Get the rules for this node
|
||||
List<ChildAssociationRef> ruleChildAssocRefs =
|
||||
this.runtimeNodeService.getChildAssocs(ruleFolder, RegexQNamePattern.MATCH_ALL, ASSOC_NAME_RULES);
|
||||
for (ChildAssociationRef ruleChildAssocRef : ruleChildAssocRefs)
|
||||
{
|
||||
// Create the rule and add to the list
|
||||
NodeRef ruleNodeRef = ruleChildAssocRef.getChildRef();
|
||||
Rule rule = createRule(nodeRef, ruleNodeRef);
|
||||
allRules.add(rule);
|
||||
}
|
||||
|
||||
// Add the list to the cache
|
||||
this.ruleCache.setRules(nodeRef, allRules);
|
||||
}
|
||||
|
||||
// Build the list of rules that is returned to the client
|
||||
for (Rule rule : allRules)
|
||||
{
|
||||
if ((rules.contains(rule) == false) &&
|
||||
(ruleTypeName == null || ruleTypeName.equals(rule.getRuleTypeName()) == true))
|
||||
{
|
||||
rules.add(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks at the type of the node and indicates whether the node can have rules associated with it
|
||||
*
|
||||
* @param nodeRef the node reference
|
||||
* @return true if the node can have rule associated with it (inherited or otherwise)
|
||||
*/
|
||||
private boolean checkNodeType(NodeRef nodeRef)
|
||||
{
|
||||
boolean result = true;
|
||||
|
||||
QName nodeType = this.nodeService.getType(nodeRef);
|
||||
if (this.dictionaryService.isSubClass(nodeType, ContentModel.TYPE_SYSTEM_FOLDER) == true ||
|
||||
this.dictionaryService.isSubClass(nodeType, ActionModel.TYPE_ACTION) == true ||
|
||||
this.dictionaryService.isSubClass(nodeType, ActionModel.TYPE_ACTION_CONDITION) == true ||
|
||||
this.dictionaryService.isSubClass(nodeType, ActionModel.TYPE_ACTION_PARAMETER) == true)
|
||||
{
|
||||
result = false;
|
||||
|
||||
if (logger.isDebugEnabled() == true)
|
||||
{
|
||||
logger.debug("A node of type " + nodeType.toString() + " was checked and can not have rules.");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the inherited rules for a given node reference
|
||||
*
|
||||
* @param nodeRef the nodeRef
|
||||
* @param ruleTypeName the rule type (null if all applicable)
|
||||
* @return a list of inherited rules (empty if none)
|
||||
*/
|
||||
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 = this.ruleCache.getInheritedRules(nodeRef);
|
||||
if (allInheritedRules == null)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the list of inherited rules to the cache
|
||||
this.ruleCache.setInheritedRules(nodeRef, allInheritedRules);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// Get the rule properties
|
||||
Map<QName, Serializable> props = this.nodeService.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
|
||||
boolean isAppliedToChildren = false;
|
||||
Boolean value = (Boolean)props.get(RuleModel.PROP_APPLY_TO_CHILDREN);
|
||||
if (value != null)
|
||||
{
|
||||
isAppliedToChildren = value.booleanValue();
|
||||
}
|
||||
rule.applyToChildren(isAppliedToChildren);
|
||||
|
||||
// Populate the composite action details
|
||||
runtimeActionService.populateCompositeAction(ruleNodeRef, rule);
|
||||
|
||||
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,
|
||||
ASSOC_NAME_RULES,
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleService#removeRule(org.alfresco.repo.ref.NodeRef, org.alfresco.repo.rule.RuleImpl)
|
||||
*/
|
||||
public void removeRule(NodeRef nodeRef, Rule rule)
|
||||
{
|
||||
if (this.nodeService.exists(nodeRef) == true &&
|
||||
this.nodeService.hasAspect(nodeRef, RuleModel.ASPECT_RULES) == true)
|
||||
{
|
||||
disableRules(nodeRef);
|
||||
try
|
||||
{
|
||||
NodeRef ruleNodeRef = getRuleNodeRefFromId(nodeRef, rule.getId());
|
||||
if (ruleNodeRef != null)
|
||||
{
|
||||
this.nodeService.removeChild(getSavedRuleFolderRef(nodeRef), ruleNodeRef);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
enableRules(nodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleService#removeAllRules(NodeRef)
|
||||
*/
|
||||
public void removeAllRules(NodeRef nodeRef)
|
||||
{
|
||||
if (this.nodeService.exists(nodeRef) == true &&
|
||||
this.nodeService.hasAspect(nodeRef, RuleModel.ASPECT_RULES) == true)
|
||||
{
|
||||
NodeRef folder = getSavedRuleFolderRef(nodeRef);
|
||||
if (folder != null)
|
||||
{
|
||||
List<ChildAssociationRef> ruleChildAssocs = this.nodeService.getChildAssocs(
|
||||
folder,
|
||||
RegexQNamePattern.MATCH_ALL, ASSOC_NAME_RULES);
|
||||
for (ChildAssociationRef ruleChildAssoc : ruleChildAssocs)
|
||||
{
|
||||
this.nodeService.removeChild(folder, ruleChildAssoc.getChildRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addRulePendingExecution(NodeRef actionableNodeRef, NodeRef actionedUponNodeRef, Rule rule)
|
||||
{
|
||||
addRulePendingExecution(actionableNodeRef, actionedUponNodeRef, rule, false);
|
||||
}
|
||||
|
||||
@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 &&
|
||||
this.disabledRules.contains(rule) == false)
|
||||
{
|
||||
PendingRuleData pendingRuleData = new PendingRuleData(actionableNodeRef, actionedUponNodeRef, rule, executeAtEnd);
|
||||
Set<ExecutedRuleData> executedRules =
|
||||
(Set<ExecutedRuleData>) AlfrescoTransactionSupport.getResource(KEY_RULES_EXECUTED);
|
||||
|
||||
if (executedRules == null || executedRules.contains(new ExecutedRuleData(actionableNodeRef, rule)) == false)
|
||||
{
|
||||
Set<PendingRuleData> pendingRules =
|
||||
(Set<PendingRuleData>) AlfrescoTransactionSupport.getResource(KEY_RULES_PENDING);
|
||||
if (pendingRules == null)
|
||||
{
|
||||
// bind pending rules to the current transaction
|
||||
pendingRules = new HashSet<PendingRuleData>();
|
||||
AlfrescoTransactionSupport.bindResource(KEY_RULES_PENDING, pendingRules);
|
||||
// bind the rule transaction listener
|
||||
AlfrescoTransactionSupport.bindListener(this.ruleTransactionListener);
|
||||
|
||||
if (logger.isDebugEnabled() == true)
|
||||
{
|
||||
logger.debug("Rule '" + rule.getTitle() + "' has been added pending execution to action upon node '" + actionedUponNodeRef.getId() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent hte same rule being executed more than one in the same transaction
|
||||
pendingRules.add(pendingRuleData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled() == true)
|
||||
{
|
||||
logger.debug("The rule '" + rule.getTitle() + "' or the node '" + rule.getOwningNodeRef().getId() + "' has been disabled.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleService#executePendingRules()
|
||||
*/
|
||||
public void executePendingRules()
|
||||
{
|
||||
AlfrescoTransactionSupport.bindResource(KEY_RULES_EXECUTED, new HashSet<ExecutedRuleData>());
|
||||
try
|
||||
{
|
||||
List<PendingRuleData> executeAtEndRules = new ArrayList<PendingRuleData>();
|
||||
executePendingRulesImpl(executeAtEndRules);
|
||||
for (PendingRuleData data : executeAtEndRules)
|
||||
{
|
||||
executePendingRule(data);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
AlfrescoTransactionSupport.unbindResource(KEY_RULES_EXECUTED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the pending rules, iterating until all pending rules have been executed
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void executePendingRulesImpl(List<PendingRuleData> executeAtEndRules)
|
||||
{
|
||||
// get the transaction-local rules to execute
|
||||
Set<PendingRuleData> pendingRules =
|
||||
(Set<PendingRuleData>) AlfrescoTransactionSupport.getResource(KEY_RULES_PENDING);
|
||||
// only execute if there are rules present
|
||||
if (pendingRules != null && !pendingRules.isEmpty())
|
||||
{
|
||||
PendingRuleData[] pendingRulesArr = pendingRules.toArray(new PendingRuleData[0]);
|
||||
// remove all pending rules from the transaction
|
||||
AlfrescoTransactionSupport.unbindResource(KEY_RULES_PENDING);
|
||||
// execute each rule
|
||||
for (PendingRuleData pendingRule : pendingRulesArr)
|
||||
{
|
||||
if (pendingRule.getExecuteAtEnd() == false)
|
||||
{
|
||||
executePendingRule(pendingRule);
|
||||
}
|
||||
else
|
||||
{
|
||||
executeAtEndRules.add(pendingRule);
|
||||
}
|
||||
}
|
||||
|
||||
// Run any rules that have been marked as pending during execution
|
||||
executePendingRulesImpl(executeAtEndRules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a pending rule
|
||||
*
|
||||
* @param pendingRule the pending rule data object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void executePendingRule(PendingRuleData pendingRule)
|
||||
{
|
||||
NodeRef actionableNodeRef = pendingRule.getActionableNodeRef();
|
||||
NodeRef actionedUponNodeRef = pendingRule.getActionedUponNodeRef();
|
||||
Rule rule = pendingRule.getRule();
|
||||
|
||||
// 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)
|
||||
Set<ExecutedRuleData> executedRules =
|
||||
(Set<ExecutedRuleData>) AlfrescoTransactionSupport.getResource(KEY_RULES_EXECUTED);
|
||||
executedRules.add(new ExecutedRuleData(actionableNodeRef, rule));
|
||||
|
||||
// Execute the rule
|
||||
this.actionService.executeAction(rule, actionedUponNodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the rule type
|
||||
*
|
||||
* @param ruleTypeAdapter the rule type adapter
|
||||
*/
|
||||
public void registerRuleType(RuleType ruleType)
|
||||
{
|
||||
this.ruleTypes.put(ruleType.getName(), ruleType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to contain the information about a rule that is executed
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
private class ExecutedRuleData
|
||||
{
|
||||
|
||||
protected NodeRef actionableNodeRef;
|
||||
protected Rule rule;
|
||||
|
||||
public ExecutedRuleData(NodeRef actionableNodeRef, Rule rule)
|
||||
{
|
||||
this.actionableNodeRef = actionableNodeRef;
|
||||
this.rule = rule;
|
||||
}
|
||||
|
||||
public NodeRef getActionableNodeRef()
|
||||
{
|
||||
return actionableNodeRef;
|
||||
}
|
||||
|
||||
public Rule getRule()
|
||||
{
|
||||
return rule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int i = actionableNodeRef.hashCode();
|
||||
i = (i*37) + rule.hashCode();
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof ExecutedRuleData)
|
||||
{
|
||||
ExecutedRuleData that = (ExecutedRuleData) obj;
|
||||
return (this.actionableNodeRef.equals(that.actionableNodeRef) &&
|
||||
this.rule.equals(that.rule));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to contain the information about a rule that is pending execution
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
private class PendingRuleData extends ExecutedRuleData
|
||||
{
|
||||
private NodeRef actionedUponNodeRef;
|
||||
private boolean executeAtEnd = false;
|
||||
|
||||
public PendingRuleData(NodeRef actionableNodeRef, NodeRef actionedUponNodeRef, Rule rule, boolean executeAtEnd)
|
||||
{
|
||||
super(actionableNodeRef, rule);
|
||||
this.actionedUponNodeRef = actionedUponNodeRef;
|
||||
this.executeAtEnd = executeAtEnd;
|
||||
}
|
||||
|
||||
public NodeRef getActionedUponNodeRef()
|
||||
{
|
||||
return actionedUponNodeRef;
|
||||
}
|
||||
|
||||
public boolean getExecuteAtEnd()
|
||||
{
|
||||
return this.executeAtEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int i = super.hashCode();
|
||||
i = (i*37) + actionedUponNodeRef.hashCode();
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof PendingRuleData)
|
||||
{
|
||||
PendingRuleData that = (PendingRuleData) obj;
|
||||
return (this.actionableNodeRef.equals(that.actionableNodeRef) &&
|
||||
this.actionedUponNodeRef.equals(that.actionedUponNodeRef) &&
|
||||
this.rule.equals(that.rule));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inactive rule cache
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
private class InactiveRuleCache implements RuleCache
|
||||
{
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleCache#getRules(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public List<Rule> getRules(NodeRef nodeRef)
|
||||
{
|
||||
// do nothing
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleCache#setRules(org.alfresco.service.cmr.repository.NodeRef, List<Rule>)
|
||||
*/
|
||||
public void setRules(NodeRef nodeRef, List<Rule> rules)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleCache#dirtyRules(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public void dirtyRules(NodeRef nodeRef)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleCache#getInheritedRules(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public List<Rule> getInheritedRules(NodeRef nodeRef)
|
||||
{
|
||||
// do nothing
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.RuleCache#setInheritedRules(org.alfresco.service.cmr.repository.NodeRef, List<Rule>)
|
||||
*/
|
||||
public void setInheritedRules(NodeRef nodeRef, List<Rule> rules)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
625
source/java/org/alfresco/repo/rule/RuleServiceImplTest.java
Normal file
625
source/java/org/alfresco/repo/rule/RuleServiceImplTest.java
Normal file
@@ -0,0 +1,625 @@
|
||||
/*
|
||||
* 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.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
|
||||
import org.alfresco.repo.action.executer.ImageTransformActionExecuter;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.CyclicChildRelationshipException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* Rule service implementation test
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class RuleServiceImplTest extends BaseRuleTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Test get rule type
|
||||
*/
|
||||
public void testGetRuleType()
|
||||
{
|
||||
List<RuleType> ruleTypes = this.ruleService.getRuleTypes();
|
||||
assertNotNull(ruleTypes);
|
||||
|
||||
// Visual check to make sure that the display labels are being returned correctly
|
||||
for (RuleType type : ruleTypes)
|
||||
{
|
||||
System.out.println(type.getDisplayLabel());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test createRule
|
||||
*/
|
||||
public void testCreateRule()
|
||||
{
|
||||
Rule newRule = this.ruleService.createRule("ruleType1");
|
||||
assertNotNull(newRule);
|
||||
assertNotNull(newRule.getId());
|
||||
assertEquals("ruleType1", newRule.getRuleTypeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test addRule
|
||||
*
|
||||
*/
|
||||
public void testAddRule()
|
||||
{
|
||||
Rule newRule = createTestRule();
|
||||
String ruleId = newRule.getId();
|
||||
this.ruleService.saveRule(this.nodeRef, newRule);
|
||||
|
||||
Rule savedRule = this.ruleService.getRule(this.nodeRef, ruleId);
|
||||
assertNotNull(savedRule);
|
||||
assertFalse(savedRule.isAppliedToChildren());
|
||||
|
||||
savedRule.applyToChildren(true);
|
||||
this.ruleService.saveRule(this.nodeRef, savedRule);
|
||||
|
||||
Rule savedRule2 = this.ruleService.getRule(this.nodeRef, ruleId);
|
||||
assertNotNull(savedRule2);
|
||||
assertTrue(savedRule2.isAppliedToChildren());
|
||||
}
|
||||
|
||||
public void testRemoveAllRules()
|
||||
{
|
||||
this.ruleService.removeAllRules(this.nodeRef);
|
||||
List<Rule> rules1 = this.ruleService.getRules(this.nodeRef);
|
||||
assertNotNull(rules1);
|
||||
assertEquals(0, rules1.size());
|
||||
|
||||
Rule newRule = this.ruleService.createRule(ruleType.getName());
|
||||
this.ruleService.saveRule(this.nodeRef, newRule);
|
||||
Rule newRule2 = this.ruleService.createRule(ruleType.getName());
|
||||
this.ruleService.saveRule(this.nodeRef, newRule2);
|
||||
|
||||
List<Rule> rules2 = this.ruleService.getRules(this.nodeRef);
|
||||
assertNotNull(rules2);
|
||||
assertEquals(2, rules2.size());
|
||||
|
||||
this.ruleService.removeAllRules(this.nodeRef);
|
||||
|
||||
List<Rule> rules3 = this.ruleService.getRules(this.nodeRef);
|
||||
assertNotNull(rules3);
|
||||
assertEquals(0, rules3.size());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get rules
|
||||
*/
|
||||
public void testGetRules()
|
||||
{
|
||||
// Check that there are no rules associationed with the node
|
||||
List<Rule> noRules = this.ruleService.getRules(this.nodeRef);
|
||||
assertNotNull(noRules);
|
||||
assertEquals(0, noRules.size());
|
||||
|
||||
// Check that we still get nothing back after the details of the node
|
||||
// have been cached in the rule store
|
||||
List<Rule> noRulesAfterCache = this.ruleService.getRules(this.nodeRef);
|
||||
assertNotNull(noRulesAfterCache);
|
||||
assertEquals(0, noRulesAfterCache.size());
|
||||
|
||||
// Add a rule to the node
|
||||
testAddRule();
|
||||
|
||||
// Get the rule from the rule service
|
||||
List<Rule> rules = this.ruleService.getRules(this.nodeRef);
|
||||
assertNotNull(rules);
|
||||
assertEquals(1, rules.size());
|
||||
|
||||
// Check the details of the rule
|
||||
Rule rule = rules.get(0);
|
||||
assertEquals("title", rule.getTitle());
|
||||
assertEquals("description", rule.getDescription());
|
||||
assertNotNull(rule.getCreatedDate());
|
||||
assertNotNull(rule.getModifiedDate());
|
||||
|
||||
// Check that the condition action have been retireved correctly
|
||||
List<ActionCondition> conditions = rule.getActionConditions();
|
||||
assertNotNull(conditions);
|
||||
assertEquals(1, conditions.size());
|
||||
List<Action> actions = rule.getActions();
|
||||
assertNotNull(actions);
|
||||
assertEquals(1, actions.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test disabling the rules
|
||||
*/
|
||||
public void testRulesDisabled()
|
||||
{
|
||||
testAddRule();
|
||||
assertTrue(this.ruleService.rulesEnabled(this.nodeRef));
|
||||
this.ruleService.disableRules(this.nodeRef);
|
||||
assertFalse(this.ruleService.rulesEnabled(this.nodeRef));
|
||||
this.ruleService.enableRules(this.nodeRef);
|
||||
assertTrue(this.ruleService.rulesEnabled(this.nodeRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to easily create a new node which can be actionable (or not)
|
||||
*
|
||||
* @param parent the parent node
|
||||
* @param isActionable indicates whether the node is actionable or not
|
||||
*/
|
||||
private NodeRef createNewNode(NodeRef parent, boolean isActionable)
|
||||
{
|
||||
NodeRef newNodeRef = this.nodeService.createNode(parent,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testnode"),
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
return newNodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the rule inheritance within the store, checking that the cache is reset correctly when
|
||||
* rules are added and removed.
|
||||
*/
|
||||
public void testRuleInheritance()
|
||||
{
|
||||
// Create the nodes and rules
|
||||
|
||||
NodeRef rootWithRules = createNewNode(this.rootNodeRef, true);
|
||||
Rule rule1 = createTestRule();
|
||||
this.ruleService.saveRule(rootWithRules, rule1);
|
||||
Rule rule2 = createTestRule(true);
|
||||
this.ruleService.saveRule(rootWithRules, rule2);
|
||||
|
||||
NodeRef nonActionableChild = createNewNode(rootWithRules, false);
|
||||
|
||||
NodeRef childWithRules = createNewNode(nonActionableChild, true);
|
||||
Rule rule3 = createTestRule();
|
||||
this.ruleService.saveRule(childWithRules, rule3);
|
||||
Rule rule4 = createTestRule(true);
|
||||
this.ruleService.saveRule(childWithRules, rule4);
|
||||
|
||||
NodeRef rootWithRules2 = createNewNode(this.rootNodeRef, true);
|
||||
this.nodeService.addChild(
|
||||
rootWithRules2,
|
||||
childWithRules,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testnode"));
|
||||
Rule rule5 = createTestRule();
|
||||
this.ruleService.saveRule(rootWithRules2, rule5);
|
||||
Rule rule6 = createTestRule(true);
|
||||
this.ruleService.saveRule(rootWithRules2, rule6);
|
||||
|
||||
// Check that the rules are inherited in the correct way
|
||||
|
||||
List<? extends Rule> allRules = this.ruleService.getRules(childWithRules, true);
|
||||
assertNotNull(allRules);
|
||||
assertEquals(4, allRules.size());
|
||||
assertTrue(allRules.contains(rule2));
|
||||
assertTrue(allRules.contains(rule3));
|
||||
assertTrue(allRules.contains(rule4));
|
||||
assertTrue(allRules.contains(rule6));
|
||||
|
||||
// Check the owning node ref
|
||||
int count = 0;
|
||||
for (Rule rule : allRules)
|
||||
{
|
||||
if (rule.getOwningNodeRef() == childWithRules)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
assertEquals(2, count);
|
||||
|
||||
List<? extends Rule> myRules = this.ruleService.getRules(childWithRules, false);
|
||||
assertNotNull(myRules);
|
||||
assertEquals(2, myRules.size());
|
||||
assertTrue(myRules.contains(rule3));
|
||||
assertTrue(myRules.contains(rule4));
|
||||
|
||||
List<? extends Rule> allRules2 = this.ruleService.getRules(nonActionableChild, true);
|
||||
assertNotNull(allRules2);
|
||||
assertEquals(1, allRules2.size());
|
||||
assertTrue(allRules2.contains(rule2));
|
||||
|
||||
List<? extends Rule> myRules2 = this.ruleService.getRules(nonActionableChild, false);
|
||||
assertNotNull(myRules2);
|
||||
assertEquals(0, myRules2.size());
|
||||
|
||||
List<? extends Rule> allRules3 = this.ruleService.getRules(rootWithRules, true);
|
||||
assertNotNull(allRules3);
|
||||
assertEquals(2, allRules3.size());
|
||||
assertTrue(allRules3.contains(rule1));
|
||||
assertTrue(allRules3.contains(rule2));
|
||||
|
||||
List<? extends Rule> myRules3 = this.ruleService.getRules(rootWithRules, false);
|
||||
assertNotNull(myRules3);
|
||||
assertEquals(2, myRules3.size());
|
||||
assertTrue(myRules3.contains(rule1));
|
||||
assertTrue(myRules3.contains(rule2));
|
||||
|
||||
List<? extends Rule> allRules4 = this.ruleService.getRules(rootWithRules2, true);
|
||||
assertNotNull(allRules4);
|
||||
assertEquals(2, allRules4.size());
|
||||
assertTrue(allRules4.contains(rule5));
|
||||
assertTrue(allRules4.contains(rule6));
|
||||
|
||||
List<? extends Rule> myRules4 = this.ruleService.getRules(rootWithRules2, false);
|
||||
assertNotNull(myRules4);
|
||||
assertEquals(2, myRules4.size());
|
||||
assertTrue(myRules4.contains(rule5));
|
||||
assertTrue(myRules4.contains(rule6));
|
||||
|
||||
// Take the root node and add another rule
|
||||
|
||||
Rule rule7 = createTestRule(true);
|
||||
this.ruleService.saveRule(rootWithRules, rule7);
|
||||
|
||||
List<? extends Rule> allRules5 = this.ruleService.getRules(childWithRules, true);
|
||||
assertNotNull(allRules5);
|
||||
assertEquals(5, allRules5.size());
|
||||
assertTrue(allRules5.contains(rule2));
|
||||
assertTrue(allRules5.contains(rule3));
|
||||
assertTrue(allRules5.contains(rule4));
|
||||
assertTrue(allRules5.contains(rule6));
|
||||
assertTrue(allRules5.contains(rule7));
|
||||
|
||||
List<? extends Rule> allRules6 = this.ruleService.getRules(nonActionableChild, true);
|
||||
assertNotNull(allRules6);
|
||||
assertEquals(2, allRules6.size());
|
||||
assertTrue(allRules6.contains(rule2));
|
||||
assertTrue(allRules6.contains(rule7));
|
||||
|
||||
List<? extends Rule> allRules7 = this.ruleService.getRules(rootWithRules, true);
|
||||
assertNotNull(allRules7);
|
||||
assertEquals(3, allRules7.size());
|
||||
assertTrue(allRules7.contains(rule1));
|
||||
assertTrue(allRules7.contains(rule2));
|
||||
assertTrue(allRules7.contains(rule7));
|
||||
|
||||
List<? extends Rule> allRules8 = this.ruleService.getRules(rootWithRules2, true);
|
||||
assertNotNull(allRules8);
|
||||
assertEquals(2, allRules8.size());
|
||||
assertTrue(allRules8.contains(rule5));
|
||||
assertTrue(allRules8.contains(rule6));
|
||||
|
||||
// Take the root node and and remove a rule
|
||||
|
||||
this.ruleService.removeRule(rootWithRules, rule7);
|
||||
|
||||
List<? extends Rule> allRules9 = this.ruleService.getRules(childWithRules, true);
|
||||
assertNotNull(allRules9);
|
||||
assertEquals(4, allRules9.size());
|
||||
assertTrue(allRules9.contains(rule2));
|
||||
assertTrue(allRules9.contains(rule3));
|
||||
assertTrue(allRules9.contains(rule4));
|
||||
assertTrue(allRules9.contains(rule6));
|
||||
|
||||
List<? extends Rule> allRules10 = this.ruleService.getRules(nonActionableChild, true);
|
||||
assertNotNull(allRules10);
|
||||
assertEquals(1, allRules10.size());
|
||||
assertTrue(allRules10.contains(rule2));
|
||||
|
||||
List<? extends Rule> allRules11 = this.ruleService.getRules(rootWithRules, true);
|
||||
assertNotNull(allRules11);
|
||||
assertEquals(2, allRules11.size());
|
||||
assertTrue(allRules11.contains(rule1));
|
||||
assertTrue(allRules11.contains(rule2));
|
||||
|
||||
List<? extends Rule> allRules12 = this.ruleService.getRules(rootWithRules2, true);
|
||||
assertNotNull(allRules12);
|
||||
assertEquals(2, allRules12.size());
|
||||
assertTrue(allRules12.contains(rule5));
|
||||
assertTrue(allRules12.contains(rule6));
|
||||
|
||||
// Delete an association
|
||||
|
||||
this.nodeService.removeChild(rootWithRules2, childWithRules);
|
||||
|
||||
List<? extends Rule> allRules13 = this.ruleService.getRules(childWithRules, true);
|
||||
assertNotNull(allRules13);
|
||||
assertEquals(3, allRules13.size());
|
||||
assertTrue(allRules13.contains(rule2));
|
||||
assertTrue(allRules13.contains(rule3));
|
||||
assertTrue(allRules13.contains(rule4));
|
||||
|
||||
List<? extends Rule> allRules14 = this.ruleService.getRules(nonActionableChild, true);
|
||||
assertNotNull(allRules14);
|
||||
assertEquals(1, allRules14.size());
|
||||
assertTrue(allRules14.contains(rule2));
|
||||
|
||||
List<? extends Rule> allRules15 = this.ruleService.getRules(rootWithRules, true);
|
||||
assertNotNull(allRules15);
|
||||
assertEquals(2, allRules15.size());
|
||||
assertTrue(allRules15.contains(rule1));
|
||||
assertTrue(allRules15.contains(rule2));
|
||||
|
||||
List<? extends Rule> allRules16 = this.ruleService.getRules(rootWithRules2, true);
|
||||
assertNotNull(allRules16);
|
||||
assertEquals(2, allRules16.size());
|
||||
assertTrue(allRules16.contains(rule5));
|
||||
assertTrue(allRules16.contains(rule6));
|
||||
|
||||
this.ruleService.disableRules(rootWithRules2);
|
||||
try
|
||||
{
|
||||
// Add an association
|
||||
this.nodeService.addChild(
|
||||
rootWithRules2,
|
||||
childWithRules,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testnode"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.ruleService.enableRules(rootWithRules2);
|
||||
}
|
||||
|
||||
List<? extends Rule> allRules17 = this.ruleService.getRules(childWithRules, true);
|
||||
assertNotNull(allRules17);
|
||||
assertEquals(4, allRules17.size());
|
||||
assertTrue(allRules17.contains(rule2));
|
||||
assertTrue(allRules17.contains(rule3));
|
||||
assertTrue(allRules17.contains(rule4));
|
||||
assertTrue(allRules17.contains(rule6));
|
||||
|
||||
List<? extends Rule> allRules18 = this.ruleService.getRules(nonActionableChild, true);
|
||||
assertNotNull(allRules18);
|
||||
assertEquals(1, allRules18.size());
|
||||
assertTrue(allRules18.contains(rule2));
|
||||
|
||||
List<? extends Rule> allRules19 = this.ruleService.getRules(rootWithRules, true);
|
||||
assertNotNull(allRules19);
|
||||
assertEquals(2, allRules19.size());
|
||||
assertTrue(allRules19.contains(rule1));
|
||||
assertTrue(allRules19.contains(rule2));
|
||||
|
||||
List<? extends Rule> allRules20 = this.ruleService.getRules(rootWithRules2, true);
|
||||
assertNotNull(allRules20);
|
||||
assertEquals(2, allRules20.size());
|
||||
assertTrue(allRules20.contains(rule5));
|
||||
assertTrue(allRules20.contains(rule6));
|
||||
|
||||
// Delete node
|
||||
|
||||
this.nodeService.deleteNode(rootWithRules2);
|
||||
|
||||
List<? extends Rule> allRules21 = this.ruleService.getRules(childWithRules, true);
|
||||
assertNotNull(allRules21);
|
||||
assertEquals(3, allRules21.size());
|
||||
assertTrue(allRules21.contains(rule2));
|
||||
assertTrue(allRules21.contains(rule3));
|
||||
assertTrue(allRules21.contains(rule4));
|
||||
|
||||
List<? extends Rule> allRules22 = this.ruleService.getRules(nonActionableChild, true);
|
||||
assertNotNull(allRules22);
|
||||
assertEquals(1, allRules22.size());
|
||||
assertTrue(allRules22.contains(rule2));
|
||||
|
||||
List<? extends Rule> allRules23 = this.ruleService.getRules(rootWithRules, true);
|
||||
assertNotNull(allRules23);
|
||||
assertEquals(2, allRules23.size());
|
||||
assertTrue(allRules23.contains(rule1));
|
||||
assertTrue(allRules23.contains(rule2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the rule store can cope with a cyclic node graph
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testCyclicGraphWithInheritedRules()
|
||||
throws Exception
|
||||
{
|
||||
NodeRef nodeRef1 = createNewNode(this.rootNodeRef, true);
|
||||
NodeRef nodeRef2 = createNewNode(nodeRef1, true);
|
||||
NodeRef nodeRef3 = createNewNode(nodeRef2, true);
|
||||
try
|
||||
{
|
||||
this.nodeService.addChild(nodeRef3, nodeRef1, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}loop"));
|
||||
fail("Expected detection of cyclic relationship");
|
||||
}
|
||||
catch (CyclicChildRelationshipException e)
|
||||
{
|
||||
// expected
|
||||
// the node will still have been created in the current transaction, although the txn will be rollback-only
|
||||
}
|
||||
|
||||
Rule rule1 = createTestRule(true);
|
||||
this.ruleService.saveRule(nodeRef1, rule1);
|
||||
Rule rule2 = createTestRule(true);
|
||||
this.ruleService.saveRule(nodeRef2, rule2);
|
||||
Rule rule3 = createTestRule(true);
|
||||
this.ruleService.saveRule(nodeRef3, rule3);
|
||||
|
||||
List<? extends Rule> allRules1 = this.ruleService.getRules(nodeRef1, true);
|
||||
assertNotNull(allRules1);
|
||||
assertEquals(3, allRules1.size());
|
||||
assertTrue(allRules1.contains(rule1));
|
||||
assertTrue(allRules1.contains(rule2));
|
||||
assertTrue(allRules1.contains(rule3));
|
||||
|
||||
List<? extends Rule> allRules2 = this.ruleService.getRules(nodeRef2, true);
|
||||
assertNotNull(allRules2);
|
||||
assertEquals(3, allRules2.size());
|
||||
assertTrue(allRules2.contains(rule1));
|
||||
assertTrue(allRules2.contains(rule2));
|
||||
assertTrue(allRules2.contains(rule3));
|
||||
|
||||
List<? extends Rule> allRules3 = this.ruleService.getRules(nodeRef3, true);
|
||||
assertNotNull(allRules3);
|
||||
assertEquals(3, allRules3.size());
|
||||
assertTrue(allRules3.contains(rule1));
|
||||
assertTrue(allRules3.contains(rule2));
|
||||
assertTrue(allRules3.contains(rule3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that rules are not duplicated when inherited
|
||||
*/
|
||||
public void testRuleDuplication()
|
||||
{
|
||||
NodeRef nodeRef1 = createNewNode(this.rootNodeRef, true);
|
||||
NodeRef nodeRef2 = createNewNode(nodeRef1, true);
|
||||
NodeRef nodeRef3 = createNewNode(nodeRef2, true);
|
||||
NodeRef nodeRef4 = createNewNode(nodeRef1, true);
|
||||
this.nodeService.addChild(nodeRef4, nodeRef3, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}test"));
|
||||
|
||||
Rule rule1 = createTestRule(true);
|
||||
this.ruleService.saveRule(nodeRef1, rule1);
|
||||
Rule rule2 = createTestRule(true);
|
||||
this.ruleService.saveRule(nodeRef2, rule2);
|
||||
Rule rule3 = createTestRule(true);
|
||||
this.ruleService.saveRule(nodeRef3, rule3);
|
||||
Rule rule4 = createTestRule(true);
|
||||
this.ruleService.saveRule(nodeRef4, rule4);
|
||||
|
||||
List<? extends Rule> allRules1 = this.ruleService.getRules(nodeRef1, true);
|
||||
assertNotNull(allRules1);
|
||||
assertEquals(1, allRules1.size());
|
||||
assertTrue(allRules1.contains(rule1));
|
||||
|
||||
List<? extends Rule> allRules2 = this.ruleService.getRules(nodeRef2, true);
|
||||
assertNotNull(allRules2);
|
||||
assertEquals(2, allRules2.size());
|
||||
assertTrue(allRules2.contains(rule1));
|
||||
assertTrue(allRules2.contains(rule2));
|
||||
|
||||
List<? extends Rule> allRules3 = this.ruleService.getRules(nodeRef3, true);
|
||||
assertNotNull(allRules3);
|
||||
assertEquals(4, allRules3.size());
|
||||
assertTrue(allRules3.contains(rule1));
|
||||
assertTrue(allRules3.contains(rule2));
|
||||
assertTrue(allRules3.contains(rule3));
|
||||
assertTrue(allRules3.contains(rule4));
|
||||
|
||||
List<? extends Rule> allRules4 = this.ruleService.getRules(nodeRef4, true);
|
||||
assertNotNull(allRules4);
|
||||
assertEquals(2, allRules4.size());
|
||||
assertTrue(allRules4.contains(rule1));
|
||||
assertTrue(allRules4.contains(rule4));
|
||||
}
|
||||
|
||||
public void testCyclicRules()
|
||||
{
|
||||
}
|
||||
|
||||
public void testCyclicAsyncRules() throws Exception
|
||||
{
|
||||
NodeRef nodeRef = createNewNode(this.rootNodeRef, true);
|
||||
|
||||
// Create the first rule
|
||||
|
||||
Map<String, Serializable> conditionProps = new HashMap<String, Serializable>();
|
||||
conditionProps.put(ComparePropertyValueEvaluator.PARAM_VALUE, "*.jpg");
|
||||
|
||||
Map<String, Serializable> actionProps = new HashMap<String, Serializable>();
|
||||
actionProps.put(ImageTransformActionExecuter.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_IMAGE_GIF);
|
||||
actionProps.put(ImageTransformActionExecuter.PARAM_DESTINATION_FOLDER, nodeRef);
|
||||
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.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);
|
||||
|
||||
// Create the next rule
|
||||
|
||||
Map<String, Serializable> conditionProps2 = new HashMap<String, Serializable>();
|
||||
conditionProps2.put(ComparePropertyValueEvaluator.PARAM_VALUE, "*.gif");
|
||||
|
||||
Map<String, Serializable> actionProps2 = new HashMap<String, Serializable>();
|
||||
actionProps2.put(ImageTransformActionExecuter.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_IMAGE_JPEG);
|
||||
actionProps2.put(ImageTransformActionExecuter.PARAM_DESTINATION_FOLDER, nodeRef);
|
||||
actionProps2.put(ImageTransformActionExecuter.PARAM_ASSOC_QNAME, ContentModel.ASSOC_CHILDREN);
|
||||
|
||||
Rule rule2 = this.ruleService.createRule(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);
|
||||
|
||||
// Save the rules
|
||||
this.ruleService.saveRule(nodeRef, rule);
|
||||
this.ruleService.saveRule(nodeRef, rule);
|
||||
|
||||
// Now create new content
|
||||
NodeRef contentNode = this.nodeService.createNode(nodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testnode"),
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
this.nodeService.setProperty(contentNode, ContentModel.PROP_NAME, "myFile.jpg");
|
||||
File file = AbstractContentTransformerTest.loadQuickTestFile("jpg");
|
||||
ContentWriter writer = this.contentService.getWriter(contentNode, ContentModel.PROP_CONTENT, true);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_IMAGE_JPEG);
|
||||
writer.putContent(file);
|
||||
|
||||
setComplete();
|
||||
endTransaction();
|
||||
|
||||
//final NodeRef finalNodeRef = nodeRef;
|
||||
|
||||
// Check to see what has happened
|
||||
// ActionServiceImplTest.postAsyncActionTest(
|
||||
// this.transactionService,
|
||||
// 10000,
|
||||
// 10,
|
||||
// new AsyncTest()
|
||||
// {
|
||||
// public boolean executeTest()
|
||||
// {
|
||||
// List<ChildAssociationRef> assocs = RuleServiceImplTest.this.nodeService.getChildAssocs(finalNodeRef);
|
||||
// for (ChildAssociationRef ref : assocs)
|
||||
// {
|
||||
// NodeRef child = ref.getChildRef();
|
||||
// System.out.println("Child name: " + RuleServiceImplTest.this.nodeService.getProperty(child, ContentModel.PROP_NAME));
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
// };
|
||||
// });
|
||||
}
|
||||
}
|
46
source/java/org/alfresco/repo/rule/RuleTestSuite.java
Normal file
46
source/java/org/alfresco/repo/rule/RuleTestSuite.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 org.alfresco.repo.rule.ruletrigger.RuleTriggerTest;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
|
||||
/**
|
||||
* Version test suite
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class RuleTestSuite extends TestSuite
|
||||
{
|
||||
/**
|
||||
* Creates the test suite
|
||||
*
|
||||
* @return the test suite
|
||||
*/
|
||||
public static Test suite()
|
||||
{
|
||||
TestSuite suite = new TestSuite();
|
||||
suite.addTestSuite(RuleTypeImplTest.class);
|
||||
suite.addTestSuite(RuleTriggerTest.class);
|
||||
suite.addTestSuite(RuleServiceImplTest.class);
|
||||
suite.addTestSuite(RuleServiceCoverageTest.class);
|
||||
return suite;
|
||||
}
|
||||
}
|
115
source/java/org/alfresco/repo/rule/RuleTransactionListener.java
Normal file
115
source/java/org/alfresco/repo/rule/RuleTransactionListener.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 org.alfresco.repo.transaction.TransactionListener;
|
||||
import org.alfresco.util.GUID;
|
||||
|
||||
/**
|
||||
* The rule service transaction listener
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class RuleTransactionListener implements TransactionListener
|
||||
{
|
||||
/**
|
||||
* Id used in equals and hash
|
||||
*/
|
||||
private String id = GUID.generate();
|
||||
|
||||
/**
|
||||
* The rule service (runtime interface)
|
||||
*/
|
||||
private RuntimeRuleService ruleService;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param
|
||||
*/
|
||||
public RuleTransactionListener(RuntimeRuleService ruleService)
|
||||
{
|
||||
this.ruleService = ruleService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#flush()
|
||||
*/
|
||||
public void flush()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#beforeCommit(boolean)
|
||||
*/
|
||||
public void beforeCommit(boolean readOnly)
|
||||
{
|
||||
this.ruleService.executePendingRules();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#beforeCompletion()
|
||||
*/
|
||||
public void beforeCompletion()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#afterCommit()
|
||||
*/
|
||||
public void afterCommit()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#afterRollback()
|
||||
*/
|
||||
public void afterRollback()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.id.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof RuleTransactionListener)
|
||||
{
|
||||
RuleTransactionListener that = (RuleTransactionListener) obj;
|
||||
return (this.id.equals(that.id));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
161
source/java/org/alfresco/repo/rule/RuleTypeImpl.java
Normal file
161
source/java/org/alfresco/repo/rule/RuleTypeImpl.java
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.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;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Rule type implementation class.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class RuleTypeImpl extends CommonResourceAbstractBase implements RuleType
|
||||
{
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private static Log logger = LogFactory.getLog(RuleTypeImpl.class);
|
||||
|
||||
/**
|
||||
* The action service
|
||||
*/
|
||||
private ActionService actionService;
|
||||
|
||||
/**
|
||||
* The rule service
|
||||
*/
|
||||
private RuleService ruleService;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ruleTriggers the rule triggers
|
||||
*/
|
||||
public RuleTypeImpl(List<RuleTrigger> ruleTriggers)
|
||||
{
|
||||
if (ruleTriggers != null)
|
||||
{
|
||||
for (RuleTrigger trigger : ruleTriggers)
|
||||
{
|
||||
trigger.registerRuleType(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the action service
|
||||
*
|
||||
* @param actionService the action service
|
||||
*/
|
||||
public void setActionService(ActionService actionService)
|
||||
{
|
||||
this.actionService = actionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rule service
|
||||
*
|
||||
* @param ruleService the rule service
|
||||
*/
|
||||
public void setRuleService(RuleService ruleService)
|
||||
{
|
||||
this.ruleService = ruleService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rule type initialise method
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
((RuntimeRuleService)this.ruleService).registerRuleType(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleType#getName()
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.rule.RuleType#getDisplayLabel()
|
||||
*/
|
||||
public String getDisplayLabel()
|
||||
{
|
||||
return I18NUtil.getMessage(this.name + "." + "display-label");
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (this.ruleService.hasRules(nodeRef) == true)
|
||||
{
|
||||
List<Rule> rules = this.ruleService.getRules(
|
||||
nodeRef,
|
||||
true,
|
||||
this.name);
|
||||
|
||||
for (Rule rule : rules)
|
||||
{
|
||||
if (logger.isDebugEnabled() == true)
|
||||
{
|
||||
logger.debug("Triggering rule " + rule.getId());
|
||||
}
|
||||
|
||||
if (rule.getExecuteAsychronously() == true)
|
||||
{
|
||||
// Execute the rule now since it will be be queued for async execution later
|
||||
this.actionService.executeAction(rule, actionedUponNodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setBeanName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
}
|
137
source/java/org/alfresco/repo/rule/RuleTypeImplTest.java
Normal file
137
source/java/org/alfresco/repo/rule/RuleTypeImplTest.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.rule.ruletrigger.RuleTrigger;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
|
||||
/**
|
||||
* Parameter definition implementation unit test.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class RuleTypeImplTest extends BaseSpringTest
|
||||
{
|
||||
private static final String NAME = "name";
|
||||
|
||||
private NodeService nodeService;
|
||||
private ContentService contentService;
|
||||
|
||||
private StoreRef testStoreRef;
|
||||
private NodeRef rootNodeRef;
|
||||
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
this.nodeService = (NodeService)this.applicationContext.getBean("nodeService");
|
||||
this.contentService = (ContentService)this.applicationContext.getBean("contentService");
|
||||
|
||||
this.testStoreRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
this.rootNodeRef = this.nodeService.getRootNode(this.testStoreRef);
|
||||
}
|
||||
|
||||
public void testConstructor()
|
||||
{
|
||||
create();
|
||||
}
|
||||
|
||||
private RuleTypeImpl create()
|
||||
{
|
||||
RuleTypeImpl temp = new RuleTypeImpl(null);
|
||||
temp.setBeanName(NAME);
|
||||
assertNotNull(temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
public void testGetName()
|
||||
{
|
||||
RuleTypeImpl temp = create();
|
||||
assertEquals(NAME, temp.getName());
|
||||
}
|
||||
|
||||
// TODO Test the display label, ensuring that the label is retrieved from the resource
|
||||
|
||||
// TODO Test setRuleTriggers
|
||||
|
||||
// TODO Test triggerRuleType
|
||||
|
||||
public void testMockInboundRuleType()
|
||||
{
|
||||
NodeRef nodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
NodeRef nodeRef2 = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
|
||||
List<RuleTrigger> triggers = new ArrayList<RuleTrigger>(2);
|
||||
triggers.add((RuleTrigger)this.applicationContext.getBean("on-content-update-trigger"));
|
||||
triggers.add((RuleTrigger)this.applicationContext.getBean("on-create-child-association-trigger"));
|
||||
|
||||
ExtendedRuleType ruleType = new ExtendedRuleType(triggers);
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Update some content in order to trigger the rule type
|
||||
ContentWriter contentWriter = this.contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
contentWriter.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
contentWriter.putContent("any old content");
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
|
||||
// Reset
|
||||
ruleType.rulesTriggered = false;
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Create a child association in order to trigger the rule type
|
||||
this.nodeService.addChild(
|
||||
nodeRef2,
|
||||
nodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN);
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
}
|
||||
|
||||
private class ExtendedRuleType extends RuleTypeImpl
|
||||
{
|
||||
public boolean rulesTriggered = false;
|
||||
|
||||
public ExtendedRuleType(List<RuleTrigger> ruleTriggers)
|
||||
{
|
||||
super(ruleTriggers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef)
|
||||
{
|
||||
this.rulesTriggered = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
159
source/java/org/alfresco/repo/rule/RulesAspect.java
Normal file
159
source/java/org/alfresco/repo/rule/RulesAspect.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.policy.Behaviour;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
|
||||
/**
|
||||
* Class containing behaviour for the rules aspect
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class RulesAspect
|
||||
{
|
||||
private Behaviour onAddAspectBehaviour;
|
||||
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
private RuleService ruleService;
|
||||
|
||||
private NodeService nodeService;
|
||||
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setRuleService(RuleService ruleService)
|
||||
{
|
||||
this.ruleService = ruleService;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
|
||||
RuleModel.ASPECT_RULES,
|
||||
new JavaBehaviour(this, "onCopyNode"));
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyComplete"),
|
||||
RuleModel.ASPECT_RULES,
|
||||
new JavaBehaviour(this, "onCopyComplete"));
|
||||
|
||||
this.onAddAspectBehaviour = new JavaBehaviour(this, "onAddAspect");
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onAddAspect"),
|
||||
RuleModel.ASPECT_RULES,
|
||||
onAddAspectBehaviour);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to diable the on add aspect policy behaviour. Helpful when importing,
|
||||
* copying and other bulk respstorative operations.
|
||||
*
|
||||
* TODO will eventually be redundant when policies can be enabled/diabled in the
|
||||
* policy componenet
|
||||
*/
|
||||
public void disbleOnAddAspect()
|
||||
{
|
||||
this.onAddAspectBehaviour.disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to enable the on add aspect policy behaviour. Helpful when importing,
|
||||
* copying and other bulk respstorative operations.
|
||||
*
|
||||
* TODO will eventually be redundant when policies can be enabled/diabled in the
|
||||
* policy componenet
|
||||
*/
|
||||
public void enableOnAddAspect()
|
||||
{
|
||||
this.onAddAspectBehaviour.enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* On add aspect policy behaviour
|
||||
* @param nodeRef
|
||||
* @param aspectTypeQName
|
||||
*/
|
||||
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
this.ruleService.disableRules(nodeRef);
|
||||
try
|
||||
{
|
||||
this.nodeService.createNode(
|
||||
nodeRef,
|
||||
RuleModel.ASSOC_RULE_FOLDER,
|
||||
RuleModel.ASSOC_RULE_FOLDER,
|
||||
ContentModel.TYPE_SYSTEM_FOLDER);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.ruleService.enableRules(nodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
public void onCopyNode(
|
||||
QName classRef,
|
||||
NodeRef sourceNodeRef,
|
||||
StoreRef destinationStoreRef,
|
||||
boolean copyToNewNode,
|
||||
PolicyScope copyDetails)
|
||||
{
|
||||
copyDetails.addAspect(RuleModel.ASPECT_RULES);
|
||||
|
||||
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(
|
||||
sourceNodeRef,
|
||||
RegexQNamePattern.MATCH_ALL,
|
||||
RuleModel.ASSOC_RULE_FOLDER);
|
||||
for (ChildAssociationRef assoc : assocs)
|
||||
{
|
||||
copyDetails.addChildAssociation(classRef, assoc, true);
|
||||
}
|
||||
|
||||
this.onAddAspectBehaviour.disable();
|
||||
}
|
||||
|
||||
public void onCopyComplete(
|
||||
QName classRef,
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationRef,
|
||||
Map<NodeRef, NodeRef> copyMap)
|
||||
{
|
||||
this.onAddAspectBehaviour.enable();
|
||||
}
|
||||
}
|
35
source/java/org/alfresco/repo/rule/RuntimeRuleService.java
Normal file
35
source/java/org/alfresco/repo/rule/RuntimeRuleService.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
|
||||
/**
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public interface RuntimeRuleService
|
||||
{
|
||||
void addRulePendingExecution(NodeRef actionableNodeRef, NodeRef actionedUponNodeRef, Rule rule);
|
||||
|
||||
void addRulePendingExecution(NodeRef actionableNodeRef, NodeRef actionedUponNodeRef, Rule rule, boolean executeAtEnd);
|
||||
|
||||
void executePendingRules();
|
||||
|
||||
void registerRuleType(RuleType ruleType);
|
||||
}
|
55
source/java/org/alfresco/repo/rule/ruleModel.xml
Normal file
55
source/java/org/alfresco/repo/rule/ruleModel.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<model name="rule:rulemodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||
|
||||
<description>Alfresco Rule Model</description>
|
||||
<author>Alfresco</author>
|
||||
<published>2005-08-16</published>
|
||||
<version>0.1</version>
|
||||
|
||||
<imports>
|
||||
<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"/>
|
||||
</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>
|
||||
<property name="rule:ruleType">
|
||||
<type>d:text</type>
|
||||
<mandatory>true</mandatory>
|
||||
</property>
|
||||
<property name="rule:applyToChildren">
|
||||
<type>d:boolean</type>
|
||||
<mandatory>true</mandatory>
|
||||
</property>
|
||||
</properties>
|
||||
</type>
|
||||
|
||||
</types>
|
||||
|
||||
<aspects>
|
||||
|
||||
<aspect name="rule:rules">
|
||||
<title>Rules</title>
|
||||
<associations>
|
||||
<child-association name="rule:ruleFolder">
|
||||
<target>
|
||||
<class>cm:systemfolder</class>
|
||||
<mandatory>false</mandatory>
|
||||
<many>false</many>
|
||||
</target>
|
||||
</child-association>
|
||||
</associations>
|
||||
</aspect>
|
||||
|
||||
</aspects>
|
||||
|
||||
</model>
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.ruletrigger;
|
||||
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* We use this specialised trigger for create node beaucse of a problem with the CIFS integration.
|
||||
* <p>
|
||||
* The create node trigger will only be fired if the object is NOT a sub-type of content.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class CreateNodeRuleTrigger extends SingleChildAssocRefPolicyRuleTrigger
|
||||
{
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private static Log logger = LogFactory.getLog(CreateNodeRuleTrigger.class);
|
||||
|
||||
DictionaryService dictionaryService;
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void policyBehaviour(ChildAssociationRef childAssocRef)
|
||||
{
|
||||
// Only fire the rule if the node is question has no potential to contain content
|
||||
// TODO we need to find a better way to do this .. how can this be resolved in CIFS??
|
||||
boolean triggerRule = false;
|
||||
QName type = this.nodeService.getType(childAssocRef.getChildRef());
|
||||
ClassDefinition classDefinition = this.dictionaryService.getClass(type);
|
||||
if (classDefinition != null)
|
||||
{
|
||||
for (PropertyDefinition propertyDefinition : classDefinition.getProperties().values())
|
||||
{
|
||||
if (propertyDefinition.getDataType().getName().equals(DataTypeDefinition.CONTENT) == true)
|
||||
{
|
||||
triggerRule = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerRule == false)
|
||||
{
|
||||
if (logger.isDebugEnabled() == true)
|
||||
{
|
||||
logger.debug(
|
||||
"Create node rule trigger fired for parent node " +
|
||||
this.nodeService.getType(childAssocRef.getParentRef()).toString() + " " + childAssocRef.getParentRef() +
|
||||
" and child node " +
|
||||
this.nodeService.getType(childAssocRef.getChildRef()).toString() + " " + childAssocRef.getChildRef());
|
||||
}
|
||||
|
||||
triggerRules(childAssocRef.getParentRef(), childAssocRef.getChildRef());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.ruletrigger;
|
||||
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
|
||||
/**
|
||||
* Rule trigger interface
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public interface RuleTrigger
|
||||
{
|
||||
/**
|
||||
* Register the rule trigger
|
||||
*/
|
||||
void registerRuleTrigger();
|
||||
|
||||
/**
|
||||
* Register the rule type as using this trigger
|
||||
*
|
||||
* @param ruleType the rule type
|
||||
*/
|
||||
void registerRuleType(RuleType ruleType);
|
||||
}
|
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.ruletrigger;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
|
||||
/**
|
||||
* Rule trigger abstract base
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
||||
{
|
||||
/**
|
||||
* A list of the rule types that are interested in this trigger
|
||||
*/
|
||||
private Set<RuleType> ruleTypes = new HashSet<RuleType>();
|
||||
|
||||
/**
|
||||
* The policy component
|
||||
*/
|
||||
protected PolicyComponent policyComponent;
|
||||
|
||||
/**
|
||||
* The node service
|
||||
*/
|
||||
protected NodeService nodeService;
|
||||
|
||||
/**
|
||||
* The authentication Component
|
||||
*/
|
||||
|
||||
protected AuthenticationComponent authenticationComponent;
|
||||
|
||||
/**
|
||||
* Set the policy component
|
||||
*
|
||||
* @param policyComponent
|
||||
* the policy component
|
||||
*/
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the node service
|
||||
*
|
||||
* @param nodeService
|
||||
* the node service
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authenticationComponent
|
||||
*/
|
||||
|
||||
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
|
||||
{
|
||||
this.authenticationComponent = authenticationComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registration of an interested rule type
|
||||
*/
|
||||
public void registerRuleType(RuleType ruleType)
|
||||
{
|
||||
this.ruleTypes.add(ruleType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the rules that relate to any interested rule types for the node
|
||||
* references passed.
|
||||
*
|
||||
* @param nodeRef
|
||||
* the node reference who rules are to be triggered
|
||||
* @param actionedUponNodeRef
|
||||
* the node reference that will be actioned upon by the rules
|
||||
*/
|
||||
protected void triggerRules(NodeRef nodeRef, NodeRef actionedUponNodeRef)
|
||||
{
|
||||
String userName = authenticationComponent.getCurrentUserName();
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
try
|
||||
{
|
||||
for (RuleType ruleType : this.ruleTypes)
|
||||
{
|
||||
ruleType.triggerRuleType(nodeRef, actionedUponNodeRef);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
if(userName != null)
|
||||
{
|
||||
authenticationComponent.setCurrentUser(userName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* 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.ruletrigger;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
|
||||
/**
|
||||
* Rule trigger test
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
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";
|
||||
private static final String ON_DELETE_ASSOCIATION_TRIGGER = "on-delete-association-trigger";
|
||||
private static final String ON_CONTENT_UPDATE_TRIGGER = "on-content-update-trigger";
|
||||
|
||||
private NodeService nodeService;
|
||||
private ContentService contentService;
|
||||
|
||||
private StoreRef testStoreRef;
|
||||
private NodeRef rootNodeRef;
|
||||
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
this.nodeService = (NodeService)this.applicationContext.getBean("nodeService");
|
||||
this.contentService = (ContentService)this.applicationContext.getBean("contentService");
|
||||
|
||||
this.testStoreRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
this.rootNodeRef = this.nodeService.getRootNode(this.testStoreRef);
|
||||
}
|
||||
|
||||
public void testOnCreateNodeTrigger()
|
||||
{
|
||||
TestRuleType ruleType = createTestRuleType(ON_CREATE_NODE_TRIGGER);
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Try and trigger the type
|
||||
this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER);
|
||||
|
||||
// Check to see if the rule type has been triggered
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
}
|
||||
|
||||
public void testOnUpdateNodeTrigger()
|
||||
{
|
||||
NodeRef nodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
|
||||
TestRuleType ruleType = createTestRuleType(ON_UPDATE_NODE_TRIGGER);
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Try and trigger the type
|
||||
this.nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, "nameChanged");
|
||||
|
||||
// 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()
|
||||
{
|
||||
NodeRef nodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
NodeRef nodeRef2 = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
|
||||
TestRuleType ruleType = createTestRuleType(ON_CREATE_CHILD_ASSOCIATION_TRIGGER);
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Try and trigger the type
|
||||
this.nodeService.addChild(
|
||||
nodeRef,
|
||||
nodeRef2,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN);
|
||||
|
||||
// Check to see if the rule type has been triggered
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
}
|
||||
|
||||
public void testOnDeleteChildAssociationTrigger()
|
||||
{
|
||||
NodeRef nodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
NodeRef nodeRef2 = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
this.nodeService.addChild(
|
||||
nodeRef,
|
||||
nodeRef2,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN);
|
||||
|
||||
TestRuleType ruleType = createTestRuleType(ON_DELETE_CHILD_ASSOCIATION_TRIGGER);
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Try and trigger the type
|
||||
this.nodeService.removeChild(nodeRef, nodeRef2);
|
||||
|
||||
// Check to see if the rule type has been triggered
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
}
|
||||
|
||||
public void testOnCreateAssociationTrigger()
|
||||
{
|
||||
NodeRef nodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
NodeRef nodeRef2 = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
|
||||
TestRuleType ruleType = createTestRuleType(ON_CREATE_ASSOCIATION_TRIGGER);
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Try and trigger the type
|
||||
this.nodeService.createAssociation(nodeRef, nodeRef2, ContentModel.ASSOC_CHILDREN);
|
||||
|
||||
// Check to see if the rule type has been triggered
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
}
|
||||
|
||||
public void testOnDeleteAssociationTrigger()
|
||||
{
|
||||
NodeRef nodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
NodeRef nodeRef2 = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
this.nodeService.createAssociation(nodeRef, nodeRef2, ContentModel.ASSOC_CHILDREN);
|
||||
|
||||
TestRuleType ruleType = createTestRuleType(ON_DELETE_ASSOCIATION_TRIGGER);
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Try and trigger the type
|
||||
this.nodeService.removeAssociation(nodeRef, nodeRef2, ContentModel.ASSOC_CHILDREN);
|
||||
|
||||
// Check to see if the rule type has been triggered
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
}
|
||||
|
||||
public void testOnContentUpdateTrigger()
|
||||
{
|
||||
NodeRef nodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
|
||||
TestRuleType ruleType = createTestRuleType(ON_CONTENT_UPDATE_TRIGGER);
|
||||
assertFalse(ruleType.rulesTriggered);
|
||||
|
||||
// Try and trigger the type
|
||||
ContentWriter contentWriter = this.contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
contentWriter.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
contentWriter.setEncoding("UTF-8");
|
||||
contentWriter.putContent("some content");
|
||||
|
||||
// Check to see if the rule type has been triggered
|
||||
assertTrue(ruleType.rulesTriggered);
|
||||
}
|
||||
|
||||
private TestRuleType createTestRuleType(String ruleTriggerName)
|
||||
{
|
||||
RuleTrigger ruleTrigger = (RuleTrigger)this.applicationContext.getBean(ruleTriggerName);
|
||||
assertNotNull(ruleTrigger);
|
||||
TestRuleType ruleType = new TestRuleType();
|
||||
ruleTrigger.registerRuleType(ruleType);
|
||||
return ruleType;
|
||||
}
|
||||
|
||||
private class TestRuleType implements RuleType
|
||||
{
|
||||
public boolean rulesTriggered = false;
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return "testRuleType";
|
||||
}
|
||||
|
||||
public String getDisplayLabel()
|
||||
{
|
||||
return "displayLabel";
|
||||
}
|
||||
|
||||
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef)
|
||||
{
|
||||
// Indicate that the rules have been triggered
|
||||
this.rulesTriggered = true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.ruletrigger;
|
||||
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.rule.RuleServiceException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
public class SingleAssocRefPolicyRuleTrigger extends RuleTriggerAbstractBase
|
||||
{
|
||||
private static final String ERR_POLICY_NAME_NOT_SET = "Unable to register rule trigger since policy name has not been set.";
|
||||
|
||||
private String policyNamespace = NamespaceService.ALFRESCO_URI;
|
||||
|
||||
private String policyName;
|
||||
|
||||
public void setPolicyNamespace(String policyNamespace)
|
||||
{
|
||||
this.policyNamespace = policyNamespace;
|
||||
}
|
||||
|
||||
public void setPolicyName(String policyName)
|
||||
{
|
||||
this.policyName = policyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.ruletrigger.RuleTrigger#registerRuleTrigger()
|
||||
*/
|
||||
public void registerRuleTrigger()
|
||||
{
|
||||
if (policyName == null)
|
||||
{
|
||||
throw new RuleServiceException(ERR_POLICY_NAME_NOT_SET);
|
||||
}
|
||||
|
||||
this.policyComponent.bindAssociationBehaviour(
|
||||
QName.createQName(this.policyNamespace, this.policyName),
|
||||
this,
|
||||
new JavaBehaviour(this, "policyBehaviour"));
|
||||
}
|
||||
|
||||
public void policyBehaviour(AssociationRef assocRef)
|
||||
{
|
||||
triggerRules(assocRef.getSourceRef(), assocRef.getTargetRef());
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.ruletrigger;
|
||||
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.rule.RuleServiceException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
public class SingleChildAssocRefPolicyRuleTrigger extends RuleTriggerAbstractBase
|
||||
{
|
||||
private static final String ERR_POLICY_NAME_NOT_SET = "Unable to register rule trigger since policy name has not been set.";
|
||||
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private static Log logger = LogFactory.getLog(SingleChildAssocRefPolicyRuleTrigger.class);
|
||||
|
||||
private String policyNamespace = NamespaceService.ALFRESCO_URI;
|
||||
|
||||
private String policyName;
|
||||
|
||||
private boolean isClassBehaviour = false;
|
||||
|
||||
public void setPolicyNamespace(String policyNamespace)
|
||||
{
|
||||
this.policyNamespace = policyNamespace;
|
||||
}
|
||||
|
||||
public void setPolicyName(String policyName)
|
||||
{
|
||||
this.policyName = policyName;
|
||||
}
|
||||
|
||||
public void setIsClassBehaviour(boolean isClassBehaviour)
|
||||
{
|
||||
this.isClassBehaviour = isClassBehaviour;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.rule.ruletrigger.RuleTrigger#registerRuleTrigger()
|
||||
*/
|
||||
public void registerRuleTrigger()
|
||||
{
|
||||
if (policyName == null)
|
||||
{
|
||||
throw new RuleServiceException(ERR_POLICY_NAME_NOT_SET);
|
||||
}
|
||||
|
||||
if (isClassBehaviour == true)
|
||||
{
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(this.policyNamespace, this.policyName),
|
||||
this,
|
||||
new JavaBehaviour(this, "policyBehaviour"));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.policyComponent.bindAssociationBehaviour(
|
||||
QName.createQName(this.policyNamespace, this.policyName),
|
||||
this,
|
||||
new JavaBehaviour(this, "policyBehaviour"));
|
||||
}
|
||||
}
|
||||
|
||||
public void policyBehaviour(ChildAssociationRef childAssocRef)
|
||||
{
|
||||
if (logger.isDebugEnabled() == true)
|
||||
{
|
||||
logger.debug("Single child assoc trigger (policy = " + this.policyName + ") fired for parent node " + childAssocRef.getParentRef() + " and child node " + childAssocRef.getChildRef());
|
||||
}
|
||||
|
||||
triggerRules(childAssocRef.getParentRef(), childAssocRef.getChildRef());
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.ruletrigger;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.RuleServiceException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
public class SingleNodeRefPolicyRuleTrigger extends RuleTriggerAbstractBase
|
||||
{
|
||||
private static final String ERR_POLICY_NAME_NOT_SET = "Unable to register rule trigger since policy name has not been set.";
|
||||
|
||||
private String policyNamespace = NamespaceService.ALFRESCO_URI;
|
||||
|
||||
private String policyName;
|
||||
|
||||
private boolean triggerParentRules = true;
|
||||
|
||||
public void setPolicyNamespace(String policyNamespace)
|
||||
{
|
||||
this.policyNamespace = policyNamespace;
|
||||
}
|
||||
|
||||
public void setPolicyName(String policyName)
|
||||
{
|
||||
this.policyName = policyName;
|
||||
}
|
||||
|
||||
public void setTriggerParentRules(boolean triggerParentRules)
|
||||
{
|
||||
this.triggerParentRules = triggerParentRules;
|
||||
}
|
||||
|
||||
public void registerRuleTrigger()
|
||||
{
|
||||
if (policyName == null)
|
||||
{
|
||||
throw new RuleServiceException(ERR_POLICY_NAME_NOT_SET);
|
||||
}
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(this.policyNamespace, this.policyName),
|
||||
this,
|
||||
new JavaBehaviour(this, "policyBehaviour"));
|
||||
}
|
||||
|
||||
public void policyBehaviour(NodeRef nodeRef)
|
||||
{
|
||||
if (triggerParentRules == true)
|
||||
{
|
||||
List<ChildAssociationRef> parentsAssocRefs = this.nodeService.getParentAssocs(nodeRef);
|
||||
for (ChildAssociationRef parentAssocRef : parentsAssocRefs)
|
||||
{
|
||||
triggerRules(parentAssocRef.getParentRef(), nodeRef);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
triggerRules(nodeRef, nodeRef);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user