TSK-395 created REST interface for TaskStatusReport
This commit is contained in:
parent
bb4d5adf35
commit
02fc6b3cd3
|
|
@ -20,12 +20,42 @@ public abstract class Report<Item extends QueryItem, ColumnHeader extends Report
|
||||||
protected List<ColumnHeader> columnHeaders = new ArrayList<>();
|
protected List<ColumnHeader> columnHeaders = new ArrayList<>();
|
||||||
private Map<String, ReportRow<Item>> reportRows = new LinkedHashMap<>();
|
private Map<String, ReportRow<Item>> reportRows = new LinkedHashMap<>();
|
||||||
private ReportRow<Item> sumRow;
|
private ReportRow<Item> sumRow;
|
||||||
|
private String rowDesc;
|
||||||
|
|
||||||
public Report(List<ColumnHeader> columnHeaders) {
|
public Report(List<ColumnHeader> columnHeaders, String rowDesc) {
|
||||||
|
this.rowDesc = rowDesc;
|
||||||
sumRow = new ReportRow<>(columnHeaders.size());
|
sumRow = new ReportRow<>(columnHeaders.size());
|
||||||
this.columnHeaders.addAll(columnHeaders);
|
this.columnHeaders.addAll(columnHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final Map<String, ReportRow<Item>> getReportRows() {
|
||||||
|
return reportRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ReportRow<Item> getSumRow() {
|
||||||
|
return sumRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final List<ColumnHeader> getColumnHeaders() {
|
||||||
|
return columnHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getRowDesc() {
|
||||||
|
return rowDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReportRow<Item> getRow(String key) {
|
||||||
|
return reportRows.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Set<String> rowTitles() {
|
||||||
|
return reportRows.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int rowSize() {
|
||||||
|
return reportRows.size();
|
||||||
|
}
|
||||||
|
|
||||||
public final void addItem(Item item) {
|
public final void addItem(Item item) {
|
||||||
ReportRow<Item> row = reportRows.computeIfAbsent(item.getKey(), (s) -> createReportRow(columnHeaders.size()));
|
ReportRow<Item> row = reportRows.computeIfAbsent(item.getKey(), (s) -> createReportRow(columnHeaders.size()));
|
||||||
if (columnHeaders.isEmpty()) {
|
if (columnHeaders.isEmpty()) {
|
||||||
|
|
@ -51,27 +81,7 @@ public abstract class Report<Item extends QueryItem, ColumnHeader extends Report
|
||||||
items.forEach(this::addItem);
|
items.forEach(this::addItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReportRow<Item> getRow(String key) {
|
|
||||||
return reportRows.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final ReportRow<Item> getSumRow() {
|
|
||||||
return sumRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<String> rowTitles() {
|
|
||||||
return reportRows.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final int rowSize() {
|
|
||||||
return reportRows.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ReportRow<Item> createReportRow(int columnSize) {
|
protected ReportRow<Item> createReportRow(int columnSize) {
|
||||||
return new ReportRow<>(columnSize);
|
return new ReportRow<>(columnSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ColumnHeader> getColumnHeaders() {
|
|
||||||
return columnHeaders;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ package pro.taskana.impl.report;
|
||||||
*/
|
*/
|
||||||
public interface ReportColumnHeader<Item extends QueryItem> {
|
public interface ReportColumnHeader<Item extends QueryItem> {
|
||||||
|
|
||||||
String displayName();
|
String getDisplayName();
|
||||||
|
|
||||||
boolean fits(Item item);
|
boolean fits(Item item);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import pro.taskana.impl.report.Report;
|
||||||
public class CategoryReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
public class CategoryReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
||||||
|
|
||||||
public CategoryReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
|
public CategoryReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
|
||||||
super(timeIntervalColumnHeaders);
|
super(timeIntervalColumnHeaders, "CLASSIFICATION CATEGORIES");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import pro.taskana.impl.report.Report;
|
||||||
public class ClassificationReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
public class ClassificationReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
||||||
|
|
||||||
public ClassificationReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
|
public ClassificationReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
|
||||||
super(timeIntervalColumnHeaders);
|
super(timeIntervalColumnHeaders, "CLASSIFICATION KEYS");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,6 @@ import pro.taskana.impl.report.Report;
|
||||||
public class CustomFieldValueReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
public class CustomFieldValueReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
||||||
|
|
||||||
public CustomFieldValueReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
|
public CustomFieldValueReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
|
||||||
super(timeIntervalColumnHeaders);
|
super(timeIntervalColumnHeaders, "CUSTOM FIELDS");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import pro.taskana.impl.report.Report;
|
||||||
public class DetailedClassificationReport extends Report<DetailedMonitorQueryItem, TimeIntervalColumnHeader> {
|
public class DetailedClassificationReport extends Report<DetailedMonitorQueryItem, TimeIntervalColumnHeader> {
|
||||||
|
|
||||||
public DetailedClassificationReport(List<TimeIntervalColumnHeader> workbasketLevelReportColumnHeaders) {
|
public DetailedClassificationReport(List<TimeIntervalColumnHeader> workbasketLevelReportColumnHeaders) {
|
||||||
super(workbasketLevelReportColumnHeaders);
|
super(workbasketLevelReportColumnHeaders, "TASK CLASSIFICATION KEYS");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import pro.taskana.TaskState;
|
||||||
import pro.taskana.impl.report.ReportColumnHeader;
|
import pro.taskana.impl.report.ReportColumnHeader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO.
|
* The TaskStatusColumnHeader represents a column for each {@link TaskState}.
|
||||||
*/
|
*/
|
||||||
public class TaskStatusColumnHeader implements ReportColumnHeader<TaskQueryItem> {
|
public class TaskStatusColumnHeader implements ReportColumnHeader<TaskQueryItem> {
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ public class TaskStatusColumnHeader implements ReportColumnHeader<TaskQueryItem>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String displayName() {
|
public String getDisplayName() {
|
||||||
return state.name();
|
return state.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,6 +26,6 @@ public class TaskStatusColumnHeader implements ReportColumnHeader<TaskQueryItem>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return displayName();
|
return getDisplayName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import pro.taskana.TaskState;
|
||||||
import pro.taskana.impl.report.Report;
|
import pro.taskana.impl.report.Report;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO.
|
* The TaskStatusReport displays the amount of tasks, differentiated by their state and grouped by domain.
|
||||||
*/
|
*/
|
||||||
public class TaskStatusReport extends Report<TaskQueryItem, TaskStatusColumnHeader> {
|
public class TaskStatusReport extends Report<TaskQueryItem, TaskStatusColumnHeader> {
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@ public class TaskStatusReport extends Report<TaskQueryItem, TaskStatusColumnHead
|
||||||
public TaskStatusReport(List<TaskState> filter) {
|
public TaskStatusReport(List<TaskState> filter) {
|
||||||
super((filter != null ? filter.stream() : Arrays.stream(TaskState.values()))
|
super((filter != null ? filter.stream() : Arrays.stream(TaskState.values()))
|
||||||
.map(TaskStatusColumnHeader::new)
|
.map(TaskStatusColumnHeader::new)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()), "DOMAINS");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,11 @@ public class TimeIntervalColumnHeader implements ReportColumnHeader<MonitorQuery
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return displayName();
|
return getDisplayName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String displayName() {
|
public String getDisplayName() {
|
||||||
return "(" + this.lowerAgeLimit + "," + this.upperAgeLimit + ")";
|
return "(" + this.lowerAgeLimit + "," + this.upperAgeLimit + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import pro.taskana.impl.report.Report;
|
||||||
public class WorkbasketLevelReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
public class WorkbasketLevelReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
||||||
|
|
||||||
public WorkbasketLevelReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
|
public WorkbasketLevelReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
|
||||||
super(timeIntervalColumnHeaders);
|
super(timeIntervalColumnHeaders, "WORKBASKET KEYS");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ public class ProvideTaskStatusReportAccTest {
|
||||||
builder.append("\n");
|
builder.append("\n");
|
||||||
builder.append(String.format(formatFirstColumnFirstLine, "Domain", "Total"));
|
builder.append(String.format(formatFirstColumnFirstLine, "Domain", "Total"));
|
||||||
for (TaskStatusColumnHeader def : columnHeaders) {
|
for (TaskStatusColumnHeader def : columnHeaders) {
|
||||||
builder.append(String.format(formatColumnWidth, def.displayName()));
|
builder.append(String.format(formatColumnWidth, def.getDisplayName()));
|
||||||
}
|
}
|
||||||
builder.append("|\n");
|
builder.append("|\n");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
@ -14,17 +13,22 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import pro.taskana.TaskMonitorService;
|
import pro.taskana.TaskMonitorService;
|
||||||
import pro.taskana.TaskState;
|
import pro.taskana.TaskState;
|
||||||
|
import pro.taskana.rest.resource.ReportResource;
|
||||||
|
import pro.taskana.rest.resource.mapper.ReportMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for all monitoring endpoints.
|
* Controller for all monitoring endpoints.
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(path = "/v1/monitor", produces = {MediaType.APPLICATION_JSON_VALUE})
|
@RequestMapping(path = "/v1/monitor", produces = "application/hal+json")
|
||||||
public class MonitorController {
|
public class MonitorController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TaskMonitorService taskMonitorService;
|
private TaskMonitorService taskMonitorService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ReportMapper reportMapper;
|
||||||
|
|
||||||
@GetMapping(path = "/countByState")
|
@GetMapping(path = "/countByState")
|
||||||
@Transactional(readOnly = true, rollbackFor = Exception.class)
|
@Transactional(readOnly = true, rollbackFor = Exception.class)
|
||||||
public ResponseEntity<?> getTaskcountForState(
|
public ResponseEntity<?> getTaskcountForState(
|
||||||
|
|
@ -65,8 +69,9 @@ public class MonitorController {
|
||||||
|
|
||||||
@GetMapping(path = "/taskStatusReport")
|
@GetMapping(path = "/taskStatusReport")
|
||||||
@Transactional(readOnly = true, rollbackFor = Exception.class)
|
@Transactional(readOnly = true, rollbackFor = Exception.class)
|
||||||
public ResponseEntity<?> getTaskStatusReport(@RequestParam(required = false) List<String> domains,
|
public ResponseEntity<ReportResource> getTaskStatusReport(@RequestParam(required = false) List<String> domains,
|
||||||
@RequestParam(required = false) List<TaskState> states) {
|
@RequestParam(required = false) List<TaskState> states) {
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(taskMonitorService.getTaskStatusReport(domains, states));
|
return ResponseEntity.status(HttpStatus.OK)
|
||||||
|
.body(reportMapper.toResource(taskMonitorService.getTaskStatusReport(domains, states), domains, states));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,6 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
|
||||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
|
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
|
||||||
|
|
||||||
import pro.taskana.ClassificationService;
|
import pro.taskana.ClassificationService;
|
||||||
|
|
@ -94,11 +91,6 @@ public class RestConfiguration {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder jacksonBuilder) {
|
|
||||||
return jacksonBuilder.build().setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Needed for injection into jackson deserilizer.
|
//Needed for injection into jackson deserilizer.
|
||||||
@Bean
|
@Bean
|
||||||
public HandlerInstantiator handlerInstantiator(ApplicationContext context) {
|
public HandlerInstantiator handlerInstantiator(ApplicationContext context) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package pro.taskana.rest.resource;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.hateoas.ResourceSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource class for {@link pro.taskana.impl.report.Report}.
|
||||||
|
*/
|
||||||
|
public class ReportResource extends ResourceSupport {
|
||||||
|
|
||||||
|
private MetaInformation meta;
|
||||||
|
|
||||||
|
private Map<String, RowResource> rows;
|
||||||
|
|
||||||
|
private RowResource sumRow;
|
||||||
|
|
||||||
|
public ReportResource(MetaInformation meta, Map<String, RowResource> rows, RowResource sumRow) {
|
||||||
|
this.meta = meta;
|
||||||
|
this.rows = rows;
|
||||||
|
this.sumRow = sumRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetaInformation getMeta() {
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, RowResource> getRows() {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RowResource getSumRow() {
|
||||||
|
return sumRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Meta Information about this ReportResource.
|
||||||
|
*/
|
||||||
|
public static class MetaInformation {
|
||||||
|
|
||||||
|
private static final String TOTAL_DESC = "Total";
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String date;
|
||||||
|
private String[] header;
|
||||||
|
private String rowDesc;
|
||||||
|
|
||||||
|
public MetaInformation(String name, String date, String[] header, String rowDesc) {
|
||||||
|
this.name = name;
|
||||||
|
this.date = date;
|
||||||
|
this.header = header;
|
||||||
|
this.rowDesc = rowDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTotalDesc() {
|
||||||
|
return TOTAL_DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRowDesc() {
|
||||||
|
return rowDesc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource class for {@link pro.taskana.impl.report.ReportRow}.
|
||||||
|
*/
|
||||||
|
public static class RowResource {
|
||||||
|
|
||||||
|
private Map<String, Integer> cells;
|
||||||
|
private int total;
|
||||||
|
|
||||||
|
public RowResource(Map<String, Integer> cells, int total) {
|
||||||
|
this.cells = cells;
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Integer> getCells() {
|
||||||
|
return cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotal() {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package pro.taskana.rest.resource.mapper;
|
||||||
|
|
||||||
|
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||||
|
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import pro.taskana.TaskState;
|
||||||
|
import pro.taskana.impl.report.QueryItem;
|
||||||
|
import pro.taskana.impl.report.Report;
|
||||||
|
import pro.taskana.impl.report.ReportColumnHeader;
|
||||||
|
import pro.taskana.impl.report.ReportRow;
|
||||||
|
import pro.taskana.impl.report.impl.TaskStatusReport;
|
||||||
|
import pro.taskana.rest.MonitorController;
|
||||||
|
import pro.taskana.rest.resource.ReportResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms any {@link Report} into its {@link ReportResource}.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ReportMapper {
|
||||||
|
|
||||||
|
public ReportResource toResource(TaskStatusReport report, List<String> domains, List<TaskState> states) {
|
||||||
|
ReportResource resource = toResource(report);
|
||||||
|
resource.add(
|
||||||
|
linkTo(methodOn(MonitorController.class).getTaskStatusReport(domains, states))
|
||||||
|
.withSelfRel().expand());
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <I extends QueryItem, H extends ReportColumnHeader<? super I>> ReportResource toResource(
|
||||||
|
Report<I, H> report) {
|
||||||
|
String[] header = report.getColumnHeaders().stream()
|
||||||
|
.map(ReportColumnHeader::getDisplayName)
|
||||||
|
.toArray(String[]::new);
|
||||||
|
ReportResource.MetaInformation meta = new ReportResource.MetaInformation(
|
||||||
|
report.getClass().getSimpleName(),
|
||||||
|
Instant.now().toString(),
|
||||||
|
header,
|
||||||
|
report.getRowDesc());
|
||||||
|
|
||||||
|
// iterate over each ReportRow and transform it to a RowResource while keeping the domain key.
|
||||||
|
Map<String, ReportResource.RowResource> rows = report.getReportRows().entrySet().stream()
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, i -> transformRow(i.getValue(), header)));
|
||||||
|
|
||||||
|
ReportResource.RowResource sumRow = transformRow(report.getSumRow(), header);
|
||||||
|
|
||||||
|
return new ReportResource(meta, rows, sumRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <I extends QueryItem> ReportResource.RowResource transformRow(ReportRow<I> row, String[] header) {
|
||||||
|
Map<String, Integer> result = new HashMap<>();
|
||||||
|
int[] cells = row.getCells();
|
||||||
|
for (int i = 0; i < cells.length; i++) {
|
||||||
|
result.put(header[i], cells[i]);
|
||||||
|
}
|
||||||
|
return new ReportResource.RowResource(result, row.getTotalValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue