Abhitocode commented on code in PR #7207:
URL: https://github.com/apache/incubator-kie/pull/7207#discussion_r4353509085


##########
kogito-jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/WorkItemModelMetaData.java:
##########
@@ -76,45 +82,209 @@ public class WorkItemModelMetaData {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(WorkItemModelMetaData.class);
 
-    private static final String TASK_INTPUT_CLASS_SUFFIX = "TaskInput";
-    private static final String TASK_OUTTPUT_CLASS_SUFFIX = "TaskOutput";
+    @KieInternal
+    public static final String CONFLICTING_TYPES_ERROR_TEMPLATE = "Conflicting 
types for %s parameter '%s' in task '%s' of process '%s': %s vs %s";
+    @KieInternal
+    public static final String MISMATCHED_DEFINITION_ERROR_TEMPLATE = "Cannot 
share taskName '%s' between work items of different definition types ('%s' vs 
'%s') in process '%s'";
+
+    private static final String TASK_INPUT_CLASS_SUFFIX = "TaskInput";
+    private static final String TASK_OUTPUT_CLASS_SUFFIX = "TaskOutput";
     private static final String TASK_MODEL_CLASS_SUFFIX = "TaskModel";
-    private static final String TASK_NAME = "TaskName";
+    private static final String TASK_NAME_PARAM = "TaskName";
     private static final String WORK_ITEM = "workItem";
     private static final String PARAMS = "params";
 
-    private final String packageName;
+    public record ParameterDefinition(String originalKey, String 
sanitizedName, String type) {
+    }
 
+    public record WorkItemNodeContext(WorkItemNode workItemNode, VariableScope 
variableScope) {
+    }
+
+    private final String packageName;
     private final VariableScope processVariableScope;
-    private final VariableScope variableScope;
-    private final WorkItemNode workItemNode;
+    private final String taskName;
     private final String processId;
+    private Work work;
 
-    private String inputModelClassName;
-    private String inputModelClassSimpleName;
-
-    private String outputModelClassName;
-    private String outputModelClassSimpleName;
+    private final String inputModelClassName;
+    private final String inputModelClassSimpleName;
+    private final String outputModelClassName;
+    private final String outputModelClassSimpleName;
+    private final String taskModelClassName;
+    private final String taskModelClassSimpleName;
 
-    private String taskModelClassName;
-    private String taskModelClassSimpleName;
+    private final List<WorkItemNodeContext> nodes = new ArrayList<>();
+    private final Map<String, ParameterDefinition> inputParamDefs = new 
LinkedHashMap<>();
+    private final Map<String, ParameterDefinition> outputParamDefs = new 
LinkedHashMap<>();
 
-    public WorkItemModelMetaData(String packageName, VariableScope 
processVariableScope, VariableScope variableScope, WorkItemNode workItemNode, 
String processId) {
+    public WorkItemModelMetaData(String packageName, VariableScope 
processVariableScope, String taskName, String processId) {
         this.packageName = packageName;
         this.processVariableScope = processVariableScope;
-        this.variableScope = variableScope;
-        this.workItemNode = workItemNode;
+        this.taskName = taskName;
         this.processId = processId;
 
-        this.inputModelClassSimpleName = 
sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" 
+ workItemNode.getId().toExternalFormat() + "_" + TASK_INTPUT_CLASS_SUFFIX);
+        String classPrefix = 
sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" 
+ sanitizeClassName(taskName));
+
+        this.inputModelClassSimpleName = classPrefix + "_" + 
TASK_INPUT_CLASS_SUFFIX;
         this.inputModelClassName = packageName + '.' + 
inputModelClassSimpleName;
 
-        this.outputModelClassSimpleName = 
sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" 
+ workItemNode.getId().toExternalFormat() + "_" + TASK_OUTTPUT_CLASS_SUFFIX);
+        this.outputModelClassSimpleName = classPrefix + "_" + 
TASK_OUTPUT_CLASS_SUFFIX;
         this.outputModelClassName = packageName + '.' + 
outputModelClassSimpleName;
 
-        this.taskModelClassSimpleName = 
sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" 
+ workItemNode.getId().toExternalFormat() + "_" + TASK_MODEL_CLASS_SUFFIX);
+        this.taskModelClassSimpleName = classPrefix + "_" + 
TASK_MODEL_CLASS_SUFFIX;
         this.taskModelClassName = packageName + '.' + taskModelClassSimpleName;
+    }
+
+    public WorkItemModelMetaData add(WorkItemNode workItemNode, VariableScope 
nodeVariableScope) {
+        if (this.work == null) {
+            this.work = Objects.requireNonNull(workItemNode.getWork(), 
"WorkItemNode work cannot be null");
+        } else {
+            String existingWorkName = this.work.getName();
+            String newWorkName = workItemNode.getWork().getName();
+            if (!existingWorkName.equals(newWorkName)) {
+                throw new IllegalArgumentException(String.format(
+                        MISMATCHED_DEFINITION_ERROR_TEMPLATE,
+                        taskName, existingWorkName, newWorkName, processId));
+            }
+        }
+
+        nodes.add(new WorkItemNodeContext(workItemNode, nodeVariableScope));
+
+        boolean isHumanTask = workItemNode instanceof HumanTaskNode;
+        Map<String, ParameterDefinition> nodeInputs = extractInputParameters(
+                workItemNode, processVariableScope, nodeVariableScope, 
isHumanTask);
+        mergeParameters(inputParamDefs, nodeInputs, "input");
+
+        Map<String, ParameterDefinition> nodeOutputs = extractOutputParameters(
+                workItemNode, processVariableScope, nodeVariableScope, 
isHumanTask);
+        mergeParameters(outputParamDefs, nodeOutputs, "output");
+
+        return this;
+    }
+
+    private void mergeParameters(Map<String, ParameterDefinition> target, 
Map<String, ParameterDefinition> source, String direction) {
+        for (Entry<String, ParameterDefinition> entry : source.entrySet()) {
+            ParameterDefinition existing = target.get(entry.getKey());
+            if (existing != null) {
+                if (!existing.type().equals(entry.getValue().type())) {
+                    throw new IllegalArgumentException(String.format(
+                            CONFLICTING_TYPES_ERROR_TEMPLATE,
+                            direction, entry.getValue().originalKey(), 
taskName, processId, existing.type(), entry.getValue().type()));
+                }
+            } else {
+                target.put(entry.getKey(), entry.getValue());
+            }
+        }
+    }
+
+    public static Map<String, ParameterDefinition> 
extractInputParameters(WorkItemNode workItemNode, VariableScope 
processVariableScope,
+            VariableScope nodeVariableScope, boolean isHumanTask) {
+        Map<String, ParameterDefinition> inputParamDefs = new 
LinkedHashMap<>();
+        Map<String, String> inputTypes = 
workItemNode.getIoSpecification().getInputTypes();
+
+        for (Entry<String, String> entry : 
workItemNode.getIoSpecification().getInputMapping().entrySet()) {
+            if (TASK_NAME_PARAM.equals(entry.getKey()) || (isHumanTask && 
HumanTaskNode.TASK_PARAMETERS.contains(entry.getKey()))) {
+                continue;
+            }
+
+            Variable variable = 
Optional.ofNullable(nodeVariableScope.findVariable(entry.getValue()))
+                    
.orElse(processVariableScope.findVariable(entry.getValue()));
+
+            if (variable == null) {
+                variable = new Variable();
+                variable.setName(entry.getKey());
+                DataType type = 
DataTypeResolver.fromType(inputTypes.get(entry.getKey()), 
Thread.currentThread().getContextClassLoader());
+                variable.setType(type);
+                if (entry.getValue() != null && 
!PatternConstants.PARAMETER_MATCHER.matcher(entry.getValue()).find()) {
+                    variable.setValue(type.readValue(entry.getValue()));
+                }
+            }
+
+            String variableType = variable.getType().getStringType();
+            if (Object.class.getCanonicalName().equals(variableType)) {
+                LOGGER.warn("{} input variable '{}' is declared as 
java.lang.Object. " +
+                        "Object type variables are persisted using Java 
serialization. " +
+                        "Make sure the stored value implements 
java.io.Serializable.",
+                        isHumanTask ? "User task" : "Work item", 
entry.getKey());
+            }
+
+            String fieldName = sanitizeJavaName(entry.getKey());
+            inputParamDefs.put(fieldName, new 
ParameterDefinition(entry.getKey(), fieldName, variableType));
+        }
+
+        for (Entry<String, Object> entry : 
workItemNode.getWork().getParameters().entrySet()) {
+            if (entry.getValue() == null || 
TASK_NAME_PARAM.equals(entry.getKey()) || (isHumanTask && 
HumanTaskNode.TASK_PARAMETERS.contains(entry.getKey()))) {

Review Comment:
   Just a doubt @pefernan , earlier the check was just 
`HumanTaskNode.TASK_PARAMETERS.contains(entry.getKey())`, now it has` 
isHumanTask &&` in front. With custom tasks the generated `TaskInput` now gets 
`UNIQUE_TASK_ID` and `NodeName` as fields next to the real inputs, which it 
didn't before. Is that intended? If not, I think the guard can be dropped here 
and on lines 186/233.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to