[Major] Made GenericReport to be auto closeable

This commit is contained in:
Robert von Burg 2019-03-05 18:01:09 +01:00
parent 543810c8f9
commit 0d1ab66cb9
5 changed files with 117 additions and 91 deletions

View File

@ -106,10 +106,10 @@ public class ReportResource {
}
JsonArray result = new JsonArray();
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext())) {
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id));
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext());
Report report = new Report(tx, id)) {
Report report = new Report(tx, id);
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id));
// set i18n data if possible
if (localeJ != null)
@ -160,11 +160,10 @@ public class ReportResource {
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject();
}
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext())) {
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id));
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext());
Report report = new Report(tx, id)) {
// get report
Report report = new Report(tx, id);
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id));
// set i18n data if possible
if (localeJ != null)
@ -260,14 +259,13 @@ public class ReportResource {
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject();
}
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext())) {
long start = System.nanoTime();
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext());
Report report = new Report(tx, id)) {
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id));
long start = System.nanoTime();
// get report
Report report = new Report(tx, id);
// set i18n data if possible
if (localeJ != null)
report.getReportPolicy().setI18nData(localeJ);
@ -354,54 +352,56 @@ public class ReportResource {
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject();
}
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext())) {
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id));
// create CSV printer with header
StreamingOutput out = getOut(cert, realm, id, localeJ, filters);
// get report
Report report = new Report(tx, id);
// set i18n data if possible
if (localeJ != null)
report.getReportPolicy().setI18nData(localeJ);
// add filters from request
filters.keySet().forEach(f -> report.filter(f, filters.getSet(f)));
// get headers
List<String> orderedColumnKeys = report.getColumnKeys();
String[] headers = new String[orderedColumnKeys.size()];
orderedColumnKeys.toArray(headers);
if (localeJ != null) {
for (int i = 0; i < headers.length; i++) {
if (localeJ.has(headers[i]))
headers[i] = localeJ.get(headers[i]).getAsString();
}
}
// create CSV printer with header
StreamingOutput out = getOut(report, headers);
// send
String fileName = id + "_" + System.currentTimeMillis() + ".csv";
return Response.ok(out, TEXT_CSV_TYPE)
.header("Content-Disposition", "attachment; filename=\"" + fileName + "\"").build();
}
// send
String fileName = id + "_" + System.currentTimeMillis() + ".csv";
return Response.ok(out, TEXT_CSV_TYPE)
.header("Content-Disposition", "attachment; filename=\"" + fileName + "\"").build();
}
private StreamingOutput getOut(Report report, String[] headers) {
private StreamingOutput getOut(Certificate cert, String realm, String reportId, JsonObject localeJ,
MapOfSets<String, String> filters) {
return out -> {
// get report content and add to the buffer
try (CSVPrinter csvP = new CSVPrinter(new OutputStreamWriter(out),
CSVFormat.DEFAULT.withHeader(headers).withDelimiter(';'))) {
report.doReport().forEach(row -> {
try {
csvP.printRecord(row.valueStream().collect(Collectors.toList())); // add to CSV
} catch (Exception e) {
logger.error("Could not write CSV row", e);
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext());
Report report = new Report(tx, reportId)) {
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), reportId));
// set i18n data if possible
if (localeJ != null)
report.getReportPolicy().setI18nData(localeJ);
// add filters from request
filters.keySet().forEach(f -> report.filter(f, filters.getSet(f)));
// get headers
List<String> orderedColumnKeys = report.getColumnKeys();
String[] headers = new String[orderedColumnKeys.size()];
orderedColumnKeys.toArray(headers);
if (localeJ != null) {
for (int i = 0; i < headers.length; i++) {
if (localeJ.has(headers[i]))
headers[i] = localeJ.get(headers[i]).getAsString();
}
});
}
// get report content and add to the buffer
try (CSVPrinter csvP = new CSVPrinter(new OutputStreamWriter(out),
CSVFormat.DEFAULT.withHeader(headers).withDelimiter(';'))) {
report.doReport().forEach(row -> {
try {
csvP.printRecord(row.valueStream().collect(Collectors.toList())); // add to CSV
} catch (Exception e) {
logger.error("Could not write CSV row", e);
}
});
}
}
};
}

View File

@ -17,7 +17,7 @@ import li.strolch.report.policy.ReportPolicy;
import li.strolch.utils.collections.DateRange;
import li.strolch.utils.collections.MapOfSets;
public class Report {
public class Report implements AutoCloseable {
private final ReportPolicy reportPolicy;
@ -88,4 +88,12 @@ public class Report {
});
}
@Override
public void close() {
try {
this.reportPolicy.close();
} catch (Exception e) {
throw new IllegalStateException("Failed to close underlying policy " + this.reportPolicy.getClass(), e);
}
}
}

View File

@ -129,6 +129,10 @@ public class GenericReport extends ReportPolicy {
}
}
public boolean isDescending() {
return this.descending;
}
public void setI18nData(JsonObject i18nData) {
this.i18nData = i18nData;
}

View File

@ -44,6 +44,10 @@ public abstract class ReportPolicy extends StrolchPolicy {
public abstract long getCounter();
public void close() throws Exception {
// do nothing
}
@Override
public void undo() {
// can't be undone

View File

@ -46,10 +46,10 @@ public class GenericReportTest {
@Test
public void shouldGenerateJsonReport() {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate)) {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate);
Report report = new Report(tx, "stockReport")) {
new Report(tx, "stockReport") //
.doReportAsJson() //
report.doReportAsJson() //
.forEach(e -> {
switch (e.get("slot").getAsString()) {
@ -111,10 +111,10 @@ public class GenericReportTest {
@Test
public void shouldFilterReport1() {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate)) {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate);
Report report = new Report(tx, "stockReport")) {
new Report(tx, "stockReport") //
.filter("Product", "product01") //
report.filter("Product", "product01") //
.doReportAsJson() //
.forEach(e -> {
@ -134,10 +134,10 @@ public class GenericReportTest {
@Test
public void shouldFilterReport2() {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate)) {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate);
Report report = new Report(tx, "stockReport")) {
new Report(tx, "stockReport") //
.filter("Product", "product01") //
report.filter("Product", "product01") //
.filter("Location", "location02") //
.doReportAsJson() //
.forEach(e -> {
@ -157,15 +157,15 @@ public class GenericReportTest {
@Test
public void shouldFilterReportByDateRange1() {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate)) {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate);
Report report = new Report(tx, "stockReport")) {
Date from = new Date(LocalDate.of(2016, 1, 1).toEpochDay() * 86400000);
Date to = new Date(LocalDate.of(2017, 1, 1).toEpochDay() * 86400000);
DateRange dateRange = new DateRange().from(from, true).to(to, false);
// expect no slots as all not in date range
List<JsonObject> result = new Report(tx, "stockReport") //
.filter("Product", "product01") //
List<JsonObject> result = report.filter("Product", "product01") //
.dateRange(dateRange) //
.doReportAsJson() //
.collect(toList());
@ -189,38 +189,48 @@ public class GenericReportTest {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate)) {
Date from = new Date(LocalDate.of(2016, 1, 1).toEpochDay() * 86400000);
Date to = new Date(LocalDate.of(2017, 1, 1).toEpochDay() * 86400000);
DateRange dateRange = new DateRange().from(from, true).to(to, false);
// expect no orders as all not in date range
Report report = new Report(tx, "fromStockReport");
List<JsonObject> result = report.filter("Product", "product01").dateRange(dateRange).doReportAsJson()
.collect(toList());
assertTrue(result.isEmpty());
try (Report report = new Report(tx, "fromStockReport")) {
Date to = new Date(LocalDate.of(2017, 1, 1).toEpochDay() * 86400000);
DateRange dateRange = new DateRange().from(from, true).to(to, false);
List<JsonObject> result = report.filter("Product", "product01").dateRange(dateRange).doReportAsJson()
.collect(toList());
assertTrue(result.isEmpty());
}
// expect 2 orders, as in date range
to = new Date(LocalDate.of(2017, 3, 1).toEpochDay() * 86400000);
dateRange = new DateRange().from(from, true).to(to, false);
report = new Report(tx, "fromStockReport");
result = report.filter("Product", "product01").dateRange(dateRange).doReportAsJson().collect(toList());
assertEquals(2, result.size());
try (Report report = new Report(tx, "fromStockReport")) {
Date to = new Date(LocalDate.of(2017, 3, 1).toEpochDay() * 86400000);
DateRange dateRange = new DateRange().from(from, true).to(to, false);
List<JsonObject> result = report.filter("Product", "product01").dateRange(dateRange).doReportAsJson()
.collect(toList());
assertEquals(2, result.size());
}
// expect 4 orders, as all in date range
to = new Date(LocalDate.of(2017, 3, 2).toEpochDay() * 86400000);
dateRange = new DateRange().from(from, true).to(to, false);
report = new Report(tx, "fromStockReport");
result = report.filter("Product", "product01", "product02").dateRange(dateRange).doReportAsJson()
.collect(toList());
assertEquals(4, result.size());
try (Report report = new Report(tx, "fromStockReport")) {
Date to = new Date(LocalDate.of(2017, 3, 2).toEpochDay() * 86400000);
DateRange dateRange = new DateRange().from(from, true).to(to, false);
List<JsonObject> result = report.filter("Product", "product01", "product02").dateRange(dateRange)
.doReportAsJson().collect(toList());
assertEquals(4, result.size());
}
}
}
@Test
public void shouldCreateFilterCriteria() {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate)) {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate);
Report report = new Report(tx, "stockReport")) {
Report report = new Report(tx, "stockReport");
MapOfSets<String, StrolchRootElement> filterCriteria = report.generateFilterCriteria();
assertFalse(filterCriteria.containsSet("Location"));
@ -237,9 +247,9 @@ public class GenericReportTest {
@Test
public void shouldCreateFilterCriteriaFiltered1() {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate)) {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate);
Report report = new Report(tx, "stockReport")) {
Report report = new Report(tx, "stockReport");
MapOfSets<String, StrolchRootElement> filterCriteria = report.filter("Product", "product01")
.generateFilterCriteria();
@ -264,13 +274,13 @@ public class GenericReportTest {
@Test
public void shouldCreateFilterCriteriaFiltered2() {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate)) {
try (StrolchTransaction tx = runtimeMock.openUserTx(certificate);
Report report = new Report(tx, "stockReport")) {
Date from = new Date(LocalDate.of(2017, 3, 1).toEpochDay() * 86400000);
Date to = new Date(LocalDate.of(2017, 3, 5).toEpochDay() * 86400000);
DateRange dateRange = new DateRange().from(from, true).to(to, false);
Report report = new Report(tx, "stockReport");
MapOfSets<String, StrolchRootElement> filterCriteria = report //
.dateRange(dateRange) //
.filter("Product", "product01") //