337 lines
14 KiB
Plaintext
337 lines
14 KiB
Plaintext
@page "/szf-parser-test"
|
|
@using SessionZero.Data
|
|
@using SessionZero.Services
|
|
@using SessionZero.Models
|
|
@inject SzfParser SzfParser
|
|
@inject ILogger<SzfParseTest> Logger
|
|
@inject SzfGenerator SzfGenerator
|
|
@inject ISzfStorageService SzfStorageService
|
|
@inject ILocalStorageService LocalStorageService
|
|
|
|
<h1 class="page-title">SZF Testing Page</h1>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h3>Input SZF</h3>
|
|
<textarea @bind="szfInputText" rows="15" class="form-control" placeholder="Paste your SZF content here..."></textarea>
|
|
<div class="mt-2">
|
|
<button class="btn btn-primary" @onclick="ParseSzf">Parse SZF</button>
|
|
<button class="btn btn-success ms-2" @onclick="SaveSzf">Save Parsed SZF</button>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h3>Generated SZF</h3>
|
|
<textarea @bind="szfOutputText" rows="15" class="form-control" readonly></textarea>
|
|
<div class="mt-2">
|
|
<button class="btn btn-info" @onclick="GenerateSzf">Generate SZF from Object</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<h3>Load SZF by GUID</h3>
|
|
<div class="input-group mb-3">
|
|
<input type="text" class="form-control" placeholder="Enter GUID to load" @bind="loadGuid" />
|
|
<button class="btn btn-secondary" @onclick="LoadSzf">Load SZF</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<h3>Parsed Object Details</h3>
|
|
@if (!string.IsNullOrEmpty(errorMessage))
|
|
{
|
|
<div class="alert alert-danger" role="alert">
|
|
<strong>Error:</strong> @errorMessage
|
|
</div>
|
|
}
|
|
@if (!string.IsNullOrEmpty(statusMessage))
|
|
{
|
|
<div class="alert alert-info" role="alert">
|
|
<strong>Status:</strong> @statusMessage
|
|
</div>
|
|
}
|
|
@if (currentSzfObject != null)
|
|
{
|
|
<div class="card card-body bg-light">
|
|
<h5>Metadata</h5>
|
|
<p><strong>Type:</strong> @currentSzfObject.TypeIdentifier</p>
|
|
<p><strong>Name:</strong> @currentSzfObject.Metadata.Name</p>
|
|
<p><strong>GUID:</strong> @currentSzfObject.Metadata.Guid</p>
|
|
<p><strong>Version:</strong> @currentSzfObject.Metadata.Version</p>
|
|
|
|
@* For a more detailed display of sections, you might need a recursive component or more complex rendering logic.
|
|
For now, we'll just indicate if sections are present. *@
|
|
<h5>Sections:</h5>
|
|
@if (currentSzfObject is Character character)
|
|
{
|
|
<p><strong>Character Sections Count:</strong> @character.CharacterSections.Count</p>
|
|
@if (character.CharacterSections.Any())
|
|
{
|
|
<h6>Top-Level Sections:</h6>
|
|
<ul>
|
|
@foreach (var section in character.CharacterSections)
|
|
{
|
|
<li>@(section.Name) (@(section.Fields.Count) fields, @(section.Subsections.Count) subsections)</li>
|
|
}
|
|
</ul>
|
|
}
|
|
}
|
|
else if (currentSzfObject is CharacterTemplate characterTemplate)
|
|
{
|
|
<p><strong>Template Sections Count:</strong> @characterTemplate.Sections.Count</p>
|
|
@if (characterTemplate.Sections.Any())
|
|
{
|
|
<h6>Top-Level Template Sections:</h6>
|
|
<ul>
|
|
@foreach (var section in characterTemplate.Sections)
|
|
{
|
|
<li>@(section.Name) (@(section.Fields.Count) fields, @(section.Subsections.Count) subsections)</li>
|
|
}
|
|
</ul>
|
|
}
|
|
<p><strong>Required Datasets Count:</strong> @characterTemplate.RequiredDatasets.Count</p>
|
|
}
|
|
else if (currentSzfObject is Dataset dataset)
|
|
{
|
|
<p><strong>Dataset Entries Count:</strong> @dataset.Entries.Count</p>
|
|
@if (dataset.Entries.Any())
|
|
{
|
|
<h6>First 5 Dataset Entries:</h6>
|
|
<ul>
|
|
@foreach (var entry in dataset.Entries.Take(5))
|
|
{
|
|
<li>@(entry.Name) (@(entry.Fields.Count) fields, @(entry.Sections.Count) subsections)</li>
|
|
}
|
|
</ul>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<p>No specific display logic for this SzfObject type.</p>
|
|
}
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<p>No SZF object parsed yet.</p>
|
|
}
|
|
</div>
|
|
|
|
@code {
|
|
private string szfInputText = string.Empty;
|
|
private string szfOutputText = string.Empty;
|
|
private SzfObject? currentSzfObject;
|
|
private string loadGuid = string.Empty;
|
|
private string statusMessage = string.Empty;
|
|
private string errorMessage = string.Empty;
|
|
|
|
// Helper to clear messages
|
|
private void ClearMessages()
|
|
{
|
|
statusMessage = string.Empty;
|
|
errorMessage = string.Empty;
|
|
}
|
|
|
|
private async void ParseSzf() // Changed from async Task to void for event handler, but calls async internally
|
|
{
|
|
ClearMessages();
|
|
try
|
|
{
|
|
if (string.IsNullOrWhiteSpace(szfInputText))
|
|
{
|
|
errorMessage = "Input SZF text cannot be empty.";
|
|
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)
|
|
{
|
|
errorMessage = $"Parsing failed: {ex.Message}";
|
|
Logger.LogError(ex, "SZF parsing error.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"An unexpected error occurred during parsing: {ex.Message}";
|
|
Logger.LogError(ex, "Unexpected error during SZF parsing.");
|
|
}
|
|
}
|
|
|
|
private void GenerateSzf() // Changed from async Task to void
|
|
{
|
|
ClearMessages();
|
|
try
|
|
{
|
|
if (currentSzfObject == null)
|
|
{
|
|
errorMessage = "No SZF object parsed to generate from. Please parse an SZF first.";
|
|
return;
|
|
}
|
|
|
|
szfOutputText = SzfGenerator.Generate(currentSzfObject);
|
|
statusMessage = "SZF successfully generated from the parsed object.";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"An error occurred during SZF generation: {ex.Message}";
|
|
Logger.LogError(ex, "SZF generation error.");
|
|
}
|
|
}
|
|
|
|
private async Task SaveSzf()
|
|
{
|
|
ClearMessages();
|
|
try
|
|
{
|
|
if (currentSzfObject == null)
|
|
{
|
|
errorMessage = "No SZF object parsed to save. Please parse an SZF first.";
|
|
return;
|
|
}
|
|
|
|
// Generate the raw SZF content from the current object
|
|
var rawContent = SzfGenerator.Generate(currentSzfObject);
|
|
|
|
// Create an SzfFile DTO from SessionZero.Models
|
|
var szfFileDto = new SzfFile
|
|
{
|
|
Guid = currentSzfObject.Metadata.Guid.ToString(),
|
|
Name = currentSzfObject.Metadata.Name,
|
|
Type = currentSzfObject.TypeIdentifier, // Use TypeIdentifier
|
|
Version = currentSzfObject.Metadata.Version?.ToString() ?? "1.0.0", // Handle null version
|
|
Content = rawContent // Storing the raw SZF string
|
|
};
|
|
|
|
await SzfStorageService.SaveSzfFileAsync(szfFileDto);
|
|
statusMessage = $"SZF '{currentSzfObject.Metadata.Name}' (GUID: {currentSzfObject.Metadata.Guid}) successfully saved to storage.";
|
|
}
|
|
catch (ArgumentException ex)
|
|
{
|
|
errorMessage = $"Save failed: {ex.Message}";
|
|
Logger.LogError(ex, "Error saving SZF due to invalid argument.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"An unexpected error occurred during saving: {ex.Message}";
|
|
Logger.LogError(ex, "Unexpected error during SZF saving.");
|
|
}
|
|
}
|
|
|
|
private async Task LoadSzf()
|
|
{
|
|
ClearMessages();
|
|
try
|
|
{
|
|
if (string.IsNullOrWhiteSpace(loadGuid))
|
|
{
|
|
errorMessage = "Please enter a GUID to load.";
|
|
return;
|
|
}
|
|
|
|
var loadedSzfFileDto = await SzfStorageService.GetSzfFileByGuidAsync(loadGuid);
|
|
|
|
if (loadedSzfFileDto == null)
|
|
{
|
|
statusMessage = $"No SZF file found for GUID: {loadGuid}";
|
|
currentSzfObject = null;
|
|
szfInputText = string.Empty;
|
|
szfOutputText = string.Empty;
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(loadedSzfFileDto.Content))
|
|
{
|
|
errorMessage = "Loaded SZF file has no content. Cannot re-parse.";
|
|
currentSzfObject = null;
|
|
szfInputText = string.Empty;
|
|
szfOutputText = string.Empty;
|
|
return;
|
|
}
|
|
|
|
// Parse the content from the loaded DTO back into an SzfObject
|
|
currentSzfObject = SzfParser.Parse(loadedSzfFileDto.Content!); // Using null-forgiving operator
|
|
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)
|
|
{
|
|
errorMessage = $"Loading and parsing failed: {ex.Message}";
|
|
Logger.LogError(ex, "Error re-parsing loaded SZF content.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"An unexpected error occurred during loading: {ex.Message}";
|
|
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
|
|
}
|
|
}
|