92 lines
2.7 KiB
C#
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;
|
|
}
|
|
}
|