using ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy; namespace ZB.MOM.WW.MxGateway.Client; /// /// One node in a lazy-loaded Galaxy browse tree. Holds the underlying /// and exposes to fetch /// its direct children on demand. Expansion is one-shot: a second call is a /// no-op. Pagination of large sibling sets is handled internally. /// public sealed class LazyBrowseNode { private readonly GalaxyRepositoryClient _client; private readonly BrowseChildrenOptions _options; private readonly List _children = []; private bool _isExpanded; internal LazyBrowseNode( GalaxyRepositoryClient client, GalaxyObject @object, bool hasChildrenHint, BrowseChildrenOptions options) { _client = client; Object = @object; HasChildrenHint = hasChildrenHint; _options = options; } /// The underlying Galaxy object for this node. public GalaxyObject Object { get; } /// True when the server reports this node has at least one matching descendant. public bool HasChildrenHint { get; } /// Direct children loaded by ; empty until then. public IReadOnlyList Children => _children; /// True after the first call completes. public bool IsExpanded => _isExpanded; /// /// Fetches direct children from the gateway and populates . /// Idempotent: subsequent calls are no-ops. /// /// Token to observe for cancellation. public async Task ExpandAsync(CancellationToken cancellationToken = default) { if (_isExpanded) { return; } string pageToken = string.Empty; HashSet seenPageTokens = new(StringComparer.Ordinal); do { BrowseChildrenRequest request = GalaxyRepositoryClient.BuildBrowseChildrenRequest(_options); request.ParentGobjectId = Object.GobjectId; request.PageToken = pageToken; BrowseChildrenReply reply = await _client .BrowseChildrenRawAsync(request, cancellationToken) .ConfigureAwait(false); for (int i = 0; i < reply.Children.Count; i++) { bool hint = i < reply.ChildHasChildren.Count && reply.ChildHasChildren[i]; _children.Add(new LazyBrowseNode(_client, reply.Children[i], hint, _options)); } pageToken = reply.NextPageToken; if (!string.IsNullOrWhiteSpace(pageToken) && !seenPageTokens.Add(pageToken)) { throw new MxGatewayException( $"Galaxy BrowseChildren returned a repeated page token '{pageToken}'."); } } while (!string.IsNullOrWhiteSpace(pageToken)); _isExpanded = true; } }