KPIController.java
/*
* Copyright 2020 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gringlobal.api.v1.impl;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.genesys.blocks.model.JsonViews;
import org.gringlobal.api.exception.NotFoundElement;
import org.gringlobal.api.v1.ApiBaseController;
import org.gringlobal.api.v1.Pagination;
import org.gringlobal.model.kpi.Dimension;
import org.gringlobal.model.kpi.Execution;
import org.gringlobal.model.kpi.ExecutionRun;
import org.gringlobal.model.kpi.KPIParameter;
import org.gringlobal.model.kpi.Observation;
import org.gringlobal.service.KPIService;
import org.gringlobal.service.KPIService.ExecutionDetails;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController("kpiApi1")
@RequestMapping(value = { KPIController.API_URL })
@PreAuthorize("isAuthenticated()")
@Tag(name = "KPI")
public class KPIController extends ApiBaseController{
/** The Constant API_URL. */
public static final String API_URL = ApiBaseController.APIv1_BASE + "/kpi";
@Autowired
private KPIService kpiService;
/**
* First declare the KPI parameters: e.g. `Accession where `
*
* @param parameter the parameter
* @return
*/
@PostMapping(value = "/parameters/save")
public KPIParameter saveParameter(@RequestBody KPIParameter parameter) {
return kpiService.save(parameter);
}
@DeleteMapping(value = "/parameters/{name:.+}")
public KPIParameter deleteParameter(@PathVariable String name) {
return kpiService.delete(kpiService.getParameter(name));
}
@GetMapping(value="/parameters")
public Page<KPIParameter> listParameters(@ParameterObject final Pagination page) {
return kpiService.listParameters(page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE));
}
@GetMapping(value="/dimensions/{name:.+}")
public Dimension<?> getDimension(@PathVariable String name) {
return kpiService.getDimension(name);
}
/**
* Then declare the KPI dimensions: e.g. `FaoInstitute#code where accessionCount gt 0`
* Dimensions provide query parameters to KPI execution
*
* @param dimension the parameter
* @return
*/
@PostMapping(value = "/dimensions/save")
public Dimension<?> saveDimension(@RequestBody Dimension<?> dimension) {
return kpiService.save(dimension);
}
@DeleteMapping(value = "/dimensions/{name:.+}")
public Dimension<?> deleteDimension(@PathVariable String name) {
return kpiService.delete(kpiService.getDimension(name));
}
@JsonView(JsonViews.Minimal.class)
@GetMapping(value="/dimensions")
public Page<Dimension<?>> listDimensions(@ParameterObject final Pagination page) {
return kpiService.listDimensions(page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE));
}
/**
* Declare execution with a {@link KPIParameter} and one or more {@link Dimension}
*
* @param execution the execution
* @return
*/
@PostMapping(value = "/executions/save")
public Execution saveExecution(@RequestBody Execution execution) {
return kpiService.save(execution);
}
@DeleteMapping(value = "/executions/{name:.+}")
public Execution deleteExecution(@PathVariable String name) {
return kpiService.delete(kpiService.getExecution(name));
}
@JsonView(JsonViews.Minimal.class)
@GetMapping(value="/executions")
public Page<Execution> listExecution(@ParameterObject final Pagination page) {
return kpiService.listExecutions(page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE));
}
@PostMapping(value = "/executions/{name:.+}/execute")
public ExecutionRun runExecution(@PathVariable String name) {
return kpiService.executeAndSave(kpiService.getExecution(name));
}
@PostMapping(value = "/executions/{name:.+}/purgeRuns")
public long purgeExecutionRuns(@PathVariable String name) {
long deleted = kpiService.purgeExecutionRuns(kpiService.getExecution(name));
System.err.println("Done deleting!");
return deleted;
}
/**
* Execution details
*/
@JsonView(JsonViews.Minimal.class)
@GetMapping(value = "/executions/{name:.+}")
public ExecutionDetails executionDetails(@PathVariable String name) {
Execution execution = kpiService.loadExecution(name);
return ExecutionDetails.from(execution, kpiService.findLastExecutionRun(execution), kpiService.listExecutionRuns(execution, PageRequest.of(0, 10)));
}
/**
* Execution info
*/
@JsonView(JsonViews.Minimal.class)
@GetMapping(value = "/executions/{name:.+}/info")
public Execution executionInfo(@PathVariable String name) {
return kpiService.getExecution(name);
}
@GetMapping(value = "/executions/{name:.+}/runs")
public Page<ExecutionRun> executionRuns(final @PathVariable String name, @ParameterObject final Pagination page) {
return kpiService.listExecutionRuns(kpiService.getExecution(name), page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE));
}
@GetMapping(value = "/executions/{name:.+}/run")
public ExecutionRun executionRunByDate(final @PathVariable String name,
@RequestParam(value="date", required = true) @DateTimeFormat(pattern="yyyy-MM-dd") final LocalDate date) {
return kpiService.findExecutionRunByDate(kpiService.getExecution(name), date);
}
@GetMapping(value = "/executions/{name:.+}/runs/{runId}")
public ExecutionRun executionRun(final @PathVariable String name, @PathVariable final long runId) {
ExecutionRun run = kpiService.getExecutionRun(runId);
if (! StringUtils.equals(run.getExecution().getName(), name)) {
throw new NotFoundElement("No run " + runId + " for execution " + name);
}
return run;
}
@DeleteMapping(value = "/executions/{name:.+}/runs/{runId}")
public ExecutionRun deleteExecutionRun(final @PathVariable String name, final @PathVariable long runId) {
var executionRun = kpiService.getExecutionRun(runId);
if (! StringUtils.equals(executionRun.getExecution().getName(), name)) {
throw new NotFoundElement("No run " + runId + " for execution " + name);
}
return kpiService.delete(executionRun);
}
@PostMapping(value = "/executions/{name:.+}/diff")
public SortedMap<LocalDate, List<Observation>> executionRuns(
final @PathVariable String name,
@RequestParam(value="days", required = false) final Integer days,
@RequestParam(value="from", required = false) @DateTimeFormat(pattern="yyyy-MM-dd") LocalDate from,
@RequestParam(value="to", required = false) @DateTimeFormat(pattern="yyyy-MM-dd") LocalDate to,
@RequestBody(required = false) final Map<String, Set<String>> keys
) throws Exception {
Execution execution = kpiService.getExecution(name);
if (execution == null) {
throw new NotFoundElement("No execution " + name);
}
if (days != null) {
LocalDate startDate = LocalDate.now();
if (to != null) {
startDate = to;
} else {
to = startDate;
}
startDate = startDate.minusDays(days);
from = startDate;
}
return kpiService.calculateRunDiff(execution, from, to, keys);
}
@PostMapping(value = "/executions/{name}/runs")
public SortedMap<LocalDate, List<Observation>> executionRunsObservations(final @PathVariable String name, final @RequestBody KPIService.ExecutionRunsRequest runsRequest) {
Execution execution = kpiService.getExecution(name);
if (execution == null) {
throw new NotFoundElement("No execution " + name);
}
return kpiService.findExecutionRuns(execution, runsRequest);
}
@GetMapping(value = "/executions/{name}/runs/group")
public List<KPIService.GroupedRunObservations> getObservationsGroupedByDimension(@PathVariable String name,
@RequestParam(value="dimensionName") String dimensionName,
@RequestParam(value="toDate", required = false) @DateTimeFormat(pattern="yyyy-MM-dd") LocalDate toDate,
@RequestParam(value="maxRuns", required = false) Integer maxRuns) {
Execution execution = kpiService.getExecution(name);
if (execution == null) {
throw new NotFoundElement("No execution " + name);
}
return kpiService.getObservationsGroupedByDimension(execution, dimensionName, toDate, maxRuns);
}
}