package betsy.tools;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
import betsy.bpmn.reporting.BPMNCsvReport;
import betsy.common.analytics.aggregation.TrivalentResult;
import betsy.common.analytics.CsvReportLoader;
import betsy.common.analytics.model.CsvReport;
import betsy.common.analytics.model.Engine;
import betsy.common.analytics.model.Test;
import com.google.common.base.Charsets;
import configuration.bpmn.BPMNProcessRepository;
import pebl.benchmark.feature.FeatureSet;
public class ResultsPerFeatureSetGenerator {
private final CsvReport csvReport;
private final List<pebl.benchmark.test.Test> processes;
public ResultsPerFeatureSetGenerator(Path csvPath, String processes) {
CsvReportLoader loader = new CsvReportLoader(csvPath, new BPMNCsvReport());
this.csvReport = loader.load();
if(processes!=null) {
this.processes = new BPMNProcessRepository().getByName(processes);
} else {
this.processes = new ArrayList<>();
BPMNProcessRepository repo = new BPMNProcessRepository();
this.processes.addAll(repo.getByNames(csvReport.getNameToTest().keySet().toArray(new String[csvReport.getNameToTest().keySet().size()])));
}
}
public void createAggregatedCSV(Path targetCsvPath) {
List<AggregatedCsvRow> rows = new ArrayList<>();
// Find all Feature Sets
List<FeatureSet> featureSets = processes.stream().map(process -> process.getFeature().getFeatureSet()).distinct().collect(
Collectors.toList());
Map<FeatureSet, List<String>> featureSetMap = new TreeMap<>();
featureSets.forEach(fs -> featureSetMap.put(fs, new ArrayList<>()));
for(pebl.benchmark.test.Test p : processes) {
FeatureSet fs = p.getFeature().getFeatureSet();
if(featureSetMap.containsKey(fs)) {
featureSetMap.get(fs).add(p.getName());
}
}
// All test results from CsvReport:
Collection<Test> allTests = csvReport.getTests();
Collection<Engine> allEngines = csvReport.getEngines();
// For each engine:
for(Engine engine : allEngines) {
// For each feature set:
for(FeatureSet featureSet : featureSetMap.keySet()) {
AggregatedCsvRow row = new AggregatedCsvRow(featureSet.getName(), engine.getName(), featureSet.getGroup().getName());
allTests.stream().filter(test -> featureSetMap.get(featureSet).contains(test.getName())).
forEach(t -> row.append(t.getEngineToResult().get(engine).getFailed(), t.getEngineToResult().get(engine).getTotal()));
rows.add(row);
}
}
writeRows(rows, targetCsvPath);
}
private void writeRows(final List<AggregatedCsvRow> rows, Path targetCsvPath) {
List<String> lines = rows.stream().map(AggregatedCsvRow::toString).collect(Collectors.toList());
try {
Files.write(targetCsvPath, lines, Charsets.UTF_8);
} catch (IOException e) {
throw new IllegalStateException("could not write file " + targetCsvPath, e);
}
}
/**
* Generates a CSV file with aggregated results per featureSet (e.g., combining all tests for the language construct "ExclusiveGateway")
*
* Resulting format is: FeatureSetName;Engine;Group;TrivalentResult;#OfFailures;#OfTests
*
* @param args expected args: args[0] - Path to standard CSV report
* args[1] - Target path for generated report
* args[2] - process limitation (e.g., only "ACTIVITIES") - all processes in CSV if is not present
*/
public static void main(String[] args) {
String processes = null;
if(args.length==3) {
processes = args[2];
}
ResultsPerFeatureSetGenerator generator = new ResultsPerFeatureSetGenerator(Paths.get(args[0]), processes);
generator.createAggregatedCSV(Paths.get(args[1]));
}
private class AggregatedCsvRow {
private static final String SEPARATOR = ";";
private final String featureSet;
private final String engine;
private final String group;
private int failures = 0;
private int tests = 0;
public AggregatedCsvRow(String featureSet, String engine, String group) {
this.featureSet = featureSet;
this.engine = engine;
this.group = group;
}
public synchronized void append(int failures, int tests) {
this.failures += failures;
this.tests += tests;
}
private TrivalentResult calculateResult() {
if(failures==tests) {
return TrivalentResult.MINUS;
} else if(failures==0) {
return TrivalentResult.PLUS;
} else {
return TrivalentResult.PLUS_MINUS;
}
}
@Override
public String toString() {
return String.join(SEPARATOR, featureSet, engine, group, calculateResult().getSign(), String.valueOf(failures), String.valueOf(tests));
}
}
}