Skip to content

Commit

Permalink
ref - Refactored card value processing
Browse files Browse the repository at this point in the history
---

The card value processing has been refactored. We just need to refactor
the calendar version, making appropriate changes as needed.

---

Type: ref
Breaking: False
Doc Required: False
Backport Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Feb 7, 2025
1 parent c7f4625 commit 306f085
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 90 deletions.
3 changes: 2 additions & 1 deletion public/VisualCard.Calendar/Parsers/VCalendarParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ public Parts.Calendar Parse()
for (int i = 0; i < CalendarContent.Length; i++)
{
// Get line
var contentLines = CalendarContent.Select((tuple) => tuple.Item2).ToArray();
var content = CalendarContent[i];
string _value = VcardCommonTools.ConstructBlocks(CalendarContent, ref i);
string _value = VcardCommonTools.ConstructBlocks(contentLines, ref i);
int lineNumber = content.Item1;
if (string.IsNullOrEmpty(_value))
continue;
Expand Down
6 changes: 3 additions & 3 deletions public/VisualCard/Parsers/VcardCommonTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ internal static CardKind GetKindEnum(string kind) =>
_ => CardKind.Others,
};

internal static string ConstructBlocks((int, string)[] cardContent, ref int i)
internal static string ConstructBlocks(string[] cardContent, ref int i)
{
StringBuilder valueBuilder = new();
bool constructing;
Expand All @@ -711,12 +711,12 @@ internal static string ConstructBlocks((int, string)[] cardContent, ref int i)
{
// Get line
var content = cardContent[idx];
string _value = content.Item2;
string _value = content;
if (string.IsNullOrEmpty(_value))
continue;

// First, check to see if we need to construct blocks
string secondLine = idx + 1 < cardContent.Length ? cardContent[idx + 1].Item2 : "";
string secondLine = idx + 1 < cardContent.Length ? cardContent[idx + 1] : "";
bool firstConstructedLine = !_value.StartsWith(VcardConstants._spaceBreak) && !_value.StartsWith(VcardConstants._tabBreak);
constructing = secondLine.StartsWithAnyOf([VcardConstants._spaceBreak, VcardConstants._tabBreak]);
secondLine = secondLine.Length > 1 ? secondLine.Substring(1) : "";
Expand Down
177 changes: 91 additions & 86 deletions public/VisualCard/Parsers/VcardParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,102 +74,20 @@ public Card Parse()

// Iterate through all the lines
StringBuilder valueBuilder = new();
string[] allowedTypes = ["HOME", "WORK", "PREF"];
string kind = "individual";
for (int i = 0; i < CardContent.Length; i++)
{
// Get line
var contentLines = CardContent.Select((tuple) => tuple.Item2).ToArray();
var content = CardContent[i];
string _value = VcardCommonTools.ConstructBlocks(CardContent, ref i);
string _value = VcardCommonTools.ConstructBlocks(contentLines, ref i);
int lineNumber = content.Item1;
if (string.IsNullOrEmpty(_value))
continue;

// Process the line
try
{
// Now, parse a property
var info = new PropertyInfo(_value);
var partType = VcardParserTools.GetPartType(info.Prefix, CardVersion, kind);

// Handle AltID
int altId = VcardCommonTools.GetAltIdFromArgs(CardVersion, info, partType);

// Check the type for allowed types
bool specifierRequired = CardVersion.Major >= 3;
string[] elementTypes = VcardCommonTools.GetTypes(info.Arguments, partType.defaultType, specifierRequired);
foreach (string elementType in elementTypes)
{
string elementTypeUpper = elementType.ToUpper();
if (!allowedTypes.Contains(elementTypeUpper) && !partType.allowedExtraTypes.Contains(elementTypeUpper) && !elementTypeUpper.StartsWith("X-"))
{
if (partType.type == PartType.PartsArray &&
((PartsArrayEnum)partType.enumeration == PartsArrayEnum.IanaNames ||
(PartsArrayEnum)partType.enumeration == PartsArrayEnum.NonstandardNames))
continue;
throw new InvalidDataException($"Part info type {partType.enumType?.Name ?? "<null>"} doesn't support property type {elementTypeUpper} because the following base types are supported: [{string.Join(", ", allowedTypes)}] and the extra types are supported: [{string.Join(", ", partType.allowedExtraTypes)}]");
}
}

// Handle the part type
string valueType = VcardCommonTools.GetFirstValue(info.Arguments, partType.defaultValueType, VcardConstants._valueArgumentSpecifier);
string finalValue = VcardCommonTools.ProcessStringValue(info.Value, valueType);

// Check for allowed values
if (partType.allowedValues.Length != 0)
{
bool found = false;
foreach (string allowedValue in partType.allowedValues)
{
if (finalValue == allowedValue)
found = true;
}
if (!found)
throw new InvalidDataException($"Value {finalValue} not in the list of allowed values [{string.Join(", ", partType.allowedValues)}]");
}

// Check for support
bool supported = partType.minimumVersionCondition(CardVersion);
if (!supported)
continue;

// Process the value
switch (partType.type)
{
case PartType.Strings:
{
StringsEnum stringType = (StringsEnum)partType.enumeration;

// Let VisualCard know that we've explicitly specified a kind.
if (stringType == StringsEnum.Kind)
{
kind = string.IsNullOrEmpty(finalValue) ? "individual" : finalValue;
card.kindExplicitlySpecified = true;
}
else if (stringType == StringsEnum.Profile && !finalValue.Equals("vcard", StringComparison.OrdinalIgnoreCase))
throw new InvalidDataException("Profile must be \"vCard\"");

// Set the string for real
var stringValueInfo = new ValueInfo<string>(info, altId, elementTypes, valueType, finalValue);
card.AddString(stringType, stringValueInfo);
}
break;
case PartType.PartsArray:
{
PartsArrayEnum partsArrayType = (PartsArrayEnum)partType.enumeration;
if (partType.fromStringFunc is null)
continue;

// Now, get the part info
finalValue = partsArrayType is PartsArrayEnum.NonstandardNames or PartsArrayEnum.IanaNames ? _value : info.Value;
var partInfo = partType.fromStringFunc(finalValue, info, altId, elementTypes, valueType, CardVersion);

// Set the array for real
card.AddPartToArray(partsArrayType, partInfo);
}
break;
default:
throw new InvalidDataException($"The type {partType.type} is invalid. Are you sure that you've specified the correct type in your vCard representation?");
}
Process(_value, ref card);
}
catch (Exception ex)
{
Expand All @@ -185,6 +103,93 @@ public Card Parse()
return card;
}

internal void Process(string _value, ref Card card)
{
string[] allowedTypes = ["HOME", "WORK", "PREF"];
string kind = card.CardKindStr;

// Parse a property
var info = new PropertyInfo(_value);
var partType = VcardParserTools.GetPartType(info.Prefix, CardVersion, kind);

// Handle AltID
int altId = VcardCommonTools.GetAltIdFromArgs(CardVersion, info, partType);

// Check the type for allowed types
bool specifierRequired = CardVersion.Major >= 3;
string[] elementTypes = VcardCommonTools.GetTypes(info.Arguments, partType.defaultType, specifierRequired);
foreach (string elementType in elementTypes)
{
string elementTypeUpper = elementType.ToUpper();
if (!allowedTypes.Contains(elementTypeUpper) && !partType.allowedExtraTypes.Contains(elementTypeUpper) && !elementTypeUpper.StartsWith("X-"))
{
if (partType.type == PartType.PartsArray &&
((PartsArrayEnum)partType.enumeration == PartsArrayEnum.IanaNames ||
(PartsArrayEnum)partType.enumeration == PartsArrayEnum.NonstandardNames))
continue;
throw new InvalidDataException($"Part info type {partType.enumType?.Name ?? "<null>"} doesn't support property type {elementTypeUpper} because the following base types are supported: [{string.Join(", ", allowedTypes)}] and the extra types are supported: [{string.Join(", ", partType.allowedExtraTypes)}]");
}
}

// Handle the part type
string valueType = VcardCommonTools.GetFirstValue(info.Arguments, partType.defaultValueType, VcardConstants._valueArgumentSpecifier);
string finalValue = VcardCommonTools.ProcessStringValue(info.Value, valueType);

// Check for allowed values
if (partType.allowedValues.Length != 0)
{
bool found = false;
foreach (string allowedValue in partType.allowedValues)
{
if (finalValue == allowedValue)
found = true;
}
if (!found)
throw new InvalidDataException($"Value {finalValue} not in the list of allowed values [{string.Join(", ", partType.allowedValues)}]");
}

// Check for support
bool supported = partType.minimumVersionCondition(CardVersion);
if (!supported)
return;

// Process the value
switch (partType.type)
{
case PartType.Strings:
{
StringsEnum stringType = (StringsEnum)partType.enumeration;

// Let VisualCard know that we've explicitly specified a kind.
if (stringType == StringsEnum.Kind)
card.kindExplicitlySpecified = true;
else if (stringType == StringsEnum.Profile && !finalValue.Equals("vcard", StringComparison.OrdinalIgnoreCase))
throw new InvalidDataException("Profile must be \"vCard\"");

// Set the string for real
var stringValueInfo = new ValueInfo<string>(info, altId, elementTypes, valueType, finalValue);
card.AddString(stringType, stringValueInfo);
}
break;
case PartType.PartsArray:
{
PartsArrayEnum partsArrayType = (PartsArrayEnum)partType.enumeration;
if (partType.fromStringFunc is null)
return;

// Now, get the part info
finalValue = partsArrayType is PartsArrayEnum.NonstandardNames or PartsArrayEnum.IanaNames ? _value : info.Value;
var partInfo = partType.fromStringFunc(finalValue, info, altId, elementTypes, valueType, CardVersion);

// Set the array for real
card.AddPartToArray(partsArrayType, partInfo);
}
break;
default:
throw new InvalidDataException($"The type {partType.type} is invalid. Are you sure that you've specified the correct type in your vCard representation?");
}
}

internal void ValidateCard(Card card)
{
// Track the required fields
Expand Down

0 comments on commit 306f085

Please sign in to comment.