/* ========================================================================
* 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);
}
}