Skip to content

Commit 8db9f57

Browse files
committed
Use a BufferedReader for importing line graphs
Closing the `BufferedReader` is conventionally handled by the function which opens it (unless otherwise noted), making the exception handling less error prone. Because streams do not handle `IOException`s it is necessary to wrap them in `UncheckedIOException`s and unpack them outside the stream. The Apache version `org.apache.commons.lang3.stream.Streams.FailableStream` would have been a great substitute, but it doesn't provide a `flatMap` method. Because a `BufferedReader` can't be read twice, a utility method `assertEqualToFile` is created which uses a new `BufferedReader` to parse line endings correctly and efficiently (instead of using `normalizedLineEndings` like the old `assertEqualFileContent` did).
1 parent a741399 commit 8db9f57

4 files changed

Lines changed: 64 additions & 40 deletions

File tree

src/main/java/org/variantsync/diffdetective/diff/difftree/serialize/LineGraphImport.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import org.variantsync.diffdetective.util.FileUtils;
66
import org.variantsync.functjonal.Pair;
77

8+
import java.io.BufferedReader;
9+
import java.io.IOException;
810
import java.nio.file.Files;
911
import java.nio.file.Path;
1012
import java.util.ArrayList;
@@ -20,20 +22,25 @@
2022
public class LineGraphImport {
2123
// public static Map<CodeType, Integer> countRootTypes = new HashMap<>();
2224

23-
public static List<DiffTree> fromFile(final Path path, final DiffTreeLineGraphImportOptions options) {
25+
/**
26+
* Transforms a line graph stored in a file into a list of {@link DiffTree DiffTrees}.
27+
*
28+
* @return All {@link DiffTree DiffTrees} contained in the line graph
29+
*/
30+
public static List<DiffTree> fromFile(final Path path, final DiffTreeLineGraphImportOptions options) throws IOException {
2431
Assert.assertTrue(Files.isRegularFile(path));
2532
Assert.assertTrue(FileUtils.isLineGraph(path));
26-
return fromLineGraph(FileUtils.readUTF8(path), options);
33+
try (BufferedReader input = Files.newBufferedReader(path)) {
34+
return fromLineGraph(input, options);
35+
}
2736
}
2837

2938
/**
3039
* Transforms a line graph into a list of {@link DiffTree DiffTrees}.
3140
*
3241
* @return All {@link DiffTree DiffTrees} contained in the line graph
3342
*/
34-
public static List<DiffTree> fromLineGraph(final String lineGraph, final DiffTreeLineGraphImportOptions options) {
35-
java.util.Scanner input = new java.util.Scanner(lineGraph);
36-
43+
public static List<DiffTree> fromLineGraph(final BufferedReader lineGraph, final DiffTreeLineGraphImportOptions options) throws IOException {
3744
// All DiffTrees read from the line graph
3845
List<DiffTree> diffTreeList = new ArrayList<>();
3946

@@ -48,8 +55,8 @@ public static List<DiffTree> fromLineGraph(final String lineGraph, final DiffTre
4855
String previousDiffTreeLine = "";
4956

5057
// Read the entire line graph
51-
while (input.hasNext()) {
52-
String ln = input.nextLine();
58+
String ln;
59+
while ((ln = lineGraph.readLine()) != null) {
5360
if (ln.startsWith(LineGraphConstants.LG_TREE_HEADER)) {
5461
// the line represents a DiffTree
5562

@@ -74,15 +81,9 @@ public static List<DiffTree> fromLineGraph(final String lineGraph, final DiffTre
7481

7582
} else if (ln.startsWith(LineGraphConstants.LG_EDGE)) {
7683
// the line represent a connection with two DiffNodes
77-
try {
78-
options.edgeFormat().connect(ln, diffNodes);
79-
} catch (IllegalArgumentException e) {
80-
input.close();
81-
throw e;
82-
}
84+
options.edgeFormat().connect(ln, diffNodes);
8385
} else if (!ln.isBlank()) {
8486
// ignore blank lines and throw an exception otherwise
85-
input.close();
8687
String errorMessage = String.format(
8788
"Line graph syntax error. Expects: \"%s\" (DiffTree), \"%s\" (DiffNode), \"%s\" (edge) or a blank space (delimiter). Faulty input: \"%s\".",
8889
LineGraphConstants.LG_TREE_HEADER,
@@ -92,7 +93,6 @@ public static List<DiffTree> fromLineGraph(final String lineGraph, final DiffTre
9293
throw new IllegalArgumentException(errorMessage);
9394
}
9495
}
95-
input.close();
9696

9797
if (!diffNodeList.isEmpty()) {
9898
DiffTree curDiffTree = parseDiffTree(previousDiffTreeLine, diffNodeList, options); // parse to DiffTree

src/main/java/org/variantsync/diffdetective/mining/postprocessing/MiningPostprocessing.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.variantsync.functjonal.Pair;
1515

1616
import java.io.IOException;
17+
import java.io.UncheckedIOException;
1718
import java.nio.file.Files;
1819
import java.nio.file.Path;
1920
import java.util.List;
@@ -85,10 +86,23 @@ public static void main(String[] args) throws IOException {
8586
*/
8687
public static List<DiffTree> parseFrequentSubgraphsIn(final Path path) throws IOException {
8788
if (Files.isDirectory(path)) {
88-
return Files.list(path)
89-
.filter(FileUtils::isLineGraph)
90-
.flatMap(file -> LineGraphImport.fromFile(file, IMPORT_OPTIONS).stream())
91-
.collect(Collectors.toList());
89+
try {
90+
return Files.list(path)
91+
.filter(FileUtils::isLineGraph)
92+
.flatMap(file -> {
93+
try {
94+
return LineGraphImport.fromFile(file, IMPORT_OPTIONS).stream();
95+
} catch (IOException e) {
96+
// Checked exceptions can't be propagated because {@code flatMap}
97+
// needs a {@code Function} which does not throw any checked
98+
// exceptions.
99+
throw new UncheckedIOException(e);
100+
}
101+
})
102+
.collect(Collectors.toList());
103+
} catch (UncheckedIOException e) {
104+
throw e.getCause();
105+
}
92106
} else {
93107
return LineGraphImport.fromFile(path, IMPORT_OPTIONS);
94108
}

src/test/java/LineGraphTest.java

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import org.variantsync.diffdetective.diff.difftree.serialize.treeformat.CommitDiffDiffTreeLabelFormat;
1010
import org.variantsync.diffdetective.util.FileUtils;
1111

12+
import java.io.BufferedReader;
1213
import java.io.IOException;
14+
import java.io.StringReader;
1315
import java.nio.file.Files;
1416
import java.nio.file.Path;
1517
import java.nio.file.Paths;
@@ -42,14 +44,16 @@ public static void init() throws IOException {
4244
* Test the import of a line graph.
4345
*/
4446
@Test
45-
public void idempotentReadWrite() {
47+
public void idempotentReadWrite() throws IOException {
4648
for (final Path testFile : TEST_FILES) {
4749
Logger.info("Testing {}", testFile);
48-
final String lineGraph = FileUtils.readUTF8(testFile);
49-
final List<DiffTree> diffTrees = LineGraphImport.fromLineGraph(lineGraph, IMPORT_OPTIONS);
50+
List<DiffTree> diffTrees;
51+
try (BufferedReader lineGraph = Files.newBufferedReader(testFile)) {
52+
diffTrees = LineGraphImport.fromLineGraph(lineGraph, IMPORT_OPTIONS);
53+
}
5054
assertConsistencyForAll(diffTrees);
5155
final String lineGraphResult = exportDiffTreeToLineGraph(diffTrees);
52-
assertEqualFileContent(lineGraph, lineGraphResult);
56+
TestUtils.assertEqualToFile(testFile, lineGraphResult);
5357
}
5458
}
5559

@@ -80,21 +84,4 @@ private static String exportDiffTreeToLineGraph(final List<DiffTree> treeList) {
8084
}
8185
return lineGraphOutput.toString();
8286
}
83-
84-
/**
85-
* Compare two line graphs.
86-
*
87-
* @param originalLineGraph The original line graph
88-
* @param generatedLineGraph The generated line graph
89-
*/
90-
private static void assertEqualFileContent(final String originalLineGraph, final String generatedLineGraph) {
91-
final String o = FileUtils.normalizedLineEndings(originalLineGraph);
92-
final String g = FileUtils.normalizedLineEndings(generatedLineGraph);
93-
// System.out.println("ORIGINAL");
94-
// System.out.println(o);
95-
// System.out.println("GENERATED");
96-
// System.out.println(g);
97-
assertEquals(o, g);
98-
}
99-
10087
}

src/test/java/TestUtils.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import org.apache.commons.io.IOUtils;
2+
import java.io.BufferedReader;
3+
import java.io.IOException;
4+
import java.io.StringReader;
5+
import java.nio.file.Files;
6+
import java.nio.file.Path;
7+
8+
import static org.junit.Assert.assertTrue;
9+
10+
public final class TestUtils {
11+
/**
12+
* Compare two line graphs.
13+
*
14+
* @param originalLineGraph The original line graph
15+
* @param generatedLineGraph The generated line graph
16+
*/
17+
public static void assertEqualToFile(final Path filePath, final String actual) throws IOException {
18+
try (BufferedReader expected = Files.newBufferedReader(filePath)) {
19+
assertTrue("expected content of " + filePath + " but was:<" + actual + ">",
20+
IOUtils.contentEqualsIgnoreEOL(expected, new StringReader(actual)));
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)