// Path: src/main/java/com/sumologic/jenkins/jenkinssumologicplugin/constants/ParallelNodeTypeEnum.java
// public enum ParallelNodeTypeEnum {
//     NORMAL,
//     PARALLEL_START,
//     PARALLEL_END,
//     PARALLEL_BRANCH_START,
//     PARALLEL_BRANCH_END,
// }
// 
// Path: src/main/java/com/sumologic/jenkins/jenkinssumologicplugin/constants/SumoConstants.java
// public static final String JENKINS_MAIN = "(master)";


import com.cloudbees.workflow.rest.external.ChunkVisitor;
import com.sumologic.jenkins.jenkinssumologicplugin.constants.ParallelNodeTypeEnum;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.workflow.actions.WorkspaceAction;
import org.jenkinsci.plugins.workflow.cps.nodes.StepEndNode;
import org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import org.jenkinsci.plugins.workflow.graph.FlowStartNode;
import org.jenkinsci.plugins.workflow.graphanalysis.ForkScanner;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import static com.sumologic.jenkins.jenkinssumologicplugin.constants.SumoConstants.JENKINS_MAIN;
            findWhereCurrentNodeIsExecuting(atomNode);
            findParallelNode(scan, atomNode);
        } catch (Exception ex) {
            LOG.log(Level.WARNING, "failed to extract plugin extension info", ex);
        }
        super.atomNode(before, atomNode, after, scan);
    }

    private void findWhereCurrentNodeIsExecuting(FlowNode atomNode) {
        if (execNodeName == null) {
            StepStartNode nodeStep = getPipelineBlockBoundaryStartNode(atomNode);
            if (nodeStep != null) {
                WorkspaceAction workspaceAction = nodeStep.getPersistentAction(WorkspaceAction.class);
                if (workspaceAction != null) {
                    execNodeName = workspaceAction.getNode();
                    execNodeStartId = nodeStep.getId();
                    if (StringUtils.isEmpty(execNodeName)) {
                        execNodeName = JENKINS_MAIN;
                    }
                }
            }
        } else if (atomNode instanceof StepStartNode && atomNode.getId().equals(execNodeStartId)) {
            execNodeName = null;
        }
        if (execNodeName != null) {
            workspaceNodes.put(atomNode.getId(), execNodeName);
        }
    }

    private void findParallelNode(@Nonnull ForkScanner scan, FlowNode atomNode) {
// Path: src/main/java/com/sumologic/jenkins/jenkinssumologicplugin/constants/ParallelNodeTypeEnum.java
// public enum ParallelNodeTypeEnum {
//     NORMAL,
//     PARALLEL_START,
//     PARALLEL_END,
//     PARALLEL_BRANCH_START,
//     PARALLEL_BRANCH_END,
// }
// 
// Path: src/main/java/com/sumologic/jenkins/jenkinssumologicplugin/constants/SumoConstants.java
// public static final String JENKINS_MAIN = "(master)";


// Path: src/main/java/com/sumologic/jenkins/jenkinssumologicplugin/pipeline/ExecutionNodeExtractor.java
import com.cloudbees.workflow.rest.external.ChunkVisitor;
import com.sumologic.jenkins.jenkinssumologicplugin.constants.ParallelNodeTypeEnum;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.workflow.actions.WorkspaceAction;
import org.jenkinsci.plugins.workflow.cps.nodes.StepEndNode;
import org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import org.jenkinsci.plugins.workflow.graph.FlowStartNode;
import org.jenkinsci.plugins.workflow.graphanalysis.ForkScanner;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import static com.sumologic.jenkins.jenkinssumologicplugin.constants.SumoConstants.JENKINS_MAIN;

            findWhereCurrentNodeIsExecuting(atomNode);
            findParallelNode(scan, atomNode);
        } catch (Exception ex) {
            LOG.log(Level.WARNING, "failed to extract plugin extension info", ex);
        }
        super.atomNode(before, atomNode, after, scan);
    }

    private void findWhereCurrentNodeIsExecuting(FlowNode atomNode) {
        if (execNodeName == null) {
            StepStartNode nodeStep = getPipelineBlockBoundaryStartNode(atomNode);
            if (nodeStep != null) {
                WorkspaceAction workspaceAction = nodeStep.getPersistentAction(WorkspaceAction.class);
                if (workspaceAction != null) {
                    execNodeName = workspaceAction.getNode();
                    execNodeStartId = nodeStep.getId();
                    if (StringUtils.isEmpty(execNodeName)) {
                        execNodeName = JENKINS_MAIN;
                    }
                }
            }
        } else if (atomNode instanceof StepStartNode && atomNode.getId().equals(execNodeStartId)) {
            execNodeName = null;
        }
        if (execNodeName != null) {
            workspaceNodes.put(atomNode.getId(), execNodeName);
        }
    }

    private void findParallelNode(@Nonnull ForkScanner scan, FlowNode atomNode) {
        if (ParallelNodeTypeEnum.NORMAL.toString().equals(String.valueOf(scan.getCurrentType()))