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:
Derek Hulley
2005-12-08 07:13:07 +00:00
commit e1e6508fec
1095 changed files with 230566 additions and 0 deletions

View 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));
}
}

View 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);
}

View 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;
}
}

View 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");
}

File diff suppressed because it is too large Load Diff

View 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
}
}
}

View 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;
// };
// });
}
}

View 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;
}
}

View 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;
}
}
}

View 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;
}
}

View 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;
}
}
}

View 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();
}
}

View 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);
}

View 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>

View File

@@ -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());
}
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}
}