/* ======================================================================== * Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Opc.Ua.Server.Fluent { /// /// Fluent surface used to wire callbacks into a node manager's /// predefined-node graph. An instance of this builder is created once /// per node manager activation by the source-generated /// NodeManagerBase.Configure hook (or supplied directly to /// hand-written managers via /// CustomNodeManager2.Configure(Action<INodeManagerBuilder>)). /// /// /// /// All node lookups are resolved eagerly against the address space at /// the time the user delegate executes; lookup failures throw /// so wiring errors surface at /// startup rather than at first request. This keeps the runtime path /// reflection-free and AOT/trim safe. /// /// /// Browse paths are forward-slash separated /// chains rooted at the manager's predefined nodes. Each segment may /// optionally carry a ns=N; namespace prefix to cross into a /// namespace other than the manager's own; segments without a prefix /// inherit the manager's first registered namespace index. /// /// /// /// builder.Node("Boilers/Boiler #1/PipeX001/ValveX001") /// .OnSimpleWrite(MyValveWriteHandler); /// /// builder.Node("ns=2;Methods/Increment") /// .As<MethodState>() /// .OnCallAsync(MyIncrementAsync); /// /// /// public interface INodeManagerBuilder { /// /// The system context active while the user's /// Configure delegate is executing. Useful for passing into /// any address-space helpers (e.g. NodeState.FindChild) /// that the user might call directly. /// ISystemContext Context { get; } /// /// The node manager whose graph is being wired. Exposed to support /// rare cases that need direct access (e.g. registering a /// dynamically generated node) without breaking out of the fluent /// chain. Use to /// obtain the synchronous facade when /// needed (e.g. when interacting with legacy callers). /// IAsyncNodeManager NodeManager { get; } /// /// Manager-level dispatch surface populated by the On* /// methods on the per-node builders. The owning node manager /// invokes this from its HistoryRead, HistoryUpdate, /// ConditionRefresh, and CreateMonitoredItems /// overrides; for nodes the dispatcher does not own a handler for, /// callers fall back to the base behavior. /// IFluentDispatcher Dispatcher { get; } /// /// Resolves a node by browse path against the manager's predefined /// nodes. Throws if the path does not resolve to exactly one node. /// /// /// Forward-slash separated chain. See /// the type-level remarks for the namespace-prefix syntax. /// /// A non-generic node builder for the resolved node. /// /// Thrown when the path is empty, ambiguous, or does not resolve. /// INodeBuilder Node(string browsePath); /// /// Strongly-typed sibling of that /// validates the resolved node is assignable to /// . /// /// /// Expected concrete derivative. /// /// See . /// /// Thrown if the node does not resolve or is not assignable to /// . /// INodeBuilder Node(string browsePath) where TState : NodeState; /// /// Resolves a node by absolute . Useful when /// the caller already holds an id (for example, one returned from /// the source-generated {Namespace}.NodeIds constants). /// INodeBuilder Node(NodeId nodeId); /// /// Strongly-typed sibling of . /// /// /// Expected concrete derivative. /// INodeBuilder Node(NodeId nodeId) where TState : NodeState; /// /// Resolves the unique node whose TypeDefinitionId /// matches . Useful for singleton /// instances such as HistoryServerCapabilities where the /// well-known type id is far more stable than the deployment-specific /// browse path. /// /// /// The type definition id of the instance to locate (typically a /// generated ObjectTypeIds.* or VariableTypeIds.* /// constant). /// /// /// /// — the id is null. /// — no instance carries that type definition. /// — more than one instance matches; supply a disambiguator via the overload. /// /// INodeBuilder NodeFromTypeId(NodeId typeDefinitionId); /// /// Like but disambiguates among /// multiple instances by matching /// against . /// /// See . /// /// Browse name of the instance to pick out. May be null, in /// which case the call behaves identically to the single-argument /// overload. /// /// /// Same conditions as plus /// when the disambiguator /// matches no candidate. /// INodeBuilder NodeFromTypeId(NodeId typeDefinitionId, QualifiedName browseName); /// /// Strongly-typed sibling of . /// /// /// Expected concrete derivative the resolved /// instance must be assignable to. /// /// /// As , plus /// if the instance is not /// assignable to . /// INodeBuilder NodeFromTypeId(NodeId typeDefinitionId) where TState : NodeState; /// /// Strongly-typed sibling of /// . /// /// See . INodeBuilder NodeFromTypeId(NodeId typeDefinitionId, QualifiedName browseName) where TState : NodeState; /// /// Resolves a variable node by browse path and returns a typed /// view that exposes /// simple Func / Action shaped /// OnRead/OnWrite overloads. /// /// /// CLR type carried by the variable's Value attribute. /// /// See . /// /// Thrown if the path does not resolve, or resolves to a node /// that is not a . /// IVariableBuilder Variable(string browsePath); /// /// Resolves a variable node by absolute /// and returns a typed /// view. /// /// /// CLR type carried by the variable's Value attribute. /// IVariableBuilder Variable(NodeId nodeId); /// /// Resolves the unique variable instance whose /// TypeDefinitionId matches /// and returns a typed /// view. Same disambiguation semantics as /// . /// /// /// CLR type carried by the variable's Value attribute. /// IVariableBuilder VariableFromTypeId(NodeId typeDefinitionId); /// /// Like but /// disambiguates among multiple instances by browse name. /// /// /// CLR type carried by the variable's Value attribute. /// IVariableBuilder VariableFromTypeId(NodeId typeDefinitionId, QualifiedName browseName); } }