1
0
Fork 0
forked from aly/qstbak
qstbak/Questionable/Questionable.Validation/SchemaRegistrar.cs
2026-08-17 20:29:32 +10:00

118 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Json.Schema;
using Questionable.FatePaths;
using Questionable.GatheringPaths;
using Questionable.Model;
using Questionable.QuestPaths;
using Questionable.SeasonalDutyPaths;
namespace Questionable.Validation;
internal sealed class SchemaRegistrar
{
private const string BaseUri = "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main";
private static readonly IReadOnlyList<(string FileName, string Uri, Func<Stream> Embedded)> Catalog = new global::_003C_003Ez__ReadOnlyArray<(string, string, Func<Stream>)>(new(string, string, Func<Stream>)[10]
{
("common-aethernetshard.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-aethernetshard.json", () => AssemblyModelLoader.CommonAethernetShard),
("common-aetheryte.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-aetheryte.json", () => AssemblyModelLoader.CommonAetheryte),
("common-classjob.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-classjob.json", () => AssemblyModelLoader.CommonClassJob),
("common-completionflags.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-completionflags.json", () => AssemblyModelLoader.CommonCompletionFlags),
("common-requiredvariables.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-requiredvariables.json", () => AssemblyModelLoader.CommonRequiredVariables),
("common-vector3.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-vector3.json", () => AssemblyModelLoader.CommonVector3),
("quest-v1.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/QuestPaths/quest-v1.json", () => AssemblyQuestLoader.QuestSchema),
("fatedefinition-v1.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/FatePaths/fatedefinition-v1.json", () => AssemblyFateDefinitionLoader.FateDefinitionSchema),
("gatheringlocation-v1.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/GatheringPaths/gatheringlocation-v1.json", () => AssemblyGatheringLocationLoader.GatheringSchema),
("seasonaldutydefinition-v1.json", "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/SeasonalDutyPaths/seasonaldutydefinition-v1.json", () => AssemblySeasonalDutyDefinitionLoader.SeasonalDutyDefinitionSchema)
});
private readonly SchemaRegistry _registry = new SchemaRegistry();
private readonly Dictionary<string, JsonSchema> _schemas = new Dictionary<string, JsonSchema>();
private readonly object _lock = new object();
private bool _built;
public void EnsureBuilt()
{
if (_built)
{
return;
}
lock (_lock)
{
if (_built)
{
return;
}
BuildOptions buildOptions = new BuildOptions
{
SchemaRegistry = _registry
};
DirectoryInfo projectRoot = FindProjectRoot();
foreach (var (fileName, key, embedded) in Catalog)
{
_schemas[key] = Build(fileName, embedded, projectRoot, buildOptions);
}
_built = true;
}
}
public JsonSchema Get(string uri)
{
EnsureBuilt();
if (!_schemas.TryGetValue(uri, out JsonSchema value))
{
throw new InvalidOperationException("schema not registered: " + uri);
}
return value;
}
private static JsonSchema Build(string fileName, Func<Stream> embedded, DirectoryInfo? projectRoot, BuildOptions buildOptions)
{
if (projectRoot != null)
{
try
{
string text = Directory.EnumerateFiles(projectRoot.FullName, fileName, SearchOption.AllDirectories).FirstOrDefault();
if (text != null)
{
return JsonSchema.FromText(File.ReadAllText(text), buildOptions);
}
}
catch
{
}
}
using StreamReader streamReader = new StreamReader(embedded());
return JsonSchema.FromText(streamReader.ReadToEnd(), buildOptions);
}
private static DirectoryInfo? FindProjectRoot()
{
try
{
string location = Assembly.GetExecutingAssembly().Location;
if (string.IsNullOrEmpty(location))
{
return null;
}
for (DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(location) ?? location); directoryInfo != null; directoryInfo = directoryInfo.Parent)
{
if (directoryInfo.GetDirectories("QuestPaths", SearchOption.TopDirectoryOnly).Length != 0 || directoryInfo.GetDirectories("Questionable.Model", SearchOption.TopDirectoryOnly).Length != 0 || directoryInfo.GetDirectories("Questionable", SearchOption.TopDirectoryOnly).Length != 0)
{
return directoryInfo;
}
}
}
catch
{
}
return null;
}
}