diff --git a/basyx.aasregistry/basyx.aasregistry-feature-discovery-integration/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/discovery/integration/DiscoveryIntegrationAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-discovery-integration/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/discovery/integration/DiscoveryIntegrationAasRegistry.java index 41a11b14c..926276987 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-discovery-integration/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/discovery/integration/DiscoveryIntegrationAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-discovery-integration/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/discovery/integration/DiscoveryIntegrationAasRegistry.java @@ -26,7 +26,6 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.discovery.integration; -import jakarta.validation.Valid; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; @@ -42,7 +41,6 @@ import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; -import java.util.Base64; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -74,21 +72,14 @@ public void insertAasDescriptor(AssetAdministrationShellDescriptor descr) throws AasDescriptorAlreadyExistsException { decorated.insertAasDescriptor(descr); - List ids = descr.getSpecificAssetIds(); - if (ids == null || ids.isEmpty()) { - log.debug("No specificAssetIds present for AAS '{}', skipping discovery integration", descr.getId()); + List allAssetIds = collectAllAssetIds(descr); + + if (allAssetIds.isEmpty()) { + log.debug("No specificAssetIds or globalAssetId present for AAS '{}', skipping discovery integration", descr.getId()); return; } - List specificAssetIds = ids.stream() - .map(rId -> { - SpecificAssetId assetId = new DefaultSpecificAssetId(); - assetId.setName(rId.getName()); - assetId.setValue(rId.getValue()); - return assetId; - }).collect(Collectors.toList()); - - discoveryApi.createAllAssetLinksById(descr.getId(), specificAssetIds); + discoveryApi.createAllAssetLinksById(descr.getId(), allAssetIds); } @Override @@ -97,25 +88,11 @@ public void replaceAasDescriptor(@NonNull String aasDescriptorId, throws AasDescriptorNotFoundException { decorated.replaceAasDescriptor(aasDescriptorId, descriptor); - List ids = descriptor.getSpecificAssetIds(); - - if (ids == null || ids.isEmpty()) { - log.debug("No specificAssetIds present for AAS '{}', skipping discovery integration update", aasDescriptorId); - discoveryApi.deleteAllAssetLinksById(aasDescriptorId); - return; - } - - List specificAssetIds = ids.stream() - .map(rId -> { - SpecificAssetId assetId = new DefaultSpecificAssetId(); - assetId.setName(rId.getName()); - assetId.setValue(rId.getValue()); - return assetId; - }) - .collect(Collectors.toList()); + List allAssetIds = collectAllAssetIds(descriptor); discoveryApi.deleteAllAssetLinksById(aasDescriptorId); - discoveryApi.createAllAssetLinksById(aasDescriptorId, specificAssetIds); + + discoveryApi.createAllAssetLinksById(aasDescriptorId, allAssetIds); } @Override @@ -158,4 +135,41 @@ public Set clear() { public ShellDescriptorSearchResponse searchAasDescriptors(@NonNull ShellDescriptorSearchRequest request) { return decorated.searchAasDescriptors(request); } + + /** + * Collects all asset IDs from the descriptor, including both specificAssetIds and globalAssetId. + * The globalAssetId is converted to a SpecificAssetId with name "globalAssetId". + * + * @param descriptor the AssetAdministrationShellDescriptor + * @return a list of all asset IDs + */ + private List collectAllAssetIds(AssetAdministrationShellDescriptor descriptor) { + List allAssetIds = new java.util.ArrayList<>(); + + // Add specificAssetIds + List ids = descriptor.getSpecificAssetIds(); + if (ids != null && !ids.isEmpty()) { + List specificAssetIds = ids.stream() + .map(rId -> { + SpecificAssetId assetId = new DefaultSpecificAssetId(); + assetId.setName(rId.getName()); + assetId.setValue(rId.getValue()); + return assetId; + }) + .collect(Collectors.toList()); + allAssetIds.addAll(specificAssetIds); + } + + // Add globalAssetId if present + String globalAssetId = descriptor.getGlobalAssetId(); + if (globalAssetId != null && !globalAssetId.isEmpty()) { + SpecificAssetId globalAssetIdEntry = new DefaultSpecificAssetId(); + globalAssetIdEntry.setName("globalAssetId"); + globalAssetIdEntry.setValue(globalAssetId); + allAssetIds.add(globalAssetIdEntry); + log.debug("Added globalAssetId '{}' to discovery service for AAS '{}'", globalAssetId, descriptor.getId()); + } + + return allAssetIds; + } } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-discovery-integration/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/discovery/integration/DiscoveryIntegrationAasRegistryTest.java b/basyx.aasregistry/basyx.aasregistry-feature-discovery-integration/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/discovery/integration/DiscoveryIntegrationAasRegistryTest.java index 80dc5885c..5e84a0068 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-discovery-integration/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/discovery/integration/DiscoveryIntegrationAasRegistryTest.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-discovery-integration/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/discovery/integration/DiscoveryIntegrationAasRegistryTest.java @@ -232,4 +232,106 @@ private SubmodelDescriptor createTestSubmodelDescriptor(String id) { submodel.setAdministration(new AdministrativeInformation()); return submodel; } + + @Test + void insertAasDescriptorWithGlobalAssetIdShouldPropagateToDiscovery() throws Exception { + log.info("Started unit test - insertAasDescriptorWithGlobalAssetIdShouldPropagateToDiscovery()"); + AssetAdministrationShellDescriptor descriptor = createTestDescriptor(AAS_DESCRIPTOR_ID); + descriptor.setGlobalAssetId("https://example.com/global-asset-123"); + descriptor.setSpecificAssetIds(createRegistrySpecificAssetIds()); + + registry.insertAasDescriptor(descriptor); + + verify(decoratedStorage).insertAasDescriptor(descriptor); + + ArgumentCaptor idCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor> assetIdsCaptor = ArgumentCaptor.forClass(List.class); + verify(discoveryService).createAllAssetLinksById(idCaptor.capture(), assetIdsCaptor.capture()); + + assertEquals(AAS_DESCRIPTOR_ID, idCaptor.getValue()); + assertEquals(3, assetIdsCaptor.getValue().size()); // 2 specificAssetIds + 1 globalAssetId + + // Verify globalAssetId was added + boolean hasGlobalAssetId = assetIdsCaptor.getValue().stream() + .anyMatch(id -> "globalAssetId".equals(id.getName()) && + "https://example.com/global-asset-123".equals(id.getValue())); + assertTrue(hasGlobalAssetId, "globalAssetId should be present in the asset IDs sent to discovery service"); + log.info("Successfully conducted unit test"); + } + + @Test + void insertAasDescriptorWithOnlyGlobalAssetIdShouldPropagateToDiscovery() throws Exception { + log.info("Started unit test - insertAasDescriptorWithOnlyGlobalAssetIdShouldPropagateToDiscovery()"); + AssetAdministrationShellDescriptor descriptor = createTestDescriptor(AAS_DESCRIPTOR_ID); + descriptor.setGlobalAssetId("https://example.com/global-asset-456"); + descriptor.setSpecificAssetIds(Collections.emptyList()); + + registry.insertAasDescriptor(descriptor); + + verify(decoratedStorage).insertAasDescriptor(descriptor); + + ArgumentCaptor idCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor> assetIdsCaptor = ArgumentCaptor.forClass(List.class); + verify(discoveryService).createAllAssetLinksById(idCaptor.capture(), assetIdsCaptor.capture()); + + assertEquals(AAS_DESCRIPTOR_ID, idCaptor.getValue()); + assertEquals(1, assetIdsCaptor.getValue().size()); // Only globalAssetId + + // Verify globalAssetId was added + SpecificAssetId capturedId = assetIdsCaptor.getValue().get(0); + assertEquals("globalAssetId", capturedId.getName()); + assertEquals("https://example.com/global-asset-456", capturedId.getValue()); + log.info("Successfully conducted unit test"); + } + + @Test + void replaceAasDescriptorWithGlobalAssetIdShouldPropagateToDiscovery() throws Exception { + log.info("Started unit test - replaceAasDescriptorWithGlobalAssetIdShouldPropagateToDiscovery()"); + AssetAdministrationShellDescriptor descriptor = createTestDescriptor(AAS_DESCRIPTOR_ID); + descriptor.setGlobalAssetId("https://example.com/global-asset-789"); + descriptor.setSpecificAssetIds(createRegistrySpecificAssetIds()); + + registry.replaceAasDescriptor(AAS_DESCRIPTOR_ID, descriptor); + + InOrder inOrder = inOrder(discoveryService); + verify(decoratedStorage).replaceAasDescriptor(AAS_DESCRIPTOR_ID, descriptor); + inOrder.verify(discoveryService).deleteAllAssetLinksById(AAS_DESCRIPTOR_ID); + + ArgumentCaptor> assetIdsCaptor = ArgumentCaptor.forClass(List.class); + inOrder.verify(discoveryService).createAllAssetLinksById(eq(AAS_DESCRIPTOR_ID), assetIdsCaptor.capture()); + + assertEquals(3, assetIdsCaptor.getValue().size()); // 2 specificAssetIds + 1 globalAssetId + + // Verify globalAssetId was added + boolean hasGlobalAssetId = assetIdsCaptor.getValue().stream() + .anyMatch(id -> "globalAssetId".equals(id.getName()) && + "https://example.com/global-asset-789".equals(id.getValue())); + assertTrue(hasGlobalAssetId, "globalAssetId should be present in the asset IDs sent to discovery service"); + + inOrder.verifyNoMoreInteractions(); + log.info("Successfully conducted unit test"); + } + + @Test + void insertAasDescriptorWithoutGlobalAssetIdShouldStillWork() throws Exception { + log.info("Started unit test - insertAasDescriptorWithoutGlobalAssetIdShouldStillWork()"); + AssetAdministrationShellDescriptor descriptor = createTestDescriptor(AAS_DESCRIPTOR_ID); + descriptor.setSpecificAssetIds(createRegistrySpecificAssetIds()); + // No globalAssetId set + + registry.insertAasDescriptor(descriptor); + + verify(decoratedStorage).insertAasDescriptor(descriptor); + + ArgumentCaptor> assetIdsCaptor = ArgumentCaptor.forClass(List.class); + verify(discoveryService).createAllAssetLinksById(eq(AAS_DESCRIPTOR_ID), assetIdsCaptor.capture()); + + assertEquals(2, assetIdsCaptor.getValue().size()); // Only 2 specificAssetIds + + // Verify no globalAssetId was added + boolean hasGlobalAssetId = assetIdsCaptor.getValue().stream() + .anyMatch(id -> "globalAssetId".equals(id.getName())); + assertFalse(hasGlobalAssetId, "globalAssetId should not be present when not set in descriptor"); + log.info("Successfully conducted unit test"); + } } \ No newline at end of file