DatasourcesController.java
package se.jobtechdev.personaldatagateway.api.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.context.request.NativeWebRequest;
import se.jobtechdev.personaldatagateway.api.generated.api.DatasourcesApi;
import se.jobtechdev.personaldatagateway.api.generated.model.*;
import se.jobtechdev.personaldatagateway.api.service.DataService;
import se.jobtechdev.personaldatagateway.api.service.DatasourceService;
import se.jobtechdev.personaldatagateway.api.service.FaqService;
import se.jobtechdev.personaldatagateway.api.service.OrganizationService;
import se.jobtechdev.personaldatagateway.api.util.LinkHeaderUtil;
import se.jobtechdev.personaldatagateway.api.util.OffsetBasedPageRequest;
import se.jobtechdev.personaldatagateway.api.util.ResponseFactory;
import java.util.List;
import java.util.UUID;
import static se.jobtechdev.personaldatagateway.api.util.ControllerUtil.assignNonNull;
import static se.jobtechdev.personaldatagateway.api.util.ControllerUtil.throwApiExceptionOnAbsentValue;
@Controller
public class DatasourcesController implements DatasourcesApi {
public static final String DELETED = "deleted";
private final DatasourceService datasourceService;
private final FaqService faqService;
private final OrganizationService organizationService;
private final DataService dataService;
private final NativeWebRequest request;
private final String baseUrl;
@Autowired
public DatasourcesController(
@Value("${pdg-api.base-url}") String baseUrl,
NativeWebRequest request,
DatasourceService datasourceService,
FaqService faqService,
OrganizationService organizationService,
DataService dataService) {
this.baseUrl = baseUrl;
this.request = request;
this.datasourceService = datasourceService;
this.faqService = faqService;
this.organizationService = organizationService;
this.dataService = dataService;
}
private static String getDatasourceNotFoundMessage(UUID datasourceId) {
return String.format("Could not find datasource by id: %s", datasourceId);
}
@Override
public ResponseEntity<Datasource> postDatasource(Datasource datasource) {
final var organizationId = datasource.getOrganizationId();
final var organization =
throwApiExceptionOnAbsentValue(
organizationService.getOrganizationById(organizationId),
HttpStatus.BAD_REQUEST,
String.format(
"Failed to handle POST datasource request - Could not find organization with id: %s",
organizationId));
final var createdDatasource =
throwApiExceptionOnAbsentValue(
datasourceService.createDatasource(
organization,
datasource.getName(),
"",
null,
null),
HttpStatus.BAD_REQUEST,
"Failed to handle POST datasource request - Attempt to create datasource resulted"
+ " in an empty result");
final var response = ResponseFactory.createDatasource(createdDatasource);
final var headers =
LinkHeaderUtil.createHeadersWithLocation(
createdDatasource.getId().toString(), new Class<?>[]{Datasource.class}, datasource);
return ResponseEntity.status(HttpStatus.CREATED)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
@CrossOrigin(origins = "*")
public ResponseEntity<List<Datasource>> getDatasources(Integer offset, Integer limit) {
final var pageable = OffsetBasedPageRequest.of(offset, limit);
final var datasources = datasourceService.getDatasources(pageable);
final var response =
datasources.stream()
.map(
ResponseFactory::createDatasource)
.toList();
final var headers =
LinkHeaderUtil.createHeadersWithPagination(
datasources, new Class<?>[]{Integer.class, Integer.class}, (int) pageable.getOffset(), pageable.getPageSize());
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
@CrossOrigin(origins = "*")
public ResponseEntity<Datasource> getDatasource(UUID datasourceId) {
final var datasource =
throwApiExceptionOnAbsentValue(
datasourceService.getDatasourceById(datasourceId),
HttpStatus.NOT_FOUND,
String.format(
"Failed to handle GET datasource - Could not find datasource with id: %s",
datasourceId));
final var response = ResponseFactory.createDatasource(datasource);
final var headers = LinkHeaderUtil.createHeaders(new Class<?>[]{UUID.class}, datasourceId);
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
public ResponseEntity<Datasource> patchDatasource(UUID datasourceId, DatasourcePatch datasourcePatch) {
final var datasource =
throwApiExceptionOnAbsentValue(
datasourceService.getDatasourceById(datasourceId),
HttpStatus.NOT_FOUND,
String.format(
"Failed to handle PATCH datasource - Could not find datasource with id: %s",
datasourceId));
final var assigned = assignNonNull(datasourcePatch, datasource, List.of(DELETED));
final var updated = datasourceService.update(assigned);
final var response = ResponseFactory.createDatasource(updated);
final var headers = LinkHeaderUtil.createHeaders(new Class<?>[]{UUID.class, DatasourcePatch.class}, datasourceId, datasourcePatch);
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
public ResponseEntity<byte[]> getDatasourceUserData(UUID datasourceId, String userId) {
final var datasource =
throwApiExceptionOnAbsentValue(
datasourceService.getDatasourceById(datasourceId),
HttpStatus.NOT_FOUND,
getDatasourceNotFoundMessage(datasourceId));
final var dataWrapper =
dataService.retrieveData(datasource, userId, request.getHeader(HttpHeaders.ACCEPT));
final var headers = LinkHeaderUtil.createHeaders(new Class<?>[]{UUID.class, String.class}, datasourceId, userId);
return ResponseEntity.status(dataWrapper.status())
.contentType(dataWrapper.contentType())
.headers(headers)
.body(dataWrapper.body());
}
@Override
public ResponseEntity<DatasourceConfig> getDatasourceConfig(UUID datasourceId) {
final var datasource =
throwApiExceptionOnAbsentValue(
datasourceService.getDatasourceById(datasourceId),
HttpStatus.NOT_FOUND,
getDatasourceNotFoundMessage(datasourceId));
final var responseBody =
ResponseFactory.createDatasourceConfig(datasource);
final var headers = LinkHeaderUtil.createHeaders(new Class<?>[]{UUID.class}, datasourceId);
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(responseBody);
}
@Override
public ResponseEntity<DatasourceConfig> patchDatasourceConfig(
UUID datasourceId, DatasourceConfigPatch datasourceConfigPatch) {
final var datasource =
throwApiExceptionOnAbsentValue(
datasourceService.getDatasourceById(datasourceId),
HttpStatus.NOT_FOUND,
getDatasourceNotFoundMessage(datasourceId));
final var assigned = assignNonNull(datasourceConfigPatch, datasource, List.of(DELETED));
final var updated = datasourceService.update(assigned);
final var responseBody =
ResponseFactory.createDatasourceConfig(updated);
responseBody.setHeaders(updated.getHeaders());
final var headers = LinkHeaderUtil.createHeaders(new Class<?>[]{UUID.class, DatasourceConfigPatch.class}, datasourceId, datasourceConfigPatch);
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(responseBody);
}
@Override
public ResponseEntity<DatasourceFaq> postDatasourceFaq(
UUID datasourceId, DatasourceFaq datasourceFaq) {
final var datasource =
throwApiExceptionOnAbsentValue(
datasourceService.getDatasourceById(datasourceId),
HttpStatus.NOT_FOUND,
String.format(
"Failed to handle POST datasource faq request - Could not find datasource with id: %s",
datasourceId));
final var faqs = datasource.getFaqEntities();
final var faq =
faqService.createFaq(
datasourceFaq.getLang(),
datasourceFaq.getTitle(),
datasourceFaq.getContent());
faqs.add(faq);
datasourceService.save(datasource);
final var response =
ResponseFactory.createDatasourceFaq(datasourceId, faq);
final var headers =
LinkHeaderUtil.createHeadersWithLocation(
faq.getId().toString(), new Class<?>[]{UUID.class, DatasourceFaq.class}, datasourceId, datasourceFaq);
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
@CrossOrigin(origins = "*")
public ResponseEntity<List<DatasourceFaq>> getDatasourceFaqs(
UUID datasourceId, String acceptLanguage, Integer offset, Integer limit) {
final var datasource =
throwApiExceptionOnAbsentValue(
datasourceService.getDatasourceById(datasourceId),
HttpStatus.NOT_FOUND,
String.format(
"Failed to handle GET datasource faqs request - Could not find datasource with id: %s",
datasourceId));
final var pageable = OffsetBasedPageRequest.of(offset, limit);
final var faqs = faqService.getDatasourceFaqs(datasource.getId(), acceptLanguage, pageable);
final var response =
faqs.stream()
.map(
faq ->
ResponseFactory.createDatasourceFaq(datasourceId, faq))
.toList();
final var headers =
LinkHeaderUtil.createHeadersWithPagination(
faqs, new Class<?>[]{UUID.class, String.class, Integer.class, Integer.class}, datasourceId, acceptLanguage, (int) pageable.getOffset(), pageable.getPageSize());
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
@CrossOrigin(origins = "*")
public ResponseEntity<DatasourceFaq> getDatasourceFaq(UUID datasourceId, UUID faqId) {
final var faq =
throwApiExceptionOnAbsentValue(
faqService.getFaqById(faqId),
HttpStatus.NOT_FOUND,
String.format(
"Failed to handle GET datasource faq request - Could not find faq with id: %s",
faqId));
final var response =
ResponseFactory.createDatasourceFaq(datasourceId, faq);
final var headers = LinkHeaderUtil.createHeaders(new Class<?>[]{UUID.class, UUID.class}, datasourceId, faqId);
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
public ResponseEntity<DatasourceFaq> patchDatasourceFaq(
UUID datasourceId, UUID faqId, DatasourceFaqPatch datasourceFaqPatch) {
final var faq =
throwApiExceptionOnAbsentValue(
faqService.getFaqById(faqId),
HttpStatus.NOT_FOUND,
String.format(
"Failed to handle PATCH datasource faq request - Could not find faq with id:"
+ " %s",
faqId));
final var patchedFaq = assignNonNull(datasourceFaqPatch, faq, List.of(DELETED));
final var updated = faqService.update(patchedFaq);
final var response =
ResponseFactory.createDatasourceFaq(datasourceId, updated);
final var headers =
LinkHeaderUtil.createHeaders(new Class<?>[]{UUID.class, UUID.class, DatasourceFaqPatch.class}, datasourceId, faqId, datasourceFaqPatch);
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
}