TSK-1344: added key for all rows

This commit is contained in:
Mustapha Zorgati 2020-07-21 16:32:23 +02:00
parent d8b9c6fed9
commit 278d17ecfe
11 changed files with 225 additions and 127 deletions

View File

@ -71,8 +71,8 @@ public class ClassificationReport extends Report<MonitorQueryItem, TimeIntervalC
}
@Override
protected DetailedClassificationRow createRow(int columnSize) {
return new DetailedClassificationRow(columnSize);
protected DetailedClassificationRow createRow(String key, int columnSize) {
return new DetailedClassificationRow(key, columnSize);
}
}
}

View File

@ -34,7 +34,7 @@ public abstract class Report<I extends QueryItem, H extends ColumnHeader<? super
protected Report(List<H> 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<I extends QueryItem, H extends ColumnHeader<? super
public final void addItem(I item) {
Row<I> 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<I extends QueryItem, H extends ColumnHeader<? super
items.forEach(this::addItem);
}
protected Row<I> createRow(int columnSize) {
return new SingleRow<>(columnSize);
protected Row<I> createRow(String key, int columnSize) {
return new SingleRow<>(key, columnSize);
}
/**

View File

@ -23,8 +23,8 @@ public class TimestampReport extends Report<TimestampQueryItem, TimeIntervalColu
}
@Override
protected TimestampRow createRow(int columnSize) {
return new TimestampRow(columnSize);
protected TimestampRow createRow(String key, int columnSize) {
return new TimestampRow(key, columnSize);
}
/** Builder for {@link TimestampReport}. */

View File

@ -9,8 +9,11 @@ import pro.taskana.monitor.api.reports.item.DetailedMonitorQueryItem;
*/
public class DetailedClassificationRow extends FoldableRow<DetailedMonitorQueryItem> {
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<DetailedMonitorQueryI
}
@Override
Row<DetailedMonitorQueryItem> buildRow(int columnSize) {
return new SingleRow<>(columnSize);
protected Row<DetailedMonitorQueryItem> buildRow(String key, int columnSize) {
return new SingleRow<>(key, columnSize);
}
}

View File

@ -17,12 +17,13 @@ import pro.taskana.monitor.api.reports.item.QueryItem;
*/
public abstract class FoldableRow<I extends QueryItem> extends SingleRow<I> {
private Map<String, Row<I>> foldableRows = new LinkedHashMap<>();
private Function<? super I, String> calcFoldableRowKey;
private int columnSize;
private final Map<String, Row<I>> foldableRows = new LinkedHashMap<>();
private final Function<? super I, String> calcFoldableRowKey;
private final int columnSize;
protected FoldableRow(int columnSize, Function<? super I, String> calcFoldableRowKey) {
super(columnSize);
protected FoldableRow(
String key, int columnSize, Function<? super I, String> calcFoldableRowKey) {
super(key, columnSize);
this.columnSize = columnSize;
this.calcFoldableRowKey = calcFoldableRowKey;
}
@ -39,7 +40,7 @@ public abstract class FoldableRow<I extends QueryItem> extends SingleRow<I> {
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<I extends QueryItem> extends SingleRow<I> {
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<I extends QueryItem> extends SingleRow<I> {
return foldableRows.get(key);
}
abstract Row<I> buildRow(int columnSize);
protected abstract Row<I> buildRow(String key, int columnSize);
@Override
public String toString() {

View File

@ -28,6 +28,8 @@ public interface Row<I extends QueryItem> {
*/
void updateTotalValue(I item);
String getKey();
int getTotalValue();
int[] getCells();

View File

@ -14,8 +14,10 @@ public class SingleRow<I extends QueryItem> implements Row<I> {
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<I extends QueryItem> implements Row<I> {
total += item.getValue();
}
@Override
public String getKey() {
return key;
}
@Override
public final int getTotalValue() {
return total;

View File

@ -9,8 +9,8 @@ import pro.taskana.monitor.api.reports.item.TimestampQueryItem;
*/
public class TimestampRow extends FoldableRow<TimestampQueryItem> {
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<TimestampQueryItem> {
}
@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<TimestampQueryItem> {
*/
public static final class OrgLevel1Row extends FoldableRow<TimestampQueryItem> {
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<TimestampQueryItem> {
}
@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<TimestampQueryItem> {
*/
public static final class OrgLevel2Row extends FoldableRow<TimestampQueryItem> {
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<TimestampQueryItem> {
}
@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<TimestampQueryItem> {
*/
public static final class OrgLevel3Row extends FoldableRow<TimestampQueryItem> {
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<TimestampQueryItem> {
}
@Override
Row<TimestampQueryItem> buildRow(int columnSize) {
return new SingleRow<>(columnSize);
protected Row<TimestampQueryItem> buildRow(String key, int columnSize) {
return new SingleRow<>(key, columnSize);
}
}
}

View File

@ -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<MonitorQueryItem> 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<MonitorQueryItem> 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<MonitorQueryItem> 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<MonitorQueryItem> 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<MonitorQueryItem> preprocessor =
(item) -> {
item.setNumberOfTasks(overrideValue);
return item;
};
// when
report.addItems(Arrays.asList(item, item), preprocessor);
// then
assertThat(report.getRows()).hasSize(1);
Row<MonitorQueryItem> 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<TimeIntervalColumnHeader> 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<MonitorQueryItem> sumRow = report.getSumRow();
assertThat(sumRow.getCells()).isEqualTo(new int[] {0, 0, 0, 0});
assertThat(sumRow.getTotalValue()).isEqualTo(0);
}
@Test
void testInsertItemWhichIsInMultipleHeaderScopes() {
// given
List<TimeIntervalColumnHeader> 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<MonitorQueryItem> 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<MonitorQueryItem> 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<MonitorQueryItem> preprocessor =
@ -187,6 +162,79 @@ class ReportTest {
assertThat(sumRow.getTotalValue()).isEqualTo(overrideValue);
}
@Test
void should_PreProcessItem_When_PreprocessorIsDefinedForBulkInsert() {
// given
int overrideValue = 5;
QueryItemPreprocessor<MonitorQueryItem> preprocessor =
(item) -> {
item.setNumberOfTasks(overrideValue);
return item;
};
// when
report.addItems(Arrays.asList(item, item), preprocessor);
// then
assertThat(report.getRows()).hasSize(1);
Row<MonitorQueryItem> 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<TimeIntervalColumnHeader> 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<MonitorQueryItem> 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<TimeIntervalColumnHeader> 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<MonitorQueryItem> 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<MonitorQueryItem> 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<MonitorQueryItem, TimeIntervalColumnHeader> {
@ -195,4 +243,35 @@ class ReportTest {
super(headerList, rowDesc);
}
}
private static class ReportWithFoldableRow
extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
protected ReportWithFoldableRow(
List<TimeIntervalColumnHeader> columnHeaders, String[] rowDesc) {
super(columnHeaders, rowDesc);
}
@Override
public FoldableTestRow getRow(String key) {
return (FoldableTestRow) super.getRow(key);
}
@Override
protected Row<MonitorQueryItem> createRow(String key, int columnSize) {
return new FoldableTestRow(key, columnSize);
}
}
private static class FoldableTestRow extends FoldableRow<MonitorQueryItem> {
protected FoldableTestRow(String key, int columnSize) {
super(key, columnSize, (item) -> item.getKey().toUpperCase());
}
@Override
protected Row<MonitorQueryItem> buildRow(String key, int columnSize) {
return new SingleRow<>(key, columnSize);
}
}
}

View File

@ -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<ReportRepresentationModel.RowResource> rows =

View File

@ -88,22 +88,22 @@ public class ReportRepresentationModel extends RepresentationModel<ReportReprese
/** Meta Information about this ReportResource. */
public static class MetaInformation {
private static final String TOTAL_DESC = "Total";
private final String name;
private final String date;
private final String[] header;
private final String[] rowDesc;
private final String totalDesc;
public MetaInformation(String name, String date, String[] header, String[] rowDesc) {
public MetaInformation(String name, String date, String[] header, String[] rowDesc, String totalDesc) {
this.name = name;
this.date = date;
this.header = header;
this.rowDesc = rowDesc;
this.totalDesc = totalDesc;
}
public String getTotalDesc() {
return TOTAL_DESC;
return totalDesc;
}
public String getName() {