This is an automated email from the ASF dual-hosted git repository.

fjtiradosarti pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git


The following commit(s) were added to refs/heads/main by this push:
     new 8e67de3c0a Adding bifunction and trifunction support to fluent api 
(#3853)
8e67de3c0a is described below

commit 8e67de3c0a93054e5b006f3d7ab7ceedf3f42dab
Author: Francisco Javier Tirado Sarti 
<[email protected]>
AuthorDate: Thu Feb 27 13:56:22 2025 +0100

    Adding bifunction and trifunction support to fluent api (#3853)
---
 .../org/jbpm/workflow/core/impl/NodeIoHelper.java  |  3 +-
 .../instance/node/WorkItemNodeInstance.java        |  3 +-
 .../process/workitems/impl/KogitoWorkItemImpl.java |  4 +-
 .../workflow/functions/FunctionDefinitionEx.java   | 29 ++++++++++--
 ...{FunctionDefinitionEx.java => TriFunction.java} | 26 ++---------
 .../executor/StaticFunctionWorkItemHandler.java    | 51 +++++++++++++++++-----
 .../workflow/executor/StaticJavaRegister.java      |  2 +-
 .../StaticFluentWorkflowApplicationTest.java       | 28 ++++++++++++
 .../serverless/workflow/fluent/ActionBuilder.java  | 12 +++++
 .../workflow/fluent/FunctionBuilder.java           | 12 ++++-
 .../workflow/WorkflowWorkItemHandler.java          |  4 +-
 11 files changed, 130 insertions(+), 44 deletions(-)

diff --git 
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeIoHelper.java 
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeIoHelper.java
index 5eaa8f0d98..0465f2658f 100644
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeIoHelper.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeIoHelper.java
@@ -21,6 +21,7 @@ package org.jbpm.workflow.core.impl;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -145,7 +146,7 @@ public class NodeIoHelper {
             Function<String, Object> targetResolver) {
 
         NodeIoHelper ioHelper = new NodeIoHelper(nodeInstanceImpl);
-        Map<String, Object> inputSet = new HashMap<>();
+        Map<String, Object> inputSet = new LinkedHashMap<>();
         // for inputs resolve it is supposed to create object by default 
constructor (that is the reason is null
         ioHelper.processInputs(dataInputAssociation, sourceResolver, 
targetResolver, (target, value) -> inputSet.put(target, value));
         return inputSet;
diff --git 
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java
 
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java
index be1ff4ddfa..e16e47b64d 100755
--- 
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java
+++ 
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java
@@ -24,6 +24,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -231,7 +232,7 @@ public class WorkItemNodeInstance extends 
StateBasedNodeInstance implements Even
         workItem.setStartDate(new Date());
         workItem.setState(ACTIVE);
 
-        Map<String, Object> resolvedParameters = new HashMap<>();
+        Map<String, Object> resolvedParameters = new LinkedHashMap<>();
 
         Collection<String> metaParameters = work.getMetaParameters();
 
diff --git 
a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoWorkItemImpl.java
 
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoWorkItemImpl.java
index af06146384..5177ad7bdc 100755
--- 
a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoWorkItemImpl.java
+++ 
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoWorkItemImpl.java
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -39,7 +40,7 @@ public class KogitoWorkItemImpl implements 
InternalKogitoWorkItem, Serializable
     private String id;
     private String name;
     private int state = 0;
-    private Map<String, Object> parameters = new ProxyMap(new HashMap<>());
+    private Map<String, Object> parameters = new ProxyMap(new 
LinkedHashMap<>());
     private Map<String, Object> results = new HashMap<>();
     private String processInstanceId;
     private String deploymentId;
@@ -325,7 +326,6 @@ public class KogitoWorkItemImpl implements 
InternalKogitoWorkItem, Serializable
         @Override
         public void putAll(Map<? extends String, ? extends Object> m) {
             map.putAll(m);
-
         }
 
         @Override
diff --git 
a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/FunctionDefinitionEx.java
 
b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/FunctionDefinitionEx.java
index e06fa51af7..27481e204c 100644
--- 
a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/FunctionDefinitionEx.java
+++ 
b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/FunctionDefinitionEx.java
@@ -18,25 +18,46 @@
  */
 package org.kie.kogito.serverless.workflow.functions;
 
+import java.util.function.BiFunction;
 import java.util.function.Function;
 
 import io.serverlessworkflow.api.functions.FunctionDefinition;
 
-public class FunctionDefinitionEx<T, V> extends FunctionDefinition {
+public class FunctionDefinitionEx extends FunctionDefinition {
 
     private static final long serialVersionUID = 1L;
-    private transient Function<T, V> function;
+    private transient Function function;
+    private transient BiFunction bifunction;
+    private transient TriFunction trifunction;
 
     public FunctionDefinitionEx(String name) {
         super(name);
     }
 
-    public FunctionDefinition withFunction(Function<T, V> function) {
+    public FunctionDefinition withFunction(Function function) {
         this.function = function;
         return this;
     }
 
-    public Function<T, V> getFunction() {
+    public FunctionDefinition withBiFunction(BiFunction function) {
+        this.bifunction = function;
+        return this;
+    }
+
+    public FunctionDefinition withTriFunction(TriFunction function) {
+        this.trifunction = function;
+        return this;
+    }
+
+    public Function getFunction() {
         return function;
     }
+
+    public BiFunction getBiFunction() {
+        return bifunction;
+    }
+
+    public TriFunction getTriFunction() {
+        return trifunction;
+    }
 }
diff --git 
a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/FunctionDefinitionEx.java
 
b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/TriFunction.java
similarity index 60%
copy from 
kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/FunctionDefinitionEx.java
copy to 
kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/TriFunction.java
index e06fa51af7..4627750caf 100644
--- 
a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/FunctionDefinitionEx.java
+++ 
b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/functions/TriFunction.java
@@ -18,25 +18,7 @@
  */
 package org.kie.kogito.serverless.workflow.functions;
 
-import java.util.function.Function;
-
-import io.serverlessworkflow.api.functions.FunctionDefinition;
-
-public class FunctionDefinitionEx<T, V> extends FunctionDefinition {
-
-    private static final long serialVersionUID = 1L;
-    private transient Function<T, V> function;
-
-    public FunctionDefinitionEx(String name) {
-        super(name);
-    }
-
-    public FunctionDefinition withFunction(Function<T, V> function) {
-        this.function = function;
-        return this;
-    }
-
-    public Function<T, V> getFunction() {
-        return function;
-    }
-}
+@FunctionalInterface
+public interface TriFunction<T, U, V, R> {
+    R apply(T arg1, U arg2, V arg3);
+}
\ No newline at end of file
diff --git 
a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticFunctionWorkItemHandler.java
 
b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticFunctionWorkItemHandler.java
index acaa404100..39bb94bb02 100644
--- 
a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticFunctionWorkItemHandler.java
+++ 
b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticFunctionWorkItemHandler.java
@@ -18,42 +18,73 @@
  */
 package org.kie.kogito.serverless.workflow.executor;
 
+import java.util.Iterator;
 import java.util.Map;
+import java.util.function.BiFunction;
 import java.util.function.Function;
 
 import org.kie.kogito.internal.process.workitem.KogitoWorkItem;
 import org.kie.kogito.jackson.utils.JsonObjectUtils;
 import org.kie.kogito.serverless.workflow.SWFConstants;
 import org.kie.kogito.serverless.workflow.WorkflowWorkItemHandler;
+import org.kie.kogito.serverless.workflow.functions.FunctionDefinitionEx;
+import org.kie.kogito.serverless.workflow.functions.TriFunction;
 
 import com.fasterxml.jackson.databind.JsonNode;
 
 import static org.kie.kogito.serverless.workflow.SWFConstants.CONTENT_DATA;
 
-public class StaticFunctionWorkItemHandler<V, T> extends 
WorkflowWorkItemHandler {
+public class StaticFunctionWorkItemHandler extends WorkflowWorkItemHandler {
 
-    private final String name;
-    private final Function<V, T> function;
+    private final FunctionDefinitionEx functionDef;
 
-    public StaticFunctionWorkItemHandler(String name, Function<V, T> function) 
{
-        this.name = name;
-        this.function = function;
+    public StaticFunctionWorkItemHandler(FunctionDefinitionEx functionDef) {
+        this.functionDef = functionDef;
     }
 
     @Override
     public String getName() {
-        return name;
+        return functionDef.getName();
     }
 
     @Override
     protected Object internalExecute(KogitoWorkItem workItem, Map<String, 
Object> parameters) {
+        if (functionDef.getFunction() != null) {
+            return internalExecute(functionDef.getFunction(), workItem, 
parameters);
+        } else if (functionDef.getBiFunction() != null) {
+            return internalExecute(functionDef.getBiFunction(), parameters);
+        } else if (functionDef.getTriFunction() != null) {
+            return internalExecute(functionDef.getTriFunction(), parameters);
+        }
+        throw new IllegalStateException("No function set");
+    }
+
+    private Object internalExecute(TriFunction triFunction, Map<String, 
Object> parameters) {
+        checkParamsSize(parameters, 3);
+        Iterator<Object> iter = parameters.values().iterator();
+        return triFunction.apply(iter.next(), iter.next(), iter.next());
+    }
+
+    private Object internalExecute(BiFunction biFunction, Map<String, Object> 
parameters) {
+        checkParamsSize(parameters, 2);
+        Iterator<Object> iter = parameters.values().iterator();
+        return biFunction.apply(iter.next(), iter.next());
+    }
+
+    private void checkParamsSize(Map<String, Object> parameters, int size) {
+        if (parameters.size() != size) {
+            throw new IllegalArgumentException("Wrong number of arguments. The 
function expects " + size);
+        }
+    }
+
+    private Object internalExecute(Function function, KogitoWorkItem workItem, 
Map<String, Object> parameters) {
         int size = parameters.size();
         if (size == 0) {
-            return function.apply((V) JsonObjectUtils.toJavaValue((JsonNode) 
workItem.getParameter(SWFConstants.MODEL_WORKFLOW_VAR)));
+            return function.apply(JsonObjectUtils.toJavaValue((JsonNode) 
workItem.getParameter(SWFConstants.MODEL_WORKFLOW_VAR)));
         } else if (size == 1 && parameters.containsKey(CONTENT_DATA)) {
-            return function.apply((V) parameters.get(CONTENT_DATA));
+            return function.apply(parameters.get(CONTENT_DATA));
         } else {
-            return function.apply((V) parameters);
+            return function.apply(parameters);
         }
     }
 }
diff --git 
a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticJavaRegister.java
 
b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticJavaRegister.java
index 17bea35b1b..36d3f71a0e 100644
--- 
a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticJavaRegister.java
+++ 
b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticJavaRegister.java
@@ -28,7 +28,7 @@ public class StaticJavaRegister implements 
StaticWorkflowRegister {
     public void register(StaticWorkflowApplication application, Workflow 
workflow) {
         if (workflow.getFunctions() != null && 
workflow.getFunctions().getFunctionDefs() != null) {
             
workflow.getFunctions().getFunctionDefs().stream().filter(FunctionDefinitionEx.class::isInstance).map(FunctionDefinitionEx.class::cast)
-                    .forEach(function -> application.registerHandler(new 
StaticFunctionWorkItemHandler<>(function.getName(), function.getFunction())));
+                    .forEach(function -> application.registerHandler(new 
StaticFunctionWorkItemHandler(function)));
         }
     }
 }
diff --git 
a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java
 
b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java
index dfc9d750d3..bd3255d6ae 100644
--- 
a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java
+++ 
b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java
@@ -194,6 +194,10 @@ public class StaticFluentWorkflowApplicationTest {
         return one * two;
     }
 
+    private double quadratic(int one, int two, int three) {
+        return Math.sqrt(one * one + two * two - three * three);
+    }
+
     @Test
     void testJava() {
         final String DOUBLE = "double";
@@ -211,6 +215,30 @@ public class StaticFluentWorkflowApplicationTest {
         }
     }
 
+    @Test
+    void testJavaTwoParams() {
+        try (StaticWorkflowApplication application = 
StaticWorkflowApplication.create()) {
+            Workflow workflow = workflow("Javatest")
+                    .start(operation().action(call(java("multiply", 
this::multiply), ".input1", ".input2")))
+                    .end().build();
+            Process<JsonNodeModel> process = application.process(workflow);
+            JsonNode result = application.execute(process, Map.of("input1", 4, 
"input2", 8)).getWorkflowdata();
+            assertThat(result.get("response").asInt()).isEqualTo(32);
+        }
+    }
+
+    @Test
+    void testJavaThreeParams() {
+        try (StaticWorkflowApplication application = 
StaticWorkflowApplication.create()) {
+            Workflow workflow = workflow("Javatest")
+                    .start(operation().action(call(java("quadratic", 
this::quadratic), ".input1", ".input2", ".input3")))
+                    .end().build();
+            Process<JsonNodeModel> process = application.process(workflow);
+            JsonNode result = application.execute(process, Map.of("input1", 3, 
"input2", 4, "input3", 5)).getWorkflowdata();
+            assertThat(result.get("response").asInt()).isEqualTo(0);
+        }
+    }
+
     @Test
     void testInterpolation() {
         interpolation("\"My name is \\(.name) and my surname is 
\\(.surname)\"");
diff --git 
a/kogito-serverless-workflow/kogito-serverless-workflow-fluent/src/main/java/org/kie/kogito/serverless/workflow/fluent/ActionBuilder.java
 
b/kogito-serverless-workflow/kogito-serverless-workflow-fluent/src/main/java/org/kie/kogito/serverless/workflow/fluent/ActionBuilder.java
index 26be06f4f7..90a69f04f4 100644
--- 
a/kogito-serverless-workflow/kogito-serverless-workflow-fluent/src/main/java/org/kie/kogito/serverless/workflow/fluent/ActionBuilder.java
+++ 
b/kogito-serverless-workflow/kogito-serverless-workflow-fluent/src/main/java/org/kie/kogito/serverless/workflow/fluent/ActionBuilder.java
@@ -22,6 +22,7 @@ import java.time.Duration;
 import java.util.Optional;
 
 import org.kie.kogito.jackson.utils.JsonObjectUtils;
+import org.kie.kogito.jackson.utils.ObjectMapperFactory;
 import org.kie.kogito.process.Process;
 import org.kie.kogito.serverless.workflow.SWFConstants;
 import org.kie.kogito.serverless.workflow.actions.WorkflowLogLevel;
@@ -98,6 +99,17 @@ public class ActionBuilder {
         return call(functionBuilder, JsonObjectUtils.fromValue(args));
     }
 
+    public static ActionBuilder call(FunctionBuilder functionBuilder, Object 
first, Object second, Object... extras) {
+        ObjectNode node = ObjectMapperFactory.get().createObjectNode();
+        node.set("arg1", JsonObjectUtils.fromValue(first));
+        node.set("arg2", JsonObjectUtils.fromValue(second));
+        int i = 3;
+        for (Object extra : extras) {
+            node.set("arg" + i++, JsonObjectUtils.fromValue(extra));
+        }
+        return call(functionBuilder, node);
+    }
+
     public static ActionBuilder call(String functionName, JsonNode args) {
         return new ActionBuilder(new Action().withFunctionRef(new 
FunctionRef().withRefName(functionName).withArguments(args)));
     }
diff --git 
a/kogito-serverless-workflow/kogito-serverless-workflow-fluent/src/main/java/org/kie/kogito/serverless/workflow/fluent/FunctionBuilder.java
 
b/kogito-serverless-workflow/kogito-serverless-workflow-fluent/src/main/java/org/kie/kogito/serverless/workflow/fluent/FunctionBuilder.java
index 1abe1d2fca..5cebe9c905 100644
--- 
a/kogito-serverless-workflow/kogito-serverless-workflow-fluent/src/main/java/org/kie/kogito/serverless/workflow/fluent/FunctionBuilder.java
+++ 
b/kogito-serverless-workflow/kogito-serverless-workflow-fluent/src/main/java/org/kie/kogito/serverless/workflow/fluent/FunctionBuilder.java
@@ -21,11 +21,13 @@ package org.kie.kogito.serverless.workflow.fluent;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
+import java.util.function.BiFunction;
 import java.util.function.Function;
 
 import org.kie.kogito.serverless.workflow.SWFConstants;
 import org.kie.kogito.serverless.workflow.actions.WorkflowLogLevel;
 import org.kie.kogito.serverless.workflow.functions.FunctionDefinitionEx;
+import org.kie.kogito.serverless.workflow.functions.TriFunction;
 import org.kie.kogito.serverless.workflow.parser.types.ServiceTypeHandler;
 
 import io.serverlessworkflow.api.functions.FunctionDefinition;
@@ -64,7 +66,15 @@ public class FunctionBuilder {
     }
 
     public static <T, V> FunctionBuilder java(String funcName, Function<T, V> 
function) {
-        return new FunctionBuilder(new FunctionDefinitionEx<T, 
V>(funcName).withFunction(function).withType(Type.CUSTOM).withOperation("java"));
+        return new FunctionBuilder(new 
FunctionDefinitionEx(funcName).withFunction(function).withType(Type.CUSTOM).withOperation("java"));
+    }
+
+    public static <T, U, R> FunctionBuilder java(String funcName, 
BiFunction<T, U, R> function) {
+        return new FunctionBuilder(new 
FunctionDefinitionEx(funcName).withBiFunction(function).withType(Type.CUSTOM).withOperation("java"));
+    }
+
+    public static <T, U, V, R> FunctionBuilder java(String funcName, 
TriFunction<T, U, V, R> function) {
+        return new FunctionBuilder(new 
FunctionDefinitionEx(funcName).withTriFunction(function).withType(Type.CUSTOM).withOperation("java"));
     }
 
     public static FunctionBuilder java(String funcName, String className, 
String methodName) {
diff --git 
a/kogito-serverless-workflow/kogito-serverless-workflow-runtime/src/main/java/org/kie/kogito/serverless/workflow/WorkflowWorkItemHandler.java
 
b/kogito-serverless-workflow/kogito-serverless-workflow-runtime/src/main/java/org/kie/kogito/serverless/workflow/WorkflowWorkItemHandler.java
index 289f319895..b397eb7e53 100644
--- 
a/kogito-serverless-workflow/kogito-serverless-workflow-runtime/src/main/java/org/kie/kogito/serverless/workflow/WorkflowWorkItemHandler.java
+++ 
b/kogito-serverless-workflow/kogito-serverless-workflow-runtime/src/main/java/org/kie/kogito/serverless/workflow/WorkflowWorkItemHandler.java
@@ -19,7 +19,7 @@
 package org.kie.kogito.serverless.workflow;
 
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Optional;
 
@@ -38,7 +38,7 @@ public abstract class WorkflowWorkItemHandler extends 
DefaultKogitoWorkItemHandl
 
     @Override
     public Optional<WorkItemTransition> 
activateWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler 
handler, KogitoWorkItem workItem, WorkItemTransition transition) {
-        Map<String, Object> parameters = new 
HashMap<>(workItem.getParameters());
+        Map<String, Object> parameters = new 
LinkedHashMap<>(workItem.getParameters());
         parameters.remove(SWFConstants.MODEL_WORKFLOW_VAR);
         logger.debug("Workflow workitem {} will be invoked with parameters 
{}", workItem.getName(), parameters);
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to