/* ======================================================================== * 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/ * ======================================================================*/ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Opc.Ua.Client; namespace Opc.Ua { /// /// Extensions for lru node cache /// public static class LruNodeCacheExtensions { /// /// Get node from cache /// public static ValueTask GetNodeAsync( this ILruNodeCache cache, ExpandedNodeId expandedNodeId, CancellationToken ct = default) { var nodeId = ExpandedNodeId.ToNodeId(expandedNodeId, cache.NamespaceUris); return cache.GetNodeAsync(nodeId, ct); } /// /// Get nodes from cache /// public static ValueTask> GetNodesAsync( this ILruNodeCache cache, IReadOnlyList expandedNodeIds, CancellationToken ct = default) { var nodeIds = expandedNodeIds .Select(expandedNodeId => ExpandedNodeId.ToNodeId( expandedNodeId, cache.NamespaceUris)) .ToList(); return cache.GetNodesAsync(nodeIds, ct); } /// /// Get node from cache /// public static ValueTask GetValueAsync( this ILruNodeCache cache, ExpandedNodeId expandedNodeId, CancellationToken ct = default) { var nodeId = ExpandedNodeId.ToNodeId(expandedNodeId, cache.NamespaceUris); return cache.GetValueAsync(nodeId, ct); } /// /// Get nodes from cache /// public static ValueTask> GetValuesAsync( this ILruNodeCache cache, IReadOnlyList expandedNodeIds, CancellationToken ct = default) { var nodeIds = expandedNodeIds .Select(expandedNodeId => ExpandedNodeId.ToNodeId( expandedNodeId, cache.NamespaceUris)) .ToList(); return cache.GetValuesAsync(nodeIds, ct); } /// /// Get references from cache /// public static ValueTask> GetReferencesAsync( this ILruNodeCache cache, ExpandedNodeId expandedNodeId, NodeId referenceTypeId, bool isInverse, bool includeSubtypes = true, CancellationToken ct = default) { var nodeId = ExpandedNodeId.ToNodeId(expandedNodeId, cache.NamespaceUris); return cache.GetReferencesAsync( nodeId, referenceTypeId, isInverse, includeSubtypes, ct); } /// /// Get references from cache /// public static ValueTask> GetReferencesAsync( this ILruNodeCache cache, IReadOnlyList expandedNodeIds, IReadOnlyList referenceTypeIds, bool isInverse, bool includeSubtypes = true, CancellationToken ct = default) { var nodeIds = expandedNodeIds .Select(expandedNodeId => ExpandedNodeId.ToNodeId( expandedNodeId, cache.NamespaceUris)) .ToList(); return cache.GetReferencesAsync( nodeIds, referenceTypeIds, isInverse, includeSubtypes, ct); } /// /// Get references from cache /// public static ValueTask> GetReferencesAsync( this ILruNodeCache cache, IReadOnlyList expandedNodeIds, NodeId referenceTypeId, bool isInverse, bool includeSubtypes = true, CancellationToken ct = default) { var nodeIds = expandedNodeIds .Select(expandedNodeId => ExpandedNodeId.ToNodeId( expandedNodeId, cache.NamespaceUris)) .ToList(); return cache.GetReferencesAsync( nodeIds, [referenceTypeId], isInverse, includeSubtypes, ct); } /// /// Get super type from cache /// public static ValueTask GetSuperTypeAsync( this ILruNodeCache cache, ExpandedNodeId expandedNodeId, CancellationToken ct = default) { var nodeId = ExpandedNodeId.ToNodeId(expandedNodeId, cache.NamespaceUris); return cache.GetSuperTypeAsync(nodeId, ct); } /// /// Is the subTypeId a subtype of the superTypeId? /// public static bool IsTypeOf( this ILruNodeCache cache, ExpandedNodeId subTypeId, NodeId superTypeId) { var nodeId = ExpandedNodeId.ToNodeId(subTypeId, cache.NamespaceUris); return cache.IsTypeOf(nodeId, superTypeId); } /// /// Returns the BuiltInType type for the DataTypeId. /// public static async Task GetBuiltInTypeAsync( this ILruNodeCache cache, NodeId datatypeId, CancellationToken ct = default) { NodeId typeId = datatypeId; while (!NodeId.IsNull(typeId)) { if (typeId.NamespaceIndex == 0 && typeId.IdType == IdType.Numeric) { var id = (BuiltInType)(int)(uint)typeId.Identifier; if (id is > BuiltInType.Null and <= BuiltInType.Enumeration and not BuiltInType.DiagnosticInfo) { return id; } } typeId = await cache.GetSuperTypeAsync(typeId, ct).ConfigureAwait(false); } return BuiltInType.Null; } } }