Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(EdrManagementApi): implements first EDR management APIs #331

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat(CPA): adds EDR api for querying the cache and getting the EDR by ID
wolf4ood committed May 22, 2023
commit d275c7ab9b6c57cadf3f9293bf6a6fae3ce2454e
Original file line number Diff line number Diff line change
@@ -22,7 +22,11 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import static java.util.Collections.emptyList;
@@ -37,12 +41,16 @@ public class InMemoryEndpointDataReferenceCache implements EndpointDataReference
private final LockManager lockManager;

private final Map<String, List<EndpointDataReferenceEntry>> entriesByAssetId;

private final Map<String, List<EndpointDataReferenceEntry>> entriesByAgreementId;

private final Map<String, EndpointDataReferenceEntry> entriesByEdrId;
private final Map<String, EndpointDataReference> edrsByTransferProcessId;

public InMemoryEndpointDataReferenceCache() {
lockManager = new LockManager(new ReentrantReadWriteLock());
entriesByAssetId = new HashMap<>();
entriesByAgreementId = new HashMap<>();
entriesByEdrId = new HashMap<>();
edrsByTransferProcessId = new HashMap<>();
}
@@ -68,13 +76,21 @@ public List<EndpointDataReferenceEntry> entriesForAsset(String assetId) {
return lockManager.readLock(() -> entriesByAssetId.getOrDefault(assetId, emptyList()));
}

@Override
public @NotNull List<EndpointDataReferenceEntry> entriesForAgreement(String agreementId) {
return lockManager.readLock(() -> entriesByAgreementId.getOrDefault(agreementId, emptyList()));
}

@Override
public void save(EndpointDataReferenceEntry entry, EndpointDataReference edr) {
lockManager.writeLock(() -> {
entriesByEdrId.put(edr.getId(), entry);
var list = entriesByAssetId.computeIfAbsent(entry.getAssetId(), k -> new ArrayList<>());
list.add(entry);

var agreementList = entriesByAgreementId.computeIfAbsent(entry.getAgreementId(), k -> new ArrayList<>());
agreementList.add(entry);

edrsByTransferProcessId.put(entry.getTransferProcessId(), edr);
return null;
});
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ plugins {
}

dependencies {
implementation(project(":spi:core-spi"))
api(libs.edc.spi.core)
implementation(libs.edc.spi.policy)
implementation(libs.edc.spi.contract)
Original file line number Diff line number Diff line change
@@ -35,7 +35,6 @@
import org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerProhibitionFunction;

import static org.eclipse.edc.policy.engine.spi.PolicyEngine.ALL_SCOPES;
import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE;

public class BusinessPartnerValidationExtension implements ServiceExtension {

@@ -56,7 +55,7 @@ public class BusinessPartnerValidationExtension implements ServiceExtension {
* </pre>
*/
// TODO replace with TX namespace
public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = EDC_NAMESPACE + "BusinessPartnerNumber";
public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = "BusinessPartnerNumber";

public static final String DEFAULT_LOG_AGREEMENT_EVALUATION = "true";

3 changes: 3 additions & 0 deletions edc-extensions/control-plane-adapter-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -20,6 +20,9 @@ plugins {

dependencies {
implementation(project(":spi:control-plane-adapter-spi"))
implementation(project(":spi:edr-cache-spi"))
implementation(project(":spi:core-spi"))

implementation(libs.edc.api.management)
implementation(libs.edc.spi.aggregateservices)
implementation(libs.jakarta.rsApi)
Original file line number Diff line number Diff line change
@@ -21,10 +21,15 @@
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.eclipse.edc.web.spi.WebService;
import org.eclipse.tractusx.edc.api.cp.adapter.transform.EdrEntryDtoToEdrEntryTransformer;
import org.eclipse.tractusx.edc.api.cp.adapter.transform.JsonObjectFromEndpointDataReferenceEntryDtoTransformer;
import org.eclipse.tractusx.edc.api.cp.adapter.transform.JsonObjectToNegotiateEdrRequestDtoTransformer;
import org.eclipse.tractusx.edc.api.cp.adapter.transform.NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer;
import org.eclipse.tractusx.edc.spi.cp.adapter.service.AdapterTransferProcessService;

import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE;
import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_PREFIX;

public class AdapterApiExtension implements ServiceExtension {

@Inject
@@ -43,8 +48,11 @@ public class AdapterApiExtension implements ServiceExtension {

@Override
public void initialize(ServiceExtensionContext context) {
jsonLdService.registerNamespace(TX_PREFIX, TX_NAMESPACE);
transformerRegistry.register(new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer());
transformerRegistry.register(new EdrEntryDtoToEdrEntryTransformer());
transformerRegistry.register(new JsonObjectToNegotiateEdrRequestDtoTransformer());
transformerRegistry.register(new JsonObjectFromEndpointDataReferenceEntryDtoTransformer());
webService.registerResource(apiConfig.getContextAlias(), new AdapterEdrController(adapterTransferProcessService, jsonLdService, transformerRegistry));
}
}
Original file line number Diff line number Diff line change
@@ -22,10 +22,14 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.json.JsonObject;
import org.eclipse.edc.api.model.DataAddressDto;
import org.eclipse.edc.api.model.IdResponseDto;
import org.eclipse.edc.web.spi.ApiErrorDetail;
import org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto;
import org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto;

import java.util.List;

@OpenAPIDefinition
@Tag(name = "Control Plane Adapter EDR Api")
public interface AdapterEdrApi {
@@ -39,4 +43,25 @@ public interface AdapterEdrApi {
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))),
})
JsonObject initiateEdrNegotiation(@Schema(implementation = NegotiateEdrRequestDto.class) JsonObject dto);

@Operation(description = "Returns all EndpointDataReference entry according to a query",
responses = {
@ApiResponse(responseCode = "200",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = EndpointDataReferenceEntryDto.class)))),
@ApiResponse(responseCode = "400", description = "Request was malformed",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class))))}
)
List<JsonObject> queryEdrs(String assetId, String agreementId);

@Operation(description = "Gets an EDR with the given transfer process ID)",
responses = {
@ApiResponse(responseCode = "200", description = "The EDR cached",
content = @Content(schema = @Schema(implementation = DataAddressDto.class))),
@ApiResponse(responseCode = "400", description = "Request was malformed, e.g. id was null",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))),
@ApiResponse(responseCode = "404", description = "An EDR with the given ID does not exist",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class))))
}
)
JsonObject getEdr(String transferProcessId);
}
Original file line number Diff line number Diff line change
@@ -16,19 +16,31 @@

import jakarta.json.JsonObject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.edc.api.model.IdResponseDto;
import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.spi.EdcException;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.spi.types.domain.edr.EndpointDataAddressConstants;
import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.eclipse.edc.web.spi.exception.InvalidRequestException;
import org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto;
import org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto;
import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceEntry;
import org.eclipse.tractusx.edc.spi.cp.adapter.model.NegotiateEdrRequest;
import org.eclipse.tractusx.edc.spi.cp.adapter.service.AdapterTransferProcessService;

import java.util.List;
import java.util.stream.Collectors;

import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper;

@Consumes({MediaType.APPLICATION_JSON})
@@ -40,6 +52,8 @@ public class AdapterEdrController implements AdapterEdrApi {
private final TypeTransformerRegistry transformerRegistry;
private final JsonLd jsonLdService;

private Monitor monitor;

public AdapterEdrController(AdapterTransferProcessService adapterTransferProcessService, JsonLd jsonLdService, TypeTransformerRegistry transformerRegistry) {
this.adapterTransferProcessService = adapterTransferProcessService;
this.jsonLdService = jsonLdService;
@@ -65,4 +79,37 @@ public JsonObject initiateEdrNegotiation(JsonObject requestObject) {
.compose(jsonLdService::compact)
.orElseThrow(f -> new EdcException("Error creating response body: " + f.getFailureDetail()));
}

@GET
@Path("/{id}")
@Override
public JsonObject getEdr(@PathParam("id") String transferProcessId) {
var edr = adapterTransferProcessService.findByTransferProcessId(transferProcessId).orElseThrow(exceptionMapper(EndpointDataReference.class, transferProcessId));

return transformerRegistry.transform(EndpointDataAddressConstants.from(edr), JsonObject.class)
.compose(jsonLdService::compact)
.orElseThrow(f -> new EdcException("Error creating response body: " + f.getFailureDetail()));
}

@GET
@Override
public List<JsonObject> queryEdrs(@QueryParam("assetId") String assetId, @QueryParam("agreementId") String agreementId) {
if (assetId == null && agreementId == null) {
throw new InvalidRequestException("At least one of this query parameter is required [assetId,agreementId]");
}
return adapterTransferProcessService.findCacheEntries(assetId, agreementId)
.orElseThrow(exceptionMapper(EndpointDataReferenceEntry.class))
.stream()
.map(edrCached -> transformerRegistry.transform(edrCached, EndpointDataReferenceEntryDto.class)
.compose(dto -> transformerRegistry.transform(dto, JsonObject.class))
.compose(jsonLdService::compact))
.peek(this::logIfError)
.filter(Result::succeeded)
.map(Result::getContent)
.collect(Collectors.toList());
}

private void logIfError(Result<?> result) {
result.onFailure(f -> monitor.warning(f.getFailureDetail()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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.tractusx.edc.api.cp.adapter.dto;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;

import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE;


public class EndpointDataReferenceEntryDto {

public static final String SIMPLE_TYPE = "EndpointDataReferenceEntryDto";

public static final String EDR_ENTRY_DTO_TYPE = TX_NAMESPACE + SIMPLE_TYPE;
public static final String EDR_ENTRY_DTO_ASSET_ID = TX_NAMESPACE + "assetId";
public static final String EDR_ENTRY_DTO_AGREEMENT_ID = TX_NAMESPACE + "agreementId";
public static final String EDR_ENTRY_TRANSFER_PROCESS_ID = TX_NAMESPACE + "transferProcessId";

private String assetId;
private String agreementId;
private String transferProcessId;

private EndpointDataReferenceEntryDto() {
}

public String getAssetId() {
return assetId;
}

public String getAgreementId() {
return agreementId;
}

public String getTransferProcessId() {
return transferProcessId;
}


@JsonPOJOBuilder(withPrefix = "")
public static class Builder {
private final EndpointDataReferenceEntryDto entry;

private Builder() {
entry = new EndpointDataReferenceEntryDto();
}

@JsonCreator
public static Builder newInstance() {
return new Builder();
}

public Builder assetId(String assetId) {
entry.assetId = assetId;
return this;
}

public Builder agreementId(String agreementId) {
entry.agreementId = agreementId;
return this;
}

public Builder transferProcessId(String transferProcessId) {
entry.transferProcessId = transferProcessId;
return this;
}

public EndpointDataReferenceEntryDto build() {
return entry;
}
}

}
Original file line number Diff line number Diff line change
@@ -23,16 +23,17 @@
import java.util.List;

import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE;

public class NegotiateEdrRequestDto {
public static final String TYPE = EDC_NAMESPACE + "NegotiateEdrRequestDto";
public static final String CONNECTOR_ADDRESS = EDC_NAMESPACE + "connectorAddress";
public static final String PROTOCOL = EDC_NAMESPACE + "protocol";
public static final String CONNECTOR_ID = EDC_NAMESPACE + "connectorId";
public static final String PROVIDER_ID = EDC_NAMESPACE + "providerId";
public static final String OFFER = EDC_NAMESPACE + "offer";
public static final String CALLBACK_ADDRESSES = EDC_NAMESPACE + "callbackAddresses";

public static final String EDR_REQUEST_DTO_TYPE = TX_NAMESPACE + "NegotiateEdrRequestDto";
public static final String EDR_REQUEST_DTO_CONNECTOR_ADDRESS = EDC_NAMESPACE + "connectorAddress";
public static final String EDR_REQUEST_DTO_PROTOCOL = EDC_NAMESPACE + "protocol";
public static final String EDR_REQUEST_DTO_CONNECTOR_ID = EDC_NAMESPACE + "connectorId";
public static final String EDR_REQUEST_DTO_PROVIDER_ID = EDC_NAMESPACE + "providerId";
public static final String EDR_REQUEST_DTO_OFFER = EDC_NAMESPACE + "offer";
public static final String EDR_REQUEST_DTO_CALLBACK_ADDRESSES = EDC_NAMESPACE + "callbackAddresses";

@NotBlank(message = "connectorAddress is mandatory")
private String connectorAddress;
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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.tractusx.edc.api.cp.adapter.transform;

import org.eclipse.edc.api.transformer.DtoTransformer;
import org.eclipse.edc.transform.spi.TransformerContext;
import org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto;
import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;


public class EdrEntryDtoToEdrEntryTransformer implements DtoTransformer<EndpointDataReferenceEntry, EndpointDataReferenceEntryDto> {

@Override
public Class<EndpointDataReferenceEntryDto> getOutputType() {
return EndpointDataReferenceEntryDto.class;
}

@Override
public Class<EndpointDataReferenceEntry> getInputType() {
return EndpointDataReferenceEntry.class;
}

@Override
public @Nullable EndpointDataReferenceEntryDto transform(@NotNull EndpointDataReferenceEntry dto, @NotNull TransformerContext context) {
return EndpointDataReferenceEntryDto.Builder.newInstance()
.agreementId(dto.getAgreementId())
.assetId(dto.getAssetId())
.transferProcessId(dto.getTransferProcessId())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.tractusx.edc.api.cp.adapter.transform;

import jakarta.json.Json;
import jakarta.json.JsonObject;
import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer;
import org.eclipse.edc.transform.spi.TransformerContext;
import org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_DTO_AGREEMENT_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_DTO_ASSET_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_DTO_TYPE;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_TRANSFER_PROCESS_ID;


public class JsonObjectFromEndpointDataReferenceEntryDtoTransformer extends AbstractJsonLdTransformer<EndpointDataReferenceEntryDto, JsonObject> {

public JsonObjectFromEndpointDataReferenceEntryDtoTransformer() {
super(EndpointDataReferenceEntryDto.class, JsonObject.class);
}

@Override
public @Nullable JsonObject transform(@NotNull EndpointDataReferenceEntryDto dto, @NotNull TransformerContext context) {
return Json.createObjectBuilder()
.add(TYPE, EDR_ENTRY_DTO_TYPE)
.add(EDR_ENTRY_DTO_AGREEMENT_ID, dto.getAgreementId())
.add(EDR_ENTRY_TRANSFER_PROCESS_ID, dto.getTransferProcessId())
.add(EDR_ENTRY_DTO_ASSET_ID, dto.getAssetId())
.build();
}


}
Original file line number Diff line number Diff line change
@@ -26,12 +26,13 @@

import java.util.ArrayList;

import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.CALLBACK_ADDRESSES;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.CONNECTOR_ADDRESS;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.CONNECTOR_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.OFFER;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.PROTOCOL;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.PROVIDER_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_CALLBACK_ADDRESSES;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_CONNECTOR_ADDRESS;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_CONNECTOR_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE;


public class JsonObjectToNegotiateEdrRequestDtoTransformer extends AbstractJsonLdTransformer<JsonObject, NegotiateEdrRequestDto> {
@@ -50,38 +51,38 @@ public JsonObjectToNegotiateEdrRequestDtoTransformer() {

private void setProperties(String key, JsonValue value, NegotiateEdrRequestDto.Builder builder, TransformerContext context) {
switch (key) {
case CONNECTOR_ADDRESS:
case EDR_REQUEST_DTO_CONNECTOR_ADDRESS:
transformString(value, builder::connectorAddress, context);
break;
case PROTOCOL:
case EDR_REQUEST_DTO_PROTOCOL:
transformString(value, builder::protocol, context);
break;
case CONNECTOR_ID:
case EDR_REQUEST_DTO_CONNECTOR_ID:
transformString(value, builder::connectorId, context);
break;
case PROVIDER_ID:
case EDR_REQUEST_DTO_PROVIDER_ID:
transformString(value, builder::providerId, context);
break;
case CALLBACK_ADDRESSES:
case EDR_REQUEST_DTO_CALLBACK_ADDRESSES:
var addresses = new ArrayList<CallbackAddressDto>();
transformArrayOrObject(value, CallbackAddressDto.class, addresses::add, context);
builder.callbackAddresses(addresses);
break;
case OFFER:
case EDR_REQUEST_DTO_OFFER:
transformArrayOrObject(value, ContractOfferDescription.class, builder::offer, context);
break;
default:
context.problem()
.unexpectedType()
.type(NegotiateEdrRequestDto.TYPE)
.type(EDR_REQUEST_DTO_TYPE)
.property(key)
.actual(key)
.expected(CONNECTOR_ADDRESS)
.expected(PROTOCOL)
.expected(CONNECTOR_ID)
.expected(PROVIDER_ID)
.expected(CALLBACK_ADDRESSES)
.expected(OFFER)
.expected(EDR_REQUEST_DTO_CONNECTOR_ADDRESS)
.expected(EDR_REQUEST_DTO_PROTOCOL)
.expected(EDR_REQUEST_DTO_CONNECTOR_ID)
.expected(EDR_REQUEST_DTO_PROVIDER_ID)
.expected(EDR_REQUEST_DTO_CALLBACK_ADDRESSES)
.expected(EDR_REQUEST_DTO_OFFER)
.report();
break;
}
Original file line number Diff line number Diff line change
@@ -20,6 +20,8 @@
import org.eclipse.edc.spi.system.injection.ObjectFactory;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.eclipse.edc.web.spi.WebService;
import org.eclipse.tractusx.edc.api.cp.adapter.transform.EdrEntryDtoToEdrEntryTransformer;
import org.eclipse.tractusx.edc.api.cp.adapter.transform.JsonObjectFromEndpointDataReferenceEntryDtoTransformer;
import org.eclipse.tractusx.edc.api.cp.adapter.transform.JsonObjectToNegotiateEdrRequestDtoTransformer;
import org.eclipse.tractusx.edc.api.cp.adapter.transform.NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer;
import org.junit.jupiter.api.BeforeEach;
@@ -61,5 +63,8 @@ void initialize_ShouldConfigureTheController(ServiceExtensionContext context) {
verify(webService).registerResource(eq(alias), isA(AdapterEdrController.class));
verify(transformerRegistry).register(isA(NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.class));
verify(transformerRegistry).register(isA(JsonObjectToNegotiateEdrRequestDtoTransformer.class));
verify(transformerRegistry).register(isA(JsonObjectFromEndpointDataReferenceEntryDtoTransformer.class));
verify(transformerRegistry).register(isA(EdrEntryDtoToEdrEntryTransformer.class));

}
}
Original file line number Diff line number Diff line change
@@ -25,19 +25,33 @@
import org.eclipse.edc.junit.annotations.ApiTest;
import org.eclipse.edc.service.spi.result.ServiceResult;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.spi.types.domain.DataAddress;
import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase;
import org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto;
import org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto;
import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceEntry;
import org.eclipse.tractusx.edc.spi.cp.adapter.model.NegotiateEdrRequest;
import org.eclipse.tractusx.edc.spi.cp.adapter.service.AdapterTransferProcessService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static io.restassured.RestAssured.given;
import static java.lang.String.format;
import static org.eclipse.edc.api.model.IdResponseDto.EDC_ID_RESPONSE_DTO_TYPE;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE;
import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.tractusx.edc.api.cp.adapter.TestFunctions.openRequest;
import static org.eclipse.tractusx.edc.api.cp.adapter.TestFunctions.requestDto;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.Builder;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_DTO_AGREEMENT_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_DTO_ASSET_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_TRANSFER_PROCESS_ID;
import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE;
import static org.hamcrest.Matchers.is;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -52,6 +66,12 @@ public class AdapterEdrControllerTest extends RestControllerTestBase {
AdapterTransferProcessService adapterTransferProcessService = mock(AdapterTransferProcessService.class);
TypeTransformerRegistry transformerRegistry = mock(TypeTransformerRegistry.class);

@BeforeEach
void setup() {
jsonLdService.registerNamespace("edc", EDC_NAMESPACE);
jsonLdService.registerNamespace("tx", TX_NAMESPACE);
}

@Test
void initEdrNegotiation_shouldWork_whenValidRequest() {

@@ -90,6 +110,125 @@ void initEdrNegotiation_shouldReturnBadRequest_whenValidInvalidRequest() {

}

@Test
void initEdrNegotiation_shouldReturnError_whenNotFound() {
var transferProcessId = "id";

when(adapterTransferProcessService.findByTransferProcessId(transferProcessId)).thenReturn(ServiceResult.notFound(""));

baseRequest()
.contentType(MediaType.APPLICATION_JSON)
.get(ADAPTER_EDR_PATH + "/" + transferProcessId)
.then()
.statusCode(404);
}

@Test
void getEdr_shouldReturnDataAddress_whenFound() {
var transferProcessId = "id";
var edr = EndpointDataReference.Builder.newInstance().endpoint("test").id(transferProcessId).build();
var response = Json.createObjectBuilder()
.add(DataAddress.TYPE, EndpointDataReference.EDR_SIMPLE_TYPE)
.add(EndpointDataReference.ENDPOINT, edr.getEndpoint())
.add(EndpointDataReference.ID, edr.getId())
.build();

when(adapterTransferProcessService.findByTransferProcessId(transferProcessId)).thenReturn(ServiceResult.success(edr));
when(transformerRegistry.transform(any(DataAddress.class), eq(JsonObject.class))).thenReturn(Result.success(response));

baseRequest()
.contentType(MediaType.APPLICATION_JSON)
.get(ADAPTER_EDR_PATH + "/" + transferProcessId)
.then()
.statusCode(200)
.body("'edc:endpoint'", is(edr.getEndpoint()))
.body("'edc:id'", is(edr.getId()))
.body("'edc:type'", is(EndpointDataReference.EDR_SIMPLE_TYPE));

}

@Test
void queryEdrs_shouldReturnCachedEntries_whenAssetIdIsProvided() {
var assetId = "id";
var transferProcessId = "id";
var agreementId = "id";

var entry = EndpointDataReferenceEntry.Builder.newInstance()
.transferProcessId(transferProcessId)
.agreementId(agreementId)
.assetId(assetId)
.build();

var entryDto = Builder.newInstance().build();

var response = Json.createObjectBuilder()
.add(TYPE, EndpointDataReferenceEntryDto.EDR_ENTRY_DTO_TYPE)
.add(EDR_ENTRY_DTO_ASSET_ID, entry.getAssetId())
.add(EDR_ENTRY_TRANSFER_PROCESS_ID, entry.getTransferProcessId())
.add(EDR_ENTRY_DTO_AGREEMENT_ID, entry.getAgreementId())
.build();


when(adapterTransferProcessService.findCacheEntries(assetId, null)).thenReturn(ServiceResult.success(List.of(entry)));
when(transformerRegistry.transform(any(EndpointDataReferenceEntry.class), eq(EndpointDataReferenceEntryDto.class))).thenReturn(Result.success(entryDto));
when(transformerRegistry.transform(any(EndpointDataReferenceEntryDto.class), eq(JsonObject.class))).thenReturn(Result.success(response));

baseRequest()
.contentType(MediaType.APPLICATION_JSON)
.get(ADAPTER_EDR_PATH + format("?=assetId=%s", assetId))
.then()
.statusCode(200)
.body("[0].'tx:transferProcessId'", is(entry.getTransferProcessId()))
.body("[0].'tx:agreementId'", is(entry.getAgreementId()))
.body("[0].'tx:assetId'", is(entry.getAssetId()));

}

@Test
void queryEdrs_shouldReturnCachedEntries_whenAgreementIdIsProvided() {
var assetId = "id";
var transferProcessId = "id";
var agreementId = "id";

var entry = EndpointDataReferenceEntry.Builder.newInstance()
.transferProcessId(transferProcessId)
.agreementId(agreementId)
.assetId(assetId)
.build();

var entryDto = Builder.newInstance().build();

var response = Json.createObjectBuilder()
.add(TYPE, EndpointDataReferenceEntryDto.EDR_ENTRY_DTO_TYPE)
.add(EDR_ENTRY_DTO_ASSET_ID, entry.getAssetId())
.add(EDR_ENTRY_TRANSFER_PROCESS_ID, entry.getTransferProcessId())
.add(EDR_ENTRY_DTO_AGREEMENT_ID, entry.getAgreementId())
.build();


when(adapterTransferProcessService.findCacheEntries(null, agreementId)).thenReturn(ServiceResult.success(List.of(entry)));
when(transformerRegistry.transform(any(EndpointDataReferenceEntry.class), eq(EndpointDataReferenceEntryDto.class))).thenReturn(Result.success(entryDto));
when(transformerRegistry.transform(any(EndpointDataReferenceEntryDto.class), eq(JsonObject.class))).thenReturn(Result.success(response));

baseRequest()
.contentType(MediaType.APPLICATION_JSON)
.get(ADAPTER_EDR_PATH + format("?=agreementId=%s", entry.getAgreementId()))
.then()
.statusCode(200)
.body("[0].'tx:transferProcessId'", is(entry.getTransferProcessId()))
.body("[0].'tx:agreementId'", is(entry.getAgreementId()))
.body("[0].'tx:assetId'", is(entry.getAssetId()));
}

@Test
void queryEdrs_shouldFail_whenNoQueryParameter() {
baseRequest()
.contentType(MediaType.APPLICATION_JSON)
.get(ADAPTER_EDR_PATH)
.then()
.statusCode(400);
}

@Override
protected Object controller() {
return new AdapterEdrController(adapterTransferProcessService, jsonLdService, transformerRegistry);
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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.tractusx.edc.api.cp.adapter.transform;

import org.eclipse.edc.transform.spi.TransformerContext;
import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceEntry;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

public class EdrEntryDtoToEdrEntryTransformerTest {

private final EdrEntryDtoToEdrEntryTransformer transformer = new EdrEntryDtoToEdrEntryTransformer();

private final TransformerContext context = mock(TransformerContext.class);

@Test
void inputOutputType() {
assertThat(transformer.getInputType()).isNotNull();
assertThat(transformer.getOutputType()).isNotNull();
}

@Test
void verify_transform() {

var entry = EndpointDataReferenceEntry.Builder.newInstance()
.agreementId("aId")
.assetId("assetId")
.transferProcessId("tpId")
.build();

var dto = transformer.transform(entry, context);

assertThat(dto).isNotNull();
assertThat(dto.getAgreementId()).isEqualTo(entry.getAgreementId());
assertThat(dto.getAssetId()).isEqualTo(entry.getAssetId());
assertThat(dto.getTransferProcessId()).isEqualTo(entry.getTransferProcessId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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.tractusx.edc.api.cp.adapter.transform;

import org.eclipse.edc.transform.spi.TransformerContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.Builder;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_DTO_AGREEMENT_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_DTO_ASSET_ID;
import static org.eclipse.tractusx.edc.api.cp.adapter.dto.EndpointDataReferenceEntryDto.EDR_ENTRY_TRANSFER_PROCESS_ID;
import static org.mockito.Mockito.mock;

class JsonObjectFromEndpointDataReferenceEntryDtoTransformerTest {

private final TransformerContext context = mock(TransformerContext.class);
private JsonObjectFromEndpointDataReferenceEntryDtoTransformer transformer;

@BeforeEach
void setUp() {
transformer = new JsonObjectFromEndpointDataReferenceEntryDtoTransformer();
}

@Test
void transform() {

var dto = Builder.newInstance()
.assetId("id")
.transferProcessId("tpId")
.agreementId("aId")
.build();

var jsonObject = transformer.transform(dto, context);

assertThat(jsonObject).isNotNull();
assertThat(jsonObject.getJsonString(EDR_ENTRY_DTO_AGREEMENT_ID).getString()).isNotNull().isEqualTo(dto.getAgreementId());
assertThat(jsonObject.getJsonString(EDR_ENTRY_DTO_ASSET_ID).getString()).isNotNull().isEqualTo(dto.getAssetId());
assertThat(jsonObject.getJsonString(EDR_ENTRY_TRANSFER_PROCESS_ID).getString()).isNotNull().isEqualTo(dto.getTransferProcessId());
}
}
Original file line number Diff line number Diff line change
@@ -20,13 +20,25 @@
import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService;
import org.eclipse.edc.service.spi.result.ServiceResult;
import org.eclipse.edc.spi.types.domain.callback.CallbackAddress;
import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference;
import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceCache;
import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceEntry;
import org.eclipse.tractusx.edc.spi.cp.adapter.model.NegotiateEdrRequest;
import org.eclipse.tractusx.edc.spi.cp.adapter.service.AdapterTransferProcessService;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.lang.String.format;
import static org.eclipse.edc.service.spi.result.ServiceResult.notFound;
import static org.eclipse.edc.service.spi.result.ServiceResult.success;

public class AdapterTransferProcessServiceImpl implements AdapterTransferProcessService {

public static final String LOCAL_ADAPTER_URI = "local://adapter";
@@ -38,14 +50,17 @@ public class AdapterTransferProcessServiceImpl implements AdapterTransferProcess
.build();
private final ContractNegotiationService contractNegotiationService;

public AdapterTransferProcessServiceImpl(ContractNegotiationService contractNegotiationService) {
private final EndpointDataReferenceCache endpointDataReferenceCache;

public AdapterTransferProcessServiceImpl(ContractNegotiationService contractNegotiationService, EndpointDataReferenceCache endpointDataReferenceCache) {
this.contractNegotiationService = contractNegotiationService;
this.endpointDataReferenceCache = endpointDataReferenceCache;
}

@Override
public ServiceResult<ContractNegotiation> initiateEdrNegotiation(NegotiateEdrRequest request) {
var contractNegotiation = contractNegotiationService.initiateNegotiation(createContractRequest(request));
return ServiceResult.success(contractNegotiation);
return success(contractNegotiation);
}

private ContractRequest createContractRequest(NegotiateEdrRequest request) {
@@ -62,4 +77,37 @@ private ContractRequest createContractRequest(NegotiateEdrRequest request) {
.requestData(requestData)
.callbackAddresses(callbacks).build();
}

@Override
public ServiceResult<EndpointDataReference> findByTransferProcessId(String transferProcessId) {
var edr = endpointDataReferenceCache.resolveReference(transferProcessId);
return Optional.ofNullable(edr)
.map(ServiceResult::success)
.orElse(notFound(format("No Edr found associated to the transfer process with id: %s", transferProcessId)));
}

@Override
public ServiceResult<List<EndpointDataReferenceEntry>> findCacheEntries(String assetId, String agreementId) {
var results = queryEdrs(assetId, agreementId)
.stream()
.filter(fieldFilter(assetId, EndpointDataReferenceEntry::getAssetId))
.filter(fieldFilter(agreementId, EndpointDataReferenceEntry::getAgreementId))
.collect(Collectors.toList());
return success(results);
}

private Predicate<EndpointDataReferenceEntry> fieldFilter(String value, Function<EndpointDataReferenceEntry, String> function) {
return entry -> Optional.ofNullable(value)
.map(val -> val.equals(function.apply(entry)))
.orElse(true);
}

private List<EndpointDataReferenceEntry> queryEdrs(String assetId, String agreementId) {
// Try first for agreementId and then assetId
return Optional.ofNullable(agreementId)
.map(endpointDataReferenceCache::entriesForAgreement)
.or(() -> Optional.ofNullable(assetId).map(endpointDataReferenceCache::entriesForAsset))
.orElseGet(Collections::emptyList);
}

}
Original file line number Diff line number Diff line change
@@ -64,6 +64,9 @@ public class LocalCallbackExtension implements ServiceExtension {

@Inject
private TransactionContext transactionContext;

@Inject
private EndpointDataReferenceCache endpointDataReferenceCache;

@Override
public String name() {
@@ -79,7 +82,7 @@ public void initialize(ServiceExtensionContext context) {
resolverRegistry.registerResolver(this::resolveProtocol);
registry.register(new InProcessCallbackMessageDispatcher(callbackRegistry));

context.registerService(AdapterTransferProcessService.class, new AdapterTransferProcessServiceImpl(contractNegotiationService));
context.registerService(AdapterTransferProcessService.class, new AdapterTransferProcessServiceImpl(contractNegotiationService, endpointDataReferenceCache));
}

private String resolveProtocol(String scheme) {
Original file line number Diff line number Diff line change
@@ -19,7 +19,11 @@
import org.eclipse.edc.connector.contract.spi.types.offer.ContractOffer;
import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService;
import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.service.spi.result.ServiceFailure;
import org.eclipse.edc.service.spi.result.ServiceResult;
import org.eclipse.edc.spi.types.domain.callback.CallbackAddress;
import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference;
import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceCache;
import org.eclipse.tractusx.edc.spi.cp.adapter.model.NegotiateEdrRequest;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
@@ -38,9 +42,11 @@ public class AdapterTransferProcessServiceImplTest {

ContractNegotiationService contractNegotiationService = mock(ContractNegotiationService.class);

EndpointDataReferenceCache endpointDataReferenceCache = mock(EndpointDataReferenceCache.class);

@Test
void initEdrNegotiation_shouldFireAContractNegotiation_WhenUsingCallbacks() {
var transferService = new AdapterTransferProcessServiceImpl(contractNegotiationService);
var transferService = new AdapterTransferProcessServiceImpl(contractNegotiationService, endpointDataReferenceCache);

var captor = ArgumentCaptor.forClass(ContractRequest.class);

@@ -65,6 +71,39 @@ void initEdrNegotiation_shouldFireAContractNegotiation_WhenUsingCallbacks() {

}

@Test
void findByTransferProcessId_shouldReturnTheEdr_whenFoundInCache() {

var transferProcessId = "tpId";

var transferService = new AdapterTransferProcessServiceImpl(contractNegotiationService, endpointDataReferenceCache);
when(endpointDataReferenceCache.resolveReference(transferProcessId)).thenReturn(EndpointDataReference.Builder.newInstance().endpoint("test").build());

var result = transferService.findByTransferProcessId(transferProcessId);

assertThat(result)
.isNotNull()
.extracting(ServiceResult::getContent)
.isNotNull();
}


@Test
void findByTransferProcessId_shouldNotFound_whenNotPresentInCache() {
var transferProcessId = "tpId";

var transferService = new AdapterTransferProcessServiceImpl(contractNegotiationService, endpointDataReferenceCache);
when(endpointDataReferenceCache.resolveReference(transferProcessId)).thenReturn(null);

var result = transferService.findByTransferProcessId(transferProcessId);

assertThat(result)
.isNotNull()
.extracting(ServiceResult::getFailure)
.extracting(ServiceFailure::getReason)
.isEqualTo(ServiceFailure.Reason.NOT_FOUND);
}

private NegotiateEdrRequest getNegotiateEdrRequest() {
return NegotiateEdrRequest.Builder.newInstance()
.protocol("protocol")
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
import org.eclipse.edc.jsonld.TitaniumJsonLd;
import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.tractusx.edc.api.cp.adapter.dto.NegotiateEdrRequestDto;

import java.util.Set;

@@ -35,7 +36,7 @@ public class EdrNegotiationHelperFunctions {

public static JsonObject createEdrNegotiationRequest(String connectorAddress, String providerId, String offerId, String assetId, JsonObject policy, JsonArray callbacks) {
return Json.createObjectBuilder()
.add(TYPE, EDC_NAMESPACE + "NegotiateEdrRequestDto")
.add(TYPE, NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE)
.add(EDC_NAMESPACE + "connectorId", providerId)
.add(EDC_NAMESPACE + "providerId", providerId)
.add(EDC_NAMESPACE + "connectorAddress", connectorAddress)
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@

public class PolicyHelperFunctions {

private static final String BUSINESS_PARTNER_EVALUATION_KEY = EDC_NAMESPACE + "BusinessPartnerNumber";
private static final String BUSINESS_PARTNER_EVALUATION_KEY = "BusinessPartnerNumber";

/**
* Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers:
Original file line number Diff line number Diff line change
@@ -180,6 +180,7 @@ public String getNegotiationState(String negotiationId) {
.extract().body().jsonPath().getString("'edc:state'");
}


public String getContractAgreementId(String negotiationId) {
return getContractNegotiationField(negotiationId, "contractAgreementId");
}
@@ -194,6 +195,28 @@ private String getContractNegotiationField(String negotiationId, String fieldNam
.getString(format("'edc:%s'", fieldName));
}

public JsonObject getEdr(String transferProcessId) {
return baseRequest()
.when()
.get("/adapter/edrs/{id}", transferProcessId)
.then()
.statusCode(200)
.extract()
.body()
.as(JsonObject.class);
}

public JsonArray getEdrEntries(String assetId) {
return baseRequest()
.when()
.get("/adapter/edrs?assetId={assetId}", assetId)
.then()
.statusCode(200)
.extract()
.body()
.as(JsonArray.class);
}


/**
* Returns this participant's BusinessPartnerNumber (=BPN). This is constructed of the runtime name plus "-BPN"
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.EDR_SIMPLE_TYPE;
import static org.eclipse.tractusx.edc.helpers.EdrNegotiationHelperFunctions.createCallback;
import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.businessPartnerNumberPolicy;
import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN;
@@ -111,6 +112,22 @@ void negotiateEdr_shouldInvokeCallbacks() throws IOException {
.collect(Collectors.toList());

assertThat(expectedEvents).usingRecursiveFieldByFieldElementComparator().containsAll(events);


var edrCaches = sokrates.getEdrEntries(assetId);

assertThat(edrCaches).hasSize(1);

var transferProcessId = edrCaches.get(0).asJsonObject().getString("tx:transferProcessId");

var edr = sokrates.getEdr(transferProcessId);

assertThat(edr.getJsonString("edc:type").getString()).isEqualTo(EDR_SIMPLE_TYPE);
assertThat(edr.getJsonString("edc:authCode").getString()).isNotNull();
assertThat(edr.getJsonString("edc:authKey").getString()).isNotNull();
assertThat(edr.getJsonString("edc:endpoint").getString()).isNotNull();
assertThat(edr.getJsonString("edc:id").getString()).isEqualTo(transferProcessId);

}

<E extends Event> ReceivedEvent createEvent(Class<E> klass) {
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ rootProject.name = "tractusx-edc"
// spi modules
include(":spi:control-plane-adapter-spi")
include(":spi:edr-cache-spi")
include(":spi:core-spi")

// core modules
include(":core:edr-cache-core")
2 changes: 2 additions & 0 deletions spi/control-plane-adapter-spi/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -19,8 +19,10 @@ plugins {


dependencies {
implementation(project(":spi:edr-cache-spi"))
implementation(libs.edc.spi.core)
implementation(libs.edc.spi.contract)
implementation(libs.edc.spi.aggregateservices)
implementation(libs.edc.spi.controlplane)
implementation(libs.edc.spi.controlplane)
}
Original file line number Diff line number Diff line change
@@ -16,8 +16,12 @@

import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation;
import org.eclipse.edc.service.spi.result.ServiceResult;
import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference;
import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceEntry;
import org.eclipse.tractusx.edc.spi.cp.adapter.model.NegotiateEdrRequest;

import java.util.List;

/**
* Service for opening a transfer process.
*/
@@ -31,4 +35,15 @@ public interface AdapterTransferProcessService {
* @return The result containing the contract negotiation id
*/
ServiceResult<ContractNegotiation> initiateEdrNegotiation(NegotiateEdrRequest request);

/**
* Return a {@link EndpointDataReference} associated with the transferProcessId in input
*
* @param transferProcessId The transferProcessId
* @return The result containing the {@link EndpointDataReference}
*/
ServiceResult<EndpointDataReference> findByTransferProcessId(String transferProcessId);

ServiceResult<List<EndpointDataReferenceEntry>> findCacheEntries(String assetId, String agreementId);

}
21 changes: 21 additions & 0 deletions spi/core-spi/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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
*
*/

plugins {
`java-library`
}

dependencies {
implementation(libs.edc.spi.core)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.tractusx.edc.edr.spi;

public final class CoreConstants {

public static final String TX_PREFIX = "tx";
public static final String TX_NAMESPACE = "https://w3id.org/tractusx/v0.0.1/ns/";

private CoreConstants() {
}
}
Original file line number Diff line number Diff line change
@@ -44,6 +44,13 @@ public interface EndpointDataReferenceCache {
@NotNull
List<EndpointDataReferenceEntry> entriesForAsset(String assetId);


/**
* Returns the {@link EndpointDataReferenceEntry}s for the agreement.
*/
@NotNull
List<EndpointDataReferenceEntry> entriesForAgreement(String agreementId);

/**
* Saves an {@link EndpointDataReference} to the cache using upsert semantics.
*/