From 278d17ecfee71d93657fc703575f1b2171982685 Mon Sep 17 00:00:00 2001 From: Mustapha Zorgati <15628173+mustaphazorgati@users.noreply.github.com> Date: Tue, 21 Jul 2020 16:32:23 +0200 Subject: [PATCH] TSK-1344: added key for all rows --- .../api/reports/ClassificationReport.java | 4 +- .../taskana/monitor/api/reports/Report.java | 12 +- .../monitor/api/reports/TimestampReport.java | 4 +- .../row/DetailedClassificationRow.java | 11 +- .../monitor/api/reports/row/FoldableRow.java | 17 +- .../taskana/monitor/api/reports/row/Row.java | 2 + .../monitor/api/reports/row/SingleRow.java | 9 +- .../monitor/api/reports/row/TimestampRow.java | 32 +-- .../taskana/monitor/internal/ReportTest.java | 247 ++++++++++++------ .../ReportRepresentationModelAssembler.java | 6 +- .../models/ReportRepresentationModel.java | 8 +- 11 files changed, 225 insertions(+), 127 deletions(-) diff --git a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/ClassificationReport.java b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/ClassificationReport.java index 6726843d7..fe61cd514 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/ClassificationReport.java +++ b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/ClassificationReport.java @@ -71,8 +71,8 @@ public class ClassificationReport extends Report columnHeaders, String[] rowDesc) { this.rowDesc = rowDesc; - sumRow = createRow(columnHeaders.size()); + sumRow = createRow("Total", columnHeaders.size()); this.columnHeaders = new ArrayList<>(columnHeaders); } @@ -69,14 +69,16 @@ public abstract class Report row = null; if (columnHeaders.isEmpty()) { - row = reportRows.computeIfAbsent(item.getKey(), (s) -> createRow(columnHeaders.size())); + row = reportRows.computeIfAbsent(item.getKey(), key -> createRow(key, columnHeaders.size())); row.updateTotalValue(item); sumRow.updateTotalValue(item); } else { for (int i = 0; i < columnHeaders.size(); i++) { if (columnHeaders.get(i).fits(item)) { if (row == null) { - row = reportRows.computeIfAbsent(item.getKey(), (s) -> createRow(columnHeaders.size())); + row = + reportRows.computeIfAbsent( + item.getKey(), key -> createRow(key, columnHeaders.size())); } row.addItem(item, i); sumRow.addItem(item, i); @@ -97,8 +99,8 @@ public abstract class Report createRow(int columnSize) { - return new SingleRow<>(columnSize); + protected Row createRow(String key, int columnSize) { + return new SingleRow<>(key, columnSize); } /** diff --git a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/TimestampReport.java b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/TimestampReport.java index 41ba8e264..9a5f30e90 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/TimestampReport.java +++ b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/TimestampReport.java @@ -23,8 +23,8 @@ public class TimestampReport extends Report { - public DetailedClassificationRow(int columnSize) { - super(columnSize, (item) -> item.getAttachmentKey() != null ? item.getAttachmentKey() : "N/A"); + public DetailedClassificationRow(String key, int columnSize) { + super( + key, + columnSize, + (item) -> item.getAttachmentKey() != null ? item.getAttachmentKey() : "N/A"); } @Override @@ -19,7 +22,7 @@ public class DetailedClassificationRow extends FoldableRow buildRow(int columnSize) { - return new SingleRow<>(columnSize); + protected Row buildRow(String key, int columnSize) { + return new SingleRow<>(key, columnSize); } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/FoldableRow.java b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/FoldableRow.java index c781859fd..1137e270c 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/FoldableRow.java +++ b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/FoldableRow.java @@ -17,12 +17,13 @@ import pro.taskana.monitor.api.reports.item.QueryItem; */ public abstract class FoldableRow extends SingleRow { - private Map> foldableRows = new LinkedHashMap<>(); - private Function calcFoldableRowKey; - private int columnSize; + private final Map> foldableRows = new LinkedHashMap<>(); + private final Function calcFoldableRowKey; + private final int columnSize; - protected FoldableRow(int columnSize, Function calcFoldableRowKey) { - super(columnSize); + protected FoldableRow( + String key, int columnSize, Function calcFoldableRowKey) { + super(key, columnSize); this.columnSize = columnSize; this.calcFoldableRowKey = calcFoldableRowKey; } @@ -39,7 +40,7 @@ public abstract class FoldableRow extends SingleRow { public void addItem(I item, int index) throws IndexOutOfBoundsException { super.addItem(item, index); foldableRows - .computeIfAbsent(calcFoldableRowKey.apply(item), (s) -> buildRow(columnSize)) + .computeIfAbsent(calcFoldableRowKey.apply(item), key -> buildRow(key, columnSize)) .addItem(item, index); } @@ -47,7 +48,7 @@ public abstract class FoldableRow extends SingleRow { public void updateTotalValue(I item) { super.updateTotalValue(item); foldableRows - .computeIfAbsent(calcFoldableRowKey.apply(item), (s) -> buildRow(columnSize)) + .computeIfAbsent(calcFoldableRowKey.apply(item), key -> buildRow(key, columnSize)) .updateTotalValue(item); } @@ -55,7 +56,7 @@ public abstract class FoldableRow extends SingleRow { return foldableRows.get(key); } - abstract Row buildRow(int columnSize); + protected abstract Row buildRow(String key, int columnSize); @Override public String toString() { diff --git a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/Row.java b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/Row.java index 2e311649c..8f3ac00e4 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/Row.java +++ b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/Row.java @@ -28,6 +28,8 @@ public interface Row { */ void updateTotalValue(I item); + String getKey(); + int getTotalValue(); int[] getCells(); diff --git a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/SingleRow.java b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/SingleRow.java index 2c12726b5..9da1a6cc1 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/SingleRow.java +++ b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/SingleRow.java @@ -14,8 +14,10 @@ public class SingleRow implements Row { private final int[] cells; private int total = 0; + private final String key; - public SingleRow(int columnCount) { + public SingleRow(String key, int columnCount) { + this.key = key; cells = new int[columnCount]; } @@ -30,6 +32,11 @@ public class SingleRow implements Row { total += item.getValue(); } + @Override + public String getKey() { + return key; + } + @Override public final int getTotalValue() { return total; diff --git a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/TimestampRow.java b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/TimestampRow.java index 80ab75609..856d9f8c9 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/TimestampRow.java +++ b/lib/taskana-core/src/main/java/pro/taskana/monitor/api/reports/row/TimestampRow.java @@ -9,8 +9,8 @@ import pro.taskana.monitor.api.reports.item.TimestampQueryItem; */ public class TimestampRow extends FoldableRow { - public TimestampRow(int columnSize) { - super(columnSize, TimestampQueryItem::getOrgLevel1); + public TimestampRow(String key, int columnSize) { + super(key, columnSize, TimestampQueryItem::getOrgLevel1); } @Override @@ -19,8 +19,8 @@ public class TimestampRow extends FoldableRow { } @Override - OrgLevel1Row buildRow(int columnSize) { - return new OrgLevel1Row(columnSize); + protected OrgLevel1Row buildRow(String key, int columnSize) { + return new OrgLevel1Row(key, columnSize); } /** @@ -29,8 +29,8 @@ public class TimestampRow extends FoldableRow { */ public static final class OrgLevel1Row extends FoldableRow { - private OrgLevel1Row(int columnSize) { - super(columnSize, TimestampQueryItem::getOrgLevel2); + private OrgLevel1Row(String key, int columnSize) { + super(key, columnSize, TimestampQueryItem::getOrgLevel2); } @Override @@ -39,8 +39,8 @@ public class TimestampRow extends FoldableRow { } @Override - OrgLevel2Row buildRow(int columnSize) { - return new OrgLevel2Row(columnSize); + protected OrgLevel2Row buildRow(String key, int columnSize) { + return new OrgLevel2Row(key, columnSize); } } @@ -50,8 +50,8 @@ public class TimestampRow extends FoldableRow { */ public static final class OrgLevel2Row extends FoldableRow { - private OrgLevel2Row(int columnSize) { - super(columnSize, TimestampQueryItem::getOrgLevel3); + private OrgLevel2Row(String key, int columnSize) { + super(key, columnSize, TimestampQueryItem::getOrgLevel3); } @Override @@ -60,8 +60,8 @@ public class TimestampRow extends FoldableRow { } @Override - OrgLevel3Row buildRow(int columnSize) { - return new OrgLevel3Row(columnSize); + protected OrgLevel3Row buildRow(String key, int columnSize) { + return new OrgLevel3Row(key, columnSize); } } @@ -71,8 +71,8 @@ public class TimestampRow extends FoldableRow { */ public static final class OrgLevel3Row extends FoldableRow { - private OrgLevel3Row(int columnSize) { - super(columnSize, TimestampQueryItem::getOrgLevel4); + private OrgLevel3Row(String key, int columnSize) { + super(key, columnSize, TimestampQueryItem::getOrgLevel4); } @Override @@ -81,8 +81,8 @@ public class TimestampRow extends FoldableRow { } @Override - Row buildRow(int columnSize) { - return new SingleRow<>(columnSize); + protected Row buildRow(String key, int columnSize) { + return new SingleRow<>(key, columnSize); } } } diff --git a/lib/taskana-core/src/test/java/pro/taskana/monitor/internal/ReportTest.java b/lib/taskana-core/src/test/java/pro/taskana/monitor/internal/ReportTest.java index 3eb83a2f1..da4030f36 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/monitor/internal/ReportTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/monitor/internal/ReportTest.java @@ -15,7 +15,9 @@ import pro.taskana.monitor.api.reports.Report; import pro.taskana.monitor.api.reports.header.TimeIntervalColumnHeader; import pro.taskana.monitor.api.reports.item.MonitorQueryItem; import pro.taskana.monitor.api.reports.item.QueryItemPreprocessor; +import pro.taskana.monitor.api.reports.row.FoldableRow; import pro.taskana.monitor.api.reports.row.Row; +import pro.taskana.monitor.api.reports.row.SingleRow; /** Tests for {@link Report}. */ class ReportTest { @@ -37,7 +39,12 @@ class ReportTest { } @Test - void testEmptyReport() { + void should_HaveSumRowTotalKey_When_ReportExists() { + assertThat(report.getSumRow().getKey()).isEqualTo("Total"); + } + + @Test + void should_HaveEmptySumRow_When_ReportIsEmpty() { // then assertThat(report.getRows()).isEmpty(); Row sumRow = report.getSumRow(); @@ -46,7 +53,54 @@ class ReportTest { } @Test - void testInsertSingleItem() { + void should_CreateRowAndSetKey_When_InsertingItemWithUnknownKey() { + // when + report.addItem(item); + + // then + assertThat(report.getRows()).hasSize(1); + Row row = report.getRow("key"); + assertThat(row.getKey()).isEqualTo("key"); + } + + @Test + void should_CreateFoldableRowAndSetKey_When_InsertingItemWithUnknownKey() { + // when + ReportWithFoldableRow report = + new ReportWithFoldableRow(HEADERS, new String[] {"rowDesc", "foldableRowDesc"}); + report.addItem(item); + + // then + assertThat(report.getRows()).hasSize(1); + FoldableTestRow row = report.getRow("key"); + assertThat(row.getKey()).isEqualTo("key"); + + assertThat(row.getFoldableRowCount()).isOne(); + Row foldableRow = row.getFoldableRow("KEY"); + assertThat(foldableRow.getKey()).isEqualTo("KEY"); + } + + @Test + void should_AppendItemValueInFoldableRow_When_ItemIsInserted() { + // when + ReportWithFoldableRow report = + new ReportWithFoldableRow(HEADERS, new String[] {"rowDesc", "foldableRowDesc"}); + report.addItem(item); + + // then + assertThat(report.getRows()).hasSize(1); + FoldableTestRow row = report.getRow("key"); + assertThat(row.getCells()).isEqualTo(new int[] {item.getValue(), 0, 0, 0}); + assertThat(row.getTotalValue()).isEqualTo(item.getValue()); + + assertThat(row.getFoldableRowCount()).isOne(); + Row foldableRow = row.getFoldableRow("KEY"); + assertThat(foldableRow.getCells()).isEqualTo(new int[] {item.getValue(), 0, 0, 0}); + assertThat(foldableRow.getTotalValue()).isEqualTo(item.getValue()); + } + + @Test + void should_AppendItemValue_When_ItemIsInserted() { // when report.addItem(item); @@ -58,7 +112,7 @@ class ReportTest { } @Test - void testInsertSameItemMultipleTimes() { + void should_AppendItemValue_When_CellAlreadyContainsValue() { // when report.addItem(item); report.addItem(item); @@ -71,13 +125,7 @@ class ReportTest { } @Test - void testInsertSameItemMultipleTimes2() { - // given - MonitorQueryItem item = new MonitorQueryItem(); - item.setKey("key"); - item.setAgeInDays(0); - item.setNumberOfTasks(3); - + void should_AppendItemValue_When_UsingBulkOperationToInsertItems() { // when report.addItems(Arrays.asList(item, item)); @@ -89,80 +137,7 @@ class ReportTest { } @Test - void testInsertSameItemMultipleTimesWithPreProcessor() { - // given - int overrideValue = 5; - QueryItemPreprocessor preprocessor = - (item) -> { - item.setNumberOfTasks(overrideValue); - return item; - }; - // when - report.addItems(Arrays.asList(item, item), preprocessor); - - // then - assertThat(report.getRows()).hasSize(1); - Row row = report.getRow("key"); - assertThat(row.getCells()).isEqualTo(new int[] {2 * overrideValue, 0, 0, 0}); - assertThat(row.getTotalValue()).isEqualTo(2 * overrideValue); - } - - @Test - void testInsertItemWithNoColumnHeaders() { - // given - List headerList = Collections.emptyList(); - report = - new MonitorQueryItemTimeIntervalColumnHeaderReport(headerList, new String[] {"rowDesc"}); - - // when - report.addItem(item); - - // then - assertThat(report.getRows()).hasSize(1); - assertThat(report.getRow("key").getCells()).isEqualTo(new int[0]); - assertThat(report.getRow("key").getTotalValue()).isEqualTo(item.getValue()); - } - - @Test - void testInsertItemWhichIsNotInHeaderScopes() { - // given - item.setAgeInDays(-2); - // when - report.addItem(item); - - // then - assertThat(report.getRows()).isEmpty(); - Row sumRow = report.getSumRow(); - assertThat(sumRow.getCells()).isEqualTo(new int[] {0, 0, 0, 0}); - assertThat(sumRow.getTotalValue()).isEqualTo(0); - } - - @Test - void testInsertItemWhichIsInMultipleHeaderScopes() { - // given - List headers = new ArrayList<>(HEADERS); - headers.add(new TimeIntervalColumnHeader(0, 3)); - report = new MonitorQueryItemTimeIntervalColumnHeaderReport(headers, new String[] {"rowDesc"}); - - item.setAgeInDays(2); - - // when - report.addItem(item); - - // then - assertThat(report.getRows()).hasSize(1); - - Row row = report.getRow("key"); - assertThat(row.getCells()).isEqualTo(new int[] {0, 0, item.getValue(), 0, item.getValue()}); - assertThat(row.getTotalValue()).isEqualTo(2 * item.getValue()); - - Row sumRow = report.getSumRow(); - assertThat(sumRow.getCells()).isEqualTo(new int[] {0, 0, item.getValue(), 0, item.getValue()}); - assertThat(sumRow.getTotalValue()).isEqualTo(2 * item.getValue()); - } - - @Test - void testInsertItemWithPreProcessor() { + void should_PreProcessItem_When_PreprocessorIsDefined() { // given int overrideValue = 5; QueryItemPreprocessor preprocessor = @@ -187,6 +162,79 @@ class ReportTest { assertThat(sumRow.getTotalValue()).isEqualTo(overrideValue); } + @Test + void should_PreProcessItem_When_PreprocessorIsDefinedForBulkInsert() { + // given + int overrideValue = 5; + QueryItemPreprocessor preprocessor = + (item) -> { + item.setNumberOfTasks(overrideValue); + return item; + }; + // when + report.addItems(Arrays.asList(item, item), preprocessor); + + // then + assertThat(report.getRows()).hasSize(1); + Row row = report.getRow("key"); + assertThat(row.getCells()).isEqualTo(new int[] {2 * overrideValue, 0, 0, 0}); + assertThat(row.getTotalValue()).isEqualTo(2 * overrideValue); + } + + @Test + void should_OnlyContainTotalRows_When_ReportContainsNoHeaders() { + // given + List headerList = Collections.emptyList(); + report = + new MonitorQueryItemTimeIntervalColumnHeaderReport(headerList, new String[] {"rowDesc"}); + + // when + report.addItem(item); + + // then + assertThat(report.getRows()).hasSize(1); + assertThat(report.getRow("key").getCells()).isEqualTo(new int[0]); + assertThat(report.getRow("key").getTotalValue()).isEqualTo(item.getValue()); + } + + @Test + void should_NotInsertItem_When_ItemIsOutOfHeaderScope() { + // given + item.setAgeInDays(-2); + // when + report.addItem(item); + + // then + assertThat(report.getRows()).isEmpty(); + Row sumRow = report.getSumRow(); + assertThat(sumRow.getCells()).isEqualTo(new int[] {0, 0, 0, 0}); + assertThat(sumRow.getTotalValue()).isEqualTo(0); + } + + @Test + void should_InsertItemMultipleTimes_When_HeaderFitsMultipleTimes() { + // given + List headers = new ArrayList<>(HEADERS); + headers.add(new TimeIntervalColumnHeader(0, 3)); + report = new MonitorQueryItemTimeIntervalColumnHeaderReport(headers, new String[] {"rowDesc"}); + + item.setAgeInDays(2); + + // when + report.addItem(item); + + // then + assertThat(report.getRows()).hasSize(1); + + Row row = report.getRow("key"); + assertThat(row.getCells()).isEqualTo(new int[] {0, 0, item.getValue(), 0, item.getValue()}); + assertThat(row.getTotalValue()).isEqualTo(2 * item.getValue()); + + Row sumRow = report.getSumRow(); + assertThat(sumRow.getCells()).isEqualTo(new int[] {0, 0, item.getValue(), 0, item.getValue()}); + assertThat(sumRow.getTotalValue()).isEqualTo(2 * item.getValue()); + } + private static class MonitorQueryItemTimeIntervalColumnHeaderReport extends Report { @@ -195,4 +243,35 @@ class ReportTest { super(headerList, rowDesc); } } + + private static class ReportWithFoldableRow + extends Report { + + protected ReportWithFoldableRow( + List columnHeaders, String[] rowDesc) { + super(columnHeaders, rowDesc); + } + + @Override + public FoldableTestRow getRow(String key) { + return (FoldableTestRow) super.getRow(key); + } + + @Override + protected Row createRow(String key, int columnSize) { + return new FoldableTestRow(key, columnSize); + } + } + + private static class FoldableTestRow extends FoldableRow { + + protected FoldableTestRow(String key, int columnSize) { + super(key, columnSize, (item) -> item.getKey().toUpperCase()); + } + + @Override + protected Row buildRow(String key, int columnSize) { + return new SingleRow<>(key, columnSize); + } + } } diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/monitor/rest/assembler/ReportRepresentationModelAssembler.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/monitor/rest/assembler/ReportRepresentationModelAssembler.java index 438c77217..f4fa1939b 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/monitor/rest/assembler/ReportRepresentationModelAssembler.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/monitor/rest/assembler/ReportRepresentationModelAssembler.java @@ -99,7 +99,11 @@ public class ReportRepresentationModelAssembler { report.getColumnHeaders().stream().map(H::getDisplayName).toArray(String[]::new); ReportRepresentationModel.MetaInformation meta = new ReportRepresentationModel.MetaInformation( - report.getClass().getSimpleName(), time.toString(), header, report.getRowDesc()); + report.getClass().getSimpleName(), + time.toString(), + header, + report.getRowDesc(), + report.getSumRow().getKey()); // iterate over each Row and transform it to a RowResource while keeping the domain key. List rows = diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/monitor/rest/models/ReportRepresentationModel.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/monitor/rest/models/ReportRepresentationModel.java index 82f4c4deb..320089a8d 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/monitor/rest/models/ReportRepresentationModel.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/monitor/rest/models/ReportRepresentationModel.java @@ -88,22 +88,22 @@ public class ReportRepresentationModel extends RepresentationModel