Skip to content
Merged

4798 #4844

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ public static List<WorkflowTask> getTasks(List<WorkflowTask> workflowTasks, Stri
returnedWorkflowTasks.addAll(getTasks(curWorkflowTasks, lastWorkflowNodeName));
}

if (firstItem instanceof Map<?, ?> map && map.containsKey(WorkflowConstants.NAME) &&
map.containsKey(WorkflowConstants.TYPE)) {
if (firstItem instanceof Map<?, ?> map && isWorkflowTaskMap(map)) {

List<WorkflowTask> curWorkflowTasks = curList.stream()
.map(item -> new WorkflowTask((Map<String, ?>) item))
Expand All @@ -75,8 +74,7 @@ public static List<WorkflowTask> getTasks(List<WorkflowTask> workflowTasks, Stri
}
// Fork/join support
} else if (firstItem instanceof List<?> list && !list.isEmpty() &&
list.getFirst() instanceof Map<?, ?> map && map.containsKey(WorkflowConstants.NAME) &&
map.containsKey(WorkflowConstants.TYPE)) {
list.getFirst() instanceof Map<?, ?> map && isWorkflowTaskMap(map)) {

for (Object curItem : curList) {
List<?> curSubList = (List<?>) curItem;
Expand All @@ -90,8 +88,7 @@ public static List<WorkflowTask> getTasks(List<WorkflowTask> workflowTasks, Stri
}
}
// Each support
} else if (entry.getValue() instanceof Map<?, ?> curMap &&
curMap.containsKey(WorkflowConstants.NAME) && curMap.containsKey(WorkflowConstants.TYPE)) {
} else if (entry.getValue() instanceof Map<?, ?> curMap && isWorkflowTaskMap(curMap)) {

returnedWorkflowTasks.addAll(
getTasks(List.of(new WorkflowTask((Map<String, ?>) curMap)), lastWorkflowNodeName));
Expand Down Expand Up @@ -124,6 +121,31 @@ public static List<WorkflowTask> getTasks(List<WorkflowTask> workflowTasks, Stri
return resultWorkflowTasks;
}

private static boolean isWorkflowTaskMap(Map<?, ?> map) {
if (!map.containsKey(WorkflowConstants.NAME) || !map.containsKey(WorkflowConstants.TYPE)) {
return false;
}

// Workflow task types always follow the format: componentName/vVersion[/operation].
// This distinguishes real tasks from user-defined data structures that happen to have
// name/type keys (e.g., PostgreSQL column definitions like {"name": "ime", "type": "STRING"}).
return map.get(WorkflowConstants.TYPE) instanceof String type && isWorkflowNodeType(type);
}

private static boolean isWorkflowNodeType(String type) {
String[] parts = type.split("/", -1);

if (parts.length < 2 || parts.length > 3) {
return false;
}

if (parts[0].isEmpty() || !parts[1].matches("v\\d+")) {
return false;
}

return parts.length == 2 || !parts[2].isEmpty();
}

private static List<WorkflowTask> getPrevious(List<WorkflowTask> workflowTasks, String workflowTaskName) {
List<WorkflowTask> previousWorkflowTasks = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,28 @@ void testNonTaskListWithTypeKeyIsIgnored() {
assertEquals(Set.of("dataStorage_1"), names);
}

@Test
void testNonTaskListWithNameAndTypeKeysIsIgnored() {
// A parameter value that's List<Map> whose maps carry BOTH `name` and `type`
// must not be mistaken for tasks if the `type` value isn't a valid workflow node
// type (e.g., PostgreSQL column definitions use {"name": "col", "type": "STRING"}).
WorkflowTask task = new WorkflowTask(Map.of(
"name", "postgresql_1",
"type", "postgresql/v1/insert",
"parameters", Map.of(
"schema", "public",
"columns", List.of(
Map.of("type", "STRING", "name", "ime"),
Map.of("type", "NUMBER", "name", "age")))));

Set<String> names = WorkflowTaskUtils.getTasks(List.of(task), null)
.stream()
.map(WorkflowTask::getName)
.collect(Collectors.toSet());

assertEquals(Set.of("postgresql_1"), names);
}

@Test
void testFlattenLoopIterateeStartingWithTaskWithoutParameters() {
WorkflowTask loop = new WorkflowTask(Map.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ private enum ValueType {
protected static OutputResponse output(
Parameters inputParameters, Parameters connectionParameters, Context context) {

if (!inputParameters.containsKey(VALUE)) {
if (!inputParameters.containsKey(VALUE) || inputParameters.get(VALUE) == null) {
return null;
}

Expand Down
Loading