[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(); JsonArray result = new JsonArray();
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext())) { try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext());
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id)); 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 // set i18n data if possible
if (localeJ != null) if (localeJ != null)
@ -160,11 +160,10 @@ public class ReportResource {
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject(); localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject();
} }
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext())) { try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext());
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id)); Report report = new Report(tx, id)) {
// get report tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id));
Report report = new Report(tx, id);
// set i18n data if possible // set i18n data if possible
if (localeJ != null) if (localeJ != null)
@ -260,14 +259,13 @@ public class ReportResource {
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject(); 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)); 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 // set i18n data if possible
if (localeJ != null) if (localeJ != null)
report.getReportPolicy().setI18nData(localeJ); report.getReportPolicy().setI18nData(localeJ);
@ -354,54 +352,56 @@ public class ReportResource {
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject(); localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject();
} }
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext())) { // create CSV printer with header
tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), id)); StreamingOutput out = getOut(cert, realm, id, localeJ, filters);
// get report // send
Report report = new Report(tx, id); String fileName = id + "_" + System.currentTimeMillis() + ".csv";
return Response.ok(out, TEXT_CSV_TYPE)
// set i18n data if possible .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"").build();
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();
}
} }
private StreamingOutput getOut(Report report, String[] headers) { private StreamingOutput getOut(Certificate cert, String realm, String reportId, JsonObject localeJ,
MapOfSets<String, String> filters) {
return out -> { return out -> {
// get report content and add to the buffer try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, realm, getContext());
try (CSVPrinter csvP = new CSVPrinter(new OutputStreamWriter(out), Report report = new Report(tx, reportId)) {
CSVFormat.DEFAULT.withHeader(headers).withDelimiter(';'))) {
report.doReport().forEach(row -> { tx.getPrivilegeContext().validateAction(new SimpleRestrictable(ReportSearch.class.getName(), reportId));
try {
csvP.printRecord(row.valueStream().collect(Collectors.toList())); // add to CSV // set i18n data if possible
} catch (Exception e) { if (localeJ != null)
logger.error("Could not write CSV row", e); 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.DateRange;
import li.strolch.utils.collections.MapOfSets; import li.strolch.utils.collections.MapOfSets;
public class Report { public class Report implements AutoCloseable {
private final ReportPolicy reportPolicy; 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) { public void setI18nData(JsonObject i18nData) {
this.i18nData = i18nData; this.i18nData = i18nData;
} }

View File

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

View File

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