using Beam.Abstractions; using HtmlAgilityPack; namespace Beam.Dynamic; /// /// Allows composition of different data providers to adapt to different types of data. /// /// public class ComposeDataProviders : IComposableDataProvider { public required IComposableDataProvider[] SelectWith { get; init; } public required IComposableDataProvider GetWith { get; init; } private ComposeDataProviders() {} public static ComposeDataProviders Create(IComposableDataProvider selectWith, IComposableDataProvider getWith) { return new ComposeDataProviders() { GetWith = getWith, SelectWith = [selectWith] }; } public static ComposeDataProviders Create(IComposableDataProvider[] selectWiths, IComposableDataProvider getWith) { return new ComposeDataProviders() { GetWith = getWith, SelectWith = selectWiths }; } /// /// Composes the data providers, first selecting a node with , then getting the data with . /// /// Throws when returns a null value. /// /// public T Get(HtmlDocument document) { var selected = Select(document); if (selected is null) throw new Exception("Selection operation failed."); return GetWith.Get(selected); } /// /// Uses the data provider to get the data from the supplied node. /// /// /// public T Get(HtmlNode node) { return GetWith.Get(node); } /// /// Uses the data provider to select a node from the supplied document. /// /// /// public HtmlNode? Select(HtmlDocument doc) { var selected = SelectWith[0].Select(doc); foreach(var provider in SelectWith.Skip(1)) { if (selected is null) return null; selected = provider.Select(selected); } return selected; } /// /// Uses the data provider to select a node from the supplied document. /// /// /// public HtmlNode? Select(HtmlNode node) { var selected = SelectWith[0].Select(node); foreach(var provider in SelectWith.Skip(1)) { if (selected is null) return null; selected = provider.Select(selected); } return selected; } }