// // Copyright (c) StellaOps. Licensed under BUSL-1.1. // namespace StellaOps.Facet; /// /// Classifies files into facets based on selectors. /// public sealed class FacetClassifier { private readonly List<(IFacet Facet, GlobMatcher Matcher)> _facetMatchers; /// /// Initializes a new instance of the class. /// /// Facets to classify against (will be sorted by priority). public FacetClassifier(IEnumerable facets) { ArgumentNullException.ThrowIfNull(facets); // Sort by priority (lowest first = highest priority) _facetMatchers = facets .OrderBy(f => f.Priority) .Select(f => (f, GlobMatcher.ForFacet(f))) .ToList(); } /// /// Creates a classifier using built-in facets. /// public static FacetClassifier Default { get; } = new(BuiltInFacets.All); /// /// Classify a file path to a facet. /// /// The file path to classify. /// The matching facet or null if no match. public IFacet? Classify(string path) { ArgumentNullException.ThrowIfNull(path); // First matching facet wins (ordered by priority) foreach (var (facet, matcher) in _facetMatchers) { if (matcher.IsMatch(path)) { return facet; } } return null; } /// /// Classify a file and return the facet ID. /// /// The file path to classify. /// The facet ID or null if no match. public string? ClassifyToId(string path) => Classify(path)?.FacetId; /// /// Classify multiple files efficiently. /// /// The file paths to classify. /// Dictionary from facet ID to matched paths. public Dictionary> ClassifyMany(IEnumerable paths) { ArgumentNullException.ThrowIfNull(paths); var result = new Dictionary>(); foreach (var path in paths) { var facet = Classify(path); if (facet is not null) { if (!result.TryGetValue(facet.FacetId, out var list)) { list = []; result[facet.FacetId] = list; } list.Add(path); } } return result; } }