diff --git a/app/pom.xml b/app/pom.xml
index 2a57c86f..58894bb4 100644
--- a/app/pom.xml
+++ b/app/pom.xml
@@ -112,6 +112,12 @@ SPDX-License-Identifier: Apache-2.0
quarkus-container-image-docker
+
+ io.quarkiverse.openapi.generator
+ quarkus-openapi-generator-server
+ 3.0.0-SNAPSHOT
+
+
io.quarkus
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclHistoryResource.java b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclHistoryResource.java
new file mode 100644
index 00000000..668dfcaf
--- /dev/null
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclHistoryResource.java
@@ -0,0 +1,74 @@
+package org.lfenergy.compas.scl.data.rest.v1;
+
+import io.quarkus.security.Authenticated;
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.lfenergy.compas.scl.data.model.IHistoryMetaItem;
+import org.lfenergy.compas.scl.data.model.Version;
+import org.lfenergy.compas.scl.data.service.CompasSclHistoryService;
+import org.lfenergy.compas.scl.extensions.model.SclFileType;
+import org.lfenergy.compas.scl.rest.api.HistoryResource;
+import org.lfenergy.compas.scl.rest.api.beans.DataResourceHistory;
+import org.lfenergy.compas.scl.rest.api.beans.DataResourceSearch;
+import org.lfenergy.compas.scl.rest.api.beans.DataResourcesResult;
+
+import java.time.OffsetDateTime;
+import java.util.List;
+import java.util.UUID;
+
+@Authenticated
+@RequestScoped
+@Path("/api")
+public class CompasSclHistoryResource implements HistoryResource {
+
+ private final CompasSclHistoryService compasSclHistoryService;
+
+ @Inject
+ public CompasSclHistoryResource(CompasSclHistoryService compasSclHistoryService) {
+ this.compasSclHistoryService = compasSclHistoryService;
+ }
+
+ @Override
+ public DataResourcesResult searchForResources(DataResourceSearch searchQuery) {
+ List historyItems = fetchHistoryItems(searchQuery);
+ DataResourcesResult result = new DataResourcesResult();
+ result.setResults(historyItems.stream().map(HistoryMapper::convertToDataResource).toList());
+ return result;
+ }
+
+ @Override
+ public DataResourceHistory retrieveDataResourceHistory(String id) {
+ List historyItems = compasSclHistoryService.listHistoryVersionsForResource(UUID.fromString(id));
+ DataResourceHistory resourcesHistories = new DataResourceHistory();
+ resourcesHistories.setVersions(historyItems.stream().map(HistoryMapper::convertToDataResourceVersion).toList());
+ return resourcesHistories;
+ }
+
+ @Override
+ public Response retrieveDataResourceByVersion(String id, String version) {
+ String fetchedData = compasSclHistoryService.findFileByIdAndVersion(UUID.fromString(id), new Version(version));
+ return Response.status(Response.Status.OK).entity(fetchedData).type(MediaType.APPLICATION_XML).build();
+ }
+
+ private List fetchHistoryItems(DataResourceSearch searchQuery) {
+ String uuid = searchQuery.getUuid();
+
+ if (uuid != null) {
+ return compasSclHistoryService.listHistoryVersionsForResource(UUID.fromString(uuid));
+ }
+
+ SclFileType type = searchQuery.getType() != null ? SclFileType.valueOf(searchQuery.getType()) : null;
+ String name = searchQuery.getName();
+ String author = searchQuery.getAuthor();
+ OffsetDateTime from = DateUtil.convertToOffsetDateTime(searchQuery.getFrom());
+ OffsetDateTime to = DateUtil.convertToOffsetDateTime(searchQuery.getTo());
+
+ if (type != null || name != null || author != null || from != null || to != null) {
+ return compasSclHistoryService.searchResourcesHistoryVersions(type, name, author, from, to);
+ }
+ return compasSclHistoryService.listHistory();
+ }
+}
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/DateUtil.java b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/DateUtil.java
new file mode 100644
index 00000000..6528ef41
--- /dev/null
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/DateUtil.java
@@ -0,0 +1,21 @@
+package org.lfenergy.compas.scl.data.rest.v1;
+
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+
+public final class DateUtil {
+
+ private DateUtil() {
+ }
+
+ public static OffsetDateTime convertToOffsetDateTime(Date date) {
+ return ObjectUtils.isEmpty(date) ? null : date.toInstant().atOffset(ZoneOffset.UTC);
+ }
+
+ public static Date convertToDate(OffsetDateTime date) {
+ return ObjectUtils.isEmpty(date) ? null : new Date(date.toInstant().toEpochMilli());
+ }
+}
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/HistoryMapper.java b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/HistoryMapper.java
new file mode 100644
index 00000000..91cb332b
--- /dev/null
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/HistoryMapper.java
@@ -0,0 +1,39 @@
+package org.lfenergy.compas.scl.data.rest.v1;
+
+import org.lfenergy.compas.scl.data.model.IHistoryMetaItem;
+import org.lfenergy.compas.scl.rest.api.beans.DataResource;
+import org.lfenergy.compas.scl.rest.api.beans.DataResourceVersion;
+
+import java.util.UUID;
+
+public final class HistoryMapper {
+
+ private HistoryMapper() {
+ }
+
+ public static DataResourceVersion convertToDataResourceVersion(IHistoryMetaItem item) {
+ DataResourceVersion version = new DataResourceVersion();
+ version.setVersion(item.getVersion());
+ version.setAuthor(item.getAuthor());
+ version.setName(item.getName());
+ version.setDeleted(item.isDeleted());
+ version.setUuid(UUID.fromString(item.getId()));
+ version.setType(item.getType());
+ version.setChangedAt(DateUtil.convertToDate(item.getChangedAt()));
+ version.setComment(item.getComment());
+ return version;
+ }
+
+ public static DataResource convertToDataResource(IHistoryMetaItem item) {
+ DataResource version = new DataResource();
+ version.setVersion(item.getVersion());
+ version.setAuthor(item.getAuthor());
+ version.setName(item.getName());
+ version.setDeleted(item.isDeleted());
+ version.setUuid(UUID.fromString(item.getId()));
+ version.setType(item.getType());
+ version.setChangedAt(DateUtil.convertToDate(item.getChangedAt()));
+ return version;
+ }
+
+}
diff --git a/app/src/main/openapi/history-api.yaml b/app/src/main/openapi/history-api.yaml
new file mode 100644
index 00000000..0897824a
--- /dev/null
+++ b/app/src/main/openapi/history-api.yaml
@@ -0,0 +1,261 @@
+openapi: 3.0.3
+info:
+ title: CoMPAS SCL Data Service History API
+ version: 1.0.0
+
+servers:
+ - url: https://demo.compas.energy
+ description: DSOM Versatel Production URL
+
+tags:
+ - name: history
+ description: Endpoints managing history of scl files
+
+security:
+ - open-id-connect:
+ - read
+
+paths:
+ /history/scl/search:
+ post:
+ tags:
+ - history
+ description: Trigger search enabled by the search filter
+ summary: Trigger search enabled by the search filter
+ operationId: searchForResources
+ requestBody:
+ description: Search filter
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DataResourceSearch'
+ responses:
+ '200':
+ description: Successfully retrieved data resources meta data for given search query
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DataResourcesResult'
+ '400':
+ description: One of the specified Parameters is not valid.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+ '401':
+ description: Authentication information is missing or invalid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+ default:
+ description: Unexpected Error, cannot handle request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+ /history/scl/{id}/versions:
+ get:
+ tags:
+ - history
+ description: Trigger search enabled by the search filter
+ summary: Trigger search enabled by the search filter
+ operationId: retrieveDataResourceHistory
+ parameters:
+ - name: id
+ in: path
+ description: Unique data resource identifier
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Succefully retrieved data resource versions
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DataResourceHistory'
+ '400':
+ description: One of the specified Parameters is not valid.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+ '401':
+ description: Authentication information is missing or invalid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+ '404':
+ description: Unable to finde data resource with given unique identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+ default:
+ description: Unexpected Error, cannot handle request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+ /history/scl/{id}/version/{version}:
+ get:
+ tags:
+ - history
+ description: Retrieve data resource for a specific version
+ summary: Retrieve data resource for a specific version
+ operationId: retrieveDataResourceByVersion
+ parameters:
+ - name: id
+ in: path
+ description: Unique data resource identifier
+ required: true
+ schema:
+ type: string
+ format: uuid
+ - name: version
+ in: path
+ description: Combined with unique identifier this combination defines a specific document
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Succefully retrieved data resource
+ content:
+ application/octet-stream:
+ schema:
+ type: string
+ format: binary
+ '401':
+ description: Authentication information is missing or invalid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+ '404':
+ description: One of the specified Parameters is not valid.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+ default:
+ description: Unexpected Error, cannot handle request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponseDto'
+
+components:
+ securitySchemes:
+ open-id-connect: # <--- Arbitrary name for the security scheme. Used to refer to it from elsewhere.
+ type: openIdConnect
+ openIdConnectUrl: https://example.com/.well-known/openid-configuration
+
+ schemas:
+ DataResourceSearch:
+ type: object
+ properties:
+ uuid:
+ type: string
+ description: "If uuid is set no other filter must be set"
+ type:
+ type: string
+ description: "Fulltext match set to one of the supported scl types: SSD, IID, ICD, SCD, CID, SED, ISD, STD, etc."
+ name:
+ type: string
+ description: "Partially match allowed"
+ author:
+ type: string
+ description: "Fulltext match which can be retrieved via extra endpoint"
+ from:
+ type: string
+ format: date-time
+ description: "Starting date and time for filtering results. Use ISO 8601 format (e.g., 2024-10-22T14:48:00Z)."
+ to:
+ type: string
+ format: date-time
+ description: "Ending date and time for filtering results. Use ISO 8601 format (e.g., 2024-10-22T14:48:00Z)."
+ DataResourcesResult:
+ type: object
+ required:
+ - results
+ properties:
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/DataResource'
+ DataResource:
+ type: object
+ required:
+ - uuid
+ - name
+ - author
+ - type
+ - changedAt
+ - version
+ - deleted
+ properties:
+ uuid:
+ type: string
+ format: uuid
+ description: "Unique identifier"
+ name:
+ type: string
+ description: "Name of the resource"
+ author:
+ type: string
+ description: "Name of the author last changed the document"
+ type:
+ type: string
+ description: "One of the supported types: SSD, IID, ICD, SCD, CID, SED, ISD, STD, etc."
+ changedAt:
+ type: string
+ format: date-time
+ description: "Point in time of last modification/upload"
+ version:
+ type: string
+ description: "Generated version by the scl-data-service"
+ deleted:
+ type: boolean
+ description: "Defines if a resource is marked as deleted"
+ default: false
+ DataResourceHistory:
+ type: object
+ required:
+ - versions
+ properties:
+ versions:
+ type: array
+ items:
+ $ref: '#/components/schemas/DataResourceVersion'
+ DataResourceVersion:
+ allOf:
+ - $ref: '#/components/schemas/DataResource'
+ - type: object
+ required:
+ - archived
+ properties:
+ comment:
+ type: string
+ description: "Comment given when uploading the data resource"
+ ErrorResponseDto:
+ required:
+ - timestamp
+ - code
+ - message
+ type: object
+ properties:
+ timestamp:
+ type: string
+ description: 2017-07-21T17:32:28Z.
+ format: 'date-time'
+ code:
+ type: string
+ example: TASK_NOT_FOUND
+ message:
+ type: string
+ example: Es wurde kein Task mit der id 'IdontExist' gefunden.
diff --git a/app/src/main/resources/application.properties b/app/src/main/resources/application.properties
index 88e84e90..c2c7f61f 100644
--- a/app/src/main/resources/application.properties
+++ b/app/src/main/resources/application.properties
@@ -7,6 +7,10 @@ compas.userinfo.who.claimname = ${USERINFO_WHO_CLAIMNAME:name}
compas.userinfo.session.warning = ${USERINFO_SESSION_WARNING:10}
compas.userinfo.session.expires = ${USERINFO_SESSION_EXPIRES:15}
+quarkus.openapi.generator.spec=history-api.yaml
+quarkus.openapi.generator.input-base-dir=src/main/openapi
+quarkus.openapi.generator.base-package=org.lfenergy.compas.scl.rest.api
+
quarkus.http.cors = false
quarkus.http.root-path = /compas-scl-data-service
quarkus.http.limits.max-body-size = 150M
diff --git a/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/model/HistoryMetaItem.java b/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/model/HistoryMetaItem.java
new file mode 100644
index 00000000..bb92b5aa
--- /dev/null
+++ b/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/model/HistoryMetaItem.java
@@ -0,0 +1,45 @@
+package org.lfenergy.compas.scl.data.model;
+
+import java.time.OffsetDateTime;
+
+public class HistoryMetaItem extends AbstractItem implements IHistoryMetaItem {
+ private final String type;
+ private final String author;
+ private final String comment;
+ private final OffsetDateTime changedAt;
+ private final boolean deleted;
+
+ public HistoryMetaItem(String id, String name, String version, String type, String author, String comment, OffsetDateTime changedAt, boolean deleted) {
+ super(id, name, version);
+ this.type = type;
+ this.author = author;
+ this.comment = comment;
+ this.changedAt = changedAt;
+ this.deleted = deleted;
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public String getAuthor() {
+ return author;
+ }
+
+ @Override
+ public String getComment() {
+ return comment;
+ }
+
+ @Override
+ public OffsetDateTime getChangedAt() {
+ return changedAt;
+ }
+
+ @Override
+ public boolean isDeleted() {
+ return deleted;
+ }
+}
diff --git a/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/CompasSclDataPostgreSQLRepository.java b/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/CompasSclDataPostgreSQLRepository.java
index f6685b08..dea7d2fc 100644
--- a/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/CompasSclDataPostgreSQLRepository.java
+++ b/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/CompasSclDataPostgreSQLRepository.java
@@ -14,14 +14,11 @@
import jakarta.inject.Inject;
import javax.sql.DataSource;
import jakarta.transaction.Transactional;
-import java.sql.Array;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.UUID;
+
+import java.sql.*;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.util.*;
import static jakarta.transaction.Transactional.TxType.REQUIRED;
import static jakarta.transaction.Transactional.TxType.SUPPORTS;
@@ -39,6 +36,12 @@ public class CompasSclDataPostgreSQLRepository implements CompasSclDataRepositor
private static final String HITEM_WHEN_FIELD = "hitem_when";
private static final String HITEM_WHAT_FIELD = "hitem_what";
+ private static final String HISTORYMETAITEM_TYPE_FIELD = "type";
+ private static final String HISTORYMETAITEM_AUTHOR_FIELD = "author";
+ private static final String HISTORYMETAITEM_COMMENT_FIELD = "comment";
+ private static final String HISTORYMETAITEM_CHANGEDAT_FIELD = "changedAt";
+ private static final String HISTORYMETAITEM_IS_DELETED_FIELD = "is_deleted";
+
private final DataSource dataSource;
@Inject
@@ -56,6 +59,7 @@ public List list(SclFileType type) {
from (select distinct on (scl_file.id) *
from scl_file
where scl_file.type = ?
+ AND scl_file.is_deleted = false
order by scl_file.id
, scl_file.major_version desc
, scl_file.minor_version desc
@@ -115,6 +119,7 @@ left outer join (
and scl_data.patch_version = scl_file.patch_version
where scl_file.id = ?
and scl_file.type = ?
+ and scl_file.is_deleted = false
order by scl_file.major_version
, scl_file.minor_version
, scl_file.patch_version
@@ -162,6 +167,7 @@ public String findByUUID(SclFileType type, UUID id, Version version) {
and scl_file.major_version = ?
and scl_file.minor_version = ?
and scl_file.patch_version = ?
+ and scl_file.is_deleted = false
""";
try (var connection = dataSource.getConnection();
@@ -191,6 +197,7 @@ public boolean hasDuplicateSclName(SclFileType type, String name) {
select distinct on (scl_file.id) scl_file.name
from scl_file
where scl_file.type = ?
+ and scl_file.is_deleted = false
order by scl_file.id
, scl_file.major_version desc
, scl_file.minor_version desc
@@ -221,6 +228,7 @@ public IAbstractItem findMetaInfoByUUID(SclFileType type, UUID id) {
from scl_file
where scl_file.id = ?
and scl_file.type = ?
+ and scl_file.is_deleted = false
order by scl_file.major_version desc, scl_file.minor_version desc, scl_file.patch_version desc
""";
@@ -303,12 +311,22 @@ insert into scl_label(scl_id, major_version, minor_version, patch_version, label
@Override
@Transactional(REQUIRED)
- public void delete(SclFileType type, UUID id) {
- var sql = """
+ public void delete(SclFileType type, UUID id, boolean softDelete) {
+ String sql;
+ if (softDelete) {
+ sql = """
+ UPDATE scl_file
+ SET scl_file.is_deleted = true
+ where scl_file.id = ?
+ and scl_file.type = ?
+ """;
+ } else {
+ sql = """
delete from scl_file
where scl_file.id = ?
and scl_file.type = ?
""";
+ }
try (var connection = dataSource.getConnection();
var stmt = connection.prepareStatement(sql)) {
@@ -322,8 +340,20 @@ public void delete(SclFileType type, UUID id) {
@Override
@Transactional(REQUIRED)
- public void delete(SclFileType type, UUID id, Version version) {
- var sql = """
+ public void delete(SclFileType type, UUID id, Version version, boolean softDelete) {
+ String sql;
+ if (softDelete) {
+ sql = """
+ UPDATE scl_file
+ SET scl_file.is_deleted = true
+ where scl_file.id = ?
+ and scl_file.type = ?
+ and scl_file.major_version = ?
+ and scl_file.minor_version = ?
+ and scl_file.patch_version = ?
+ """;
+ } else {
+ sql = """
delete from scl_file
where scl_file.id = ?
and scl_file.type = ?
@@ -331,6 +361,7 @@ public void delete(SclFileType type, UUID id, Version version) {
and scl_file.minor_version = ?
and scl_file.patch_version = ?
""";
+ }
try (var connection = dataSource.getConnection();
var stmt = connection.prepareStatement(sql)) {
@@ -345,6 +376,116 @@ public void delete(SclFileType type, UUID id, Version version) {
}
}
+ @Override
+ @Transactional(SUPPORTS)
+ public String findByUUID(UUID id, Version version) {
+ var sql = """
+ select scl_file.scl_data
+ from scl_file
+ where scl_file.id = ?
+ and scl_file.major_version = ?
+ and scl_file.minor_version = ?
+ and scl_file.patch_version = ?
+ """;
+
+ try (var connection = dataSource.getConnection();
+ var stmt = connection.prepareStatement(sql)) {
+ stmt.setObject(1, id);
+ stmt.setInt(2, version.getMajorVersion());
+ stmt.setInt(3, version.getMinorVersion());
+ stmt.setInt(4, version.getPatchVersion());
+
+ try (var resultSet = stmt.executeQuery()) {
+ if (resultSet.next()) {
+ return resultSet.getString(SCL_DATA_FIELD);
+ }
+ var message = String.format("No record found with ID '%s' and version '%s'", id, version);
+ throw new CompasNoDataFoundException(message);
+ }
+ } catch (SQLException exp) {
+ throw new CompasSclDataServiceException(POSTGRES_SELECT_ERROR_CODE, "Error select scl data from database!", exp);
+ }
+ }
+
+ @Override
+ @Transactional(SUPPORTS)
+ public List listHistory() {
+ var sql = """
+ select *
+ from scl_file
+ order by
+ scl_file.id ASC,
+ scl_file.major_version DESC,
+ scl_file.minor_version DESC,
+ scl_file.patch_version DESC
+ """;
+ return executeHistoryQuery(sql, Collections.emptyList());
+ }
+
+ @Override
+ @Transactional(SUPPORTS)
+ public List listHistory(SclFileType type, String name, String author, OffsetDateTime from, OffsetDateTime to) {
+ StringBuilder sqlBuilder = new StringBuilder("""
+ select *
+ from scl_file
+ where 1=1
+ """);
+
+ List
+
+ org.eclipse.microprofile.config
+ microprofile-config-api
+
diff --git a/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclDataService.java b/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclDataService.java
index dbbccd31..e780bdfe 100644
--- a/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclDataService.java
+++ b/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclDataService.java
@@ -43,13 +43,15 @@ public class CompasSclDataService {
private final CompasSclDataRepository repository;
private final ElementConverter converter;
private final SclElementProcessor sclElementProcessor;
+ private final FeatureFlagsConfiguration featureFlagsConfiguration;
@Inject
public CompasSclDataService(CompasSclDataRepository repository, ElementConverter converter,
- SclElementProcessor sclElementProcessor) {
+ SclElementProcessor sclElementProcessor, FeatureFlagsConfiguration featureFlagsConfiguration) {
this.repository = repository;
this.converter = converter;
this.sclElementProcessor = sclElementProcessor;
+ this.featureFlagsConfiguration = featureFlagsConfiguration;
}
/**
@@ -215,7 +217,7 @@ public String update(SclFileType type, UUID id, ChangeSetType changeSetType, Str
*/
@Transactional(REQUIRED)
public void delete(SclFileType type, UUID id) {
- repository.delete(type, id);
+ repository.delete(type, id, featureFlagsConfiguration.isSoftDeleteEnabled());
}
/**
@@ -227,7 +229,7 @@ public void delete(SclFileType type, UUID id) {
*/
@Transactional(REQUIRED)
public void delete(SclFileType type, UUID id, Version version) {
- repository.delete(type, id, version);
+ repository.delete(type, id, version, featureFlagsConfiguration.isSoftDeleteEnabled());
}
/**
diff --git a/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclHistoryService.java b/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclHistoryService.java
new file mode 100644
index 00000000..36e844f4
--- /dev/null
+++ b/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclHistoryService.java
@@ -0,0 +1,68 @@
+package org.lfenergy.compas.scl.data.service;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.transaction.Transactional;
+import org.lfenergy.compas.scl.data.model.IHistoryMetaItem;
+import org.lfenergy.compas.scl.data.model.Version;
+import org.lfenergy.compas.scl.data.repository.CompasSclDataRepository;
+import org.lfenergy.compas.scl.extensions.model.SclFileType;
+
+import java.time.OffsetDateTime;
+import java.util.List;
+import java.util.UUID;
+
+import static jakarta.transaction.Transactional.TxType.SUPPORTS;
+
+@ApplicationScoped
+public class CompasSclHistoryService {
+
+ private final CompasSclDataRepository repository;
+
+ @Inject
+ public CompasSclHistoryService(CompasSclDataRepository repository) {
+ this.repository = repository;
+ }
+
+ /**
+ * List the latest version of all SCL File history entries.
+ *
+ * @return The List of Items found.
+ */
+ @Transactional(SUPPORTS)
+ public List listHistory() {
+ return repository.listHistory();
+ }
+
+ /**
+ * Get a specific version of a specific SCL XML File (using the UUID) for a specific type.
+ *
+ * @param id The UUID of the record to search for.
+ * @param version The version to search for.
+ * @return The found version of the SCL XML Files.
+ */
+ @Transactional(SUPPORTS)
+ public String findFileByIdAndVersion(UUID id, Version version) {
+ return repository.findByUUID(id, version);
+ }
+
+ /**
+ * List the history entries of an SCL File specified by an uuid.
+ *
+ * @return The List of Items found.
+ */
+ @Transactional(SUPPORTS)
+ public List listHistoryVersionsForResource(UUID id) {
+ return repository.listHistoryVersionsByUUID(id);
+ }
+
+ /**
+ * List the latest version of all SCL File history entries.
+ *
+ * @return The List of Items found.
+ */
+ @Transactional(SUPPORTS)
+ public List searchResourcesHistoryVersions(SclFileType type, String name, String author, OffsetDateTime from, OffsetDateTime to) {
+ return repository.listHistory(type, name, author, from, to);
+ }
+}
diff --git a/service/src/main/java/org/lfenergy/compas/scl/data/service/FeatureFlagsConfiguration.java b/service/src/main/java/org/lfenergy/compas/scl/data/service/FeatureFlagsConfiguration.java
new file mode 100644
index 00000000..444da518
--- /dev/null
+++ b/service/src/main/java/org/lfenergy/compas/scl/data/service/FeatureFlagsConfiguration.java
@@ -0,0 +1,15 @@
+package org.lfenergy.compas.scl.data.service;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+@ApplicationScoped
+public class FeatureFlagsConfiguration {
+
+ @ConfigProperty(name = "compas.scl-data-service.features.soft-delete-enabled", defaultValue = "false")
+ boolean softDeleteEnabled;
+
+ public boolean isSoftDeleteEnabled() {
+ return softDeleteEnabled;
+ }
+}
diff --git a/service/src/test/java/org/lfenergy/compas/scl/data/service/CompasSclDataServiceTest.java b/service/src/test/java/org/lfenergy/compas/scl/data/service/CompasSclDataServiceTest.java
index 142674b8..30deaccb 100644
--- a/service/src/test/java/org/lfenergy/compas/scl/data/service/CompasSclDataServiceTest.java
+++ b/service/src/test/java/org/lfenergy/compas/scl/data/service/CompasSclDataServiceTest.java
@@ -48,10 +48,11 @@ class CompasSclDataServiceTest {
private final ElementConverter converter = new ElementConverter();
private final SclElementProcessor processor = new SclElementProcessor();
+ private final FeatureFlagsConfiguration featureFlagsConfiguration = new FeatureFlagsConfiguration();
@BeforeEach
void beforeEach() {
- compasSclDataService = new CompasSclDataService(compasSclDataRepository, converter, processor);
+ compasSclDataService = new CompasSclDataService(compasSclDataRepository, converter, processor, featureFlagsConfiguration);
}
@Test
@@ -304,11 +305,12 @@ void update_WhenCalledWithXMLStringWithoutSCL_ThenCompasExceptionThrown() {
void delete_WhenCalledWithoutVersion_ThenRepositoryIsCalled() {
var uuid = UUID.randomUUID();
- doNothing().when(compasSclDataRepository).delete(SCL_TYPE, uuid);
+ doNothing().when(compasSclDataRepository).delete(SCL_TYPE, uuid, Boolean.FALSE);
+ featureFlagsConfiguration.softDeleteEnabled = Boolean.FALSE;
compasSclDataService.delete(SCL_TYPE, uuid);
- verify(compasSclDataRepository).delete(SCL_TYPE, uuid);
+ verify(compasSclDataRepository).delete(SCL_TYPE, uuid, Boolean.FALSE);
}
@Test
@@ -316,11 +318,37 @@ void delete_WhenCalledWithVersion_ThenRepositoryIsCalled() {
var uuid = UUID.randomUUID();
var version = new Version(1, 0, 0);
- doNothing().when(compasSclDataRepository).delete(SCL_TYPE, uuid, version);
+ doNothing().when(compasSclDataRepository).delete(SCL_TYPE, uuid, version, Boolean.FALSE);
+ featureFlagsConfiguration.softDeleteEnabled = Boolean.FALSE;
compasSclDataService.delete(SCL_TYPE, uuid, version);
- verify(compasSclDataRepository).delete(SCL_TYPE, uuid, version);
+ verify(compasSclDataRepository).delete(SCL_TYPE, uuid, version, Boolean.FALSE);
+ }
+
+ @Test
+ void deleteWithSoftDelete_WhenCalledWithoutVersion_ThenRepositoryIsCalled() {
+ var uuid = UUID.randomUUID();
+
+ doNothing().when(compasSclDataRepository).delete(SCL_TYPE, uuid, Boolean.TRUE);
+
+ featureFlagsConfiguration.softDeleteEnabled = Boolean.TRUE;
+ compasSclDataService.delete(SCL_TYPE, uuid);
+
+ verify(compasSclDataRepository).delete(SCL_TYPE, uuid, Boolean.TRUE);
+ }
+
+ @Test
+ void deleteWithSoftDelete_WhenCalledWithVersion_ThenRepositoryIsCalled() {
+ var uuid = UUID.randomUUID();
+ var version = new Version(1, 0, 0);
+
+ doNothing().when(compasSclDataRepository).delete(SCL_TYPE, uuid, version, Boolean.TRUE);
+
+ featureFlagsConfiguration.softDeleteEnabled = Boolean.TRUE;
+ compasSclDataService.delete(SCL_TYPE, uuid, version);
+
+ verify(compasSclDataRepository).delete(SCL_TYPE, uuid, version, Boolean.TRUE);
}
@Test