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<>();
|
||||
private Map<String, ReportRow<Item>> reportRows = new LinkedHashMap<>();
|
||||
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());
|
||||
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) {
|
||||
ReportRow<Item> row = reportRows.computeIfAbsent(item.getKey(), (s) -> createReportRow(columnHeaders.size()));
|
||||
if (columnHeaders.isEmpty()) {
|
||||
|
@ -51,27 +81,7 @@ public abstract class Report<Item extends QueryItem, ColumnHeader extends Report
|
|||
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) {
|
||||
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> {
|
||||
|
||||
String displayName();
|
||||
String getDisplayName();
|
||||
|
||||
boolean fits(Item item);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import pro.taskana.impl.report.Report;
|
|||
public class CategoryReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
||||
|
||||
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 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 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 DetailedClassificationReport(List<TimeIntervalColumnHeader> workbasketLevelReportColumnHeaders) {
|
||||
super(workbasketLevelReportColumnHeaders);
|
||||
super(workbasketLevelReportColumnHeaders, "TASK CLASSIFICATION KEYS");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,7 +4,7 @@ import pro.taskana.TaskState;
|
|||
import pro.taskana.impl.report.ReportColumnHeader;
|
||||
|
||||
/**
|
||||
* TODO.
|
||||
* The TaskStatusColumnHeader represents a column for each {@link TaskState}.
|
||||
*/
|
||||
public class TaskStatusColumnHeader implements ReportColumnHeader<TaskQueryItem> {
|
||||
|
||||
|
@ -15,7 +15,7 @@ public class TaskStatusColumnHeader implements ReportColumnHeader<TaskQueryItem>
|
|||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
public String getDisplayName() {
|
||||
return state.name();
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,6 @@ public class TaskStatusColumnHeader implements ReportColumnHeader<TaskQueryItem>
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return displayName();
|
||||
return getDisplayName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import pro.taskana.TaskState;
|
|||
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> {
|
||||
|
||||
|
@ -19,7 +19,7 @@ public class TaskStatusReport extends Report<TaskQueryItem, TaskStatusColumnHead
|
|||
public TaskStatusReport(List<TaskState> filter) {
|
||||
super((filter != null ? filter.stream() : Arrays.stream(TaskState.values()))
|
||||
.map(TaskStatusColumnHeader::new)
|
||||
.collect(Collectors.toList()));
|
||||
.collect(Collectors.toList()), "DOMAINS");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,11 +35,11 @@ public class TimeIntervalColumnHeader implements ReportColumnHeader<MonitorQuery
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return displayName();
|
||||
return getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
public String getDisplayName() {
|
||||
return "(" + this.lowerAgeLimit + "," + this.upperAgeLimit + ")";
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import pro.taskana.impl.report.Report;
|
|||
public class WorkbasketLevelReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
|
||||
|
||||
public WorkbasketLevelReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
|
||||
super(timeIntervalColumnHeaders);
|
||||
super(timeIntervalColumnHeaders, "WORKBASKET KEYS");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ public class ProvideTaskStatusReportAccTest {
|
|||
builder.append("\n");
|
||||
builder.append(String.format(formatFirstColumnFirstLine, "Domain", "Total"));
|
||||
for (TaskStatusColumnHeader def : columnHeaders) {
|
||||
builder.append(String.format(formatColumnWidth, def.displayName()));
|
||||
builder.append(String.format(formatColumnWidth, def.getDisplayName()));
|
||||
}
|
||||
builder.append("|\n");
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.util.List;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
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.TaskState;
|
||||
import pro.taskana.rest.resource.ReportResource;
|
||||
import pro.taskana.rest.resource.mapper.ReportMapper;
|
||||
|
||||
/**
|
||||
* Controller for all monitoring endpoints.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(path = "/v1/monitor", produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
@RequestMapping(path = "/v1/monitor", produces = "application/hal+json")
|
||||
public class MonitorController {
|
||||
|
||||
@Autowired
|
||||
private TaskMonitorService taskMonitorService;
|
||||
|
||||
@Autowired
|
||||
private ReportMapper reportMapper;
|
||||
|
||||
@GetMapping(path = "/countByState")
|
||||
@Transactional(readOnly = true, rollbackFor = Exception.class)
|
||||
public ResponseEntity<?> getTaskcountForState(
|
||||
|
@ -65,8 +69,9 @@ public class MonitorController {
|
|||
|
||||
@GetMapping(path = "/taskStatusReport")
|
||||
@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) {
|
||||
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.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 pro.taskana.ClassificationService;
|
||||
|
@ -94,11 +91,6 @@ public class RestConfiguration {
|
|||
return b;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder jacksonBuilder) {
|
||||
return jacksonBuilder.build().setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
|
||||
}
|
||||
|
||||
//Needed for injection into jackson deserilizer.
|
||||
@Bean
|
||||
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