Seperation of concerns for szf object parsing
This commit is contained in:
parent
2e212e2c37
commit
66dd01020c
@ -26,6 +26,123 @@ public class Dataset : SzfObject
|
||||
ImageUrl = imageField.Value?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses sections specific to the Dataset object, such as entries and their subsections.
|
||||
/// This method is called by the SzfParser to populate Dataset-specific data.
|
||||
/// </summary>
|
||||
/// <param name="sections">A list of all parsed sections from the SZF file.</param>
|
||||
public override void ParseSections(List<SzfSection> sections)
|
||||
{
|
||||
// Dictionary to hold DatasetEntry objects by their name for easy lookup
|
||||
var entriesByName = new Dictionary<string, DatasetEntry>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// First pass: Identify and populate top-level DatasetEntry objects
|
||||
foreach (var szfSection in sections)
|
||||
{
|
||||
if (szfSection.Name.StartsWith("Entry:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var entryName = szfSection.Name.Substring("Entry:".Length).Trim();
|
||||
if (string.IsNullOrEmpty(entryName)) continue;
|
||||
|
||||
var newEntry = new DatasetEntry { Name = entryName };
|
||||
foreach (var field in szfSection.Fields)
|
||||
{
|
||||
newEntry.Fields.Add(ConvertToDatasetField(field));
|
||||
}
|
||||
|
||||
Entries.Add(newEntry);
|
||||
entriesByName[entryName] = newEntry;
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: Populate sections and subsections for each entry
|
||||
foreach (var szfSection in sections)
|
||||
{
|
||||
// We are looking for sections like "Entry.EntryName.SectionName" or "Entry.EntryName.SectionName.SubSectionName"
|
||||
if (!szfSection.Name.StartsWith("Entry.", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
|
||||
// Split the section name by '.' to identify parts
|
||||
var nameParts = szfSection.Name.Split('.');
|
||||
|
||||
// Ensure it's a section of an entry (e.g., "Entry.EntryName.Section")
|
||||
if (nameParts.Length < 3 || !nameParts[0].Equals("Entry", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
|
||||
var entryName = nameParts[1];
|
||||
if (!entriesByName.TryGetValue(entryName, out var targetEntry)) continue; // Entry not found, skip
|
||||
|
||||
// We need to build the hierarchy of DatasetSection objects
|
||||
DatasetSection? currentParentSection = null;
|
||||
List<DatasetSection> currentSectionList = targetEntry.Sections;
|
||||
|
||||
for (int i = 2; i < nameParts.Length; i++) // Start from the first section name after "Entry.EntryName"
|
||||
{
|
||||
var sectionNamePart = nameParts[i];
|
||||
var existingSection = currentSectionList.FirstOrDefault(s =>
|
||||
s.Name.Equals(sectionNamePart, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (existingSection == null)
|
||||
{
|
||||
// Create new section
|
||||
var newSection = new DatasetSection { Name = sectionNamePart };
|
||||
currentSectionList.Add(newSection);
|
||||
currentParentSection = newSection;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentParentSection = existingSection;
|
||||
}
|
||||
|
||||
// If this is the last part of the section name, populate its fields
|
||||
if (i == nameParts.Length - 1)
|
||||
{
|
||||
foreach (var field in szfSection.Fields)
|
||||
{
|
||||
currentParentSection.Fields.Add(ConvertToDatasetField(field));
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next level down in the hierarchy
|
||||
currentSectionList = currentParentSection.Subsections;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert SzfField to DatasetField
|
||||
/// </summary>
|
||||
private DatasetField ConvertToDatasetField(SzfField szfField)
|
||||
{
|
||||
return new DatasetField
|
||||
{
|
||||
Name = szfField.Name,
|
||||
Type = ParseDatasetFieldType(szfField.Type),
|
||||
Value = szfField.Value
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse DatasetFieldType from string
|
||||
/// </summary>
|
||||
private DatasetFieldType ParseDatasetFieldType(string typeString)
|
||||
{
|
||||
return typeString.ToLower() switch
|
||||
{
|
||||
"text" => DatasetFieldType.Text,
|
||||
"text-field" => DatasetFieldType.TextField,
|
||||
"number" => DatasetFieldType.Number,
|
||||
"bool" => DatasetFieldType.Boolean,
|
||||
"group" => DatasetFieldType.Group,
|
||||
"calculated" => DatasetFieldType.Calculated,
|
||||
"system" => DatasetFieldType.System,
|
||||
"dataset-reference" => DatasetFieldType.DatasetReference,
|
||||
"dataset-type" => DatasetFieldType.DatasetType,
|
||||
"dataset-reference-multiple" => DatasetFieldType.DatasetReferenceMultiple,
|
||||
"dataset-type-multiple" => DatasetFieldType.DatasetTypeMultiple,
|
||||
_ => DatasetFieldType.Text
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public override SzfValidationResult Validate()
|
||||
{
|
||||
var result = base.Validate();
|
||||
|
@ -15,6 +15,13 @@ public abstract class SzfObject
|
||||
|
||||
public abstract SzfObjectType ObjectType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Abstract method for SzfObjects to parse their specific sections from the raw parsed structure.
|
||||
/// This promotes separation of concerns by moving type-specific parsing logic into the SzfObject itself.
|
||||
/// </summary>
|
||||
/// <param name="sections">A list of all parsed sections from the SZF file.</param>
|
||||
public abstract void ParseSections(List<SzfSection> sections);
|
||||
|
||||
public virtual SzfValidationResult Validate()
|
||||
{
|
||||
var result = new SzfValidationResult { IsValid = true };
|
||||
|
@ -281,99 +281,8 @@ public class SzfParser
|
||||
obj.PopulateFromMetadata(metadata);
|
||||
}
|
||||
|
||||
// Process type-specific content
|
||||
ProcessTypeSpecificContent(obj, parseResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process type-specific content based on the object type
|
||||
/// </summary>
|
||||
private void ProcessTypeSpecificContent(SzfObject obj, SzfParseResult parseResult)
|
||||
{
|
||||
switch (obj)
|
||||
{
|
||||
case Dataset dataset:
|
||||
ProcessDatasetContent(dataset, parseResult);
|
||||
break;
|
||||
// Add other types as they're implemented
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process dataset-specific content (entries and their sections)
|
||||
/// </summary>
|
||||
private void ProcessDatasetContent(Dataset dataset, SzfParseResult parseResult)
|
||||
{
|
||||
var entrySections = parseResult.Sections
|
||||
.Where(s => s.Name.StartsWith("Entry:", StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
|
||||
foreach (var entrySection in entrySections)
|
||||
{
|
||||
var entryName = entrySection.Name.Substring(6).Trim(); // Remove "Entry: " prefix
|
||||
var entry = new DatasetEntry { Name = entryName };
|
||||
|
||||
// Add fields directly on the entry
|
||||
foreach (var field in entrySection.Fields)
|
||||
{
|
||||
entry.Fields.Add(ConvertToDatasetField(field));
|
||||
}
|
||||
|
||||
// Find subsections for this entry
|
||||
var entrySubsections = parseResult.Sections
|
||||
.Where(s => s.Name.StartsWith($"Entry.{entryName}.", StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
|
||||
foreach (var subsection in entrySubsections)
|
||||
{
|
||||
var sectionName = subsection.Name.Substring($"Entry.{entryName}.".Length);
|
||||
var datasetSection = new DatasetSection { Name = sectionName };
|
||||
|
||||
foreach (var field in subsection.Fields)
|
||||
{
|
||||
datasetSection.Fields.Add(ConvertToDatasetField(field));
|
||||
}
|
||||
|
||||
entry.Sections.Add(datasetSection);
|
||||
}
|
||||
|
||||
dataset.Entries.Add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert SzfField to DatasetField
|
||||
/// </summary>
|
||||
private DatasetField ConvertToDatasetField(SzfField szfField)
|
||||
{
|
||||
return new DatasetField
|
||||
{
|
||||
Name = szfField.Name,
|
||||
Type = ParseDatasetFieldType(szfField.Type),
|
||||
Value = szfField.Value
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse DatasetFieldType from string
|
||||
/// </summary>
|
||||
private DatasetFieldType ParseDatasetFieldType(string typeString)
|
||||
{
|
||||
return typeString.ToLower() switch
|
||||
{
|
||||
"text" => DatasetFieldType.Text,
|
||||
"text-field" => DatasetFieldType.TextField,
|
||||
"number" => DatasetFieldType.Number,
|
||||
"bool" => DatasetFieldType.Boolean,
|
||||
"group" => DatasetFieldType.Group,
|
||||
"calculated" => DatasetFieldType.Calculated,
|
||||
"system" => DatasetFieldType.System,
|
||||
"dataset-reference" => DatasetFieldType.DatasetReference,
|
||||
"dataset-type" => DatasetFieldType.DatasetType,
|
||||
"dataset-reference-multiple" => DatasetFieldType.DatasetReferenceMultiple,
|
||||
"dataset-type-multiple" => DatasetFieldType.DatasetTypeMultiple,
|
||||
_ => DatasetFieldType.Text
|
||||
};
|
||||
// Delegate type-specific section parsing to the SzfObject itself
|
||||
obj.ParseSections(parseResult.Sections);
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,7 +300,7 @@ internal class SzfParseResult
|
||||
/// <summary>
|
||||
/// Internal class representing a parsed section
|
||||
/// </summary>
|
||||
internal class SzfSection
|
||||
public class SzfSection
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public List<SzfField> Fields { get; set; } = new();
|
||||
|
Loading…
Reference in New Issue
Block a user