6dc5af7aa2
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
62 lines
3.3 KiB
C#
62 lines
3.3 KiB
C#
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);
|
|
}
|