From 2c37fb86fbb81e1bcd7e10dab9636d5718037793 Mon Sep 17 00:00:00 2001 From: Hadrien Kohl Date: Thu, 29 Aug 2024 14:43:49 +0200 Subject: [PATCH] Refactor --- .../fr/insee/vtl/prov/ProvenanceUtils.java | 42 ++++----- .../main/java/fr/insee/vtl/prov/Variable.java | 88 +++++++++++++++++++ .../insee/vtl/prov/VariableGraphListener.java | 88 ++----------------- .../vtl/prov/VariableGraphListenerTest.java | 34 +++---- 4 files changed, 135 insertions(+), 117 deletions(-) create mode 100644 vtl-prov/src/main/java/fr/insee/vtl/prov/Variable.java diff --git a/vtl-prov/src/main/java/fr/insee/vtl/prov/ProvenanceUtils.java b/vtl-prov/src/main/java/fr/insee/vtl/prov/ProvenanceUtils.java index 37cd67fb3..80651142c 100644 --- a/vtl-prov/src/main/java/fr/insee/vtl/prov/ProvenanceUtils.java +++ b/vtl-prov/src/main/java/fr/insee/vtl/prov/ProvenanceUtils.java @@ -12,25 +12,25 @@ public class ProvenanceUtils { - public static List toBusinessModel(ProvenanceListener listener) { - // TODO: @nico te graph needs to be refactored. I'll try to fix it before monday. - - ArrayList model = new ArrayList<>(); - LinkedHashMap variables = listener.variables; - variables.values().forEach(node -> { - String name = node.name; - Map parents = node.parents; - VTLDataset vtlDataset = new VTLDataset(name); - model.add(vtlDataset); - }); - return model; - } - - public static void toJSON(ProvenanceListener.Node node) { - - } - - public static void toRDF(ProvenanceListener.Node node) { - - } + //public static List toBusinessModel(ProvenanceListener listener) { + // // TODO: @nico te graph needs to be refactored. I'll try to fix it before monday. + // + // ArrayList model = new ArrayList<>(); + // LinkedHashMap variables = listener.variables; + // variables.values().forEach(node -> { + // String name = node.name; + // Map parents = node.parents; + // VTLDataset vtlDataset = new VTLDataset(name); + // model.add(vtlDataset); + // }); + // return model; + //} +// + //public static void toJSON(ProvenanceListener.Node node) { +// + //} +// + //public static void toRDF(ProvenanceListener.Node node) { +// + //} } diff --git a/vtl-prov/src/main/java/fr/insee/vtl/prov/Variable.java b/vtl-prov/src/main/java/fr/insee/vtl/prov/Variable.java new file mode 100644 index 000000000..64ab45538 --- /dev/null +++ b/vtl-prov/src/main/java/fr/insee/vtl/prov/Variable.java @@ -0,0 +1,88 @@ +package fr.insee.vtl.prov; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.misc.Interval; + +import java.util.Optional; + +public class Variable { + + /** + * Returns the text of a context with empty space (aka. all channels). + */ + private static String getText(ParserRuleContext ctx) { + Token start = ctx.getStart(); + Token stop = ctx.getStop(); + return start.getInputStream().getText(new Interval(start.getStartIndex(), stop.getStopIndex())); + } + + // Identifier of the variable. + private final ParserRuleContext nameCtx; + + // Expression of the variable, if any. + private final ParserRuleContext exprCtx; + + // Version of the variable. + private Integer version = 0; + + // Previous version. + private Variable previous; + + Variable(ParserRuleContext name, ParserRuleContext expression) { + this.nameCtx = name; + this.exprCtx = expression; + } + + public Variable(ParserRuleContext name) { + this.nameCtx = name; + this.exprCtx = null; + } + + public String getName() { + return getText(this.nameCtx); + } + + public String getVersion() { + return getName() + "_" + this.version; + } + + public Optional getExpression() { + return Optional.ofNullable(exprCtx) + .map(Variable::getText); + } + + public Optional getPrevious() { + return Optional.ofNullable(previous); + } + + public Variable newVersion() { + Variable copy = new Variable(this.nameCtx, this.exprCtx); + copy.version = this.version + 1; + copy.previous = this; + return copy; + } + + @Override + public String toString() { + return getVersion(); + } + + public final boolean isSame(Variable other) { + return nameCtx.equals(other.nameCtx); + } + + @Override + public final boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Variable)) return false; + + Variable variable = (Variable) o; + return getVersion().equals(variable.getVersion()); + } + + @Override + public int hashCode() { + return nameCtx.hashCode(); + } +} diff --git a/vtl-prov/src/main/java/fr/insee/vtl/prov/VariableGraphListener.java b/vtl-prov/src/main/java/fr/insee/vtl/prov/VariableGraphListener.java index 8fe97bf4f..3db4ddf23 100644 --- a/vtl-prov/src/main/java/fr/insee/vtl/prov/VariableGraphListener.java +++ b/vtl-prov/src/main/java/fr/insee/vtl/prov/VariableGraphListener.java @@ -3,14 +3,11 @@ import fr.insee.vtl.parser.VtlBaseListener; import fr.insee.vtl.parser.VtlParser; import org.antlr.v4.runtime.ParserRuleContext; -import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.misc.Interval; import org.jgrapht.graph.DefaultDirectedGraph; import org.jgrapht.graph.DefaultEdge; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -19,82 +16,15 @@ */ public class VariableGraphListener extends VtlBaseListener { - /** - * Returns the text of a context with empty space (aka. all channels). - */ - private static String getText(ParserRuleContext ctx) { - Token start = ctx.getStart(); - Token stop = ctx.getStop(); - return start.getInputStream().getText(new Interval(start.getStartIndex(), stop.getStopIndex())); - } - - private static class Variable { - private final ParserRuleContext name; - private final ParserRuleContext expression; - private Integer version = 0; - - private Variable(ParserRuleContext name, ParserRuleContext expression) { - this.name = name; - this.expression = expression; - } - - public Variable(ParserRuleContext name) { - this.name = name; - this.expression = null; - } - - public String getName() { - return getText(this.name); - } - - public String getVersion() { - return getName() + "_" + this.version; - } - - public Optional getExpression() { - return Optional.ofNullable(expression) - .map(VariableGraphListener::getText); - } - - public Variable newVersion() { - Variable copy = new Variable(this.name, this.expression); - copy.version = this.version + 1; - return copy; - } - - @Override - public String toString() { - return "Variable{" + - "name=" + getName() + - "(_" + version + ")" + - ", expression=" + getExpression() + - '}'; - } - - @Override - public final boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Variable)) return false; - - Variable variable = (Variable) o; - return name.equals(variable.name); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - } - private Variable current; private final Map seen = new LinkedHashMap<>(); - private final DefaultDirectedGraph graph = new DefaultDirectedGraph<>(DefaultEdge.class); + private final DefaultDirectedGraph graph = new DefaultDirectedGraph<>(DefaultEdge.class); private void setCurrent(ParserRuleContext id, ParserRuleContext expression) { assert current == null; current = new Variable(id, expression); if (seen.containsKey(current.getName())) { - current = seen.get(current.getName()).newVersion(); + current = seen.get(current.getName()).newVersion(); } } @@ -126,12 +56,12 @@ public void exitPersistAssignment(VtlParser.PersistAssignmentContext ctx) { @Override public void enterVarID(VtlParser.VarIDContext ctx) { - assert current != null; + Variable newVariable = new Variable(ctx); // Ignore if token is the same. - if (newVariable.equals(current)) { + if (newVariable.isSame(current)) { return; } @@ -142,13 +72,13 @@ public void enterVarID(VtlParser.VarIDContext ctx) { seen.put(newVariable.getName(), newVariable); } - graph.addVertex(newVariable.getVersion()); - graph.addVertex(current.getVersion()); - graph.addEdge(newVariable.getVersion(), current.getVersion()); + graph.addVertex(newVariable); + graph.addVertex(current); + graph.addEdge(newVariable, current); } - public DefaultDirectedGraph getGraph() { + public DefaultDirectedGraph getGraph() { Set selfLoops = graph.edgeSet().stream() .filter(e -> graph.getEdgeSource(e).equals(graph.getEdgeTarget(e))) .collect(Collectors.toSet()); @@ -159,7 +89,7 @@ public DefaultDirectedGraph getGraph() { /** * Returns the last variables (sink vertex) of the graph. */ - public Set getVariables() { + public Set getVariables() { return graph.vertexSet().stream() .filter(v -> graph.outgoingEdgesOf(v).isEmpty()) .collect(Collectors.toSet()); diff --git a/vtl-prov/src/test/java/fr/insee/vtl/prov/VariableGraphListenerTest.java b/vtl-prov/src/test/java/fr/insee/vtl/prov/VariableGraphListenerTest.java index 918105e91..e0ac42500 100644 --- a/vtl-prov/src/test/java/fr/insee/vtl/prov/VariableGraphListenerTest.java +++ b/vtl-prov/src/test/java/fr/insee/vtl/prov/VariableGraphListenerTest.java @@ -33,10 +33,10 @@ void testComplexGraph() { VariableGraphListener provenanceListener = parseAndListen(expr); - assertThat(provenanceListener.getVariables()).containsExactly( + assertThat(provenanceListener.getVariables()).map(Variable::toString).containsExactlyInAnyOrder( "ds8" ); - DefaultDirectedGraph graph = provenanceListener.getGraph(); + DefaultDirectedGraph graph = provenanceListener.getGraph(); assertThat(graph.edgeSet()).map(DefaultEdge::toString).containsExactly( "(ds1_0 : ds2_0)", "(ds2_0 : ds3_0)", "(ds3_0 : ds4_0)", "(ds4_0 : ds5_0)" ); @@ -52,10 +52,10 @@ void testSimpleGraph() { VariableGraphListener provenanceListener = parseAndListen(expr); - assertThat(provenanceListener.getVariables()).containsExactly( + assertThat(provenanceListener.getVariables()).map(Variable::toString).containsExactlyInAnyOrder( "ds5_0" ); - DefaultDirectedGraph graph = provenanceListener.getGraph(); + DefaultDirectedGraph graph = provenanceListener.getGraph(); assertThat(graph.edgeSet()).map(DefaultEdge::toString).containsExactly( "(ds1_0 : ds2_0)", "(ds2_0 : ds3_0)", "(ds3_0 : ds4_0)", "(ds4_0 : ds5_0)" ); @@ -68,10 +68,10 @@ void testComposition() { VariableGraphListener provenanceListener = parseAndListen(expr); - assertThat(provenanceListener.getVariables()).containsExactly( + assertThat(provenanceListener.getVariables()).map(Variable::toString).containsExactlyInAnyOrder( "ds3_0" ); - DefaultDirectedGraph graph = provenanceListener.getGraph(); + DefaultDirectedGraph graph = provenanceListener.getGraph(); assertThat(graph.edgeSet()).map(DefaultEdge::toString).containsExactly( "(ds1_0 : ds2_0)", "(ds2_0 : ds3_0)" ); @@ -84,10 +84,10 @@ void testArithmeticGraph() { VariableGraphListener provenanceListener = parseAndListen(expr); - assertThat(provenanceListener.getVariables()).containsExactly( + assertThat(provenanceListener.getVariables()).map(Variable::toString).containsExactlyInAnyOrder( "ds3_0" ); - DefaultDirectedGraph graph = provenanceListener.getGraph(); + DefaultDirectedGraph graph = provenanceListener.getGraph(); assertThat(graph.edgeSet()).map(DefaultEdge::toString).containsExactly( "(ds1_0 : ds2_0)", "(ds2_0 : ds3_0)", "(ds1_0 : ds3_0)" ); @@ -100,10 +100,10 @@ void testTwoGraphs() { VariableGraphListener provenanceListener = parseAndListen(expr); - assertThat(provenanceListener.getVariables()).containsExactly( + assertThat(provenanceListener.getVariables()).map(Variable::toString).containsExactlyInAnyOrder( "ds3_0", "ds6_0" ); - DefaultDirectedGraph graph = provenanceListener.getGraph(); + DefaultDirectedGraph graph = provenanceListener.getGraph(); assertThat(graph.edgeSet()).map(DefaultEdge::toString).containsExactly( "(ds2_0 : ds3_0)", "(ds1_0 : ds3_0)", "(ds5_0 : ds6_0)", "(ds4_0 : ds6_0)" ); @@ -116,10 +116,10 @@ void testTwoConnectedGraphs() { VariableGraphListener provenanceListener = parseAndListen(expr); - assertThat(provenanceListener.getVariables()).containsExactly( + assertThat(provenanceListener.getVariables()).map(Variable::toString).containsExactlyInAnyOrder( "ds5_0", "ds3_0" ); - DefaultDirectedGraph graph = provenanceListener.getGraph(); + DefaultDirectedGraph graph = provenanceListener.getGraph(); assertThat(graph.edgeSet()).map(DefaultEdge::toString).containsExactly( "(ds2_0 : ds3_0)", "(ds1_0 : ds3_0)", "(ds4_0 : ds5_0)", "(ds1_0 : ds5_0)" ); @@ -135,16 +135,16 @@ void testCyclicGraphs() { "ds1 := ds2 * ds1;"; VariableGraphListener provenanceListener = parseAndListen(expr); - assertThat(provenanceListener.getVariables()).containsExactly( + assertThat(provenanceListener.getVariables()).map(Variable::toString).containsExactlyInAnyOrder( "ds1_2" ); - DefaultDirectedGraph graph = provenanceListener.getGraph(); + DefaultDirectedGraph graph = provenanceListener.getGraph(); assertThat(graph.edgeSet()).map(DefaultEdge::toString).containsExactly( "(ds0_0 : ds1_0)", "(ds1_0 : ds1_1)", "(ds1_1 : ds1_2)", "(ds2_0 : ds1_2)" ); } - public static void printTree(Graph graph, String currentNode, String prefix, boolean isLast) { + public static void printTree(Graph graph, Variable currentNode, String prefix, boolean isLast) { if (currentNode == null || !graph.containsVertex(currentNode)) { return; } @@ -159,13 +159,13 @@ public static void printTree(Graph graph, String currentNod // Recursively print each child node for (DefaultEdge edge : outgoingEdges) { - String targetNode = graph.getEdgeSource(edge); + Variable targetNode = graph.getEdgeSource(edge); printTree(graph, targetNode, prefix + (isLast ? " " : "│ "), ++index == count); } } private static void printTrees(VariableGraphListener provenanceListener) { - for (String variable : provenanceListener.getVariables()) { + for (Variable variable : provenanceListener.getVariables()) { printTree(provenanceListener.getGraph(), variable, "", false); } }