// SzfObject.cs
using System;
using System.Collections.Generic;
using System.Reflection;
namespace SessionZero.Data;
///
/// Represents common metadata for all SzfObjects.
///
public class SzfMetadata
{
public string Name { get; set; } = string.Empty;
public Version? Version { get; set; }
public Guid Guid { get; set; }
public string? Description { get; set; }
public string? Author { get; set; }
}
public abstract class SzfObject
{
///
/// The unique string identifier for this SzfObject type, derived from its SzfObjectAttribute.
///
public string TypeIdentifier { get; }
///
/// Common metadata for all SzfObjects.
///
public SzfMetadata Metadata { get; set; } = new SzfMetadata();
///
/// Default constructor that reads the TypeIdentifier from the SzfObjectAttribute.
///
protected SzfObject()
{
// Read the SzfObjectAttribute from the concrete class type
var attribute = GetType().GetCustomAttribute();
if (attribute == null)
{
// This indicates a missing attribute, which means the class is not properly defined as an SzfObject.
throw new InvalidOperationException(
$"SzfObject class '{GetType().Name}' is missing the SzfObjectAttribute. All concrete SzfObject types must have this attribute.");
}
TypeIdentifier = attribute.TypeIdentifier;
// Initialize metadata with a new GUID, this is a default, can be overridden by parsing
Metadata.Guid = Guid.NewGuid();
}
///
/// Populates the object's metadata from a dictionary of parsed SzfFields.
/// This method is intended to be overridden by derived classes to handle their specific metadata.
///
/// A dictionary of metadata fields.
public virtual void PopulateFromMetadata(Dictionary metadata)
{
if (metadata.TryGetValue("Name", out var nameField))
Metadata.Name = nameField.Value?.ToString() ?? string.Empty;
if (metadata.TryGetValue("Version", out var versionField))
{
if (Version.TryParse(versionField.Value?.ToString(), out var ver))
{
Metadata.Version = ver;
}
}
if (metadata.TryGetValue("GUID", out var guidField))
{
if (Guid.TryParse(guidField.Value?.ToString() ?? string.Empty, out var guid))
{
Metadata.Guid = guid;
}
}
if (metadata.TryGetValue("Description", out var descriptionField))
Metadata.Description = descriptionField.Value?.ToString();
if (metadata.TryGetValue("Author", out var authorField))
Metadata.Author = authorField.Value?.ToString();
}
///
/// Parses the sections of the Szf object from a flat list of SzfSection objects
/// and constructs the object's internal data structure. This is an abstract method
/// that must be implemented by derived classes.
///
/// A list of parsed SzfSections.
public abstract void ParseSections(List sections);
///
/// Generates the metadata section of the Szf file using the provided writer.
/// This method is virtual and can be extended by derived classes to add their specific metadata.
///
/// The SzfFieldWriter to use for writing.
public virtual void GenerateMetadata(SzfFieldWriter writer)
{
// Write standard metadata fields common to all SzfObjects
writer.AppendSectionHeader("Metadata"); // Corrected method call
writer.WriteField("Name", "text", Metadata.Name);
writer.WriteField("Version", "text",
Metadata.Version?.ToString() ?? string.Empty); // Ensure Version is not null
writer.WriteField("GUID", "text", Metadata.Guid.ToString());
if (!string.IsNullOrEmpty(Metadata.Description))
writer.WriteField("Description", "text-field", Metadata.Description);
if (!string.IsNullOrEmpty(Metadata.Author))
writer.WriteField("Author", "text", Metadata.Author);
writer.AppendLine(); // Corrected method call to end section with a newline
}
///
/// Generates the content sections of the Szf file using the provided writer.
/// This is an abstract method that must be implemented by derived classes.
///
/// The SzfFieldWriter to use for writing.
public abstract void GenerateContent(SzfFieldWriter writer);
///
/// Validates the current state of the Szf object.
/// This method is virtual and can be extended by derived classes to add their specific validation rules.
///
/// A SzfValidationResult indicating any errors or warnings.
public virtual SzfValidationResult Validate()
{
var result = new SzfValidationResult();
if (string.IsNullOrWhiteSpace(Metadata.Name))
result.AddError("Name is required for SzfObject");
if (Metadata.Version == null)
result.AddError("Version is required for SzfObject");
if (Metadata.Guid == Guid.Empty)
result.AddError("GUID is required for SzfObject");
return result;
}
}
public class SzfValidationResult
{
public bool IsValid { get; set; } = true;
public List Errors { get; set; } = [];
public List Warnings { get; set; } = [];
public void AddError(string error)
{
Errors.Add(error);
IsValid = false;
}
public void AddWarning(string warning)
{
Warnings.Add(warning);
}
}
public class SzfField
{
public string Name { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
public object? Value { get; set; }
}