Skip to content

Commit

Permalink
feat(dsp): implement TransferSuspensionMessage transformers (#3987)
Browse files Browse the repository at this point in the history
* refactor: move common transformers to transformer-core (#3982)

* feat(dsp): implement transfer suspension message transformers
  • Loading branch information
ndr-brt authored Mar 11, 2024
1 parent 99ecae9 commit 108dfe6
Show file tree
Hide file tree
Showing 11 changed files with 422 additions and 49 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/apidoc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
apiGroup: [ 'observability-api', 'public-api', 'management-api', 'control-api' ]
apiGroup: [ 'public-api', 'management-api', 'control-api' ]
env:
rootDir: resources/openapi/yaml/${{ matrix.apiGroup }}
SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_TOKEN }}
Expand Down
32 changes: 0 additions & 32 deletions core/common/transform-dspace/build.gradle.kts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Original file line number Diff line number Diff line change
Expand Up @@ -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}.
*/
Expand All @@ -45,6 +50,9 @@ public class DspTransferProcessTransformExtension implements ServiceExtension {
@Inject
private TypeTransformerRegistry registry;

@Inject
private TypeManager typeManager;

@Override
public String name() {
return NAME;
Expand All @@ -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));
}
}
Original file line number Diff line number Diff line change
@@ -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<TransferSuspensionMessage, JsonObject> {

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();

}
}
Original file line number Diff line number Diff line change
@@ -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<JsonObject, TransferSuspensionMessage> {

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.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<JsonObject, TransferTerminationMessage> {
Expand All @@ -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;
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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());
}
}
Loading

0 comments on commit 108dfe6

Please sign in to comment.