org.jbpm.workflow.instance.node.RuleSetNodeInstance Maven / Gradle / Ivy
/**
* Copyright 2005 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.jbpm.workflow.instance.node;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import org.drools.core.common.InternalAgenda;
import org.drools.core.common.InternalKnowledgeRuntime;
import org.drools.core.process.core.datatype.DataType;
import org.drools.core.process.instance.WorkItem;
import org.drools.core.util.MVELSafeHelper;
import org.jbpm.process.core.context.variable.Variable;
import org.jbpm.process.core.context.variable.VariableScope;
import org.jbpm.process.core.impl.DataTransformerRegistry;
import org.jbpm.process.instance.context.variable.VariableScopeInstance;
import org.jbpm.workflow.core.node.DataAssociation;
import org.jbpm.workflow.core.node.RuleSetNode;
import org.jbpm.workflow.core.node.Transformation;
import org.jbpm.workflow.instance.impl.NodeInstanceResolverFactory;
import org.kie.api.runtime.process.DataTransformer;
import org.kie.api.runtime.process.EventListener;
import org.kie.api.runtime.process.NodeInstance;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.internal.runtime.KnowledgeRuntime;
import org.kie.internal.runtime.StatefulKnowledgeSession;
import org.mvel2.integration.impl.MapVariableResolverFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Runtime counterpart of a ruleset node.
*
* @author Kris Verlaenen
*/
public class RuleSetNodeInstance extends StateBasedNodeInstance implements EventListener {
private static final long serialVersionUID = 510l;
private static final Logger logger = LoggerFactory.getLogger(RuleSetNodeInstance.class);
private Map factHandles = new HashMap();
private String ruleFlowGroup;
protected RuleSetNode getRuleSetNode() {
return (RuleSetNode) getNode();
}
public void internalTrigger(final NodeInstance from, String type) {
super.internalTrigger(from, type);
// if node instance was cancelled, abort
if (getNodeInstanceContainer().getNodeInstance(getId()) == null) {
return;
}
if ( !org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE.equals( type ) ) {
throw new IllegalArgumentException( "A RuleSetNode only accepts default incoming connections!" );
}
// first set rule flow group
setRuleFlowGroup(resolveRuleFlowGroup(getRuleSetNode().getRuleFlowGroup()));
//proceed
KnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
Map inputs = evaluateParameters(getRuleSetNode());
for (Entry entry : inputs.entrySet()) {
String inputKey = getRuleFlowGroup() + "_" +getProcessInstance().getId() +"_"+entry.getKey();
factHandles.put(inputKey, kruntime.insert(entry.getValue()));
}
addRuleSetListener();
((InternalAgenda) getProcessInstance().getKnowledgeRuntime().getAgenda())
.activateRuleFlowGroup( getRuleFlowGroup(), getProcessInstance().getId(), getUniqueId() );
}
public void addEventListeners() {
super.addEventListeners();
addRuleSetListener();
}
private String getRuleSetEventType() {
InternalKnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
if (kruntime instanceof StatefulKnowledgeSession) {
return "RuleFlowGroup_" + getRuleFlowGroup() + "_" + ((StatefulKnowledgeSession) kruntime).getIdentifier();
} else {
return "RuleFlowGroup_" + getRuleFlowGroup();
}
}
private void addRuleSetListener() {
getProcessInstance().addEventListener(getRuleSetEventType(), this, true);
}
public void removeEventListeners() {
super.removeEventListeners();
getProcessInstance().removeEventListener(getRuleSetEventType(), this, true);
}
public void cancel() {
super.cancel();
((InternalAgenda) getProcessInstance().getKnowledgeRuntime().getAgenda())
.deactivateRuleFlowGroup( getRuleFlowGroup() );
}
public void signalEvent(String type, Object event) {
if (getRuleSetEventType().equals(type)) {
removeEventListeners();
retractFacts();
triggerCompleted();
}
}
public void retractFacts() {
Map objects = new HashMap();
KnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
for (Entry entry : factHandles.entrySet()) {
Object object = ((StatefulKnowledgeSession)kruntime).getObject(entry.getValue());
String key = entry.getKey();
key = key.replaceAll(getRuleFlowGroup()+"_", "");
key = key.replaceAll(getProcessInstance().getId()+"_", "");
objects.put(key , object);
kruntime.delete(entry.getValue());
}
RuleSetNode ruleSetNode = getRuleSetNode();
if (ruleSetNode != null) {
for (Iterator iterator = ruleSetNode.getOutAssociations().iterator(); iterator.hasNext(); ) {
DataAssociation association = iterator.next();
if (association.getTransformation() != null) {
Transformation transformation = association.getTransformation();
DataTransformer transformer = DataTransformerRegistry.get().find(transformation.getLanguage());
if (transformer != null) {
Object parameterValue = transformer.transform(transformation.getCompiledExpression(), objects);
VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
resolveContextInstance(VariableScope.VARIABLE_SCOPE, association.getTarget());
if (variableScopeInstance != null && parameterValue != null) {
variableScopeInstance.setVariable(association.getTarget(), parameterValue);
} else {
logger.warn("Could not find variable scope for variable {}", association.getTarget());
logger.warn("Continuing without setting variable.");
}
if (parameterValue != null) {
variableScopeInstance.setVariable(association.getTarget(), parameterValue);
}
}
} else if (association.getAssignments() == null || association.getAssignments().isEmpty()) {
VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
resolveContextInstance(VariableScope.VARIABLE_SCOPE, association.getTarget());
if (variableScopeInstance != null) {
Object value = objects.get(association.getSources().get(0));
if (value == null) {
try {
value = MVELSafeHelper.getEvaluator().eval(association.getSources().get(0), new MapVariableResolverFactory(objects));
} catch (Throwable t) {
// do nothing
}
}
Variable varDef = variableScopeInstance.getVariableScope().findVariable(association.getTarget());
DataType dataType = varDef.getType();
// exclude java.lang.Object as it is considered unknown type
if (!dataType.getStringType().endsWith("java.lang.Object") && value instanceof String) {
value = dataType.readValue((String) value);
}
variableScopeInstance.setVariable(association.getTarget(), value);
} else {
logger.warn("Could not find variable scope for variable {}", association.getTarget());
}
}
}
}
factHandles.clear();
}
protected Map evaluateParameters(RuleSetNode ruleSetNode) {
Map replacements = new HashMap();
for (Iterator iterator = ruleSetNode.getInAssociations().iterator(); iterator.hasNext(); ) {
DataAssociation association = iterator.next();
if (association.getTransformation() != null) {
Transformation transformation = association.getTransformation();
DataTransformer transformer = DataTransformerRegistry.get().find(transformation.getLanguage());
if (transformer != null) {
Object parameterValue = transformer.transform(transformation.getCompiledExpression(), getSourceParameters(association));
if (parameterValue != null) {
replacements.put(association.getTarget(), parameterValue);
}
}
} else if (association.getAssignments() == null || association.getAssignments().isEmpty()) {
Object parameterValue = null;
VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
resolveContextInstance(VariableScope.VARIABLE_SCOPE, association.getSources().get(0));
if (variableScopeInstance != null) {
parameterValue = variableScopeInstance.getVariable(association.getSources().get(0));
} else {
try {
parameterValue = MVELSafeHelper.getEvaluator().eval(association.getSources().get(0), new NodeInstanceResolverFactory(this));
} catch (Throwable t) {
logger.error("Could not find variable scope for variable {}", association.getSources().get(0));
logger.error("when trying to execute RuleSetNode {}", ruleSetNode.getName());
logger.error("Continuing without setting parameter.");
}
}
if (parameterValue != null) {
replacements.put(association.getTarget(), parameterValue);
}
}
}
for (Map.Entry entry: ruleSetNode.getParameters().entrySet()) {
if (entry.getValue() instanceof String) {
Object value = resolveVariable(entry.getValue());
if (value != null) {
replacements.put(entry.getKey(), value);
}
}
}
return replacements;
}
private Object resolveVariable(Object s) {
if (s instanceof String) {
Matcher matcher = PARAMETER_MATCHER.matcher((String) s);
while (matcher.find()) {
String paramName = matcher.group(1);
VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
resolveContextInstance(VariableScope.VARIABLE_SCOPE, paramName);
if (variableScopeInstance != null) {
Object variableValue = variableScopeInstance.getVariable(paramName);
if (variableValue != null) {
return variableValue;
}
} else {
try {
Object variableValue = MVELSafeHelper.getEvaluator().eval(paramName, new NodeInstanceResolverFactory(this));
if (variableValue != null) {
return variableValue;
}
} catch (Throwable t) {
logger.error("Could not find variable scope for variable {}", paramName);
}
}
}
}
return s;
}
protected Map getSourceParameters(DataAssociation association) {
Map parameters = new HashMap();
for (String sourceParam : association.getSources()) {
Object parameterValue = null;
VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
resolveContextInstance(VariableScope.VARIABLE_SCOPE, sourceParam);
if (variableScopeInstance != null) {
parameterValue = variableScopeInstance.getVariable(sourceParam);
} else {
try {
parameterValue = MVELSafeHelper.getEvaluator().eval(sourceParam, new NodeInstanceResolverFactory(this));
} catch (Throwable t) {
logger.warn("Could not find variable scope for variable {}", sourceParam);
}
}
if (parameterValue != null) {
parameters.put(association.getTarget(), parameterValue);
}
}
return parameters;
}
private String resolveRuleFlowGroup(String origin) {
return (String) resolveVariable(origin);
}
public Map getFactHandles() {
return factHandles;
}
public void setFactHandles(Map factHandles) {
this.factHandles = factHandles;
}
public String getRuleFlowGroup() {
if (ruleFlowGroup == null || ruleFlowGroup.trim().length() == 0) {
ruleFlowGroup = getRuleSetNode().getRuleFlowGroup();
}
return ruleFlowGroup;
}
public void setRuleFlowGroup(String ruleFlowGroup) {
this.ruleFlowGroup = ruleFlowGroup;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy