Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
38ca92c
feat: implement CachedGetRequestClient with hybrid caching and user-s…
mm-kgi Jul 23, 2026
2a99f7a
feat: implement ShellDescriptorService to retrieve and populate AAS s…
mm-kgi Jul 23, 2026
bc8e4db
feat: implement CachedGetRequestClient for resilient HTTP requests wi…
mm-kgi Jul 23, 2026
7d096ae
feat: implement ShellDescriptorService to retrieve and construct shel…
mm-kgi Jul 23, 2026
1562e65
refactor: remove redundant test for skipping failed shell descriptors…
mm-kgi Jul 23, 2026
2dd641c
refactor: simplify SendGetRequestAsync method implementation
mm-kgi Jul 23, 2026
0b1f0e0
feat: implement CachedGetRequestClient with HybridCache and user-cont…
mm-kgi Jul 23, 2026
8e1e3e2
Merge branch 'develop' into 1474-caching-template-retrieval
mm-kgi Jul 23, 2026
1595b62
For testing, will be removed
mm-kgi Jul 24, 2026
9b28a13
removed extra auth added for testing
mm-kgi Jul 24, 2026
1d15a08
feat: implement plugin-based data retrieval and submodel repository p…
mm-kgi Jul 31, 2026
77a54fb
Refactor SubmodelRepositoryService and related components for paginat…
mm-hsh Jul 31, 2026
ef0393d
refactor: rewrite submodel pagination concept documentation to detail…
mm-kgi Jul 31, 2026
cd95786
Revert "Refactor SubmodelRepositoryService and related components for…
mm-kgi Jul 31, 2026
196fd34
Refactor SubmodelRepositoryService and related components for paginat…
mm-hsh Jul 31, 2026
dd828fa
chore: remove outdated Submodel Pagination Cursor Concept documentation
mm-kgi Aug 1, 2026
97d2cf7
refactor: enhance pagination logic and update submodel ID handling in…
mm-kgi Aug 3, 2026
f3409a0
Implement two-field cursor-based pagination
mm-kgi Aug 3, 2026
7405a8b
feat: implement SubmodelDescriptorService and SubmodelRepositoryServi…
mm-kgi Aug 4, 2026
d628558
merge from parent branch
mm-kgi Aug 4, 2026
b22b66a
feat: implement plugin data provider interface and handler for managi…
mm-kgi Aug 4, 2026
78bc905
feat: enhance pagination and data retrieval logic across services and…
mm-kgi Aug 16, 2026
ceb2907
parent branch merge
mm-kgi Aug 16, 2026
5383bea
Merge branch 'develop' into pagination-tests
mm-kgi Aug 19, 2026
5f84d22
feat: refactor pagination logic and introduce SubmodelPaginationState…
mm-kgi Aug 19, 2026
d4a5c3a
fix: update null handling in results and improve query parameter usage
mm-kgi Aug 19, 2026
88e6d2e
feat: enhance metadata retrieval by adding pagination parameters to G…
mm-kgi Aug 19, 2026
fd7b0b8
resolve semantic id filter issue
mm-kgi Aug 20, 2026
0e9bbf9
refactor: clean up code formatting and remove unnecessary null-forgiv…
mm-kgi Aug 20, 2026
fb7a142
refactor: update GetAllSubmodelsRequest to use constructor parameters…
mm-kgi Aug 21, 2026
703c919
feat: implement default pagination limit in various services and hand…
mm-kgi Aug 26, 2026
27dc822
fix: update cursor in paging metadata for GetAllShellDescriptors_Expe…
mm-kgi Aug 26, 2026
58e184d
fix: update idShort values from "M&M" to "MM" across various test fil…
mm-kgi Aug 27, 2026
7c262bc
fix: add missing newline at the end of Get All Submodels - by idShort…
mm-kgi Aug 27, 2026
d373978
1511: Refactor code structure for improved readability and maintainab…
mm-mcn Aug 27, 2026
b2503ca
git merge with parent branch
mm-kgi Sep 2, 2026
ade6180
merge conflit resolve
mm-kgi Sep 2, 2026
ef02dae
enhance response
mm-hsh Sep 3, 2026
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 @@ -11,7 +11,6 @@
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Shared.Providers;
using AAS.TwinEngine.DataEngine.DomainModel.Shared;
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.SubmodelRepository;
using AAS.TwinEngine.DataEngine.DomainModel.Shared;
using AAS.TwinEngine.DataEngine.DomainModel.SubmodelRepository;
using AAS.TwinEngine.DataEngine.Infrastructure.Http.Clients;
using AAS.TwinEngine.DataEngine.ModuleTests.Common;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@
<None Update="SubmodelRegistry\TestData\GetSubmodelDescriptorById_CustomSubmodel_Expected.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SubmodelRegistry\TestData\GetAllSubmodelDescriptors_WithTwoFieldCursor_Expected.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SubmodelRepository\TestData\GetSubmodelElement_ContactInfo_ContactInformation_Expected.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down Expand Up @@ -141,6 +144,9 @@
<None Update="SubmodelRepository\TestData\GetAllSubmodelElements_ContactInfo_With_Cursor_Expected.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SubmodelRepository\TestData\GetAllSubmodels_WithTwoFieldCursor_Expected.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Discovery\TestData\GetSpecificAssetIdByAasIdentifier_Expected.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,47 @@ public async Task GetAllShellDescriptors_WithPagination()
Assert.Equal(countLimit2 + 1, countLimit3);
}

[Fact]
public async Task GetAllShellDescriptors_WithLimitAndCursor()
{
// Arrange
var urlLimit2 = "/shell-descriptors?limit=2";

// Act
var responseLimit2 = await ApiContext.GetAsync(urlLimit2);

// Assert
AssertSuccessResponse(responseLimit2);

var contentLimit2 = await responseLimit2.TextAsync();
Assert.False(string.IsNullOrEmpty(contentLimit2));

var jsonLimit2 = JsonDocument.Parse(contentLimit2);
var resultLimit2 = jsonLimit2.RootElement.GetProperty("result");
Assert.Equal(2, resultLimit2.GetArrayLength());

var cursor = jsonLimit2.RootElement.GetProperty("paging_metadata").GetProperty("cursor").GetString();
Assert.False(string.IsNullOrEmpty(cursor));

// Act - request next page using the cursor returned above
var urlWithCursor = $"/shell-descriptors?limit=2&cursor={cursor}";
var responseWithCursor = await ApiContext.GetAsync(urlWithCursor);

// Assert
AssertSuccessResponse(responseWithCursor);

var contentWithCursor = await responseWithCursor.TextAsync();
Assert.False(string.IsNullOrEmpty(contentWithCursor));

var jsonWithCursor = JsonDocument.Parse(contentWithCursor);
var resultWithCursor = jsonWithCursor.RootElement.GetProperty("result");

// Ensure the second page does not repeat the first element of the first page
var firstIdPage1 = resultLimit2[0].GetProperty("id").GetString();
var firstIdPage2 = resultWithCursor[0].GetProperty("id").GetString();
Assert.NotEqual(firstIdPage1, firstIdPage2);
}

[Fact]
public async Task GetShellDescriptorById_ShouldReturnSuccess_ContentAsExpected()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,27 @@ public async Task GetSubmodelDescriptorById_CustomSubmodel_ShouldReturnSuccess_C

await CompareJsonAsync(json, Path.Combine(Directory.GetCurrentDirectory(), "SubmodelRegistry", "TestData", "GetSubmodelDescriptorById_CustomSubmodel_Expected.json"));
}

[Fact]

public async Task GetAllSubmodelDescriptors_WithTwoFieldCursor_ShouldReturnSuccess_ContentAsExpected()
{

// Arrange
var url = "/submodel-descriptors?limit=2&cursor=aHR0cHM6Ly9tbS1zb2Z0d2FyZS5jb20vc3VibW9kZWwvMDAwLTAwMi9DdXN0b21TdWJtb2RlbHxodHRwczovL21tLXNvZnR3YXJlLmNvbS9pZHMvYWFzLzAwMC0wMDE";

// Act
var response = await ApiContext.GetAsync(url);

// Assert
AssertSuccessResponse(response);
var content = await response.TextAsync();
Assert.False(string.IsNullOrEmpty(content));

var json = JsonDocument.Parse(content);
Assert.NotNull(json);

await CompareJsonAsync(json, Path.Combine(Directory.GetCurrentDirectory(), "SubmodelRegistry", "TestData", "GetAllSubmodelDescriptors_WithTwoFieldCursor_Expected.json"));

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
"paging_metadata": {
"cursor": "aHR0cHM6Ly9tbS1zb2Z0d2FyZS5jb20vc3VibW9kZWwvMDAwLTAwMi9IYW5kb3ZlckRvY3VtZW50YXRpb258aHR0cHM6Ly9tbS1zb2Z0d2FyZS5jb20vaWRzL2Fhcy8wMDAtMDAy"
},
"result": [
{
"description": null,
"displayName": null,
"extensions": null,
"administration": null,
"idShort": "ContactInformations",
"id": "https://mm-software.com/submodel/000-002/ContactInformation",
"semanticId": {
"type": "ModelReference",
"referredSemanticId": null,
"keys": [
{
"type": "Submodel",
"value": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations"
}
]
},
"supplementalSemanticId": null,
"endpoints": [
{
"interface": "SUBMODEL-3.0",
"protocolInformation": {
"href": "http://localhost:8080/submodels/aHR0cHM6Ly9tbS1zb2Z0d2FyZS5jb20vc3VibW9kZWwvMDAwLTAwMi9Db250YWN0SW5mb3JtYXRpb24",
"endpointProtocol": "http",
"endpointProtocolVersion": null,
"subprotocol": null,
"subprotocolBody": null,
"subprotocolBodyEncoding": null,
"securityAttributes": null
}
}
]
},
{
"description": [
{
"language": "en",
"text": "The Submodel defines a set meta data for the handover of documentation from the manufacturer to the operator for industrial equipment"
}
],
"displayName": null,
"extensions": null,
"administration": {
"embeddedDataSpecifications": null,
"version": "2",
"revision": "0",
"creator": null,
"templateId": "https://admin-shell.io/idta-02004-2-0"
},
"idShort": "HandoverDocumentation",
"id": "https://mm-software.com/submodel/000-002/HandoverDocumentation",
"semanticId": {
"type": "ModelReference",
"referredSemanticId": null,
"keys": [
{
"type": "Submodel",
"value": "0173-1#01-AHF578#003"
}
]
},
"supplementalSemanticId": null,
"endpoints": [
{
"interface": "SUBMODEL-3.0",
"protocolInformation": {
"href": "http://localhost:8080/submodels/aHR0cHM6Ly9tbS1zb2Z0d2FyZS5jb20vc3VibW9kZWwvMDAwLTAwMi9IYW5kb3ZlckRvY3VtZW50YXRpb24",
"endpointProtocol": "http",
"endpointProtocolVersion": null,
"subprotocol": null,
"subprotocolBody": null,
"subprotocolBodyEncoding": null,
"securityAttributes": null
}
}
]
}
]
}

Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,27 @@ public async Task GetAllSubmodels_PaginationFlow_SecondPageHasDistinctResults()
Assert.NotEqual(firstResult, secondResult.GetProperty("id").GetString());
}
}

[Fact]

public async Task GetAllSubmodels_WithTwoFieldCursor_ShouldReturnSuccess_ContentAsExpected()
{

// Arrange
var url = "/submodels?limit=2&cursor=aHR0cHM6Ly9tbS1zb2Z0d2FyZS5jb20vc3VibW9kZWwvMDAwLTAwMi9DdXN0b21TdWJtb2RlbHxodHRwczovL21tLXNvZnR3YXJlLmNvbS9pZHMvYWFzLzAwMC0wMDE";

// Act
var response = await ApiContext.GetAsync(url);

// Assert
AssertSuccessResponse(response);
var content = await response.TextAsync();
Assert.False(string.IsNullOrEmpty(content));

var json = JsonDocument.Parse(content);
Assert.NotNull(json);

await CompareJsonAsync(json, Path.Combine(Directory.GetCurrentDirectory(), "SubmodelRepository", "TestData", "GetAllSubmodels_WithTwoFieldCursor_Expected.json"));

}
}
Loading
Loading