Skip to content

Commit

Permalink
Large refactoring to simplify visitor behaviour for export functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
avishek-sen-gupta committed Aug 24, 2024
1 parent c0ca712 commit 0ee387f
Show file tree
Hide file tree
Showing 16 changed files with 278 additions and 142 deletions.
6 changes: 4 additions & 2 deletions scripts/aws-carddemo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ myArray=("CBACT01C.cbl" "CBACT04C.cbl" "CBTRN03C.cbl" "CBACT03C.cbl" "CBSTM03B.C
# "CSUTLDTC.cbl"
# "CBSTM03A.CBL" POINTER data type needs to be accomodated while building data structures
for str in ${myArray[@]}; do
# source config-local/local.env.sh && java -jar smojol-cli/target/smojol-cli.jar run $str --commands="BUILD_PROGRAM_DEPENDENCIES" --srcDir /Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cbl --copyBooksDir "/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy,/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy-bms" --dialectJarPath che-che4z-lsp-for-cobol-integration/server/dialect-idms/target/dialect-idms.jar --dialect COBOL --reportDir out --generation=PARAGRAPH
# source config-local/local.env.sh && java -jar smojol-cli/target/smojol-cli.jar run $str --commands="EXPORT_TO_GRAPHML WRITE_FLOW_AST WRITE_CFG WRITE_DATA_STRUCTURES EXPORT_UNIFIED_TO_JSON" --srcDir /Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cbl --copyBooksDir "/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy,/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy-bms" --dialectJarPath che-che4z-lsp-for-cobol-integration/server/dialect-idms/target/dialect-idms.jar --dialect COBOL --reportDir out --generation=PARAGRAPH

source config-local/local.env.sh && java -jar smojol-cli/target/smojol-cli.jar dependency $str --srcDir /Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cbl --copyBooksDir "/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy,/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy-bms" --dialectJarPath che-che4z-lsp-for-cobol-integration/server/dialect-idms/target/dialect-idms.jar --dialect COBOL --neo4j --permissiveSearch
source config-local/local.env.sh && java -jar smojol-cli/target/smojol-cli.jar run $str --commands="INJECT_INTO_NEO4J" --srcDir /Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cbl --copyBooksDir "/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy,/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy-bms" --dialectJarPath che-che4z-lsp-for-cobol-integration/server/dialect-idms/target/dialect-idms.jar --dialect COBOL --reportDir out --generation=PARAGRAPH

# source config-local/local.env.sh && java -jar smojol-cli/target/smojol-cli.jar dependency $str --srcDir /Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cbl --copyBooksDir "/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy,/Users/asgupta/code/aws-mainframe-modernization-carddemo/app/cpy-bms" --dialectJarPath che-che4z-lsp-for-cobol-integration/server/dialect-idms/target/dialect-idms.jar --dialect COBOL --neo4j --permissiveSearch
done
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.smojol.common.ast;

public class BytecodeGeneratorVisitor extends FlowNodeASTVisitor<FlowNode> {
public BytecodeGeneratorVisitor(FlowNode ancestor) {
super(ancestor);
}

@Override
public FlowNodeASTVisitor<FlowNode> visit(FlowNode node) {
return this;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package org.smojol.common.ast;

public abstract class FlowNodeASTVisitor<T> {
protected final T ancestor;

public interface FlowNodeASTVisitor<T> {
T visit(FlowNode node, T parent);
T root();
public FlowNodeASTVisitor(T ancestor) {
this.ancestor = ancestor;
}

public abstract FlowNodeASTVisitor<T> visit(FlowNode node);
public T root() {
return ancestor;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package org.smojol.common.ast;


public class SerialisableFlowNodeASTVisitor implements FlowNodeASTVisitor<SerialisableASTFlowNode> {
SerialisableASTFlowNode root = new SerialisableASTFlowNode();
@Override
public SerialisableASTFlowNode visit(FlowNode node, SerialisableASTFlowNode parent) {
SerialisableASTFlowNode child = new SerialisableASTFlowNode(node);
parent.addChild(child);
return child;
public class SerialisableFlowNodeASTVisitor extends FlowNodeASTVisitor<SerialisableASTFlowNode> {
public SerialisableFlowNodeASTVisitor(SerialisableASTFlowNode ancestorNode) {
super(ancestorNode);
}

public SerialisableFlowNodeASTVisitor() {
this(null);
}

@Override
public SerialisableASTFlowNode root() {
return root;
public FlowNodeASTVisitor<SerialisableASTFlowNode> visit(FlowNode node) {
SerialisableASTFlowNode child = new SerialisableASTFlowNode(node);
if (ancestor == null) return new SerialisableFlowNodeASTVisitor(child);
ancestor.addChild(child);
return new SerialisableFlowNodeASTVisitor(child);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.smojol.toolkit.analysis.graph.graphml;

import org.smojol.common.ast.FlowNode;
import org.smojol.common.ast.FlowNodeASTVisitor;
import org.smojol.toolkit.analysis.graph.jgrapht.JGraphTCodeOperations;

import static com.mojo.woof.NodeRelations.CONTAINS_CODE;

public class JGraphTASTGraphBuilderVisitor extends FlowNodeASTVisitor<FlowNode> {
private final JGraphTCodeOperations astGraphOperations;

public JGraphTASTGraphBuilderVisitor(JGraphTCodeOperations astGraphOperations, FlowNode ancestor) {
super(ancestor);
this.astGraphOperations = astGraphOperations;
}

public JGraphTASTGraphBuilderVisitor(JGraphTCodeOperations astGraphOperations) {
this(astGraphOperations, null);
}

@Override
public FlowNodeASTVisitor<FlowNode> visit(FlowNode node) {
astGraphOperations.addNode(node);
if (ancestor == null) return new JGraphTASTGraphBuilderVisitor(astGraphOperations, node);
astGraphOperations.connect(ancestor, node, CONTAINS_CODE);
return new JGraphTASTGraphBuilderVisitor(astGraphOperations, node);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.smojol.toolkit.analysis.graph.graphml;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.smojol.common.ast.FlowNode;
import org.smojol.common.ast.FlowNodeASTVisitor;
import org.smojol.common.vm.structure.CobolDataStructure;
import org.smojol.toolkit.analysis.graph.DataDependencyPairComputer;
import org.smojol.toolkit.analysis.graph.jgrapht.JGraphTDataOperations;

import java.util.List;
import java.util.Map;

import static com.mojo.woof.NodeRelations.*;
import static com.mojo.woof.NodeRelations.FLOWS_INTO;

public class JGraphTDataDependencyBuilderVisitor extends FlowNodeASTVisitor<CobolDataStructure> {
private final JGraphTDataOperations dataGraphOperations;
private final CobolDataStructure dataRoot;

public JGraphTDataDependencyBuilderVisitor(JGraphTDataOperations jGraphTDataOperations, CobolDataStructure dataRoot) {
this(jGraphTDataOperations, dataRoot, null);
}

public JGraphTDataDependencyBuilderVisitor(JGraphTDataOperations jGraphTDataOperations, CobolDataStructure dataRoot, CobolDataStructure ancestor) {
super(ancestor);
this.dataGraphOperations = jGraphTDataOperations;
this.dataRoot = dataRoot;
}

@Override
public FlowNodeASTVisitor<CobolDataStructure> visit(FlowNode node) {
Map.Entry<List<CobolDataStructure>, List<CobolDataStructure>> pairs = DataDependencyPairComputer.dependencyPairs(node, dataRoot);
if (ImmutablePair.nullPair().equals(pairs)) return this;
if (pairs.getValue().isEmpty()) {
accesses(node, pairs.getKey());
return this;
}
connect(pairs.getKey(), pairs.getValue(), node);
return this;
}

private void accesses(FlowNode node, List<CobolDataStructure> accessedStructures) {
accessedStructures.forEach(s -> {
if (!dataGraphOperations.containsVertex(s)) dataGraphOperations.addNode(s);
dataGraphOperations.connect(node, s, ACCESSES);
});
}

private void connect(List<CobolDataStructure> froms, List<CobolDataStructure> tos, FlowNode node) {
tos.forEach(to -> {
dataGraphOperations.connect(node, to, MODIFIES);
froms.forEach(from -> {
if (!dataGraphOperations.containsVertex(from)) dataGraphOperations.addNode(from);
dataGraphOperations.connect(node, from, ACCESSES);
dataGraphOperations.connect(from, to, FLOWS_INTO);
});
});
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.smojol.toolkit.analysis.graph.graphml;

import lombok.Getter;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.jgrapht.Graph;
import org.jgrapht.alg.clique.BronKerboschCliqueFinder;
import org.jgrapht.alg.clustering.KSpanningTreeClustering;
Expand All @@ -12,7 +11,6 @@
import org.jgrapht.nio.AttributeType;
import org.jgrapht.nio.DefaultAttribute;
import org.jgrapht.nio.graphml.GraphMLExporter;
import org.smojol.toolkit.analysis.graph.DataDependencyPairComputer;
import org.smojol.toolkit.analysis.graph.NodeSpecBuilder;
import org.smojol.toolkit.analysis.graph.jgrapht.JGraphTDataOperations;
import org.smojol.toolkit.analysis.graph.jgrapht.JGraphTCodeOperations;
Expand Down Expand Up @@ -59,7 +57,9 @@ public JGraphTGraphBuilder(CobolDataStructure dataStructures, FlowNode procedure
}

public void buildAST() {
new FlowNodeASTTraversal<FlowNode>().build(astRoot, this::buildJGraphTNodes);
// new FlowNodeASTTraversal<FlowNode>().build(astRoot, this::buildJGraphTNodes);
JGraphTASTGraphBuilderVisitor jGraphTASTGraphBuilderVisitor = new JGraphTASTGraphBuilderVisitor(astGraphOperations);
new FlowNodeASTTraversal<FlowNode>().accept(astRoot, jGraphTASTGraphBuilderVisitor);
}

public void buildCFG() {
Expand All @@ -69,44 +69,8 @@ public void buildCFG() {
public void buildDataStructures() {
dataRoot.accept(new GraphMLDataStructureVisitor(dataStructuresGraph, qualifier), null, n -> false, dataRoot);
dataRoot.accept(new GraphMLRedefinitionVisitor(dataStructuresGraph, qualifier), null, n -> false, dataRoot);
new FlowNodeASTTraversal<Boolean>().build(astRoot, this::buildDataDependency);
}

public FlowNode buildJGraphTNodes(FlowNode node, FlowNode parent) {
astGraphOperations.addNode(node);
if (parent == null) return node;
astGraphOperations.connect(parent, node, CONTAINS_CODE);
return node;
}

public Boolean buildDataDependency(FlowNode node, Boolean parent) {
Map.Entry<List<CobolDataStructure>, List<CobolDataStructure>> pairs = DataDependencyPairComputer.dependencyPairs(node, dataRoot);
if (ImmutablePair.nullPair().equals(pairs)) return false;
if (pairs.getValue().isEmpty()) {
accesses(node, pairs.getKey());
return true;
}
connect(pairs.getKey(), pairs.getValue(), node);
return true;
}

private void accesses(FlowNode node, List<CobolDataStructure> accessedStructures) {
accessedStructures.forEach(s -> {
if (!dataGraphOperations.containsVertex(s)) dataGraphOperations.addNode(s);
dataGraphOperations.connect(node, s, ACCESSES);
});

}

private void connect(List<CobolDataStructure> froms, List<CobolDataStructure> tos, FlowNode node) {
tos.forEach(to -> {
dataGraphOperations.connect(node, to, MODIFIES);
froms.forEach(from -> {
if (!dataGraphOperations.containsVertex(from)) dataGraphOperations.addNode(from);
dataGraphOperations.connect(node, from, ACCESSES);
dataGraphOperations.connect(from, to, FLOWS_INTO);
});
});
// new FlowNodeASTTraversal<Boolean>().build(astRoot, this::buildDataDependency);
new FlowNodeASTTraversal<CobolDataStructure>().accept(astRoot, new JGraphTDataDependencyBuilderVisitor(dataGraphOperations, dataRoot));
}

private Attribute attr(String attribute) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.smojol.toolkit.analysis.graph.graphml;

import com.mojo.woof.GraphSDK;
import org.neo4j.driver.Record;
import org.smojol.common.ast.FlowNode;
import org.smojol.common.ast.FlowNodeASTVisitor;
import org.smojol.toolkit.analysis.graph.NodeSpecBuilder;
import org.smojol.toolkit.analysis.graph.neo4j.NodeReferenceStrategy;

public class Neo4JASTBuilderVisitor extends FlowNodeASTVisitor<Record> {
private final NodeReferenceStrategy astNodeReferenceStrategy;
private final GraphSDK graphSDK;
private final NodeSpecBuilder qualifier;

public Neo4JASTBuilderVisitor(NodeReferenceStrategy astNodeReferenceStrategy, GraphSDK graphSDK, NodeSpecBuilder qualifier, Record ancestorRecord) {
super(ancestorRecord);
this.astNodeReferenceStrategy = astNodeReferenceStrategy;
this.graphSDK = graphSDK;
this.qualifier = qualifier;
}

public Neo4JASTBuilderVisitor(NodeReferenceStrategy astNodeReferenceStrategy, GraphSDK sdk, NodeSpecBuilder qualifier) {
this(astNodeReferenceStrategy, sdk, qualifier, null);
}

@Override
public FlowNodeASTVisitor<Record> visit(FlowNode node) {
Record record = astNodeReferenceStrategy.reference(node, graphSDK, qualifier);
if (ancestor == null) return new Neo4JASTBuilderVisitor(astNodeReferenceStrategy, graphSDK, qualifier, record);
graphSDK.containsCodeNode(ancestor, record);
return new Neo4JASTBuilderVisitor(astNodeReferenceStrategy, graphSDK, qualifier, record);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.smojol.toolkit.analysis.graph.graphml;

import com.mojo.woof.GraphSDK;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.neo4j.driver.Record;
import org.smojol.common.ast.FlowNode;
import org.smojol.common.ast.FlowNodeASTVisitor;
import org.smojol.common.vm.structure.CobolDataStructure;
import org.smojol.toolkit.analysis.graph.DataDependencyPairComputer;
import org.smojol.toolkit.analysis.graph.NodeSpecBuilder;
import org.smojol.toolkit.analysis.graph.NodeToWoof;
import org.smojol.toolkit.analysis.graph.neo4j.NodeReferenceStrategy;

import java.util.List;
import java.util.Map;

public class Neo4JDataDependencyBuilderVisitor extends FlowNodeASTVisitor<Record> {

private final GraphSDK sdk;
private final NodeSpecBuilder qualifier;
private final NodeReferenceStrategy dependencyAttachmentStrategy;
private final CobolDataStructure dataRoot;

public Neo4JDataDependencyBuilderVisitor(CobolDataStructure dataRoot, GraphSDK graphSDK, NodeSpecBuilder qualifier, NodeReferenceStrategy dependencyAttachmentStrategy, Record ancestor) {
super(ancestor);
this.sdk = graphSDK;
this.qualifier = qualifier;
this.dependencyAttachmentStrategy = dependencyAttachmentStrategy;
this.dataRoot = dataRoot;
}

public Neo4JDataDependencyBuilderVisitor(CobolDataStructure dataRoot, GraphSDK sdk, NodeSpecBuilder qualifier, NodeReferenceStrategy dependencyAttachmentStrategy) {
this(dataRoot, sdk, qualifier, dependencyAttachmentStrategy, null);
}

@Override
public FlowNodeASTVisitor<Record> visit(FlowNode node) {
Map.Entry<List<CobolDataStructure>, List<CobolDataStructure>> pairs = DataDependencyPairComputer.dependencyPairs(node, dataRoot);
if (ImmutablePair.nullPair().equals(pairs)) return this;
if (pairs.getValue().isEmpty()) {
accesses(node, pairs.getKey());
return this;
}
connect(pairs.getKey(), pairs.getValue(), node);
return this;
}

private void accesses(FlowNode attachmentNode, List<CobolDataStructure> dataNodes) {
System.out.println("Attaching IF??? " + attachmentNode.type() + " " + dataNodes.size());
Record attachmentNodeRecord = dependencyAttachmentStrategy.reference(attachmentNode, sdk, qualifier);
dataNodes.forEach(n -> {
Record n4jFrom = sdk.newOrExisting(qualifier.dataNodeSearchSpec(n), NodeToWoof.dataStructureToWoof(n, qualifier));
sdk.accesses(attachmentNodeRecord, n4jFrom);
});
}

private void connect(List<CobolDataStructure> froms, List<CobolDataStructure> tos, FlowNode attachmentNode) {
Record attachmentNodeRecord = dependencyAttachmentStrategy.reference(attachmentNode, sdk, qualifier);
tos.forEach(to -> {
froms.forEach(f -> System.out.println(f.name()));
List<Record> nodes = sdk.findNodes(qualifier.dataNodeSearchSpec(to));
Record n4jTo = !nodes.isEmpty() ? nodes.getFirst() : sdk.createNode(NodeToWoof.dataStructureToWoof(to, qualifier));
sdk.modifies(attachmentNodeRecord, n4jTo);
froms.forEach(from -> {
Record n4jFrom = sdk.newOrExisting(qualifier.dataNodeSearchSpec(from), NodeToWoof.dataStructureToWoof(from, qualifier));
sdk.flowsInto(n4jFrom, n4jTo);
sdk.accesses(attachmentNodeRecord, n4jFrom);
});
});
}
}
Loading

0 comments on commit 0ee387f

Please sign in to comment.