From 920cc0161a9230fe57f28be85ce0187a7e9d79c6 Mon Sep 17 00:00:00 2001 From: Jim Marino Date: Mon, 8 May 2023 15:50:55 +0200 Subject: [PATCH] feat: add consumer/provider id support for DSP messages (#2907) Add consumer/provider id support for DSP messages --- ...omContractAgreementMessageTransformer.java | 14 +++- ...ToContractAgreementMessageTransformer.java | 68 +++++++++++++++---- .../DspNegotiationPropertyAndTypeNames.java | 2 + ...ntractAgreementMessageTransformerTest.java | 15 +++- ...ntractAgreementMessageTransformerTest.java | 23 +++++-- 5 files changed, 99 insertions(+), 23 deletions(-) diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org.eclipse.edc.protocol.dsp.negotiation.transform/from/JsonObjectFromContractAgreementMessageTransformer.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org.eclipse.edc.protocol.dsp.negotiation.transform/from/JsonObjectFromContractAgreementMessageTransformer.java index 62362f11ab2..bd6887be421 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org.eclipse.edc.protocol.dsp.negotiation.transform/from/JsonObjectFromContractAgreementMessageTransformer.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org.eclipse.edc.protocol.dsp.negotiation.transform/from/JsonObjectFromContractAgreementMessageTransformer.java @@ -14,6 +14,7 @@ package org.eclipse.edc.protocol.dsp.negotiation.transform.from; +import jakarta.json.Json; import jakarta.json.JsonBuilderFactory; import jakarta.json.JsonObject; import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreementMessage; @@ -27,7 +28,9 @@ import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_AGREEMENT_MESSAGE; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_AGREEMENT; +import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID; +import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID; /** @@ -50,12 +53,21 @@ public JsonObjectFromContractAgreementMessageTransformer(JsonBuilderFactory json builder.add(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID, object.getProcessId()); - var policy = context.transform(object.getContractAgreement().getPolicy(), JsonObject.class); + var agreement = object.getContractAgreement(); + + var policy = context.transform(agreement.getPolicy(), JsonObject.class); if (policy == null) { context.reportProblem("Cannot transform from ContractAgreementMessage with null policy"); return null; } + // add the consumer and provider ids to the agreement + var copiedPolicy = Json.createObjectBuilder(); + policy.forEach(copiedPolicy::add); + policy = copiedPolicy.add(DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID, agreement.getConsumerId()) + .add(DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID, agreement.getProviderId()) + .build(); + builder.add(DSPACE_NEGOTIATION_PROPERTY_AGREEMENT, policy); return builder.build(); diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org.eclipse.edc.protocol.dsp.negotiation.transform/to/JsonObjectToContractAgreementMessageTransformer.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org.eclipse.edc.protocol.dsp.negotiation.transform/to/JsonObjectToContractAgreementMessageTransformer.java index 9100c2e0acb..46d45bbb0b7 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org.eclipse.edc.protocol.dsp.negotiation.transform/to/JsonObjectToContractAgreementMessageTransformer.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org.eclipse.edc.protocol.dsp.negotiation.transform/to/JsonObjectToContractAgreementMessageTransformer.java @@ -14,6 +14,7 @@ package org.eclipse.edc.protocol.dsp.negotiation.transform.to; +import jakarta.json.Json; import jakarta.json.JsonObject; import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreement; import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreementMessage; @@ -23,8 +24,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Set; + import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_AGREEMENT; +import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID; +import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP; import static org.eclipse.edc.protocol.dsp.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; @@ -32,6 +37,8 @@ * Creates a {@link ContractAgreementMessage} from a {@link JsonObject}. */ public class JsonObjectToContractAgreementMessageTransformer extends AbstractJsonLdTransformer { + private static final Set EXCLUDED_POLICY_KEYWORDS = + Set.of(DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID, DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID); public JsonObjectToContractAgreementMessageTransformer() { super(JsonObject.class, ContractAgreementMessage.class); @@ -39,36 +46,71 @@ public JsonObjectToContractAgreementMessageTransformer() { @Override public @Nullable ContractAgreementMessage transform(@NotNull JsonObject object, @NotNull TransformerContext context) { - var builder = ContractAgreementMessage.Builder.newInstance(); - builder.protocol(DATASPACE_PROTOCOL_HTTP); - transformString(object.get(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID), builder::processId, context); + var messageBuilder = ContractAgreementMessage.Builder.newInstance(); + messageBuilder.protocol(DATASPACE_PROTOCOL_HTTP); + transformString(object.get(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID), messageBuilder::processId, context); + + var jsonAgreement = object.getJsonObject(DSPACE_NEGOTIATION_PROPERTY_AGREEMENT); + if (jsonAgreement == null) { + context.reportProblem("Cannot transform to ContractAgreementMessage with null agreement"); + return null; + } - var policy = context.transform(object.getJsonObject(DSPACE_NEGOTIATION_PROPERTY_AGREEMENT), Policy.class); + var filteredJsonAgreement = filterAgreementProperties(jsonAgreement); + + var policy = context.transform(filteredJsonAgreement, Policy.class); if (policy == null) { - context.reportProblem("Cannot transform to ContractAgreementMessage with null policy"); + context.reportProblem("Cannot transform to ContractAgreementMessage with invalid policy"); return null; } - var agreement = contractAgreement(object, policy, context); + var agreement = contractAgreement(object, jsonAgreement, policy, context); if (agreement == null) { context.reportProblem("Cannot transform to ContractAgreementMessage with null agreement"); return null; } - builder.contractAgreement(agreement); + messageBuilder.contractAgreement(agreement); - return builder.build(); + return messageBuilder.build(); + } + + private JsonObject filterAgreementProperties(JsonObject jsonAgreement) { + var copiedJsonAgreement = Json.createObjectBuilder(); + jsonAgreement.entrySet().stream() + .filter(e -> !EXCLUDED_POLICY_KEYWORDS.contains(e.getKey())) + .forEach(e -> copiedJsonAgreement.add(e.getKey(), e.getValue())); + return copiedJsonAgreement.build(); } - private ContractAgreement contractAgreement(JsonObject object, Policy policy, TransformerContext context) { + @Nullable + private ContractAgreement contractAgreement(JsonObject jsonMessage, JsonObject jsonAgreement, Policy policy, TransformerContext context) { var builder = ContractAgreement.Builder.newInstance(); - builder.id(nodeId(object)); - builder.providerId(""); // TODO - builder.consumerId(""); // TODO + var agreementId = nodeId(jsonAgreement); + if (agreementId == null) { + context.reportProblem("No id specified on ContractAgreement"); + return null; + } + builder.id(agreementId); + + var consumerId = jsonAgreement.get(DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID); + if (consumerId == null) { + context.reportProblem("No consumer id specified on ContractAgreement"); + return null; + } + transformString(consumerId, builder::consumerId, context); + + var providerId = jsonAgreement.get(DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID); + if (providerId == null) { + context.reportProblem("No provider id specified on ContractAgreement"); + return null; + } + transformString(providerId, builder::providerId, context); + builder.policy(policy); builder.assetId(policy.getTarget()); - var timestamp = object.getString(DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP); + var timestamp = jsonMessage.getString(DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP); try { builder.contractSigningDate(Long.parseLong(timestamp)); } catch (NumberFormatException exception) { diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/transform/DspNegotiationPropertyAndTypeNames.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/transform/DspNegotiationPropertyAndTypeNames.java index bca95a0b355..4520d93ce26 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/transform/DspNegotiationPropertyAndTypeNames.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/transform/DspNegotiationPropertyAndTypeNames.java @@ -48,6 +48,8 @@ public interface DspNegotiationPropertyAndTypeNames { String DSPACE_NEGOTIATION_PROPERTY_OFFER = DSPACE_SCHEMA + "offer"; String DSPACE_NEGOTIATION_PROPERTY_DATASET = DSPACE_SCHEMA + "dataSet"; String DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP = DSPACE_SCHEMA + "timestamp"; + String DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID = DSPACE_SCHEMA + "consumerId"; + String DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID = DSPACE_SCHEMA + "providerId"; // event types diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/test/java/org/eclipse/edc/protocol/dsp/negotiation/transform/from/JsonObjectFromContractAgreementMessageTransformerTest.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/test/java/org/eclipse/edc/protocol/dsp/negotiation/transform/from/JsonObjectFromContractAgreementMessageTransformerTest.java index 78ae8018930..86d7253af21 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/test/java/org/eclipse/edc/protocol/dsp/negotiation/transform/from/JsonObjectFromContractAgreementMessageTransformerTest.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/test/java/org/eclipse/edc/protocol/dsp/negotiation/transform/from/JsonObjectFromContractAgreementMessageTransformerTest.java @@ -36,7 +36,9 @@ import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_AGREEMENT_MESSAGE; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_AGREEMENT; +import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID; +import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -47,6 +49,8 @@ import static org.mockito.Mockito.when; class JsonObjectFromContractAgreementMessageTransformerTest { + private static final String PROVIDER_ID = "providerId"; + private static final String CONSUMER_ID = "consumerId"; private final JsonBuilderFactory jsonFactory = Json.createBuilderFactory(Map.of()); private final TransformerContext context = mock(TransformerContext.class); @@ -80,7 +84,12 @@ void transform() { assertThat(result.getJsonString(ID).getString()).isNotEmpty(); assertThat(result.getJsonString(TYPE).getString()).isEqualTo(DSPACE_NEGOTIATION_AGREEMENT_MESSAGE); assertThat(result.getJsonString(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID).getString()).isEqualTo(value); - assertThat(result.getJsonObject(DSPACE_NEGOTIATION_PROPERTY_AGREEMENT)).isNotNull(); + + var jsonAgreement = result.getJsonObject(DSPACE_NEGOTIATION_PROPERTY_AGREEMENT); + assertThat(jsonAgreement).isNotNull(); + + assertThat(jsonAgreement.getJsonString(DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID).getString()).isEqualTo(CONSUMER_ID); + assertThat(jsonAgreement.getJsonString(DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID).getString()).isEqualTo(PROVIDER_ID); verify(context, never()).reportProblem(anyString()); } @@ -106,8 +115,8 @@ void transform_nullPolicy() { private ContractAgreement contractAgreement() { return ContractAgreement.Builder.newInstance() .id(String.valueOf(UUID.randomUUID())) - .providerId("agentId") - .consumerId("agentId") + .providerId(PROVIDER_ID) + .consumerId(CONSUMER_ID) .assetId("assetId") .policy(policy()).build(); } diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/test/java/org/eclipse/edc/protocol/dsp/negotiation/transform/to/JsonObjectToContractAgreementMessageTransformerTest.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/test/java/org/eclipse/edc/protocol/dsp/negotiation/transform/to/JsonObjectToContractAgreementMessageTransformerTest.java index a97bf6f625e..7588a8b4cc6 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/test/java/org/eclipse/edc/protocol/dsp/negotiation/transform/to/JsonObjectToContractAgreementMessageTransformerTest.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/test/java/org/eclipse/edc/protocol/dsp/negotiation/transform/to/JsonObjectToContractAgreementMessageTransformerTest.java @@ -35,7 +35,9 @@ import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_TYPE_AGREEMENT; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_AGREEMENT_MESSAGE; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_AGREEMENT; +import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID; +import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID; import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; @@ -47,6 +49,11 @@ import static org.mockito.Mockito.when; class JsonObjectToContractAgreementMessageTransformerTest { + private static final String CONSUMER_ID = "consumerId"; + private static final String PROVIDER_ID = "providerId"; + private static final String AGREEMENT_ID = "agreementId"; + private static final String PROCESS_ID = "processId"; + private static final String MESSAGE_ID = "messageId"; private final JsonBuilderFactory jsonFactory = Json.createBuilderFactory(Map.of()); private final TransformerContext context = mock(TransformerContext.class); @@ -60,11 +67,10 @@ void setUp() { @Test void transform() { - var value = "example"; var message = jsonFactory.createObjectBuilder() - .add(JsonLdKeywords.ID, value) + .add(JsonLdKeywords.ID, MESSAGE_ID) .add(JsonLdKeywords.TYPE, DSPACE_NEGOTIATION_AGREEMENT_MESSAGE) - .add(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID, value) + .add(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID, PROCESS_ID) .add(DSPACE_NEGOTIATION_PROPERTY_AGREEMENT, contractAgreement()) .add(DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP, "123") .build(); @@ -76,10 +82,12 @@ void transform() { assertThat(result).isNotNull(); assertThat(result.getClass()).isEqualTo(ContractAgreementMessage.class); assertThat(result.getProtocol()).isNotEmpty(); - assertThat(result.getProcessId()).isEqualTo(value); + assertThat(result.getProcessId()).isEqualTo(PROCESS_ID); assertThat(result.getContractAgreement()).isNotNull(); assertThat(result.getContractAgreement().getClass()).isEqualTo(ContractAgreement.class); - assertThat(result.getContractAgreement().getId()).isEqualTo(value); + assertThat(result.getContractAgreement().getId()).isEqualTo(AGREEMENT_ID); + assertThat(result.getContractAgreement().getConsumerId()).isEqualTo(CONSUMER_ID); + assertThat(result.getContractAgreement().getProviderId()).isEqualTo(PROVIDER_ID); assertThat(result.getContractAgreement().getAssetId()).isEqualTo("target"); verify(context, never()).reportProblem(anyString()); @@ -123,7 +131,10 @@ void transform_invalidTimestamp() { private JsonObject contractAgreement() { return jsonFactory.createObjectBuilder() + .add(JsonLdKeywords.ID, AGREEMENT_ID) .add(JsonLdKeywords.TYPE, ODRL_POLICY_TYPE_AGREEMENT) + .add(DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID, CONSUMER_ID) + .add(DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID, PROVIDER_ID) .build(); } @@ -139,4 +150,4 @@ private Policy policy() { .target("target") .build(); } -} \ No newline at end of file +}