Files
ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/TemplateNaming.cs
T
Joseph Doherty 7b0b9c7365 refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)
Solution + 23 src projects + 26 test projects renamed; folders, csproj,
namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated.
ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated.
SQL roles/logins, LDAP domains, CLI command name, and CLI config dir
(~/.scadalink → ~/.scadabridge) also renamed.

Build green; 5 Host.Tests fail awaiting SQL login rename in next commit.
Pre-existing StaleTagMonitor timing flakes unchanged.

Rename script committed at tools/rename-to-scadabridge.sh.
2026-05-28 09:37:45 -04:00

58 lines
2.5 KiB
C#

using ZB.MOM.WW.ScadaBridge.Commons.Entities.Templates;
namespace ZB.MOM.WW.ScadaBridge.TemplateEngine;
/// <summary>
/// Resolves the hierarchical ("qualified") name of a composition-derived
/// template. A derived template stores only its <em>contained</em> name — the
/// owning composition slot's <c>InstanceName</c>, unique only within that owner.
/// The qualified path (<c>Owner.Slot.Slot…</c>) is computed on demand by
/// walking the <see cref="Template.OwnerCompositionId"/> chain up to the base
/// template.
/// </summary>
public static class TemplateNaming
{
/// <summary>
/// Returns the dotted hierarchical name of <paramref name="template"/>. For
/// a base (non-derived) template this is just its stored name. The walk is
/// null-safe: if any owner link is missing from the supplied lookups it
/// stops and falls back to the stored contained name, and a cycle (which
/// the composition graph should never contain) is broken defensively.
/// </summary>
/// <param name="template">The template whose qualified name to compute.</param>
/// <param name="byId">Lookup of all templates by primary key.</param>
/// <param name="compById">Lookup of all template compositions by primary key.</param>
/// <returns>The dotted hierarchical name (e.g., <c>Owner.Slot.Name</c>).</returns>
public static string QualifiedName(
Template template,
IReadOnlyDictionary<int, Template> byId,
IReadOnlyDictionary<int, TemplateComposition> compById)
{
ArgumentNullException.ThrowIfNull(template);
ArgumentNullException.ThrowIfNull(byId);
ArgumentNullException.ThrowIfNull(compById);
return Resolve(template, byId, compById, new HashSet<int>());
}
private static string Resolve(
Template template,
IReadOnlyDictionary<int, Template> byId,
IReadOnlyDictionary<int, TemplateComposition> compById,
HashSet<int> visited)
{
// Base template, broken owner link, or a cycle → the stored name is the
// best (and contained) answer.
if (!template.IsDerived
|| template.OwnerCompositionId is not { } compId
|| !compById.TryGetValue(compId, out var composition)
|| !byId.TryGetValue(composition.TemplateId, out var owner)
|| !visited.Add(template.Id))
{
return template.Name;
}
return $"{Resolve(owner, byId, compById, visited)}.{composition.InstanceName}";
}
}