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]