Skip to content

Commit

Permalink
imp - Promoted Xml to PartsArray
Browse files Browse the repository at this point in the history
---

We've promoted Xml to PartsArray to make it more intuitive.

---

Type: imp
Breaking: False
Doc Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Mar 30, 2024
1 parent c701062 commit 5e4154f
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 8 deletions.
1 change: 1 addition & 0 deletions VisualCard.ShowContacts/TestFiles/fourVCard4.vcf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ LANG;TYPE=home:en
LANG;TYPE=work:de
X-ANDROID-CUSTOM:vnd.android.cursor.item/nickname;NVL.N;1
;;;;;;;;;;;;;
XML:<b>Not an xCard XML element</b>\n<b>Not a second xCard XML element</b>
END:VCARD

BEGIN:VCARD
Expand Down
2 changes: 1 addition & 1 deletion VisualCard/Parsers/VcardParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Textify.General;
using VisualCard.Exceptions;
using VisualCard.Parts;
Expand Down Expand Up @@ -154,7 +155,6 @@ public Card Parse()
case StringsEnum.ProductId:
case StringsEnum.SortString:
case StringsEnum.AccessClassification:
case StringsEnum.Xml:
// Unescape the value
finalValue = Regex.Unescape(value);
break;
Expand Down
6 changes: 3 additions & 3 deletions VisualCard/Parsers/VcardParserTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ internal static bool StringSupported(StringsEnum stringsEnum, Version cardVersio
StringsEnum.ProductId => cardVersion.Major >= 3,
StringsEnum.SortString => cardVersion.Major == 3 || cardVersion.Major == 5,
StringsEnum.AccessClassification => cardVersion.Major != 2 || cardVersion.Major != 4,
StringsEnum.Xml => cardVersion.Major == 4,
StringsEnum.FreeBusyUrl => cardVersion.Major >= 4,
StringsEnum.CalendarUrl => cardVersion.Major >= 4,
StringsEnum.CalendarSchedulingRequestUrl => cardVersion.Major >= 4,
Expand Down Expand Up @@ -129,6 +128,7 @@ internal static bool EnumArrayTypeSupported(PartsArrayEnum partsArrayEnum, Versi
PartsArrayEnum.Labels => cardVersion.Major != 4,
PartsArrayEnum.Agents => cardVersion.Major != 4,
PartsArrayEnum.Langs => cardVersion.Major >= 4,
PartsArrayEnum.Xml => cardVersion.Major == 4,
_ =>
throw new InvalidOperationException("Invalid parts array enumeration type to get supported value"),
};
Expand Down Expand Up @@ -159,7 +159,6 @@ internal static string GetPrefixFromStringsEnum(StringsEnum stringsEnum) =>
StringsEnum.SortString => VcardConstants._sortStringSpecifier,
StringsEnum.Source => VcardConstants._sourceSpecifier,
StringsEnum.Url => VcardConstants._urlSpecifier,
StringsEnum.Xml => VcardConstants._xmlSpecifier,
_ =>
throw new NotImplementedException($"String enumeration {stringsEnum} is not implemented.")
};
Expand Down Expand Up @@ -196,6 +195,7 @@ internal static string GetPrefixFromPartsArrayEnum(PartsArrayEnum partsArrayEnum
PartsArrayEnum.Impps => VcardConstants._imppSpecifier,
PartsArrayEnum.Categories => VcardConstants._categoriesSpecifier,
PartsArrayEnum.Langs => VcardConstants._langSpecifier,
PartsArrayEnum.Xml => VcardConstants._xmlSpecifier,
PartsArrayEnum.NonstandardNames => VcardConstants._xSpecifier,
_ =>
throw new NotImplementedException($"String enumeration {partsArrayEnum} is not implemented.")
Expand All @@ -222,6 +222,7 @@ internal static (PartType type, object enumeration, Type enumType, Func<string,
VcardConstants._imppSpecifier => (PartType.PartsArray, PartsArrayEnum.Impps, typeof(ImppInfo), ImppInfo.FromStringVcardStatic, ImppInfo.FromStringVcardWithTypeStatic),
VcardConstants._categoriesSpecifier => (PartType.PartsArray, PartsArrayEnum.Categories, typeof(CategoryInfo), CategoryInfo.FromStringVcardStatic, CategoryInfo.FromStringVcardWithTypeStatic),
VcardConstants._langSpecifier => (PartType.PartsArray, PartsArrayEnum.Langs, typeof(LangInfo), LangInfo.FromStringVcardStatic, LangInfo.FromStringVcardWithTypeStatic),
VcardConstants._xmlSpecifier => (PartType.PartsArray, PartsArrayEnum.Xml, typeof(XmlInfo), XmlInfo.FromStringVcardStatic, XmlInfo.FromStringVcardWithTypeStatic),
VcardConstants._xSpecifier => (PartType.PartsArray, PartsArrayEnum.NonstandardNames, typeof(XNameInfo), XNameInfo.FromStringVcardStatic, XNameInfo.FromStringVcardWithTypeStatic),
VcardConstants._revSpecifier => (PartType.Parts, PartsEnum.Revision, typeof(RevisionInfo), RevisionInfo.FromStringVcardStatic, RevisionInfo.FromStringVcardWithTypeStatic),
VcardConstants._birthSpecifier => (PartType.Parts, PartsEnum.Birthdate, typeof(BirthDateInfo), BirthDateInfo.FromStringVcardStatic, BirthDateInfo.FromStringVcardWithTypeStatic),
Expand All @@ -236,7 +237,6 @@ internal static (PartType type, object enumeration, Type enumType, Func<string,
VcardConstants._productIdSpecifier => (PartType.Strings, StringsEnum.ProductId, null, null, null),
VcardConstants._sortStringSpecifier => (PartType.Strings, StringsEnum.SortString, null, null, null),
VcardConstants._classSpecifier => (PartType.Strings, StringsEnum.AccessClassification, null, null, null),
VcardConstants._xmlSpecifier => (PartType.Strings, StringsEnum.Xml, null, null, null),
VcardConstants._fbUrlSpecifier => (PartType.Strings, StringsEnum.FreeBusyUrl, null, null, null),
VcardConstants._calUriSpecifier => (PartType.Strings, StringsEnum.CalendarUrl, null, null, null),
VcardConstants._caladrUriSpecifier => (PartType.Strings, StringsEnum.CalendarSchedulingRequestUrl, null, null, null),
Expand Down
4 changes: 4 additions & 0 deletions VisualCard/Parts/Enums/PartsArrayEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ public enum PartsArrayEnum
/// </summary>
Langs,
/// <summary>
/// The contact's XML code
/// </summary>
Xml,
/// <summary>
/// The contact's extended options (usually starts with X-SOMETHING:Value1;Value2...)
/// </summary>
NonstandardNames,
Expand Down
4 changes: 0 additions & 4 deletions VisualCard/Parts/Enums/StringsEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ public enum StringsEnum
/// </summary>
Source,
/// <summary>
/// The contact's XML code
/// </summary>
Xml,
/// <summary>
/// The contact's free/busy indicator URL
/// </summary>
FreeBusyUrl,
Expand Down
161 changes: 161 additions & 0 deletions VisualCard/Parts/Implementations/XmlInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
//
// VisualCard Copyright (C) 2021-2024 Aptivi
//
// This file is part of VisualCard
//
// VisualCard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// VisualCard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using VisualCard.Parsers;

namespace VisualCard.Parts.Implementations
{
/// <summary>
/// Contact XML info
/// </summary>
[DebuggerDisplay("XML = {XML}")]
public class XmlInfo : BaseCardPartInfo, IEquatable<XmlInfo>
{
/// <summary>
/// The contact's XML field
/// </summary>
public XmlDocument Xml { get; }

/// <summary>
/// The contact's XML string that generated the <see cref="Xml"/> property
/// </summary>
public string XmlString { get; }

internal static BaseCardPartInfo FromStringVcardStatic(string value, int altId, Version cardVersion) =>
new XmlInfo().FromStringVcardInternal(value, altId, cardVersion);

internal static BaseCardPartInfo FromStringVcardWithTypeStatic(string value, string[] finalArgs, int altId, Version cardVersion) =>
new XmlInfo().FromStringVcardWithTypeInternal(value, finalArgs, altId, cardVersion);

internal override string ToStringVcardInternal(Version cardVersion)
{
bool installAltId = AltId >= 0 && AltArguments.Length > 0;
return
$"{VcardConstants._xmlSpecifier}" +
$"{(installAltId ? VcardConstants._fieldDelimiter + VcardConstants._altIdArgumentSpecifier + AltId + VcardConstants._argumentDelimiter : VcardConstants._argumentDelimiter)}" +
$"{XmlString}";
}

internal override BaseCardPartInfo FromStringVcardInternal(string value, int altId, Version cardVersion)
{
// Get the value
string xmlValue = value.Substring(VcardConstants._xmlSpecifier.Length + 1);

// Populate the fields
return InstallInfo(xmlValue, altId, cardVersion);
}

internal override BaseCardPartInfo FromStringVcardWithTypeInternal(string value, string[] finalArgs, int altId, Version cardVersion)
{
// Get the value
string xmlValue = value.Substring(value.IndexOf(VcardConstants._argumentDelimiter) + 1);

// Populate the fields
return InstallInfo(xmlValue, finalArgs, altId, cardVersion);
}

private XmlInfo InstallInfo(string value, int altId, Version cardVersion) =>
InstallInfo(value, [], altId, cardVersion);

private XmlInfo InstallInfo(string value, string[] finalArgs, int altId, Version cardVersion)
{
// Check to see if the XML document is valid or not
string finalXml =
$"""
<?xml version="1.0" encoding="UTF-8"?>
<visualcardroot>
{value.Replace("\\n", "\n")}
</visualcardroot>
""";
XmlDocument doc = new();
doc.LoadXml(finalXml);

// Add the fetched information
bool altIdSupported = cardVersion.Major >= 4;
XmlInfo _xml = new(altIdSupported ? altId : 0, altIdSupported ? finalArgs : [], doc, value);
return _xml;
}

/// <inheritdoc/>
public override bool Equals(object obj) =>
base.Equals(obj);

/// <summary>
/// Checks to see if both the parts are equal
/// </summary>
/// <param name="other">The target <see cref="XmlInfo"/> instance to check to see if they equal</param>
/// <returns>True if all the part elements are equal. Otherwise, false.</returns>
public bool Equals(XmlInfo other) =>
Equals(this, other);

/// <summary>
/// Checks to see if both the parts are equal
/// </summary>
/// <param name="source">The source <see cref="XmlInfo"/> instance to check to see if they equal</param>
/// <param name="target">The target <see cref="XmlInfo"/> instance to check to see if they equal</param>
/// <returns>True if all the part elements are equal. Otherwise, false.</returns>
public bool Equals(XmlInfo source, XmlInfo target)
{
// We can't perform this operation on null.
if (source is null)
return false;

// Check all the properties
return
source.AltArguments.SequenceEqual(target.AltArguments) &&
source.AltId == target.AltId &&
source.Xml == target.Xml
;
}

/// <inheritdoc/>
public override int GetHashCode()
{
int hashCode = -771740963;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<string[]>.Default.GetHashCode(AltArguments);
hashCode = hashCode * -1521134295 + AltId.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<XmlDocument>.Default.GetHashCode(Xml);
return hashCode;
}

/// <inheritdoc/>
public static bool operator ==(XmlInfo left, XmlInfo right) =>
EqualityComparer<XmlInfo>.Default.Equals(left, right);

/// <inheritdoc/>
public static bool operator !=(XmlInfo left, XmlInfo right) =>
!(left == right);

internal XmlInfo() { }

internal XmlInfo(int altId, string[] altArguments, XmlDocument xml, string xmlString)
{
AltId = altId;
AltArguments = altArguments;
Xml = xml;
XmlString = xmlString;
}
}
}

0 comments on commit 5e4154f

Please sign in to comment.