diff --git a/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/ContractNegotiationApiExtension.java b/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/ContractNegotiationApiExtension.java index 9b63a232c1c..e9477fd4c5c 100644 --- a/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/ContractNegotiationApiExtension.java +++ b/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/ContractNegotiationApiExtension.java @@ -38,6 +38,7 @@ import java.util.Map; +import static org.eclipse.edc.connector.api.management.contractnegotiation.v3.model.ContractRequestDto.CONTRACT_REQUEST_DTO_TYPE; import static org.eclipse.edc.connector.contract.spi.types.command.TerminateNegotiationCommand.TERMINATE_NEGOTIATION_TYPE; import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.CONTRACT_REQUEST_TYPE; @@ -80,7 +81,7 @@ public void initialize(ServiceExtensionContext context) { validatorRegistry.register(CONTRACT_REQUEST_TYPE, ContractRequestValidator.instance()); validatorRegistry.register(TERMINATE_NEGOTIATION_TYPE, TerminateNegotiationValidator.instance()); - validatorRegistry.register(CONTRACT_REQUEST_TYPE, ContractRequestDtoValidator.instance()); + validatorRegistry.register(CONTRACT_REQUEST_DTO_TYPE, ContractRequestDtoValidator.instance()); var monitor = context.getMonitor(); diff --git a/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApi.java b/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApi.java index 2e317a6f88a..446924ab111 100644 --- a/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApi.java +++ b/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApi.java @@ -131,7 +131,7 @@ record ContractRequestSchema( public static final String CONTRACT_REQUEST_EXAMPLE = """ { "@context": { "edc": "https://w3id.org/edc/v0.0.1/ns/" }, - "@type": "https://w3id.org/edc/v0.0.1/ns/ContractRequest", + "@type": "https://w3id.org/edc/v0.0.1/ns/ContractRequestDto", "connectorAddress": "http://provider-address", "protocol": "dataspace-protocol-http", "providerId": "provider-id", diff --git a/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiController.java b/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiController.java index 738ecfd0c33..75d6de55af5 100644 --- a/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiController.java +++ b/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiController.java @@ -43,8 +43,8 @@ import java.util.Optional; import static jakarta.json.stream.JsonCollectors.toJsonArray; +import static org.eclipse.edc.connector.api.management.contractnegotiation.v3.model.ContractRequestDto.CONTRACT_REQUEST_DTO_TYPE; import static org.eclipse.edc.connector.contract.spi.types.command.TerminateNegotiationCommand.TERMINATE_NEGOTIATION_TYPE; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.CONTRACT_REQUEST_TYPE; import static org.eclipse.edc.spi.query.QuerySpec.EDC_QUERY_SPEC_TYPE; import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; @@ -129,7 +129,7 @@ public JsonObject getAgreementForNegotiation(@PathParam("id") String negotiation @POST @Override public JsonObject initiateContractNegotiation(JsonObject requestObject) { - validatorRegistry.validate(CONTRACT_REQUEST_TYPE, requestObject) + validatorRegistry.validate(CONTRACT_REQUEST_DTO_TYPE, requestObject) .orElseThrow(ValidationFailureException::new); var contractRequestDto = transformerRegistry.transform(requestObject, ContractRequestDto.class) diff --git a/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/model/ContractRequestDto.java b/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/model/ContractRequestDto.java index 45f172be417..2ee626d01bc 100644 --- a/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/model/ContractRequestDto.java +++ b/extensions/control-plane/api/management-api/contract-negotiation-api/src/main/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/model/ContractRequestDto.java @@ -28,7 +28,7 @@ */ public class ContractRequestDto { - public static final String CONTRACT_REQUEST_TYPE = EDC_NAMESPACE + "ContractRequest"; + public static final String CONTRACT_REQUEST_DTO_TYPE = EDC_NAMESPACE + "ContractRequestDto"; public static final String CONNECTOR_ADDRESS = EDC_NAMESPACE + "connectorAddress"; public static final String PROTOCOL = EDC_NAMESPACE + "protocol"; public static final String PROVIDER_ID = EDC_NAMESPACE + "providerId"; diff --git a/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/ContractNegotiationApiExtensionTest.java b/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/ContractNegotiationApiExtensionTest.java index 241c0f53a4c..fabfa2ac4ce 100644 --- a/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/ContractNegotiationApiExtensionTest.java +++ b/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/ContractNegotiationApiExtensionTest.java @@ -21,6 +21,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import static org.eclipse.edc.connector.api.management.contractnegotiation.v3.model.ContractRequestDto.CONTRACT_REQUEST_DTO_TYPE; import static org.eclipse.edc.connector.contract.spi.types.command.TerminateNegotiationCommand.TERMINATE_NEGOTIATION_TYPE; import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.CONTRACT_REQUEST_TYPE; import static org.mockito.ArgumentMatchers.any; @@ -43,6 +44,7 @@ void initiate_shouldRegisterValidators(ServiceExtensionContext context, Contract extension.initialize(context); verify(validatorRegistry).register(eq(CONTRACT_REQUEST_TYPE), any()); + verify(validatorRegistry).register(eq(CONTRACT_REQUEST_DTO_TYPE), any()); verify(validatorRegistry).register(eq(TERMINATE_NEGOTIATION_TYPE), any()); } } diff --git a/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiControllerTest.java b/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiControllerTest.java index b444daccab9..69a0b16c08b 100644 --- a/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiControllerTest.java +++ b/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiControllerTest.java @@ -380,7 +380,7 @@ void initiate_shouldReturnBadRequest_whenValidationFails() { .then() .statusCode(400); - verify(validatorRegistry).validate(eq(ContractRequestDto.CONTRACT_REQUEST_TYPE), any()); + verify(validatorRegistry).validate(eq(ContractRequestDto.CONTRACT_REQUEST_DTO_TYPE), any()); verifyNoInteractions(transformerRegistry, service); } diff --git a/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiTest.java b/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiTest.java new file mode 100644 index 00000000000..5dc33621d91 --- /dev/null +++ b/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/ContractNegotiationApiTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2023 ZF Friedrichshafen 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: + * ZF Friedrichshafen AG - Negotiation API enhancement + * + */ + +package org.eclipse.edc.connector.api.management.contractnegotiation.v3; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.JsonObject; +import org.eclipse.edc.api.transformer.JsonObjectToCallbackAddressTransformer; +import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToTerminateNegotiationCommandTransformer; +import org.eclipse.edc.connector.api.management.contractnegotiation.v3.transform.ContractRequestDtoToContractRequestTransformer; +import org.eclipse.edc.connector.api.management.contractnegotiation.v3.transform.JsonObjectToContractRequestDtoTransformer; +import org.eclipse.edc.connector.api.management.contractnegotiation.validation.ContractRequestValidator; +import org.eclipse.edc.connector.api.management.contractnegotiation.validation.TerminateNegotiationValidator; +import org.eclipse.edc.connector.contract.spi.types.command.TerminateNegotiationCommand; +import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; +import org.eclipse.edc.core.transform.TypeTransformerRegistryImpl; +import org.eclipse.edc.core.transform.transformer.OdrlTransformersFactory; +import org.eclipse.edc.jsonld.JsonLdExtension; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.jsonld.util.JacksonJsonLd; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.eclipse.edc.connector.api.management.contractnegotiation.ContractNegotiationApi.NegotiationStateSchema.NEGOTIATION_STATE_EXAMPLE; +import static org.eclipse.edc.connector.api.management.contractnegotiation.ContractNegotiationApi.TerminateNegotiationSchema.TERMINATE_NEGOTIATION_EXAMPLE; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.NegotiationState.NEGOTIATION_STATE_STATE; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.NegotiationState.NEGOTIATION_STATE_TYPE; +import static org.eclipse.edc.connector.api.management.contractnegotiation.v3.ContractNegotiationApi.ContractRequestSchema.CONTRACT_REQUEST_EXAMPLE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.edc.junit.extensions.TestServiceExtensionContext.testServiceExtensionContext; + +class ContractNegotiationApiTest { + + private final ObjectMapper objectMapper = JacksonJsonLd.createObjectMapper(); + private final JsonLd jsonLd = new JsonLdExtension().createJsonLdService(testServiceExtensionContext()); + private final TypeTransformerRegistry transformer = new TypeTransformerRegistryImpl(); + + @BeforeEach + void setUp() { + transformer.register(new JsonObjectToContractRequestDtoTransformer()); + transformer.register(new ContractRequestDtoToContractRequestTransformer()); + transformer.register(new JsonObjectToCallbackAddressTransformer()); + transformer.register(new JsonObjectToTerminateNegotiationCommandTransformer()); + OdrlTransformersFactory.jsonObjectToOdrlTransformers().forEach(transformer::register); + } + + @Test + void contractRequestExample() throws JsonProcessingException { + var validator = ContractRequestValidator.instance(); + + var jsonObject = objectMapper.readValue(CONTRACT_REQUEST_EXAMPLE, JsonObject.class); + assertThat(jsonObject).isNotNull(); + + var expanded = jsonLd.expand(jsonObject); + assertThat(expanded).isSucceeded() + .satisfies(exp -> assertThat(validator.validate(exp)).isSucceeded()) + .extracting(e -> transformer.transform(e, ContractRequest.class)) + .satisfies(transformResult -> assertThat(transformResult).isSucceeded() + .satisfies(transformed -> { + assertThat(transformed.getProviderId()).isNotBlank(); + })); + } + + @Test + void terminateNegotiationExample() throws JsonProcessingException { + var validator = TerminateNegotiationValidator.instance(); + + var jsonObject = objectMapper.readValue(TERMINATE_NEGOTIATION_EXAMPLE, JsonObject.class); + assertThat(jsonObject).isNotNull(); + + var expanded = jsonLd.expand(jsonObject); + assertThat(expanded).isSucceeded() + .satisfies(exp -> assertThat(validator.validate(exp)).isSucceeded()) + .extracting(e -> transformer.transform(e, TerminateNegotiationCommand.class)) + .satisfies(transformResult -> assertThat(transformResult).isSucceeded() + .satisfies(transformed -> { + assertThat(transformed.getEntityId()).isNotBlank(); + assertThat(transformed.getReason()).isNotBlank(); + })); + } + + @Test + void negotiationStateExample() throws JsonProcessingException { + var jsonObject = objectMapper.readValue(NEGOTIATION_STATE_EXAMPLE, JsonObject.class); + var expanded = jsonLd.expand(jsonObject); + + assertThat(expanded).isSucceeded().satisfies(content -> { + assertThat(content.getJsonArray(TYPE).getString(0)).isEqualTo(NEGOTIATION_STATE_TYPE); + assertThat(content.getJsonArray(NEGOTIATION_STATE_STATE).getJsonObject(0).getString(VALUE)).isNotBlank(); + }); + } + +} diff --git a/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/transform/JsonObjectToContractRequestDtoTransformerTest.java b/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/transform/JsonObjectToContractRequestDtoTransformerTest.java index 90b2453f64e..53e6e8fde92 100644 --- a/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/transform/JsonObjectToContractRequestDtoTransformerTest.java +++ b/extensions/control-plane/api/management-api/contract-negotiation-api/src/test/java/org/eclipse/edc/connector/api/management/contractnegotiation/v3/transform/JsonObjectToContractRequestDtoTransformerTest.java @@ -65,7 +65,7 @@ void setUp() { @Test void transform() { var jsonObject = Json.createObjectBuilder() - .add(TYPE, ContractRequestDto.CONTRACT_REQUEST_TYPE) + .add(TYPE, ContractRequestDto.CONTRACT_REQUEST_DTO_TYPE) .add(CONNECTOR_ADDRESS, "test-address") .add(PROTOCOL, "test-protocol") .add(PROVIDER_ID, "test-provider-id") @@ -97,7 +97,7 @@ void transform() { @Test void transform_shouldSetProviderIdAsConnectorAddress_whenProviderIdNotDefined() { var jsonObject = Json.createObjectBuilder() - .add(TYPE, ContractRequestDto.CONTRACT_REQUEST_TYPE) + .add(TYPE, ContractRequestDto.CONTRACT_REQUEST_DTO_TYPE) .add(CONNECTOR_ADDRESS, "test-address") .add(PROTOCOL, "test-protocol") .add(ASSET_ID, "asset-id")