Skip to content

Commit d59aa36

Browse files
committed
Add grouped export of results, currently only supported by the ScriptFrontend through --group-scopes
1 parent 9e56baf commit d59aa36

3 files changed

Lines changed: 99 additions & 11 deletions

File tree

src/main/java/nl/rug/jbi/jsm/Bootstrap.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public static void main(final String[] args) throws IOException {
5757
final Set<String> input = Sets.newHashSet();
5858
final Set<String> libraries = Sets.newHashSet();
5959
final Set<String> output = Sets.newHashSet();
60+
boolean groupExportScopes = false;
6061

6162
Set<String> selectedSet = Sets.newHashSet();
6263

@@ -67,6 +68,8 @@ public static void main(final String[] args) throws IOException {
6768
selectedSet = libraries;
6869
} else if ("--out".equalsIgnoreCase(arg)) {
6970
selectedSet = output;
71+
} else if ("--group-scopes".equalsIgnoreCase(arg)) {
72+
groupExportScopes = true;
7073
} else {
7174
selectedSet.add(arg);
7275
}
@@ -75,7 +78,7 @@ public static void main(final String[] args) throws IOException {
7578
checkArgument(!input.isEmpty(), "Scriptable mode requires a specified input. (--in)");
7679
checkArgument(!output.isEmpty(), "Scriptable mode requires a specified output. (--out)");
7780

78-
frontend = new ScriptFrontend(core, input, libraries, output);
81+
frontend = new ScriptFrontend(core, input, libraries, output, groupExportScopes);
7982
} else {
8083
//GUI mode
8184
frontend = new GUIFrontend(core);

src/main/java/nl/rug/jbi/jsm/frontend/ScriptFrontend.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class ScriptFrontend implements Frontend {
3333

3434
private final Set<String> input;
3535
private final Set<String> libraries;
36+
private final boolean groupExportScopes;
3637

3738
private final Table<String, Class, Object> resultsClass = HashBasedTable.create();
3839
private final Table<String, Class, Object> resultsPackage = HashBasedTable.create();
@@ -53,11 +54,13 @@ public ScriptFrontend(
5354
final JSMCore core,
5455
final Set<String> input,
5556
final Set<String> libraries,
56-
final Set<String> output
57+
final Set<String> output,
58+
final boolean groupExportScopes
5759
) throws IOException {
5860
this.core = core;
5961
this.input = input;
6062
this.libraries = libraries;
63+
this.groupExportScopes = groupExportScopes;
6164
this.exporter = getOutputWriter(output);
6265

6366
logger.info("Exporting to {}", this.exporter);
@@ -66,10 +69,15 @@ public ScriptFrontend(
6669
private static void exportData(
6770
final ResultsExporter exporter,
6871
final Table<String, Class, Object> results,
69-
final MetricScope scope
72+
final MetricScope scope,
73+
final boolean groupExportScopes
7074
) throws IOException {
71-
for (final Map.Entry<Class, Map<String, Object>> entry : results.columnMap().entrySet()) {
72-
exporter.exportData(entry.getKey(), scope, entry.getValue());
75+
if (groupExportScopes) {
76+
exporter.exportDataCollection(scope, results);
77+
} else {
78+
for (final Map.Entry<Class, Map<String, Object>> entry : results.columnMap().entrySet()) {
79+
exporter.exportData(entry.getKey(), scope, entry.getValue());
80+
}
7381
}
7482
}
7583

@@ -157,9 +165,9 @@ public synchronized void processResult(List<MetricResult> resultList) {
157165
public void signalDone() {
158166
logger.info("Processing finished, exporting results");
159167
try {
160-
exportData(this.exporter, this.resultsClass, MetricScope.CLASS);
161-
exportData(this.exporter, this.resultsPackage, MetricScope.PACKAGE);
162-
exportData(this.exporter, this.resultsCollection, MetricScope.COLLECTION);
168+
exportData(this.exporter, this.resultsClass, MetricScope.CLASS, this.groupExportScopes);
169+
exportData(this.exporter, this.resultsPackage, MetricScope.PACKAGE, this.groupExportScopes);
170+
exportData(this.exporter, this.resultsCollection, MetricScope.COLLECTION, this.groupExportScopes);
163171

164172
this.exporter.close();
165173
} catch (IOException e) {

src/main/java/nl/rug/jbi/jsm/util/ResultsExporter.java

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@
33
import au.com.bytecode.opencsv.CSVWriter;
44
import com.google.common.base.Function;
55
import com.google.common.base.Objects;
6-
import com.google.common.collect.FluentIterable;
6+
import com.google.common.collect.*;
77
import nl.rug.jbi.jsm.core.calculator.MetricScope;
88

99
import java.io.Closeable;
1010
import java.io.File;
1111
import java.io.FileWriter;
1212
import java.io.IOException;
1313
import java.text.NumberFormat;
14+
import java.util.Iterator;
15+
import java.util.List;
1416
import java.util.Map;
1517

1618
import static com.google.common.base.Preconditions.checkArgument;
@@ -96,7 +98,8 @@ private File getFileForName(final String identifier, final boolean strict) throw
9698
* @param results Map with results for the given metric and scope.
9799
* @throws IOException If it gets thrown by the underlying CSVWriter
98100
*/
99-
public void exportData(final Class metricClass, final MetricScope scope, final Map<String, Object> results) throws IOException {
101+
public void exportData(final Class metricClass, final MetricScope scope, final Map<String, Object> results)
102+
throws IOException {
100103
checkArgument(metricClass != null);
101104
assert metricClass != null;
102105
checkArgument(scope != null);
@@ -132,10 +135,84 @@ public String[] apply(Map.Entry<String, Object> entry) {
132135
.toList()
133136
);
134137
} finally {
135-
writer.close();
138+
try {
139+
writer.close();
140+
} catch (IOException ignored) {
141+
//Prevent finally block from overriding exceptions
142+
}
143+
}
144+
}
145+
146+
147+
/**
148+
* Exports a data set collection, creates a file to contain the results, writes the filename to the mapping file
149+
* and then write all the data from the given table to that file.
150+
*
151+
* @param scope Scope of the results getting exported.
152+
* @param results Map with results for the given scope.
153+
* @throws IOException If it gets thrown by the underlying CSVWriter
154+
*/
155+
public void exportDataCollection(final MetricScope scope, final Table<String, Class, Object> results)
156+
throws IOException {
157+
checkArgument(scope != null);
158+
assert scope != null;
159+
checkArgument(results != null);
160+
assert results != null;
161+
162+
final File metricOutput = getFileForName(scope.toString(), false);
163+
164+
//Output mappings
165+
final String outputFileName = metricOutput.toString();
166+
for (final Class c : results.columnKeySet()) {
167+
this.mappingWriter.writeNext(new String[]{c.getName(), scope.toString(), outputFileName});
168+
}
169+
this.mappingWriter.flush();
170+
171+
//Write results
172+
final CSVWriter writer = new CSVWriter(new FileWriter(metricOutput));
173+
try {
174+
//Output headers
175+
final List<String> headers = Lists.newLinkedList();
176+
headers.add("Identifier");
177+
headers.addAll(Collections2.transform(results.columnKeySet(), new Function<Class, String>() {
178+
@Override
179+
public String apply(Class aClass) {
180+
return aClass.getSimpleName();
181+
}
182+
}));
183+
writer.writeNext(headers.toArray(new String[headers.size()]));
184+
185+
//Output data
186+
final ImmutableList<String[]> mappedDataSet = FluentIterable.from(results.rowMap().entrySet())
187+
.transform(new Function<Map.Entry<String, Map<Class, Object>>, String[]>() {
188+
@Override
189+
public String[] apply(Map.Entry<String, Map<Class, Object>> entry) {
190+
final String[] ret = new String[1 + entry.getValue().size()];
191+
ret[0] = entry.getKey();
192+
193+
final Iterator<Object> it = entry.getValue().values().iterator();
194+
int count = 1;
195+
while (it.hasNext()) {
196+
ret[count++] = printObject(it.next(), ResultsExporter.this.nf);
197+
}
198+
199+
return ret;
200+
}
201+
})
202+
.toList();
203+
writer.writeAll(mappedDataSet);
204+
} finally {
205+
try {
206+
writer.close();
207+
} catch (IOException ignored) {
208+
//Prevent finally block from overriding exceptions
209+
}
136210
}
137211
}
138212

213+
/**
214+
* @return Relative location of the 'mapping' file
215+
*/
139216
public String getMappingFileName() {
140217
return this.mappingFileName;
141218
}

0 commit comments

Comments
 (0)