CropTraitObservationController.java
/*
* Copyright 2024 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.v2.impl;
import com.querydsl.core.types.OrderSpecifier;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.ArrayUtils;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.gringlobal.api.ApiBaseController;
import org.gringlobal.api.FilteredPage;
import org.gringlobal.api.Pagination;
import org.gringlobal.api.model.CropTraitDTO;
import org.gringlobal.api.model.CropTraitObservationAttachDTO;
import org.gringlobal.api.model.CropTraitObservationDTO;
import org.gringlobal.api.model.CropTraitObservationDataAttachDTO;
import org.gringlobal.api.model.CropTraitObservationDataDTO;
import org.gringlobal.api.model.InventoryDTO;
import org.gringlobal.api.model.TranslatedCropTraitObservationDTO;
import org.gringlobal.api.v2.CRUDController;
import org.gringlobal.api.v2.FilteredCRUDController;
import org.gringlobal.api.v2.facade.CropTraitObservationApiService;
import org.gringlobal.api.v2.facade.CropTraitObservationAttachmentApiService;
import org.gringlobal.api.v2.facade.CropTraitObservationDataApiService;
import org.gringlobal.api.v2.facade.CropTraitObservationDataAttachmentApiService;
import org.gringlobal.custom.elasticsearch.SearchException;
import org.gringlobal.model.CropTraitObservation;
import org.gringlobal.model.CropTraitObservationAttach;
import org.gringlobal.model.CropTraitObservationData;
import org.gringlobal.model.CropTraitObservationDataAttach;
import org.gringlobal.model.QCropTrait;
import org.gringlobal.model.QCropTraitObservation;
import org.gringlobal.model.QCropTraitObservationData;
import org.gringlobal.model.QInventory;
import org.gringlobal.service.filter.CropTraitObservationDataFilter;
import org.gringlobal.service.filter.CropTraitObservationFilter;
import org.gringlobal.spring.MinifyingHttpMessageConverter;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.Valid;
import java.io.IOException;
@RestController("cropTraitObservationApi2")
@RequestMapping(CropTraitObservationController.API_URL)
@PreAuthorize("isAuthenticated()")
@Tag(name = "CropTraitObservation")
public class CropTraitObservationController extends FilteredCRUDController<CropTraitObservationDTO, CropTraitObservation, CropTraitObservationApiService, CropTraitObservationFilter> {
public static final String API_URL = ApiBaseController.APIv2_BASE + "/crop-trait/observations";
@Autowired
private CropTraitObservationAttachmentApiService cropTraitObservationAttachmentApiService;
private OrderSpecifier<?>[] observationsDefaultSort() {
return new OrderSpecifier[] { QCropTraitObservation.cropTraitObservation.inventory().id.asc() };
}
@PostMapping(value = "/attach/{cropTraitObservationId}", produces = { MediaType.APPLICATION_JSON_VALUE })
@Operation(description = "Attach crop trait observation file", summary = "Attach file")
public CropTraitObservationAttachDTO uploadFile(@PathVariable(name = "cropTraitObservationId") final Long cropTraitObservationId, @RequestPart(name = "file") final MultipartFile file,
@RequestPart(name = "metadata") final CropTraitObservationAttachmentApiService.CropTraitObservationAttachmentRequestDTO metadata) throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
return cropTraitObservationAttachmentApiService.uploadFile(cropTraitObservationId, file, metadata);
}
@DeleteMapping(value = "/attach/{cropTraitObservationId}/{attachmentId}", produces = { MediaType.APPLICATION_JSON_VALUE })
@Operation(description = "Remove attached file", summary = "Remove file")
public CropTraitObservationAttachDTO removeFile(@PathVariable(name = "cropTraitObservationId") final Long cropTraitObservationId, @PathVariable(name = "attachmentId") final Long attachmentId) {
return cropTraitObservationAttachmentApiService.removeFile(cropTraitObservationId, attachmentId);
}
@RestController("cropTraitObservationAttachApi2")
@RequestMapping(CropTraitObservationController.CropTraitObservationAttachController.API_URL)
@PreAuthorize("isAuthenticated()")
@Tag(name = "CropTraitObservation")
public static class CropTraitObservationAttachController extends CRUDController<CropTraitObservationAttachDTO, CropTraitObservationAttach, CropTraitObservationAttachmentApiService> {
/** The Constant API_URL. */
public static final String API_URL = CropTraitObservationController.API_URL + "/attach/meta";
@Override
@Operation(operationId = "createCropTraitObservationAttach", description = "Create cropTraitObservationAttach", summary = "Create")
public CropTraitObservationAttachDTO create(@RequestBody CropTraitObservationAttachDTO entity) {
// Throws UnsupportedOperationException
return super.create(entity);
}
@Override
@Operation(operationId = "updateCropTraitObservationAttach", description = "Update an existing record", summary = "Update")
public CropTraitObservationAttachDTO update(@RequestBody CropTraitObservationAttachDTO entity) {
return super.update(entity);
}
@Override
@Operation(operationId = "getCropTraitObservationAttach", description = "Get record by ID", summary = "Get")
public CropTraitObservationAttachDTO get(@PathVariable long id) {
return super.get(id);
}
@Override
@Operation(operationId = "deleteCropTraitObservationAttach", description = "Delete existing record by ID", summary = "Delete")
public CropTraitObservationAttachDTO remove(@PathVariable long id) {
return super.remove(id);
}
}
/**
* Get filtered translated list of CropTraitObservation.
*
* @param page the page
* @param filter the filter
* @return the page
* @throws SearchException
*/
@PostMapping(value = "/t/list", produces = { MediaType.APPLICATION_JSON_VALUE })
@Operation(description = "Retrieve list of records matching the filter", summary = "List by filter")
public FilteredPage<TranslatedCropTraitObservationDTO, CropTraitObservationFilter> listTranslated(@ParameterObject final Pagination page, @RequestBody(required = false) final CropTraitObservationFilter filter) throws SearchException, IOException {
CropTraitObservationFilter normalizedFilter = shortFilterService.normalizeFilter(filter, filterType());
Pageable pageable = ArrayUtils.isEmpty(page.getS()) ? page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, defaultSort()) : page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE);
return new FilteredPage<>(normalizedFilter, serviceFacade.listTranslated(filter, pageable));
}
/**
* Get distinct inventories from CropTraitObservations for selected method.
*
* @param methodId the id of method
* @param page the page
* @return the page of inventories
*/
@GetMapping(value = "/{methodId}/inventories", produces = { MediaType.APPLICATION_JSON_VALUE })
public Page<InventoryDTO> getInventories(@ParameterObject final Pagination page, @PathVariable Long methodId) {
Pageable pageable = ArrayUtils.isEmpty(page.getS()) ? page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, QInventory.inventory.id.asc()) : page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE);
return serviceFacade.getObservationInventoriesByMethod(methodId, pageable);
}
/**
* Get distinct crop trait from CropTraitObservations for selected method.
*
* @param methodId the id of method
* @param page the page
* @return the page of crop traits
*/
@GetMapping(value = "/{methodId}/traits", produces = { MediaType.APPLICATION_JSON_VALUE })
public Page<CropTraitDTO> getTraits(@ParameterObject final Pagination page, @PathVariable Long methodId) {
Pageable pageable = ArrayUtils.isEmpty(page.getS()) ? page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, QCropTrait.cropTrait.id.asc()) : page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE);
return serviceFacade.getObservationTraitsByMethod(methodId, pageable);
}
/**
* Ensure CropTraitObservations for given method, inventories and traits
*
* @param request the request
* @return the number of created observations
*/
@PostMapping(value = "/ensure")
public int ensureObservations(@RequestBody @Valid CropTraitObservationApiService.EnsureObservationsRequest request) {
return serviceFacade.ensureObservations(request);
}
@PostMapping(value = "/search", produces = { MinifyingHttpMessageConverter.APPLICATION_MINIFIED_JSON_VALUE })
public CropTraitObservationApiService.FilteredObservations filterObservations(@ParameterObject final Pagination page,
@RequestBody(required = true) final CropTraitObservationFilter filter) {
Pageable pageable = ArrayUtils.isEmpty(page.getS()) ? page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, observationsDefaultSort()) : page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE);
return serviceFacade.search(filter, pageable);
}
@RestController("cropTraitObservationDataApi2")
@RequestMapping(CropTraitObservationController.CropTraitObservationDataController.API_URL)
@PreAuthorize("isAuthenticated()")
@Tag(name = "CropTrait")
public static class CropTraitObservationDataController extends FilteredCRUDController<CropTraitObservationDataDTO, CropTraitObservationData, CropTraitObservationDataApiService, CropTraitObservationDataFilter> {
/** The Constant API_URL. */
public static final String API_URL = CropTraitObservationController.API_URL + "-data";
@Autowired
private CropTraitObservationDataAttachmentApiService cropTraitObservationDataAttachmentApiService;
private OrderSpecifier<?>[] observationsDataDefaultSort() {
return new OrderSpecifier[] { QCropTraitObservationData.cropTraitObservationData.inventory().id.asc() };
}
@PostMapping(value = "/attach/{cropTraitObservationDataId}", produces = { MediaType.APPLICATION_JSON_VALUE })
@Operation(description = "Attach crop trait observation data file", summary = "Attach file")
public CropTraitObservationDataAttachDTO uploadFile(@PathVariable(name = "cropTraitObservationDataId") final Long cropTraitObservationDataId, @RequestPart(name = "file") final MultipartFile file,
@RequestPart(name = "metadata") final CropTraitObservationDataAttachmentApiService.CropTraitObservationDataAttachmentRequestDTO metadata) throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
return cropTraitObservationDataAttachmentApiService.uploadFile(cropTraitObservationDataId, file, metadata);
}
@DeleteMapping(value = "/attach/{cropTraitObservationDataId}/{attachmentId}", produces = { MediaType.APPLICATION_JSON_VALUE })
@Operation(description = "Remove attached file", summary = "Remove file")
public CropTraitObservationDataAttachDTO removeFile(@PathVariable(name = "cropTraitObservationDataId") final Long cropTraitObservationDataId, @PathVariable(name = "attachmentId") final Long attachmentId) {
return cropTraitObservationDataAttachmentApiService.removeFile(cropTraitObservationDataId, attachmentId);
}
@RestController("cropTraitObservationDataAttachApi2")
@RequestMapping(CropTraitObservationDataAttachController.API_URL)
@PreAuthorize("isAuthenticated()")
@Tag(name = "CropTraitObservationData")
public static class CropTraitObservationDataAttachController extends CRUDController<CropTraitObservationDataAttachDTO, CropTraitObservationDataAttach, CropTraitObservationDataAttachmentApiService> {
/** The Constant API_URL. */
public static final String API_URL = CropTraitObservationDataController.API_URL + "/attach/meta";
@Override
@Operation(operationId = "createCropTraitObservationDataAttach", description = "Create cropTraitObservationDataAttach", summary = "Create")
public CropTraitObservationDataAttachDTO create(@RequestBody CropTraitObservationDataAttachDTO entity) {
return super.create(entity);
}
@Override
@Operation(operationId = "updateCropTraitObservationDataAttach", description = "Update an existing record", summary = "Update")
public CropTraitObservationDataAttachDTO update(@RequestBody CropTraitObservationDataAttachDTO entity) {
return super.update(entity);
}
@Override
@Operation(operationId = "getCropTraitObservationDataAttach", description = "Get record by ID", summary = "Get")
public CropTraitObservationDataAttachDTO get(@PathVariable long id) {
return super.get(id);
}
@Override
@Operation(operationId = "deleteCropTraitObservationDataAttach", description = "Delete existing record by ID", summary = "Delete")
public CropTraitObservationDataAttachDTO remove(@PathVariable long id) {
return super.remove(id);
}
}
/**
* Get distinct inventories from CropTraitObservationData for selected method.
*
* @param methodId the id of method
* @param page the page
* @return the page of inventories
*/
@GetMapping(value = "/{methodId}/inventories", produces = { MediaType.APPLICATION_JSON_VALUE })
public Page<InventoryDTO> getInventories(@ParameterObject final Pagination page, @PathVariable Long methodId) {
Pageable pageable = ArrayUtils.isEmpty(page.getS()) ? page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, QInventory.inventory.id.asc()) : page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE);
return serviceFacade.getObservationDataInventoriesByMethod(methodId, pageable);
}
/**
* Get distinct crop trait from CropTraitObservationData for selected method.
*
* @param methodId the id of method
* @param page the page
* @return the page of crop traits
*/
@GetMapping(value = "/{methodId}/traits", produces = { MediaType.APPLICATION_JSON_VALUE })
public Page<CropTraitDTO> getTraits(@ParameterObject final Pagination page, @PathVariable Long methodId) {
Pageable pageable = ArrayUtils.isEmpty(page.getS()) ? page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, QCropTrait.cropTrait.id.asc()) : page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE);
return serviceFacade.getObservationDataTraitsByMethod(methodId, pageable);
}
/**
* Ensure CropTraitObservationData for given method, inventories and traits
*
* @param request the request
* @return the number of created observation data
*/
@PostMapping(value = "/ensure")
public int ensureObservationData(@RequestBody @Valid CropTraitObservationApiService.EnsureObservationsRequest request) {
return serviceFacade.ensureObservationData(request);
}
@PostMapping(value = "/search", produces = { MinifyingHttpMessageConverter.APPLICATION_MINIFIED_JSON_VALUE })
public CropTraitObservationDataApiService.FilteredObservationsData filterObservationsData(@ParameterObject final Pagination page,
@RequestBody(required = true) final CropTraitObservationDataFilter filter) {
Pageable pageable = ArrayUtils.isEmpty(page.getS()) ? page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, observationsDataDefaultSort()) : page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE);
return serviceFacade.search(filter, pageable);
}
}
}