Skip to content

Commit 7e226c3

Browse files
authored
Merge pull request #754 from kusumotolab/refactor-output
Exporter周りのリファクタリング
2 parents 19ade57 + e17fd97 commit 7e226c3

31 files changed

+698
-1215
lines changed

build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ dependencies {
7070

7171
testImplementation 'org.assertj:assertj-core:3.10.0'
7272
testImplementation 'org.mockito:mockito-core:2.+'
73+
testImplementation 'com.google.jimfs:jimfs:1.1'
7374

7475
// Declare by "runtimeOnly" cuz hamcrest is necessary to execute junit-test dynamically,
7576
// but it doesn't seem to be loaded on compile task.

src/main/java/jp/kusumotolab/kgenprog/CUILauncher.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
import jp.kusumotolab.kgenprog.ga.validation.DefaultCodeValidation;
2121
import jp.kusumotolab.kgenprog.ga.validation.SourceCodeValidation;
2222
import jp.kusumotolab.kgenprog.ga.variant.Variant;
23-
import jp.kusumotolab.kgenprog.output.Exporter;
24-
import jp.kusumotolab.kgenprog.output.ExporterFactory;
23+
import jp.kusumotolab.kgenprog.output.Exporters;
2524
import jp.kusumotolab.kgenprog.project.test.LocalTestExecutor;
2625
import jp.kusumotolab.kgenprog.project.test.TestExecutor;
2726

@@ -61,10 +60,10 @@ public List<Variant> launch(final Configuration config) {
6160
final VariantSelection variantSelection = new DefaultVariantSelection(config.getHeadcount(),
6261
random);
6362
final TestExecutor testExecutor = new LocalTestExecutor(config);
64-
final Exporter exporter = ExporterFactory.create(config);
63+
final Exporters exporters = new Exporters(config);
6564
final KGenProgMain kGenProgMain =
6665
new KGenProgMain(config, faultLocalization, mutation, crossover, sourceCodeGeneration,
67-
sourceCodeValidation, variantSelection, testExecutor, exporter);
66+
sourceCodeValidation, variantSelection, testExecutor, exporters);
6867

6968
return kGenProgMain.run();
7069
}

src/main/java/jp/kusumotolab/kgenprog/Configuration.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ public SecondVariantSelectionStrategy.Strategy getSecondVariantSelectionStrategy
188188
return secondVariantSelectionStrategy;
189189
}
190190

191-
public boolean getHistoryRecord() {
191+
public boolean isHistoryRecord() {
192192
return historyRecord;
193193
}
194194

src/main/java/jp/kusumotolab/kgenprog/KGenProgMain.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import jp.kusumotolab.kgenprog.ga.validation.SourceCodeValidation;
1717
import jp.kusumotolab.kgenprog.ga.variant.Variant;
1818
import jp.kusumotolab.kgenprog.ga.variant.VariantStore;
19-
import jp.kusumotolab.kgenprog.output.Exporter;
19+
import jp.kusumotolab.kgenprog.output.Exporters;
2020
import jp.kusumotolab.kgenprog.project.jdt.JDTASTConstruction;
2121
import jp.kusumotolab.kgenprog.project.test.TestExecutor;
2222
import jp.kusumotolab.kgenprog.project.test.TestResult;
@@ -41,7 +41,7 @@ public class KGenProgMain {
4141
private final SourceCodeValidation sourceCodeValidation;
4242
private final VariantSelection variantSelection;
4343
private final TestExecutor testExecutor;
44-
private final Exporter exporter;
44+
private final Exporters exporters;
4545
private final JDTASTConstruction astConstruction;
4646

4747
/**
@@ -55,13 +55,13 @@ public class KGenProgMain {
5555
* @param sourceCodeValidation コード評価を行うインスタンス
5656
* @param variantSelection 個体の選択を行うインスタンス
5757
* @param testExecutor テスト実行を行うインスタンス
58-
* @param exporter 出力処理を行うインスタンス
58+
* @param exporters 出力処理を行うインスタンス
5959
*/
6060
public KGenProgMain(final Configuration config, final FaultLocalization faultLocalization,
6161
final Mutation mutation, final Crossover crossover,
6262
final SourceCodeGeneration sourceCodeGeneration,
6363
final SourceCodeValidation sourceCodeValidation, final VariantSelection variantSelection,
64-
final TestExecutor testExecutor, final Exporter exporter) {
64+
final TestExecutor testExecutor, final Exporters exporters) {
6565

6666
this.config = config;
6767
this.faultLocalization = faultLocalization;
@@ -72,7 +72,7 @@ public KGenProgMain(final Configuration config, final FaultLocalization faultLoc
7272
this.variantSelection = variantSelection;
7373
this.testExecutor = testExecutor;
7474
this.astConstruction = new JDTASTConstruction();
75-
this.exporter = exporter;
75+
this.exporters = exporters;
7676
}
7777

7878
/**
@@ -84,8 +84,6 @@ public KGenProgMain(final Configuration config, final FaultLocalization faultLoc
8484
public List<Variant> run() throws RuntimeException {
8585
logConfig();
8686

87-
// outDirを空にする
88-
exporter.clearPreviousResults();
8987
testExecutor.initialize();
9088

9189
final Strategies strategies = new Strategies(faultLocalization, astConstruction,
@@ -143,7 +141,7 @@ public List<Variant> run() throws RuntimeException {
143141
}
144142

145143
// 出力処理を行う
146-
exporter.export(variantStore);
144+
exporters.exportAll(variantStore);
147145

148146
stopwatch.unsplit();
149147
strategies.finish();

src/main/java/jp/kusumotolab/kgenprog/ga/variant/VariantStore.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ public VariantStore(final Configuration config, final Strategies strategies) {
4747

4848
variantCounter = new AtomicLong();
4949
generation = new OrdinalNumber(0);
50-
elementReplacer = newElementReplacer(config.getHistoryRecord());
50+
elementReplacer = newElementReplacer(config.isHistoryRecord());
5151
initialVariant = createInitialVariant();
5252
currentVariants = Collections.singletonList(initialVariant);
5353
allVariants = new LinkedList<>();
54-
variantRecorder = newVariantRecorder(config.getHistoryRecord());
54+
variantRecorder = newVariantRecorder(config.isHistoryRecord());
5555
variantRecorder.accept(initialVariant);
5656
generatedVariants = new ArrayList<>();
5757
foundSolutions = new ArrayList<>();
@@ -230,4 +230,7 @@ private Consumer<Variant> newVariantRecorder(final boolean historyRecord) {
230230
};
231231
}
232232

233+
public Configuration getConfiguration() {
234+
return config;
235+
}
233236
}
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,28 @@
11
package jp.kusumotolab.kgenprog.output;
22

33
import java.io.IOException;
4-
import java.nio.file.FileVisitOption;
4+
import java.io.UncheckedIOException;
55
import java.nio.file.Files;
66
import java.nio.file.Path;
7-
import java.util.Comparator;
8-
import java.util.List;
9-
import java.util.stream.Collectors;
10-
import org.slf4j.Logger;
11-
import org.slf4j.LoggerFactory;
12-
import jp.kusumotolab.kgenprog.Configuration;
137
import jp.kusumotolab.kgenprog.ga.variant.VariantStore;
148

159
/**
16-
* ログや外部ファイルへの出力処理を行うクラス
10+
* ログや外部ファイルへの出力処理を行うインタフェース
1711
*/
18-
public abstract class Exporter {
19-
20-
private static final Logger log = LoggerFactory.getLogger(Exporter.class);
21-
protected final Configuration config;
22-
23-
public Exporter(final Configuration config) {
24-
this.config = config;
25-
}
12+
interface Exporter {
2613

2714
/**
2815
* ログや外部ファイルへの出力を行う
2916
*/
30-
public abstract void export(final VariantStore variantStore);
31-
32-
/**
33-
* 以前の出力結果を削除する.
34-
*/
35-
public final void clearPreviousResults() throws RuntimeException {
36-
if (Files.notExists(config.getOutDir())) {
37-
return;
38-
}
39-
40-
try {
41-
final List<Path> subFiles = Files.walk(config.getOutDir(), FileVisitOption.FOLLOW_LINKS)
42-
.filter(e -> !e.equals(config.getOutDir()))
43-
.sorted(Comparator.reverseOrder())
44-
.collect(Collectors.toList());
45-
46-
for (final Path subFile : subFiles) {
47-
Files.deleteIfExists(subFile);
17+
void export(final VariantStore variantStore);
18+
19+
default void createDir(final Path outdir) {
20+
if (Files.notExists(outdir)) {
21+
try {
22+
Files.createDirectories(outdir);
23+
} catch (IOException e) {
24+
throw new UncheckedIOException(e); // couldn't handle this exception
4825
}
49-
} catch (final IOException e) {
50-
final String message = String.format("Cannot clear directory (%s)", config.getOutDir());
51-
log.error(message);
52-
throw new RuntimeException(message);
5326
}
5427
}
5528
}

src/main/java/jp/kusumotolab/kgenprog/output/ExporterFactory.java

-28
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,64 @@
11
package jp.kusumotolab.kgenprog.output;
22

3-
import java.util.List;
3+
import java.io.IOException;
4+
import java.io.UncheckedIOException;
5+
import java.nio.file.Files;
6+
import java.nio.file.Path;
7+
import java.util.Collections;
8+
import java.util.Comparator;
9+
import java.util.Set;
10+
import java.util.stream.Stream;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
413
import jp.kusumotolab.kgenprog.Configuration;
514
import jp.kusumotolab.kgenprog.ga.variant.VariantStore;
615

7-
public class Exporters extends Exporter {
16+
public class Exporters {
817

9-
private List<Exporter> exporters;
18+
private static final Logger log = LoggerFactory.getLogger(Exporters.class);
19+
private final Path outdir;
20+
private final Set<Exporter> exporterSet;
1021

11-
public Exporters(final Configuration config, final List<Exporter> exporters) {
12-
super(config);
13-
this.exporters = exporters;
22+
public Exporters(final Configuration config) {
23+
outdir = config.getOutDir();
24+
exporterSet = createExporterSet(config);
25+
clearPreviousResults();
1426
}
1527

16-
@Override
17-
public void export(final VariantStore variantStore) {
18-
exporters.forEach(e -> e.export(variantStore));
28+
private Set<Exporter> createExporterSet(final Configuration config) {
29+
if (config.needNotOutput()) {
30+
return Collections.emptySet();
31+
}
32+
if (config.isHistoryRecord()) {
33+
return Set.of(new PatchExporter(outdir), new JSONExporter(outdir));
34+
}
35+
return Set.of(new PatchExporter(outdir));
36+
}
37+
38+
public void exportAll(final VariantStore variantStore) {
39+
if (exporterSet.isEmpty()) {
40+
return; // do nothing when exporters are empty
41+
}
42+
this.exporterSet.forEach(e -> e.export(variantStore));
43+
}
44+
45+
private void clearPreviousResults() {
46+
if (Files.notExists(outdir)) {
47+
return;
48+
}
49+
50+
// delete outdir recursively
51+
try (final Stream<Path> walk = Files.walk(outdir)) {
52+
walk.sorted(Comparator.reverseOrder())
53+
.forEach(path -> {
54+
try {
55+
Files.delete(path);
56+
} catch (final IOException e) {
57+
log.warn(String.format("warn: cannot clear outdir %s", path));
58+
}
59+
});
60+
} catch (final IOException e) {
61+
throw new UncheckedIOException(e);
62+
}
1963
}
2064
}
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
package jp.kusumotolab.kgenprog.output;
22

3-
import java.io.IOException;
4-
import java.nio.file.Files;
5-
import java.nio.file.Path;
63
import java.util.List;
7-
import org.slf4j.Logger;
8-
import org.slf4j.LoggerFactory;
4+
import java.util.stream.Collectors;
95

106
/***
117
* 1ファイルの変更内容.
8+
* 単一ファイルの差分情報.
9+
*
1210
* @author k-naitou
1311
*
1412
*/
1513
public class FileDiff {
1614

17-
private static final Logger log = LoggerFactory.getLogger(FileDiff.class);
18-
1915
private final List<String> diff;
20-
public final String fileName;
16+
private final String fileName;
2117
private final List<String> originalSourceCodeLines;
2218
private final List<String> modifiedSourceCodeLines;
2319

24-
public FileDiff(final List<String> diff, final String fileName,
20+
public FileDiff(final String fileName, final List<String> diff,
2521
final List<String> originalSourceCodeLines, final List<String> modifiedSourceCodeLines) {
2622
this.diff = diff;
2723
this.fileName = fileName;
2824
this.originalSourceCodeLines = originalSourceCodeLines;
2925
this.modifiedSourceCodeLines = modifiedSourceCodeLines;
3026
}
3127

28+
public String getFileName() {
29+
return fileName;
30+
}
31+
3232
public List<String> getOriginalSourceCodeLines() {
3333
return originalSourceCodeLines;
3434
}
@@ -37,16 +37,13 @@ public List<String> getModifiedSourceCodeLines() {
3737
return modifiedSourceCodeLines;
3838
}
3939

40-
public String getDiff() {
41-
return String.join(System.lineSeparator(), diff);
40+
public List<String> getDiff() {
41+
return diff;
4242
}
4343

44-
public void write(final Path outDir) {
45-
try {
46-
Files.write(outDir.resolve(fileName + ".java"), modifiedSourceCodeLines);
47-
Files.write(outDir.resolve(fileName + ".diff"), diff);
48-
} catch (final IOException e) {
49-
log.error(e.getMessage(), e);
50-
}
44+
@Override
45+
public String toString() {
46+
return diff.stream()
47+
.collect(Collectors.joining(System.lineSeparator()));
5148
}
5249
}

src/main/java/jp/kusumotolab/kgenprog/output/FileDiffSerializer.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ public JsonElement serialize(final FileDiff fileDiff, final Type type,
4747
final JsonSerializationContext context) {
4848

4949
final JsonObject serializedFileDiff = new JsonObject();
50-
serializedFileDiff.addProperty("fileName", fileDiff.fileName);
51-
serializedFileDiff.addProperty("diff", fileDiff.getDiff());
50+
serializedFileDiff.addProperty("fileName", fileDiff.getFileName());
51+
serializedFileDiff.addProperty("diff", fileDiff.getDiff().toString());
5252

5353
return serializedFileDiff;
5454
}

0 commit comments

Comments
 (0)