feat(m9/T26a): read-only inheritance resolve service + GetResolvedTemplateMembersCommand
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
/// <summary>
|
||||
/// Read-only response for <see cref="GetResolvedTemplateMembersCommand"/>: the
|
||||
/// EFFECTIVE inherited member set for a template, computed fresh from the full
|
||||
/// inheritance chain (root → leaf, arbitrary depth) and annotated per member
|
||||
/// with its origin and lock state — plus a staleness summary comparing the
|
||||
/// template's STORED member rows against this freshly-resolved set.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The precedence used to compute the effective member set MIRRORS
|
||||
/// <c>FlatteningService.ResolveInherited*</c> exactly (derived wins;
|
||||
/// <c>IsInherited</c> placeholders never shadow the live base value; locked
|
||||
/// members flagged), so the editor preview agrees with what a deploy would
|
||||
/// produce. This is the AUTHORING view only — it never mutates stored rows and
|
||||
/// is not on the deploy path.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Member values surfaced here are the inheritance-resolved values BEFORE any
|
||||
/// composition or instance override is applied — composition is a separate
|
||||
/// concern owned by the instance flattener, and there are no instances in the
|
||||
/// template-authoring context.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed record ResolvedTemplateMembers
|
||||
{
|
||||
/// <summary>The template the member set was resolved for.</summary>
|
||||
public int TemplateId { get; init; }
|
||||
/// <summary>The template's name.</summary>
|
||||
public string TemplateName { get; init; } = string.Empty;
|
||||
/// <summary>The immediate parent template id, or null when this is a root template.</summary>
|
||||
public int? ParentTemplateId { get; init; }
|
||||
|
||||
/// <summary>The effective resolved attributes (own + transitively inherited).</summary>
|
||||
public IReadOnlyList<ResolvedTemplateMemberInfo> Attributes { get; init; } = [];
|
||||
/// <summary>The effective resolved alarms (own + transitively inherited).</summary>
|
||||
public IReadOnlyList<ResolvedTemplateMemberInfo> Alarms { get; init; } = [];
|
||||
/// <summary>The effective resolved scripts (own + transitively inherited).</summary>
|
||||
public IReadOnlyList<ResolvedTemplateMemberInfo> Scripts { get; init; } = [];
|
||||
/// <summary>The effective resolved native alarm source bindings (own + transitively inherited).</summary>
|
||||
public IReadOnlyList<ResolvedTemplateMemberInfo> NativeAlarmSources { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Staleness summary: whether the template's stored member rows differ from
|
||||
/// this freshly-resolved set (e.g. a base member added after the derived
|
||||
/// template was created, or a multi-level inherited member not present in
|
||||
/// the stored rows), and how many inherited members differ.
|
||||
/// </summary>
|
||||
public ResolvedTemplateStaleness Staleness { get; init; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One effective member in a <see cref="ResolvedTemplateMembers"/> set,
|
||||
/// annotated with where its winning definition came from and its lock state.
|
||||
/// </summary>
|
||||
public sealed record ResolvedTemplateMemberInfo
|
||||
{
|
||||
/// <summary>The member name (bare; inheritance-resolved members are never path-qualified).</summary>
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// True when the winning definition lives on an ANCESTOR template rather
|
||||
/// than on the resolved template itself — i.e. this member is inherited.
|
||||
/// </summary>
|
||||
public bool IsInherited { get; init; }
|
||||
|
||||
/// <summary>The id of the template that supplied the winning definition.</summary>
|
||||
public int OriginTemplateId { get; init; }
|
||||
/// <summary>The name of the template that supplied the winning definition.</summary>
|
||||
public string OriginTemplateName { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// True when the member is locked from override (<c>IsLocked</c> on the
|
||||
/// winning row) — a derived template cannot change it.
|
||||
/// </summary>
|
||||
public bool IsLocked { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// True when an ANCESTOR marked this member <c>LockedInDerived</c> — the
|
||||
/// derived template may not override it (rendered read-only with a lock in
|
||||
/// the editor). Distinct from <see cref="IsLocked"/>: a base may forbid
|
||||
/// override (<c>LockedInDerived</c>) without the member itself being a
|
||||
/// locked composition member.
|
||||
/// </summary>
|
||||
public bool IsBaseLocked { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The effective value for the member, type-appropriate: attribute value,
|
||||
/// script code, alarm priority/trigger summary, or native-source reference.
|
||||
/// Provided so the editor preview shows the live (post-resolution) value
|
||||
/// without re-walking the chain itself. Null when the member type carries
|
||||
/// no single scalar value.
|
||||
/// </summary>
|
||||
public string? EffectiveValue { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Staleness summary comparing a template's STORED member rows against the
|
||||
/// freshly-resolved inherited member set.
|
||||
/// </summary>
|
||||
public sealed record ResolvedTemplateStaleness
|
||||
{
|
||||
/// <summary>
|
||||
/// True when the stored derived rows differ from the freshly-resolved set —
|
||||
/// the base changed after the derived template was created, so the editor
|
||||
/// should surface a "base changed" banner.
|
||||
/// </summary>
|
||||
public bool IsStale { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of inherited members whose freshly-resolved state differs
|
||||
/// from what the stored rows reflect (missing rows, added base members,
|
||||
/// changed inherited values). This is the count the editor banner shows.
|
||||
/// </summary>
|
||||
public int DifferingMemberCount { get; init; }
|
||||
}
|
||||
@@ -7,6 +7,16 @@ public record UpdateTemplateCommand(int TemplateId, string Name, string? Descrip
|
||||
public record DeleteTemplateCommand(int TemplateId);
|
||||
public record ValidateTemplateCommand(int TemplateId);
|
||||
|
||||
/// <summary>
|
||||
/// Read-only authoring query (M9/T26a): returns the EFFECTIVE inherited member
|
||||
/// set for a template — computed fresh from the full inheritance chain
|
||||
/// (arbitrary depth), annotated per member with origin + lock state — plus a
|
||||
/// staleness summary comparing the template's stored rows against the resolved
|
||||
/// set. Feeds the template editor's inheritance preview + base-change banner;
|
||||
/// never mutates stored rows. Response: <see cref="ResolvedTemplateMembers"/>.
|
||||
/// </summary>
|
||||
public record GetResolvedTemplateMembersCommand(int TemplateId);
|
||||
|
||||
// Template member operations
|
||||
public record AddTemplateAttributeCommand(int TemplateId, string Name, string DataType, string? Value, string? Description, string? DataSourceReference, bool IsLocked, string? ElementDataType = null);
|
||||
public record UpdateTemplateAttributeCommand(int AttributeId, string Name, string DataType, string? Value, string? Description, string? DataSourceReference, bool IsLocked, string? ElementDataType = null);
|
||||
|
||||
Reference in New Issue
Block a user