Skip to content

Commit

Permalink
feat: refactored, still a work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
tomcarman committed Jul 2, 2024
1 parent 13710c5 commit 9d2dd12
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 48 deletions.
9 changes: 9 additions & 0 deletions src/common/experimental/FlowNodeWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class FlowNodeWrapper {
this.addWaitEventConnectors(node);
this.addRuleConnectors(node);
this.addScheduledPaths(node);
this.addTerminatorWhenMissingDefaultConnector(node);
}

private buildTerminators(): void {
Expand All @@ -50,6 +51,14 @@ export class FlowNodeWrapper {
this.connectors.push({ type: connectorType, ...connector, connectionLabel });
}

private addTerminatorWhenMissingDefaultConnector(node: AnyFlowNode): void {
if (this.type === 'decisions') {
if ('defaultConnectorLabel' in node && !('defaultConnector' in node)) {
this.addTerminator(node.defaultConnectorLabel);
}
}
}

private addStandardConnector(node: AnyFlowNode): void {
if ('connector' in node && node.connector) {
const connectionLabel = this.type === 'start' ? 'Run Immediately' : undefined;
Expand Down
159 changes: 112 additions & 47 deletions src/common/experimental/FlowWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,67 +30,132 @@ export function walk(flow: FlowWrapper): void {
}
}

export function getPaths(flow: FlowWrapper): void {
console.log('\nGetting paths for flow: ', flow.flowName);
export function getPaths(flow: FlowWrapper): string[][] {
const nodesMap: { [key: string]: FlowNodeWrapper } = {};
flow.nodes.forEach((node) => {
nodesMap[node.name] = node;
// console.log(node.name);
// console.log(node.connectors);
});
const paths: string[][] = [];
const visited: { [key: string]: number } = {};

const paths: Array<Array<[string, string?]>> = [];
const visitedConnections = new Set<string>();
function explore(currentNode: string, path: string[], visitedLoops: Set<string>): void {
if (visited[currentNode]) {
visited[currentNode]++;
} else {
visited[currentNode] = 1;
}

function explore(node: FlowNodeWrapper, path: Array<[string, string?]>): void {
console.log('\nExploring node: ', node.name);
console.log('(previously explored connections: ', visitedConnections, ')');
console.log('Current path: ', path);
const node = nodesMap[currentNode];
path.push(currentNode);

if (node.connectors.length === 0) {
console.log('Node has no connectors, adding to paths');
path.push([node.name]);
if (!node || node.connectors.length === 0) {
paths.push([...path]);
} else {
console.log('Looking for connectors...');

for (const connector of node.connectors) {
if (!visitedConnections.has(node.name + connector.targetReference)) {
console.log('Connector: ', connector);
console.log('Targets: ', connector.targetReference);
console.log('Adding to path: ', [node.name, connector.connectionLabel]);
path.push([node.name, connector.connectionLabel]);

if (connector.type === 'Terminator') {
console.log('Terminator found, adding to paths');
path.push(['END']);
paths.push([...path]);
} else {
if (connector.type === 'nextValueConnector') {
visitedConnections.add(node.name + connector.targetReference);
}
// visitedConnections.add(node.name+connector.type+connector.targetReference);
const targetNode = flow.nodes.find((x) => x.name === connector.targetReference);
if (targetNode) {
console.log('Found target node: ', targetNode.name);
explore(targetNode, path);
} else {
paths.push([...path]);
}
}
path.pop();
return;
}
let isTerminator = false;
for (const connector of node.connectors) {
if (connector.type === 'Terminator') {
paths.push([...path, `${connector.connectionLabel} Terminator`]);
isTerminator = true;
} else if (connector.type === 'nextValueConnector') {
if (!visitedLoops.has(currentNode)) {
visitedLoops.add(currentNode);
explore(connector.targetReference, path, visitedLoops);
visitedLoops.delete(currentNode);
}
} else if (!visited[connector.targetReference] || visited[connector.targetReference] < 2) {
explore(connector.targetReference, path, visitedLoops);
}
}

console.log('Backtracking...');
if (isTerminator && node.connectors.length === 0) {
paths.push([...path]);
}

path.pop();
}

explore(flow.nodes.find((x) => x.type === 'start') as FlowNodeWrapper, []);
if (visited[currentNode] > 1) {
visited[currentNode]--;
} else {
delete visited[currentNode];
}
} // End explore

explore('Start', [], new Set<string>());

return printPaths(paths);
}
// printPaths(paths);

function printPaths(paths: Array<Array<[string, string?]>>): void {
if (paths) {
console.log(paths);
}
return paths;
}

// function printPaths(paths: string[][]): void {
// if (paths) {
// console.log('All Paths: ', paths);
// }
// }

// export function getPaths(flow: FlowWrapper): void {
// console.log('\nGetting paths for flow: ', flow.flowName);

// const paths: Array<Array<[string, string?]>> = [];
// const visitedConnections = new Set<string>();

// function explore(node: FlowNodeWrapper, path: Array<[string, string?]>): void {
// console.log('\nExploring node: ', node.name);
// console.log('(previously explored connections: ', visitedConnections, ')');
// console.log('Current path: ', path);

// if (node.connectors.length === 0) {
// console.log('Node has no connectors, adding to paths');
// path.push([node.name]);
// paths.push([...path]);
// } else {
// console.log('Looking for connectors...');

// for (const connector of node.connectors) {
// if (!visitedConnections.has(node.name+connector.type+connector.targetReference)) {
// console.log('Connector: ', connector);
// console.log('Targets: ', connector.targetReference);
// console.log('Adding to path: ', [node.name, connector.connectionLabel]);
// path.push([node.name, connector.connectionLabel]);

// // if (connector.type === 'Terminator') {
// // console.log('Terminator found, adding to paths');
// // path.push(['END']);
// // paths.push([...path]);
// // } else {
// if (connector.type === 'nextValueConnector') {
// visitedConnections.add(node.name+connector.type+connector.targetReference);
// }
// const targetNode = flow.nodes.find((x) => x.name === connector.targetReference);
// if (targetNode) {
// console.log('Found target node: ', targetNode.name);
// explore(targetNode, path);
// } else {
// paths.push([...path]);
// }
// }
// }
// }
// console.log('Backtracking...');
// path.pop();
// }

// explore(flow.nodes.find((x) => x.type === 'start') as FlowNodeWrapper, []);

// return printPaths(paths);

// }

// function printPaths(paths: Array<Array<[string, string?]>>): void {
// if (paths) {
// console.log('All Paths: ', paths);
// }
// }

function printNode(node: FlowNodeWrapper): void {
console.log('\n\n--- NODE ---');
console.log('Name: ', node.name);
Expand Down
5 changes: 4 additions & 1 deletion src/rules/no-dml-in-flow-for-loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ export default class NoDmlInFlowForLoop extends RuleClass {
const flowWrapper = new FlowWrapper(flow);

// walk(flowWrapper);
getPaths(flowWrapper);
// console.log(JSON.stringify(flowWrapper, null, 2));
const paths = getPaths(flowWrapper);
console.log('Flow: ', flow.label);
console.log('Paths: ', paths);
}
}
}

0 comments on commit 9d2dd12

Please sign in to comment.