First attempt at dependency validation
This commit is contained in:
parent
11ba80b34b
commit
51ec6a480d
@ -9,7 +9,7 @@ public class CharacterTemplate : SzfObject
|
||||
public string GameSystem { get; set; } = string.Empty;
|
||||
public List<RequiredDatasetReference> RequiredDatasets { get; set; } = new();
|
||||
public List<TemplateSection> Sections { get; set; } = new();
|
||||
|
||||
|
||||
public override void PopulateFromMetadata(Dictionary<string, SzfField> metadata)
|
||||
{
|
||||
base.PopulateFromMetadata(metadata);
|
||||
@ -184,6 +184,44 @@ public class CharacterTemplate : SzfObject
|
||||
if (string.IsNullOrWhiteSpace(GameSystem))
|
||||
result.AddError("GameSystem is required for CharacterTemplate");
|
||||
|
||||
// NEW: Validate resolved datasets
|
||||
foreach (var reqDatasetRef in RequiredDatasets)
|
||||
{
|
||||
if (reqDatasetRef.Reference == null)
|
||||
{
|
||||
result.AddError($"Required dataset alias '{reqDatasetRef.Alias}' has a null reference.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reqDatasetRef.ResolvedDataset == null)
|
||||
{
|
||||
result.AddWarning(
|
||||
$"Required dataset for alias '{reqDatasetRef.Alias}' (GUID: {reqDatasetRef.Reference.Guid}) could not be resolved or loaded.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Optionally, perform a deeper validation of the resolved dataset.
|
||||
// For example, if the template expects specific entries or fields in the dataset:
|
||||
// if (!reqDatasetRef.ResolvedDataset.Entries.Any(e => e.Name == "ExpectedEntry"))
|
||||
// {
|
||||
// result.AddWarning($"Resolved dataset for '{reqDatasetRef.Alias}' is missing 'ExpectedEntry'.");
|
||||
// }
|
||||
|
||||
// Also, you can run the resolved dataset's own validation:
|
||||
var datasetValidation = reqDatasetRef.ResolvedDataset.Validate();
|
||||
if (!datasetValidation.IsValid)
|
||||
{
|
||||
result.AddWarning(
|
||||
$"Resolved dataset '{reqDatasetRef.ResolvedDataset.Metadata.Name}' (GUID: {reqDatasetRef.ResolvedDataset.Metadata.Guid}) for alias '{reqDatasetRef.Alias}' has validation issues:");
|
||||
foreach (var error in datasetValidation.Errors)
|
||||
{
|
||||
result.AddWarning($"- Dataset Error: {error}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -192,6 +230,7 @@ public class RequiredDatasetReference
|
||||
{
|
||||
public string Alias { get; set; } = string.Empty;
|
||||
public DatasetReference? Reference { get; set; }
|
||||
public Dataset? ResolvedDataset { get; set; } // New property to hold the resolved Dataset object
|
||||
}
|
||||
|
||||
public class TemplateSection
|
||||
|
@ -10,7 +10,7 @@ public class Dataset : SzfObject
|
||||
public string DatasetType { get; set; } = string.Empty;
|
||||
public string ImageUrl { get; set; } = string.Empty; // New field for dataset image
|
||||
public List<DatasetEntry> Entries { get; set; } = new();
|
||||
public Dictionary<string, object> Metadata { get; set; } = new(); // To store other metadata fields
|
||||
public Dictionary<string, object> OtherMetadata { get; set; } = new(); // To store other metadata fields
|
||||
|
||||
|
||||
public override void PopulateFromMetadata(Dictionary<string, SzfField> metadata)
|
||||
@ -29,7 +29,7 @@ public class Dataset : SzfObject
|
||||
if (!new[] { "Name", "Version", "GUID", "Description", "Author", "Type", "ImageUrl" }
|
||||
.Contains(kvp.Key, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Metadata[kvp.Key] = kvp.Value.Value!;
|
||||
OtherMetadata[kvp.Key] = kvp.Value.Value!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,7 +116,7 @@ public class Dataset : SzfObject
|
||||
writer.WriteField("ImageUrl", "text", ImageUrl);
|
||||
|
||||
// Write any other dynamic metadata
|
||||
foreach (var kvp in Metadata)
|
||||
foreach (var kvp in OtherMetadata)
|
||||
{
|
||||
writer.WriteField(kvp.Key, "text", kvp.Value); // Assuming text for generic metadata for now
|
||||
}
|
||||
|
@ -132,7 +132,7 @@
|
||||
errorMessage = string.Empty;
|
||||
}
|
||||
|
||||
private void ParseSzf() // Changed from async Task to void
|
||||
private async void ParseSzf() // Changed from async Task to void for event handler, but calls async internally
|
||||
{
|
||||
ClearMessages();
|
||||
try
|
||||
@ -143,9 +143,13 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform initial parsing
|
||||
currentSzfObject = SzfParser.Parse(szfInputText);
|
||||
statusMessage = $"SZF successfully parsed. Type: {currentSzfObject.TypeIdentifier}, Name: {currentSzfObject.Metadata.Name}";
|
||||
szfOutputText = string.Empty; // Clear generated output on new parse
|
||||
|
||||
// NEW: Resolve dependencies after initial parsing
|
||||
await ResolveSzfObjectDependencies(currentSzfObject);
|
||||
}
|
||||
catch (SzfParseException ex)
|
||||
{
|
||||
@ -199,8 +203,8 @@
|
||||
{
|
||||
Guid = currentSzfObject.Metadata.Guid.ToString(),
|
||||
Name = currentSzfObject.Metadata.Name,
|
||||
Type = currentSzfObject.TypeIdentifier, // The type identifier (e.g., "character", "dataset")
|
||||
Version = currentSzfObject.Metadata.Version.ToString(),
|
||||
Type = currentSzfObject.TypeIdentifier, // Use TypeIdentifier
|
||||
Version = currentSzfObject.Metadata.Version?.ToString() ?? "1.0.0", // Handle null version
|
||||
Content = rawContent // Storing the raw SZF string
|
||||
};
|
||||
|
||||
@ -255,6 +259,9 @@
|
||||
szfInputText = loadedSzfFileDto.Content!; // Using null-forgiving operator
|
||||
szfOutputText = string.Empty; // Clear previous generated output
|
||||
statusMessage = $"SZF '{currentSzfObject.Metadata.Name}' (GUID: {currentSzfObject.Metadata.Guid}) successfully loaded and parsed.";
|
||||
|
||||
// NEW: Resolve dependencies after loading and parsing
|
||||
await ResolveSzfObjectDependencies(currentSzfObject);
|
||||
}
|
||||
catch (SzfParseException ex)
|
||||
{
|
||||
@ -267,4 +274,63 @@
|
||||
Logger.LogError(ex, "Unexpected error during SZF loading.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resolve dependencies for the given SzfObject.
|
||||
/// Currently, this resolves RequiredDatasets for CharacterTemplates.
|
||||
/// </summary>
|
||||
/// <param name="szfObject">The SzfObject to resolve dependencies for.</param>
|
||||
private async Task ResolveSzfObjectDependencies(SzfObject szfObject)
|
||||
{
|
||||
if (szfObject is CharacterTemplate characterTemplate)
|
||||
{
|
||||
foreach (var reqDatasetRef in characterTemplate.RequiredDatasets)
|
||||
{
|
||||
if (reqDatasetRef.Reference != null)
|
||||
{
|
||||
var datasetGuid = reqDatasetRef.Reference.Guid;
|
||||
try
|
||||
{
|
||||
var loadedSzfFileDto = await SzfStorageService.GetSzfFileByGuidAsync(datasetGuid.ToString());
|
||||
if (loadedSzfFileDto != null && !string.IsNullOrWhiteSpace(loadedSzfFileDto.Content))
|
||||
{
|
||||
// Parse the content of the referenced dataset
|
||||
var parsedReferencedObject = SzfParser.Parse(loadedSzfFileDto.Content);
|
||||
if (parsedReferencedObject is Dataset dataset)
|
||||
{
|
||||
reqDatasetRef.ResolvedDataset = dataset;
|
||||
// Add a message that the dataset was resolved
|
||||
statusMessage += $"\n- Resolved dataset '{dataset.Metadata.Name}' (GUID: {dataset.Metadata.Guid}) for alias '{reqDatasetRef.Alias}'.";
|
||||
|
||||
// You can optionally run validation on the resolved dataset immediately
|
||||
// if you want feedback during resolution, in addition to the main object's validation.
|
||||
var validationResult = dataset.Validate();
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
statusMessage += $"\n (Warning: Resolved dataset has validation issues.)";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log a warning if the resolved object is not a Dataset
|
||||
statusMessage += $"\n- Warning: Reference for alias '{reqDatasetRef.Alias}' (GUID: {datasetGuid}) resolved to an object of type '{parsedReferencedObject?.GetType().Name ?? "Unknown"}' instead of 'Dataset'.";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log a warning if the dataset file is not found or has no content
|
||||
statusMessage += $"\n- Warning: Dataset for alias '{reqDatasetRef.Alias}' (GUID: {datasetGuid}) not found in storage or is empty. Cannot resolve.";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log any parsing errors for the referenced dataset
|
||||
statusMessage += $"\n- Warning: Failed to load or parse dataset for alias '{reqDatasetRef.Alias}' (GUID: {datasetGuid}): {ex.Message}";
|
||||
Logger.LogError(ex, $"Failed to load/parse referenced dataset {datasetGuid} for CharacterTemplate.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add similar logic for other SzfObject types that might have dependencies
|
||||
}
|
||||
}
|
||||
|
@ -111,10 +111,13 @@ A dataset file is a collection of structured entries.
|
||||
|
||||
# Metadata for the entire item collection
|
||||
[Metadata]
|
||||
# These fields are mandatory for all datasets.
|
||||
Name (text) = Core Fantasy Items
|
||||
Type (text) = items
|
||||
Guid (text) = c3d4e5f6-g7h8-9012-cdef-123456789012
|
||||
Version (text) = 1.0.0
|
||||
# Optional metadata fields
|
||||
Author (text) = Fantasy Creator
|
||||
Description (text-field) = A collection of basic items for any fantasy campaign.
|
||||
|
||||
# Definition for a Longsword
|
||||
|
Loading…
Reference in New Issue
Block a user