v3 Batch 3 contracts: IEffectiveNameGuard authoring-time uniqueness seam
Wave-A shared contract. WP2 implements + registers the guard; WP1 consumes it in UnsTreeService reference/VirtualTag/ScriptedAlarm mutations. Ordinal, mirrors the deploy-time DraftValidator UnsEffectiveNameCollision rule. Claude-Session: https://claude.ai/code/session_01LVneM3eh1UtJxEisFXgmox
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns;
|
||||
|
||||
/// <summary>
|
||||
/// Which authoring surface a proposed effective name comes from. Used to word the collision
|
||||
/// error and to exclude the correct same-kind self-row on an edit (rename / override change).
|
||||
/// </summary>
|
||||
public enum EffectiveNameSourceKind
|
||||
{
|
||||
/// <summary>A <see cref="Configuration.Entities.UnsTagReference"/> (effective name =
|
||||
/// <c>DisplayNameOverride</c> else the backing raw tag's <c>Name</c>).</summary>
|
||||
Reference,
|
||||
|
||||
/// <summary>An equipment-bound <see cref="Configuration.Entities.VirtualTag"/> (effective name = <c>Name</c>).</summary>
|
||||
VirtualTag,
|
||||
|
||||
/// <summary>An equipment-bound <see cref="Configuration.Entities.ScriptedAlarm"/> (effective name = <c>Name</c>).</summary>
|
||||
ScriptedAlarm,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// v3 Batch 3 authoring-time guard for the UNS effective-name uniqueness rule. Within an
|
||||
/// equipment the EFFECTIVE leaf name must be unique across its <c>UnsTagReferences</c>
|
||||
/// (<c>DisplayNameOverride</c> else the backing raw tag's <c>Name</c>), its <c>VirtualTags</c>
|
||||
/// (<c>Name</c>), and its <c>ScriptedAlarms</c> (<c>Name</c>) — the three share the equipment's
|
||||
/// UNS NodeId space (<c>{EquipmentId}/{EffectiveName}</c>). This is the authoring mirror of the
|
||||
/// deploy-time <c>DraftValidator</c> <c>UnsEffectiveNameCollision</c> rule; comparison is
|
||||
/// <see cref="StringComparer.Ordinal"/> to match NodeId semantics and the validator.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Injectable (registered <c>Scoped</c>, its own pooled context per call — the same pattern
|
||||
/// <c>UnsTreeService</c> uses). Consumed by <c>UnsTreeService</c>'s reference / virtual-tag /
|
||||
/// scripted-alarm mutations, which call <see cref="CheckAsync"/> before persisting and surface a
|
||||
/// non-null result as the mutation's readable failure. The deploy gate remains the backstop for
|
||||
/// rename-induced collisions the authoring check never saw.
|
||||
/// </remarks>
|
||||
public interface IEffectiveNameGuard
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests whether <paramref name="proposedEffectiveName"/> would collide with an existing
|
||||
/// effective name within <paramref name="equipmentId"/>.
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">The owning equipment's logical id.</param>
|
||||
/// <param name="proposedEffectiveName">The effective name to be authored (override else raw name for a reference; Name for a VT/alarm).</param>
|
||||
/// <param name="kind">Which surface the proposed name is for (words the error; identifies the self-row kind to exclude).</param>
|
||||
/// <param name="excludeSourceId">
|
||||
/// On an edit, the logical id of the row being changed (its <c>UnsTagReferenceId</c> /
|
||||
/// <c>VirtualTagId</c> / <c>ScriptedAlarmId</c>) so it is excluded from the collision set;
|
||||
/// <see langword="null"/> on a create.
|
||||
/// </param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>
|
||||
/// <see langword="null"/> when the name is free; otherwise a readable error naming the
|
||||
/// colliding existing source and the equipment.
|
||||
/// </returns>
|
||||
Task<string?> CheckAsync(
|
||||
string equipmentId,
|
||||
string proposedEffectiveName,
|
||||
EffectiveNameSourceKind kind,
|
||||
string? excludeSourceId,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
Reference in New Issue
Block a user