using Microsoft.Extensions.Logging;
using StellaOps.Scanner.Surface.Models;
namespace StellaOps.Scanner.Surface.Discovery;
///
/// Registry for surface entry and entry point collectors.
///
public interface ISurfaceEntryRegistry
{
/// Registers a surface entry collector.
void RegisterCollector(ISurfaceEntryCollector collector);
/// Registers an entry point collector.
void RegisterEntryPointCollector(IEntryPointCollector collector);
/// Gets all registered surface entry collectors.
IReadOnlyList GetCollectors();
/// Gets all registered entry point collectors.
IReadOnlyList GetEntryPointCollectors();
/// Gets collectors that support the specified surface type.
IReadOnlyList GetCollectorsForType(SurfaceType type);
/// Gets entry point collectors that support the specified language.
IReadOnlyList GetEntryPointCollectorsForLanguage(string language);
}
///
/// Default implementation of surface entry registry.
///
public sealed class SurfaceEntryRegistry : ISurfaceEntryRegistry
{
private readonly List _collectors = [];
private readonly List _entryPointCollectors = [];
private readonly ILogger _logger;
private readonly object _lock = new();
public SurfaceEntryRegistry(ILogger logger)
{
_logger = logger;
}
public void RegisterCollector(ISurfaceEntryCollector collector)
{
ArgumentNullException.ThrowIfNull(collector);
lock (_lock)
{
if (_collectors.Any(c => c.CollectorId == collector.CollectorId))
{
_logger.LogWarning("Collector {CollectorId} already registered, skipping", collector.CollectorId);
return;
}
_collectors.Add(collector);
_logger.LogDebug("Registered surface collector: {CollectorId}", collector.CollectorId);
}
}
public void RegisterEntryPointCollector(IEntryPointCollector collector)
{
ArgumentNullException.ThrowIfNull(collector);
lock (_lock)
{
if (_entryPointCollectors.Any(c => c.CollectorId == collector.CollectorId))
{
_logger.LogWarning("Entry point collector {CollectorId} already registered, skipping", collector.CollectorId);
return;
}
_entryPointCollectors.Add(collector);
_logger.LogDebug("Registered entry point collector: {CollectorId}", collector.CollectorId);
}
}
public IReadOnlyList GetCollectors()
{
lock (_lock) return [.. _collectors];
}
public IReadOnlyList GetEntryPointCollectors()
{
lock (_lock) return [.. _entryPointCollectors];
}
public IReadOnlyList GetCollectorsForType(SurfaceType type)
{
lock (_lock)
{
return [.. _collectors.Where(c => c.SupportedTypes.Contains(type))];
}
}
public IReadOnlyList GetEntryPointCollectorsForLanguage(string language)
{
ArgumentException.ThrowIfNullOrWhiteSpace(language);
lock (_lock)
{
return [.. _entryPointCollectors.Where(c =>
c.SupportedLanguages.Contains(language, StringComparer.OrdinalIgnoreCase))];
}
}
}