Files
git.stella-ops.org/src/__Libraries/StellaOps.Facet/FacetClassifier.cs

92 lines
2.7 KiB
C#

// <copyright file="FacetClassifier.cs" company="StellaOps">
// Copyright (c) StellaOps. Licensed under BUSL-1.1.
// </copyright>
namespace StellaOps.Facet;
/// <summary>
/// Classifies files into facets based on selectors.
/// </summary>
public sealed class FacetClassifier
{
private readonly List<(IFacet Facet, GlobMatcher Matcher)> _facetMatchers;
/// <summary>
/// Initializes a new instance of the <see cref="FacetClassifier"/> class.
/// </summary>
/// <param name="facets">Facets to classify against (will be sorted by priority).</param>
public FacetClassifier(IEnumerable<IFacet> facets)
{
ArgumentNullException.ThrowIfNull(facets);
// Sort by priority (lowest first = highest priority)
_facetMatchers = facets
.OrderBy(f => f.Priority)
.Select(f => (f, GlobMatcher.ForFacet(f)))
.ToList();
}
/// <summary>
/// Creates a classifier using built-in facets.
/// </summary>
public static FacetClassifier Default { get; } = new(BuiltInFacets.All);
/// <summary>
/// Classify a file path to a facet.
/// </summary>
/// <param name="path">The file path to classify.</param>
/// <returns>The matching facet or null if no match.</returns>
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;
}
/// <summary>
/// Classify a file and return the facet ID.
/// </summary>
/// <param name="path">The file path to classify.</param>
/// <returns>The facet ID or null if no match.</returns>
public string? ClassifyToId(string path)
=> Classify(path)?.FacetId;
/// <summary>
/// Classify multiple files efficiently.
/// </summary>
/// <param name="paths">The file paths to classify.</param>
/// <returns>Dictionary from facet ID to matched paths.</returns>
public Dictionary<string, List<string>> ClassifyMany(IEnumerable<string> paths)
{
ArgumentNullException.ThrowIfNull(paths);
var result = new Dictionary<string, List<string>>();
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;
}
}