/* ======================================================================== * 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.Threading; using System.Threading.Tasks; namespace Opc.Ua.Client.FileSystem { /// /// Strongly-typed handle to a single OPC UA FileDirectoryType /// instance. Mirrors . /// public sealed class UaDirectoryInfo : UaFileSystemInfo { internal UaDirectoryInfo( FileSystemClient owner, UaDirectoryInfo? parent, NodeId nodeId, QualifiedName browseName, IReadOnlyList segments) : base(owner, parent, nodeId, browseName, segments) { Proxy = new FileDirectoryTypeClient( owner.Session, nodeId, owner.Session.MessageContext.Telemetry); } /// public override bool IsDirectory => true; /// /// The underlying proxy. /// public FileDirectoryTypeClient Proxy { get; } /// public override ValueTask RefreshAsync(CancellationToken ct = default) { // FileDirectoryType has no scalar properties to refresh; the // child-set is inherently lazy via EnumerateAsync. return default; } /// /// Enumerates the immediate children of this directory. /// Returns both files () and /// sub-directories () in browse /// order. /// public IAsyncEnumerable EnumerateAsync( CancellationToken ct = default) { return Owner.EnumerateChildrenAsync(this, includeFiles: true, includeDirectories: true, ct); } /// /// Enumerates only the file children of this directory. /// public async IAsyncEnumerable EnumerateFilesAsync( [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken ct = default) { await foreach (UaFileSystemInfo child in Owner .EnumerateChildrenAsync(this, includeFiles: true, includeDirectories: false, ct) .ConfigureAwait(false)) { if (child is UaFileInfo file) { yield return file; } } } /// /// Enumerates only the directory children of this directory. /// public async IAsyncEnumerable EnumerateDirectoriesAsync( [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken ct = default) { await foreach (UaFileSystemInfo child in Owner .EnumerateChildrenAsync(this, includeFiles: false, includeDirectories: true, ct) .ConfigureAwait(false)) { if (child is UaDirectoryInfo dir) { yield return dir; } } } /// /// Creates a new sub-directory in this directory. /// /// The new directory's leaf name. Must NOT /// include a namespace prefix or a path separator. /// Cancellation token. public ValueTask CreateSubdirectoryAsync( string name, CancellationToken ct = default) { return Owner.CreateDirectoryInAsync(this, name, ct); } /// /// Creates a new empty file in this directory. The server is /// asked NOT to immediately open the file /// (requestFileOpen: false); call /// /// when you are ready to write. /// /// The new file's leaf name. Must NOT /// include a namespace prefix or a path separator. /// Cancellation token. public ValueTask CreateFileAsync( string name, CancellationToken ct = default) { return Owner.CreateFileInAsync(this, name, ct); } /// /// Deletes this directory. When /// is false the directory /// must be empty (an is /// thrown otherwise). When true the server's recursive /// Delete primitive is invoked exactly once (no /// client-side traversal). /// public ValueTask DeleteAsync( bool recursive, CancellationToken ct = default) { return Owner.DeleteCoreAsync(this, recursive, ct); } } }