Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -74,21 +72,14 @@ public void insertAasDescriptor(AssetAdministrationShellDescriptor descr)
throws AasDescriptorAlreadyExistsException {
decorated.insertAasDescriptor(descr);

List<org.eclipse.digitaltwin.basyx.aasregistry.model.SpecificAssetId> ids = descr.getSpecificAssetIds();
if (ids == null || ids.isEmpty()) {
log.debug("No specificAssetIds present for AAS '{}', skipping discovery integration", descr.getId());
List<SpecificAssetId> allAssetIds = collectAllAssetIds(descr);

if (allAssetIds.isEmpty()) {
log.debug("No specificAssetIds or globalAssetId present for AAS '{}', skipping discovery integration", descr.getId());
return;
}

List<SpecificAssetId> 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
Expand All @@ -97,25 +88,11 @@ public void replaceAasDescriptor(@NonNull String aasDescriptorId,
throws AasDescriptorNotFoundException {
decorated.replaceAasDescriptor(aasDescriptorId, descriptor);

List<org.eclipse.digitaltwin.basyx.aasregistry.model.SpecificAssetId> 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<SpecificAssetId> specificAssetIds = ids.stream()
.map(rId -> {
SpecificAssetId assetId = new DefaultSpecificAssetId();
assetId.setName(rId.getName());
assetId.setValue(rId.getValue());
return assetId;
})
.collect(Collectors.toList());
List<SpecificAssetId> allAssetIds = collectAllAssetIds(descriptor);

discoveryApi.deleteAllAssetLinksById(aasDescriptorId);
discoveryApi.createAllAssetLinksById(aasDescriptorId, specificAssetIds);

discoveryApi.createAllAssetLinksById(aasDescriptorId, allAssetIds);
}

@Override
Expand Down Expand Up @@ -158,4 +135,41 @@ public Set<String> 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<SpecificAssetId> collectAllAssetIds(AssetAdministrationShellDescriptor descriptor) {
List<SpecificAssetId> allAssetIds = new java.util.ArrayList<>();

// Add specificAssetIds
List<org.eclipse.digitaltwin.basyx.aasregistry.model.SpecificAssetId> ids = descriptor.getSpecificAssetIds();
if (ids != null && !ids.isEmpty()) {
List<SpecificAssetId> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> idCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<List<SpecificAssetId>> 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<String> idCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<List<SpecificAssetId>> 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<List<SpecificAssetId>> 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<List<SpecificAssetId>> 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");
}
}
Loading