diff --git a/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/facilitator/DigitalTwinsFacilitator.java b/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/facilitator/DigitalTwinsFacilitator.java index 09fbe627c..1c239f74f 100644 --- a/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/facilitator/DigitalTwinsFacilitator.java +++ b/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/facilitator/DigitalTwinsFacilitator.java @@ -54,7 +54,7 @@ public class DigitalTwinsFacilitator { @Value(value = "${digital-twins.api:/api/v3.0}") private String dtApiUri; - + @Value(value = "${manufacturerId}") public String manufacturerId; @@ -63,7 +63,8 @@ public List shellLookup(ShellLookupRequest request) throws ServiceExcept } @SneakyThrows - public List shellLookupFromDDTR(ShellLookupRequest request, String ddtrUrl, String edcBPN) throws ServiceException { + public List shellLookupFromDDTR(ShellLookupRequest request, String ddtrUrl, String edcBPN) + throws ServiceException { URI dtURL = (ddtrUrl == null || ddtrUrl.length() <= 0) ? getDtURL(digitalTwinsHost) : getDtURL(ddtrUrl); @@ -145,6 +146,18 @@ public ShellDescriptorResponse createShellDescriptor(ShellDescriptorRequest requ return responseBody; } + public void updateShellSpecificAssetIdentifiers(String shellId, List specificAssetIds) { + + digitalTwinsFeignClient.deleteShellSpecificAttributes(getDtURL(digitalTwinsHost), + encodeShellIdBase64Utf8(shellId), manufacturerId); + + ResponseEntity> registerSubmodel = digitalTwinsFeignClient.createShellSpecificAttributes( + getDtURL(digitalTwinsHost), encodeShellIdBase64Utf8(shellId), manufacturerId, specificAssetIds); + if (registerSubmodel.getStatusCode() != HttpStatus.CREATED) { + log.error("Error in shell SpecificAssetIdentifiers deletion: " + registerSubmodel.toString()); + } + } + public void createSubModel(String shellId, CreateSubModelRequest request) { request.setDescription(List.of()); 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 1b14d8459..d2cb2f7fb 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 @@ -23,6 +23,7 @@ import static org.eclipse.tractusx.sde.common.constants.CommonConstants.MANUFACTURER_PART_ID; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -124,16 +125,18 @@ public List prepareDtEndpoint(String shellId, String submodelIdentific } @SneakyThrows - private ArrayList getSpecificAssetIds(Map specificAssetIds, List bpns) { + public List getSpecificAssetIds(Map specificAssetIds, List bpns) { - ArrayList specificIdentifiers = new ArrayList<>(); + List specificIdentifiers = new ArrayList<>(); + + List keyList = bpnKeyRefrence(bpns); + specificAssetIds.entrySet().stream().forEach(entry -> { List list = publicReadableSpecificAssetIDs.get(entry.getKey()); ExternalSubjectId externalSubjectId = null; if (list != null && (list.contains("*") || list.contains(entry.getValue()))) { - externalSubjectId = ExternalSubjectId.builder() .type("ExternalReference") .keys(List.of(Keys.builder().type("GlobalReference").value(PUBLIC_READABLE).build())) @@ -141,14 +144,13 @@ private ArrayList getSpecificAssetIds(Map specificAssetI specificIdentifiers.add(new KeyValuePair(entry.getKey(), entry.getValue(), externalSubjectId)); } else { - if (bpns!=null && !bpns.isEmpty()) { - for (String bpn : bpns) { - externalSubjectId = ExternalSubjectId.builder() - .type("ExternalReference") - .keys(List.of(Keys.builder().type("GlobalReference").value(bpn).build())) - .build(); - specificIdentifiers.add(new KeyValuePair(entry.getKey(), entry.getValue(), externalSubjectId)); - } + if (keyList != null && !keyList.isEmpty()) { + + externalSubjectId = ExternalSubjectId.builder() + .type("ExternalReference").keys(keyList) + .build(); + specificIdentifiers.add(new KeyValuePair(entry.getKey(), entry.getValue(), externalSubjectId)); + } else { Map map = new HashMap<>(); map.put("name", entry.getKey()); @@ -161,6 +163,15 @@ private ArrayList getSpecificAssetIds(Map specificAssetI return specificIdentifiers; } + private List bpnKeyRefrence(List bpns) { + if (bpns != null && !(bpns.size() == 1 && bpns.contains(manufacturerId))) { + return bpns.stream() + .map(bpn -> Keys.builder().type("GlobalReference").value(bpn).build()) + .toList(); + } + return Collections.emptyList(); + } + private String encodedUrl(String format) { return format.replace(":", "%3A"); } diff --git a/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/gateways/external/DigitalTwinsFeignClient.java b/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/gateways/external/DigitalTwinsFeignClient.java index a2c5c9050..03891020c 100644 --- a/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/gateways/external/DigitalTwinsFeignClient.java +++ b/modules/sde-external-services/digital-twins/src/main/java/org/eclipse/tractusx/sde/digitaltwins/gateways/external/DigitalTwinsFeignClient.java @@ -21,11 +21,11 @@ package org.eclipse.tractusx.sde.digitaltwins.gateways.external; import java.net.URI; +import java.util.List; import org.eclipse.tractusx.sde.common.model.KeycloakJWTTokenResponse; import org.eclipse.tractusx.sde.digitaltwins.entities.request.CreateSubModelRequest; import org.eclipse.tractusx.sde.digitaltwins.entities.request.ShellDescriptorRequest; -import org.eclipse.tractusx.sde.digitaltwins.entities.request.ShellLookupQueryRequest; import org.eclipse.tractusx.sde.digitaltwins.entities.response.ShellDescriptorResponse; import org.eclipse.tractusx.sde.digitaltwins.entities.response.ShellLookupResponse; import org.eclipse.tractusx.sde.digitaltwins.entities.response.SubModelListResponse; @@ -46,33 +46,40 @@ public interface DigitalTwinsFeignClient { @PostMapping KeycloakJWTTokenResponse readAuthToken(URI url, @RequestBody MultiValueMap body); - @DeleteMapping(path = "/shell-descriptors/{aasIdentifier}/submodel-descriptors/{submodelIdentifier}") - ResponseEntity deleteSubmodelfromShellById(URI url, @PathVariable("aasIdentifier") String shellId, - @PathVariable("submodelIdentifier") String submodelIdentifier); - @PostMapping(path = "/shell-descriptors") ResponseEntity createShellDescriptor(URI url, @RequestBody ShellDescriptorRequest request); + @GetMapping(path = "/shell-descriptors/{aasIdentifier}") ResponseEntity getShellDescriptorByShellId(URI url, @PathVariable("aasIdentifier") String shellId); + + @DeleteMapping(path = "/shell-descriptors/{aasIdentifier}") + ResponseEntity deleteShell(URI url, @PathVariable("assetIds") String shellId); @PostMapping(path = "/shell-descriptors/{aasIdentifier}/submodel-descriptors") ResponseEntity createSubModel(URI url, @PathVariable("aasIdentifier") String shellId, @RequestBody CreateSubModelRequest request); - + @GetMapping(path = "/shell-descriptors/{aasIdentifier}/submodel-descriptors") ResponseEntity getSubModels(URI digitalTwinsHost, @PathVariable("aasIdentifier") String shellId); + @DeleteMapping(path = "/shell-descriptors/{aasIdentifier}/submodel-descriptors/{submodelIdentifier}") + ResponseEntity deleteSubmodelfromShellById(URI url, @PathVariable("aasIdentifier") String shellId, + @PathVariable("submodelIdentifier") String submodelIdentifier); + @GetMapping(path = "/lookup/shells") ResponseEntity shellLookup(URI url, @RequestParam String assetIds, @RequestHeader("Edc-Bpn") String edcBpn); - - @DeleteMapping(path = "/lookup/shells/{assetIds}") - ResponseEntity deleteShell(URI url, @PathVariable("assetIds") String shellId); - @PostMapping(path = "/lookup/shells/query") - ResponseEntity shellLookupByQuery(URI url, @RequestBody ShellLookupQueryRequest request); + @PostMapping(path = "/lookup/shells/{assetIds}") + ResponseEntity> createShellSpecificAttributes(URI url, @PathVariable("assetIds") String shellId, + @RequestHeader("Edc-Bpn") String edcBpn, @RequestBody List specificAssetIds); + + @DeleteMapping(path = "/lookup/shells/{assetIds}") + ResponseEntity deleteShellSpecificAttributes(URI url, @PathVariable("assetIds") String shellId, + @RequestHeader("Edc-Bpn") String edcBpn); + } diff --git a/modules/sde-submodules/batch/src/main/java/org/eclipse/tractusx/sde/submodels/batch/steps/DigitalTwinsBatchCsvHandlerUseCase.java b/modules/sde-submodules/batch/src/main/java/org/eclipse/tractusx/sde/submodels/batch/steps/DigitalTwinsBatchCsvHandlerUseCase.java index c7b7de189..8e234b4a5 100644 --- a/modules/sde-submodules/batch/src/main/java/org/eclipse/tractusx/sde/submodels/batch/steps/DigitalTwinsBatchCsvHandlerUseCase.java +++ b/modules/sde-submodules/batch/src/main/java/org/eclipse/tractusx/sde/submodels/batch/steps/DigitalTwinsBatchCsvHandlerUseCase.java @@ -80,6 +80,10 @@ private Batch doRun(Batch batch) throws CsvHandlerDigitalTwinUseCaseException { } else if (shellIds.size() == 1) { logDebug(String.format("Shell id found for '%s'", shellLookupRequest.toJsonString())); shellId = shellIds.stream().findFirst().orElse(null); + + digitalTwinsFacilitator.updateShellSpecificAssetIdentifiers(shellId, + digitalTwinsUtility.getSpecificAssetIds(getSpecificAssetIds(batch), batch.getBpnNumbers())); + logDebug(String.format("Shell id '%s'", shellId)); } else { throw new CsvHandlerDigitalTwinUseCaseException( diff --git a/modules/sde-submodules/part-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/pap/steps/DigitalTwinsPartAsPlannedHandlerStep.java b/modules/sde-submodules/part-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/pap/steps/DigitalTwinsPartAsPlannedHandlerStep.java index 70dd331d8..8f34e4e9b 100644 --- a/modules/sde-submodules/part-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/pap/steps/DigitalTwinsPartAsPlannedHandlerStep.java +++ b/modules/sde-submodules/part-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/pap/steps/DigitalTwinsPartAsPlannedHandlerStep.java @@ -77,6 +77,10 @@ private PartAsPlanned doRun(PartAsPlanned partAsPlannedAspect) throws CsvHandler } else if (shellIds.size() == 1) { logDebug(String.format("Shell id found for '%s'", shellLookupRequest.toJsonString())); shellId = shellIds.stream().findFirst().orElse(null); + + digitalTwinsFacilitator.updateShellSpecificAssetIdentifiers(shellId, + digitalTwinsUtility.getSpecificAssetIds(getSpecificAssetIds(partAsPlannedAspect), partAsPlannedAspect.getBpnNumbers())); + logDebug(String.format("Shell id '%s'", shellId)); } else { throw new CsvHandlerDigitalTwinUseCaseException( diff --git a/modules/sde-submodules/part-site-information-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/psiap/steps/DigitalTwinsPartSiteInformationAsPlannedHandlerStep.java b/modules/sde-submodules/part-site-information-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/psiap/steps/DigitalTwinsPartSiteInformationAsPlannedHandlerStep.java index 2555513c1..ac6cbf64e 100644 --- a/modules/sde-submodules/part-site-information-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/psiap/steps/DigitalTwinsPartSiteInformationAsPlannedHandlerStep.java +++ b/modules/sde-submodules/part-site-information-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/psiap/steps/DigitalTwinsPartSiteInformationAsPlannedHandlerStep.java @@ -80,6 +80,11 @@ private PartSiteInformationAsPlanned doRun(PartSiteInformationAsPlanned partSite } else if (shellIds.size() == 1) { logDebug(String.format("Shell id found for '%s'", shellLookupRequest.toJsonString())); shellId = shellIds.stream().findFirst().orElse(null); + + digitalTwinsFacilitator.updateShellSpecificAssetIdentifiers(shellId, + digitalTwinsUtility.getSpecificAssetIds(getSpecificAssetIds(partSiteInformationAsPlannedAspect), + partSiteInformationAsPlannedAspect.getBpnNumbers())); + logDebug(String.format("Shell id '%s'", shellId)); } else { throw new CsvHandlerDigitalTwinUseCaseException( diff --git a/modules/sde-submodules/serial-part-typization/src/main/java/org/eclipse/tractusx/sde/submodels/spt/steps/DigitalTwinsAspectCsvHandlerUseCase.java b/modules/sde-submodules/serial-part-typization/src/main/java/org/eclipse/tractusx/sde/submodels/spt/steps/DigitalTwinsAspectCsvHandlerUseCase.java index 18ef9c5fa..be3984045 100644 --- a/modules/sde-submodules/serial-part-typization/src/main/java/org/eclipse/tractusx/sde/submodels/spt/steps/DigitalTwinsAspectCsvHandlerUseCase.java +++ b/modules/sde-submodules/serial-part-typization/src/main/java/org/eclipse/tractusx/sde/submodels/spt/steps/DigitalTwinsAspectCsvHandlerUseCase.java @@ -78,6 +78,8 @@ private Aspect doRun(Aspect aspect) throws CsvHandlerDigitalTwinUseCaseException } else if (shellIds.size() == 1) { logDebug(String.format("Shell id found for '%s'", shellLookupRequest.toJsonString())); shellId = shellIds.stream().findFirst().orElse(null); + digitalTwinsFacilitator.updateShellSpecificAssetIdentifiers(shellId, + digitalTwinsUtility.getSpecificAssetIds(getSpecificAssetIds(aspect), aspect.getBpnNumbers())); logDebug(String.format("Shell id '%s'", shellId)); } else { throw new CsvHandlerDigitalTwinUseCaseException( diff --git a/modules/sde-submodules/single-level-bom-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/slbap/steps/DigitalTwinsSingleLevelBoMAsPlannedHandlerStep.java b/modules/sde-submodules/single-level-bom-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/slbap/steps/DigitalTwinsSingleLevelBoMAsPlannedHandlerStep.java index cb382dbcc..2d2601f8a 100644 --- a/modules/sde-submodules/single-level-bom-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/slbap/steps/DigitalTwinsSingleLevelBoMAsPlannedHandlerStep.java +++ b/modules/sde-submodules/single-level-bom-as-planned/src/main/java/org/eclipse/tractusx/sde/submodels/slbap/steps/DigitalTwinsSingleLevelBoMAsPlannedHandlerStep.java @@ -80,6 +80,12 @@ private SingleLevelBoMAsPlanned doRun(SingleLevelBoMAsPlanned singleLevelBoMAsPl } else if (shellIds.size() == 1) { logDebug(String.format("Shell id found for '%s'", shellLookupRequest.toJsonString())); shellId = shellIds.stream().findFirst().orElse(null); + + digitalTwinsFacilitator.updateShellSpecificAssetIdentifiers(shellId, + digitalTwinsUtility.getSpecificAssetIds( + getSpecificAssetIdsForSingleLevel(singleLevelBoMAsPlannedAspect), + singleLevelBoMAsPlannedAspect.getBpnNumbers())); + logDebug(String.format("Shell id '%s'", shellId)); } else { throw new CsvHandlerDigitalTwinUseCaseException( @@ -145,14 +151,22 @@ private Map getSpecificAssetIds(PartAsPlanned partAsPlannedAspec } private ShellLookupRequest getShellLookupRequest(SingleLevelBoMAsPlanned singleLevelBoMAsPlannedAspect) { + ShellLookupRequest shellLookupRequest = new ShellLookupRequest(); - shellLookupRequest.addLocalIdentifier(CommonConstants.ASSET_LIFECYCLE_PHASE, CommonConstants.AS_PLANNED); - shellLookupRequest.addLocalIdentifier(CommonConstants.MANUFACTURER_PART_ID, - singleLevelBoMAsPlannedAspect.getParentManufacturerPartId()); - shellLookupRequest.addLocalIdentifier(CommonConstants.MANUFACTURER_ID, digitalTwinsUtility.getManufacturerId()); + getSpecificAssetIdsForSingleLevel(singleLevelBoMAsPlannedAspect).entrySet().stream() + .forEach(entry -> shellLookupRequest.addLocalIdentifier(entry.getKey(), entry.getValue())); return shellLookupRequest; } + + private Map getSpecificAssetIdsForSingleLevel(SingleLevelBoMAsPlanned singleLevelBoMAsPlannedAspect) { + Map specificIdentifiers = new HashMap<>(); + specificIdentifiers.put(CommonConstants.ASSET_LIFECYCLE_PHASE, CommonConstants.AS_PLANNED); + specificIdentifiers.put(CommonConstants.MANUFACTURER_PART_ID, + singleLevelBoMAsPlannedAspect.getParentManufacturerPartId()); + specificIdentifiers.put(CommonConstants.MANUFACTURER_ID, digitalTwinsUtility.getManufacturerId()); + return specificIdentifiers; + } private ShellDescriptorRequest getShellDescriptorRequest(PartAsPlanned partAsPlannedAspect) { diff --git a/modules/sde-submodules/single-level-usage-as-built/src/main/java/org/eclipse/tractusx/sde/submodels/sluab/steps/DigitalTwinsSingleLevelUsageAsBuiltCsvHandlerUseCase.java b/modules/sde-submodules/single-level-usage-as-built/src/main/java/org/eclipse/tractusx/sde/submodels/sluab/steps/DigitalTwinsSingleLevelUsageAsBuiltCsvHandlerUseCase.java index 6897de509..112bffbd9 100644 --- a/modules/sde-submodules/single-level-usage-as-built/src/main/java/org/eclipse/tractusx/sde/submodels/sluab/steps/DigitalTwinsSingleLevelUsageAsBuiltCsvHandlerUseCase.java +++ b/modules/sde-submodules/single-level-usage-as-built/src/main/java/org/eclipse/tractusx/sde/submodels/sluab/steps/DigitalTwinsSingleLevelUsageAsBuiltCsvHandlerUseCase.java @@ -80,6 +80,12 @@ private SingleLevelUsageAsBuilt doRun(SingleLevelUsageAsBuilt aspectSingleLevelU } else if (shellIds.size() == 1) { logDebug(String.format("Shell id found for '%s'", shellLookupRequest.toJsonString())); shellId = shellIds.stream().findFirst().orElse(null); + + digitalTwinsFacilitator.updateShellSpecificAssetIdentifiers(shellId, + digitalTwinsUtility.getSpecificAssetIds( + getSpecificAssetIdsForSingleLevel(aspectSingleLevelUsageAsBuilt), + aspectSingleLevelUsageAsBuilt.getBpnNumbers())); + logDebug(String.format("Shell id '%s'", shellId)); } else { throw new CsvHandlerDigitalTwinUseCaseException( @@ -143,18 +149,29 @@ private String createShellDescriptor(SingleLevelUsageAsBuilt aspectSingleLevelUs private ShellLookupRequest getShellLookupRequest(SingleLevelUsageAsBuilt aspectSingleLevelUsageAsBuilt) { ShellLookupRequest shellLookupRequest = new ShellLookupRequest(); - shellLookupRequest.addLocalIdentifier(CommonConstants.PART_INSTANCE_ID, + + getSpecificAssetIdsForSingleLevel(aspectSingleLevelUsageAsBuilt).entrySet().stream() + .forEach(entry -> shellLookupRequest.addLocalIdentifier(entry.getKey(), entry.getValue())); + + return shellLookupRequest; + } + + private Map getSpecificAssetIdsForSingleLevel( + SingleLevelUsageAsBuilt aspectSingleLevelUsageAsBuilt) { + + Map specificIdentifiers = new HashMap<>(); + + specificIdentifiers.put(CommonConstants.PART_INSTANCE_ID, aspectSingleLevelUsageAsBuilt.getParentPartInstanceId()); - shellLookupRequest.addLocalIdentifier(CommonConstants.MANUFACTURER_PART_ID, + specificIdentifiers.put(CommonConstants.MANUFACTURER_PART_ID, aspectSingleLevelUsageAsBuilt.getParentManufacturerPartId()); - shellLookupRequest.addLocalIdentifier(CommonConstants.MANUFACTURER_ID, digitalTwinsUtility.getManufacturerId()); + specificIdentifiers.put(CommonConstants.MANUFACTURER_ID, digitalTwinsUtility.getManufacturerId()); if (aspectSingleLevelUsageAsBuilt.hasOptionalParentIdentifier()) { - shellLookupRequest.addLocalIdentifier(aspectSingleLevelUsageAsBuilt.getParentOptionalIdentifierKey(), + specificIdentifiers.put(aspectSingleLevelUsageAsBuilt.getParentOptionalIdentifierKey(), aspectSingleLevelUsageAsBuilt.getParentOptionalIdentifierValue()); } - - return shellLookupRequest; + return specificIdentifiers; } private Map getSpecificAssetIds(Aspect aspect) {