use of io.automatiko.engine.workflow.process.core.node.DataAssociation in project automatiko-engine by automatiko-io.
the class SubProcessNodeInstance method internalTrigger.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
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 (!io.automatiko.engine.workflow.process.core.Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
throw new IllegalArgumentException("A SubProcess node only accepts default incoming connections!");
}
Map<String, Object> parameters = new HashMap<String, Object>();
for (Iterator<DataAssociation> iterator = getSubProcessNode().getInAssociations().iterator(); iterator.hasNext(); ) {
DataAssociation mapping = iterator.next();
Object parameterValue = null;
if (mapping.getTransformation() != null) {
Transformation transformation = mapping.getTransformation();
DataTransformer transformer = DataTransformerRegistry.get().find(transformation.getLanguage());
if (transformer != null) {
parameterValue = transformer.transform(transformation.getCompiledExpression(), getSourceParameters(mapping));
}
} else {
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) resolveContextInstance(VariableScope.VARIABLE_SCOPE, mapping.getSources().get(0));
if (variableScopeInstance != null) {
parameterValue = variableScopeInstance.getVariable(mapping.getSources().get(0));
} else {
try {
ExpressionEvaluator evaluator = (ExpressionEvaluator) ((WorkflowProcess) getProcessInstance().getProcess()).getDefaultContext(ExpressionEvaluator.EXPRESSION_EVALUATOR);
parameterValue = evaluator.evaluate(mapping.getSources().get(0), new NodeInstanceResolverFactory(this));
} catch (Throwable t) {
parameterValue = VariableUtil.resolveVariable(mapping.getSources().get(0), this);
if (parameterValue != null) {
parameters.put(mapping.getTarget(), parameterValue);
} else {
logger.error("Could not find variable scope for variable {}", mapping.getSources().get(0));
logger.error("when trying to execute SubProcess node {}", getSubProcessNode().getName());
logger.error("Continuing without setting parameter.");
}
}
}
}
if (parameterValue != null) {
parameters.put(mapping.getTarget(), parameterValue);
}
}
String processId = getSubProcessNode().getProcessId();
if (processId == null) {
// if process id is not given try with process name
processId = getSubProcessNode().getProcessName();
}
// resolve processId if necessary
Map<String, String> replacements = new HashMap<String, String>();
Matcher matcher = PatternConstants.PARAMETER_MATCHER.matcher(processId);
while (matcher.find()) {
String paramName = matcher.group(1);
String replacementKey = paramName;
String defaultValue = "";
if (paramName.contains(":")) {
String[] items = paramName.split(":");
paramName = items[0];
defaultValue = items[1];
}
if (replacements.get(replacementKey) == null) {
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) resolveContextInstance(VariableScope.VARIABLE_SCOPE, paramName);
if (variableScopeInstance != null) {
Object variableValue = variableScopeInstance.getVariable(paramName);
String variableValueString = variableValue == null ? defaultValue : variableValue.toString();
replacements.put(replacementKey, variableValueString);
} else {
try {
ExpressionEvaluator evaluator = (ExpressionEvaluator) ((WorkflowProcess) getProcessInstance().getProcess()).getDefaultContext(ExpressionEvaluator.EXPRESSION_EVALUATOR);
Object variableValue = evaluator.evaluate(paramName, new NodeInstanceResolverFactory(this));
String variableValueString = variableValue == null ? defaultValue : variableValue.toString();
replacements.put(replacementKey, variableValueString);
} catch (Throwable t) {
logger.error("Could not find variable scope for variable {}", paramName);
logger.error("when trying to replace variable in processId for sub process {}", getNodeName());
logger.error("Continuing without setting process id.");
}
}
}
}
for (Map.Entry<String, String> replacement : replacements.entrySet()) {
processId = processId.replace("#{" + replacement.getKey() + "}", replacement.getValue());
}
// start process instance
Process process = getProcessInstance().getProcessRuntime().getProcess(processId);
if (process == null) {
logger.error("Could not find process {}", processId);
logger.error("Aborting process");
((ProcessInstance) getProcessInstance()).setState(ProcessInstance.STATE_ABORTED);
throw new RuntimeException("Could not find process " + processId);
} else {
ProcessRuntime kruntime = ((ProcessInstance) getProcessInstance()).getProcessRuntime();
if (getSubProcessNode().getMetaData("MICollectionInput") != null) {
// remove foreach input variable to avoid problems when running in variable
// strict mode
parameters.remove(getSubProcessNode().getMetaData("MICollectionInput"));
}
ProcessInstance processInstance = null;
if (((WorkflowProcessInstanceImpl) getProcessInstance()).getCorrelationKey() != null) {
// in case there is correlation key on parent instance pass it along to child so
// it can be easily correlated
// since correlation key must be unique for active instances it appends
// processId and timestamp
List<String> businessKeys = new ArrayList<String>();
businessKeys.add(((WorkflowProcessInstanceImpl) getProcessInstance()).getCorrelationKey());
businessKeys.add(processId);
businessKeys.add(String.valueOf(System.currentTimeMillis()));
CorrelationKey subProcessCorrelationKey = new StringCorrelationKey(businessKeys.stream().collect(Collectors.joining(":")));
processInstance = (ProcessInstance) ((CorrelationAwareProcessRuntime) kruntime).createProcessInstance(processId, subProcessCorrelationKey, parameters);
} else {
processInstance = (ProcessInstance) kruntime.createProcessInstance(processId, parameters);
}
this.processInstanceId = processInstance.getId();
((ProcessInstanceImpl) processInstance).setMetaData("ParentProcessInstanceId", getProcessInstance().getId());
((ProcessInstanceImpl) processInstance).setMetaData("ParentNodeInstanceId", getUniqueId());
((ProcessInstanceImpl) processInstance).setMetaData("ParentNodeId", getSubProcessNode().getUniqueId());
((ProcessInstanceImpl) processInstance).setParentProcessInstanceId(getProcessInstance().getId());
((ProcessInstanceImpl) processInstance).setRootProcessInstanceId(StringUtils.isEmpty(getProcessInstance().getRootProcessInstanceId()) ? getProcessInstance().getId() : getProcessInstance().getRootProcessInstanceId());
((ProcessInstanceImpl) processInstance).setRootProcessId(StringUtils.isEmpty(getProcessInstance().getRootProcessId()) ? getProcessInstance().getProcessId() : getProcessInstance().getRootProcessId());
((ProcessInstanceImpl) processInstance).setSignalCompletion(getSubProcessNode().isWaitForCompletion());
((ProcessInstanceImpl) processInstance).addChild(processInstance.getProcessId(), processInstance.getId());
kruntime.startProcessInstance(processInstance.getId());
if (!getSubProcessNode().isWaitForCompletion()) {
triggerCompleted();
} else if (processInstance.getState() == ProcessInstance.STATE_COMPLETED || processInstance.getState() == ProcessInstance.STATE_ABORTED) {
processInstanceCompleted(processInstance);
} else {
addProcessListener();
}
}
}
use of io.automatiko.engine.workflow.process.core.node.DataAssociation in project automatiko-engine by automatiko-io.
the class RuleSetNodeInstance method processOutputs.
@SuppressWarnings({ "unchecked", "rawtypes" })
private void processOutputs(Map<String, Object> inputs, Map<String, Object> objects) {
logger.debug("Rules evaluation results {}", objects);
RuleSetNode ruleSetNode = getRuleSetNode();
if (ruleSetNode != null) {
for (Iterator<DataAssociation> 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) {
Map<String, Object> dataSet = new HashMap<String, Object>();
if (getNodeInstanceContainer() instanceof CompositeContextNodeInstance) {
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) ((CompositeContextNodeInstance) getNodeInstanceContainer()).getContextInstance(VariableScope.VARIABLE_SCOPE);
if (variableScopeInstance != null) {
dataSet.putAll(variableScopeInstance.getVariables());
}
}
dataSet.putAll(inputs);
dataSet.putAll(objects);
Object parameterValue = transformer.transform(transformation.getCompiledExpression(), dataSet);
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) resolveContextInstance(VariableScope.VARIABLE_SCOPE, association.getTarget());
if (variableScopeInstance != null && parameterValue != null) {
variableScopeInstance.setVariable(this, association.getTarget(), parameterValue);
} else {
logger.warn("Could not find variable scope for variable {}", association.getTarget());
logger.warn("Continuing without setting variable.");
}
}
} 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 {
ExpressionEvaluator evaluator = (ExpressionEvaluator) ((WorkflowProcess) getProcessInstance().getProcess()).getDefaultContext(ExpressionEvaluator.EXPRESSION_EVALUATOR);
value = evaluator.evaluate(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(this, association.getTarget(), value);
} else {
String output = association.getSources().get(0);
String target = association.getTarget();
Matcher matcher = PatternConstants.PARAMETER_MATCHER.matcher(target);
if (matcher.find()) {
String paramName = matcher.group(1);
String expression = VariableUtil.transformDotNotation(paramName, output);
NodeInstanceResolverFactory resolver = new NodeInstanceResolverFactory(this);
resolver.addExtraParameters(objects);
Serializable compiled = MVEL.compileExpression(expression);
MVEL.executeExpression(compiled, resolver);
String varName = VariableUtil.nameFromDotNotation(paramName);
variableScopeInstance = (VariableScopeInstance) resolveContextInstance(VARIABLE_SCOPE, varName);
variableScopeInstance.setVariable(this, varName, variableScopeInstance.getVariable(varName));
} else {
logger.warn("Could not find variable scope for variable {}", association.getTarget());
}
}
}
}
}
}
use of io.automatiko.engine.workflow.process.core.node.DataAssociation in project automatiko-engine by automatiko-io.
the class ServiceTaskDescriptor method completeWorkItem.
private MethodCallExpr completeWorkItem(BlockStmt executeWorkItemBody, MethodCallExpr callService) {
Expression results = null;
List<DataAssociation> outAssociations = workItemNode.getOutAssociations();
if (hasReturn()) {
VariableDeclarationExpr resultField = new VariableDeclarationExpr().addVariable(new VariableDeclarator(new ClassOrInterfaceType(null, Object.class.getCanonicalName()), "result", callService));
executeWorkItemBody.addStatement(resultField);
if (outAssociations.isEmpty()) {
results = new NullLiteralExpr();
} else {
results = new MethodCallExpr(new NameExpr("java.util.Collections"), "singletonMap").addArgument(new StringLiteralExpr(outAssociations.get(0).getSources().isEmpty() ? "workflowdata" : outAssociations.get(0).getSources().get(0))).addArgument(new NameExpr("result"));
}
} else if (outAssociations.isEmpty()) {
executeWorkItemBody.addStatement(callService);
results = new NullLiteralExpr();
} else {
VariableDeclarationExpr resultField = new VariableDeclarationExpr().addVariable(new VariableDeclarator(new ClassOrInterfaceType(null, Object.class.getCanonicalName()), "result", callService));
executeWorkItemBody.addStatement(resultField);
results = new MethodCallExpr(new NameExpr("java.util.Collections"), "singletonMap").addArgument(new StringLiteralExpr(outAssociations.get(0).getSources().isEmpty() ? "workflowdata" : outAssociations.get(0).getSources().get(0))).addArgument(new NameExpr("result"));
}
MethodCallExpr completeWorkItem = new MethodCallExpr(new NameExpr("workItemManager"), "completeWorkItem").addArgument(new MethodCallExpr(new NameExpr("workItem"), "getId")).addArgument(results);
return completeWorkItem;
}
use of io.automatiko.engine.workflow.process.core.node.DataAssociation in project automatiko-engine by automatiko-io.
the class StartNodeVisitor method visitNode.
@Override
public void visitNode(WorkflowProcess process, String factoryField, StartNode node, BlockStmt body, VariableScope variableScope, ProcessMetaData metadata) {
body.addStatement(getAssignedFactoryMethod(factoryField, StartNodeFactory.class, getNodeId(node), getNodeKey(), new LongLiteralExpr(node.getId()))).addStatement(getNameMethod(node, "Start")).addStatement(getFactoryMethod(getNodeId(node), METHOD_INTERRUPTING, new BooleanLiteralExpr(node.isInterrupting())));
visitMetaData(node.getMetaData(), body, getNodeId(node));
boolean serverless = ProcessToExecModelGenerator.isServerlessWorkflow(process);
if (serverless) {
for (DataAssociation association : node.getOutAssociations()) {
if (association.getAssignments() != null && !association.getAssignments().isEmpty()) {
TaskOutputJqAssignmentAction action = (TaskOutputJqAssignmentAction) association.getAssignments().get(0).getMetaData("Action");
String outputFilter = action.getOutputFilterExpression();
String scopeFilter = action.getScopeFilter();
body.addStatement(getFactoryMethod(getNodeId(node), METHOD_OUT_JQ_MAPPING, (outputFilter != null ? new StringLiteralExpr().setString(outputFilter) : new NullLiteralExpr()), (scopeFilter != null ? new StringLiteralExpr().setString(scopeFilter) : new NullLiteralExpr()), new BooleanLiteralExpr(action.isIgnoreScopeFilter())));
}
}
} else {
for (DataAssociation entry : node.getOutAssociations()) {
if (entry.getAssignments() != null && !entry.getAssignments().isEmpty()) {
Assignment assignment = entry.getAssignments().get(0);
body.addStatement(getFactoryMethod(getNodeId(node), "outMapping", new StringLiteralExpr(entry.getSources().get(0)), new NullLiteralExpr(), new StringLiteralExpr(assignment.getDialect()), new StringLiteralExpr(assignment.getFrom()), new StringLiteralExpr(assignment.getTo())));
} else {
body.addStatement(getFactoryMethod(getNodeId(node), "outMapping", new StringLiteralExpr(entry.getSources().get(0)), new StringLiteralExpr(entry.getTarget()), new NullLiteralExpr(), new NullLiteralExpr(), new NullLiteralExpr()));
}
}
}
body.addStatement(getDoneMethod(getNodeId(node)));
if (node.getTimer() != null) {
Timer timer = node.getTimer();
body.addStatement(getFactoryMethod(getNodeId(node), METHOD_TIMER, getOrNullExpr(timer.getDelay()), getOrNullExpr(timer.getPeriod()), getOrNullExpr(timer.getDate()), new IntegerLiteralExpr(node.getTimer().getTimeType())));
} else if (node.getTriggers() != null && !node.getTriggers().isEmpty()) {
Map<String, Object> nodeMetaData = node.getMetaData();
TriggerMetaData trigger = new TriggerMetaData((String) nodeMetaData.get(TRIGGER_REF), (String) nodeMetaData.get(TRIGGER_TYPE), (String) nodeMetaData.get(MESSAGE_TYPE), (String) nodeMetaData.get(TRIGGER_MAPPING), String.valueOf(node.getId()), node.getName(), (String) nodeMetaData.get(TRIGGER_CORRELATION), (String) nodeMetaData.get(TRIGGER_CORRELATION_EXPR)).validate();
trigger.addContext(node.getMetaData());
trigger.addContext(Collections.singletonMap("_node_", node));
// mark the trigger as capable of starting new instance only if this is top level start node
if (node.getParentContainer() instanceof WorkflowProcess) {
trigger.setStart(true);
}
metadata.addTrigger(trigger);
handleTrigger(node, nodeMetaData, body, variableScope, metadata);
} else {
// since there is start node without trigger then make sure it is startable
metadata.setStartable(true);
}
}
use of io.automatiko.engine.workflow.process.core.node.DataAssociation in project automatiko-engine by automatiko-io.
the class ScriptTaskHandler method readDataInputAssociation.
protected void readDataInputAssociation(org.w3c.dom.Node xmlNode, ActionNode actionNode, Map<String, String> dataInputs) {
// sourceRef
org.w3c.dom.Node subNode = xmlNode.getFirstChild();
if ("sourceRef".equals(subNode.getNodeName())) {
List<String> sources = new ArrayList<>();
sources.add(subNode.getTextContent());
subNode = subNode.getNextSibling();
while ("sourceRef".equals(subNode.getNodeName())) {
sources.add(subNode.getTextContent());
subNode = subNode.getNextSibling();
}
// targetRef
String target = subNode.getTextContent();
// transformation
Transformation transformation = null;
subNode = subNode.getNextSibling();
if (subNode != null && "transformation".equals(subNode.getNodeName())) {
String lang = subNode.getAttributes().getNamedItem("language").getNodeValue();
String expression = subNode.getTextContent();
DataTransformer transformer = transformerRegistry.find(lang);
if (transformer == null) {
throw new IllegalArgumentException("No transformer registered for language " + lang);
}
transformation = new Transformation(lang, expression);
subNode = subNode.getNextSibling();
}
// assignments
List<Assignment> assignments = new LinkedList<Assignment>();
while (subNode != null) {
String expressionLang = ((Element) subNode).getAttribute("expressionLanguage");
if (expressionLang == null || expressionLang.trim().isEmpty()) {
expressionLang = "XPath";
}
org.w3c.dom.Node ssubNode = subNode.getFirstChild();
String from = ssubNode.getTextContent();
String to = ssubNode.getNextSibling().getTextContent();
assignments.add(new Assignment(expressionLang, from, to));
subNode = subNode.getNextSibling();
}
actionNode.addInAssociation(new DataAssociation(sources, dataInputs.get(target), assignments, transformation));
}
}
Aggregations