[Major] Made GenericReport to be auto closeable
This commit is contained in:
parent
543810c8f9
commit
0d1ab66cb9
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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") //
|
||||||
|
|
Loading…
Reference in New Issue