From 18ee9285c545d42f4a9078d8582fce3616d67c4b Mon Sep 17 00:00:00 2001 From: ChetanT-System Date: Thu, 23 May 2024 16:18:07 +0530 Subject: [PATCH 1/4] - PCF exchange code refactor and bpdm service api call changes --- .../repository/PcfRequestRepository.java | 4 +- .../AsyncPushPCFDataForApproveRequest.java | 2 +- .../service/impl/PCFRepositoryService.java | 6 +- .../service/impl/PcfExchangeServiceImpl.java | 72 ++++++++---- .../service/impl/ProxyRequestInterface.java | 30 +++-- .../PCFAssetStaticPropertyHolder.java | 67 +++++++++++ .../sde/common/submodel/executor/Step.java | 16 ++- .../PCFExchangeAssetProvider.java | 19 ++- .../sde/core/controller/PingController.java | 10 +- .../controller/PortalProxyController.java | 12 +- .../sde/core/service/PartnerPoolService.java | 110 ++++++++++++++++++ .../step/DigitalTwinAccessRuleFacilator.java | 36 ++++-- .../step/DigitalTwinUseCaseHandler.java | 22 +++- .../PortalProxyControllerTest.java | 6 +- .../resources/application-test.properties | 5 + .../entities/common/ProtocolInformation.java | 6 +- .../facilitator/DigitalTwinsUtility.java | 28 +++-- .../EDCAssetConfigurableConstant.java | 18 ++- .../sde/edc/gateways/external/EDCGateway.java | 17 ++- .../model/response/QueryDataOfferModel.java | 4 +- .../sde/edc/services/LookUpDTTwin.java | 68 ++++++++--- .../sde/edc/util/BPDMEdcAssetUtility.java | 88 ++++++++++++++ .../sde/edc/util/DDTRUrlCacheUtility.java | 13 ++- .../tractusx/sde/edc/util/EDCAssetLookUp.java | 37 +++--- .../sde/edc/util/EDCAssetUrlCacheService.java | 41 ++++++- .../sde/edc/util/PCFExchangeAssetUtils.java | 12 +- .../api/IPartnerPoolExternalServiceApi.java | 7 +- .../portal/handler/PortalProxyService.java | 24 +--- 28 files changed, 635 insertions(+), 145 deletions(-) create mode 100644 modules/sde-common/src/main/java/org/eclipse/tractusx/sde/common/configuration/properties/PCFAssetStaticPropertyHolder.java create mode 100644 modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/service/PartnerPoolService.java create mode 100644 modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/BPDMEdcAssetUtility.java diff --git a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/repository/PcfRequestRepository.java b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/repository/PcfRequestRepository.java index c6edbfa62..d539a77fd 100644 --- a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/repository/PcfRequestRepository.java +++ b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/repository/PcfRequestRepository.java @@ -32,7 +32,9 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface PcfRequestRepository extends JpaRepository { - + + List findByProductId(String productId); + Optional findByRequestIdAndProductIdAndBpnNumber(String requestId, String productId, String bpnNumber); diff --git a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/AsyncPushPCFDataForApproveRequest.java b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/AsyncPushPCFDataForApproveRequest.java index 60ecc73d9..a169d83cd 100644 --- a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/AsyncPushPCFDataForApproveRequest.java +++ b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/AsyncPushPCFDataForApproveRequest.java @@ -96,7 +96,7 @@ public void pushPCFDataForApproveRequest(List originalObjectList, Po // push api call Runnable runnable = () -> proxyRequestInterface.sendNotificationToConsumer(status, calculatedPCFValue, request.getProductId(), request.getBpnNumber(), - request.getRequestId(), request.getMessage()); + request.getRequestId(), request.getMessage(), false); new Thread(runnable).start(); diff --git a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/PCFRepositoryService.java b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/PCFRepositoryService.java index 3f3ab4db9..53ce04746 100644 --- a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/PCFRepositoryService.java +++ b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/PCFRepositoryService.java @@ -118,6 +118,11 @@ public PcfRequestEntity savePcfStatus(String requestId, PCFRequestStatusEnum sta return savePcfStatus(requestId, status, null); } + @SneakyThrows + public List findByProductId(String productId) { + return pcfRequestRepository.findByProductId(productId); + } + @SneakyThrows public PcfRequestEntity savePcfStatus(String requestId, PCFRequestStatusEnum status, String remark) { @@ -150,5 +155,4 @@ public PagingResponse getPcfData(List status, PCFTypeEnum return PagingResponse.builder().items(requestList).pageSize(result.getSize()).page(result.getNumber()) .totalItems(result.getTotalElements()).build(); } - } \ No newline at end of file diff --git a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/PcfExchangeServiceImpl.java b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/PcfExchangeServiceImpl.java index 1ea3146a4..f04cd4c2f 100644 --- a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/PcfExchangeServiceImpl.java +++ b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/PcfExchangeServiceImpl.java @@ -25,6 +25,7 @@ import java.util.UUID; import org.apache.commons.lang3.StringUtils; +import org.eclipse.tractusx.sde.common.configuration.properties.PCFAssetStaticPropertyHolder; import org.eclipse.tractusx.sde.common.entities.PolicyModel; import org.eclipse.tractusx.sde.common.exception.NoDataFoundException; import org.eclipse.tractusx.sde.common.exception.ServiceException; @@ -35,6 +36,7 @@ import org.eclipse.tractusx.sde.edc.model.request.ConsumerRequest; import org.eclipse.tractusx.sde.edc.model.response.QueryDataOfferModel; import org.eclipse.tractusx.sde.edc.util.EDCAssetUrlCacheService; +import org.eclipse.tractusx.sde.pcfexchange.entity.PcfRequestEntity; import org.eclipse.tractusx.sde.pcfexchange.entity.PcfResponseEntity; import org.eclipse.tractusx.sde.pcfexchange.enums.PCFRequestStatusEnum; import org.eclipse.tractusx.sde.pcfexchange.enums.PCFTypeEnum; @@ -60,11 +62,13 @@ public class PcfExchangeServiceImpl implements IPCFExchangeService { private final PCFRepositoryService pcfRepositoryService; private final PcfReqsponseRepository pcfReqsponseRepository; private final EDCAssetUrlCacheService edcAssetUrlCacheService; - + @Qualifier("DatabaseUsecaseHandler") private final DatabaseUsecaseStep databaseUsecaseStep; - + private final ProxyRequestInterface proxyRequestInterface; + + private final PCFAssetStaticPropertyHolder pcfAssetStaticPropertyHolder; @SneakyThrows @Override @@ -99,7 +103,7 @@ public String requestForPcfDataExistingOffer(String productId, ConsumerRequest c @Override public Object requestForPcfNotExistDataOffer(PcfRequestModel pcfRequestModel) { - + StringBuilder sb = new StringBuilder(); String requestId = UUID.randomUUID().toString(); List pcfExchangeUrlOffers = null; @@ -109,8 +113,7 @@ public Object requestForPcfNotExistDataOffer(PcfRequestModel pcfRequestModel) { PCFRequestStatusEnum.SENDING_REQUEST, ""); // 1 fetch EDC connectors and DTR Assets from EDC connectors - pcfExchangeUrlOffers = edcAssetUrlCacheService - .getPCFExchangeUrlFromTwin(pcfRequestModel.getBpnNumber()); + pcfExchangeUrlOffers = edcAssetUrlCacheService.getPCFExchangeUrlFromTwin(pcfRequestModel.getBpnNumber()); // 2 request for PCF value for non existing sub model and send notification to // call provider for data @@ -142,16 +145,17 @@ public String actionOnPcfRequestAndSendNotificationToConsumer(PcfRequestModel pc String remark = ""; try { - JsonObject calculatedPCFValue = databaseUsecaseStep.readCreatedTwinsBySpecifyColomn( - "urn:bamm:io.catenax.pcf", pcfRequestModel.getProductId()).get("json").getAsJsonObject(); - + JsonObject calculatedPCFValue = databaseUsecaseStep + .readCreatedTwinsBySpecifyColomn(pcfAssetStaticPropertyHolder.getSematicIdPart(), pcfRequestModel.getProductId()) + .get("json").getAsJsonObject(); + PCFRequestStatusEnum status = pcfRepositoryService.identifyRunningStatus(pcfRequestModel.getRequestId(), pcfRequestModel.getStatus()); // push api call Runnable runnable = () -> proxyRequestInterface.sendNotificationToConsumer(status, calculatedPCFValue, pcfRequestModel.getProductId(), pcfRequestModel.getBpnNumber(), pcfRequestModel.getRequestId(), - pcfRequestModel.getMessage()); + pcfRequestModel.getMessage(), true); new Thread(runnable).start(); @@ -178,7 +182,7 @@ public PcfRequestModel savePcfRequestData(String requestId, String productId, St PCFRequestStatusEnum status = PCFRequestStatusEnum.REQUESTED; String remark = ""; try { - databaseUsecaseStep.readCreatedTwinsBySpecifyColomn("urn:bamm:io.catenax.pcf", productId); + databaseUsecaseStep.readCreatedTwinsBySpecifyColomn(pcfAssetStaticPropertyHolder.getSematicIdPart(), productId); } catch (NoDataFoundException e) { String msg = "The PCF calculated value does not exist in system, please upload PCF value for '" + productId + "' in systems using Manual/Recurring Upload"; @@ -197,19 +201,6 @@ public void recievedPCFData(String productId, String bpnNumber, String requestId PCFRequestStatusEnum status = null; - PcfResponseEntity entity = PcfResponseEntity.builder() - .pcfData(pcfData) - .requestId(requestId) - .message(message) - .responseId(UUID.randomUUID().toString()) - .lastUpdatedTime(Instant.now().getEpochSecond()) - .build(); - - pcfReqsponseRepository.save(entity); - - if(StringUtils.isBlank(requestId)) - throw new ServiceException("RequestId not recieved from provider to marked PCF exchange request"); - if (pcfData != null && !pcfData.isEmpty() && !pcfData.asText().equals("{}")) { status = PCFRequestStatusEnum.RECEIVED; } else if (StringUtils.isNotBlank(requestId)) { @@ -217,8 +208,39 @@ public void recievedPCFData(String productId, String bpnNumber, String requestId } else status = PCFRequestStatusEnum.FAILED; - pcfRepositoryService.savePcfStatus(requestId, status); - + if (StringUtils.isNotBlank(requestId)) { + + PcfResponseEntity entity = PcfResponseEntity.builder() + .pcfData(pcfData) + .requestId(requestId) + .message(message) + .responseId(UUID.randomUUID().toString()) + .lastUpdatedTime(Instant.now().getEpochSecond()) + .build(); + + pcfReqsponseRepository.save(entity); + + pcfRepositoryService.savePcfStatus(requestId, status); + } + else { + List findByProductId = pcfRepositoryService.findByProductId(productId); + + for (PcfRequestEntity fentity : findByProductId) { + + PcfResponseEntity entity = PcfResponseEntity.builder() + .pcfData(pcfData) + .requestId(fentity.getRequestId()) + .message(message) + .responseId(UUID.randomUUID().toString()) + .lastUpdatedTime(Instant.now().getEpochSecond()) + .build(); + + pcfReqsponseRepository.save(entity); + + pcfRepositoryService.savePcfStatus(fentity.getRequestId(), status); + } + + } } @Override diff --git a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/ProxyRequestInterface.java b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/ProxyRequestInterface.java index ddd99bc6b..68c43250e 100644 --- a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/ProxyRequestInterface.java +++ b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/ProxyRequestInterface.java @@ -59,6 +59,16 @@ public class ProxyRequestInterface { public void requestToProviderForPCFValue(String productId, StringBuilder reponseMap, String requestId, String message, QueryDataOfferModel dataset, boolean isRequestToNonexistingTwin) { try { + String connectorOfferUrl = dataset.getConnectorOfferUrl(); + String pcfProductPath = ""; + if (connectorOfferUrl.contains("@")) { + String[] split = connectorOfferUrl.split("@"); + if (split.length > 1) { + dataset.setConnectorOfferUrl(split[0]); + pcfProductPath = split[1]; + } + } + EDRCachedByIdResponse edrToken = edcAssetUrlCacheService.verifyAndGetToken(dataset.getConnectorId(), dataset); @@ -73,7 +83,7 @@ public void requestToProviderForPCFValue(String productId, StringBuilder reponse pcfpushEnpoint = new URI( edrToken.getEndpoint() + SLASH_DELIMETER + PRODUCT_IDS + SLASH_DELIMETER + productId); else - pcfpushEnpoint = new URI(edrToken.getEndpoint()); + pcfpushEnpoint = new URI(edrToken.getEndpoint() + pcfProductPath); Map header = new HashMap<>(); header.put("authorization", edrToken.getAuthorization()); @@ -90,17 +100,17 @@ public void requestToProviderForPCFValue(String productId, StringBuilder reponse reponseMap.append(errorMsg); } } catch (FeignException e) { - log.error(LogUtil.encode("FeignRequest requestToProviderForPCFValue:" + e.request())); + log.error("FeignRequest requestToProviderForPCFValue:" + e.request()); String error= StringUtils.isBlank(e.contentUTF8()) ? e.getMessage() : e.contentUTF8(); String errorMsg= "Unable to request to provider '"+ dataset.getConnectorOfferUrl()+"' for '"+productId+"' product PCF value beacuse error in remote service execution"; - log.error(LogUtil.encode("FeignException requestToProviderForPCFValue: " + errorMsg + ", because: " +error)); + log.error("FeignException requestToProviderForPCFValue: " + errorMsg + ", because: " +error); reponseMap.append(errorMsg); } } @SneakyThrows public void sendNotificationToConsumer(PCFRequestStatusEnum status, JsonObject calculatedPCFValue, - String productId, String bpnNumber, String requestId, String message) { + String productId, String bpnNumber, String requestId, String message, boolean isNeedToSendRequestIdtoConsumer) { // 1 fetch EDC connectors and DTR Assets from EDC connectors List pcfExchangeUrlOffers = edcAssetUrlCacheService.getPCFExchangeUrlFromTwin(bpnNumber); @@ -114,9 +124,9 @@ public void sendNotificationToConsumer(PCFRequestStatusEnum status, JsonObject c pcfExchangeUrlOffers.parallelStream().forEach(dtOffer -> { if (PCFRequestStatusEnum.SENDING_REJECT_NOTIFICATION.equals(status)) { - sendNotification(null, productId, bpnNumber, requestId, dtOffer, status, message); + sendNotification(null, productId, bpnNumber, requestId, dtOffer, status, message, isNeedToSendRequestIdtoConsumer); } else { - sendNotification(calculatedPCFValue, productId, bpnNumber, requestId, dtOffer, status, message); + sendNotification(calculatedPCFValue, productId, bpnNumber, requestId, dtOffer, status, message, isNeedToSendRequestIdtoConsumer); } }); @@ -125,7 +135,7 @@ public void sendNotificationToConsumer(PCFRequestStatusEnum status, JsonObject c @SneakyThrows private void sendNotification(JsonObject calculatedPCFValue, String productId, String bpnNumber, String requestId, - QueryDataOfferModel dtOffer, PCFRequestStatusEnum status, String message) { + QueryDataOfferModel dtOffer, PCFRequestStatusEnum status, String message, boolean isNeedToSendRequestIdtoConsumer) { String sendNotificationStatus = ""; try { EDRCachedByIdResponse edrToken = edcAssetUrlCacheService.verifyAndGetToken(bpnNumber, dtOffer); @@ -139,7 +149,11 @@ private void sendNotification(JsonObject calculatedPCFValue, String productId, S header.put("authorization", edrToken.getAuthorization()); header.put("Edc-Bpn", bpnNumber); - pcfExchangeProxy.uploadPcfSubmodel(pcfpushEnpoint, header, requestId, message, + String sendRequestId = requestId; + if (!isNeedToSendRequestIdtoConsumer) + sendRequestId = ""; + + pcfExchangeProxy.uploadPcfSubmodel(pcfpushEnpoint, header, sendRequestId, message, jsonObjectMapper.gsonObjectToJsonNode(calculatedPCFValue)); sendNotificationStatus = "SUCCESS"; diff --git a/modules/sde-common/src/main/java/org/eclipse/tractusx/sde/common/configuration/properties/PCFAssetStaticPropertyHolder.java b/modules/sde-common/src/main/java/org/eclipse/tractusx/sde/common/configuration/properties/PCFAssetStaticPropertyHolder.java new file mode 100644 index 000000000..9a9f2a338 --- /dev/null +++ b/modules/sde-common/src/main/java/org/eclipse/tractusx/sde/common/configuration/properties/PCFAssetStaticPropertyHolder.java @@ -0,0 +1,67 @@ +/******************************************************************************** + * Copyright (c) 2024 T-Systems International GmbH + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.sde.common.configuration.properties; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +@Component +@Configuration +public class PCFAssetStaticPropertyHolder { + + @Value(value = "${digital-twin.pcf.sematicid:}") + public String sematicId; + + @Value(value = "${digital-twin.pcf.sematicid:}") + public String sematicIdPart; + + private String pcfExchangeAssetId; + + public String getSematicId() { + if (StringUtils.isAllBlank(sematicId)) + sematicId = "urn:samm:io.catenax.pcf:6.0.0#Pcf"; + return sematicId; + } + + public void setSematicId(String sematicId) { + this.sematicId = sematicId; + } + + public String getSematicIdPart() { + if (StringUtils.isAllBlank(sematicIdPart)) + sematicIdPart = "urn:samm:io.catenax.pcf"; + return sematicIdPart; + } + + public void setSematicIdPart(String sematicIdPart) { + this.sematicIdPart = sematicIdPart; + } + + public String getPcfExchangeAssetId() { + return pcfExchangeAssetId; + } + + public void setPcfExchangeAssetId(String pcfExchangeAssetId) { + this.pcfExchangeAssetId = pcfExchangeAssetId; + } + +} diff --git a/modules/sde-common/src/main/java/org/eclipse/tractusx/sde/common/submodel/executor/Step.java b/modules/sde-common/src/main/java/org/eclipse/tractusx/sde/common/submodel/executor/Step.java index caaf58168..40b739929 100644 --- a/modules/sde-common/src/main/java/org/eclipse/tractusx/sde/common/submodel/executor/Step.java +++ b/modules/sde-common/src/main/java/org/eclipse/tractusx/sde/common/submodel/executor/Step.java @@ -80,6 +80,16 @@ public String getDataPlaneUrlOfSubmodule() { JsonElement jsonElement = this.submodelSchema.get("submodelDataPlaneUrl"); return jsonElement == null || jsonElement.isJsonNull() ? "" : jsonElement.getAsString(); } + + public String getSematicIdReferenceOfSubmodule() { + JsonElement jsonElement = this.submodelSchema.get("sematicIdReference"); + return jsonElement == null || jsonElement.isJsonNull() ? "" : jsonElement.getAsString(); + } + + public String getInterfaceNameOfSubmodule() { + JsonElement jsonElement = this.submodelSchema.get("interfaceName"); + return jsonElement == null || jsonElement.isJsonNull() ? "" : jsonElement.getAsString(); + } public JsonObject getAddOnOfModel() { return this.submodelSchema.get("addOn").getAsJsonObject(); @@ -111,7 +121,11 @@ public boolean checkAppendURNUUIDWithIdentifier() { return jsonElement == null || jsonElement.isJsonNull() || jsonElement.getAsBoolean(); } - + public boolean usePCFAssetIdAsDTSubprotocolBodyId() { + JsonElement jsonElement = this.getAddOnOfModel().get("usePCFAssetIdAsDTSubprotocolBodyId"); + return !(jsonElement == null || jsonElement.isJsonNull()) || (jsonElement !=null && jsonElement.getAsBoolean()); + } + public JsonObject checkIsRelationSubmodel() { JsonElement jsonElement = this.getAddOnOfModel().get("isRelationSubmodel"); return jsonElement == null || jsonElement.isJsonNull() ? null : jsonElement.getAsJsonObject(); diff --git a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/configuration/PCFExchangeAssetProvider.java b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/configuration/PCFExchangeAssetProvider.java index c3d5a69ff..f4058fca4 100644 --- a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/configuration/PCFExchangeAssetProvider.java +++ b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/configuration/PCFExchangeAssetProvider.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; +import org.eclipse.tractusx.sde.common.configuration.properties.PCFAssetStaticPropertyHolder; import org.eclipse.tractusx.sde.common.configuration.properties.SDEConfigurationProperties; import org.eclipse.tractusx.sde.common.entities.Policies; import org.eclipse.tractusx.sde.common.entities.PolicyModel; @@ -39,6 +40,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -60,15 +62,15 @@ public class PCFExchangeAssetProvider { private final ValueReplacerUtility valueReplacerUtility; private final SDEConfigurationProperties sdeConfigurationProperties; private final EDCAssetConfigurableConstant edcAssetConfigurableConstant; + private final PCFAssetStaticPropertyHolder pcfAssetStaticPropertyHolder; @PostConstruct @SneakyThrows public void init() { String assetId = UUIdGenerator.getUuid(); - String sematicId = "urn:samm:io.catenax.pcf:6.0.0#Pcf"; AssetEntryRequest assetEntryRequest = assetFactory.getAssetRequest("", "PCF Exchange endpoint information", - assetId, "1", "", "", sematicId, edcAssetConfigurableConstant.getAssetPropTypePCFExchangeType()); + assetId, "1", "", "", pcfAssetStaticPropertyHolder.getSematicId(), edcAssetConfigurableConstant.getAssetPropTypePCFExchangeType()); String baseUrl = sdeConfigurationProperties.getSdeHostname() + "/pcf"; assetEntryRequest.getDataAddress().getProperties().put("baseUrl", baseUrl); @@ -84,8 +86,11 @@ public void init() { ObjectNode requestBody = (ObjectNode) new ObjectMapper().readTree(valueReplacerUtility .valueReplacerUsingFileTemplate("/edc_request_template/edc_asset_lookup.json", inputData)); - - if (!edcGateway.assetExistsLookupBasedOnType(requestBody)) { + JsonNode assetExistsLookupBasedOnTypeGetAsAsset = edcGateway.assetExistsLookupBasedOnTypeGetAsAsset(requestBody); + + if (assetExistsLookupBasedOnTypeGetAsAsset == null || + assetExistsLookupBasedOnTypeGetAsAsset.isNull() || + (assetExistsLookupBasedOnTypeGetAsAsset.isArray() && assetExistsLookupBasedOnTypeGetAsAsset.isEmpty())) { List accessPolicy = PolicyOperationUtil .getStringPolicyAsPolicyList(edcAssetConfigurableConstant.getPcfExcahngeAccessPolicy()); @@ -99,10 +104,14 @@ public void init() { .build(); Map createEDCAsset = createEDCAssetFacilator.createEDCAsset(assetEntryRequest, policy); + + pcfAssetStaticPropertyHolder.setPcfExchangeAssetId(assetEntryRequest.getId()); log.info("PCF Exchange asset creates :" + createEDCAsset.toString()); + } else { + + pcfAssetStaticPropertyHolder.setPcfExchangeAssetId(assetExistsLookupBasedOnTypeGetAsAsset.get(0).get("@id").asText()); log.info("PCF Exchange asset exists in edc connector, so ignoring asset creation"); } } - } \ No newline at end of file diff --git a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/controller/PingController.java b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/controller/PingController.java index a19e11446..09b4d45a8 100644 --- a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/controller/PingController.java +++ b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/controller/PingController.java @@ -1,7 +1,7 @@ /******************************************************************************** * Copyright (c) 2022 BMW GmbH - * Copyright (c) 2022, 2024 T-Systems International GmbH - * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2022,2024 T-Systems International GmbH + * Copyright (c) 2022,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -57,4 +57,10 @@ public ResponseEntity clearDdtrurlCache() { edcAssetUrlCacheService.clearDDTRUrlCache(); return ok().body("Cleared"); } + + @GetMapping(value = "/cache/clear-pcfurl") + public ResponseEntity clearPCFExchangeUrlCache() { + edcAssetUrlCacheService.clearPCFExchangeUrlCache(); + return ok().body("Cleared"); + } } \ No newline at end of file diff --git a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/controller/PortalProxyController.java b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/controller/PortalProxyController.java index 48c23282c..5be1f85f2 100644 --- a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/controller/PortalProxyController.java +++ b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/controller/PortalProxyController.java @@ -1,6 +1,6 @@ /******************************************************************************** - * Copyright (c) 2023 T-Systems International GmbH - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023,2024 T-Systems International GmbH + * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -23,6 +23,7 @@ import java.util.List; +import org.eclipse.tractusx.sde.core.service.PartnerPoolService; import org.eclipse.tractusx.sde.portal.handler.PortalProxyService; import org.eclipse.tractusx.sde.portal.model.ConnectorInfo; import org.eclipse.tractusx.sde.portal.model.response.LegalEntityResponse; @@ -46,13 +47,16 @@ public class PortalProxyController { @Autowired private PortalProxyService portalProxyService; + @Autowired + private PartnerPoolService partnerPoolService; + @GetMapping(value = "/legal-entities") @PreAuthorize("hasPermission('','consumer_search_connectors')") - public ResponseEntity> fetchLegalEntitiesData(@RequestParam String searchText, + public ResponseEntity> fetchLegalEntitiesData(@RequestParam (required = false) String bpnLs, @RequestParam String searchText, @RequestParam Integer page, @RequestParam Integer size) throws Exception { log.info("Request received : /api/legal-entities"); - List legalEntitiesResponse = portalProxyService.fetchLegalEntitiesData(searchText, + List legalEntitiesResponse = partnerPoolService.fetchLegalEntitiesData(bpnLs, searchText, page, size); return ok().body(legalEntitiesResponse); } diff --git a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/service/PartnerPoolService.java b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/service/PartnerPoolService.java new file mode 100644 index 000000000..f1aad3dab --- /dev/null +++ b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/service/PartnerPoolService.java @@ -0,0 +1,110 @@ +/******************************************************************************** + * Copyright (c) 2024 T-Systems International GmbH + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.sde.core.service; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.tractusx.sde.edc.constants.EDCAssetConfigurableConstant; +import org.eclipse.tractusx.sde.edc.model.edr.EDRCachedByIdResponse; +import org.eclipse.tractusx.sde.edc.model.response.QueryDataOfferModel; +import org.eclipse.tractusx.sde.edc.util.EDCAssetUrlCacheService; +import org.eclipse.tractusx.sde.portal.api.IPartnerPoolExternalServiceApi; +import org.eclipse.tractusx.sde.portal.model.LegalEntityData; +import org.eclipse.tractusx.sde.portal.model.response.LegalEntityResponse; +import org.springframework.stereotype.Service; + +import feign.FeignException; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor +public class PartnerPoolService { + + private final EDCAssetUrlCacheService edcAssetUrlCacheService; + + private final EDCAssetConfigurableConstant edcAssetConfigurableConstant; + + private final IPartnerPoolExternalServiceApi partnerPoolExternalServiceApi; + + @SneakyThrows + public List fetchLegalEntitiesData(String bpnLs, String searchText, Integer page, Integer size) { + + List legalEntityResponseList = new LinkedList<>(); + List ddTROffers = edcAssetUrlCacheService.getBpdmUrl(); + + for (QueryDataOfferModel dtOffer : ddTROffers) { + + EDRCachedByIdResponse edrToken = edcAssetUrlCacheService.verifyAndGetToken(edcAssetConfigurableConstant.getBpdmProviderBpnl(), dtOffer); + + if (edrToken != null) { + + LegalEntityData legalEntity = fetchLegalEntityDataByEdrToken(bpnLs, searchText, edcAssetConfigurableConstant.getBpdmProviderEdcPublicApi(), edrToken, page, size ); + legalEntityResponseList.addAll(legalEntity.getContent().stream().map(companyData -> + LegalEntityResponse.builder() + .bpn(companyData.getBpnl()) + .name(companyData.getLegalName()) + .build()) + .toList()); + + } else { + log.warn("EDR token is null, unable to fetch legal entities data for :" + dtOffer.toString()); + return Collections.emptyList(); + } + } + + return Optional.ofNullable(legalEntityResponseList).orElse(Collections.emptyList()); + } + + + private LegalEntityData fetchLegalEntityDataByEdrToken(String bpnLs, String legalName, + String bpdmProviderEdcPublicUrl, EDRCachedByIdResponse edrToken, Integer page, Integer size) { + + LegalEntityData legalEntityData = null; + try { + + Map header = new HashMap<>(); + header.put("authorization", edrToken.getAuthorization()); + + legalEntityData = partnerPoolExternalServiceApi.fetchLegalEntityData(bpnLs, legalName, page, size, header); + + } catch (FeignException e) { + String err = e.contentUTF8(); + err = StringUtils.isBlank(err) ? e.getMessage() : err; + String errorMsg = "Unable to fetch LegalEntity Data for " + legalName + "Or BpnLs " + bpnLs + " because: " + + err; + log.error("FeignException : " + errorMsg); + } catch (Exception e) { + String errorMsg = "Unable to fetch LegalEntity Data for " + legalName + "Or BpnLs " + bpnLs + "because: " + + e.getMessage(); + log.error("Exception : " + errorMsg); + } + return legalEntityData; + } +} diff --git a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/submodel/executor/step/DigitalTwinAccessRuleFacilator.java b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/submodel/executor/step/DigitalTwinAccessRuleFacilator.java index 4246bd3be..13abe679f 100644 --- a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/submodel/executor/step/DigitalTwinAccessRuleFacilator.java +++ b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/submodel/executor/step/DigitalTwinAccessRuleFacilator.java @@ -62,6 +62,8 @@ public class DigitalTwinAccessRuleFacilator extends Step { @Qualifier("DatabaseUsecaseHandler") private final DatabaseUsecaseStep databaseUseCaseStep; + private static final String PUBLIC_READABLE = "PUBLIC_READABLE"; + private String createRuleTemplate = """ { "validFrom": "2020-01-02T03:04:05Z", @@ -111,17 +113,12 @@ public void createAccessRule(Integer rowIndex, ObjectNode jsonObject, Map accessBPNList = PolicyOperationUtil.getAccessBPNList(policy); List accessruleIds = new ArrayList<>(); - for (String bpn : accessBPNList) { - - String requestTemplate = String.format(createRuleTemplate, bpn, - digitalTwinsUtility.createAccessRuleMandatorySpecificAssetIds(specificAssetIds), - digitalTwinsUtility.createAccessRuleVisibleSpecificAssetIdNames(specificAssetIds), sematicId); - - JsonNode requestBody = new ObjectMapper().readTree(requestTemplate); - - JsonNode response = digitalTwinFacilitator - .createAccessControlsRule(sdeConfigProperties.getManufacturerId(), requestBody); - accessruleIds.add(response.get("id").asText()); + if (accessBPNList.isEmpty()) { + createAccessRuleMethod(specificAssetIds, sematicId, accessruleIds, PUBLIC_READABLE); + } else { + for (String bpn : accessBPNList) { + createAccessRuleMethod(specificAssetIds, sematicId, accessruleIds, bpn); + } } jsonObject.put(SubmoduleCommonColumnsConstant.SHELL_ACCESS_RULE_IDS, StringUtils.join(accessruleIds, ",")); @@ -135,6 +132,23 @@ public void createAccessRule(Integer rowIndex, ObjectNode jsonObject, Map specificAssetIds, String sematicId, + List accessruleIds, String bpn) { + + String requestTemplate = String.format(createRuleTemplate, bpn, + digitalTwinsUtility.createAccessRuleMandatorySpecificAssetIds(specificAssetIds), + digitalTwinsUtility.createAccessRuleVisibleSpecificAssetIdNames(specificAssetIds), sematicId); + + JsonNode requestBody = new ObjectMapper().readTree(requestTemplate); + + JsonNode response = digitalTwinFacilitator.createAccessControlsRule(sdeConfigProperties.getManufacturerId(), + requestBody); + + accessruleIds.add(response.get("id").asText()); + + } + private void deleteAllExistingDTAccessRulesIfExist(Integer rowIndex, ObjectNode jsonObject) { String identifier = getIdentifier(jsonObject, getIdentifierOfModel()); diff --git a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/submodel/executor/step/DigitalTwinUseCaseHandler.java b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/submodel/executor/step/DigitalTwinUseCaseHandler.java index eb00c85f9..4460a58f6 100644 --- a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/submodel/executor/step/DigitalTwinUseCaseHandler.java +++ b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/submodel/executor/step/DigitalTwinUseCaseHandler.java @@ -25,6 +25,7 @@ import java.util.TreeMap; import org.apache.commons.lang3.StringUtils; +import org.eclipse.tractusx.sde.common.configuration.properties.PCFAssetStaticPropertyHolder; import org.eclipse.tractusx.sde.common.configuration.properties.SDEConfigurationProperties; import org.eclipse.tractusx.sde.common.constants.CommonConstants; import org.eclipse.tractusx.sde.common.constants.SubmoduleCommonColumnsConstant; @@ -71,6 +72,8 @@ public class DigitalTwinUseCaseHandler extends Step implements DigitalTwinUsecas private final DigitalTwinAccessRuleFacilator digitalTwinAccessRuleFacilator; + private final PCFAssetStaticPropertyHolder pcfAssetStaticPropertyHolder; + @Value(value = "${edc.hostname}${edc.dataplane.endpointpath:/api/public}") public String digitalTwinEdcDataplaneEndpoint; @@ -179,17 +182,28 @@ public JsonNode checkAndCreateSubmodulIfNotExist(Integer rowIndex, ObjectNode js String submodelIdentifier = identification.get("submodelIdentifier"); if (StringUtils.isNotBlank(path)) { - path = FORWARD_SLASH + getNameOfModel() + FORWARD_SLASH + path + FORWARD_SLASH - + submodelRequestidentifier; + path = FORWARD_SLASH + path + FORWARD_SLASH+ submodelRequestidentifier; } if (StringUtils.isBlank(submodelDataPlaneUrl)) { submodelDataPlaneUrl = digitalTwinEdcDataplaneEndpoint; } + String endPointAddress= submodelDataPlaneUrl + path; + + String edcAssetId = shellId + "-" + submodelIdentifier; + + if (usePCFAssetIdAsDTSubprotocolBodyId()) + edcAssetId = pcfAssetStaticPropertyHolder.getPcfExchangeAssetId(); + + + String sematicIdReference = getSematicIdReferenceOfSubmodule(); + + String interfaceName = getInterfaceNameOfSubmodule(); + CreateSubModelRequest createSubModelRequest = digitalTwinsUtility.getCreateSubModelRequest(shellId, - getsemanticIdOfModel(), getIdShortOfModel(), submodelIdentifier, submodelDataPlaneUrl + path, - getSubmodelShortDescriptionOfModel()); + getsemanticIdOfModel(), getIdShortOfModel(), submodelIdentifier, edcAssetId, endPointAddress, + getSubmodelShortDescriptionOfModel(), sematicIdReference, interfaceName); if (foundSubmodel == null) { logDebug(String.format("No submodels for '%s'", shellId)); diff --git a/modules/sde-core/src/test/java/org/eclipse/tractusx/sde/controllers/PortalProxyControllerTest.java b/modules/sde-core/src/test/java/org/eclipse/tractusx/sde/controllers/PortalProxyControllerTest.java index 9417834d0..1bb7137c8 100644 --- a/modules/sde-core/src/test/java/org/eclipse/tractusx/sde/controllers/PortalProxyControllerTest.java +++ b/modules/sde-core/src/test/java/org/eclipse/tractusx/sde/controllers/PortalProxyControllerTest.java @@ -25,6 +25,7 @@ import java.util.List; import org.eclipse.tractusx.sde.core.controller.PortalProxyController; +import org.eclipse.tractusx.sde.core.service.PartnerPoolService; import org.eclipse.tractusx.sde.portal.handler.PortalProxyService; import org.eclipse.tractusx.sde.portal.model.ConnectorInfo; import org.eclipse.tractusx.sde.portal.model.response.UnifiedBPNValidationStatusEnum; @@ -50,6 +51,9 @@ class PortalProxyControllerTest { @MockBean private PortalProxyService portalProxyService; + + @MockBean + private PartnerPoolService partnerPoolService; @Autowired private PortalProxyController consumerController; @@ -57,7 +61,7 @@ class PortalProxyControllerTest { @Test void testFetchLegalEntitiesData() throws Exception { - when(portalProxyService.fetchLegalEntitiesData((String) any(), (Integer) any(), (Integer) any())) + when(partnerPoolService.fetchLegalEntitiesData((String) any(),(String) any(), (Integer) any(), (Integer) any())) .thenReturn(List.of()); MockHttpServletRequestBuilder getResult = MockMvcRequestBuilders.get("/legal-entities"); MockHttpServletRequestBuilder paramResult = getResult.param("page", String.valueOf(0)).param("searchText", "bmw"); diff --git a/modules/sde-core/src/test/resources/application-test.properties b/modules/sde-core/src/test/resources/application-test.properties index 5651f211b..ca540bb7f 100644 --- a/modules/sde-core/src/test/resources/application-test.properties +++ b/modules/sde-core/src/test/resources/application-test.properties @@ -98,6 +98,11 @@ partner.pool.clientSecret=test partner.pool.grantType=client_credentials +bpdm.provider.edc.dataspace.api=test +bpdm.provider.bpnl=test +bpdm.provider.edc.public.api=test + + ## Portal backend and Connector discovery portal.backend.hostname=test portal.backend.authentication.url=test diff --git a/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/entities/common/ProtocolInformation.java b/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/entities/common/ProtocolInformation.java index 0bede9268..563f811c1 100644 --- a/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/entities/common/ProtocolInformation.java +++ b/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/entities/common/ProtocolInformation.java @@ -1,7 +1,7 @@ /******************************************************************************** * Copyright (c) 2022 BMW GmbH - * Copyright (c) 2022, 2023 T-Systems International GmbH - * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022,2024 T-Systems International GmbH + * Copyright (c) 2022,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -42,7 +42,7 @@ public class ProtocolInformation { private String endpointAddress; private String endpointProtocol; private List endpointProtocolVersion; - private String subProtocol; + private String subprotocol; private String subprotocolBody; private String subprotocolBodyEncoding; private List securityAttributes; diff --git a/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/facilitator/DigitalTwinsUtility.java b/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/facilitator/DigitalTwinsUtility.java index 45d70ab34..2c61ab697 100644 --- a/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/facilitator/DigitalTwinsUtility.java +++ b/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/facilitator/DigitalTwinsUtility.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.Map.Entry; +import org.apache.commons.lang3.StringUtils; import org.eclipse.tractusx.sde.common.constants.CommonConstants; import org.eclipse.tractusx.sde.common.entities.PolicyModel; import org.eclipse.tractusx.sde.common.utils.PolicyOperationUtil; @@ -99,12 +100,16 @@ private String resizeShortId(String str) { @SneakyThrows public CreateSubModelRequest getCreateSubModelRequest(String shellId, String sematicId, String idShortofModel, - String identification, String endpointAddress, String description) { + String identification, String edcAssetId, String endpointAddress, String description, + String sematicIdReference, String interfaceName) { + + if (StringUtils.isAllBlank(sematicIdReference)) + sematicIdReference = CommonConstants.SUBMODEL; SemanticId semanticId = SemanticId.builder().type(CommonConstants.EXTERNAL_REFERENCE) - .keys(List.of(new Keys(CommonConstants.SUBMODEL, sematicId))).build(); + .keys(List.of(new Keys(sematicIdReference, sematicId))).build(); - List endpoints = prepareDtEndpoint(shellId, identification, endpointAddress); + List endpoints = prepareDtEndpoint(edcAssetId, endpointAddress, interfaceName); MultiLanguage engLang = MultiLanguage.builder().language("en").text(description).build(); @@ -112,17 +117,19 @@ public CreateSubModelRequest getCreateSubModelRequest(String shellId, String sem .description(List.of(engLang)).endpoints(endpoints).build(); } - public List prepareDtEndpoint(String shellId, String submodelIdentification, String endpointAddress) { + public List prepareDtEndpoint(String edcAssetId, String endpointAddress, String interfaceName) { List endpoints = new ArrayList<>(); - endpoints.add(Endpoint.builder().endpointInterface(CommonConstants.INTERFACE) - .protocolInformation(ProtocolInformation.builder() - .endpointAddress(endpointAddress) + + if (StringUtils.isAllBlank(interfaceName)) + interfaceName = CommonConstants.INTERFACE; + + endpoints.add(Endpoint.builder().endpointInterface(interfaceName) + .protocolInformation(ProtocolInformation.builder().endpointAddress(endpointAddress) .endpointProtocol(CommonConstants.HTTP) .endpointProtocolVersion(List.of(CommonConstants.ENDPOINT_PROTOCOL_VERSION)) - .subProtocol(CommonConstants.SUB_PROTOCOL) - .subprotocolBody("id=" + shellId + "-" + submodelIdentification + ";dspEndpoint=" - + digitalTwinEdcDspEndpoint) + .subprotocol(CommonConstants.SUB_PROTOCOL) + .subprotocolBody("id=" + edcAssetId + ";dspEndpoint=" + digitalTwinEdcDspEndpoint) .subprotocolBodyEncoding(CommonConstants.BODY_ENCODING) .securityAttributes(List.of(new SecurityAttributes("NONE", "NONE", "NONE"))).build()) .build()); @@ -256,5 +263,4 @@ public List encodeAssetIdsObjectOnlyPartInstanceId(ShellLookupRequest re public String encodeValueAsBase64Utf8(String string) { return Base64.getUrlEncoder().encodeToString(string.getBytes()); } - } \ No newline at end of file diff --git a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/constants/EDCAssetConfigurableConstant.java b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/constants/EDCAssetConfigurableConstant.java index ff1574ce9..a55bd4dff 100644 --- a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/constants/EDCAssetConfigurableConstant.java +++ b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/constants/EDCAssetConfigurableConstant.java @@ -1,6 +1,6 @@ /******************************************************************************** - * Copyright (c) 2024 T-Systems International GmbH - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2023,2024 T-Systems International GmbH + * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -20,6 +20,8 @@ package org.eclipse.tractusx.sde.edc.constants; +import java.util.List; + import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @@ -67,5 +69,17 @@ public class EDCAssetConfigurableConstant { @Value("${edc.policy.digital-twin.usage:Membership@active}") private String digitalTwinExchangeUsagePolicy; + + @Value("#{'${edc.bpdm.asset.search.criteria:https://purl.org/dc/terms/subject@cx-taxo:ReadAccessPoolForCatenaXMember;https://w3id.org/catenax/ontology/common/version@6.0}'.split(';')}") + private List edcBPDMSearchCriteria; + + @Value("${bpdm.provider.edc.dataspace.api}") + private String bpdmProviderEdcDataspaceApi; + + @Value("${bpdm.provider.edc.public.api}") + private String bpdmProviderEdcPublicApi; + + @Value("${bpdm.provider.bpnl}") + private String bpdmProviderBpnl; } diff --git a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/gateways/external/EDCGateway.java b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/gateways/external/EDCGateway.java index 334ecac1c..58307e26e 100644 --- a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/gateways/external/EDCGateway.java +++ b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/gateways/external/EDCGateway.java @@ -1,7 +1,7 @@ /******************************************************************************** - * Copyright (c) 2022 BMW GmbH - * Copyright (c) 2022, 2024 T-Systems International GmbH - * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2022 BMW GmbH + * Copyright (c) 2022,2024 T-Systems International GmbH + * Copyright (c) 2022,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -66,6 +66,17 @@ public boolean assetExistsLookupBasedOnType(ObjectNode requestBody) { } return true; } + + public JsonNode assetExistsLookupBasedOnTypeGetAsAsset(ObjectNode requestBody) { + try { + return edcFeignClientApi.getAssetByType(requestBody); + } catch (FeignException e) { + if (e.status() == HttpStatus.NOT_FOUND.value()) { + return null; + } + throw e; + } + } public String createAsset(AssetEntryRequest request) { try { diff --git a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/model/response/QueryDataOfferModel.java b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/model/response/QueryDataOfferModel.java index 9b10952e2..a2ba8bd38 100644 --- a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/model/response/QueryDataOfferModel.java +++ b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/model/response/QueryDataOfferModel.java @@ -90,7 +90,9 @@ public boolean equals(Object obj) { // type casting of the argument. QueryDataOfferModel offer = (QueryDataOfferModel) obj; - return (offer.assetId.equals(this.assetId) && offer.connectorOfferUrl.equals(this.connectorOfferUrl)); + return (offer.assetId.equals(this.assetId) + && offer.connectorOfferUrl.equals(this.connectorOfferUrl) + && offer.sematicVersion.equals(this.sematicVersion)); } @Override diff --git a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/services/LookUpDTTwin.java b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/services/LookUpDTTwin.java index 9fe90603d..c36802c54 100644 --- a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/services/LookUpDTTwin.java +++ b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/services/LookUpDTTwin.java @@ -35,6 +35,7 @@ import org.eclipse.tractusx.sde.common.utils.LogUtil; import org.eclipse.tractusx.sde.digitaltwins.entities.common.KeyValuePair; import org.eclipse.tractusx.sde.digitaltwins.entities.common.MultiLanguage; +import org.eclipse.tractusx.sde.digitaltwins.entities.common.ProtocolInformation; import org.eclipse.tractusx.sde.digitaltwins.entities.request.ShellLookupRequest; import org.eclipse.tractusx.sde.digitaltwins.entities.response.ShellDescriptorResponse; import org.eclipse.tractusx.sde.digitaltwins.entities.response.ShellDescriptorResponseList; @@ -93,7 +94,7 @@ public List lookUpTwin(EDRCachedByIdResponse edrToken, Quer header.put("Edc-Bpn", sdeConfigurationProperties.getManufacturerId()); if (StringUtils.isBlank(manufacturerPartId)) { - return lookUpAllShellForBPN(submodel, endpoint, dtOfferUrl, header, offset, limit); + return lookUpAllShellForBPN(bpnNumber, submodel, endpoint, dtOfferUrl, header, offset, limit); } else { return lookUpTwinBasedOnBPNAndManufacturerPartId(manufacturerPartId, bpnNumber, submodel, endpoint, dtOfferUrl, header); @@ -113,7 +114,7 @@ private List lookUpTwinBasedOnBPNAndManufacturerPartId(Stri ShellLookupResponse response = mapper.readValue(shellLookup, ShellLookupResponse.class); return getSubmodelDetails(shellLookupRequest, endpoint, header, dtOfferUrl, response.getResult(), - submodel); + submodel, bpnNumber); } catch (FeignException e) { log.error(LogUtil.encode("LookUpTwinBasedOnBPNAndManufacturerPartId RequestBody: " + e.request())); @@ -131,7 +132,7 @@ private List lookUpTwinBasedOnBPNAndManufacturerPartId(Stri return Collections.emptyList(); } - private List lookUpAllShellForBPN(String submodel, String endpoint, String dtOfferUrl, + private List lookUpAllShellForBPN(String searchBPN, String submodel, String endpoint, String dtOfferUrl, Map header, Integer offset, Integer limit) { List queryOnDataOffers = new ArrayList<>(); try { @@ -139,7 +140,7 @@ private List lookUpAllShellForBPN(String submodel, String e ShellDescriptorResponseList allShell = eDCDigitalTwinProxyForLookUp.getAllShell(new URI(endpoint), offset, limit, header); for (ShellDescriptorResponse shellDescriptorResponse : allShell.getResult()) - preapreSubmodelResult(submodel, queryOnDataOffers, shellDescriptorResponse); + preapreSubmodelResult(submodel, queryOnDataOffers, shellDescriptorResponse, searchBPN); } catch (FeignException e) { log.error(LogUtil.encode("FeignException LookUpAllShellForBPN request : "+e.request())); @@ -159,7 +160,7 @@ private List lookUpAllShellForBPN(String submodel, String e @SneakyThrows private List getSubmodelDetails(ShellLookupRequest shellLookupRequest, String endpoint, - Map header, String dtOfferUrl, List shellIds, String submodel) { + Map header, String dtOfferUrl, List shellIds, String submodel, String searchBPN) { List queryOnDataOffers = new ArrayList<>(); for (String shellId : shellIds) { @@ -169,26 +170,29 @@ private List getSubmodelDetails(ShellLookupRequest shellLoo + shellDescriptorResponseStr)); ShellDescriptorResponse shellDescriptorResponse = mapper.readValue(shellDescriptorResponseStr, ShellDescriptorResponse.class); - preapreSubmodelResult(submodel, queryOnDataOffers, shellDescriptorResponse); + preapreSubmodelResult(submodel, queryOnDataOffers, shellDescriptorResponse, searchBPN); } return queryOnDataOffers; } private void preapreSubmodelResult(String submodel, List queryOnDataOffers, - ShellDescriptorResponse shellDescriptorResponse) { + ShellDescriptorResponse shellDescriptorResponse, String searchBPN) { String manufacturerPartId = getSpecificKeyFromList(shellDescriptorResponse, "manufacturerPartId"); String manufacturerBPNId = getSpecificKeyFromList(shellDescriptorResponse, "manufacturerId"); + + if(StringUtils.isBlank(manufacturerBPNId)) { + manufacturerBPNId= searchBPN; + } - if (StringUtils.isNotBlank(shellDescriptorResponse.getIdShort())) - for (SubModelResponse subModelResponse : shellDescriptorResponse.getSubmodelDescriptors()) { + for (SubModelResponse subModelResponse : shellDescriptorResponse.getSubmodelDescriptors()) { - String sematicId = subModelResponse.getSemanticId().getKeys().get(0).getValue(); + String sematicId = subModelResponse.getSemanticId().getKeys().get(0).getValue(); - buildQdmOffer(submodel, queryOnDataOffers, shellDescriptorResponse, manufacturerPartId, - manufacturerBPNId, subModelResponse, sematicId); - } + buildQdmOffer(submodel, queryOnDataOffers, shellDescriptorResponse, manufacturerPartId, + manufacturerBPNId, subModelResponse, sematicId); + } } private void buildQdmOffer(String submodel, List queryOnDataOffers, @@ -198,8 +202,17 @@ private void buildQdmOffer(String submodel, List queryOnDat if (!subModelResponse.getIdShort().isEmpty() && sematicId.toLowerCase().contains(submodel.toLowerCase()) && subModelResponse.getEndpoints() != null) { - String subprotocolBody = subModelResponse.getEndpoints().get(0).getProtocolInformation() - .getSubprotocolBody(); + ProtocolInformation protocolInformation = subModelResponse.getEndpoints().get(0).getProtocolInformation(); + + String subprotocolBody = protocolInformation.getSubprotocolBody(); + + String submodelIdShort = subModelResponse.getIdShort(); + + String href = ""; + if(submodelIdShort.equals("PCFExchangeEndpoint")) { + href = protocolInformation.getEndpointAddress(); + href = href.replace("https://edc.data.plane", "@"); + } String[] edcInfo = subprotocolBody.split(";"); String[] assetInfo = edcInfo[0].split("="); @@ -210,14 +223,19 @@ private void buildQdmOffer(String submodel, List queryOnDat String description = descriptionOptional.isPresent() ? descriptionOptional.get() : ""; + String shellIdShort = shellDescriptorResponse.getIdShort(); + + if(StringUtils.isBlank(shellIdShort)) + shellIdShort ="ShellTwinIdShortNotVisible"; + QueryDataOfferModel qdm = QueryDataOfferModel.builder() .publisher(manufacturerBPNId) .manufacturerPartId(manufacturerPartId) - .connectorOfferUrl(connectorInfo[1]) + .connectorOfferUrl(connectorInfo[1]+href) .assetId(assetInfo[1]) .type(subModelResponse.getIdShort()) .sematicVersion(sematicId) - .title(shellDescriptorResponse.getIdShort()) + .title(shellIdShort) .description(description) .build(); @@ -230,8 +248,22 @@ public List getEDCOffer(List assetId String joinStr = StringUtils.join(assetId.stream().map(QueryDataOfferRequest::getAssetId).toList(), "\",\""); String filterExpression = String.format(filterExpressionTemplate, joinStr); - return catalogResponseBuilder.queryOnDataOffers(queryDataOfferRequestKey.getLeft(), + + String connectorOfferUrl = queryDataOfferRequestKey.getLeft(); + if (connectorOfferUrl.contains("@")) { + String[] split = connectorOfferUrl.split("@"); + if (split.length > 1) { + connectorOfferUrl = split[0]; + } + } + + List queryOnDataOffers = catalogResponseBuilder.queryOnDataOffers(connectorOfferUrl, queryDataOfferRequestKey.getRight(), 0, 1000, filterExpression); + + return queryOnDataOffers.stream().map(obj-> { + obj.setConnectorOfferUrl(queryDataOfferRequestKey.getLeft()); + return obj; + }).toList(); } private String getSpecificKeyFromList(ShellDescriptorResponse shellDescriptorResponse, String key) { diff --git a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/BPDMEdcAssetUtility.java b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/BPDMEdcAssetUtility.java new file mode 100644 index 000000000..925180d82 --- /dev/null +++ b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/BPDMEdcAssetUtility.java @@ -0,0 +1,88 @@ +/******************************************************************************** + * Copyright (c) 2024 T-Systems International GmbH + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.sde.edc.util; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.tractusx.sde.common.utils.LogUtil; +import org.eclipse.tractusx.sde.edc.constants.EDCAssetConfigurableConstant; +import org.eclipse.tractusx.sde.edc.entities.request.contractdefinition.Criterion; +import org.eclipse.tractusx.sde.edc.model.response.QueryDataOfferModel; +import org.eclipse.tractusx.sde.portal.model.ConnectorInfo; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor +public class BPDMEdcAssetUtility { + + private final EDCAssetLookUp edcAssetLookUp; + + private final EDCAssetConfigurableConstant edcAssetConfigurableConstant; + + @Cacheable(value = "bpn-bpdm", key = "#bpnNumber") + public List getBpdmUrl(String bpnNumber) { + + ConnectorInfo confo =ConnectorInfo.builder().bpn(bpnNumber) + .connectorEndpoint(List.of(edcAssetConfigurableConstant.getBpdmProviderEdcDataspaceApi())) + .build(); + + return edcAssetLookUp.getEDCAssetsByType(List.of(confo), getFilterCriteria()); + } + + @CacheEvict(value = "bpn-bpdm", key = "#bpnNumber") + public void removeBpdmCache(String bpnNumber) { + log.info(LogUtil.encode("Cleared '" + bpnNumber + "' bpn-bpdm cache")); + } + + @CacheEvict(value = "bpn-bpdm", allEntries = true) + public void cleareBpdmAllCache() { + log.info("Cleared All bpn-pcfexchange cache"); + } + + private List getFilterCriteria() { + + List criterias = new ArrayList<>(); + + List edcBPDMSearchCriteriaList = edcAssetConfigurableConstant.getEdcBPDMSearchCriteria(); + for (String edcBPDMSearchCriteria : edcBPDMSearchCriteriaList) { + if (StringUtils.isNotBlank(edcBPDMSearchCriteria)) { + String[] split1 = edcBPDMSearchCriteria.split("@"); + if (split1.length == 2) { + criterias.add(Criterion.builder() + .operandLeft(split1[0]) + .operator("=") + .operandRight(split1[1]) + .build()); + } + } + } + return criterias; + } + +} diff --git a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/DDTRUrlCacheUtility.java b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/DDTRUrlCacheUtility.java index 5c79f557a..e74fc8ba1 100644 --- a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/DDTRUrlCacheUtility.java +++ b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/DDTRUrlCacheUtility.java @@ -23,6 +23,7 @@ import java.util.List; import org.eclipse.tractusx.sde.edc.constants.EDCAssetConfigurableConstant; +import org.eclipse.tractusx.sde.edc.entities.request.contractdefinition.Criterion; import org.eclipse.tractusx.sde.edc.model.response.QueryDataOfferModel; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; @@ -42,7 +43,7 @@ public class DDTRUrlCacheUtility { @Cacheable(value = "bpn-ddtr", key = "#bpnNumber") public List getDDTRUrl(String bpnNumber) { - return edcAssetLookUp.getEDCAssetsByType(bpnNumber, edcAssetConfigurableConstant.getAssetPropTypeDigitalTwin()); + return edcAssetLookUp.getEDCAssetsByType(bpnNumber, getFilterCriteria()); } @CacheEvict(value = "bpn-ddtr", key = "#bpnNumber") @@ -54,4 +55,14 @@ public void removeDDTRUrlCache(String bpnNumber) { public void cleareDDTRUrlAllCache() { log.info("Cleared All bpn-ddtr cache"); } + + private List getFilterCriteria() { + + return List.of( + Criterion.builder() + .operandLeft("'http://purl.org/dc/terms/type'.'@id'") + .operator("=") + .operandRight("https://w3id.org/catenax/taxonomy#" + edcAssetConfigurableConstant.getAssetPropTypeDigitalTwin()) + .build()); + } } \ No newline at end of file diff --git a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/EDCAssetLookUp.java b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/EDCAssetLookUp.java index 67e805d33..5a80cc87b 100644 --- a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/EDCAssetLookUp.java +++ b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/EDCAssetLookUp.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; +import org.eclipse.tractusx.sde.edc.entities.request.contractdefinition.Criterion; import org.eclipse.tractusx.sde.edc.model.response.QueryDataOfferModel; import org.eclipse.tractusx.sde.edc.services.CatalogResponseBuilder; import org.eclipse.tractusx.sde.portal.handler.PortalProxyService; @@ -29,6 +30,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import com.google.gson.Gson; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -44,49 +47,51 @@ public class EDCAssetLookUp { private String consumerHost; private String filterExpressionTemplate = """ - "filterExpression": [{ - "operandLeft": "'http://purl.org/dc/terms/type'.'@id'", - "operator": "=", - "operandRight": "https://w3id.org/catenax/taxonomy#%s" - }]"""; + "filterExpression": %s"""; - public List getEDCAssetsByType(String bpnNumber, String assetType) { + public List getEDCAssetsByType(String bpnNumber, List filtercriteria) { List connectorInfos = portalProxyService.fetchConnectorInfo(List.of(bpnNumber)); - List distinctList = connectorInfos.stream().distinct().toList(); + return getEDCAssetsByType(distinctList, filtercriteria); - List offers = new ArrayList<>(); + } + + public List getEDCAssetsByType(List distinctList, + List filterCriteria) { - String filterExpression = String.format(filterExpressionTemplate, assetType); + List offers = new ArrayList<>(); + + Gson gson = new Gson(); + String filterCriteriaList = gson.toJson(filterCriteria); + String filterExpression = String.format(filterExpressionTemplate, filterCriteriaList); distinctList.stream().forEach( connectorInfo -> connectorInfo.getConnectorEndpoint().parallelStream().distinct().forEach(connector -> { try { if (!connector.contains(consumerHost)) { - + List queryDataOfferModel = catalogResponseBuilder - .queryOnDataOffers(connector, bpnNumber, 0, 100, filterExpression); + .queryOnDataOffers(connector, connectorInfo.getBpn(), 0, 100, filterExpression); - log.info("For Connector " + connector + ", found " + assetType + " assets :" + log.info("For Connector " + connector + ", found " + filterCriteria.toString() + " assets :" + queryDataOfferModel.size()); queryDataOfferModel.forEach(each -> each.setConnectorOfferUrl(connector)); offers.addAll(queryDataOfferModel); - + } else { log.warn("The Consumer and Provider Connector are same so ignoring it for lookup " - + assetType + " in to " + connector); + + filterCriteria.toString() + " in to " + connector); } } catch (Exception e) { - log.error("Error while looking EDC catalog for " + assetType + ", " + connector + log.error("Error while looking EDC catalog for " + filterCriteria.toString() + ", " + connector + ", Exception :" + e.getMessage()); } })); return offers; } - } \ No newline at end of file diff --git a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/EDCAssetUrlCacheService.java b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/EDCAssetUrlCacheService.java index e0e44b4a2..c4f086599 100644 --- a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/EDCAssetUrlCacheService.java +++ b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/EDCAssetUrlCacheService.java @@ -24,7 +24,9 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.commons.lang3.StringUtils; import org.eclipse.tractusx.sde.common.exception.ServiceException; +import org.eclipse.tractusx.sde.edc.constants.EDCAssetConfigurableConstant; import org.eclipse.tractusx.sde.edc.entities.request.policies.ActionRequest; import org.eclipse.tractusx.sde.edc.entities.request.policies.PolicyConstraintBuilderService; import org.eclipse.tractusx.sde.edc.model.edr.EDRCachedByIdResponse; @@ -47,12 +49,16 @@ public class EDCAssetUrlCacheService { private static final Map dDTRmap = new ConcurrentHashMap<>(); private static final Map pcfExchangeURLMap = new ConcurrentHashMap<>(); + private static final Map bpdmMap = new ConcurrentHashMap<>(); private final ContractNegotiationService contractNegotiationService; private final PolicyConstraintBuilderService policyConstraintBuilderService; private final DDTRUrlCacheUtility dDTRUrlCacheUtility; private final PCFExchangeAssetUtils pcfExchangeAssetUtils; + private final BPDMEdcAssetUtility bpdmEdcAssetUtility; + + private final EDCAssetConfigurableConstant edcAssetConfigurableConstant; @SneakyThrows public EDRCachedByIdResponse verifyAndGetToken(String bpnNumber, QueryDataOfferModel queryDataOfferModel) { @@ -70,7 +76,7 @@ public EDRCachedByIdResponse verifyAndGetToken(String bpnNumber, QueryDataOfferM EDRCachedResponse eDRCachedResponse = contractNegotiationService.verifyOrCreateContractNegotiation( bpnNumber, Map.of(), queryDataOfferModel.getConnectorOfferUrl(), action, offer); - if (eDRCachedResponse == null) { + if (eDRCachedResponse == null || StringUtils.isBlank(eDRCachedResponse.getTransferProcessId())) { throw new ServiceException("Time out!! to get EDC EDR status to lookup '" + queryDataOfferModel.getConnectorOfferUrl() + ", " + queryDataOfferModel.getAssetId() + "', The current status is null"); @@ -90,6 +96,7 @@ public EDRCachedByIdResponse verifyAndGetToken(String bpnNumber, QueryDataOfferM return null; } + // dDTR public List getDDTRUrl(String bpnNumber) { LocalDateTime cacheExpTime = dDTRmap.get(bpnNumber); @@ -120,6 +127,7 @@ public void removeDDTRUrlCache(String bpnNumber) { dDTRmap.remove(bpnNumber); } + // PCF public List getPCFExchangeUrlFromTwin(String bpnNumber) { LocalDateTime cacheExpTime = pcfExchangeURLMap.get(bpnNumber); @@ -149,4 +157,35 @@ public void removePCFExchangeCache(String bpnNumber) { pcfExchangeAssetUtils.removePCFExchangeCache(bpnNumber); pcfExchangeURLMap.remove(bpnNumber); } + + //BPDM + public List getBpdmUrl() { + + LocalDateTime cacheExpTime = bpdmMap.get(edcAssetConfigurableConstant.getBpdmProviderBpnl()); + LocalDateTime currDate = LocalDateTime.now(); + + if (cacheExpTime == null) + cacheExpTime = currDate.plusHours(12); + else if (currDate.isAfter(cacheExpTime)) { + bpdmEdcAssetUtility.removeBpdmCache(edcAssetConfigurableConstant.getBpdmProviderBpnl()); + cacheExpTime = currDate.plusHours(12); + } + bpdmMap.put(edcAssetConfigurableConstant.getBpdmProviderBpnl(), cacheExpTime); + List bpdmUrls = bpdmEdcAssetUtility.getBpdmUrl(edcAssetConfigurableConstant.getBpdmProviderBpnl()); + if (bpdmUrls.isEmpty()) { + log.info("Found connector list empty so removing existing cache and retry to fetch"); + removeBpdmCache(); + } + return bpdmUrls; + } + + public void clearBpdmUrlCache() { + bpdmMap.clear(); + bpdmEdcAssetUtility.cleareBpdmAllCache(); + } + + public void removeBpdmCache() { + bpdmEdcAssetUtility.removeBpdmCache(edcAssetConfigurableConstant.getBpdmProviderBpnl()); + bpdmMap.remove(edcAssetConfigurableConstant.getBpdmProviderBpnl()); + } } \ No newline at end of file diff --git a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/PCFExchangeAssetUtils.java b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/PCFExchangeAssetUtils.java index bfd001438..93dd1eb81 100644 --- a/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/PCFExchangeAssetUtils.java +++ b/modules/sde-external-services/edc/src/main/java/org/eclipse/tractusx/sde/edc/util/PCFExchangeAssetUtils.java @@ -23,6 +23,7 @@ import org.eclipse.tractusx.sde.common.utils.LogUtil; import org.eclipse.tractusx.sde.edc.constants.EDCAssetConfigurableConstant; +import org.eclipse.tractusx.sde.edc.entities.request.contractdefinition.Criterion; import org.eclipse.tractusx.sde.edc.model.response.QueryDataOfferModel; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; @@ -42,7 +43,7 @@ public class PCFExchangeAssetUtils { @Cacheable(value = "bpn-pcfexchange", key = "#bpnNumber") public List getPCFExchangeUrl(String bpnNumber) { - return edcAssetLookUp.getEDCAssetsByType(bpnNumber, edcAssetConfigurableConstant.getAssetPropTypePCFExchangeType()); + return edcAssetLookUp.getEDCAssetsByType(bpnNumber, getFilterCriteria()); } @CacheEvict(value = "bpn-pcfexchange", key = "#bpnNumber") @@ -54,5 +55,14 @@ public void removePCFExchangeCache(String bpnNumber) { public void clearePCFExchangeAllCache() { log.info("Cleared All bpn-pcfexchange cache"); } + + private List getFilterCriteria() { + return List.of( + Criterion.builder() + .operandLeft("'http://purl.org/dc/terms/type'.'@id'") + .operator("=") + .operandRight("https://w3id.org/catenax/taxonomy#"+edcAssetConfigurableConstant.getAssetPropTypePCFExchangeType()) + .build()); + } } diff --git a/modules/sde-external-services/portal/src/main/java/org/eclipse/tractusx/sde/portal/api/IPartnerPoolExternalServiceApi.java b/modules/sde-external-services/portal/src/main/java/org/eclipse/tractusx/sde/portal/api/IPartnerPoolExternalServiceApi.java index d9ca4cdfe..0686db574 100644 --- a/modules/sde-external-services/portal/src/main/java/org/eclipse/tractusx/sde/portal/api/IPartnerPoolExternalServiceApi.java +++ b/modules/sde-external-services/portal/src/main/java/org/eclipse/tractusx/sde/portal/api/IPartnerPoolExternalServiceApi.java @@ -19,16 +19,19 @@ ********************************************************************************/ package org.eclipse.tractusx.sde.portal.api; +import java.util.Map; + import org.eclipse.tractusx.sde.portal.model.LegalEntityData; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestParam; -@FeignClient(value = "IPartnerPoolExternalServiceApi", url = "${partner.pool.hostname}" , configuration = PartnerPoolExternalServiceApiConfiguration.class) +@FeignClient(value = "IPartnerPoolExternalServiceApi", url = "${bpdm.provider.edc.public.api}") public interface IPartnerPoolExternalServiceApi { @GetMapping(path = "/legal-entities") - LegalEntityData fetchLegalEntityData(@RequestParam String legalName, @RequestParam Integer page, @RequestParam Integer size); + LegalEntityData fetchLegalEntityData(@RequestParam String bpnLs, @RequestParam String legalName, @RequestParam Integer page, @RequestParam Integer size,@RequestHeader Map header); } \ No newline at end of file diff --git a/modules/sde-external-services/portal/src/main/java/org/eclipse/tractusx/sde/portal/handler/PortalProxyService.java b/modules/sde-external-services/portal/src/main/java/org/eclipse/tractusx/sde/portal/handler/PortalProxyService.java index d59d2ce73..293e869bd 100644 --- a/modules/sde-external-services/portal/src/main/java/org/eclipse/tractusx/sde/portal/handler/PortalProxyService.java +++ b/modules/sde-external-services/portal/src/main/java/org/eclipse/tractusx/sde/portal/handler/PortalProxyService.java @@ -1,6 +1,6 @@ /******************************************************************************** - * Copyright (c) 2023 T-Systems International GmbH - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023,2024 T-Systems International GmbH + * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -19,15 +19,10 @@ ********************************************************************************/ package org.eclipse.tractusx.sde.portal.handler; -import java.util.Collections; import java.util.List; -import java.util.Optional; -import org.eclipse.tractusx.sde.portal.api.IPartnerPoolExternalServiceApi; import org.eclipse.tractusx.sde.portal.api.IPortalExternalServiceApi; import org.eclipse.tractusx.sde.portal.model.ConnectorInfo; -import org.eclipse.tractusx.sde.portal.model.LegalEntityData; -import org.eclipse.tractusx.sde.portal.model.response.LegalEntityResponse; import org.eclipse.tractusx.sde.portal.model.response.UnifiedBPNValidationStatusEnum; import org.eclipse.tractusx.sde.portal.model.response.UnifiedBpnValidationResponse; import org.eclipse.tractusx.sde.portal.utils.MemberCompanyBPNCacheUtilityService; @@ -44,21 +39,6 @@ public class PortalProxyService { private final IPortalExternalServiceApi portalExternalServiceApi; - private final IPartnerPoolExternalServiceApi partnerPoolExternalServiceApi; - - @SneakyThrows - public List fetchLegalEntitiesData(String searchText, Integer page, Integer size) { - LegalEntityData legalEntity = partnerPoolExternalServiceApi.fetchLegalEntityData(searchText, page, size); - return Optional - .ofNullable(legalEntity.getContent() - .stream() - .map(companyData -> LegalEntityResponse.builder() - .bpn(companyData.getBpnl()).name(companyData.getLegalName()).build()) - .toList()) - .orElse(Collections.emptyList()); - - } - @SneakyThrows public List fetchConnectorInfo(List bpns) { return portalExternalServiceApi.fetchConnectorInfo(bpns); From 7cf42997f564c6835bb21b21e3521400734eec38 Mon Sep 17 00:00:00 2001 From: ChetanT-System Date: Thu, 23 May 2024 16:38:26 +0530 Subject: [PATCH 2/4] - Change log file updated --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a984fe798..00449fbc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added - Correction in semanticId changes in pcf. - EDC code changes refactor. +- PCF exchange code changes refactor. +- New changes for BPDM service api access/call using EDC. ### Fixed - Fix for PCF data sovereignty test. From fbbf0f3cc6647c264b88ff14f74d128da1e27961 Mon Sep 17 00:00:00 2001 From: ChetanT-System Date: Fri, 24 May 2024 11:41:30 +0530 Subject: [PATCH 3/4] - CodeQL issues fixed --- .../sde/pcfexchange/service/impl/ProxyRequestInterface.java | 4 ++-- .../tractusx/sde/core/service/PartnerPoolService.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/ProxyRequestInterface.java b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/ProxyRequestInterface.java index 68c43250e..daf9637ec 100644 --- a/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/ProxyRequestInterface.java +++ b/modules/pcf-exchange/src/main/java/org/eclipse/tractusx/sde/pcfexchange/service/impl/ProxyRequestInterface.java @@ -100,10 +100,10 @@ public void requestToProviderForPCFValue(String productId, StringBuilder reponse reponseMap.append(errorMsg); } } catch (FeignException e) { - log.error("FeignRequest requestToProviderForPCFValue:" + e.request()); + log.error(LogUtil.encode("FeignRequest requestToProviderForPCFValue:" + e.request())); String error= StringUtils.isBlank(e.contentUTF8()) ? e.getMessage() : e.contentUTF8(); String errorMsg= "Unable to request to provider '"+ dataset.getConnectorOfferUrl()+"' for '"+productId+"' product PCF value beacuse error in remote service execution"; - log.error("FeignException requestToProviderForPCFValue: " + errorMsg + ", because: " +error); + log.error(LogUtil.encode("FeignException requestToProviderForPCFValue: " + errorMsg + ", because: " +error)); reponseMap.append(errorMsg); } } diff --git a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/service/PartnerPoolService.java b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/service/PartnerPoolService.java index f1aad3dab..1b76411ac 100644 --- a/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/service/PartnerPoolService.java +++ b/modules/sde-core/src/main/java/org/eclipse/tractusx/sde/core/service/PartnerPoolService.java @@ -28,6 +28,7 @@ import java.util.Optional; import org.apache.commons.lang3.StringUtils; +import org.eclipse.tractusx.sde.common.utils.LogUtil; import org.eclipse.tractusx.sde.edc.constants.EDCAssetConfigurableConstant; import org.eclipse.tractusx.sde.edc.model.edr.EDRCachedByIdResponse; import org.eclipse.tractusx.sde.edc.model.response.QueryDataOfferModel; @@ -99,11 +100,11 @@ private LegalEntityData fetchLegalEntityDataByEdrToken(String bpnLs, String lega err = StringUtils.isBlank(err) ? e.getMessage() : err; String errorMsg = "Unable to fetch LegalEntity Data for " + legalName + "Or BpnLs " + bpnLs + " because: " + err; - log.error("FeignException : " + errorMsg); + log.error(LogUtil.encode("FeignException : " + errorMsg)); } catch (Exception e) { String errorMsg = "Unable to fetch LegalEntity Data for " + legalName + "Or BpnLs " + bpnLs + "because: " + e.getMessage(); - log.error("Exception : " + errorMsg); + log.error(LogUtil.encode("Exception : " + errorMsg)); } return legalEntityData; } From 8ed79d0c057434721814085e853f9aa33315a463 Mon Sep 17 00:00:00 2001 From: ChetanT-System Date: Fri, 24 May 2024 13:59:24 +0530 Subject: [PATCH 4/4] - Copyright headers updated --- .../tractusx/sde/controllers/PortalProxyControllerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/sde-core/src/test/java/org/eclipse/tractusx/sde/controllers/PortalProxyControllerTest.java b/modules/sde-core/src/test/java/org/eclipse/tractusx/sde/controllers/PortalProxyControllerTest.java index 1bb7137c8..1ab51ab6f 100644 --- a/modules/sde-core/src/test/java/org/eclipse/tractusx/sde/controllers/PortalProxyControllerTest.java +++ b/modules/sde-core/src/test/java/org/eclipse/tractusx/sde/controllers/PortalProxyControllerTest.java @@ -1,6 +1,6 @@ /******************************************************************************** - * Copyright (c) 2022, 2023 T-Systems International GmbH - * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022,2024 T-Systems International GmbH + * Copyright (c) 2022,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership.