using Microsoft.Extensions.DependencyInjection;
using StellaOps.AdvisoryAI.Remediation.ScmConnector;
using StellaOps.Plugin.Abstractions;
using StellaOps.Plugin.Abstractions.Capabilities;
namespace StellaOps.AdvisoryAI.Scm.Plugin.Unified;
///
/// Factory for creating unified SCM plugin adapters from existing connectors.
///
public sealed class ScmPluginAdapterFactory
{
private readonly ScmConnectorCatalog _catalog;
private readonly Dictionary _adapters = new(StringComparer.OrdinalIgnoreCase);
private readonly object _lock = new();
///
/// Creates a new factory instance.
///
/// The SCM connector catalog.
public ScmPluginAdapterFactory(ScmConnectorCatalog catalog)
{
_catalog = catalog ?? throw new ArgumentNullException(nameof(catalog));
}
///
/// Gets all available unified SCM plugins.
///
/// Connector options.
/// List of unified SCM plugins.
public IReadOnlyList GetAllPlugins(ScmConnectorOptions options)
{
var result = new List();
foreach (var plugin in _catalog.Plugins)
{
if (plugin.IsAvailable(options))
{
var adapter = GetOrCreateAdapter(plugin.ScmType, options);
if (adapter != null)
{
result.Add(adapter);
}
}
}
return result;
}
///
/// Gets a unified SCM plugin by SCM type.
///
/// SCM type identifier.
/// Connector options.
/// Unified SCM plugin, or null if not found.
public IPlugin? GetPlugin(string scmType, ScmConnectorOptions options)
{
return GetOrCreateAdapter(scmType, options);
}
///
/// Gets a unified SCM plugin that can handle the given repository URL.
///
/// Repository URL to handle.
/// Connector options.
/// Unified SCM plugin, or null if not found.
public IPlugin? GetPluginForRepository(string repositoryUrl, ScmConnectorOptions options)
{
var plugin = _catalog.Plugins.FirstOrDefault(p => p.CanHandle(repositoryUrl));
if (plugin == null)
return null;
return GetOrCreateAdapter(plugin.ScmType, options);
}
///
/// Gets the SCM capability for a connector.
///
/// SCM type identifier.
/// Connector options.
/// SCM capability, or null if not found.
public IScmCapability? GetCapability(string scmType, ScmConnectorOptions options)
{
return GetOrCreateAdapter(scmType, options);
}
private ScmPluginAdapter? GetOrCreateAdapter(string scmType, ScmConnectorOptions options)
{
lock (_lock)
{
if (_adapters.TryGetValue(scmType, out var existing))
{
return existing;
}
var plugin = _catalog.Plugins.FirstOrDefault(
p => p.ScmType.Equals(scmType, StringComparison.OrdinalIgnoreCase));
if (plugin == null || !plugin.IsAvailable(options))
{
return null;
}
var connector = _catalog.GetConnector(scmType, options);
if (connector == null)
{
return null;
}
var adapter = new ScmPluginAdapter(connector, plugin, options);
_adapters[scmType] = adapter;
return adapter;
}
}
}
///
/// Extension methods for registering unified SCM plugin services.
///
public static class ScmPluginAdapterExtensions
{
///
/// Adds unified SCM plugin adapter services to the service collection.
///
/// Service collection.
/// Service collection for chaining.
public static IServiceCollection AddUnifiedScmPlugins(this IServiceCollection services)
{
services.AddSingleton();
return services;
}
}