namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip; /// /// The ONE place an AbCip driver's effective transport is decided from its configured /// . The driver constructor, the Test Connect probe and the /// CLI (through the driver) all resolve through here, so they cannot disagree about what an absent /// transport key means. /// Precedence (final review I1): an explicit per-driver transport key wins; otherwise the /// node-level default (Drivers:AbCip:DefaultTransport, read in the Host composition root and passed /// in as nodeDefault); otherwise the compiled . /// public static class AbCipTransportResolver { /// The compiled default: the transport an absent key selects when no node default is configured. public const AbCipTransport Default = AbCipTransport.Native; /// Returns the effective transport: an explicit value always wins; null means . /// The configured transport, or null for "use the default". /// The node-level default for drivers with no key (the compiled unless pinned). /// The transport the driver runs on. public static AbCipTransport Resolve(AbCipTransport? configured, AbCipTransport nodeDefault = Default) => configured ?? nodeDefault; /// Returns the effective transport for . /// The driver options. /// The node-level default for drivers with no key. /// The transport the driver runs on. public static AbCipTransport Resolve(AbCipDriverOptions options, AbCipTransport nodeDefault = Default) { ArgumentNullException.ThrowIfNull(options); return Resolve(options.Transport, nodeDefault); } /// /// Parses a transport name the way the driver-config transport key and the node-level default /// are parsed: a defined enum NAME, case-insensitive. Numeric strings ("0", "7") and the flags form /// ("Native,Libplctag") are rejected — Enum.TryParse alone accepts both. /// /// The raw value. /// The parsed transport. /// True when names a transport. public static bool TryParse(string? raw, out AbCipTransport transport) { transport = Default; if (string.IsNullOrWhiteSpace(raw)) return false; // Exact name match only: Enum.TryParse would also accept "1" and the flags form "Native,Libplctag". var name = Enum.GetNames() .FirstOrDefault(n => string.Equals(n, raw.Trim(), StringComparison.OrdinalIgnoreCase)); return name is not null && Enum.TryParse(name, out transport); } /// /// Operator-facing description of the configured-vs-effective transport for the init log line: /// Native (default) when the key was absent and the compiled default applies, /// Libplctag (node default) when the key was absent and the node pinned a different default, /// Native (configured) when the key was explicit. /// /// The configured transport, or null. /// The node-level default. /// A short description. public static string Describe(AbCipTransport? configured, AbCipTransport nodeDefault = Default) => configured is not null ? $"{configured} (configured)" : nodeDefault == Default ? $"{nodeDefault} (default)" : $"{nodeDefault} (node default)"; }