From 30ba4bbbb5e86e2e39401a424eca8b7bb8a1cbc8 Mon Sep 17 00:00:00 2001 From: ndr_brt Date: Mon, 11 Mar 2024 11:47:31 +0100 Subject: [PATCH] feat(dsp): implement transfer suspension message transformers --- core/common/transform-dspace/build.gradle.kts | 32 ------ .../dsp/type/DspPropertyAndTypeNames.java | 1 + ...spTransferProcessPropertyAndTypeNames.java | 2 +- .../DspTransferProcessTransformExtension.java | 36 ++++-- ...mTransferSuspensionMessageTransformer.java | 56 ++++++++++ ...oTransferSuspensionMessageTransformer.java | 105 ++++++++++++++++++ ...TransferTerminationMessageTransformer.java | 5 +- ...nsferSuspensionMessageTransformerTest.java | 70 ++++++++++++ ...nsferSuspensionMessageTransformerTest.java | 98 ++++++++++++++++ .../protocol/TransferSuspensionMessage.java | 64 +++++++++++ 10 files changed, 421 insertions(+), 48 deletions(-) delete mode 100644 core/common/transform-dspace/build.gradle.kts create mode 100644 data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/from/JsonObjectFromTransferSuspensionMessageTransformer.java create mode 100644 data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/to/JsonObjectToTransferSuspensionMessageTransformer.java create mode 100644 data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/from/JsonObjectFromTransferSuspensionMessageTransformerTest.java create mode 100644 data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/to/JsonObjectToTransferSuspensionMessageTransformerTest.java create mode 100644 spi/control-plane/transfer-spi/src/main/java/org/eclipse/edc/connector/transfer/spi/types/protocol/TransferSuspensionMessage.java diff --git a/core/common/transform-dspace/build.gradle.kts b/core/common/transform-dspace/build.gradle.kts deleted file mode 100644 index e6ee99441e6..00000000000 --- a/core/common/transform-dspace/build.gradle.kts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation - * - */ - -plugins { - `java-library` - `maven-publish` -} - -dependencies { - api(project(":spi:common:catalog-spi")) - api(project(":spi:common:core-spi")) - api(project(":spi:common:json-ld-spi")) - api(project(":spi:common:transform-spi")) - - api(libs.jakartaJson) - - implementation(project(":core:common:transform-core")) - - testImplementation(project(":core:common:junit")) - testImplementation(project(":extensions:common:json-ld")) -} diff --git a/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/type/DspPropertyAndTypeNames.java b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/type/DspPropertyAndTypeNames.java index 55278536afb..db2c0047fea 100644 --- a/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/type/DspPropertyAndTypeNames.java +++ b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/type/DspPropertyAndTypeNames.java @@ -25,6 +25,7 @@ public interface DspPropertyAndTypeNames { String DSPACE_PROPERTY_REASON = DSPACE_SCHEMA + "reason"; String DSPACE_PROPERTY_CONSUMER_PID = DSPACE_SCHEMA + "consumerPid"; String DSPACE_PROPERTY_PROVIDER_PID = DSPACE_SCHEMA + "providerPid"; + @Deprecated(since = "0.5.1") String DSPACE_PROPERTY_PROCESS_ID = DSPACE_SCHEMA + "processId"; String DSPACE_PROPERTY_CALLBACK_ADDRESS = DSPACE_SCHEMA + "callbackAddress"; String DSPACE_PROPERTY_STATE = DSPACE_SCHEMA + "state"; diff --git a/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/type/DspTransferProcessPropertyAndTypeNames.java b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/type/DspTransferProcessPropertyAndTypeNames.java index d600f9e5588..7db83f3e6ff 100644 --- a/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/type/DspTransferProcessPropertyAndTypeNames.java +++ b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/type/DspTransferProcessPropertyAndTypeNames.java @@ -24,11 +24,11 @@ public interface DspTransferProcessPropertyAndTypeNames { String DSPACE_TYPE_TRANSFER_REQUEST_MESSAGE = DSPACE_SCHEMA + "TransferRequestMessage"; String DSPACE_TYPE_TRANSFER_START_MESSAGE = DSPACE_SCHEMA + "TransferStartMessage"; String DSPACE_TYPE_TRANSFER_COMPLETION_MESSAGE = DSPACE_SCHEMA + "TransferCompletionMessage"; + String DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE = DSPACE_SCHEMA + "TransferSuspensionMessage"; String DSPACE_TYPE_TRANSFER_TERMINATION_MESSAGE = DSPACE_SCHEMA + "TransferTerminationMessage"; String DSPACE_TYPE_TRANSFER_PROCESS = DSPACE_SCHEMA + "TransferProcess"; String DSPACE_TYPE_TRANSFER_ERROR = DSPACE_SCHEMA + "TransferError"; String DSPACE_PROPERTY_CONTRACT_AGREEMENT_ID = DSPACE_SCHEMA + "agreementId"; String DSPACE_PROPERTY_DATA_ADDRESS = DSPACE_SCHEMA + "dataAddress"; - String DSPACE_PROPERTY_CORRELATION_ID = DSPACE_SCHEMA + "correlationId"; } diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/DspTransferProcessTransformExtension.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/DspTransferProcessTransformExtension.java index 273b03ac5d7..8fd99883bc1 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/DspTransferProcessTransformExtension.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/DspTransferProcessTransformExtension.java @@ -20,20 +20,25 @@ import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.from.JsonObjectFromTransferProcessTransformer; import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.from.JsonObjectFromTransferRequestMessageTransformer; import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.from.JsonObjectFromTransferStartMessageTransformer; +import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.from.JsonObjectFromTransferSuspensionMessageTransformer; import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.from.JsonObjectFromTransferTerminationMessageTransformer; import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.to.JsonObjectToTransferCompletionMessageTransformer; import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.to.JsonObjectToTransferProcessAckTransformer; import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.to.JsonObjectToTransferRequestMessageTransformer; import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.to.JsonObjectToTransferStartMessageTransformer; +import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.to.JsonObjectToTransferSuspensionMessageTransformer; import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.to.JsonObjectToTransferTerminationMessageTransformer; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import java.util.Map; +import static org.eclipse.edc.spi.CoreConstants.JSON_LD; + /** * Provides the transformers for transferprocess message types via the {@link TypeTransformerRegistry}. */ @@ -45,6 +50,9 @@ public class DspTransferProcessTransformExtension implements ServiceExtension { @Inject private TypeTransformerRegistry registry; + @Inject + private TypeManager typeManager; + @Override public String name() { return NAME; @@ -53,19 +61,23 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { var builderFactory = Json.createBuilderFactory(Map.of()); + var objectMapper = typeManager.getMapper(JSON_LD); + + var dspRegistry = registry.forContext("dsp-api"); - var dspApiTransformerRegistry = registry.forContext("dsp-api"); - dspApiTransformerRegistry.register(new JsonObjectFromTransferProcessTransformer(builderFactory)); - dspApiTransformerRegistry.register(new JsonObjectFromTransferStartMessageTransformer(builderFactory)); - dspApiTransformerRegistry.register(new JsonObjectFromTransferCompletionMessageTransformer(builderFactory)); - dspApiTransformerRegistry.register(new JsonObjectFromTransferTerminationMessageTransformer(builderFactory)); - dspApiTransformerRegistry.register(new JsonObjectFromTransferRequestMessageTransformer(builderFactory)); - dspApiTransformerRegistry.register(new JsonObjectFromDataAddressTransformer(builderFactory)); + dspRegistry.register(new JsonObjectFromTransferProcessTransformer(builderFactory)); + dspRegistry.register(new JsonObjectFromTransferStartMessageTransformer(builderFactory)); + dspRegistry.register(new JsonObjectFromTransferCompletionMessageTransformer(builderFactory)); + dspRegistry.register(new JsonObjectFromTransferTerminationMessageTransformer(builderFactory)); + dspRegistry.register(new JsonObjectFromTransferRequestMessageTransformer(builderFactory)); + dspRegistry.register(new JsonObjectFromTransferSuspensionMessageTransformer(builderFactory)); + dspRegistry.register(new JsonObjectFromDataAddressTransformer(builderFactory)); - dspApiTransformerRegistry.register(new JsonObjectToTransferRequestMessageTransformer()); - dspApiTransformerRegistry.register(new JsonObjectToTransferCompletionMessageTransformer()); - dspApiTransformerRegistry.register(new JsonObjectToTransferStartMessageTransformer()); - dspApiTransformerRegistry.register(new JsonObjectToTransferTerminationMessageTransformer()); - dspApiTransformerRegistry.register(new JsonObjectToTransferProcessAckTransformer()); + dspRegistry.register(new JsonObjectToTransferRequestMessageTransformer()); + dspRegistry.register(new JsonObjectToTransferCompletionMessageTransformer()); + dspRegistry.register(new JsonObjectToTransferStartMessageTransformer()); + dspRegistry.register(new JsonObjectToTransferTerminationMessageTransformer()); + dspRegistry.register(new JsonObjectToTransferProcessAckTransformer()); + dspRegistry.register(new JsonObjectToTransferSuspensionMessageTransformer(objectMapper)); } } diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/from/JsonObjectFromTransferSuspensionMessageTransformer.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/from/JsonObjectFromTransferSuspensionMessageTransformer.java new file mode 100644 index 00000000000..5fd59e3d9b1 --- /dev/null +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/from/JsonObjectFromTransferSuspensionMessageTransformer.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.from; + +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObject; +import org.eclipse.edc.connector.transfer.spi.types.protocol.TransferSuspensionMessage; +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 static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_CODE; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_CONSUMER_PID; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_PROVIDER_PID; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_REASON; +import static org.eclipse.edc.protocol.dsp.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE; + +public class JsonObjectFromTransferSuspensionMessageTransformer extends AbstractJsonLdTransformer { + + private final JsonBuilderFactory jsonBuilderFactory; + + public JsonObjectFromTransferSuspensionMessageTransformer(JsonBuilderFactory jsonBuilderFactory) { + super(TransferSuspensionMessage.class, JsonObject.class); + this.jsonBuilderFactory = jsonBuilderFactory; + } + + @Override + public @Nullable JsonObject transform(@NotNull TransferSuspensionMessage message, @NotNull TransformerContext context) { + var builder = jsonBuilderFactory.createObjectBuilder() + .add(ID, message.getId()) + .add(TYPE, DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE) + .add(DSPACE_PROPERTY_CONSUMER_PID, message.getConsumerPid()) + .add(DSPACE_PROPERTY_PROVIDER_PID, message.getProviderPid()) + .add(DSPACE_PROPERTY_REASON, jsonBuilderFactory.createArrayBuilder(message.getReason())); + + addIfNotNull(message.getCode(), DSPACE_PROPERTY_CODE, builder); + + return builder.build(); + + } +} diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/to/JsonObjectToTransferSuspensionMessageTransformer.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/to/JsonObjectToTransferSuspensionMessageTransformer.java new file mode 100644 index 00000000000..e7422408b31 --- /dev/null +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/to/JsonObjectToTransferSuspensionMessageTransformer.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.to; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; +import org.eclipse.edc.connector.transfer.spi.types.protocol.TransferSuspensionMessage; +import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static jakarta.json.JsonValue.ValueType.ARRAY; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_CODE; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_CONSUMER_PID; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_PROVIDER_PID; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_REASON; +import static org.eclipse.edc.protocol.dsp.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE; +import static org.eclipse.edc.protocol.dsp.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_TERMINATION_MESSAGE; + +public class JsonObjectToTransferSuspensionMessageTransformer extends AbstractJsonLdTransformer { + + private final ObjectMapper objectMapper; + + public JsonObjectToTransferSuspensionMessageTransformer(ObjectMapper objectMapper) { + super(JsonObject.class, TransferSuspensionMessage.class); + this.objectMapper = objectMapper; + } + + @Override + public @Nullable TransferSuspensionMessage transform(@NotNull JsonObject messageObject, @NotNull TransformerContext context) { + var builder = TransferSuspensionMessage.Builder.newInstance(); + + if (!transformMandatoryString(messageObject.get(DSPACE_PROPERTY_CONSUMER_PID), builder::consumerPid, context)) { + context.problem() + .missingProperty() + .type(DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE) + .property(DSPACE_PROPERTY_CONSUMER_PID) + .report(); + return null; + } + + if (!transformMandatoryString(messageObject.get(DSPACE_PROPERTY_PROVIDER_PID), builder::providerPid, context)) { + context.problem() + .missingProperty() + .type(DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE) + .property(DSPACE_PROPERTY_PROVIDER_PID) + .report(); + return null; + } + + if (!transformMandatoryString(messageObject.get(DSPACE_PROPERTY_CODE), builder::code, context)) { + context.problem() + .missingProperty() + .type(DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE) + .property(DSPACE_PROPERTY_CODE) + .report(); + return null; + } + + var reasons = messageObject.get(DSPACE_PROPERTY_REASON); + if (reasons != null) { + if (reasons instanceof JsonArray array && !array.isEmpty()) { + builder.reason(array.stream().map(this::deserialize).toList()); + } else { + context.problem() + .unexpectedType() + .type(DSPACE_TYPE_TRANSFER_TERMINATION_MESSAGE) + .property(DSPACE_PROPERTY_REASON) + .actual(reasons.getValueType()) + .expected(ARRAY) + .report(); + } + } + + return builder.build(); + + } + + private Object deserialize(JsonValue it) { + try { + return objectMapper.readValue(it.toString(), Map.class); + } catch (JsonProcessingException e) { + throw new EdcException("Error deserializing 'reason' field."); + } + } +} diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/to/JsonObjectToTransferTerminationMessageTransformer.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/to/JsonObjectToTransferTerminationMessageTransformer.java index eb497740e29..0880874c047 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/to/JsonObjectToTransferTerminationMessageTransformer.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/type/to/JsonObjectToTransferTerminationMessageTransformer.java @@ -28,7 +28,6 @@ import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_PROCESS_ID; import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_PROVIDER_PID; import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_REASON; -import static org.eclipse.edc.protocol.dsp.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_START_MESSAGE; import static org.eclipse.edc.protocol.dsp.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_TERMINATION_MESSAGE; public class JsonObjectToTransferTerminationMessageTransformer extends AbstractJsonLdTransformer { @@ -47,7 +46,7 @@ public JsonObjectToTransferTerminationMessageTransformer() { if (processId == null) { context.problem() .missingProperty() - .type(DSPACE_TYPE_TRANSFER_START_MESSAGE) + .type(DSPACE_TYPE_TRANSFER_TERMINATION_MESSAGE) .property(DSPACE_PROPERTY_CONSUMER_PID) .report(); return null; @@ -60,7 +59,7 @@ public JsonObjectToTransferTerminationMessageTransformer() { if (processId == null) { context.problem() .missingProperty() - .type(DSPACE_TYPE_TRANSFER_START_MESSAGE) + .type(DSPACE_TYPE_TRANSFER_TERMINATION_MESSAGE) .property(DSPACE_PROPERTY_PROVIDER_PID) .report(); return null; diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/from/JsonObjectFromTransferSuspensionMessageTransformerTest.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/from/JsonObjectFromTransferSuspensionMessageTransformerTest.java new file mode 100644 index 00000000000..8fa5fa8a7b5 --- /dev/null +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/from/JsonObjectFromTransferSuspensionMessageTransformerTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.transferprocess.transformer.from; + +import jakarta.json.Json; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonString; +import org.eclipse.edc.connector.transfer.spi.types.protocol.TransferSuspensionMessage; +import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.from.JsonObjectFromTransferSuspensionMessageTransformer; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_CODE; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_CONSUMER_PID; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_PROVIDER_PID; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_REASON; +import static org.eclipse.edc.protocol.dsp.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + + +class JsonObjectFromTransferSuspensionMessageTransformerTest { + + private final JsonBuilderFactory jsonFactory = Json.createBuilderFactory(Map.of()); + private final TransformerContext context = mock(); + + private final JsonObjectFromTransferSuspensionMessageTransformer transformer = + new JsonObjectFromTransferSuspensionMessageTransformer(jsonFactory); + + @Test + void transformTransferSuspensionMessage() { + var message = TransferSuspensionMessage.Builder.newInstance() + .consumerPid("consumerPid") + .providerPid("providerPid") + .protocol("dsp") + .code("testCode") + .reason("testReason") + .build(); + + var result = transformer.transform(message, context); + + assertThat(result).isNotNull(); + assertThat(result.getJsonString(TYPE).getString()).isEqualTo(DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE); + assertThat(result.getJsonString(DSPACE_PROPERTY_CONSUMER_PID).getString()).isEqualTo("consumerPid"); + assertThat(result.getJsonString(DSPACE_PROPERTY_PROVIDER_PID).getString()).isEqualTo("providerPid"); + assertThat(result.getJsonString(DSPACE_PROPERTY_CODE).getString()).isEqualTo("testCode"); + assertThat(result.getJsonArray(DSPACE_PROPERTY_REASON)).hasSize(1).first() + .isInstanceOfSatisfying(JsonString.class, reason -> assertThat(reason.getString()).isEqualTo("testReason")); + + verify(context, never()).reportProblem(anyString()); + } +} diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/to/JsonObjectToTransferSuspensionMessageTransformerTest.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/to/JsonObjectToTransferSuspensionMessageTransformerTest.java new file mode 100644 index 00000000000..1cb2ba52b26 --- /dev/null +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transformer/to/JsonObjectToTransferSuspensionMessageTransformerTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.transferprocess.transformer.to; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.Json; +import org.eclipse.edc.jsonld.util.JacksonJsonLd; +import org.eclipse.edc.protocol.dsp.transferprocess.transformer.type.to.JsonObjectToTransferSuspensionMessageTransformer; +import org.eclipse.edc.transform.spi.ProblemBuilder; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static jakarta.json.Json.createObjectBuilder; +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; +import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_SCHEMA; +import static org.eclipse.edc.protocol.dsp.transferprocess.transformer.to.TestInput.getExpanded; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_CODE; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_CONSUMER_PID; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_PROVIDER_PID; +import static org.eclipse.edc.protocol.dsp.type.DspPropertyAndTypeNames.DSPACE_PROPERTY_REASON; +import static org.eclipse.edc.protocol.dsp.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class JsonObjectToTransferSuspensionMessageTransformerTest { + + private final TransformerContext context = mock(); + private final ObjectMapper objectMapper = JacksonJsonLd.createObjectMapper(); + private final JsonObjectToTransferSuspensionMessageTransformer transformer = + new JsonObjectToTransferSuspensionMessageTransformer(objectMapper); + + @Test + void shouldTransform() { + var json = createObjectBuilder() + .add(CONTEXT, createObjectBuilder().add(VOCAB, DSPACE_SCHEMA)) + .add(TYPE, DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE) + .add(DSPACE_PROPERTY_CONSUMER_PID, "consumerPid") + .add(DSPACE_PROPERTY_PROVIDER_PID, "providerPid") + .add(DSPACE_PROPERTY_CODE, "testCode") + .add(DSPACE_PROPERTY_REASON, Json.createArrayBuilder() + .add(createObjectBuilder().add("complex", "reason")) + .add("reason")) + .build(); + + var result = transformer.transform(getExpanded(json), context); + + assertThat(result).isNotNull(); + + assertThat(result.getProviderPid()).isEqualTo("providerPid"); + assertThat(result.getConsumerPid()).isEqualTo("consumerPid"); + assertThat(result.getReason()).hasSize(2) + .containsOnly(Map.of(DSPACE_SCHEMA + "complex", List.of(Map.of(VALUE, "reason"))), Map.of(VALUE, "reason")); + assertThat(result.getCode()).isEqualTo("testCode"); + + verify(context, never()).reportProblem(anyString()); + } + + @Test + void shouldReportError_whenMissingPids() { + when(context.problem()).thenReturn(new ProblemBuilder(context)); + var reason = Json.createBuilderFactory(Map.of()).createObjectBuilder().add(DSPACE_SCHEMA + "foo", "bar"); + var reasonArray = Json.createBuilderFactory(Map.of()).createArrayBuilder().add(reason).build(); + + var json = createObjectBuilder() + .add(TYPE, DSPACE_TYPE_TRANSFER_SUSPENSION_MESSAGE) + .add(DSPACE_PROPERTY_CODE, "testCode") + .add(DSPACE_PROPERTY_REASON, Json.createBuilderFactory(Map.of()).createArrayBuilder().add(reasonArray).build()) + .build(); + + var result = transformer.transform(getExpanded(json), context); + + assertThat(result).isNull(); + verify(context).reportProblem(anyString()); + } + +} diff --git a/spi/control-plane/transfer-spi/src/main/java/org/eclipse/edc/connector/transfer/spi/types/protocol/TransferSuspensionMessage.java b/spi/control-plane/transfer-spi/src/main/java/org/eclipse/edc/connector/transfer/spi/types/protocol/TransferSuspensionMessage.java new file mode 100644 index 00000000000..83dd1f53d23 --- /dev/null +++ b/spi/control-plane/transfer-spi/src/main/java/org/eclipse/edc/connector/transfer/spi/types/protocol/TransferSuspensionMessage.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.connector.transfer.spi.types.protocol; + +import java.util.ArrayList; +import java.util.List; + +/** + * The {@link TransferSuspensionMessage} is sent by the provider or consumer at any point except a terminal state to + * indicate the data transfer process should be suspended. If the termination was due to an + * error, the sender may include error information. + */ +public class TransferSuspensionMessage extends TransferRemoteMessage { + + private String code; + private List reason = new ArrayList<>(); + + public String getCode() { + return code; + } + + public List getReason() { + return reason; + } + + public static class Builder extends TransferRemoteMessage.Builder { + + private Builder() { + super(new TransferSuspensionMessage()); + } + + public static Builder newInstance() { + return new Builder(); + } + + public Builder code(String code) { + message.code = code; + return this; + } + + public Builder reason(String reason) { + message.reason.add(reason); + return this; + } + + public Builder reason(List reason) { + message.reason.addAll(reason); + return this; + } + + } +}