diff --git a/process-inspector-test/src_test/com/axonivy/utils/process/inspector/test/FlowMixedSubProcess.java b/process-inspector-test/src_test/com/axonivy/utils/process/inspector/test/FlowMixedSubProcess.java index 2fe00b8..17ade8a 100644 --- a/process-inspector-test/src_test/com/axonivy/utils/process/inspector/test/FlowMixedSubProcess.java +++ b/process-inspector-test/src_test/com/axonivy/utils/process/inspector/test/FlowMixedSubProcess.java @@ -30,7 +30,7 @@ void shouldFindAllTasks() throws Exception { var start = ProcessGraphHelper.findByElementName(process, "start"); var detectedTasks = processInspector.findAllTasks(start, UseCase.BIGPROJECT); - var expected = Arrays.array("TaskA", "SubA-TaskA", "SubA-TaskC", "SubA-TaskB", "SubD-TaskB", "SubB-TaskA", "SubD-TaskC", "SubC-TaskA", "SubD-TaskB", "SubD-TaskA"); + var expected = Arrays.array("TaskA", "SubA-TaskA", "SubA-TaskC", "SubA-TaskB", "SubD-TaskB", "SubB-TaskA", "SubD-TaskC", "SubC-TaskA", "SubD-TaskD", "SubD-TaskA"); var taskNames = getTaskNames(detectedTasks); assertArrayEquals(expected, taskNames); } diff --git a/process-inspector/src/com/axonivy/utils/process/inspector/internal/PathFinder.java b/process-inspector/src/com/axonivy/utils/process/inspector/internal/PathFinder.java index 9402672..6bd8f56 100644 --- a/process-inspector/src/com/axonivy/utils/process/inspector/internal/PathFinder.java +++ b/process-inspector/src/com/axonivy/utils/process/inspector/internal/PathFinder.java @@ -2,6 +2,9 @@ import static com.axonivy.utils.process.inspector.internal.helper.AnalysisPathHelper.addAllToPath; import static com.axonivy.utils.process.inspector.internal.helper.AnalysisPathHelper.addToPath; +import static com.axonivy.utils.process.inspector.internal.helper.AnalysisPathHelper.getAnalysisPathFrom; +import static com.axonivy.utils.process.inspector.internal.helper.AnalysisPathHelper.getAnalysisPathTo; +import static com.axonivy.utils.process.inspector.internal.helper.AnalysisPathHelper.getPathByStartElements; import static com.axonivy.utils.process.inspector.internal.helper.AnalysisPathHelper.replaceFirstElement; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; @@ -167,8 +170,7 @@ private ProcessElement findIntersectionTaskSwitchGateway(Map> mergePath(Map> source, ProcessElement intersection, List subPath) { - Map> pathBeforeIntersection = getPathBeforeIntersection(source, - intersection); + Map> pathBeforeIntersection = getAnalysisPathTo(source, intersection); Map> pathNotIntersection = source.entrySet().stream() .filter(entry -> !pathBeforeIntersection.keySet().contains(entry.getKey())).collect(toMap( @@ -234,14 +236,14 @@ private List convertToAnalysisPaths(Map startElements = intersectionEntry.getValue(); - var paths = getPathByStartElements(source, startElements); + Map> paths = getPathByStartElements(source, startElements); - var pathBeforeIntersection = getPathBeforeIntersection(paths, intersection); + Map> pathBeforeIntersection = getAnalysisPathTo(paths, intersection); // Call recursion inside convertToTaskParallelGroup TaskParallelGroup taskGroup = convertToTaskParallelGroup(pathBeforeIntersection); - List subPathAfterIntersection = getAnalysisPathFromIntersection(paths, intersection); + List subPathAfterIntersection = getAnalysisPathFrom(paths, intersection); result.addAll(addToPath(List.of(new AnalysisPath(List.of(taskGroup))), subPathAfterIntersection)); } @@ -250,87 +252,31 @@ private List convertToAnalysisPaths(Map> getPathHaveNoIntersection( - Map> source, Map> intersections) { - List startElementWithIntersection = intersections.values().stream().flatMap(Collection::stream) + Map> source, + Map> intersections) { + + List startElementWithIntersection = intersections.values().stream() + .flatMap(Collection::stream) .toList(); - return source.entrySet().stream().filter(entry -> !startElementWithIntersection.contains(entry.getKey())) - .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, - LinkedHashMap::new)); + return source.entrySet().stream() + .filter(entry -> !startElementWithIntersection.contains(entry.getKey())) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new)); } - private TaskParallelGroup convertToTaskParallelGroupWithInternalPath( - Map> internalPaths) { + private TaskParallelGroup convertToTaskParallelGroupWithInternalPath(Map> internalPaths) { TaskParallelGroup taskGroup = new TaskParallelGroup(null); - taskGroup.setInternalPaths(convertToInternalPathForTaskParallelGroup(internalPaths)); - return taskGroup; - } - - private Map> convertToInternalPathForTaskParallelGroup( - Map> internalPath) { + Map> result = new LinkedHashMap<>(); - internalPath.entrySet().forEach(it -> { - NodeElement element = (NodeElement) it.getKey().getElement(); - result.put(element.getIncoming().get(0), it.getValue()); - }); - return result; - } - - private List getAnalysisPathFromIntersection(Map> source, - ProcessElement intersection) { - Set result = new HashSet<>(); - List paths = source.values().stream().flatMap(Collection::stream).toList(); - for (AnalysisPath path : paths) { - List elements = path.getElements(); - int index = elements.indexOf(intersection); - if (index >= 0) { - List beforeIntersection = elements.subList(index, elements.size() - 1); - result.add(new AnalysisPath(beforeIntersection)); - } - } - - return new ArrayList<>(result); - } - - private Map> getPathByStartElements( - Map> source, Set elements) { - Map> result = new LinkedHashMap<>(); - - elements.forEach(key -> { - List paths = source.get(key); - if (isNotEmpty(paths)) { - result.put(key, paths); - } + internalPaths.entrySet().forEach(it -> { + SequenceFlow sequenceFlow = processGraph.getFirstIncoming(it.getKey().getElement()); + result.put(sequenceFlow, it.getValue()); }); - - return result; - } - - private Map> getPathBeforeIntersection( - Map> paths, ProcessElement intersection) { - Map> pathBeforeIntersection = new LinkedHashMap<>(); - for (Entry> entry : paths.entrySet()) { - List beforeIntersections = getAnalysisPathBeforeIntersection(entry.getValue(), intersection); - if (isNotEmpty(beforeIntersections)) { - pathBeforeIntersection.put(entry.getKey(), beforeIntersections); - } - } - - return pathBeforeIntersection; + + taskGroup.setInternalPaths(result); + return taskGroup; } - private List getAnalysisPathBeforeIntersection(List paths, - ProcessElement intersection) { - List result = new ArrayList<>(); - for (AnalysisPath path : paths) { - int index = path.getElements().indexOf(intersection); - if (index >= 0) { - List beforeIntersection = path.getElements().subList(0, index); - result.add(new AnalysisPath(beforeIntersection)); - } - } - return result; - } private Map> getLastIntersectionByStartElements(Map> paths) { var intersections = getAllIntersectionTaskSwitchGatewayWithStartElement(paths); diff --git a/process-inspector/src/com/axonivy/utils/process/inspector/internal/ProcessGraph.java b/process-inspector/src/com/axonivy/utils/process/inspector/internal/ProcessGraph.java index ccbca43..4086640 100644 --- a/process-inspector/src/com/axonivy/utils/process/inspector/internal/ProcessGraph.java +++ b/process-inspector/src/com/axonivy/utils/process/inspector/internal/ProcessGraph.java @@ -186,6 +186,13 @@ public String getAlternativeNameId(BaseElement alternative) { .collect(Collectors.joining("-")); } + public SequenceFlow getFirstIncoming(BaseElement element) { + if(element instanceof NodeElement) { + return ((NodeElement) element).getIncoming().stream().findFirst().orElse(null); + } + return null; + } + private boolean containPrefixs(String content, String... prefix) { return List.of(prefix).stream().allMatch(it -> content.contains(it)); } diff --git a/process-inspector/src/com/axonivy/utils/process/inspector/internal/WorkflowPath.java b/process-inspector/src/com/axonivy/utils/process/inspector/internal/WorkflowPath.java index db0197c..12554b0 100644 --- a/process-inspector/src/com/axonivy/utils/process/inspector/internal/WorkflowPath.java +++ b/process-inspector/src/com/axonivy/utils/process/inspector/internal/WorkflowPath.java @@ -97,7 +97,7 @@ protected List convertToDetectedElements(Map convertPathToDetectedElements(ProcessElement start // It is EmbeddedProcessElement if (element instanceof SubProcessGroup) { - List internalPaths = ((SubProcessGroup) element).getInternalPaths(); - List subPaths = getAnalysisPathBaseOnNextSequenceFlow(internalPaths, nextElement.getElement()); + List subPaths = ((SubProcessGroup) element).getInternalPaths(); + //List subPaths = getAnalysisPathBaseOnNextSequenceFlow(internalPaths, nextElement.getElement()); List allTaskFromSubPath = new ArrayList<>(); for(AnalysisPath subPath : subPaths) { ProcessElement startSubElement = subPath.getElements().get(0); diff --git a/process-inspector/src/com/axonivy/utils/process/inspector/internal/helper/AnalysisPathHelper.java b/process-inspector/src/com/axonivy/utils/process/inspector/internal/helper/AnalysisPathHelper.java index 5364248..afeecdb 100644 --- a/process-inspector/src/com/axonivy/utils/process/inspector/internal/helper/AnalysisPathHelper.java +++ b/process-inspector/src/com/axonivy/utils/process/inspector/internal/helper/AnalysisPathHelper.java @@ -4,9 +4,13 @@ import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.apache.commons.collections4.ListUtils; @@ -47,7 +51,8 @@ public static List addAllToPath(List paths, List addAllToPath(List paths, Map> pathOptions) { + public static List addAllToPath(List paths, + Map> pathOptions) { List result = new ArrayList<>(); if (pathOptions.isEmpty()) { result.addAll(paths); @@ -68,7 +73,6 @@ public static List addAllToPath(List paths, Map replaceFirstElement(ProcessElement element, List subPaths) { if (subPaths.isEmpty()) { @@ -84,82 +88,124 @@ public static List replaceFirstElement(ProcessElement element, Lis return result; } - + public static int getLastIndex(AnalysisPath path) { List elements = path.getElements(); return elements.size() == 0 ? 0 : elements.size() - 1; } - + public static ProcessElement getLastElement(AnalysisPath path) { List elements = path.getElements(); int size = elements.size(); return size == 0 ? null : elements.get(size - 1); } - + public static NodeElement getFirstNodeElement(List paths) { - NodeElement startNode = AnalysisPathHelper.getAllProcessElement(paths).stream() - .map(ProcessElement::getElement) - .filter(NodeElement.class::isInstance) - .findFirst() - .map(NodeElement.class::cast) - .orElse(null); + NodeElement startNode = AnalysisPathHelper.getAllProcessElement(paths).stream().map(ProcessElement::getElement) + .filter(NodeElement.class::isInstance).findFirst().map(NodeElement.class::cast).orElse(null); return startNode; } - - public static List removeLastElementByClassType(List paths , Class clazz) { + + public static List removeLastElementByClassType(List paths, Class clazz) { List result = new ArrayList<>(); for (AnalysisPath path : paths) { int lastIndex = AnalysisPathHelper.getLastIndex(path); List pathElements = new ArrayList<>(path.getElements()); ProcessElement lastElement = pathElements.get(lastIndex); - + if (lastElement instanceof CommonElement && clazz.isInstance(lastElement.getElement())) { pathElements.remove(lastIndex); } - + result.add(new AnalysisPath(pathElements)); } return result; } - + public static List getAllProcessElement(List paths) { - List elements = paths.stream() - .map(AnalysisPath::getElements) - .flatMap(List::stream) - .flatMap(it -> getAllProcessElement(it).stream()) - .toList(); + List elements = paths.stream().map(AnalysisPath::getElements).flatMap(List::stream) + .flatMap(it -> getAllProcessElement(it).stream()).toList(); return elements; } - + public static List getAllProcessElement(ProcessElement element) { - if(element instanceof CommonElement) { + if (element instanceof CommonElement) { return List.of(element); } - - if(element instanceof TaskParallelGroup) { + + if (element instanceof TaskParallelGroup) { List result = new ArrayList<>(); - + TaskParallelGroup group = (TaskParallelGroup) element; - if(group.getElement() != null) { + if (group.getElement() != null) { result.add(new CommonElement(group.getElement())); } - - for(Entry> entry : group.getInternalPaths().entrySet()) { - List allProcessElement = entry.getValue().stream() - .map(AnalysisPath::getElements) - .flatMap(List::stream) - .flatMap(it -> getAllProcessElement(it).stream()) - .toList(); - - result.add(new CommonElement(entry.getKey())); + + for (Entry> entry : group.getInternalPaths().entrySet()) { + List allProcessElement = entry.getValue().stream().map(AnalysisPath::getElements) + .flatMap(List::stream).flatMap(it -> getAllProcessElement(it).stream()).toList(); + + result.add(new CommonElement(entry.getKey())); result.addAll(allProcessElement); } - + return result; } - + return emptyList(); } + + public static > Map getPathByStartElements(Map source, Set keys) { + Map result = new LinkedHashMap<>(); + keys.forEach(key -> { + V paths = source.get(key); + if (isNotEmpty(paths)) { + result.put(key, paths); + } + }); + return result; + } + + public static List getAnalysisPathFrom(Map> source, ProcessElement from) { + Set result = new HashSet<>(); + List paths = source.values().stream().flatMap(Collection::stream).toList(); + + for (AnalysisPath path : paths) { + List elements = path.getElements(); + int index = elements.indexOf(from); + if (index >= 0) { + List afterFrom = elements.subList(index, elements.size() - 1); + result.add(new AnalysisPath(afterFrom)); + } + } + + return new ArrayList<>(result); + + } + + public static Map> getAnalysisPathTo(Map> source, ProcessElement to) { + Map> pathBeforeIntersection = new LinkedHashMap<>(); + for (Entry> entry : source.entrySet()) { + List beforeTo = getAnalysisPathTo(entry.getValue(), to); + if (isNotEmpty(beforeTo)) { + pathBeforeIntersection.put(entry.getKey(), beforeTo); + } + } + + return pathBeforeIntersection; + } + + private static List getAnalysisPathTo(List source, ProcessElement to) { + List result = new ArrayList<>(); + for (AnalysisPath path : source) { + int index = path.getElements().indexOf(to); + if (index >= 0) { + List beforeIntersection = path.getElements().subList(0, index); + result.add(new AnalysisPath(beforeIntersection)); + } + } + return result; + } }