Files
api-generator/Generator/DataSource/Yaml/YamlBuilder.cs
2025-10-11 13:08:09 +02:00

164 lines
4.7 KiB
C#

using System.Text;
using Core;
using Core.Helpers;
using Core.Yaml;
using MoreLinq;
namespace Generator.DataSource.Yaml;
public class YamlBuilder
{
private OpenApiYaml _file;
private bool _isSubNode;
private readonly string _configIdentifier;
private readonly Dictionary<string, YamlConfig> _configs;
private readonly OpenApiYamlExtractor _extractor;
public YamlBuilder(string filePath, string configIdentifier)
{
_isSubNode = false;
_configIdentifier = configIdentifier;
_file = new OpenApiYaml(filePath);
_configs = new Dictionary<string, YamlConfig>();
_extractor = new OpenApiYamlExtractor();
}
/// <summary>
/// Adds all raw references to the object to build
/// </summary>
public void AddReferences()
{
var scopedRefs = _extractor.ExtractScopedRefs(_file.Location.ToString());
var allRefs = _extractor.ExtractAllRefs(_file.Location.ToString());
_file.ScopedRefs = scopedRefs;
_file.OutScopedRefs = allRefs;
_file.OutScopedRefs.ExceptWith(scopedRefs);
}
/// <summary>
/// Attributes the dedicated config file to the object to build
/// </summary>
public void SelectConfig()
{
if (_configs.ContainsKey(_file.Location.GetFileName()))
{
_file.Config = _configs[_file.Location.GetFileName()];
}
else
{
throw new Exception($"{_file.Location} cannot be generated. You either made a typo " +
$"or forgot to register file in {GetConfig(_file.Location)}");
}
}
/// <summary>
/// Adds all built schemas to the object to build
/// </summary>
public void AddSchema()
{
using var enumerator = _file.ScopedRefs.GetEnumerator();
while (enumerator.MoveNext())
{
var loc = new Location(enumerator.Current);
var fileName = loc.GetFileName();
if(!_configs.ContainsKey(fileName)) continue;
var schema = _isSubNode ?
_extractor.ExtractNode(loc.ToString())
: CreateSubNode(loc.ToString());
schema.Config = _configs[fileName];
_file.ReferencedSchemas.Add(schema);
}
}
/// <summary>
/// Adds the models that will be ignored to the object to build
/// </summary>
public void AddIgnoredModels()
{
foreach (var reference in _file.Refs)
{
var loc = new Location(reference);
var schema = _extractor.ExtractNode(loc.ToString());
_file.IgnoredModels.UnionWith(schema.Models);
}
}
/// <summary>
/// Simply output the object to build
/// </summary>
/// <returns></returns>
public OpenApiYaml Create() => _file;
/// <summary>
/// Loads the object to build
/// </summary>
public void LoadSpec()
{
_file = _extractor.ExtractNode(_file.Location.ToString());
_file.Openapi = _file.Openapi;
if (_file.Info != null) _file.Info = new Dictionary<string, object>(_file.Info);
_file.Tags = _file.Tags == null ? new List<object>() : [.._file.Tags];
}
/// <summary>
/// Load all the found config files into the builder
/// </summary>
public void LoadConfigs()
{
LoadConfig(_file.Location);
foreach (var reference in _file.Refs) LoadConfig(new Location(reference));
}
private void LoadConfig(Location path)
{
var configPath = GetConfig(path)?.ToString();
if (configPath == null || _configs.ContainsKey(path.GetFileName())) return;
_extractor.LoadConfigs(configPath)
.ForEach(c => _configs.TryAdd(c.Key, c.Value));
}
private void SetForSubNode() => _isSubNode = true;
private OpenApiYaml CreateSubNode(string path)
{
var yamlBuilder = new YamlBuilder(path, _configIdentifier);
yamlBuilder.SetForSubNode();
yamlBuilder.LoadSpec();
yamlBuilder.AddReferences();
yamlBuilder.LoadConfigs();
yamlBuilder.AddSchema();
yamlBuilder.AddIgnoredModels();
return yamlBuilder.Create();
}
private Location? GetConfig(Location loc)
{
var spec = loc.GetFolder();
var pathItems = loc.Path.Split(['/', '\\']);
pathItems[^1] = spec + _configIdentifier;
var builder = new StringBuilder();
builder.AppendJoin("/", pathItems);
var configPath = builder.ToString();
try
{
PathHelper.CheckPathValidity(configPath);
}
catch (FileNotFoundException)
{
return null;
}
return new Location(configPath);
}
}