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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,5 @@ local.properties
/.env

**.iml

.DS_Store
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.DeserializationException;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetAdministrationShell;
import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier;
import org.eclipse.digitaltwin.basyx.http.HttpBaSyxHeader;
import org.eclipse.digitaltwin.basyx.http.pagination.Base64UrlEncodedCursor;
Expand Down Expand Up @@ -192,6 +191,26 @@ public void getAllAasWithIdShort() throws IOException, ParseException {
BaSyxHttpTestUtils.assertSameJSONContent(getPaginatedAas1JSONString(), getJSONWithoutCursorInfo(actualJsonFromServer));
}

@Test
public void getAllAasWithMultipleDifferentGlobalAssetIds() throws IOException, ParseException {
createMultipleAasOnServer();
CloseableHttpResponse retrievalResponse = getAllAasMultipleDifferentGlobalAssetIdsParam();
assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode());

String actualJsonFromServer = BaSyxHttpTestUtils.getResponseAsString(retrievalResponse);
BaSyxHttpTestUtils.assertSameJSONContent(getEmptyResultJSONString(), getJSONWithoutCursorInfo(actualJsonFromServer));
}

@Test
public void getAllAasWithMultipleIdenticalGlobalAssetIds() throws IOException, ParseException {
createMultipleAasOnServer();
CloseableHttpResponse retrievalResponse = getAllAasMultipleIdenticalGlobalAssetIdsParam();
assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode());

String actualJsonFromServer = BaSyxHttpTestUtils.getResponseAsString(retrievalResponse);
BaSyxHttpTestUtils.assertSameJSONContent(getPaginatedAas1JSONString(), getJSONWithoutCursorInfo(actualJsonFromServer));
}

@Test
public void deleteAas() throws IOException {
createDummyAasOnServer(getAas1JSONString());
Expand Down Expand Up @@ -423,6 +442,10 @@ public void deleteNonExistingThumbnail() throws FileNotFoundException, Unsupport
private String getPaginatedAas1JSONString() throws FileNotFoundException, IOException {
return BaSyxHttpTestUtils.readJSONStringFromClasspath("PaginatedAasSimple_1.json");
}

private String getEmptyResultJSONString() throws FileNotFoundException, IOException {
return BaSyxHttpTestUtils.readJSONStringFromClasspath("EmptyResponse.json");
}

private String getJSONWithoutCursorInfo(String response) throws JsonMappingException, JsonProcessingException {
return BaSyxHttpTestUtils.removeCursorFromJSON(response);
Expand Down Expand Up @@ -489,6 +512,14 @@ protected CloseableHttpResponse getAllAasGlobalAssetIdsParam() throws IOExceptio
return BaSyxHttpTestUtils.executeGetOnURL(getURL()+"?assetIds=ew0KIm5hbWUiOiJnbG9iYWxBc3NldElkIiwNCiJ2YWx1ZSI6Imdsb2JhbEFzc2V0SWQiDQp9");
}

protected CloseableHttpResponse getAllAasMultipleDifferentGlobalAssetIdsParam() throws IOException {
return BaSyxHttpTestUtils.executeGetOnURL(getURL()+"?assetIds=ew0KIm5hbWUiOiJnbG9iYWxBc3NldElkIiwNCiJ2YWx1ZSI6Imdsb2JhbEFzc2V0SWQiDQp9&assetIds=ew0KIm5hbWUiOiJnbG9iYWxBc3NldElkIiwNCiJ2YWx1ZSI6ImR1bW15QWFzQXNzZXRJZCINCn0");
}

protected CloseableHttpResponse getAllAasMultipleIdenticalGlobalAssetIdsParam() throws IOException {
return BaSyxHttpTestUtils.executeGetOnURL(getURL()+"?assetIds=ew0KIm5hbWUiOiJnbG9iYWxBc3NldElkIiwNCiJ2YWx1ZSI6Imdsb2JhbEFzc2V0SWQiDQp9&assetIds=ew0KIm5hbWUiOiJnbG9iYWxBc3NldElkIiwNCiJ2YWx1ZSI6Imdsb2JhbEFzc2V0SWQiDQp9");
}

protected CloseableHttpResponse getAllAasIdShortParam() throws IOException {
return BaSyxHttpTestUtils.executeGetOnURL(getURL()+"?idShort=ExampleMotor");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"paging_metadata": {},
"result": [
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.TreeMap;
Expand Down Expand Up @@ -115,9 +116,9 @@ public AssetInformation getAssetInformation(String aasId) {
public Iterable<AssetAdministrationShell> getAllAas(List<SpecificAssetId> assetIds, String idShort) {
Iterable<AssetAdministrationShell> allAas = findAll();
List<AssetAdministrationShell> filteredAas = new java.util.ArrayList<>();
String globalAssetId = null;
List<SpecificAssetId> globalAssetIds = new ArrayList<>();
try {
globalAssetId = assetIds.stream().filter(assetId -> assetId.getName().equals("globalAssetId")).findFirst().get().getValue();
globalAssetIds = assetIds.stream().filter(assetId -> assetId.getName().equals("globalAssetId")).toList();
assetIds = assetIds.stream().filter(assetId -> !assetId.getName().equals("globalAssetId")).collect(Collectors.toList());
} catch (Exception e) {}
for (AssetAdministrationShell aas : allAas){
Expand All @@ -129,7 +130,15 @@ public Iterable<AssetAdministrationShell> getAllAas(List<SpecificAssetId> assetI
matchesAssetIds = false;
}
boolean matchesIdShort = (idShort == null || aas.getIdShort().equals(idShort));
boolean matchesGlobalAssetId = (globalAssetId == null || (aas.getAssetInformation() != null && aas.getAssetInformation().getGlobalAssetId() != null && aas.getAssetInformation().getGlobalAssetId().equals(globalAssetId)));
boolean matchesGlobalAssetId = globalAssetIds.isEmpty();
for (SpecificAssetId globalAssetId : globalAssetIds){
String id = globalAssetId.getValue();
if (aas.getAssetInformation() == null || aas.getAssetInformation().getGlobalAssetId() == null || !aas.getAssetInformation().getGlobalAssetId().equals(id)) {
matchesGlobalAssetId = false;
break;
}
matchesGlobalAssetId = true;
}
if (matchesAssetIds && matchesIdShort && matchesGlobalAssetId) {
filteredAas.add(aas);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,11 @@ private List<Criteria> buildAasFilterCriteria(List<SpecificAssetId> assetIds, St
List<Criteria> criteriaList = new ArrayList<>();

// Extract globalAssetId from assetIds
String globalAssetId = null;
List<SpecificAssetId> globalAssetIds = new ArrayList<>();
try {
globalAssetId = assetIds.stream()
globalAssetIds = assetIds.stream()
.filter(assetId -> "globalAssetId".equals(assetId.getName()))
.findFirst()
.map(SpecificAssetId::getValue)
.orElse(null);
.toList();

assetIds = assetIds.stream()
.filter(assetId -> !"globalAssetId".equals(assetId.getName()))
Expand All @@ -267,8 +265,8 @@ private List<Criteria> buildAasFilterCriteria(List<SpecificAssetId> assetIds, St
}

// Match globalAssetId if present
if (globalAssetId != null && !globalAssetId.isEmpty()) {
criteriaList.add(Criteria.where("assetInformation.globalAssetId").is(globalAssetId));
for (SpecificAssetId globalAssetId : globalAssetIds) {
criteriaList.add(Criteria.where("assetInformation.globalAssetId").is(globalAssetId.getValue()));
}
Comment on lines +268 to 270
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for handling multiple globalAssetIds is incorrect. When multiple globalAssetIds are provided, adding each as a separate criteria with AND operator (line 217) means the query would require an AAS to match ALL globalAssetIds simultaneously, which is impossible since an AAS can only have one globalAssetId. This should either return an empty result (like the InMemory implementation) or use OR logic. The InMemory backend correctly returns an empty list when multiple globalAssetIds are detected.

Copilot uses AI. Check for mistakes.

return criteriaList;
Expand Down