Skip to content

Commit 039c119

Browse files
authored
Merge pull request #49 from PTCInc/Endpoint-Resolver-Issue
Endpoint resolver fix for DeviceTagGroup and DeviceTagCollection fix / refactor
2 parents 678e958 + c94803b commit 039c119

11 files changed

Lines changed: 37 additions & 39 deletions

File tree

Kepware.Api.Test/ApiClient/LoadEntity.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ public async Task LoadEntityAsync_ShouldReturnTagCollection_WhenApiRespondsSucce
352352
.ReturnsResponse(tagsJson, "application/json");
353353

354354
// Act
355-
var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync<DeviceTagGroupTagCollection, Tag>(new DeviceTagGroup("B Registers", new Device("16 Bit Device", "Data Type Examples")));
355+
var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync<DeviceTagCollection, Tag>(new DeviceTagGroup("B Registers", new Device("16 Bit Device", "Data Type Examples")));
356356

357357
// Assert
358358
Assert.NotNull(result);
@@ -363,15 +363,15 @@ public async Task LoadEntityAsync_ShouldReturnTagCollection_WhenApiRespondsSucce
363363

364364
#endregion
365365

366-
#region LoadEntityAsync - Exception Fall
366+
#region LoadEntityAsync - Exception Fail
367367

368368
[Fact]
369369
public async Task LoadEntityAsync_ShouldThrowInvalidOperationException_WhenLoadRecursiveEndpointWithStringList()
370370
{
371371
// Act & Assert
372372
var exception = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
373373
{
374-
await _kepwareApiClient.GenericConfig.LoadCollectionAsync<DeviceTagGroupTagCollection, Tag>(["Data Type Examples", "16 Bit Device", "B Registers"]);
374+
await _kepwareApiClient.GenericConfig.LoadCollectionAsync<DeviceTagCollection, Tag>(["Data Type Examples", "16 Bit Device", "B Registers"]);
375375
});
376376

377377
Assert.Equal("Recursive endpoint does not support string list item name", exception.Message);

Kepware.Api.Test/ApiClient/ProjectLoadTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private static void CompareTagGroupsRecursive(DeviceTagGroupCollection? expected
165165
var thisName = parentName + "/" + ExpectedTagGroup.Name;
166166
if (ExpectedTagGroup.Tags?.Count > 0 || ActualTagGroup.Tags?.Count > 0)
167167
{
168-
var tagCompareResult = EntityCompare.Compare<DeviceTagGroupTagCollection, Tag>(ExpectedTagGroup.Tags, ExpectedTagGroup.Tags);
168+
var tagCompareResult = EntityCompare.Compare<DeviceTagCollection, Tag>(ExpectedTagGroup.Tags, ExpectedTagGroup.Tags);
169169
tagCompareResult.ShouldNotBeNull();
170170
tagCompareResult.UnchangedItems.ShouldNotBeEmpty($"All tags in device {thisName} should be unchanged.");
171171
tagCompareResult.ChangedItems.ShouldBeEmpty($"No tags in device {thisName} should be changed.");

Kepware.Api.Test/Util/EndpointResolverTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void ResolveEndpoint_ShouldReturnCorrectRecursiveEndpoint()
5656
var owner = new DeviceTagGroup("Values", new DeviceTagGroup("B Registers", new Device("16 Bit Device", new Channel("Data Type Examples"))));
5757

5858
// Act
59-
var endpoint = EndpointResolver.ResolveEndpoint<DeviceTagGroupTagCollection>(owner);
59+
var endpoint = EndpointResolver.ResolveEndpoint<DeviceTagCollection>(owner);
6060

6161
// Assert
6262
Assert.Equal("/config/v1/project/channels/Data%20Type%20Examples/devices/16%20Bit%20Device/tag_groups/B%20Registers/tag_groups/Values/tags", endpoint);
@@ -98,7 +98,7 @@ public void ResolveEndpoint_ShouldThrowException_WhenRecursiveEndpointDoesNotSup
9898

9999
// Act & Assert
100100
var exception = Assert.Throws<InvalidOperationException>(() =>
101-
EndpointResolver.ResolveEndpoint<DeviceTagGroupTagCollection>(owner, "Boolean1")
101+
EndpointResolver.ResolveEndpoint<DeviceTagCollection>(owner, "Boolean1")
102102
);
103103

104104
Assert.Equal("Recursive endpoint does not support item name", exception.Message);

Kepware.Api.TestIntg/ApiClient/LoadEntity.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ public async Task LoadEntityAsync_ShouldReturnTagCollection_WhenApiRespondsSucce
258258
var tagList = await AddSimulatorTestTags(device);
259259

260260
// Act
261-
var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync<DeviceTagGroupTagCollection, Tag>(device);
261+
var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync<DeviceTagCollection, Tag>(device);
262262

263263
// Assert
264264
Assert.NotNull(result);
@@ -318,7 +318,7 @@ public async Task LoadEntityAsync_ShouldReturnTagCollectionFromTagGroup_WhenApiR
318318
var tagList = await AddSimulatorTestTags(tagGroup);
319319

320320
// Act
321-
var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync<DeviceTagGroupTagCollection, Tag>(tagGroup);
321+
var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync<DeviceTagCollection, Tag>(tagGroup);
322322

323323
// Assert
324324
Assert.NotNull(result);

Kepware.Api.TestIntg/ApiClient/ProjectLoadTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ private static void CompareTagGroupsRecursive(DeviceTagGroupCollection? expected
163163
var thisName = parentName + "/" + ExpectedTagGroup.Name;
164164
if (ExpectedTagGroup.Tags?.Count > 0 || ActualTagGroup.Tags?.Count > 0)
165165
{
166-
var tagCompareResult = EntityCompare.Compare<DeviceTagGroupTagCollection, Tag>(ExpectedTagGroup.Tags, ExpectedTagGroup.Tags);
166+
var tagCompareResult = EntityCompare.Compare<DeviceTagCollection, Tag>(ExpectedTagGroup.Tags, ExpectedTagGroup.Tags);
167167
tagCompareResult.ShouldNotBeNull();
168168
tagCompareResult.UnchangedItems.ShouldNotBeEmpty($"All tags in device {thisName} should be unchanged.");
169169
tagCompareResult.ChangedItems.ShouldBeEmpty($"No tags in device {thisName} should be changed.");

Kepware.Api.TestIntg/appsettings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"TestServer": {
55
"Host": "http://localhost",
66
"Port": 57412,
7-
"UserName": "Test",
8-
"Password": "Kepware400400400"
7+
"UserName": "Administrator",
8+
"Password": "ReallyStrongPassword400!"
99
}
1010
}
1111
}

Kepware.Api/ClientHandler/GenericApiHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ public async Task<bool[]> InsertItemsAsync<T, K>(List<K> items, int pageSize = 1
310310
for (int i = 0; i < totalPageCount; i++)
311311
{
312312
var pageItems = items.Skip(i * pageSize).Take(pageSize).ToList();
313-
m_logger.LogInformation("Inserting {NumItems} {TypeName} on {Endpoint} in batch {BatchNr} of {TotalBatches} ...", pageItems.Count, typeof(K).Name, endpoint, i + 1, totalPageCount);
313+
m_logger.LogInformation("Inserting {NumItems} {TypeName}(s) on {Endpoint} in batch {BatchNr} of {TotalBatches} ...", pageItems.Count, typeof(K).Name, endpoint, i + 1, totalPageCount);
314314

315315
var jsonContent = JsonSerializer.Serialize(pageItems, KepJsonContext.GetJsonListTypeInfo<K>());
316316
HttpContent httpContent = new StringContent(jsonContent, Encoding.UTF8, "application/json");

Kepware.Api/ClientHandler/ProjectApiHandler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public ProjectApiHandler(KepwareApiClient kepwareApiClient, ChannelApiHandler ch
119119

120120
foreach (var tagGroup in tagGroupCompare.UnchangedItems.Concat(tagGroupCompare.ChangedItems))
121121
{
122-
var tagGroupTagCompare = await m_kepwareApiClient.GenericConfig.CompareAndApply<DeviceTagGroupTagCollection, Tag>(tagGroup.Left!.Tags, tagGroup.Right!.Tags, tagGroup.Right, cancellationToken).ConfigureAwait(false);
122+
var tagGroupTagCompare = await m_kepwareApiClient.GenericConfig.CompareAndApply<DeviceTagCollection, Tag>(tagGroup.Left!.Tags, tagGroup.Right!.Tags, tagGroup.Right, cancellationToken).ConfigureAwait(false);
123123

124124
updates += tagGroupTagCompare.ChangedItems.Count;
125125
inserts += tagGroupTagCompare.ItemsOnlyInLeft.Count;
@@ -376,7 +376,7 @@ private static void SetOwnerRecursive(IEnumerable<DeviceTagGroup> tagGroups, Nam
376376

377377
foreach (var tagGroup in tagGroupCompare.UnchangedItems.Concat(tagGroupCompare.ChangedItems))
378378
{
379-
var tagGroupTagCompare = await apiClient.GenericConfig.CompareAndApply<DeviceTagGroupTagCollection, Tag>(tagGroup.Left!.Tags, tagGroup.Right!.Tags, tagGroup.Right, cancellationToken: cancellationToken).ConfigureAwait(false);
379+
var tagGroupTagCompare = await apiClient.GenericConfig.CompareAndApply<DeviceTagCollection, Tag>(tagGroup.Left!.Tags, tagGroup.Right!.Tags, tagGroup.Right, cancellationToken: cancellationToken).ConfigureAwait(false);
380380

381381
ret.inserts = tagGroupTagCompare.ItemsOnlyInLeft.Count;
382382
ret.updates = tagGroupTagCompare.ChangedItems.Count;
@@ -407,7 +407,7 @@ internal static async Task LoadTagGroupsRecursiveAsync(KepwareApiClient apiClien
407407
{
408408
// Load the Tag Groups and Tags of the current Tag Group
409409
tagGroup.TagGroups = await apiClient.GenericConfig.LoadCollectionAsync<DeviceTagGroupCollection, DeviceTagGroup>(tagGroup, cancellationToken).ConfigureAwait(false);
410-
tagGroup.Tags = await apiClient.GenericConfig.LoadCollectionAsync<DeviceTagGroupTagCollection, Tag>(tagGroup, cancellationToken).ConfigureAwait(false);
410+
tagGroup.Tags = await apiClient.GenericConfig.LoadCollectionAsync<DeviceTagCollection, Tag>(tagGroup, cancellationToken).ConfigureAwait(false);
411411

412412
// Recursively load the Tag Groups and Tags of the child Tag Groups
413413
if (tagGroup.TagGroups != null && tagGroup.TagGroups.Count > 0)

Kepware.Api/Model/EndpointAttribute.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@ namespace Kepware.Api.Model
99
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
1010
public class EndpointAttribute : Attribute
1111
{
12+
/// <summary>
13+
/// Represents the base endpoint template for the entity type.
14+
/// </summary>
1215
public string EndpointTemplate { get; }
16+
17+
/// <summary>
18+
/// Represents the suffix to append to the endpoint. This is optional and is often used
19+
/// when entity types are collection types in the Kepware Configuration API, like tags or
20+
/// tag groups can have dynamic endpoints based on their parent entity.
21+
/// </summary>
1322
public string? Suffix { get; } = null;
1423

1524
public EndpointAttribute(string endpointTemplate, string? suffix = default)
@@ -22,7 +31,17 @@ public EndpointAttribute(string endpointTemplate, string? suffix = default)
2231
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
2332
public class RecursiveEndpointAttribute : EndpointAttribute
2433
{
34+
/// <summary>
35+
/// Represents the endpoint template for the recursive or dynamically
36+
/// generated endpoints based on their parent entity. Examples would include tags and tag groups.
37+
/// </summary>
2538
public string RecursiveEnd { get; }
39+
40+
/// <summary>
41+
/// Represents the type of the owner that is used to resolve the recursive endpoint.
42+
/// Example: if the entity is a tag group, the endpoint resolution would need to
43+
/// recursively/dynamically resolve if it's parent is a tag group as well.
44+
/// </summary>
2645
public Type RecursiveOwnerType { get; }
2746

2847
public RecursiveEndpointAttribute(string endpointTemplate, string recursiveEnd, Type recursiveOwnerType, string? suffix = default)

Kepware.Api/Model/Project/DeviceTagGroup.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Kepware.Api.Model
1111
/// <summary>
1212
/// Represents a tag group in a device
1313
/// </summary>
14-
[RecursiveEndpoint("/config/v1/project/channels/{channelName}/devices/{deviceName}", "/tag_groups/{groupName}", typeof(DeviceTagGroup))]
14+
[RecursiveEndpoint("/config/v1/project/channels/{channelName}/devices/{deviceName}", "/tag_groups/{groupName}", typeof(DeviceTagGroup), suffix: "/tag_groups/{groupName}")]
1515
public class DeviceTagGroup : NamedEntity
1616
{
1717
public DeviceTagGroup()
@@ -37,7 +37,7 @@ public DeviceTagGroup(string name, DeviceTagGroup owner)
3737
[YamlIgnore]
3838
[JsonPropertyName("tags")]
3939
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
40-
public DeviceTagGroupTagCollection? Tags { get; set; }
40+
public DeviceTagCollection? Tags { get; set; }
4141

4242
/// <summary>
4343
/// Recursively cleans up the tag group and all its children

0 commit comments

Comments
 (0)