From 4b8f3817ab51638c065d6182becaaaeada8a90f6 Mon Sep 17 00:00:00 2001 From: ppel Date: Thu, 29 Aug 2024 13:17:20 +0200 Subject: [PATCH 1/4] #441281 - Added new endpoint for getting complex vocabularies. Modified catalog request for policies visualization (not working yet) --- docker/Dockerfile | 2 +- .../ComplexPolicyDefinitionApi.java | 33 + .../ComplexPolicyDefinitionApiController.java | 34 + .../complexpolicy/mapper/PolicyMapper.java | 18 + .../build.gradle.kts | 6 + .../FederatedCatalogCacheApiExtension.java | 25 +- .../FederatedCatalogCacheApiController.java | 735 ++++++++++++++++-- .../federated/model/DspContractOffer.java | 10 + ...nObjectFromUiContractOfferTransformer.java | 137 ++++ .../inesdata/federated/utils/JsonLdUtils.java | 300 +++++++ .../upm/inesdata/federated/utils/Prop.java | 219 ++++++ .../connector/src/main/resources/logback.xml | 2 +- 12 files changed, 1465 insertions(+), 56 deletions(-) create mode 100644 extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/model/DspContractOffer.java create mode 100644 extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/transformer/JsonObjectFromUiContractOfferTransformer.java create mode 100644 extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/utils/JsonLdUtils.java create mode 100644 extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/utils/Prop.java diff --git a/docker/Dockerfile b/docker/Dockerfile index 43d7d91..3712c0d 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -35,4 +35,4 @@ COPY resources/* ${CONNECTOR_RESOURCES}/ # Use "exec" for Kubernetes graceful termination (SIGINT) to reach JVM. ENTRYPOINT [ "sh", "-c", \ - "exec java $JVM_ARGS -jar connector.jar"] + "exec java $JVM_ARGS -agentlib:jdwp=transport=dt_socket,address=0.0.0.0:18787,server=y,suspend=y -jar connector.jar"] diff --git a/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/controller/ComplexPolicyDefinitionApi.java b/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/controller/ComplexPolicyDefinitionApi.java index 11d6a7e..ab9471d 100644 --- a/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/controller/ComplexPolicyDefinitionApi.java +++ b/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/controller/ComplexPolicyDefinitionApi.java @@ -13,6 +13,9 @@ import jakarta.json.JsonObject; import org.eclipse.edc.api.model.ApiCoreSchema; import org.upm.inesdata.complexpolicy.model.PolicyDefinitionCreateDto; +import org.upm.inesdata.complexpolicy.model.PolicyDefinitionDto; + +import java.util.List; @OpenAPIDefinition( info = @Info( @@ -63,4 +66,34 @@ public interface ComplexPolicyDefinitionApi { ) JsonObject createPolicyDefinitionV3(PolicyDefinitionCreateDto var1); + @Operation( + description = "Creates a new policy definition", + requestBody = @RequestBody( + content = {@Content( + schema = @Schema( + ) + )} + ), + responses = {@ApiResponse( + responseCode = "200", + description = "Returns the Policy Definitions", + content = {@Content( + schema = @Schema( + implementation = ApiCoreSchema.IdResponseSchema.class + ) + )} + ), @ApiResponse( + responseCode = "400", + description = "Request body was malformed", + content = {@Content( + array = @ArraySchema( + schema = @Schema( + implementation = ApiCoreSchema.ApiErrorDetailSchema.class + ) + ) + )} + )} + ) + List getPolicyDefinitions(JsonObject querySpecJson); + } diff --git a/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/controller/ComplexPolicyDefinitionApiController.java b/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/controller/ComplexPolicyDefinitionApiController.java index e32fb04..2dcd212 100644 --- a/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/controller/ComplexPolicyDefinitionApiController.java +++ b/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/controller/ComplexPolicyDefinitionApiController.java @@ -10,14 +10,21 @@ import org.eclipse.edc.connector.controlplane.services.spi.policydefinition.PolicyDefinitionService; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.exception.InvalidRequestException; +import org.eclipse.edc.web.spi.exception.ValidationFailureException; import org.upm.inesdata.complexpolicy.mapper.PolicyMapper; import org.upm.inesdata.complexpolicy.model.PolicyDefinitionCreateDto; +import org.upm.inesdata.complexpolicy.model.PolicyDefinitionDto; import org.upm.inesdata.complexpolicy.model.UiPolicyExpression; +import java.util.Comparator; +import java.util.List; + import static java.lang.String.format; +import static org.eclipse.edc.spi.query.QuerySpec.EDC_QUERY_SPEC_TYPE; import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; @Consumes({"application/json"}) @@ -59,6 +66,7 @@ public JsonObject createPolicyDefinitionV3(PolicyDefinitionCreateDto request) { .orElseThrow(f -> new EdcException("Error creating response body: " + f.getFailureDetail())); } + public PolicyDefinition buildPolicyDefinition(String id, UiPolicyExpression uiPolicyExpression) { var policy = policyMapper.buildPolicy(uiPolicyExpression); return PolicyDefinition.Builder.newInstance() @@ -66,4 +74,30 @@ public PolicyDefinition buildPolicyDefinition(String id, UiPolicyExpression uiPo .policy(policy) .build(); } + + + + @POST + @Path("request") + public List getPolicyDefinitions(JsonObject querySpecJson) { + QuerySpec querySpec; + if (querySpecJson == null) { + querySpec = QuerySpec.Builder.newInstance().build(); + } else { + validator.validate(EDC_QUERY_SPEC_TYPE, querySpecJson).orElseThrow(ValidationFailureException::new); + + querySpec = transformerRegistry.transform(querySpecJson, QuerySpec.class) + .orElseThrow(InvalidRequestException::new); + } + + var policyDefinitions = getAllPolicyDefinitions(querySpec); + return policyDefinitions.stream() + .sorted(Comparator.comparing(PolicyDefinition::getCreatedAt).reversed()) + .map(policyMapper::buildPolicyDefinitionDto) + .toList(); + } + + private List getAllPolicyDefinitions(QuerySpec querySpec) { + return service.search(querySpec).orElseThrow(f -> new EdcException("Error getting policy definitions: " + f.getFailureDetail())); + } } diff --git a/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/mapper/PolicyMapper.java b/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/mapper/PolicyMapper.java index 88352b5..b444e94 100644 --- a/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/mapper/PolicyMapper.java +++ b/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/mapper/PolicyMapper.java @@ -3,12 +3,14 @@ import jakarta.json.JsonObject; import lombok.RequiredArgsConstructor; +import org.eclipse.edc.connector.controlplane.policy.spi.PolicyDefinition; import org.eclipse.edc.policy.model.Action; import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.policy.model.PolicyType; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.upm.inesdata.complexpolicy.exception.FailedMappingException; +import org.upm.inesdata.complexpolicy.model.PolicyDefinitionDto; import org.upm.inesdata.complexpolicy.model.UiPolicy; import org.upm.inesdata.complexpolicy.model.UiPolicyExpression; import org.upm.inesdata.complexpolicy.utils.JsonUtils; @@ -101,4 +103,20 @@ public JsonObject buildPolicyJsonLd(Policy policy) { return typeTransformerRegistry.transform(policy, JsonObject.class) .orElseThrow(FailedMappingException::ofFailure); } + + /** + * Builds a simplified policy definition DTO from a policy definition + *

+ * This operation is lossy. + * + * @param policyDefinition policy definition + * @return ui policy + */ + public PolicyDefinitionDto buildPolicyDefinitionDto(PolicyDefinition policyDefinition) { + var policy = buildUiPolicy(policyDefinition.getPolicy()); + return PolicyDefinitionDto.builder() + .policyDefinitionId(policyDefinition.getId()) + .policy(policy) + .build(); + } } diff --git a/extensions/federated-catalog-cache-api/build.gradle.kts b/extensions/federated-catalog-cache-api/build.gradle.kts index 9952cdc..c597551 100644 --- a/extensions/federated-catalog-cache-api/build.gradle.kts +++ b/extensions/federated-catalog-cache-api/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { api(project(":spi:federated-catalog-cache-spi")) + api(project(":extensions:complex-policy-api")) api(libs.edc.spi.core) implementation(libs.edc.spi.transform) implementation(libs.edc.web.spi) @@ -26,5 +27,10 @@ dependencies { implementation(libs.edc.federated.catalog.api) implementation(libs.edc.federated.catalog.core) implementation(libs.edc.federated.catalog.spi) + annotationProcessor(libs.lombok) + compileOnly(libs.lombok) + testAnnotationProcessor(libs.lombok) + testCompileOnly(libs.lombok) + api(libs.edc.policy.definition.api) } diff --git a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/FederatedCatalogCacheApiExtension.java b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/FederatedCatalogCacheApiExtension.java index 620fd80..f3ad20d 100644 --- a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/FederatedCatalogCacheApiExtension.java +++ b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/FederatedCatalogCacheApiExtension.java @@ -1,9 +1,12 @@ package org.upm.inesdata.federated; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.json.Json; -import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfigurationExtension; import org.eclipse.edc.connector.controlplane.transform.edc.from.JsonObjectFromAssetTransformer; import org.eclipse.edc.connector.controlplane.transform.edc.to.JsonObjectToAssetTransformer; +import org.eclipse.edc.connector.controlplane.transform.odrl.OdrlTransformersFactory; +import org.eclipse.edc.connector.controlplane.transform.odrl.to.JsonObjectToPolicyTransformer; +import org.eclipse.edc.connector.core.agent.NoOpParticipantIdMapper; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; @@ -17,8 +20,16 @@ import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.WebService; import org.eclipse.edc.web.spi.configuration.ApiContext; +import org.upm.inesdata.complexpolicy.mapper.AtomicConstraintMapper; +import org.upm.inesdata.complexpolicy.mapper.ExpressionExtractor; +import org.upm.inesdata.complexpolicy.mapper.ExpressionMapper; +import org.upm.inesdata.complexpolicy.mapper.LiteralMapper; +import org.upm.inesdata.complexpolicy.mapper.OperatorMapper; +import org.upm.inesdata.complexpolicy.mapper.PolicyMapper; +import org.upm.inesdata.complexpolicy.mapper.PolicyValidator; import org.upm.inesdata.federated.controller.FederatedCatalogCacheApiController; import org.upm.inesdata.federated.service.FederatedCatalogCacheServiceImpl; +import org.upm.inesdata.federated.transformer.JsonObjectFromUiContractOfferTransformer; import org.upm.inesdata.spi.federated.FederatedCatalogCacheService; import org.upm.inesdata.spi.federated.index.PaginatedFederatedCacheStoreIndex; @@ -81,8 +92,18 @@ public void initialize(ServiceExtensionContext context) { managementApiTransformerRegistry.register(new JsonObjectFromAssetTransformer(factory, jsonLdMapper)); managementApiTransformerRegistry.register(new JsonObjectToAssetTransformer()); + var participantIdMapper = new NoOpParticipantIdMapper(); + managementApiTransformerRegistry.register(new JsonObjectToPolicyTransformer(participantIdMapper)); + managementApiTransformerRegistry.register(new JsonObjectFromUiContractOfferTransformer(jsonLdMapper, factory)); + OdrlTransformersFactory.jsonObjectToOdrlTransformers(participantIdMapper).forEach(managementApiTransformerRegistry::register); + + ExpressionMapper expressionMapper = new ExpressionMapper( + new AtomicConstraintMapper(new LiteralMapper(new ObjectMapper()), new OperatorMapper())); + ExpressionExtractor expressionExtractor = new ExpressionExtractor(new PolicyValidator(), expressionMapper); + PolicyMapper policyMapper = new PolicyMapper(expressionExtractor, expressionMapper, managementApiTransformerRegistry); + var federatedCatalogCacheApiController = new FederatedCatalogCacheApiController(this.federatedCatalogCacheService(), managementApiTransformerRegistry, - validator,monitor); + validator, monitor, policyMapper); webService.registerResource(ApiContext.MANAGEMENT, federatedCatalogCacheApiController); } } diff --git a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/controller/FederatedCatalogCacheApiController.java b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/controller/FederatedCatalogCacheApiController.java index 23b1d85..4881679 100644 --- a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/controller/FederatedCatalogCacheApiController.java +++ b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/controller/FederatedCatalogCacheApiController.java @@ -1,28 +1,33 @@ package org.upm.inesdata.federated.controller; +import jakarta.json.Json; import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; -import jakarta.servlet.annotation.MultipartConfig; -import jakarta.ws.rs.BadRequestException; +import jakarta.json.JsonReader; +import jakarta.json.JsonValue; import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; -import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.AbstractResult; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.exception.InvalidRequestException; import org.eclipse.edc.web.spi.exception.ValidationFailureException; +import org.jetbrains.annotations.NotNull; +import org.upm.inesdata.complexpolicy.mapper.PolicyMapper; +import org.upm.inesdata.complexpolicy.model.UiPolicy; +import org.upm.inesdata.federated.model.DspContractOffer; +import org.upm.inesdata.federated.model.UiContractOffer; +import org.upm.inesdata.federated.utils.JsonLdUtils; +import org.upm.inesdata.federated.utils.Prop; import org.upm.inesdata.spi.federated.FederatedCatalogCacheService; -import java.util.Objects; +import java.io.StringReader; import static jakarta.json.stream.JsonCollectors.toJsonArray; import static org.eclipse.edc.spi.query.QuerySpec.EDC_QUERY_SPEC_TYPE; @@ -32,52 +37,678 @@ * Controller class for the Federated Catalog Cache API. This class implements the {@link FederatedCatalogCacheApi} * interface and provides the API endpoints to interact with the federated catalog cache. */ -@Consumes({ MediaType.APPLICATION_JSON }) -@Produces({ MediaType.APPLICATION_JSON }) +@Consumes({MediaType.APPLICATION_JSON}) +@Produces({MediaType.APPLICATION_JSON}) @Path("/federatedcatalog") public class FederatedCatalogCacheApiController implements FederatedCatalogCacheApi { - private final TypeTransformerRegistry transformerRegistry; - private final FederatedCatalogCacheService service; - private final JsonObjectValidatorRegistry validator; - private final Monitor monitor; - - /** - * Constructs a FederatedCatalogCacheApiController with the specified dependencies. - * - * @param service the service used to access the federated catalog cache. - * @param transformerRegistry the registry for type transformers. - * @param validator the registry for JSON object validators. - * @param monitor the monitor used for logging and monitoring. - */ - public FederatedCatalogCacheApiController(FederatedCatalogCacheService service, - TypeTransformerRegistry transformerRegistry, JsonObjectValidatorRegistry validator, Monitor monitor) { - this.transformerRegistry = transformerRegistry; - this.service = service; - this.validator = validator; - this.monitor = monitor; - } - - /** - * (non-javadoc) - * - * @see FederatedCatalogCacheApi#getFederatedCatalog(JsonObject) - */ - @Override - @POST - @Path("/request") - public JsonArray getFederatedCatalog(JsonObject querySpecJson) { - QuerySpec querySpec; - if (querySpecJson == null) { - querySpec = QuerySpec.Builder.newInstance().build(); - } else { - validator.validate(EDC_QUERY_SPEC_TYPE, querySpecJson).orElseThrow(ValidationFailureException::new); - - querySpec = transformerRegistry.transform(querySpecJson, QuerySpec.class) - .orElseThrow(InvalidRequestException::new); + private final TypeTransformerRegistry transformerRegistry; + private final FederatedCatalogCacheService service; + private final JsonObjectValidatorRegistry validator; + private final Monitor monitor; + private final PolicyMapper policyMapper; + + /** + * Constructs a FederatedCatalogCacheApiController with the specified dependencies. + * + * @param service the service used to access the federated catalog cache. + * @param transformerRegistry the registry for type transformers. + * @param validator the registry for JSON object validators. + * @param monitor the monitor used for logging and monitoring. + * @param policyMapper the mapper used for policies + */ + public FederatedCatalogCacheApiController(FederatedCatalogCacheService service, + TypeTransformerRegistry transformerRegistry, JsonObjectValidatorRegistry validator, Monitor monitor, PolicyMapper policyMapper) { + this.transformerRegistry = transformerRegistry; + this.service = service; + this.validator = validator; + this.monitor = monitor; + this.policyMapper = policyMapper; + } + + /** + * (non-javadoc) + * + * @see FederatedCatalogCacheApi#getFederatedCatalog(JsonObject) + */ + @Override + @POST + @Path("/request") + public JsonArray getFederatedCatalog(JsonObject querySpecJson) { + QuerySpec querySpec; + if (querySpecJson == null) { + querySpec = QuerySpec.Builder.newInstance().build(); + } else { + validator.validate(EDC_QUERY_SPEC_TYPE, querySpecJson).orElseThrow(ValidationFailureException::new); + + querySpec = transformerRegistry.transform(querySpecJson, QuerySpec.class) + .orElseThrow(InvalidRequestException::new); + } + + String jsonString = """ + [ + { + "@id":"579097eb-12e1-4d88-bba9-1cabd08a8e03", + "@type":"http://www.w3.org/ns/dcat#Catalog", + "https://w3id.org/dspace/v0.8/participantId":"connector-c1", + "http://www.w3.org/ns/dcat#service":[ + { + "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", + "@type":"http://www.w3.org/ns/dcat#DataService", + "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", + "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", + "http://purl.org/dc/terms/terms":"dspace:connector", + "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" + } + ], + "https://w3id.org/edc/v0.0.1/ns/originator":"http://connector-c1:19194/protocol", + "https://w3id.org/edc/v0.0.1/ns/participantId":"connector-c1", + "http://www.w3.org/ns/dcat#dataset":[ + { + "@id":"Asset 2008", + "@type":"http://www.w3.org/ns/dcat#Dataset", + "http://www.w3.org/ns/dcat#distribution":[ + { + "@type":"http://www.w3.org/ns/dcat#Distribution", + "http://purl.org/dc/terms/format":{ + "@id":"HttpData-PULL" + }, + "http://www.w3.org/ns/dcat#accessService":{ + "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", + "@type":"http://www.w3.org/ns/dcat#DataService", + "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", + "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", + "http://purl.org/dc/terms/terms":"dspace:connector", + "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" + } + }, + { + "@type":"http://www.w3.org/ns/dcat#Distribution", + "http://purl.org/dc/terms/format":{ + "@id":"HttpData-PUSH" + }, + "http://www.w3.org/ns/dcat#accessService":{ + "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", + "@type":"http://www.w3.org/ns/dcat#DataService", + "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", + "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", + "http://purl.org/dc/terms/terms":"dspace:connector", + "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" + } + }, + { + "@type":"http://www.w3.org/ns/dcat#Distribution", + "http://purl.org/dc/terms/format":{ + "@id":"AmazonS3-PULL" + }, + "http://www.w3.org/ns/dcat#accessService":{ + "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", + "@type":"http://www.w3.org/ns/dcat#DataService", + "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", + "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", + "http://purl.org/dc/terms/terms":"dspace:connector", + "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" + } + }, + { + "@type":"http://www.w3.org/ns/dcat#Distribution", + "http://purl.org/dc/terms/format":{ + "@id":"AmazonS3-PUSH" + }, + "http://www.w3.org/ns/dcat#accessService":{ + "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", + "@type":"http://www.w3.org/ns/dcat#DataService", + "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", + "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", + "http://purl.org/dc/terms/terms":"dspace:connector", + "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" + } + } + ], + "https://w3id.org/edc/v0.0.1/ns/assetType":"machineLearning", + "http://purl.org/dc/terms/format":"", + "https://w3id.org/edc/v0.0.1/ns/version":"Asset 2008", + "http://www.w3.org/ns/dcat#keyword":"test", + "http://www.w3.org/ns/dcat#byteSize":"", + "https://w3id.org/edc/v0.0.1/ns/name":"Asset 2008", + "https://w3id.org/edc/v0.0.1/ns/participantId":"connector-c1", + "https://w3id.org/edc/v0.0.1/ns/assetData":{ + "https://w3id.org/edc/v0.0.1/ns/machine-learning-vocabulary":[ + { + "https://w3id.org/edc/v0.0.1/ns/title":[ + { + "@value":"title vocab" + } + ], + "https://w3id.org/edc/v0.0.1/ns/keyword":[ + { + "@value":"test" + }, + { + "@value":"conn1" + } + ], + "https://w3id.org/edc/v0.0.1/ns/trainedOn":[ + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-object" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-object" + } + ], + "https://w3id.org/edc/v0.0.1/ns/description":[ + { + "@value":"desc-object" + } + ], + "https://w3id.org/edc/v0.0.1/ns/url":[ + { + "@value":"desc-url" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-object-2" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-object-2" + } + ], + "https://w3id.org/edc/v0.0.1/ns/description":[ + { + "@value":"desc-object-2" + } + ], + "https://w3id.org/edc/v0.0.1/ns/url":[ + { + "@value":"desc-url-2" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-object-3" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-object-3" + } + ], + "https://w3id.org/edc/v0.0.1/ns/description":[ + { + "@value":"desc-object-3" + } + ], + "https://w3id.org/edc/v0.0.1/ns/url":[ + { + "@value":"desc-url-3" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-object-4" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-object-4" + } + ], + "https://w3id.org/edc/v0.0.1/ns/description":[ + { + "@value":"desc-object-4" + } + ], + "https://w3id.org/edc/v0.0.1/ns/url":[ + { + "@value":"desc-url-4" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-object-5" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-object-5" + } + ], + "https://w3id.org/edc/v0.0.1/ns/description":[ + { + "@value":"desc-object-5" + } + ], + "https://w3id.org/edc/v0.0.1/ns/url":[ + { + "@value":"desc-url-5" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-object-6" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-object-6 fjhkdshfsdjkfh djskfhsdjkfh sdjkfhsdjkfhs jkfdshjkfh sdkfjhsdjkfheuiwfhwefj dfbfewjfbewifu fewbfuwbfe" + } + ], + "https://w3id.org/edc/v0.0.1/ns/description":[ + { + "@value":"desc-object-6" + } + ], + "https://w3id.org/edc/v0.0.1/ns/url":[ + { + "@value":"desc-url-6" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-object-7" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-object-7" + } + ], + "https://w3id.org/edc/v0.0.1/ns/description":[ + { + "@value":"desc-object-7" + } + ], + "https://w3id.org/edc/v0.0.1/ns/url":[ + { + "@value":"desc-url-7" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-object-8" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-object-8" + } + ], + "https://w3id.org/edc/v0.0.1/ns/description":[ + { + "@value":"desc-object-8" + } + ], + "https://w3id.org/edc/v0.0.1/ns/url":[ + { + "@value":"desc-url-8" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-object-9" + } + ], + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-object-9" + } + ], + "https://w3id.org/edc/v0.0.1/ns/description":[ + { + "@value":"desc-object-9" + } + ], + "https://w3id.org/edc/v0.0.1/ns/url":[ + { + "@value":"desc-url-9" + } + ] + } + ], + "https://w3id.org/edc/v0.0.1/ns/complexProperty":[ + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-1" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-1" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-2" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-2" + } + ] + }, + { + "https://w3id.org/edc/v0.0.1/ns/identifier":[ + { + "@value":"id-3" + } + ], + "https://w3id.org/edc/v0.0.1/ns/name":[ + { + "@value":"name-3" + } + ] + } + ], + "https://w3id.org/edc/v0.0.1/ns/objectProperty":[ + { + "https://w3id.org/edc/v0.0.1/ns/id":[ + { + "@value":"id-single-object" + } + ], + "https://w3id.org/edc/v0.0.1/ns/notation":[ + { + "@value":"notation-single-object" + } + ] + } + ], + "https://w3id.org/edc/v0.0.1/ns/otherProperty":[ + { + "@value":"other property" + } + ] + } + ] + }, + "http://purl.org/dc/terms/description":"

Asset 2008

", + "https://w3id.org/edc/v0.0.1/ns/id":"Asset 2008", + "https://w3id.org/edc/v0.0.1/ns/contenttype":"", + "https://w3id.org/edc/v0.0.1/ns/shortDescription":"Asset 2008", + "http://www.w3.org/ns/odrl/2/hasPolicy":[ + { + "contractOfferId":"YWx3YXlzLXRydWUtY29udHJhY3Q=:QXNzZXQgMjAwOA==:N2Y5ZDYwZGUtYjZkZC00NWQyLWIzZmQtNzBiYmY2NTQ2MzU1", + "policy":{ + "policyJsonLd":"{\\"@id\\":\\"2b8de936-dab3-4e9e-98dc-ca9a2a09bf4e\\",\\"@type\\":\\"http://www.w3.org/ns/odrl/2/Set\\",\\"http://www.w3.org/ns/odrl/2/permission\\":[{\\"http://www.w3.org/ns/odrl/2/action\\":{\\"@id\\":\\"USE\\"},\\"http://www.w3.org/ns/odrl/2/constraint\\":[{\\"http://www.w3.org/ns/odrl/2/leftOperand\\":[{\\"@id\\":\\"ALWAYS_TRUE\\"}],\\"http://www.w3.org/ns/odrl/2/operator\\":[{\\"@id\\":\\"http://www.w3.org/ns/odrl/2/eq\\"}],\\"http://www.w3.org/ns/odrl/2/rightOperand\\":{\\"@value\\":\\"true\\"}}]}],\\"http://www.w3.org/ns/odrl/2/prohibition\\":[],\\"http://www.w3.org/ns/odrl/2/obligation\\":[]}", + "expression":{ + "type":"CONSTRAINT", + "constraint":{ + "left":"ALWAYS_TRUE", + "operator":"EQ", + "right":{ + "type":"STRING", + "value":"true" + } + } + }, + "errors":[ + \s + ] + } + }, + { + "contractOfferId":"aW5lc2RhdGEtY29udHJhY3Q=:QXNzZXQgMjAwOA==:YWY1OWNlNWItOGM4MC00OTE3LWFmNDYtZDc1MTI4MmNlODJj", + "policy":{ + "policyJsonLd":"{\\"@id\\":\\"6a605ec9-3834-4450-99e3-5e7ce0731588\\",\\"@type\\":\\"http://www.w3.org/ns/odrl/2/Set\\",\\"http://www.w3.org/ns/odrl/2/permission\\":[{\\"http://www.w3.org/ns/odrl/2/action\\":{\\"@id\\":\\"USE\\"},\\"http://www.w3.org/ns/odrl/2/constraint\\":[{\\"http://www.w3.org/ns/odrl/2/leftOperand\\":[{\\"@id\\":\\"POLICY_EVALUATION_TIME\\"}],\\"http://www.w3.org/ns/odrl/2/operator\\":[{\\"@id\\":\\"http://www.w3.org/ns/odrl/2/lt\\"}],\\"http://www.w3.org/ns/odrl/2/rightOperand\\":{\\"@value\\":\\"2024-12-31T23:59:59+01:00\\"}}]}],\\"http://www.w3.org/ns/odrl/2/prohibition\\":[],\\"http://www.w3.org/ns/odrl/2/obligation\\":[]}", + "expression":{ + "type":"CONSTRAINT", + "constraint":{ + "left":"POLICY_EVALUATION_TIME", + "operator":"LT", + "right":{ + "type":"STRING", + "value":"2024-12-31T23:59:59+01:00" + } + } + }, + "errors":[ + \s + ] + } + } + ] + }, + { + "@id":"another-asset", + "@type":"http://www.w3.org/ns/dcat#Dataset", + "http://www.w3.org/ns/dcat#distribution":[ + { + "@type":"http://www.w3.org/ns/dcat#Distribution", + "http://purl.org/dc/terms/format":{ + "@id":"HttpData-PULL" + }, + "http://www.w3.org/ns/dcat#accessService":{ + "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", + "@type":"http://www.w3.org/ns/dcat#DataService", + "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", + "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", + "http://purl.org/dc/terms/terms":"dspace:connector", + "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" + } + }, + { + "@type":"http://www.w3.org/ns/dcat#Distribution", + "http://purl.org/dc/terms/format":{ + "@id":"HttpData-PUSH" + }, + "http://www.w3.org/ns/dcat#accessService":{ + "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", + "@type":"http://www.w3.org/ns/dcat#DataService", + "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", + "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", + "http://purl.org/dc/terms/terms":"dspace:connector", + "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" + } + }, + { + "@type":"http://www.w3.org/ns/dcat#Distribution", + "http://purl.org/dc/terms/format":{ + "@id":"AmazonS3-PULL" + }, + "http://www.w3.org/ns/dcat#accessService":{ + "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", + "@type":"http://www.w3.org/ns/dcat#DataService", + "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", + "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", + "http://purl.org/dc/terms/terms":"dspace:connector", + "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" + } + }, + { + "@type":"http://www.w3.org/ns/dcat#Distribution", + "http://purl.org/dc/terms/format":{ + "@id":"AmazonS3-PUSH" + }, + "http://www.w3.org/ns/dcat#accessService":{ + "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", + "@type":"http://www.w3.org/ns/dcat#DataService", + "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", + "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", + "http://purl.org/dc/terms/terms":"dspace:connector", + "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" + } + } + ], + "https://w3id.org/edc/v0.0.1/ns/assetType":"machineLearning", + "http://purl.org/dc/terms/format":"", + "https://w3id.org/edc/v0.0.1/ns/version":"another-asset-version", + "http://www.w3.org/ns/dcat#keyword":"conn1,test", + "http://www.w3.org/ns/dcat#byteSize":"", + "https://w3id.org/edc/v0.0.1/ns/name":"another-asset-name", + "https://w3id.org/edc/v0.0.1/ns/participantId":"connector-c1", + "https://w3id.org/edc/v0.0.1/ns/assetData":{ + "https://w3id.org/edc/v0.0.1/ns/machine-learning-vocabulary":[ + { + "https://w3id.org/edc/v0.0.1/ns/title":[ + { + "@value":"another-asset learning" + } + ], + "https://w3id.org/edc/v0.0.1/ns/keyword":[ + { + "@value":"learning" + } + ] + } + ] + }, + "http://purl.org/dc/terms/description":"

another-asset-long-desc

", + "https://w3id.org/edc/v0.0.1/ns/id":"another-asset", + "https://w3id.org/edc/v0.0.1/ns/contenttype":"", + "https://w3id.org/edc/v0.0.1/ns/shortDescription":"another-asset-short-desc", + "http://www.w3.org/ns/odrl/2/hasPolicy":[ + { + "contractOfferId":"YWx3YXlzLXRydWUtY29udHJhY3Q=:YW5vdGhlci1hc3NldA==:YTc3NThmODItNWMzNS00ZDI3LTgwNmQtODNkZGMzZWY4OGEw", + "policy":{ + "policyJsonLd":"{\\"@id\\":\\"feca33c3-b915-4b4e-a606-8055b1eb6499\\",\\"@type\\":\\"http://www.w3.org/ns/odrl/2/Set\\",\\"http://www.w3.org/ns/odrl/2/permission\\":[{\\"http://www.w3.org/ns/odrl/2/action\\":{\\"@id\\":\\"USE\\"},\\"http://www.w3.org/ns/odrl/2/constraint\\":[{\\"http://www.w3.org/ns/odrl/2/leftOperand\\":[{\\"@id\\":\\"ALWAYS_TRUE\\"}],\\"http://www.w3.org/ns/odrl/2/operator\\":[{\\"@id\\":\\"http://www.w3.org/ns/odrl/2/eq\\"}],\\"http://www.w3.org/ns/odrl/2/rightOperand\\":{\\"@value\\":\\"true\\"}}]}],\\"http://www.w3.org/ns/odrl/2/prohibition\\":[],\\"http://www.w3.org/ns/odrl/2/obligation\\":[]}", + "expression":{ + "type":"CONSTRAINT", + "constraint":{ + "left":"ALWAYS_TRUE", + "operator":"EQ", + "right":{ + "type":"STRING", + "value":"true" + } + } + }, + "errors":[ + \s + ] + } + }, + { + "contractOfferId":"aW5lc2RhdGEtY29udHJhY3Q=:YW5vdGhlci1hc3NldA==:ZmRjYWM5MjQtNDExOC00N2UzLWE2YmUtNzAzNjY4NTEzNmFi", + "policy":{ + "policyJsonLd":"{\\"@id\\":\\"1148f5dc-b54a-4b2f-9e0a-bf98c340d579\\",\\"@type\\":\\"http://www.w3.org/ns/odrl/2/Set\\",\\"http://www.w3.org/ns/odrl/2/permission\\":[{\\"http://www.w3.org/ns/odrl/2/action\\":{\\"@id\\":\\"USE\\"},\\"http://www.w3.org/ns/odrl/2/constraint\\":[{\\"http://www.w3.org/ns/odrl/2/leftOperand\\":[{\\"@id\\":\\"POLICY_EVALUATION_TIME\\"}],\\"http://www.w3.org/ns/odrl/2/operator\\":[{\\"@id\\":\\"http://www.w3.org/ns/odrl/2/lt\\"}],\\"http://www.w3.org/ns/odrl/2/rightOperand\\":{\\"@value\\":\\"2024-12-31T23:59:59+01:00\\"}}]}],\\"http://www.w3.org/ns/odrl/2/prohibition\\":[],\\"http://www.w3.org/ns/odrl/2/obligation\\":[]}", + "expression":{ + "type":"CONSTRAINT", + "constraint":{ + "left":"POLICY_EVALUATION_TIME", + "operator":"LT", + "right":{ + "type":"STRING", + "value":"2024-12-31T23:59:59+01:00" + } + } + }, + "errors":[ + \s + ] + } + } + ] + } + ] + } + ] + """; + +/* JsonArray response = service.searchPagination(querySpec).orElseThrow(exceptionMapper(QuerySpec.class, null)).stream() + .map(it -> transformerRegistry.transform(it, JsonObject.class)) + .peek(r -> r.onFailure(f -> monitor.warning(f.getFailureDetail()))).filter(Result::succeeded) + .map(Result::getContent) + .map(this::modifyPolicyResponse) + .collect(toJsonArray());*/ + + JsonReader jsonReader = Json.createReader(new StringReader(jsonString)); + JsonArray jsonArray = jsonReader.readArray(); + jsonReader.close(); + + return jsonArray; } - return service.searchPagination(querySpec).orElseThrow(exceptionMapper(QuerySpec.class, null)).stream() - .map(it -> transformerRegistry.transform(it, JsonObject.class)) - .peek(r -> r.onFailure(f -> monitor.warning(f.getFailureDetail()))).filter(Result::succeeded) - .map(Result::getContent).collect(toJsonArray()); - } + + private JsonObject modifyPolicyResponse(JsonObject originalResponse) { + if (originalResponse.get(Prop.Dcat.DATASET) != null) { + JsonArray datasets = originalResponse.getJsonArray(Prop.Dcat.DATASET); + JsonArrayBuilder datasetArrayBuilder = Json.createArrayBuilder(); + + for (JsonValue datasetElement : datasets) { + + JsonObject dataset = datasetElement.asJsonObject(); + + if (dataset.getJsonArray(Prop.Odrl.HAS_POLICY) != null) { + var contractOffers = JsonLdUtils.listOfObjects(dataset, Prop.Odrl.HAS_POLICY).stream() + .map(this::buildContractOffer) + .map(this::buildUiContractOffer) + .toList(); + + JsonArrayBuilder uiContractOffersJsonBuilder = Json.createArrayBuilder(); + contractOffers.forEach(offer -> uiContractOffersJsonBuilder.add(transformerRegistry.transform(offer, JsonObject.class).getContent())); + + JsonArray uiContractOffersJson = uiContractOffersJsonBuilder.build(); + + JsonObject modifiedDatasetJson = Json.createObjectBuilder(dataset) + .remove(Prop.Odrl.HAS_POLICY) + .add(Prop.Odrl.HAS_POLICY, uiContractOffersJson) + .build(); + + datasetArrayBuilder.add(modifiedDatasetJson); + } + } + + JsonArray datasetArrayModified = datasetArrayBuilder.build(); + + return Json.createObjectBuilder(originalResponse) + .remove(Prop.Dcat.DATASET) + .add(Prop.Dcat.DATASET, datasetArrayModified) + .build(); + } else { + return originalResponse; + } + } + + @NotNull + private DspContractOffer buildContractOffer(JsonObject json) { + return new DspContractOffer(JsonLdUtils.id(json), json); + } + + private UiPolicy buildUiPolicy(DspContractOffer contractOffer) { + JsonArrayBuilder typeArrayBuilder = Json.createArrayBuilder(); + typeArrayBuilder.add("http://www.w3.org/ns/odrl/2/Set"); + + JsonArray typeArray = typeArrayBuilder.build(); + + JsonObject modifiedJson = Json.createObjectBuilder(contractOffer.getPolicyJsonLd()) + .remove(Prop.TYPE) + .add(Prop.TYPE, typeArray) + .build(); + + var policy = policyMapper.buildPolicy(modifiedJson); + return policyMapper.buildUiPolicy(policy); + } + + private UiContractOffer buildUiContractOffer(DspContractOffer contractOffer) { + var uiContractOffer = new UiContractOffer(); + uiContractOffer.setContractOfferId(contractOffer.getContractOfferId()); + uiContractOffer.setPolicy(buildUiPolicy(contractOffer)); + return uiContractOffer; + } + } diff --git a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/model/DspContractOffer.java b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/model/DspContractOffer.java new file mode 100644 index 0000000..5a78ae2 --- /dev/null +++ b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/model/DspContractOffer.java @@ -0,0 +1,10 @@ +package org.upm.inesdata.federated.model; + +import jakarta.json.JsonObject; +import lombok.Data; + +@Data +public class DspContractOffer { + private final String contractOfferId; + private final JsonObject policyJsonLd; +} \ No newline at end of file diff --git a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/transformer/JsonObjectFromUiContractOfferTransformer.java b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/transformer/JsonObjectFromUiContractOfferTransformer.java new file mode 100644 index 0000000..94044d3 --- /dev/null +++ b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/transformer/JsonObjectFromUiContractOfferTransformer.java @@ -0,0 +1,137 @@ +package org.upm.inesdata.federated.transformer; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.Json; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; +import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.upm.inesdata.complexpolicy.model.UiPolicy; +import org.upm.inesdata.complexpolicy.model.UiPolicyConstraint; +import org.upm.inesdata.complexpolicy.model.UiPolicyExpression; +import org.upm.inesdata.complexpolicy.model.UiPolicyLiteral; +import org.upm.inesdata.federated.model.UiContractOffer; + +import java.io.StringReader; + +public class JsonObjectFromUiContractOfferTransformer extends AbstractJsonLdTransformer { + + private final ObjectMapper objectMapper; + private final JsonBuilderFactory jsonFactory; + + public JsonObjectFromUiContractOfferTransformer(ObjectMapper objectMapper, JsonBuilderFactory jsonFactory) { + super(UiContractOffer.class, JsonObject.class); + this.objectMapper = objectMapper; + this.jsonFactory = jsonFactory; + } + + @Override + public Class getInputType() { + return UiContractOffer.class; + } + + @Override + public Class getOutputType() { + return JsonObject.class; + } + + @Override + public @Nullable JsonObject transform(@NotNull UiContractOffer input, @NotNull TransformerContext context) { + JsonObjectBuilder jsonObjectBuilder = jsonFactory.createObjectBuilder(); + jsonObjectBuilder.add("contractOfferId", input.getContractOfferId()); + + UiPolicy policy = input.getPolicy(); + if (policy != null) { + JsonObjectBuilder policyBuilder = jsonFactory.createObjectBuilder(); + policyBuilder.add("policyJsonLd", policy.getPolicyJsonLd()); + + if (policy.getExpression() != null) { + policyBuilder.add("expression", transformPolicyExpression(policy.getExpression())); + } + + JsonArrayBuilder errorsBuilder = jsonFactory.createArrayBuilder(); + if (policy.getErrors() != null) { + for (String error : policy.getErrors()) { + errorsBuilder.add(error); + } + } + policyBuilder.add("errors", errorsBuilder); + + jsonObjectBuilder.add("policy", policyBuilder); + } + + return jsonObjectBuilder.build(); + } + + private JsonValue transformPolicyExpression(UiPolicyExpression expression) { + if (expression == null) { + return jsonFactory.createObjectBuilder().build(); + } + + JsonObjectBuilder expressionBuilder = jsonFactory.createObjectBuilder(); + expressionBuilder.add("type", expression.getType().name()); + + if (expression.getExpressions() != null) { + JsonArrayBuilder expressionsArrayBuilder = jsonFactory.createArrayBuilder(); + for (UiPolicyExpression subExpression : expression.getExpressions()) { + expressionsArrayBuilder.add(transformPolicyExpression(subExpression)); + } + expressionBuilder.add("expressions", expressionsArrayBuilder); + } + + if (expression.getConstraint() != null) { + expressionBuilder.add("constraint", transformPolicyConstraint(expression.getConstraint())); + } + + return expressionBuilder.build(); + } + + private JsonValue transformPolicyConstraint(UiPolicyConstraint constraint) { + if (constraint == null) { + return jsonFactory.createObjectBuilder().build(); + } + + JsonObjectBuilder constraintBuilder = jsonFactory.createObjectBuilder(); + constraintBuilder.add("left", constraint.getLeft()); + constraintBuilder.add("operator", constraint.getOperator().name()); + constraintBuilder.add("right", transformPolicyLiteral(constraint.getRight())); + + return constraintBuilder.build(); + } + + private JsonValue transformPolicyLiteral(UiPolicyLiteral literal) { + if (literal == null) { + return jsonFactory.createObjectBuilder().build(); + } + + JsonObjectBuilder literalBuilder = jsonFactory.createObjectBuilder(); + literalBuilder.add("type", literal.getType().name()); + + switch (literal.getType()) { + case STRING -> literalBuilder.add("value", literal.getValue()); + case STRING_LIST -> { + JsonArrayBuilder listBuilder = jsonFactory.createArrayBuilder(); + for (String value : literal.getValueList()) { + listBuilder.add(value); + } + literalBuilder.add("valueList", listBuilder); + } + case JSON -> { + try { + JsonValue jsonValue = Json.createReader(new StringReader(literal.getValue())).readValue(); + literalBuilder.add("value", jsonValue); + } catch (Exception e) { + throw new RuntimeException("Error parsing JSON value", e); + } + } + default -> throw new IllegalArgumentException("Unsupported literal type: " + literal.getType()); + } + + return literalBuilder.build(); + } +} diff --git a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/utils/JsonLdUtils.java b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/utils/JsonLdUtils.java new file mode 100644 index 0000000..d50bd98 --- /dev/null +++ b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/utils/JsonLdUtils.java @@ -0,0 +1,300 @@ +package org.upm.inesdata.federated.utils; + +import com.apicatalog.jsonld.JsonLdError; +import com.apicatalog.jsonld.document.JsonDocument; +import jakarta.json.Json; +import jakarta.json.JsonNumber; +import jakarta.json.JsonObject; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.upm.inesdata.complexpolicy.utils.JsonUtils; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class JsonLdUtils { + private static final JsonDocument EMPTY_CONTEXT_DOCUMENT = JsonDocument.of(Json.createObjectBuilder() + .add(Prop.CONTEXT, Json.createObjectBuilder()) + .build()); + + /** + * Compact JSON-LD, but don't compact property names to namespaces. + * + * @param json json-ld + * @return compacted values + */ + public static JsonObject tryCompact(JsonObject json) { + try { + return com.apicatalog.jsonld.JsonLd.compact(JsonDocument.of(json), EMPTY_CONTEXT_DOCUMENT).get(); + } catch (JsonLdError e) { + return json; + } + } + + /** + * Compact JSON-LD, but don't compact property names to namespaces. + * + * @param json json-ld + * @return compacted values + */ + public static JsonObject expandKeysOnly(JsonObject json) { + try { + var expanded = com.apicatalog.jsonld.JsonLd.expand(JsonDocument.of(json)).get(); + return com.apicatalog.jsonld.JsonLd.compact(JsonDocument.of(expanded), EMPTY_CONTEXT_DOCUMENT).get(); + } catch (JsonLdError e) { + return json; + } + } + + public static boolean isEmptyArray(JsonValue json) { + return list(json).isEmpty(); + } + + public static boolean isEmptyObject(JsonValue json) { + return object(json).isEmpty(); + } + + + /** + * Get the ID value of an object + * + * @param json json-ld + * @return id or null + */ + public static String id(JsonObject json) { + return string(json, "@id"); + } + + /** + * Get a string property + * + * @param json json-ld + * @return string value or null + */ + public static String string(JsonValue json) { + var value = value(json); + if (value == null) { + return null; + } + + return switch (value.getValueType()) { + case STRING -> ((JsonString) value).getString(); + case NUMBER -> ((JsonNumber) value).bigDecimalValue().toString(); + case FALSE -> "false"; + case TRUE -> "true"; + case NULL -> null; + // We do this over throwing errors because we want to be able to handle invalid json-ld + case ARRAY, OBJECT -> JsonUtils.toJson(value); + }; + } + + /** + * Get a offset date time property + * + * @param json json-ld + * @return offset date time value or null + */ + public static LocalDate localDate(JsonValue json) { + var str = string(json); + if (str == null) { + return null; + } + + try { + return LocalDate.parse(str); + } catch (DateTimeParseException e) { + return null; + } + } + + /** + * Get a boolean property + * + * @param json json-ld + * @return boolean value or null + */ + public static Boolean bool(JsonValue json) { + var value = value(json); + if (value == null) { + return null; + } + + return switch (value.getValueType()) { + case STRING -> switch (((JsonString) value).getString().toLowerCase()) { + case "true" -> Boolean.TRUE; + case "false" -> Boolean.FALSE; + default -> null; + }; + case FALSE -> Boolean.FALSE; + case TRUE -> Boolean.TRUE; + case NUMBER, NULL, ARRAY, OBJECT -> null; + }; + } + + /** + * Get a list property. + * + * @param json json-ld + * @return list of values + */ + public static List list(JsonValue json) { + return switch (json.getValueType()) { + case ARRAY -> json.asJsonArray(); + case FALSE, TRUE, NUMBER, STRING, OBJECT -> List.of(json); + case NULL -> List.of(); + }; + } + + /** + * Get a list property while unwrapping values and only keeping objects. + * + * @param json json-ld + * @return list of values + */ + public static List listOfObjects(JsonValue json) { + return list(json).stream() + .map(JsonLdUtils::value) // unwrap @value + .filter(JsonObject.class::isInstance) + .map(JsonObject.class::cast) + .toList(); + } + + /** + * Get the innermost @value of an object. Also removes wrappings in lists. + * + * @param json json-ld + * @return innermost @value + */ + public static JsonValue value(JsonValue json) { + return switch (json.getValueType()) { + case ARRAY -> { + var array = json.asJsonArray(); + if (array.isEmpty()) { + yield null; + } + yield value(array.get(0)); + } + case OBJECT -> { + var object = json.asJsonObject(); + if (object.containsKey("@value")) { + yield value(object.get("@value")); + } else { + yield object; + } + } + case STRING, NUMBER, FALSE, TRUE, NULL -> json; + }; + } + + /** + * Get a string property + * + * @param object json-ld + * @param key key + * @return string or null + */ + public static String string(JsonObject object, String key) { + JsonValue field = object.get(key); + if (field == null) { + return null; + } + return string(field); + } + + /** + * Get a offset date time property + * + * @param object json-ld + * @param key key + * @return offset date time or null + */ + public static LocalDate localDate(JsonObject object, String key) { + JsonValue field = object.get(key); + if (field == null) { + return null; + } + return localDate(field); + } + + /** + * Get an object property. Defaults to an empty object for ease of use if not found. + * + * @param object json-ld + * @param key key + * @return string or null + */ + public static JsonObject object(JsonObject object, String key) { + return object(object.get(key)); + } + + /** + * Get an object property. Defaults to an empty object for ease of use if not found. + * + * @param field json-ld + * @return string or null + */ + public static JsonObject object(JsonValue field) { + if (field == null) { + return JsonValue.EMPTY_JSON_OBJECT; + } + + var unwrapped = value(field); + if (unwrapped == null || unwrapped.getValueType() != JsonValue.ValueType.OBJECT) { + return JsonValue.EMPTY_JSON_OBJECT; + } + + return (JsonObject) unwrapped; + } + + /** + * Get a list property while unwrapping values and only keeping objects. + * + * @param object json-ld + * @param key key + * @return list of values + */ + public static List listOfObjects(JsonObject object, String key) { + JsonValue field = object.get(key); + if (field == null) { + return List.of(); + } + return listOfObjects(field); + } + + /** + * Get a list of strings. defaults to empty list + * + * @param object json-ld + * @param key key + * @return string list or empty list + */ + public static List stringList(JsonObject object, String key) { + JsonValue field = object.get(key); + if (field == null) { + return List.of(); + } + return list(field).stream() + .map(JsonLdUtils::string) + .toList(); + } + + /** + * Get a boolean property. defaults to null + * + * @param object json-ld + * @param key key + * @return boolean or null + */ + public static Boolean bool(JsonObject object, String key) { + JsonValue field = object.get(key); + if (field == null) { + return null; + } + return bool(field); + } +} + diff --git a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/utils/Prop.java b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/utils/Prop.java new file mode 100644 index 0000000..c53f102 --- /dev/null +++ b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/utils/Prop.java @@ -0,0 +1,219 @@ +package org.upm.inesdata.federated.utils; + +import lombok.experimental.UtilityClass; + +/** + * Constants for used JSON-LD Vocabulary. + *

+ * Please note, that due to how JSON-LD / ontologies are defined, all property names of a namespace are just + * mixed together on the same level. A property, e.g. type, might be used in multiple classes, which is an + * abstraction leak by design. + */ +@UtilityClass +public class Prop { + public final String ID = "@id"; + public final String TYPE = "@type"; + public final String VALUE = "@value"; + public final String CONTEXT = "@context"; + public final String LANGUAGE = "@language"; + public final String PROPERTIES = "properties"; + + @UtilityClass + public class Edc { + public final String CTX = "https://w3id.org/edc/v0.0.1/ns/"; + public final String CTX_ALIAS = "edc"; + public final String TYPE_ASSET = CTX + "Asset"; + public final String TYPE_DATA_ADDRESS = CTX + "DataAddress"; + public final String ID = CTX + "id"; + public final String PARTICIPANT_ID = CTX + "participantId"; + public final String PROPERTIES = CTX + "properties"; + public final String PRIVATE_PROPERTIES = CTX + "privateProperties"; + public final String DATA_ADDRESS = CTX + "dataAddress"; + public final String TYPE = CTX + "type"; + public final String DATA_ADDRESS_TYPE_HTTP_DATA = "HttpData"; + public final String DATA_ADDRESS_TYPE_HTTP_PROXY = "HttpProxy"; + public final String BASE_URL = CTX + "baseUrl"; + public final String METHOD = CTX + "method"; + public final String CONTENT_TYPE = CTX + "contentType"; + public final String QUERY_PARAMS = CTX + "queryParams"; + public final String AUTH_KEY = CTX + "authKey"; + public final String AUTH_CODE = CTX + "authCode"; + public final String SECRET_NAME = CTX + "secretName"; + public final String PROXY_METHOD = CTX + "proxyMethod"; + public final String PROXY_PATH = CTX + "proxyPath"; + public final String PROXY_QUERY_PARAMS = CTX + "proxyQueryParams"; + public final String PROXY_BODY = CTX + "proxyBody"; + + // Transfer Request Related + public static String TYPE_TRANSFER_REQUEST = CTX + "TransferRequest"; + public final String CONNECTOR_ADDRESS = CTX + "connectorAddress"; + public final String CONTRACT_ID = CTX + "contractId"; + public final String CONNECTOR_ID = CTX + "connectorId"; + public final String ASSET_ID = CTX + "assetId"; + public final String DATA_DESTINATION = CTX + "dataDestination"; + public final String RECEIVER_HTTP_ENDPOINT = CTX + "receiverHttpEndpoint"; + } + + /** + * DCAT Vocabulary, see https://www.w3.org/TR/vocab-dcat-3 + */ + @UtilityClass + public class Dcat { + /** + * Context as specified in https://www.w3.org/TR/vocab-dcat-3/#normative-namespaces + */ + public final String CTX = "http://www.w3.org/ns/dcat#"; + + /** + * Context as used in the Core EDC, or atleast how its output from a DCAT request + */ + public final String CTX_WRONG_BUT_USED_BY_CORE_EDC = "https://www.w3.org/ns/dcat/"; + + public final String DATASET = CTX + "dataset"; + public final String DISTRIBUTION = CTX + "distribution"; + public final String DISTRIBUTION_AS_USED_BY_CORE_EDC = CTX_WRONG_BUT_USED_BY_CORE_EDC + "distribution"; + public final String VERSION = CTX + "version"; + public final String KEYWORDS = CTX + "keyword"; + public final String LANDING_PAGE = CTX + "landingPage"; + public final String MEDIATYPE = CTX + "mediaType"; + public final String START_DATE = CTX + "startDate"; + public final String END_DATE = CTX + "endDate"; + public final String DOWNLOAD_URL = CTX + "downloadURL"; + } + + /** + * ODRL Vocabulary, see DCAT 3 Specification + */ + @UtilityClass + public class Odrl { + public final String CTX = "http://www.w3.org/ns/odrl/2/"; + public final String HAS_POLICY = CTX + "hasPolicy"; + public final String ACTION = CTX + "action"; + public final String TYPE = CTX + "type"; + public final String CONSTRAINT = CTX + "constraint"; + public final String AND = CTX + "and"; + public final String PERMISSION = CTX + "permission"; + public final String LEFT_OPERAND = CTX + "leftOperand"; + public final String RIGHT_OPERAND = CTX + "rightOperand"; + public final String USE = "USE"; + } + + /** + * Dcterms Metadata Terms Vocabulary, see DCMI Metadata Terms + */ + @UtilityClass + public class Dcterms { + public final String CTX = "http://purl.org/dc/terms/"; + public final String IDENTIFIER = CTX + "identifier"; + public final String TITLE = CTX + "title"; + public final String DESCRIPTION = CTX + "description"; + public final String LANGUAGE = CTX + "language"; + public final String CREATOR = CTX + "creator"; + public final String PUBLISHER = CTX + "publisher"; + public final String LICENSE = CTX + "license"; + public final String TEMPORAL = CTX + "temporal"; + public final String ACCRUAL_PERIODICITY = CTX + "accrualPeriodicity"; + public final String SPATIAL = CTX + "spatial"; + public final String RIGHTS_HOLDER = CTX + "rightsHolder"; + public final String RIGHTS = CTX + "rights"; + public final String RIGHTS_STATEMENT = CTX + "RightsStatement"; + } + + /** + * Dcterms Metadata Terms Vocabulary, see DCAT 3 Specification + */ + @UtilityClass + public class SovityDcatExt { + public final String CTX = "https://semantic.sovity.io/dcat-ext#"; + public final String CUSTOM_JSON = CTX + "customJson"; + public final String PRIVATE_CUSTOM_JSON = CTX + "privateCustomJson"; + public final String DATA_SOURCE_AVAILABILITY = CTX + "dataSourceAvailability"; + public final String DATA_SOURCE_AVAILABILITY_ON_REQUEST = "ON_REQUEST"; + public final String CONTACT_EMAIL = CTX + "contactEmail"; + public final String CONTACT_PREFERRED_EMAIL_SUBJECT = CTX + "contactPreferredEmailSubject"; + + @UtilityClass + public class HttpDatasourceHints { + public final String METHOD = CTX + "httpDatasourceHintsProxyMethod"; + public final String PATH = CTX + "httpDatasourceHintsProxyPath"; + public final String QUERY_PARAMS = CTX + "httpDatasourceHintsProxyQueryParams"; + public final String BODY = CTX + "httpDatasourceHintsProxyBody"; + } + } + + @UtilityClass + public class SovityMessageExt { + public final String CTX = "https://semantic.sovity.io/message/generic/"; + public final String REQUEST = CTX + "request"; + public final String RESPONSE = CTX + "response"; + public final String ERROR_MESSAGE = CTX + "errorMessage"; + public final String HEADER = CTX + "header"; + public final String BODY = CTX + "body"; + } + + /** + * FOAF Vocabulary + */ + @UtilityClass + public class Foaf { + public final String CTX = "http://xmlns.com/foaf/0.1/"; + public final String ORGANIZATION = CTX + "Organization"; + public final String NAME = CTX + "name"; + public final String HOMEPAGE = CTX + "homepage"; + } + + /** + * Namespace mobilitydcatap as specified in + * mobilityDCAT-AP + */ + @UtilityClass + public class MobilityDcatAp { + public final String CTX = "https://w3id.org/mobilitydcat-ap/"; + public final String MOBILITY_THEME = CTX + "mobilityTheme"; + + @UtilityClass + public class DataCategoryProps { + public final String CTX = "https://w3id.org/mobilitydcat-ap/mobility-theme/"; + public final String DATA_CATEGORY = CTX + "data-content-category"; + public final String DATA_SUBCATEGORY = CTX + "data-content-sub-category"; + } + + public final String TRANSPORT_MODE = CTX + "transportMode"; + public final String GEO_REFERENCE_METHOD = CTX + "georeferencingMethod"; + public final String MOBILITY_DATA_STANDARD = CTX + "mobilityDataStandard"; + + // Optional property of mobilitydcatap:mobilityDataStandard + public final String SCHEMA = CTX + "schema"; + } + + /** + * Namespace skos as specified in + * mobilityDCAT-AP + */ + @UtilityClass + public class Skos { + public final String CTX = "http://www.w3.org/2004/02/skos/core#"; + public final String PREF_LABEL = CTX + "prefLabel"; + } + + /** + * Namespace adms as specified in + * mobilityDCAT-AP + */ + @UtilityClass + public class Adms { + public final String CTX = "http://www.w3.org/ns/adms#"; + public final String SAMPLE = CTX + "sample"; + } + + /** + * Namespace rdfs as specified in + * mobilityDCAT-AP + */ + @UtilityClass + public class Rdfs { + public final String CTX = "http://www.w3.org/2000/01/rdf-schema#"; + public final String LITERAL = CTX + "Literal"; + public final String LABEL = CTX + "label"; + } +} diff --git a/launchers/connector/src/main/resources/logback.xml b/launchers/connector/src/main/resources/logback.xml index 841c995..b830fed 100644 --- a/launchers/connector/src/main/resources/logback.xml +++ b/launchers/connector/src/main/resources/logback.xml @@ -11,7 +11,7 @@ - + \ No newline at end of file From ba3d53fc2f9445703beab23450d2da2aec9d5878 Mon Sep 17 00:00:00 2001 From: ppel Date: Thu, 29 Aug 2024 13:18:56 +0200 Subject: [PATCH 2/4] #441281 - Added policies DTO (not working yet) --- .../model/PolicyDefinitionDto.java | 22 ++++++++++ .../federated/model/UiContractOffer.java | 40 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/model/PolicyDefinitionDto.java create mode 100644 extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/model/UiContractOffer.java diff --git a/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/model/PolicyDefinitionDto.java b/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/model/PolicyDefinitionDto.java new file mode 100644 index 0000000..43af5ef --- /dev/null +++ b/extensions/complex-policy-api/src/main/java/org/upm/inesdata/complexpolicy/model/PolicyDefinitionDto.java @@ -0,0 +1,22 @@ +package org.upm.inesdata.complexpolicy.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@Data +@AllArgsConstructor +@RequiredArgsConstructor +@Builder(toBuilder = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@Schema(description = "Policy Definition as required for the Policy Definition Page") +public class PolicyDefinitionDto { + @Schema(description = "Policy Definition ID", requiredMode = Schema.RequiredMode.REQUIRED) + private String policyDefinitionId; + + @Schema(description = "Policy Contents", requiredMode = Schema.RequiredMode.REQUIRED) + private UiPolicy policy; +} diff --git a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/model/UiContractOffer.java b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/model/UiContractOffer.java new file mode 100644 index 0000000..bb87df4 --- /dev/null +++ b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/model/UiContractOffer.java @@ -0,0 +1,40 @@ +package org.upm.inesdata.federated.model; + + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import org.upm.inesdata.complexpolicy.model.UiPolicy; + +@Data +@AllArgsConstructor +@RequiredArgsConstructor +@Builder(toBuilder = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@Schema(description = "Catalog Data Offer's Contract Offer as required by the UI") +public class UiContractOffer { + @Schema(description = "Contract Offer ID", requiredMode = Schema.RequiredMode.REQUIRED) + private String contractOfferId; + + @Schema(description = "Policy", requiredMode = Schema.RequiredMode.REQUIRED) + private UiPolicy policy; + + public String getContractOfferId() { + return contractOfferId; + } + + public void setContractOfferId(String contractOfferId) { + this.contractOfferId = contractOfferId; + } + + public UiPolicy getPolicy() { + return policy; + } + + public void setPolicy(UiPolicy policy) { + this.policy = policy; + } +} From 0a6b86da75000efcf67cfcf5457123f636a4ab10 Mon Sep 17 00:00:00 2001 From: ppel Date: Thu, 5 Sep 2024 07:49:44 +0200 Subject: [PATCH 3/4] #441281 - Modified ContractOffer transformer --- .../FederatedCatalogCacheApiController.java | 596 +----------------- ...nObjectFromUiContractOfferTransformer.java | 31 +- .../connector/src/main/resources/logback.xml | 2 +- 3 files changed, 47 insertions(+), 582 deletions(-) diff --git a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/controller/FederatedCatalogCacheApiController.java b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/controller/FederatedCatalogCacheApiController.java index 4881679..08f0045 100644 --- a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/controller/FederatedCatalogCacheApiController.java +++ b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/controller/FederatedCatalogCacheApiController.java @@ -4,7 +4,6 @@ import jakarta.json.JsonArray; import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; -import jakarta.json.JsonReader; import jakarta.json.JsonValue; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.POST; @@ -27,8 +26,6 @@ import org.upm.inesdata.federated.utils.Prop; import org.upm.inesdata.spi.federated.FederatedCatalogCacheService; -import java.io.StringReader; - import static jakarta.json.stream.JsonCollectors.toJsonArray; import static org.eclipse.edc.spi.query.QuerySpec.EDC_QUERY_SPEC_TYPE; import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; @@ -84,564 +81,12 @@ public JsonArray getFederatedCatalog(JsonObject querySpecJson) { .orElseThrow(InvalidRequestException::new); } - String jsonString = """ - [ - { - "@id":"579097eb-12e1-4d88-bba9-1cabd08a8e03", - "@type":"http://www.w3.org/ns/dcat#Catalog", - "https://w3id.org/dspace/v0.8/participantId":"connector-c1", - "http://www.w3.org/ns/dcat#service":[ - { - "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", - "@type":"http://www.w3.org/ns/dcat#DataService", - "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", - "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", - "http://purl.org/dc/terms/terms":"dspace:connector", - "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" - } - ], - "https://w3id.org/edc/v0.0.1/ns/originator":"http://connector-c1:19194/protocol", - "https://w3id.org/edc/v0.0.1/ns/participantId":"connector-c1", - "http://www.w3.org/ns/dcat#dataset":[ - { - "@id":"Asset 2008", - "@type":"http://www.w3.org/ns/dcat#Dataset", - "http://www.w3.org/ns/dcat#distribution":[ - { - "@type":"http://www.w3.org/ns/dcat#Distribution", - "http://purl.org/dc/terms/format":{ - "@id":"HttpData-PULL" - }, - "http://www.w3.org/ns/dcat#accessService":{ - "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", - "@type":"http://www.w3.org/ns/dcat#DataService", - "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", - "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", - "http://purl.org/dc/terms/terms":"dspace:connector", - "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" - } - }, - { - "@type":"http://www.w3.org/ns/dcat#Distribution", - "http://purl.org/dc/terms/format":{ - "@id":"HttpData-PUSH" - }, - "http://www.w3.org/ns/dcat#accessService":{ - "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", - "@type":"http://www.w3.org/ns/dcat#DataService", - "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", - "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", - "http://purl.org/dc/terms/terms":"dspace:connector", - "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" - } - }, - { - "@type":"http://www.w3.org/ns/dcat#Distribution", - "http://purl.org/dc/terms/format":{ - "@id":"AmazonS3-PULL" - }, - "http://www.w3.org/ns/dcat#accessService":{ - "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", - "@type":"http://www.w3.org/ns/dcat#DataService", - "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", - "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", - "http://purl.org/dc/terms/terms":"dspace:connector", - "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" - } - }, - { - "@type":"http://www.w3.org/ns/dcat#Distribution", - "http://purl.org/dc/terms/format":{ - "@id":"AmazonS3-PUSH" - }, - "http://www.w3.org/ns/dcat#accessService":{ - "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", - "@type":"http://www.w3.org/ns/dcat#DataService", - "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", - "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", - "http://purl.org/dc/terms/terms":"dspace:connector", - "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" - } - } - ], - "https://w3id.org/edc/v0.0.1/ns/assetType":"machineLearning", - "http://purl.org/dc/terms/format":"", - "https://w3id.org/edc/v0.0.1/ns/version":"Asset 2008", - "http://www.w3.org/ns/dcat#keyword":"test", - "http://www.w3.org/ns/dcat#byteSize":"", - "https://w3id.org/edc/v0.0.1/ns/name":"Asset 2008", - "https://w3id.org/edc/v0.0.1/ns/participantId":"connector-c1", - "https://w3id.org/edc/v0.0.1/ns/assetData":{ - "https://w3id.org/edc/v0.0.1/ns/machine-learning-vocabulary":[ - { - "https://w3id.org/edc/v0.0.1/ns/title":[ - { - "@value":"title vocab" - } - ], - "https://w3id.org/edc/v0.0.1/ns/keyword":[ - { - "@value":"test" - }, - { - "@value":"conn1" - } - ], - "https://w3id.org/edc/v0.0.1/ns/trainedOn":[ - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-object" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-object" - } - ], - "https://w3id.org/edc/v0.0.1/ns/description":[ - { - "@value":"desc-object" - } - ], - "https://w3id.org/edc/v0.0.1/ns/url":[ - { - "@value":"desc-url" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-object-2" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-object-2" - } - ], - "https://w3id.org/edc/v0.0.1/ns/description":[ - { - "@value":"desc-object-2" - } - ], - "https://w3id.org/edc/v0.0.1/ns/url":[ - { - "@value":"desc-url-2" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-object-3" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-object-3" - } - ], - "https://w3id.org/edc/v0.0.1/ns/description":[ - { - "@value":"desc-object-3" - } - ], - "https://w3id.org/edc/v0.0.1/ns/url":[ - { - "@value":"desc-url-3" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-object-4" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-object-4" - } - ], - "https://w3id.org/edc/v0.0.1/ns/description":[ - { - "@value":"desc-object-4" - } - ], - "https://w3id.org/edc/v0.0.1/ns/url":[ - { - "@value":"desc-url-4" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-object-5" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-object-5" - } - ], - "https://w3id.org/edc/v0.0.1/ns/description":[ - { - "@value":"desc-object-5" - } - ], - "https://w3id.org/edc/v0.0.1/ns/url":[ - { - "@value":"desc-url-5" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-object-6" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-object-6 fjhkdshfsdjkfh djskfhsdjkfh sdjkfhsdjkfhs jkfdshjkfh sdkfjhsdjkfheuiwfhwefj dfbfewjfbewifu fewbfuwbfe" - } - ], - "https://w3id.org/edc/v0.0.1/ns/description":[ - { - "@value":"desc-object-6" - } - ], - "https://w3id.org/edc/v0.0.1/ns/url":[ - { - "@value":"desc-url-6" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-object-7" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-object-7" - } - ], - "https://w3id.org/edc/v0.0.1/ns/description":[ - { - "@value":"desc-object-7" - } - ], - "https://w3id.org/edc/v0.0.1/ns/url":[ - { - "@value":"desc-url-7" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-object-8" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-object-8" - } - ], - "https://w3id.org/edc/v0.0.1/ns/description":[ - { - "@value":"desc-object-8" - } - ], - "https://w3id.org/edc/v0.0.1/ns/url":[ - { - "@value":"desc-url-8" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-object-9" - } - ], - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-object-9" - } - ], - "https://w3id.org/edc/v0.0.1/ns/description":[ - { - "@value":"desc-object-9" - } - ], - "https://w3id.org/edc/v0.0.1/ns/url":[ - { - "@value":"desc-url-9" - } - ] - } - ], - "https://w3id.org/edc/v0.0.1/ns/complexProperty":[ - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-1" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-1" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-2" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-2" - } - ] - }, - { - "https://w3id.org/edc/v0.0.1/ns/identifier":[ - { - "@value":"id-3" - } - ], - "https://w3id.org/edc/v0.0.1/ns/name":[ - { - "@value":"name-3" - } - ] - } - ], - "https://w3id.org/edc/v0.0.1/ns/objectProperty":[ - { - "https://w3id.org/edc/v0.0.1/ns/id":[ - { - "@value":"id-single-object" - } - ], - "https://w3id.org/edc/v0.0.1/ns/notation":[ - { - "@value":"notation-single-object" - } - ] - } - ], - "https://w3id.org/edc/v0.0.1/ns/otherProperty":[ - { - "@value":"other property" - } - ] - } - ] - }, - "http://purl.org/dc/terms/description":"

Asset 2008

", - "https://w3id.org/edc/v0.0.1/ns/id":"Asset 2008", - "https://w3id.org/edc/v0.0.1/ns/contenttype":"", - "https://w3id.org/edc/v0.0.1/ns/shortDescription":"Asset 2008", - "http://www.w3.org/ns/odrl/2/hasPolicy":[ - { - "contractOfferId":"YWx3YXlzLXRydWUtY29udHJhY3Q=:QXNzZXQgMjAwOA==:N2Y5ZDYwZGUtYjZkZC00NWQyLWIzZmQtNzBiYmY2NTQ2MzU1", - "policy":{ - "policyJsonLd":"{\\"@id\\":\\"2b8de936-dab3-4e9e-98dc-ca9a2a09bf4e\\",\\"@type\\":\\"http://www.w3.org/ns/odrl/2/Set\\",\\"http://www.w3.org/ns/odrl/2/permission\\":[{\\"http://www.w3.org/ns/odrl/2/action\\":{\\"@id\\":\\"USE\\"},\\"http://www.w3.org/ns/odrl/2/constraint\\":[{\\"http://www.w3.org/ns/odrl/2/leftOperand\\":[{\\"@id\\":\\"ALWAYS_TRUE\\"}],\\"http://www.w3.org/ns/odrl/2/operator\\":[{\\"@id\\":\\"http://www.w3.org/ns/odrl/2/eq\\"}],\\"http://www.w3.org/ns/odrl/2/rightOperand\\":{\\"@value\\":\\"true\\"}}]}],\\"http://www.w3.org/ns/odrl/2/prohibition\\":[],\\"http://www.w3.org/ns/odrl/2/obligation\\":[]}", - "expression":{ - "type":"CONSTRAINT", - "constraint":{ - "left":"ALWAYS_TRUE", - "operator":"EQ", - "right":{ - "type":"STRING", - "value":"true" - } - } - }, - "errors":[ - \s - ] - } - }, - { - "contractOfferId":"aW5lc2RhdGEtY29udHJhY3Q=:QXNzZXQgMjAwOA==:YWY1OWNlNWItOGM4MC00OTE3LWFmNDYtZDc1MTI4MmNlODJj", - "policy":{ - "policyJsonLd":"{\\"@id\\":\\"6a605ec9-3834-4450-99e3-5e7ce0731588\\",\\"@type\\":\\"http://www.w3.org/ns/odrl/2/Set\\",\\"http://www.w3.org/ns/odrl/2/permission\\":[{\\"http://www.w3.org/ns/odrl/2/action\\":{\\"@id\\":\\"USE\\"},\\"http://www.w3.org/ns/odrl/2/constraint\\":[{\\"http://www.w3.org/ns/odrl/2/leftOperand\\":[{\\"@id\\":\\"POLICY_EVALUATION_TIME\\"}],\\"http://www.w3.org/ns/odrl/2/operator\\":[{\\"@id\\":\\"http://www.w3.org/ns/odrl/2/lt\\"}],\\"http://www.w3.org/ns/odrl/2/rightOperand\\":{\\"@value\\":\\"2024-12-31T23:59:59+01:00\\"}}]}],\\"http://www.w3.org/ns/odrl/2/prohibition\\":[],\\"http://www.w3.org/ns/odrl/2/obligation\\":[]}", - "expression":{ - "type":"CONSTRAINT", - "constraint":{ - "left":"POLICY_EVALUATION_TIME", - "operator":"LT", - "right":{ - "type":"STRING", - "value":"2024-12-31T23:59:59+01:00" - } - } - }, - "errors":[ - \s - ] - } - } - ] - }, - { - "@id":"another-asset", - "@type":"http://www.w3.org/ns/dcat#Dataset", - "http://www.w3.org/ns/dcat#distribution":[ - { - "@type":"http://www.w3.org/ns/dcat#Distribution", - "http://purl.org/dc/terms/format":{ - "@id":"HttpData-PULL" - }, - "http://www.w3.org/ns/dcat#accessService":{ - "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", - "@type":"http://www.w3.org/ns/dcat#DataService", - "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", - "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", - "http://purl.org/dc/terms/terms":"dspace:connector", - "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" - } - }, - { - "@type":"http://www.w3.org/ns/dcat#Distribution", - "http://purl.org/dc/terms/format":{ - "@id":"HttpData-PUSH" - }, - "http://www.w3.org/ns/dcat#accessService":{ - "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", - "@type":"http://www.w3.org/ns/dcat#DataService", - "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", - "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", - "http://purl.org/dc/terms/terms":"dspace:connector", - "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" - } - }, - { - "@type":"http://www.w3.org/ns/dcat#Distribution", - "http://purl.org/dc/terms/format":{ - "@id":"AmazonS3-PULL" - }, - "http://www.w3.org/ns/dcat#accessService":{ - "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", - "@type":"http://www.w3.org/ns/dcat#DataService", - "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", - "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", - "http://purl.org/dc/terms/terms":"dspace:connector", - "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" - } - }, - { - "@type":"http://www.w3.org/ns/dcat#Distribution", - "http://purl.org/dc/terms/format":{ - "@id":"AmazonS3-PUSH" - }, - "http://www.w3.org/ns/dcat#accessService":{ - "@id":"6fc9cba4-6c08-4862-8fd5-54cc79825ea3", - "@type":"http://www.w3.org/ns/dcat#DataService", - "http://www.w3.org/ns/dcat#endpointDescription":"dspace:connector", - "http://www.w3.org/ns/dcat#endpointUrl":"http://connector-c1:19194/protocol", - "http://purl.org/dc/terms/terms":"dspace:connector", - "http://purl.org/dc/terms/endpointUrl":"http://connector-c1:19194/protocol" - } - } - ], - "https://w3id.org/edc/v0.0.1/ns/assetType":"machineLearning", - "http://purl.org/dc/terms/format":"", - "https://w3id.org/edc/v0.0.1/ns/version":"another-asset-version", - "http://www.w3.org/ns/dcat#keyword":"conn1,test", - "http://www.w3.org/ns/dcat#byteSize":"", - "https://w3id.org/edc/v0.0.1/ns/name":"another-asset-name", - "https://w3id.org/edc/v0.0.1/ns/participantId":"connector-c1", - "https://w3id.org/edc/v0.0.1/ns/assetData":{ - "https://w3id.org/edc/v0.0.1/ns/machine-learning-vocabulary":[ - { - "https://w3id.org/edc/v0.0.1/ns/title":[ - { - "@value":"another-asset learning" - } - ], - "https://w3id.org/edc/v0.0.1/ns/keyword":[ - { - "@value":"learning" - } - ] - } - ] - }, - "http://purl.org/dc/terms/description":"

another-asset-long-desc

", - "https://w3id.org/edc/v0.0.1/ns/id":"another-asset", - "https://w3id.org/edc/v0.0.1/ns/contenttype":"", - "https://w3id.org/edc/v0.0.1/ns/shortDescription":"another-asset-short-desc", - "http://www.w3.org/ns/odrl/2/hasPolicy":[ - { - "contractOfferId":"YWx3YXlzLXRydWUtY29udHJhY3Q=:YW5vdGhlci1hc3NldA==:YTc3NThmODItNWMzNS00ZDI3LTgwNmQtODNkZGMzZWY4OGEw", - "policy":{ - "policyJsonLd":"{\\"@id\\":\\"feca33c3-b915-4b4e-a606-8055b1eb6499\\",\\"@type\\":\\"http://www.w3.org/ns/odrl/2/Set\\",\\"http://www.w3.org/ns/odrl/2/permission\\":[{\\"http://www.w3.org/ns/odrl/2/action\\":{\\"@id\\":\\"USE\\"},\\"http://www.w3.org/ns/odrl/2/constraint\\":[{\\"http://www.w3.org/ns/odrl/2/leftOperand\\":[{\\"@id\\":\\"ALWAYS_TRUE\\"}],\\"http://www.w3.org/ns/odrl/2/operator\\":[{\\"@id\\":\\"http://www.w3.org/ns/odrl/2/eq\\"}],\\"http://www.w3.org/ns/odrl/2/rightOperand\\":{\\"@value\\":\\"true\\"}}]}],\\"http://www.w3.org/ns/odrl/2/prohibition\\":[],\\"http://www.w3.org/ns/odrl/2/obligation\\":[]}", - "expression":{ - "type":"CONSTRAINT", - "constraint":{ - "left":"ALWAYS_TRUE", - "operator":"EQ", - "right":{ - "type":"STRING", - "value":"true" - } - } - }, - "errors":[ - \s - ] - } - }, - { - "contractOfferId":"aW5lc2RhdGEtY29udHJhY3Q=:YW5vdGhlci1hc3NldA==:ZmRjYWM5MjQtNDExOC00N2UzLWE2YmUtNzAzNjY4NTEzNmFi", - "policy":{ - "policyJsonLd":"{\\"@id\\":\\"1148f5dc-b54a-4b2f-9e0a-bf98c340d579\\",\\"@type\\":\\"http://www.w3.org/ns/odrl/2/Set\\",\\"http://www.w3.org/ns/odrl/2/permission\\":[{\\"http://www.w3.org/ns/odrl/2/action\\":{\\"@id\\":\\"USE\\"},\\"http://www.w3.org/ns/odrl/2/constraint\\":[{\\"http://www.w3.org/ns/odrl/2/leftOperand\\":[{\\"@id\\":\\"POLICY_EVALUATION_TIME\\"}],\\"http://www.w3.org/ns/odrl/2/operator\\":[{\\"@id\\":\\"http://www.w3.org/ns/odrl/2/lt\\"}],\\"http://www.w3.org/ns/odrl/2/rightOperand\\":{\\"@value\\":\\"2024-12-31T23:59:59+01:00\\"}}]}],\\"http://www.w3.org/ns/odrl/2/prohibition\\":[],\\"http://www.w3.org/ns/odrl/2/obligation\\":[]}", - "expression":{ - "type":"CONSTRAINT", - "constraint":{ - "left":"POLICY_EVALUATION_TIME", - "operator":"LT", - "right":{ - "type":"STRING", - "value":"2024-12-31T23:59:59+01:00" - } - } - }, - "errors":[ - \s - ] - } - } - ] - } - ] - } - ] - """; - -/* JsonArray response = service.searchPagination(querySpec).orElseThrow(exceptionMapper(QuerySpec.class, null)).stream() - .map(it -> transformerRegistry.transform(it, JsonObject.class)) - .peek(r -> r.onFailure(f -> monitor.warning(f.getFailureDetail()))).filter(Result::succeeded) - .map(Result::getContent) - .map(this::modifyPolicyResponse) - .collect(toJsonArray());*/ - - JsonReader jsonReader = Json.createReader(new StringReader(jsonString)); - JsonArray jsonArray = jsonReader.readArray(); - jsonReader.close(); - - return jsonArray; + return service.searchPagination(querySpec).orElseThrow(exceptionMapper(QuerySpec.class, null)).stream() + .map(it -> transformerRegistry.transform(it, JsonObject.class)) + .peek(r -> r.onFailure(f -> monitor.warning(f.getFailureDetail()))).filter(Result::succeeded) + .map(Result::getContent) + .map(this::modifyPolicyResponse) + .collect(toJsonArray()); } private JsonObject modifyPolicyResponse(JsonObject originalResponse) { @@ -650,26 +95,45 @@ private JsonObject modifyPolicyResponse(JsonObject originalResponse) { JsonArrayBuilder datasetArrayBuilder = Json.createArrayBuilder(); for (JsonValue datasetElement : datasets) { - JsonObject dataset = datasetElement.asJsonObject(); if (dataset.getJsonArray(Prop.Odrl.HAS_POLICY) != null) { + JsonArray existingPolicies = dataset.getJsonArray(Prop.Odrl.HAS_POLICY); + var contractOffers = JsonLdUtils.listOfObjects(dataset, Prop.Odrl.HAS_POLICY).stream() .map(this::buildContractOffer) .map(this::buildUiContractOffer) .toList(); JsonArrayBuilder uiContractOffersJsonBuilder = Json.createArrayBuilder(); - contractOffers.forEach(offer -> uiContractOffersJsonBuilder.add(transformerRegistry.transform(offer, JsonObject.class).getContent())); - + contractOffers.forEach(offer -> uiContractOffersJsonBuilder.add( + transformerRegistry.transform(offer, JsonObject.class).getContent())); JsonArray uiContractOffersJson = uiContractOffersJsonBuilder.build(); + JsonArrayBuilder newHasPolicyArrayBuilder = Json.createArrayBuilder(); + + for (int i = 0; i < uiContractOffersJson.size(); i++) { + JsonObject complexPolicyElement = uiContractOffersJson.getJsonObject(i); + JsonValue offerElement = i < existingPolicies.size() ? existingPolicies.get(i) : null; + + JsonObject newHasPolicyElement = Json.createObjectBuilder() + .add(Prop.Edc.CTX + "complexPolicy", complexPolicyElement) + .add(Prop.Edc.CTX + "offer", offerElement) + .build(); + + newHasPolicyArrayBuilder.add(newHasPolicyElement); + } + + JsonArray newHasPolicyArray = newHasPolicyArrayBuilder.build(); + JsonObject modifiedDatasetJson = Json.createObjectBuilder(dataset) .remove(Prop.Odrl.HAS_POLICY) - .add(Prop.Odrl.HAS_POLICY, uiContractOffersJson) + .add(Prop.Odrl.HAS_POLICY, newHasPolicyArray) .build(); datasetArrayBuilder.add(modifiedDatasetJson); + } else { + datasetArrayBuilder.add(dataset); } } @@ -691,7 +155,7 @@ private DspContractOffer buildContractOffer(JsonObject json) { private UiPolicy buildUiPolicy(DspContractOffer contractOffer) { JsonArrayBuilder typeArrayBuilder = Json.createArrayBuilder(); - typeArrayBuilder.add("http://www.w3.org/ns/odrl/2/Set"); + typeArrayBuilder.add(Prop.Odrl.CTX + "Set"); JsonArray typeArray = typeArrayBuilder.build(); diff --git a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/transformer/JsonObjectFromUiContractOfferTransformer.java b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/transformer/JsonObjectFromUiContractOfferTransformer.java index 94044d3..084f337 100644 --- a/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/transformer/JsonObjectFromUiContractOfferTransformer.java +++ b/extensions/federated-catalog-cache-api/src/main/java/org/upm/inesdata/federated/transformer/JsonObjectFromUiContractOfferTransformer.java @@ -16,6 +16,7 @@ import org.upm.inesdata.complexpolicy.model.UiPolicyExpression; import org.upm.inesdata.complexpolicy.model.UiPolicyLiteral; import org.upm.inesdata.federated.model.UiContractOffer; +import org.upm.inesdata.federated.utils.Prop; import java.io.StringReader; @@ -43,15 +44,15 @@ public Class getOutputType() { @Override public @Nullable JsonObject transform(@NotNull UiContractOffer input, @NotNull TransformerContext context) { JsonObjectBuilder jsonObjectBuilder = jsonFactory.createObjectBuilder(); - jsonObjectBuilder.add("contractOfferId", input.getContractOfferId()); + jsonObjectBuilder.add(Prop.Edc.CTX + "contractOfferId", input.getContractOfferId()); UiPolicy policy = input.getPolicy(); if (policy != null) { JsonObjectBuilder policyBuilder = jsonFactory.createObjectBuilder(); - policyBuilder.add("policyJsonLd", policy.getPolicyJsonLd()); + policyBuilder.add(Prop.Edc.CTX + "policyJsonLd", policy.getPolicyJsonLd()); if (policy.getExpression() != null) { - policyBuilder.add("expression", transformPolicyExpression(policy.getExpression())); + policyBuilder.add(Prop.Edc.CTX + "expression", transformPolicyExpression(policy.getExpression())); } JsonArrayBuilder errorsBuilder = jsonFactory.createArrayBuilder(); @@ -60,9 +61,9 @@ public Class getOutputType() { errorsBuilder.add(error); } } - policyBuilder.add("errors", errorsBuilder); + policyBuilder.add(Prop.Edc.CTX + "errors", errorsBuilder); - jsonObjectBuilder.add("policy", policyBuilder); + jsonObjectBuilder.add(Prop.Edc.CTX + "policy", policyBuilder); } return jsonObjectBuilder.build(); @@ -74,18 +75,18 @@ private JsonValue transformPolicyExpression(UiPolicyExpression expression) { } JsonObjectBuilder expressionBuilder = jsonFactory.createObjectBuilder(); - expressionBuilder.add("type", expression.getType().name()); + expressionBuilder.add(Prop.Edc.CTX + "type", expression.getType().name()); if (expression.getExpressions() != null) { JsonArrayBuilder expressionsArrayBuilder = jsonFactory.createArrayBuilder(); for (UiPolicyExpression subExpression : expression.getExpressions()) { expressionsArrayBuilder.add(transformPolicyExpression(subExpression)); } - expressionBuilder.add("expressions", expressionsArrayBuilder); + expressionBuilder.add(Prop.Edc.CTX + "expressions", expressionsArrayBuilder); } if (expression.getConstraint() != null) { - expressionBuilder.add("constraint", transformPolicyConstraint(expression.getConstraint())); + expressionBuilder.add(Prop.Edc.CTX + "constraint", transformPolicyConstraint(expression.getConstraint())); } return expressionBuilder.build(); @@ -97,9 +98,9 @@ private JsonValue transformPolicyConstraint(UiPolicyConstraint constraint) { } JsonObjectBuilder constraintBuilder = jsonFactory.createObjectBuilder(); - constraintBuilder.add("left", constraint.getLeft()); - constraintBuilder.add("operator", constraint.getOperator().name()); - constraintBuilder.add("right", transformPolicyLiteral(constraint.getRight())); + constraintBuilder.add(Prop.Edc.CTX + "left", constraint.getLeft()); + constraintBuilder.add(Prop.Edc.CTX + "operator", constraint.getOperator().name()); + constraintBuilder.add(Prop.Edc.CTX + "right", transformPolicyLiteral(constraint.getRight())); return constraintBuilder.build(); } @@ -110,21 +111,21 @@ private JsonValue transformPolicyLiteral(UiPolicyLiteral literal) { } JsonObjectBuilder literalBuilder = jsonFactory.createObjectBuilder(); - literalBuilder.add("type", literal.getType().name()); + literalBuilder.add(Prop.Edc.CTX + "type", literal.getType().name()); switch (literal.getType()) { - case STRING -> literalBuilder.add("value", literal.getValue()); + case STRING -> literalBuilder.add(Prop.Edc.CTX + "value", literal.getValue()); case STRING_LIST -> { JsonArrayBuilder listBuilder = jsonFactory.createArrayBuilder(); for (String value : literal.getValueList()) { listBuilder.add(value); } - literalBuilder.add("valueList", listBuilder); + literalBuilder.add(Prop.Edc.CTX + "valueList", listBuilder); } case JSON -> { try { JsonValue jsonValue = Json.createReader(new StringReader(literal.getValue())).readValue(); - literalBuilder.add("value", jsonValue); + literalBuilder.add(Prop.Edc.CTX + "value", jsonValue); } catch (Exception e) { throw new RuntimeException("Error parsing JSON value", e); } diff --git a/launchers/connector/src/main/resources/logback.xml b/launchers/connector/src/main/resources/logback.xml index b830fed..841c995 100644 --- a/launchers/connector/src/main/resources/logback.xml +++ b/launchers/connector/src/main/resources/logback.xml @@ -11,7 +11,7 @@ - + \ No newline at end of file From 21dd1e0e4e9141f4c9daa8bc4dec5c79df80ab72 Mon Sep 17 00:00:00 2001 From: ppel Date: Thu, 5 Sep 2024 10:35:59 +0200 Subject: [PATCH 4/4] Restored dockerfile --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 3712c0d..43d7d91 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -35,4 +35,4 @@ COPY resources/* ${CONNECTOR_RESOURCES}/ # Use "exec" for Kubernetes graceful termination (SIGINT) to reach JVM. ENTRYPOINT [ "sh", "-c", \ - "exec java $JVM_ARGS -agentlib:jdwp=transport=dt_socket,address=0.0.0.0:18787,server=y,suspend=y -jar connector.jar"] + "exec java $JVM_ARGS -jar connector.jar"]