Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Sofia Papacharalampous 2024-06-24 17:44:42 +03:00
commit 9f9638531a
7 changed files with 759 additions and 70 deletions

View File

@ -2,7 +2,6 @@ package org.opencdmp.configurations;
import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.*; import io.swagger.v3.oas.models.security.*;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;

View File

@ -12,9 +12,7 @@ import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.ValidationFilterAnnotation; import gr.cite.tools.validation.ValidationFilterAnnotation;
import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.ExampleObject;
@ -28,10 +26,10 @@ import org.opencdmp.commons.enums.DmpAccessType;
import org.opencdmp.commons.enums.DmpStatus; import org.opencdmp.commons.enums.DmpStatus;
import org.opencdmp.commons.enums.IsActive; import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.controllers.swagger.SwaggerHelpers; import org.opencdmp.controllers.swagger.SwaggerHelpers;
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
import org.opencdmp.controllers.swagger.annotation.Swagger400; import org.opencdmp.controllers.swagger.annotation.Swagger400;
import org.opencdmp.controllers.swagger.annotation.Swagger404; import org.opencdmp.controllers.swagger.annotation.Swagger404;
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses; import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.StorageFileEntity; import org.opencdmp.data.StorageFileEntity;
import org.opencdmp.model.DescriptionValidationResult; import org.opencdmp.model.DescriptionValidationResult;
@ -96,18 +94,23 @@ public class DescriptionController {
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final MessageSource messageSource; private final MessageSource messageSource;
private final ElasticQueryHelperService elasticQueryHelperService; private final ElasticQueryHelperService elasticQueryHelperService;
private final StorageFileService storageFileService; private final StorageFileService storageFileService;
private final ConventionService conventionService; private final ConventionService conventionService;
private final FieldSetExpanderService fieldSetExpanderService; private final FieldSetExpanderService fieldSetExpanderService;
public DescriptionController( public DescriptionController(
BuilderFactory builderFactory, BuilderFactory builderFactory,
AuditService auditService, AuditService auditService,
DescriptionService descriptionService, DescriptionService descriptionService,
CensorFactory censorFactory, CensorFactory censorFactory,
QueryFactory queryFactory, QueryFactory queryFactory,
MessageSource messageSource, MessageSource messageSource,
ElasticQueryHelperService elasticQueryHelperService, StorageFileService storageFileService, ConventionService conventionService, FieldSetExpanderService fieldSetExpanderService) { ElasticQueryHelperService elasticQueryHelperService, StorageFileService storageFileService, ConventionService conventionService, FieldSetExpanderService fieldSetExpanderService) {
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.auditService = auditService; this.auditService = auditService;
this.descriptionService = descriptionService; this.descriptionService = descriptionService;
@ -115,9 +118,9 @@ public class DescriptionController {
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.messageSource = messageSource; this.messageSource = messageSource;
this.elasticQueryHelperService = elasticQueryHelperService; this.elasticQueryHelperService = elasticQueryHelperService;
this.storageFileService = storageFileService; this.storageFileService = storageFileService;
this.conventionService = conventionService; this.conventionService = conventionService;
this.fieldSetExpanderService = fieldSetExpanderService; this.fieldSetExpanderService = fieldSetExpanderService;
} }
@PostMapping("public/query") @PostMapping("public/query")
@ -130,7 +133,7 @@ public class DescriptionController {
//DescriptionQuery query = lookup.enrich(this.queryFactory).authorize(EnumSet.of(Public)).dmpSubQuery(this.queryFactory.query(DmpQuery.class).isActive(IsActive.Active).statuses(DmpStatus.Finalized).accessTypes(DmpAccessType.Public)); //DescriptionQuery query = lookup.enrich(this.queryFactory).authorize(EnumSet.of(Public)).dmpSubQuery(this.queryFactory.query(DmpQuery.class).isActive(IsActive.Active).statuses(DmpStatus.Finalized).accessTypes(DmpAccessType.Public));
QueryResult<PublicDescription> queryResult = this.elasticQueryHelperService.collectPublic(lookup, EnumSet.of(Public), null); QueryResult<PublicDescription> queryResult = this.elasticQueryHelperService.collectPublic(lookup, EnumSet.of(Public), null);
this.auditService.track(AuditableAction.Description_PublicQuery, "lookup", lookup); this.auditService.track(AuditableAction.Description_PublicQuery, "lookup", lookup);
return queryResult; return queryResult;
@ -142,13 +145,14 @@ public class DescriptionController {
public PublicDescription publicGet(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { public PublicDescription publicGet(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("retrieving" + PublicDescription.class.getSimpleName()).And("id", id).And("fields", fieldSet)); logger.debug(new MapLogEntry("retrieving" + PublicDescription.class.getSimpleName()).And("id", id).And("fields", fieldSet));
fieldSet = this.fieldSetExpanderService.expand(fieldSet); fieldSet = this.fieldSetExpanderService.expand(fieldSet);
this.censorFactory.censor(PublicDescriptionCensor.class).censor(fieldSet); this.censorFactory.censor(PublicDescriptionCensor.class).censor(fieldSet);
DescriptionQuery query = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).dmpSubQuery(this.queryFactory.query(DmpQuery.class).isActive(IsActive.Active).statuses(DmpStatus.Finalized).accessTypes(DmpAccessType.Public)); DescriptionQuery query = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).dmpSubQuery(this.queryFactory.query(DmpQuery.class).isActive(IsActive.Active).statuses(DmpStatus.Finalized).accessTypes(DmpAccessType.Public));
PublicDescription model = this.builderFactory.builder(PublicDescriptionBuilder.class).authorize(EnumSet.of(Public)).build(fieldSet, query.firstAs(fieldSet)); PublicDescription model = this.builderFactory.builder(PublicDescriptionBuilder.class).authorize(EnumSet.of(Public)).build(fieldSet, query.firstAs(fieldSet));
if (model == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, PublicDescription.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (model == null)
throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, PublicDescription.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.auditService.track(AuditableAction.Description_PublicLookup, Map.ofEntries( this.auditService.track(AuditableAction.Description_PublicLookup, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id), new AbstractMap.SimpleEntry<String, Object>("id", id),
@ -160,18 +164,24 @@ public class DescriptionController {
@PostMapping("query") @PostMapping("query")
@OperationWithTenantHeader(summary = "Query all descriptions", description = SwaggerHelpers.Description.endpoint_query, requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = SwaggerHelpers.Description.endpoint_query_request_body, content = @Content( @OperationWithTenantHeader(summary = "Query all descriptions", description = SwaggerHelpers.Description.endpoint_query, requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = SwaggerHelpers.Description.endpoint_query_request_body, content = @Content(
examples = { examples = {
@ExampleObject( @ExampleObject(
name = "Pagination and projection", name = "Pagination and projection",
description = "Simple paginated request using a property projection list and pagination info", description = "Simple paginated request using a property projection list and pagination info",
value = SwaggerHelpers.Description.endpoint_query_request_body_example value = SwaggerHelpers.Description.endpoint_query_request_body_example
) )
} }
)), responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(examples = @ExampleObject( )), responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(
name = "First page", array = @ArraySchema(
description = "Example with the first page of paginated results", schema = @Schema(
value = SwaggerHelpers.Description.endpoint_query_response_example implementation = Description.class
)))) )
),
examples = @ExampleObject(
name = "First page",
description = "Example with the first page of paginated results",
value = SwaggerHelpers.Description.endpoint_query_response_example
))))
public QueryResult<Description> query(@RequestBody DescriptionLookup lookup) throws MyApplicationException, MyForbiddenException { public QueryResult<Description> query(@RequestBody DescriptionLookup lookup) throws MyApplicationException, MyForbiddenException {
logger.debug("querying {}", Description.class.getSimpleName()); logger.debug("querying {}", Description.class.getSimpleName());
@ -184,7 +194,6 @@ public class DescriptionController {
return queryResult; return queryResult;
} }
@GetMapping("{id}") @GetMapping("{id}")
@OperationWithTenantHeader(summary = "Fetch a specific description by id") @OperationWithTenantHeader(summary = "Fetch a specific description by id")
@Swagger404 @Swagger404
@ -222,7 +231,7 @@ public class DescriptionController {
) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException { ) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException {
logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
fieldSet = this.fieldSetExpanderService.expand(fieldSet); fieldSet = this.fieldSetExpanderService.expand(fieldSet);
Description persisted = this.descriptionService.persist(model, fieldSet); Description persisted = this.descriptionService.persist(model, fieldSet);
this.auditService.track(AuditableAction.Description_Persist, Map.ofEntries( this.auditService.track(AuditableAction.Description_Persist, Map.ofEntries(
@ -245,7 +254,7 @@ public class DescriptionController {
) throws MyApplicationException, MyForbiddenException, MyNotFoundException, IOException, InvalidApplicationException { ) throws MyApplicationException, MyForbiddenException, MyNotFoundException, IOException, InvalidApplicationException {
logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
fieldSet = this.fieldSetExpanderService.expand(fieldSet); fieldSet = this.fieldSetExpanderService.expand(fieldSet);
Description persisted = this.descriptionService.persistStatus(model, fieldSet); Description persisted = this.descriptionService.persistStatus(model, fieldSet);
this.auditService.track(AuditableAction.Description_PersistStatus, Map.ofEntries( this.auditService.track(AuditableAction.Description_PersistStatus, Map.ofEntries(
@ -327,7 +336,7 @@ public class DescriptionController {
) throws IOException { ) throws IOException {
logger.debug(new MapLogEntry("uploadFieldFiles" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); logger.debug(new MapLogEntry("uploadFieldFiles" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
fieldSet = this.fieldSetExpanderService.expand(fieldSet); fieldSet = this.fieldSetExpanderService.expand(fieldSet);
StorageFile persisted = this.descriptionService.uploadFieldFile(model, file, fieldSet); StorageFile persisted = this.descriptionService.uploadFieldFile(model, file, fieldSet);
this.auditService.track(AuditableAction.Description_UploadFieldFiles, Map.ofEntries( this.auditService.track(AuditableAction.Description_UploadFieldFiles, Map.ofEntries(
@ -350,18 +359,20 @@ public class DescriptionController {
StorageFileEntity storageFile = this.descriptionService.getFieldFile(id, fileId); StorageFileEntity storageFile = this.descriptionService.getFieldFile(id, fileId);
byte[] file = this.storageFileService.readAsBytesSafe(id); byte[] file = this.storageFileService.readAsBytesSafe(id);
if (file == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, StorageFile.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (file == null)
throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, StorageFile.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.auditService.track(AuditableAction.Description_GetFieldFile, Map.ofEntries( this.auditService.track(AuditableAction.Description_GetFieldFile, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id) new AbstractMap.SimpleEntry<String, Object>("id", id)
)); ));
String contentType = storageFile.getMimeType(); String contentType = storageFile.getMimeType();
if (this.conventionService.isNullOrEmpty(contentType)) contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE; if (this.conventionService.isNullOrEmpty(contentType))
contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
return ResponseEntity.ok() return ResponseEntity.ok()
.contentType(MediaType.valueOf(contentType)) .contentType(MediaType.valueOf(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + storageFile.getName() + (storageFile.getExtension().startsWith(".") ? "" : ".") + storageFile.getExtension() + "\"") .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + storageFile.getName() + (storageFile.getExtension().startsWith(".") ? "" : ".") + storageFile.getExtension() + "\"")
.body(new ByteArrayResource(file)); .body(new ByteArrayResource(file));
} }

View File

@ -13,9 +13,21 @@ import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.ValidationFilterAnnotation; import gr.cite.tools.validation.ValidationFilterAnnotation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.JAXBException;
import org.opencdmp.audit.AuditableAction; import org.opencdmp.audit.AuditableAction;
import org.opencdmp.authorization.AuthorizationFlags; import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.controllers.swagger.SwaggerHelpers;
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
import org.opencdmp.controllers.swagger.annotation.Swagger400;
import org.opencdmp.controllers.swagger.annotation.Swagger404;
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
import org.opencdmp.data.DescriptionTemplateEntity; import org.opencdmp.data.DescriptionTemplateEntity;
import org.opencdmp.model.builder.descriptiontemplate.DescriptionTemplateBuilder; import org.opencdmp.model.builder.descriptiontemplate.DescriptionTemplateBuilder;
import org.opencdmp.model.censorship.descriptiontemplate.DescriptionTemplateCensor; import org.opencdmp.model.censorship.descriptiontemplate.DescriptionTemplateCensor;
@ -49,6 +61,8 @@ import java.util.UUID;
@RestController @RestController
@RequestMapping(path = "api/description-template") @RequestMapping(path = "api/description-template")
@Tag(name = "Description Templates", description = "Manage description templates")
@SwaggerCommonErrorResponses
public class DescriptionTemplateController { public class DescriptionTemplateController {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateController.class)); private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateController.class));
@ -64,25 +78,45 @@ public class DescriptionTemplateController {
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final MessageSource messageSource; private final MessageSource messageSource;
private final FieldSetExpanderService fieldSetExpanderService; private final FieldSetExpanderService fieldSetExpanderService;
public DescriptionTemplateController( public DescriptionTemplateController(
BuilderFactory builderFactory, BuilderFactory builderFactory,
AuditService auditService, AuditService auditService,
DescriptionTemplateService descriptionTemplateTypeService, DescriptionTemplateService descriptionTemplateTypeService,
CensorFactory censorFactory, CensorFactory censorFactory,
QueryFactory queryFactory, QueryFactory queryFactory,
MessageSource messageSource, FieldSetExpanderService fieldSetExpanderService) { MessageSource messageSource, FieldSetExpanderService fieldSetExpanderService) {
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.auditService = auditService; this.auditService = auditService;
this.descriptionTemplateTypeService = descriptionTemplateTypeService; this.descriptionTemplateTypeService = descriptionTemplateTypeService;
this.censorFactory = censorFactory; this.censorFactory = censorFactory;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.messageSource = messageSource; this.messageSource = messageSource;
this.fieldSetExpanderService = fieldSetExpanderService; this.fieldSetExpanderService = fieldSetExpanderService;
} }
@PostMapping("query") @PostMapping("query")
@OperationWithTenantHeader(summary = "Query all description templates", description = SwaggerHelpers.DescriptionTemplate.endpoint_query, requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = SwaggerHelpers.DescriptionTemplate.endpoint_query_request_body, content = @Content(
examples = {
@ExampleObject(
name = "Pagination and projection",
description = "Simple paginated request using a property projection list and pagination info",
value = SwaggerHelpers.DescriptionTemplate.endpoint_query_request_body_example
)
}
)), responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(
array = @ArraySchema(
schema = @Schema(
implementation = DescriptionTemplate.class
)
),
examples = @ExampleObject(
name = "First page",
description = "Example with the first page of paginated results",
value = SwaggerHelpers.DescriptionTemplate.endpoint_query_response_example
))))
public QueryResult<DescriptionTemplate> query(@RequestBody DescriptionTemplateLookup lookup) throws MyApplicationException, MyForbiddenException { public QueryResult<DescriptionTemplate> query(@RequestBody DescriptionTemplateLookup lookup) throws MyApplicationException, MyForbiddenException {
logger.debug("querying {}", DescriptionTemplate.class.getSimpleName()); logger.debug("querying {}", DescriptionTemplate.class.getSimpleName());
@ -100,7 +134,12 @@ public class DescriptionTemplateController {
} }
@GetMapping("{id}") @GetMapping("{id}")
public DescriptionTemplate get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { @OperationWithTenantHeader(summary = "Fetch a specific description template by id")
@Swagger404
public DescriptionTemplate get(
@Parameter(name = "id", description = "The id of a description template to fetch", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id,
@Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet
) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("retrieving" + DescriptionTemplate.class.getSimpleName()).And("id", id).And("fields", fieldSet)); logger.debug(new MapLogEntry("retrieving" + DescriptionTemplate.class.getSimpleName()).And("id", id).And("fields", fieldSet));
fieldSet = this.fieldSetExpanderService.expand(fieldSet); fieldSet = this.fieldSetExpanderService.expand(fieldSet);
@ -120,9 +159,15 @@ public class DescriptionTemplateController {
} }
@PostMapping("persist") @PostMapping("persist")
@OperationWithTenantHeader(summary = "Create a new or update an existing description template")
@Swagger400
@Swagger404
@Transactional @Transactional
@ValidationFilterAnnotation(validator = DescriptionTemplatePersist.DescriptionTemplatePersistValidator.ValidatorName, argumentName = "model") @ValidationFilterAnnotation(validator = DescriptionTemplatePersist.DescriptionTemplatePersistValidator.ValidatorName, argumentName = "model")
public DescriptionTemplate persist(@RequestBody DescriptionTemplatePersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException { public DescriptionTemplate persist(
@RequestBody DescriptionTemplatePersist model,
@Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet
) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException {
logger.debug(new MapLogEntry("persisting" + DescriptionTemplate.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); logger.debug(new MapLogEntry("persisting" + DescriptionTemplate.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
fieldSet = this.fieldSetExpanderService.expand(fieldSet); fieldSet = this.fieldSetExpanderService.expand(fieldSet);
new BaseFieldSet(fieldSet.getFields()).ensure(DescriptionTemplate._id); new BaseFieldSet(fieldSet.getFields()).ensure(DescriptionTemplate._id);
@ -137,8 +182,12 @@ public class DescriptionTemplateController {
} }
@DeleteMapping("{id}") @DeleteMapping("{id}")
@OperationWithTenantHeader(summary = "Delete a description template by id")
@Swagger404
@Transactional @Transactional
public void delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException { public void delete(
@Parameter(name = "id", description = "The id of a description template to delete", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id
) throws MyForbiddenException, InvalidApplicationException {
logger.debug(new MapLogEntry("retrieving" + DescriptionTemplate.class.getSimpleName()).And("id", id)); logger.debug(new MapLogEntry("retrieving" + DescriptionTemplate.class.getSimpleName()).And("id", id));
this.descriptionTemplateTypeService.deleteAndSave(id); this.descriptionTemplateTypeService.deleteAndSave(id);
@ -147,7 +196,12 @@ public class DescriptionTemplateController {
} }
@GetMapping("clone/{id}") @GetMapping("clone/{id}")
public DescriptionTemplate buildClone(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { @OperationWithTenantHeader(summary = "Clone a description template by id")
@Swagger404
public DescriptionTemplate buildClone(
@Parameter(name = "id", description = "The id of a description template to clone", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id,
@Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet
) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("clone" + DmpBlueprint.class.getSimpleName()).And("id", id).And("fields", fieldSet)); logger.debug(new MapLogEntry("clone" + DmpBlueprint.class.getSimpleName()).And("id", id).And("fields", fieldSet));
fieldSet = this.fieldSetExpanderService.expand(fieldSet); fieldSet = this.fieldSetExpanderService.expand(fieldSet);
@ -164,9 +218,15 @@ public class DescriptionTemplateController {
} }
@PostMapping("new-version") @PostMapping("new-version")
@OperationWithTenantHeader(summary = "Create a new version of a description template")
@Swagger400
@Swagger404
@Transactional @Transactional
@ValidationFilterAnnotation(validator = NewVersionDescriptionTemplatePersist.NewVersionDescriptionTemplatePersistValidator.ValidatorName, argumentName = "model") @ValidationFilterAnnotation(validator = NewVersionDescriptionTemplatePersist.NewVersionDescriptionTemplatePersistValidator.ValidatorName, argumentName = "model")
public DescriptionTemplate createNewVersion(@RequestBody NewVersionDescriptionTemplatePersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException { public DescriptionTemplate createNewVersion(
@RequestBody NewVersionDescriptionTemplatePersist model,
@Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet
) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException {
logger.debug(new MapLogEntry("persisting" + NewVersionDescriptionTemplatePersist.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); logger.debug(new MapLogEntry("persisting" + NewVersionDescriptionTemplatePersist.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
fieldSet = this.fieldSetExpanderService.expand(fieldSet); fieldSet = this.fieldSetExpanderService.expand(fieldSet);
DescriptionTemplate persisted = this.descriptionTemplateTypeService.createNewVersion(model, fieldSet); DescriptionTemplate persisted = this.descriptionTemplateTypeService.createNewVersion(model, fieldSet);
@ -180,7 +240,11 @@ public class DescriptionTemplateController {
} }
@RequestMapping(method = RequestMethod.GET, value = "/xml/export/{id}", produces = "application/xml") @RequestMapping(method = RequestMethod.GET, value = "/xml/export/{id}", produces = "application/xml")
public @ResponseBody ResponseEntity<byte[]> getXml(@PathVariable UUID id) throws JAXBException, ParserConfigurationException, IOException, TransformerException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException { @OperationWithTenantHeader(summary = "Export a description template in xml by id")
@Swagger404
public @ResponseBody ResponseEntity<byte[]> getXml(
@Parameter(name = "id", description = "The id of a description template to export", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable UUID id
) throws JAXBException, ParserConfigurationException, IOException, TransformerException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException {
logger.debug(new MapLogEntry("export" + DescriptionTemplate.class.getSimpleName()).And("id", id)); logger.debug(new MapLogEntry("export" + DescriptionTemplate.class.getSimpleName()).And("id", id));
ResponseEntity<byte[]> response = this.descriptionTemplateTypeService.exportXml(id); ResponseEntity<byte[]> response = this.descriptionTemplateTypeService.exportXml(id);
@ -193,8 +257,13 @@ public class DescriptionTemplateController {
} }
@RequestMapping(method = RequestMethod.POST, value = {"/xml/import/{groupId}", "/xml/import"}) @RequestMapping(method = RequestMethod.POST, value = {"/xml/import/{groupId}", "/xml/import"})
@OperationWithTenantHeader(summary = "Import a description template from an xml file")
@Transactional @Transactional
public DescriptionTemplate importXml(@RequestParam("file") MultipartFile file, @PathVariable(value = "groupId", required = false) UUID groupId, FieldSet fieldSet) throws IOException, JAXBException, InvalidApplicationException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException { public DescriptionTemplate importXml(
@RequestParam("file") MultipartFile file,
@Parameter(name = "groupId", description = "The group id of a description template to import. This is optional.", example = "c0c163dc-2965-45a5-9608-f76030578609") @PathVariable(value = "groupId", required = false) UUID groupId,
@Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet
) throws IOException, JAXBException, InvalidApplicationException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException {
logger.debug(new MapLogEntry("import" + DescriptionTemplate.class.getSimpleName()).And("file", file).And("groupId", groupId)); logger.debug(new MapLogEntry("import" + DescriptionTemplate.class.getSimpleName()).And("file", file).And("groupId", groupId));
fieldSet = this.fieldSetExpanderService.expand(fieldSet); fieldSet = this.fieldSetExpanderService.expand(fieldSet);

View File

@ -11,8 +11,20 @@ import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.ValidationFilterAnnotation; import gr.cite.tools.validation.ValidationFilterAnnotation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.opencdmp.audit.AuditableAction; import org.opencdmp.audit.AuditableAction;
import org.opencdmp.authorization.AuthorizationFlags; import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.controllers.swagger.SwaggerHelpers;
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
import org.opencdmp.controllers.swagger.annotation.Swagger400;
import org.opencdmp.controllers.swagger.annotation.Swagger404;
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
import org.opencdmp.data.DescriptionTemplateTypeEntity; import org.opencdmp.data.DescriptionTemplateTypeEntity;
import org.opencdmp.model.DescriptionTemplateType; import org.opencdmp.model.DescriptionTemplateType;
import org.opencdmp.model.builder.DescriptionTemplateTypeBuilder; import org.opencdmp.model.builder.DescriptionTemplateTypeBuilder;
@ -33,10 +45,14 @@ import java.util.*;
@RestController @RestController
@RequestMapping(path = "api/description-template-type") @RequestMapping(path = "api/description-template-type")
@Tag(name = "Description Template Types", description = "Manage description template types")
@SwaggerCommonErrorResponses
public class DescriptionTemplateTypeController { public class DescriptionTemplateTypeController {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeController.class)); private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeController.class));
private final BuilderFactory builderFactory; private final BuilderFactory builderFactory;
private final AuditService auditService; private final AuditService auditService;
private final DescriptionTemplateTypeService descriptionTemplateTypeService; private final DescriptionTemplateTypeService descriptionTemplateTypeService;
@ -63,6 +79,25 @@ public class DescriptionTemplateTypeController {
} }
@PostMapping("query") @PostMapping("query")
@OperationWithTenantHeader(summary = "Query all description template types", description = SwaggerHelpers.DescriptionTemplateType.endpoint_query, requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = SwaggerHelpers.DescriptionTemplateType.endpoint_query_request_body, content = @Content(
examples = {
@ExampleObject(
name = "Pagination and projection",
description = "Simple paginated request using a property projection list and pagination info",
value = SwaggerHelpers.DescriptionTemplateType.endpoint_query_request_body_example
)
}
)), responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(
array = @ArraySchema(
schema = @Schema(
implementation = DescriptionTemplateType.class
)
),
examples = @ExampleObject(
name = "First page",
description = "Example with the first page of paginated results",
value = SwaggerHelpers.DescriptionTemplateType.endpoint_query_response_example
))))
public QueryResult<DescriptionTemplateType> Query(@RequestBody DescriptionTemplateTypeLookup lookup) throws MyApplicationException, MyForbiddenException { public QueryResult<DescriptionTemplateType> Query(@RequestBody DescriptionTemplateTypeLookup lookup) throws MyApplicationException, MyForbiddenException {
logger.debug("querying {}", DescriptionTemplateType.class.getSimpleName()); logger.debug("querying {}", DescriptionTemplateType.class.getSimpleName());
@ -81,7 +116,12 @@ public class DescriptionTemplateTypeController {
} }
@GetMapping("{id}") @GetMapping("{id}")
public DescriptionTemplateType Get(@PathVariable("id") UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException { @OperationWithTenantHeader(summary = "Fetch a specific description template type by id")
@Swagger404
public DescriptionTemplateType Get(
@Parameter(name = "id", description = "The id of a description template type to fetch", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id,
@Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet, Locale locale
) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("retrieving" + DescriptionTemplateType.class.getSimpleName()).And("id", id).And("fields", fieldSet)); logger.debug(new MapLogEntry("retrieving" + DescriptionTemplateType.class.getSimpleName()).And("id", id).And("fields", fieldSet));
this.censorFactory.censor(DescriptionTemplateTypeCensor.class).censor(fieldSet, null); this.censorFactory.censor(DescriptionTemplateTypeCensor.class).censor(fieldSet, null);
@ -101,9 +141,15 @@ public class DescriptionTemplateTypeController {
} }
@PostMapping("persist") @PostMapping("persist")
@OperationWithTenantHeader(summary = "Create a new or update an existing description template type")
@Swagger400
@Swagger404
@Transactional @Transactional
@ValidationFilterAnnotation(validator = DescriptionTemplateTypePersist.DescriptionTemplateTypePersistValidator.ValidatorName, argumentName ="model") @ValidationFilterAnnotation(validator = DescriptionTemplateTypePersist.DescriptionTemplateTypePersistValidator.ValidatorName, argumentName = "model")
public DescriptionTemplateType Persist(@RequestBody DescriptionTemplateTypePersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { public DescriptionTemplateType Persist(
@RequestBody DescriptionTemplateTypePersist model,
@Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet
) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException {
logger.debug(new MapLogEntry("persisting" + DescriptionTemplateType.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); logger.debug(new MapLogEntry("persisting" + DescriptionTemplateType.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
DescriptionTemplateType persisted = this.descriptionTemplateTypeService.persist(model, fieldSet); DescriptionTemplateType persisted = this.descriptionTemplateTypeService.persist(model, fieldSet);
@ -116,8 +162,12 @@ public class DescriptionTemplateTypeController {
} }
@DeleteMapping("{id}") @DeleteMapping("{id}")
@OperationWithTenantHeader(summary = "Delete a description template type by id")
@Swagger404
@Transactional @Transactional
public void Delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException { public void Delete(
@Parameter(name = "id", description = "The id of a description template type to delete", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id
) throws MyForbiddenException, InvalidApplicationException {
logger.debug(new MapLogEntry("retrieving" + DescriptionTemplateType.class.getSimpleName()).And("id", id)); logger.debug(new MapLogEntry("retrieving" + DescriptionTemplateType.class.getSimpleName()).And("id", id));
this.descriptionTemplateTypeService.deleteAndSave(id); this.descriptionTemplateTypeService.deleteAndSave(id);

View File

@ -11,9 +11,7 @@ import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.ValidationFilterAnnotation; import gr.cite.tools.validation.ValidationFilterAnnotation;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
@ -149,11 +147,15 @@ public class DmpController {
} }
@PostMapping("query") @PostMapping("query")
@OperationWithTenantHeader(summary = "Query all plans", description = SwaggerHelpers.Dmp.endpoint_query, requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = SwaggerHelpers.Dmp.endpoint_query_request_body, content = @Content(examples = @ExampleObject( @OperationWithTenantHeader(summary = "Query all plans", description = SwaggerHelpers.Dmp.endpoint_query, requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = SwaggerHelpers.Dmp.endpoint_query_request_body, content = @Content(
name = "Pagination and projection", examples = {
description = "Simple paginated request using a property projection list and pagination info", @ExampleObject(
value = SwaggerHelpers.Dmp.endpoint_query_request_body_example name = "Pagination and projection",
))), responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( description = "Simple paginated request using a property projection list and pagination info",
value = SwaggerHelpers.Dmp.endpoint_query_request_body_example
)
}
)), responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(
array = @ArraySchema( array = @ArraySchema(
schema = @Schema( schema = @Schema(
implementation = Dmp.class implementation = Dmp.class

View File

@ -903,11 +903,6 @@ public class SwaggerHelpers {
"count":2912 "count":2912
} }
"""; """;
public static final String endpoint_ =
"""
""";
} }
public static class Description { public static class Description {
@ -1765,4 +1760,567 @@ public class SwaggerHelpers {
"""; """;
} }
public static class DescriptionTemplate {
public static final String endpoint_query =
"""
This endpoint is used to fetch all the available description templates.<br/>
It also allows to restrict the results using a query object passed in the request body.<br/>
""";
public static final String endpoint_query_request_body =
"""
Let's explore the options this object gives us.
### <u>General query parameters:</u>
<ul>
<li><b>page:</b>
This is an object controlling the pagination of the results. It contains two properties.
</li>
<ul>
<li><b>offset:</b>
How many records to omit.
</li>
<li><b>size:</b>
How many records to include in each page.
</li>
</ul>
</ul>
For example, if we want the third page, and our pages to contain 15 elements, we would pass the following object:
```JSON
{
"offset": 30,
"size": 15
}
```
<ul>
<li><b>order:</b>
This is an object controlling the ordering of the results.
It contains a list of strings called <i>items</i> with the names of the properties to use.
<br/>If the name of the property is prefixed with a <b>'-'</b>, the ordering direction is <b>DESC</b>. Otherwise, it is <b>ASC</b>.
</li>
</ul>
For example, if we wanted to order based on the field 'createdAt' in descending order, we would pass the following object:
```JSON
{
"items": [
"-createdAt"
],
}
```
<ul>
<li><b>metadata:</b>
This is an object containing metadata for the request. There is only one available option.
<ul>
<li><b>countAll:</b>
If this is set to true, the count property included in the response will account for all the records regardless the pagination,
with all the rest of filtering options applied of course.
Otherwise, if it is set to false or not present, only the returned results will be counted.
<br/>The first option is useful for the UI clients to calculate how many result pages are available.
</li>
</ul>
</li>
<li><b>project:</b>
This is an object controlling the data projection of the results.
It contains a list of strings called <i>fields</i> with the names of the properties to project.
<br/>You can also include properties that are deeper in the object tree by prefixing them with dots.
</li>
</ul>
### <u>Description template specific query parameters:</u>
<ul>
<li><b>like:</b>
If there is a like parameter present in the query, only the description template entities that include the contents of the parameter either in their labels or the descriptions will be in the response.
</li>
<li><b>ids:</b>
This is a list and contains the ids we want to include in the response. <br/>If empty, every record is included.
</li>
<li><b>excludedIds:</b>
This is a list and contains the ids we want to exclude from the response. <br/>If empty, no record gets excluded.
</li>
<li><b>groupIds:</b>
This is a list and contains the group ids we want the templates to have. Every template and all its versions, have the same groupId. <br/>If empty, every record is included.
</li>
<li><b>excludedGroupIds:</b>
This is a list and contains the group ids we want the templates not to have. Every template and all its versions, have the same groupId. <br/>If empty, no record gets excluded.
</li>
<li><b>typeIds:</b>
This is a list and contains the type ids we want the templates to have. Every template has a type designated by a type id. <br/>If empty, every record is included.
</li>
<li><b>isActive:</b>
This is a list and determines which records we want to include in the response, based on if they are deleted or not.
This filter works like this. If we want to view only the active records we pass [1] and for only the deleted records we pass [0].
<br/>If not present or if we pass [0,1], every record is included.
</li>
<li><b>statuses:</b>
This is a list and determines which records we want to include in the response, based on their status.
The status can be <i>Draft</i> or <i>Finalized</i>. We add 0 or 1 to the list respectively.
<br/>If not present, every record is included.
</li>
<li><b>versionStatuses:</b>
This is a list and determines which records we want to include in the response, based on their version status.
The status can be <i>Current</i>, <i>Previous</i> or <i>NotFinalized</i>. We add 0, 1 or 2 to the list respectively.
<br/>If not present, every record is included.
</li>
<li><b>onlyCanEdit:</b>
This is a boolean and determines whether to fetch only the templates the user can edit or every one.
<br/>If not present, every record is included.
</li>
</ul>
""";
public static final String endpoint_query_request_body_example =
"""
{
"project":{
"fields":[
"id",
"label",
"description",
"status",
"version",
"groupId",
"updatedAt",
"createdAt",
"hash",
"belongsToCurrentTenant",
"isActive",
"authorizationFlags.EditDescriptionTemplate",
"authorizationFlags.DeleteDescriptionTemplate",
"authorizationFlags.CloneDescriptionTemplate",
"authorizationFlags.CreateNewVersionDescriptionTemplate",
"authorizationFlags.ImportDescriptionTemplate",
"authorizationFlags.ExportDescriptionTemplate"
]
},
"metadata":{
"countAll":true
},
"page":{
"offset":0,
"size":10
},
"isActive":[
1
],
"order":{
"items":[
"-createdAt"
]
},
"versionStatuses":[
0,
2
],
"onlyCanEdit":true
}
""";
public static final String endpoint_query_response_example =
"""
{
"items":[
{
"id":"fbbea99b-9259-430b-9f1b-c78f3df8a07c",
"label":"url",
"description":"zxccx",
"groupId":"71d1b878-9980-4b35-b58d-98597e1f2579",
"version":1,
"createdAt":"2024-06-21T13:13:38.344835Z",
"updatedAt":"2024-06-21T13:13:43.001378Z",
"isActive":1,
"status":1,
"hash":"1718975623",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
},
{
"id":"6d2c5983-6125-4fc0-833a-3618d35d0c72",
"label":"to-delete",
"description":"test",
"groupId":"95fc6c79-ee17-4cd9-bad7-0d70ce17b9a4",
"version":1,
"createdAt":"2024-06-21T10:22:33.116729Z",
"updatedAt":"2024-06-21T10:22:52.668175Z",
"isActive":1,
"status":0,
"hash":"1718965372",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
},
{
"id":"e0cb75fe-6f3b-4770-8857-f6b3de9d5411",
"label":"Test Purple Roles",
"description":"Test Purple Roles",
"groupId":"bd3159c7-0b42-431c-8c0f-b353c1343b79",
"version":1,
"createdAt":"2024-06-19T09:53:10.567662Z",
"updatedAt":"2024-06-19T09:53:18.122353Z",
"isActive":1,
"status":1,
"hash":"1718790798",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
},
{
"id":"17eeb5ef-0f2a-40bb-b9b3-4e89a749a08a",
"label":"Purple_template_1.xml",
"description":"Desc",
"groupId":"419bbe42-91e0-4ba4-97cf-c9502063a7ef",
"version":1,
"createdAt":"2024-06-19T09:30:34.925496Z",
"updatedAt":"2024-06-19T09:31:05.429197Z",
"isActive":1,
"status":1,
"hash":"1718789465",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
},
{
"id":"9f6bd3bc-b611-4641-bceb-2e64b0bd34cd",
"label":"RDA_test_new_.xml",
"description":"RDA test",
"groupId":"3c88259f-4b16-4fc3-adf2-cee2ea4b882d",
"version":2,
"createdAt":"2024-06-19T07:14:11.748649Z",
"updatedAt":"2024-06-19T07:14:11.748649Z",
"isActive":1,
"status":0,
"hash":"1718781251",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
},
{
"id":"212342fe-ab6f-4604-b80e-ac23aca93c76",
"label":"RDA test with fix multiplicity1",
"description":"RDA test",
"groupId":"4ff3e924-8623-4b58-a61b-94740b67c4aa",
"version":1,
"createdAt":"2024-06-18T14:04:55.574099Z",
"updatedAt":"2024-06-20T10:45:35.188002Z",
"isActive":1,
"status":1,
"hash":"1718880335",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
},
{
"id":"dddf404e-da59-4097-86d9-29f085ee40da",
"label":"RDA test new ",
"description":"RDA test",
"groupId":"3c88259f-4b16-4fc3-adf2-cee2ea4b882d",
"version":1,
"createdAt":"2024-06-17T12:09:24.296094Z",
"updatedAt":"2024-06-17T12:20:40.432586Z",
"isActive":1,
"status":1,
"hash":"1718626840",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
},
{
"id":"fa67ecbf-c3b4-4e19-b531-764cf7b4d508",
"label":"test",
"description":"test",
"groupId":"bd1a655e-a47b-4edc-a9a2-214dc2971c12",
"version":1,
"createdAt":"2024-06-17T08:41:36.664047Z",
"updatedAt":"2024-06-17T08:41:36.678049Z",
"isActive":1,
"status":0,
"hash":"1718613696",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
},
{
"id":"54527748-7c8a-4045-8b8e-f7be65900302",
"label":"RDA test",
"description":"RDA test",
"groupId":"bf36f613-422a-4d4a-aee1-8a377157f265",
"version":1,
"createdAt":"2024-06-14T08:10:55.988008Z",
"updatedAt":"2024-06-14T10:42:17.438789Z",
"isActive":1,
"status":1,
"hash":"1718361737",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
},
{
"id":"d2f41a59-d369-431d-bf3a-eb29fb4423e7",
"label":"CHIST-ERA Data Management",
"description":"This is a DMP template created based on the CHIST-ERA RDM policy and DMP template.",
"groupId":"c8ef1ecc-f0a6-4f06-a62d-2769968c3d0a",
"version":3,
"createdAt":"2024-04-17T16:58:57Z",
"updatedAt":"2024-04-17T16:58:57Z",
"isActive":1,
"status":1,
"hash":"1713373137",
"authorizationFlags":[
"CreateNewVersionDescriptionTemplate",
"CloneDescriptionTemplate",
"ImportDescriptionTemplate",
"DeleteDescriptionTemplate",
"EditDescriptionTemplate",
"ExportDescriptionTemplate"
],
"belongsToCurrentTenant":true
}
],
"count":40
}
""";
}
public static class DescriptionTemplateType {
public static final String endpoint_query =
"""
This endpoint is used to fetch all the available description template types.<br/>
It also allows to restrict the results using a query object passed in the request body.<br/>
""";
public static final String endpoint_query_request_body =
"""
Let's explore the options this object gives us.
### <u>General query parameters:</u>
<ul>
<li><b>page:</b>
This is an object controlling the pagination of the results. It contains two properties.
</li>
<ul>
<li><b>offset:</b>
How many records to omit.
</li>
<li><b>size:</b>
How many records to include in each page.
</li>
</ul>
</ul>
For example, if we want the third page, and our pages to contain 15 elements, we would pass the following object:
```JSON
{
"offset": 30,
"size": 15
}
```
<ul>
<li><b>order:</b>
This is an object controlling the ordering of the results.
It contains a list of strings called <i>items</i> with the names of the properties to use.
<br/>If the name of the property is prefixed with a <b>'-'</b>, the ordering direction is <b>DESC</b>. Otherwise, it is <b>ASC</b>.
</li>
</ul>
For example, if we wanted to order based on the field 'createdAt' in descending order, we would pass the following object:
```JSON
{
"items": [
"-createdAt"
],
}
```
<ul>
<li><b>metadata:</b>
This is an object containing metadata for the request. There is only one available option.
<ul>
<li><b>countAll:</b>
If this is set to true, the count property included in the response will account for all the records regardless the pagination,
with all the rest of filtering options applied of course.
Otherwise, if it is set to false or not present, only the returned results will be counted.
<br/>The first option is useful for the UI clients to calculate how many result pages are available.
</li>
</ul>
</li>
<li><b>project:</b>
This is an object controlling the data projection of the results.
It contains a list of strings called <i>fields</i> with the names of the properties to project.
<br/>You can also include properties that are deeper in the object tree by prefixing them with dots.
</li>
</ul>
### <u>Description template type specific query parameters:</u>
<ul>
<li><b>like:</b>
If there is a like parameter present in the query, only the description template type entities that include the contents of the parameter in their labels will be in the response.
</li>
<li><b>ids:</b>
This is a list and contains the ids we want to include in the response. <br/>If empty, every record is included.
</li>
<li><b>excludedIds:</b>
This is a list and contains the ids we want to exclude from the response. <br/>If empty, no record gets excluded.
</li>
<li><b>isActives:</b>
This is a list and determines which records we want to include in the response, based on if they are deleted or not.
This filter works like this. If we want to view only the active records we pass [1] and for only the deleted records we pass [0].
<br/>If not present or if we pass [0,1], every record is included.
</li>
<li><b>statuses:</b>
This is a list and determines which records we want to include in the response, based on their status.
The status can be <i>Draft</i> or <i>Finalized</i>. We add 0 or 1 to the list respectively.
<br/>If not present, every record is included.
</li>
</ul>
""";
public static final String endpoint_query_request_body_example =
"""
{
"project":{
"fields":[
"id",
"name",
"status",
"updatedAt",
"createdAt",
"hash",
"belongsToCurrentTenant",
"isActive"
]
},
"metadata":{
"countAll":true
},
"page":{
"offset":0,
"size":10
},
"isActive":[
1
],
"order":{
"items":[
"-createdAt"
]
}
}
""";
public static final String endpoint_query_response_example =
"""
{
"items":[
{
"id":"709a8400-10ca-11ee-be56-0242ac120002",
"name":"Dataset",
"createdAt":"2024-06-10T07:54:59.508261Z",
"updatedAt":"2024-06-10T07:54:59.508261Z",
"isActive":1,
"status":1,
"hash":"1718006099",
"belongsToCurrentTenant":true
},
{
"id":"3b15c046-a978-4b5a-9376-66525b7f1ac9",
"name":"Software",
"createdAt":"2024-06-10T07:54:59.508261Z",
"updatedAt":"2024-06-10T07:54:59.508261Z",
"isActive":1,
"status":1,
"hash":"1718006099",
"belongsToCurrentTenant":true
}
],
"count":2
}
""";
}
public static class DmpBlueprint {
}
public static class FileTransformer {
}
public static class EntityDoi {
}
public static class Deposit {
}
} }

View File

@ -3,15 +3,15 @@ springdoc:
groups: groups:
enabled: true enabled: true
groupConfigs: groupConfigs:
- group: public-api - group: legacy-api
displayName: Legacy displayName: Legacy
packagesToScan: org.opencdmp.controllers.publicapi packagesToScan: org.opencdmp.controllers.publicapi
pathsToMatch: "/api/public/dmps/**, /api/public/datasets/**" pathsToMatch: "/api/public/dmps/**, /api/public/datasets/**"
- group: internal-api - group: current-api
displayName: Current displayName: Current
packagesToScan: org.opencdmp.controllers packagesToScan: org.opencdmp.controllers
packagesToExclude: org.opencdmp.controllers.publicapi packagesToExclude: org.opencdmp.controllers.publicapi
pathsToMatch: "/api/dmp/**, /api/description/**" pathsToMatch: "/api/dmp/**, /api/description/**, /api/description-template/**, /api/description-template-type/**"
swaggerUi: swaggerUi:
enabled: true enabled: true
useRootPath: true useRootPath: true