qstbak/Questionable/Questionable.Validation.Validators/DefinitionSchemaValidator.cs
2026-08-17 20:29:32 +10:00

102 lines
2.8 KiB
C#

using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Text.Json.Nodes;
using Json.Schema;
namespace Questionable.Validation.Validators;
internal abstract class DefinitionSchemaValidator : IDefinitionSchemaValidator
{
protected const string BaseUri = "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main";
private readonly SchemaRegistrar _schemaRegistrar;
private readonly Dictionary<ushort, JsonNode> _nodes = new Dictionary<ushort, JsonNode>();
private JsonSchema? _schema;
protected abstract EPathType PathType { get; }
protected abstract string MainSchemaUri { get; }
protected DefinitionSchemaValidator(SchemaRegistrar schemaRegistrar)
{
_schemaRegistrar = schemaRegistrar;
}
public void Enqueue(ushort id, JsonNode node)
{
_nodes[id] = node;
}
public void Reset()
{
_nodes.Clear();
}
public IEnumerable<ValidationIssue> Validate()
{
if (_nodes.Count == 0)
{
yield break;
}
if (_schema == null)
{
_schema = _schemaRegistrar.Get(MainSchemaUri);
}
foreach (var (id, node) in _nodes)
{
foreach (ValidationIssue item in ValidateImmediate(id, node))
{
yield return item;
}
}
}
public List<ValidationIssue> ValidateImmediate(ushort id, JsonNode node)
{
if (_schema == null)
{
_schema = _schemaRegistrar.Get(MainSchemaUri);
}
EvaluationResults evaluationResults = _schema.Evaluate(JsonSerializer.SerializeToElement(node), new EvaluationOptions
{
Culture = CultureInfo.InvariantCulture,
OutputFormat = OutputFormat.Hierarchical
});
if (evaluationResults.IsValid)
{
return new List<ValidationIssue>();
}
List<SchemaValidationHelper.ParsedError> list = new List<SchemaValidationHelper.ParsedError>();
SchemaValidationHelper.CollectLeafErrors(evaluationResults, list);
if (list.Count == 0)
{
int num = 1;
List<ValidationIssue> list2 = new List<ValidationIssue>(num);
CollectionsMarshal.SetCount(list2, num);
CollectionsMarshal.AsSpan(list2)[0] = new ValidationIssue
{
PathType = PathType,
Id = id.ToString(CultureInfo.InvariantCulture),
Location = null,
Type = EIssueType.InvalidJsonSchema,
Severity = EIssueSeverity.Error,
Description = "JSON schema validation failed"
};
return list2;
}
return list.Select((SchemaValidationHelper.ParsedError error) => new ValidationIssue
{
PathType = PathType,
Id = id.ToString(CultureInfo.InvariantCulture),
Location = (string.IsNullOrEmpty(error.PropertyPath) ? null : error.PropertyPath),
Type = EIssueType.InvalidJsonSchema,
Severity = EIssueSeverity.Error,
Description = (string.IsNullOrEmpty(error.PropertyPath) ? error.Message : (error.PropertyPath + ": " + error.Message))
}).ToList();
}
}