diff --git a/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/AdHocSubProcessHandler.java b/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/AdHocSubProcessHandler.java index 8d11bbc3dc5..89a24f95137 100755 --- a/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/AdHocSubProcessHandler.java +++ b/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/AdHocSubProcessHandler.java @@ -63,17 +63,26 @@ protected Node handleNode(final Node node, final Element element, final String u if ("false".equals(cancelRemainingInstances)) { dynamicNode.setCancelRemainingInstances(false); } + + dynamicNode.setLanguage("http://www.java.com/java"); + // by default it should not autocomplete as it's adhoc org.w3c.dom.Node xmlNode = element.getFirstChild(); dynamicNode.setActivationCondition((String) node.getMetaData().get(CUSTOM_ACTIVATION_CONDITION)); while (xmlNode != null) { String nodeName = xmlNode.getNodeName(); if (COMPLETION_CONDITION.equals(nodeName)) { + Element completeConditionElement = (Element) xmlNode; + String dialect = completeConditionElement.getAttribute("language"); + String expression = xmlNode.getTextContent(); if (AUTOCOMPLETE_EXPRESSIONS.contains(expression)) { dynamicNode.setAutoComplete(true); } else { dynamicNode.setCompletionCondition(expression); + if (!dialect.isBlank()) { + dynamicNode.setLanguage(dialect); + } } } xmlNode = xmlNode.getNextSibling(); @@ -104,7 +113,7 @@ public void writeNode(Node node, StringBuilder xmlDump, int metaDataType) { visitConnectionsAndAssociations(dynamicNode, xmlDump, metaDataType); if (dynamicNode.isAutoComplete()) { - xmlDump.append(" " + AUTOCOMPLETE_COMPLETION_CONDITION + "" + EOL); + xmlDump.append("" + AUTOCOMPLETE_COMPLETION_CONDITION + "" + EOL); } endNode("adHocSubProcess", xmlDump); } diff --git a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/DynamicNodeVisitor.java b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/DynamicNodeVisitor.java index 6535aa5466f..555ac270adc 100644 --- a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/DynamicNodeVisitor.java +++ b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/DynamicNodeVisitor.java @@ -20,8 +20,10 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.stream.Stream; +import org.jbpm.compiler.canonical.builtin.ReturnValueEvaluatorBuilderService; import org.jbpm.compiler.canonical.node.NodeVisitorBuilderService; import org.jbpm.process.core.context.variable.VariableScope; import org.jbpm.ruleflow.core.factory.DynamicNodeFactory; @@ -35,8 +37,11 @@ public class DynamicNodeVisitor extends CompositeContextNodeVisitor { - public DynamicNodeVisitor(NodeVisitorBuilderService nodeVisitorService) { + private ReturnValueEvaluatorBuilderService builder; + + public DynamicNodeVisitor(NodeVisitorBuilderService nodeVisitorService, ClassLoader classLoader) { super(nodeVisitorService); + this.builder = ReturnValueEvaluatorBuilderService.instance(classLoader); } @Override @@ -56,22 +61,26 @@ protected String getDefaultName() { @Override public Stream visitCustomFields(DynamicNode node, VariableScope variableScope) { + if (node.isAutoComplete()) { + return Collections. emptyList().stream(); + } + Collection methods = new ArrayList<>(); methods.add(getFactoryMethod(getNodeId(node), METHOD_LANGUAGE, getOrNullExpr(node.getLanguage()))); - if (node.getActivationCondition() != null && !node.getActivationCondition().trim().isEmpty()) { - methods.add(getActivationConditionStatement(node, variableScope)); + if (node.getActivationCondition() != null && !node.getActivationCondition().isBlank()) { + methods.add(getActivationConditionStatement(node)); } - if (node.getCompletionCondition() != null && !node.getCompletionCondition().trim().isEmpty()) { - methods.add(getCompletionConditionStatement(node, variableScope)); + if (node.getCompletionCondition() != null && !node.getCompletionCondition().isBlank()) { + methods.add(getCompletionConditionStatement(node)); } return methods.stream(); } - private MethodCallExpr getActivationConditionStatement(DynamicNode node, VariableScope scope) { - return getFactoryMethod(getNodeId(node), METHOD_ACTIVATION_EXPRESSION, createLambdaExpr(node.getActivationCondition(), scope)); + private MethodCallExpr getActivationConditionStatement(DynamicNode node) { + return getFactoryMethod(getNodeId(node), METHOD_ACTIVATION_EXPRESSION, builder.build(node, node.getLanguage(), node.getActivationCondition(), Boolean.class, (String) null)); } - private MethodCallExpr getCompletionConditionStatement(DynamicNode node, VariableScope scope) { - return getFactoryMethod(getNodeId(node), METHOD_COMPLETION_EXPRESSION, createLambdaExpr(node.getCompletionCondition(), scope)); + private MethodCallExpr getCompletionConditionStatement(DynamicNode node) { + return getFactoryMethod(getNodeId(node), METHOD_COMPLETION_EXPRESSION, builder.build(node, node.getLanguage(), node.getCompletionCondition(), Boolean.class, (String) null)); } } diff --git a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/builtin/JavaConstraintEvaluatorBuilder.java b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/builtin/JavaConstraintEvaluatorBuilder.java index d85f3fe76ba..621592cc278 100644 --- a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/builtin/JavaConstraintEvaluatorBuilder.java +++ b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/builtin/JavaConstraintEvaluatorBuilder.java @@ -26,12 +26,14 @@ import org.jbpm.process.core.context.variable.Variable; import org.jbpm.process.core.context.variable.VariableScope; +import com.github.javaparser.ParseProblemException; import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.LambdaExpr; import com.github.javaparser.ast.expr.NameExpr; import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.ReturnStmt; import com.github.javaparser.ast.type.UnknownType; public class JavaConstraintEvaluatorBuilder implements ReturnValueEvaluatorBuilder { @@ -48,7 +50,16 @@ public Expression build(ContextResolver resolver, String expression, Class ty new Parameter(new UnknownType(), KCONTEXT_VAR), // (kcontext) -> actionBody); - BlockStmt blockStmt = StaticJavaParser.parseBlock("{" + expression + "}"); + BlockStmt blockStmt = parseExpression(expression); + + if (blockStmt == null) { + blockStmt = parseStatement(expression); + } + + if (blockStmt == null) { + blockStmt = StaticJavaParser.parseBlock(expression); + } + Set identifiers = new HashSet<>(blockStmt.findAll(NameExpr.class)); for (NameExpr v : identifiers) { @@ -57,7 +68,7 @@ public Expression build(ContextResolver resolver, String expression, Class ty continue; } Variable variable = variableScope.findVariable(v.getNameAsString()); - actionBody.addStatement(AbstractNodeVisitor.makeAssignment(variable)); + actionBody.addStatement(0, AbstractNodeVisitor.makeAssignment(variable)); } blockStmt.getStatements().forEach(actionBody::addStatement); @@ -65,4 +76,23 @@ public Expression build(ContextResolver resolver, String expression, Class ty return lambda; } + private BlockStmt parseStatement(String expression) { + try { + BlockStmt block = new BlockStmt(); + block.addStatement(StaticJavaParser.parseStatement("{" + expression + "}")); + return block; + } catch (ParseProblemException e) { + return null; + } + } + + private BlockStmt parseExpression(String expression) { + try { + BlockStmt block = new BlockStmt(); + block.addStatement(new ReturnStmt(StaticJavaParser.parseExpression(expression))); + return block; + } catch (ParseProblemException e) { + return null; + } + } } diff --git a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/node/DynamicNodeVisitorBuilder.java b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/node/DynamicNodeVisitorBuilder.java index f463651f74a..fdf5f54821c 100644 --- a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/node/DynamicNodeVisitorBuilder.java +++ b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/node/DynamicNodeVisitorBuilder.java @@ -32,7 +32,7 @@ public Class type() { @Override public AbstractNodeVisitor visitor(NodeVisitorBuilderService nodeVisitorService, ClassLoader classLoader) { - return new DynamicNodeVisitor(nodeVisitorService); + return new DynamicNodeVisitor(nodeVisitorService, classLoader); } } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/DynamicNodeFactory.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/DynamicNodeFactory.java index 53acb5bcdcf..c956b051983 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/DynamicNodeFactory.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/DynamicNodeFactory.java @@ -18,13 +18,11 @@ */ package org.jbpm.ruleflow.core.factory; -import java.util.function.Predicate; - +import org.jbpm.process.instance.impl.ReturnValueEvaluator; import org.jbpm.ruleflow.core.RuleFlowNodeContainerFactory; import org.jbpm.workflow.core.NodeContainer; import org.jbpm.workflow.core.node.DynamicNode; import org.kie.api.definition.process.WorkflowElementIdentifier; -import org.kie.api.runtime.process.ProcessContext; public class DynamicNodeFactory> extends AbstractCompositeNodeFactory, T> { @@ -45,12 +43,12 @@ public DynamicNodeFactory language(String language) { return this; } - public DynamicNodeFactory activationExpression(Predicate activationExpression) { + public DynamicNodeFactory activationExpression(ReturnValueEvaluator activationExpression) { getDynamicNode().setActivationExpression(activationExpression); return this; } - public DynamicNodeFactory completionExpression(Predicate completionExpression) { + public DynamicNodeFactory completionExpression(ReturnValueEvaluator completionExpression) { getDynamicNode().setCompletionExpression(completionExpression); return this; } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/DynamicNode.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/DynamicNode.java index d09348f1e5f..5130acaddc2 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/DynamicNode.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/DynamicNode.java @@ -20,9 +20,9 @@ import java.util.Arrays; import java.util.List; -import java.util.function.Predicate; import java.util.stream.Collectors; +import org.jbpm.process.instance.impl.ReturnValueEvaluator; import org.kie.api.definition.process.Node; import org.kie.api.definition.process.WorkflowElementIdentifier; import org.kie.api.runtime.process.ProcessContext; @@ -42,8 +42,8 @@ public class DynamicNode extends CompositeContextNode { */ private String completionCondition; - private Predicate activationPredicate; - private Predicate completionPredicate; + private ReturnValueEvaluator activationPredicate; + private ReturnValueEvaluator completionPredicate; private String language; public DynamicNode() { @@ -89,22 +89,22 @@ public void setCompletionCondition(String completionCondition) { this.completionCondition = completionCondition; } - public DynamicNode setActivationExpression(Predicate activationPredicate) { + public DynamicNode setActivationExpression(ReturnValueEvaluator activationPredicate) { this.activationPredicate = activationPredicate; return this; } - public DynamicNode setCompletionExpression(Predicate copmletionPredicate) { + public DynamicNode setCompletionExpression(ReturnValueEvaluator copmletionPredicate) { this.completionPredicate = copmletionPredicate; return this; } public boolean canActivate(ProcessContext context) { - return activationPredicate == null || activationPredicate.test(context); + return activationPredicate == null || (Boolean) activationPredicate.eval(context); } public boolean canComplete(ProcessContext context) { - return isAutoComplete() || (completionPredicate != null && completionPredicate.test(context)); + return isAutoComplete() || (completionPredicate != null && (Boolean) completionPredicate.eval(context)); } public boolean hasCompletionCondition() {