Commit d63fa76e authored by Jean-Baptiste Nizet's avatar Jean-Baptiste Nizet Committed by Cédric Exbrayat
Browse files

chore: upgrade spring boot and other dependencies, switch to springdoc

springfox is unmaintained, and doesn't work with Spring Boot, so this commit replaces it with springdoc
parent cbc3024d
......@@ -10,11 +10,11 @@ buildscript {
plugins {
java
jacoco
id("org.springframework.boot") version "2.5.4"
id("com.gorylenko.gradle-git-properties") version "2.3.1"
id("org.springframework.boot") version "2.6.4"
id("com.gorylenko.gradle-git-properties") version "2.4.0"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
id("org.sonarqube")
id("org.owasp.dependencycheck") version "6.0.3"
id("org.owasp.dependencycheck") version "7.0.0"
}
java {
......@@ -91,7 +91,7 @@ tasks {
}
}
extra["springCloudVersion"] = "2020.0.3"
extra["springCloudVersion"] = "2021.0.1"
dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
......@@ -110,19 +110,17 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
// Elasticsearch
implementation("org.elasticsearch:elasticsearch:7.13.2")
implementation("org.elasticsearch.client:elasticsearch-rest-high-level-client:7.13.2")
implementation("org.elasticsearch:elasticsearch")
implementation("org.elasticsearch.client:elasticsearch-rest-high-level-client")
// Swagger
implementation("io.swagger:swagger-annotations:1.5.21")
implementation("io.springfox:springfox-swagger2:2.9.2")
implementation("io.springfox:springfox-swagger-ui:2.9.2")
implementation("org.springdoc:springdoc-openapi-ui:1.6.6")
// Others
implementation("com.google.guava:guava:27.0.1-jre")
implementation("com.opencsv:opencsv:4.4")
implementation("com.google.guava:guava:31.1-jre")
implementation("com.opencsv:opencsv:5.6")
// Test dependencies
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.jsoup:jsoup:1.14.2")
testImplementation("org.jsoup:jsoup:1.14.3")
}
package fr.inra.urgi.faidare.api.brapi.v1;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableSet;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiCall;
import fr.inra.urgi.faidare.domain.brapi.v1.response.BrapiListResponse;
import fr.inra.urgi.faidare.domain.criteria.base.PaginationCriteriaImpl;
import fr.inra.urgi.faidare.domain.data.CallVO;
import fr.inra.urgi.faidare.domain.response.ApiResponseFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springdoc.webmvc.api.OpenApiWebMvcResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.service.ApiDescription;
import springfox.documentation.service.Documentation;
import springfox.documentation.spring.web.DocumentationCache;
import springfox.documentation.spring.web.plugins.Docket;
import javax.validation.Valid;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author gcornut
*/
@Api(tags = {"Breeding API"}, description = "BrAPI endpoint")
@Tag(name = "Breeding API", description = "BrAPI endpoint")
@RestController
public class CallsController {
private static final String BRAPI_PATH = "/brapi/v1/";
......@@ -39,28 +42,28 @@ public class CallsController {
"1.1",
"1.2"
);
private final OpenApiWebMvcResource openApiResource;
private final ObjectMapper objectMapper;
private List<BrapiCall> implementedCalls;
private AtomicReference<List<BrapiCall>> implementedCalls = new AtomicReference<>(null);
private final DocumentationCache documentationCache;
@Autowired
public CallsController(DocumentationCache documentationCache) {
this.documentationCache = documentationCache;
public CallsController(OpenApiWebMvcResource openApiResource, ObjectMapper objectMapper) {
this.openApiResource = openApiResource;
this.objectMapper = objectMapper;
}
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Calls/Calls.md
*/
@ApiOperation("List implemented Breeding API calls")
@Operation(summary = "List implemented Breeding API calls")
@GetMapping("/brapi/v1/calls")
public BrapiListResponse<BrapiCall> calls(@Valid PaginationCriteriaImpl criteria) {
if (implementedCalls == null) {
implementedCalls = swaggerToBrapiCalls();
public BrapiListResponse<BrapiCall> calls(@Valid PaginationCriteriaImpl criteria, HttpServletRequest request) throws JsonProcessingException {
if (implementedCalls.get() == null) {
implementedCalls.set(swaggerToBrapiCalls(request));
}
return ApiResponseFactory.createSubListResponse(
criteria.getPageSize(), criteria.getPage(), implementedCalls
criteria.getPageSize(), criteria.getPage(), implementedCalls.get()
);
}
......@@ -70,39 +73,25 @@ public class CallsController {
* This must be done after swagger has time to generate the API
* documentation and thus can't be done in this class constructor
*/
private List<BrapiCall> swaggerToBrapiCalls() {
Documentation apiDocumentation = this.documentationCache.documentationByGroup(Docket.DEFAULT_GROUP_NAME);
// Get all endpoints
return apiDocumentation.getApiListings().values().stream()
.flatMap(endpointListing -> endpointListing.getApis().stream())
// Only with BrAPI path
.filter(endpointDescription -> endpointDescription.getPath().startsWith(BRAPI_PATH))
// Group by endpoint path (ex: /brapi/v1/phenotype => [GET, POST, ...])
.collect(Collectors.groupingBy(ApiDescription::getPath))
.entrySet().stream()
// Convert to BrAPI call
.map(endpointGroup -> {
String path = endpointGroup.getKey();
List<ApiDescription> endpoints = endpointGroup.getValue();
// BrAPI call path should not include the base BrAPI path
@SuppressWarnings("unchecked")
private List<BrapiCall> swaggerToBrapiCalls(HttpServletRequest request) throws JsonProcessingException {
String json = openApiResource.openapiJson(request, "/v3/api-docs", Locale.ENGLISH);
Map<String, Object> map = objectMapper.readValue(json,
new TypeReference<Map<String, Object>>() {});
Map<String, Object> pathMap = (Map<String, Object>) map.get("paths");
return pathMap.entrySet().stream()
.filter(entry -> entry.getKey().startsWith(BRAPI_PATH))
.map(entry -> {
String path = entry.getKey();
Map<String, Object> methodMap = (Map<String, Object>) entry.getValue();
Set<String> methods = methodMap.keySet().stream().map(String::toUpperCase).collect(Collectors.toSet());
CallVO call = new CallVO(path.replace(BRAPI_PATH, ""));
// List every endpoint for current path
Set<String> methods = endpoints.stream()
// List all operations for each endpoint
.flatMap(endpointDescription -> endpointDescription.getOperations().stream())
// List all methods
.map(operation -> operation.getMethod().toString())
.collect(Collectors.toSet());
call.setMethods(methods);
return call;
})
// Sort by call name
.sorted(Comparator.comparing(CallVO::getCall))
.collect(Collectors.toList());
}
}
package fr.inra.urgi.faidare.api.brapi.v1;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import java.util.List;
import javax.validation.Valid;
import fr.inra.urgi.faidare.api.NotFoundException;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiGermplasm;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiGermplasmAttributeValueList;
......@@ -18,19 +23,19 @@ import fr.inra.urgi.faidare.domain.response.PaginatedList;
import fr.inra.urgi.faidare.domain.response.Pagination;
import fr.inra.urgi.faidare.repository.es.GermplasmAttributeRepository;
import fr.inra.urgi.faidare.service.es.GermplasmService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@Api(tags = {"Breeding API"}, description = "BrAPI endpoint")
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "Breeding API", description = "BrAPI endpoint")
@RestController
public class GermplasmController {
......@@ -48,7 +53,7 @@ public class GermplasmController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Germplasm/GermplasmDetailsByGermplasmDbId.md
*/
@ApiOperation("Get germplasm by id")
@Operation(summary = "Get germplasm by id")
@GetMapping("/brapi/v1/germplasm/{germplasmDbId}")
public BrapiResponse<BrapiGermplasm> getGermplasm(@PathVariable String germplasmDbId) {
LOGGER.debug("germplasmDbId = " + germplasmDbId);
......@@ -59,7 +64,7 @@ public class GermplasmController {
return ApiResponseFactory.createSingleObjectResponse(germplasm, null);
}
@ApiOperation("List germplasm")
@Operation(summary = "List germplasm")
@GetMapping("/brapi/v1/germplasm")
public BrapiListResponse<? extends BrapiGermplasm> listGermplasm(
@Valid PaginationCriteriaImpl paginationCriteria
......@@ -73,7 +78,7 @@ public class GermplasmController {
/**
* @link https://brapi.docs.apiary.io/#reference/germplasm/germplasm/get-germplasm-mcpd-by-germplasmdbid
*/
@ApiOperation("Get germplasm mcpd by id")
@Operation(summary = "Get germplasm mcpd by id")
@GetMapping("/brapi/v1/germplasm/{germplasmDbId}/mcpd")
public BrapiResponse<GermplasmMcpdVO> getGermplasmMcpd(@PathVariable String germplasmDbId) {
LOGGER.debug("germplasmDbId = " + germplasmDbId);
......@@ -88,7 +93,7 @@ public class GermplasmController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Germplasm/GermplasmSearchGET.md
*/
@ApiOperation("Search germplasm")
@Operation(summary = "Search germplasm")
@GetMapping(value = "/brapi/v1/germplasm-search")
public BrapiListResponse<? extends BrapiGermplasm> searchGermplasm(
@Valid GermplasmGETSearchCriteria criteria
......@@ -99,7 +104,7 @@ public class GermplasmController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Germplasm/GermplasmSearchPOST.md
*/
@ApiOperation("Search germplasm")
@Operation(summary = "Search germplasm")
@PostMapping(value = "/brapi/v1/germplasm-search", consumes = APPLICATION_JSON_VALUE)
public BrapiListResponse<? extends BrapiGermplasm> searchGermplasm(
@Valid @RequestBody(required = false) GermplasmPOSTSearchCriteria criteria
......@@ -116,7 +121,7 @@ public class GermplasmController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/GermplasmAttributes/GermplasmAttributeValuesByGermplasmDbId.md
*/
@ApiOperation("List germplasm attributes")
@Operation(summary = "List germplasm attributes")
@GetMapping("/brapi/v1/germplasm/{germplasmDbId}/attributes")
public BrapiResponse<BrapiGermplasmAttributeValueList> listGermplasmAttributes(
@PathVariable String germplasmDbId,
......@@ -139,7 +144,7 @@ public class GermplasmController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/GermplasmAttributes/GermplasmAttributeValuesByGermplasmDbId.md
*/
@ApiOperation("Get germplasm pedigree")
@Operation(summary = "Get germplasm pedigree")
@GetMapping("/brapi/v1/germplasm/{germplasmDbId}/pedigree")
public BrapiResponse<BrapiPedigree> getPedigree(
@PathVariable String germplasmDbId
......@@ -151,7 +156,7 @@ public class GermplasmController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Germplasm/Germplasm_GermplasmDbId_Progeny_GET.yaml
*/
@ApiOperation("Get germplasm progeny")
@Operation(summary = "Get germplasm progeny")
@GetMapping("/brapi/v1/germplasm/{germplasmDbId}/progeny")
public BrapiResponse<BrapiProgeny> getProgeny(
@PathVariable String germplasmDbId
......
package fr.inra.urgi.faidare.api.brapi.v1;
import javax.validation.Valid;
import fr.inra.urgi.faidare.api.NotFoundException;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiLocation;
import fr.inra.urgi.faidare.domain.brapi.v1.response.BrapiListResponse;
......@@ -8,19 +10,17 @@ import fr.inra.urgi.faidare.domain.criteria.LocationCriteria;
import fr.inra.urgi.faidare.domain.response.ApiResponseFactory;
import fr.inra.urgi.faidare.domain.response.PaginatedList;
import fr.inra.urgi.faidare.repository.es.LocationRepository;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
/**
* @author gcornut
*/
@Api(tags = {"Breeding API"}, description = "BrAPI endpoint")
@Tag(name = "Breeding API", description = "BrAPI endpoint")
@RestController
public class LocationController {
......@@ -34,7 +34,7 @@ public class LocationController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Locations/LocationDetails.md
*/
@ApiOperation("Get location")
@Operation(summary = "Get location")
@GetMapping("/brapi/v1/locations/{locationDbId}")
public BrapiResponse<BrapiLocation> getLocation(@PathVariable String locationDbId) {
BrapiLocation location = repository.getById(locationDbId);
......@@ -47,7 +47,7 @@ public class LocationController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Locations/ListLocations.md
*/
@ApiOperation("List locations")
@Operation(summary = "List locations")
@GetMapping("/brapi/v1/locations")
public BrapiListResponse<? extends BrapiLocation> listLocations(
@Valid LocationCriteria criteria
......
package fr.inra.urgi.faidare.api.brapi.v1;
import java.util.List;
import javax.validation.Valid;
import fr.inra.urgi.faidare.api.NotFoundException;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiObservationVariable;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiOntology;
......@@ -9,22 +12,19 @@ import fr.inra.urgi.faidare.domain.criteria.ObservationVariableCriteria;
import fr.inra.urgi.faidare.domain.criteria.base.PaginationCriteriaImpl;
import fr.inra.urgi.faidare.domain.response.ApiResponseFactory;
import fr.inra.urgi.faidare.repository.file.CropOntologyRepository;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
/**
* @author gcornut
*/
@Api(tags = {"Breeding API"}, description = "BrAPI endpoint")
@Tag(name = "Breeding API", description = "BrAPI endpoint")
@RestController
public class ObservationVariableController {
......@@ -38,7 +38,7 @@ public class ObservationVariableController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/ObservationVariables/VariableDetails.md
*/
@ApiOperation("Get variable")
@Operation(summary = "Get variable")
@GetMapping("/brapi/v1/variables/{observationVariableDbId}")
public BrapiResponse<BrapiObservationVariable> getVariable(@PathVariable String observationVariableDbId) {
BrapiObservationVariable variable = repository.getVariableById(observationVariableDbId);
......@@ -51,10 +51,10 @@ public class ObservationVariableController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/ObservationVariables/VariableOntologyList.md
*/
@ApiOperation("List ontologies")
@Operation(summary = "List ontologies")
@GetMapping("/brapi/v1/ontologies")
public BrapiListResponse<? extends BrapiOntology> listOntologies(
@Valid @ApiParam PaginationCriteriaImpl criteria
@Valid @Parameter PaginationCriteriaImpl criteria
) {
List<? extends BrapiOntology> ontologies = repository.getOntologies();
......@@ -67,10 +67,10 @@ public class ObservationVariableController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/ObservationVariables/VariableList.md
*/
@ApiOperation("List variables")
@Operation(summary = "List variables")
@GetMapping("/brapi/v1/variables")
public BrapiListResponse<? extends BrapiObservationVariable> listVariables(
@Valid @ApiParam ObservationVariableCriteria criteria
@Valid @Parameter ObservationVariableCriteria criteria
) {
// Get variables by trait class or get all variables
List<? extends BrapiObservationVariable> variables;
......
package fr.inra.urgi.faidare.api.brapi.v1;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import javax.validation.Valid;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiObservationUnit;
import fr.inra.urgi.faidare.domain.brapi.v1.response.BrapiListResponse;
import fr.inra.urgi.faidare.domain.criteria.ObservationUnitCriteria;
import fr.inra.urgi.faidare.domain.response.ApiResponseFactory;
import fr.inra.urgi.faidare.domain.response.PaginatedList;
import fr.inra.urgi.faidare.repository.es.ObservationUnitRepository;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* @author gcornut
*/
@Api(tags = {"Breeding API"}, description = "BrAPI endpoint")
@Tag(name = "Breeding API", description = "BrAPI endpoint")
@RestController
public class PhenotypeController {
......@@ -34,7 +34,7 @@ public class PhenotypeController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Phenotypes/PhenotypeSearch.md
*/
@ApiOperation("Search phenotypes")
@Operation(summary = "Search phenotypes")
@PostMapping(value = "/brapi/v1/phenotypes-search", consumes = APPLICATION_JSON_VALUE)
public BrapiListResponse<? extends BrapiObservationUnit> searchPhenotypes(@Valid @RequestBody(required = false) ObservationUnitCriteria criteria) {
PaginatedList<? extends BrapiObservationUnit> result = repository.find(criteria);
......
package fr.inra.urgi.faidare.api.brapi.v1;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import javax.validation.Valid;
import fr.inra.urgi.faidare.api.NotFoundException;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiProgram;
import fr.inra.urgi.faidare.domain.brapi.v1.response.BrapiListResponse;
......@@ -9,20 +13,20 @@ import fr.inra.urgi.faidare.domain.data.ProgramVO;
import fr.inra.urgi.faidare.domain.response.ApiResponseFactory;
import fr.inra.urgi.faidare.domain.response.PaginatedList;
import fr.inra.urgi.faidare.repository.es.ProgramRepository;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
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.RestController;
/**
* @author gcornut
*/
@Api(tags = {"Breeding API"}, description = "BrAPI endpoint")
@Tag(name = "Breeding API", description = "BrAPI endpoint")
@RestController
public class ProgramController {
......@@ -36,7 +40,7 @@ public class ProgramController {
/**
* Not officially present in BrAPI
*/
@ApiOperation("Get program")
@Operation(summary = "Get program")
@GetMapping("/brapi/v1/programs/{programDbId}")
public BrapiResponse<BrapiProgram> getProgram(@PathVariable String programDbId) {
ProgramVO program = repository.getById(programDbId);
......@@ -49,9 +53,9 @@ public class ProgramController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Programs/ListPrograms.md
*/
@ApiOperation("List programs")
@Operation(summary = "List programs")
@GetMapping("/brapi/v1/programs")
public BrapiListResponse<? extends BrapiProgram> listPrograms(@Valid @ApiParam ProgramCriteria criteria) {
public BrapiListResponse<? extends BrapiProgram> listPrograms(@Valid @Parameter ProgramCriteria criteria) {
PaginatedList<ProgramVO> result = repository.find(criteria);
return ApiResponseFactory.createListResponse(result.getPagination(), null, result);
}
......@@ -59,7 +63,7 @@ public class ProgramController {
/**
* @link https://github.com/plantbreeding/API/blob/master/Specification/Programs/ProgramSearch.md
*/
@ApiOperation("Search programs")
@Operation(summary = "Search programs")
@PostMapping(value = "/brapi/v1/programs-search", consumes = APPLICATION_JSON_VALUE)
public BrapiListResponse<? extends BrapiProgram> searchPrograms(@Valid @RequestBody(required = false) ProgramCriteria criteria) {
return listPrograms(criteria);
......
package fr.inra.urgi.faidare.api.brapi.v1;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import java.util.List;
import java.util.Set;
import javax.validation.Valid;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import fr.inra.urgi.faidare.api.NotFoundException;
import fr.inra.urgi.faidare.domain.brapi.v1.data.*;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiGermplasm;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiObservationUnit;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiObservationVariable;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiStudyDetail;
import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiStudySummary;
import fr.inra.urgi.faidare.domain.brapi.v1.response.BrapiListResponse;
import fr.inra.urgi.faidare.domain.brapi.v1.response.BrapiResponse;
import fr.inra.urgi.faidare.domain.criteria.*;
import fr.inra.urgi.faidare.domain.criteria.GermplasmPOSTSearchCriteria;
import fr.inra.urgi.faidare.domain.criteria.ObservationUnitCriteria;
import fr.inra.urgi.faidare.domain.criteria.StudyObservationUnitCriteria;
import fr.inra.urgi.faidare.domain.criteria.StudySearchCriteria;
import fr.inra.urgi.faidare.domain.criteria.StudySummaryCriteria;
import fr.inra.urgi.faidare.domain.criteria.base.PaginationCriteriaImpl;
import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmVO;
import fr.inra.urgi.faidare.domain.data.phenotype.ObservationUnitVO;
......@@ -21,22 +35,20 @@ import fr.inra.urgi.faidare.repository.es.ObservationUnitRepository;
import fr.inra.urgi.faidare.repository.es.StudyRepository;
import fr.inra.urgi.faidare.repository.file.CropOntologyRepository;
import fr.inra.urgi.faidare.utils.StringFunctions;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Set;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
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;