This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace LehrerApp.Templating;
|
||||
|
||||
public static class TemplateDataResolver
|
||||
{
|
||||
public static IReadOnlyList<string> ValidateConstants(TemplateManifest manifest)
|
||||
{
|
||||
var issues = new List<string>();
|
||||
var definitions = manifest.Placeholders.GroupBy(x => x.Name, StringComparer.Ordinal)
|
||||
.ToDictionary(x => x.Key, x => x.First(), StringComparer.Ordinal);
|
||||
foreach (var constant in manifest.Placeholders.Where(x => x.IsConstant))
|
||||
{
|
||||
try
|
||||
{
|
||||
ConstantValue(constant);
|
||||
if (constant.Type is not (PlaceholderType.Text or PlaceholderType.Multiline)) continue;
|
||||
foreach (var reference in TemplateRichText.UsedPlaceholders(constant.ConstantValue ?? ""))
|
||||
{
|
||||
if (!definitions.TryGetValue(reference, out var target))
|
||||
issues.Add($"Konstanter Text „{constant.Name}“ verwendet den nicht deklarierten Platzhalter „{reference}“.");
|
||||
else if (target.IsConstant)
|
||||
issues.Add($"Konstanter Text „{constant.Name}“ darf nur externe Platzhalter verwenden; „{reference}“ ist ebenfalls konstant.");
|
||||
else if (target.Type is not (PlaceholderType.Text or PlaceholderType.Multiline
|
||||
or PlaceholderType.Date or PlaceholderType.Number))
|
||||
issues.Add($"Eingebetteter Platzhalter „{reference}“ hat keinen textuell darstellbaren Typ.");
|
||||
}
|
||||
}
|
||||
catch (InvalidDataException ex) { issues.Add(ex.Message); }
|
||||
}
|
||||
return issues;
|
||||
}
|
||||
|
||||
public static IReadOnlyDictionary<string, PlaceholderValue> Resolve(TemplateManifest manifest,
|
||||
IReadOnlyDictionary<string, PlaceholderValue> externalValues)
|
||||
{
|
||||
var result = new Dictionary<string, PlaceholderValue>(externalValues, StringComparer.Ordinal);
|
||||
foreach (var definition in manifest.Placeholders.Where(x => x.IsConstant))
|
||||
result[definition.Name] = ConstantValue(definition);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PlaceholderValue ConstantValue(PlaceholderDefinition definition)
|
||||
{
|
||||
var raw = definition.ConstantValue ?? "";
|
||||
return definition.Type switch
|
||||
{
|
||||
PlaceholderType.Text => new TextValue(raw),
|
||||
PlaceholderType.Multiline => new MultilineValue(raw),
|
||||
PlaceholderType.Date => new DateValue(ParseDate(definition, raw)),
|
||||
PlaceholderType.Number => new NumberValue(ParseNumber(definition, raw)),
|
||||
_ => throw new InvalidDataException(
|
||||
$"Platzhalter „{definition.Name}“ vom Typ {definition.Type} kann keinen konstanten Textwert verwenden."),
|
||||
};
|
||||
}
|
||||
|
||||
private static DateOnly ParseDate(PlaceholderDefinition definition, string raw)
|
||||
{
|
||||
if (DateOnly.TryParse(raw, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date)
|
||||
|| DateOnly.TryParse(raw, CultureInfo.GetCultureInfo("de-DE"), DateTimeStyles.None, out date)) return date;
|
||||
throw Error(definition, "Datum, z. B. 2026-08-30");
|
||||
}
|
||||
|
||||
private static decimal ParseNumber(PlaceholderDefinition definition, string raw)
|
||||
{
|
||||
if (decimal.TryParse(raw, NumberStyles.Number, CultureInfo.InvariantCulture, out var number)
|
||||
|| decimal.TryParse(raw, NumberStyles.Number, CultureInfo.GetCultureInfo("de-DE"), out number)) return number;
|
||||
throw Error(definition, "Zahl");
|
||||
}
|
||||
|
||||
private static InvalidDataException Error(PlaceholderDefinition definition, string expected) =>
|
||||
new($"Konstanter Wert für „{definition.Name}“ ist ungültig; erwartet wird: {expected}.");
|
||||
}
|
||||
Reference in New Issue
Block a user