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;
}
}