refactor(config): DraftValidator Galaxy rule reads ExplicitFullName via TagConfigIntent (R2-11)

This commit is contained in:
Joseph Doherty
2026-07-13 10:48:50 -04:00
parent c1e19ea954
commit a3c2b11e34
3 changed files with 9 additions and 18 deletions
@@ -1,4 +1,5 @@
using System.Text.RegularExpressions;
using ZB.MOM.WW.OtOpcUa.Commons.Types;
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
@@ -47,29 +48,16 @@ public static class DraftValidator
if (t.EquipmentId is null) continue;
if (!typeByDriver.TryGetValue(t.DriverInstanceId, out var dtype) || dtype != "GalaxyMxGateway")
continue;
if (string.IsNullOrWhiteSpace(ExtractTagConfigFullName(t.TagConfig)))
// The Galaxy rule wants the EXPLICIT reference, not the raw-blob fallback — so it reads
// TagConfigIntent.ExplicitFullName (the "FullName" property only when present-and-string,
// else null), preserving the historical null-on-absent semantics by construction (R2-11).
if (string.IsNullOrWhiteSpace(TagConfigIntent.Parse(t.TagConfig).ExplicitFullName))
errors.Add(new("GalaxyTagMissingReference",
$"Galaxy tag '{t.TagId}' on equipment '{t.EquipmentId}' is missing a Galaxy reference (TagConfig.FullName)",
t.TagId));
}
}
// Minimal reader for the top-level "FullName" string in a tag's schemaless TagConfig JSON
// (mirrors AddressSpaceComposer.ExtractTagFullName — a small local copy, consistent with this codebase
// where the composer keeps its own).
private static string? ExtractTagConfigFullName(string? tagConfig)
{
if (string.IsNullOrWhiteSpace(tagConfig)) return null;
try
{
using var doc = System.Text.Json.JsonDocument.Parse(tagConfig);
return doc.RootElement.ValueKind == System.Text.Json.JsonValueKind.Object
&& doc.RootElement.TryGetProperty("FullName", out var fn)
&& fn.ValueKind == System.Text.Json.JsonValueKind.String ? fn.GetString() : null;
}
catch (System.Text.Json.JsonException) { return null; }
}
private static void ValidateNoEquipmentSignalNameCollision(DraftSnapshot draft, List<ValidationError> errors)
{
// Materialiser NodeId key: "{EquipmentId}[/{FolderPath}]/{Name}". Tag (EquipmentId != null) and
@@ -27,6 +27,9 @@
<ItemGroup>
<ProjectReference Include="..\ZB.MOM.WW.OtOpcUa.Core.Abstractions\ZB.MOM.WW.OtOpcUa.Core.Abstractions.csproj"/>
<!-- R2-11 (01/C-1): consume the shared TagConfigIntent.Parse byte-parity authority in Commons.
Cycle-safe — Commons has zero in-repo ProjectReferences. -->
<ProjectReference Include="..\ZB.MOM.WW.OtOpcUa.Commons\ZB.MOM.WW.OtOpcUa.Commons.csproj"/>
</ItemGroup>
</Project>