using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Scraping.Selectors;
namespace Scraping.Rules
{
/// not the same as LocatedRuleSet. IRuleClass only acts upon 1 product item at a time. RuleFamily returns many product items
internal class RuleFamily
{
public By RowsLocator;
public IRuleClass Rules;
public IEnumerable GetRows(WebElement rootWebElement)
=> rootWebElement.FindElements(RowsLocator).ToList();
}
internal interface IRuleClass { void Run(WebElement element, T productItem); }
internal class BasicRule : IRuleClass
{
public Action Action;
public BasicRule() { }
public BasicRule(Action action) => Action = action;
// this is only place that rules actions are actually run
// error handling, logging, et al. belong here
public void Run(WebElement element, T productItem) => Action(element, productItem);
}
internal class RuleSet : IRuleClass, IEnumerable>
{
private List> rules { get; } = new List>();
public void Add(IRuleClass ruleClass) => rules.Add(ruleClass);
public void Add(Action action) => rules.Add(new BasicRule(action));
public void AddRange(IEnumerable> rules) => this.rules.AddRange(rules);
public IEnumerator> GetEnumerator() => rules.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => rules.GetEnumerator();
public virtual void Run(WebElement element, T productItem)
{
foreach (var rule in rules)
rule.Run(element, productItem);
}
}
/// LocatedRuleSet loops through found items. When it's 0 or 1, LocatedRuleSet is an easy way to parse only if exists
internal class LocatedRuleSet : RuleSet
{
public By ElementsLocator;
public LocatedRuleSet(By elementsLocator) => ElementsLocator = elementsLocator;
public override void Run(WebElement parentElement, T productItem)
{
foreach (var childElements in parentElement.FindElements(ElementsLocator))
base.Run(childElements, productItem);
}
}
}