Skip to content

Commit

Permalink
add - doc - Added vCard 4.0 RELATED and CLIENTPIDM...
Browse files Browse the repository at this point in the history
...AP properties

---

We've added two new properties to the vCard parser for vCard 4.0: CLIENTPIDMAP and RELATED.

---

Type: add
Breaking: False
Doc Required: True
Backport Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Oct 1, 2024
1 parent e67a952 commit 60ff9b1
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 0 deletions.
2 changes: 2 additions & 0 deletions VisualCard/Parsers/VcardConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,7 @@ internal static class VcardConstants

// Available in vCard 4.0
internal const string _memberSpecifier = "MEMBER";
internal const string _relatedSpecifier = "RELATED";
internal const string _clientPidMapSpecifier = "CLIENTPIDMAP";
}
}
10 changes: 10 additions & 0 deletions VisualCard/Parsers/VcardParserTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ internal static bool EnumArrayTypeSupported(PartsArrayEnum partsArrayEnum, Versi
PartsArrayEnum.CalendarSchedulingRequestUrl => cardVersion.Major >= 4,
PartsArrayEnum.ContactUri => cardVersion.Major >= 4,
PartsArrayEnum.Member => kind == "group" && cardVersion.Major == 4,
PartsArrayEnum.Related => cardVersion.Major == 4,
PartsArrayEnum.ClientPidMap => cardVersion.Major == 4,

// Extensions are allowed
_ => true,
Expand Down Expand Up @@ -119,6 +121,8 @@ internal static string GetPrefixFromPartsArrayEnum(PartsArrayEnum partsArrayEnum
PartsArrayEnum.Url => VcardConstants._urlSpecifier,
PartsArrayEnum.ContactUri => VcardConstants._contactUriSpecifier,
PartsArrayEnum.Member => VcardConstants._memberSpecifier,
PartsArrayEnum.Related => VcardConstants._relatedSpecifier,
PartsArrayEnum.ClientPidMap => VcardConstants._clientPidMapSpecifier,

// Extensions are allowed
PartsArrayEnum.NonstandardNames => VcardConstants._xSpecifier,
Expand Down Expand Up @@ -197,6 +201,10 @@ internal static (PartsArrayEnum, PartCardinality) GetPartsArrayEnumFromType(Type
return (PartsArrayEnum.ContactUri, PartCardinality.Any);
else if (partsArrayType == typeof(MemberInfo))
return (PartsArrayEnum.Member, PartCardinality.Any);
else if (partsArrayType == typeof(RelatedInfo))
return (PartsArrayEnum.Related, PartCardinality.Any);
else if (partsArrayType == typeof(ClientPidMapInfo))
return (PartsArrayEnum.ClientPidMap, PartCardinality.Any);

// Extensions are allowed
else if (partsArrayType == typeof(XNameInfo))
Expand Down Expand Up @@ -240,6 +248,8 @@ internal static (PartType type, object enumeration, Type? enumType, Func<string,
VcardConstants._caladrUriSpecifier => (PartType.PartsArray, PartsArrayEnum.CalendarSchedulingRequestUrl, typeof(CalendarSchedulingRequestUrlInfo), CalendarSchedulingRequestUrlInfo.FromStringVcardStatic, "", "", "uri", []),
VcardConstants._contactUriSpecifier => (PartType.PartsArray, PartsArrayEnum.ContactUri, typeof(ContactUriInfo), ContactUriInfo.FromStringVcardStatic, "", "", "uri", []),
VcardConstants._memberSpecifier => (PartType.PartsArray, PartsArrayEnum.Member, typeof(MemberInfo), MemberInfo.FromStringVcardStatic, "", "", "uri", []),
VcardConstants._relatedSpecifier => (PartType.PartsArray, PartsArrayEnum.Related, typeof(RelatedInfo), RelatedInfo.FromStringVcardStatic, "", "", "uri", []),
VcardConstants._clientPidMapSpecifier => (PartType.PartsArray, PartsArrayEnum.ClientPidMap, typeof(ClientPidMapInfo), ClientPidMapInfo.FromStringVcardStatic, "", "", "text", []),
VcardConstants._kindSpecifier => (PartType.Strings, StringsEnum.Kind, null, null, "", "", "text", []),
VcardConstants._mailerSpecifier => (PartType.Strings, StringsEnum.Mailer, null, null, "", "", "text", []),
VcardConstants._productIdSpecifier => (PartType.Strings, StringsEnum.ProductId, null, null, "", "", "text", []),
Expand Down
8 changes: 8 additions & 0 deletions VisualCard/Parts/Enums/PartsArrayEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ public enum PartsArrayEnum
/// </summary>
Member,
/// <summary>
/// The related member URI
/// </summary>
Related,
/// <summary>
/// Client PID map
/// </summary>
ClientPidMap,
/// <summary>
/// The contact's extended IANA options (usually starts with SOMETHING:Value1;Value2...)
/// </summary>
IanaNames = int.MaxValue - 2,
Expand Down
131 changes: 131 additions & 0 deletions VisualCard/Parts/Implementations/ClientPidMapInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// 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.IO;
using Textify.General;

namespace VisualCard.Parts.Implementations
{
/// <summary>
/// Client PID map info
/// </summary>
[DebuggerDisplay("Client PID Map = {PidNum};{PidUri}")]
public class ClientPidMapInfo : BaseCardPartInfo, IEquatable<ClientPidMapInfo>
{
/// <summary>
/// Client PID number
/// </summary>
public int PidNum { get; }

/// <summary>
/// Client PID URI
/// </summary>
public string? PidUri { get; }

internal static BaseCardPartInfo FromStringVcardStatic(string value, string[] finalArgs, int altId, string[] elementTypes, string group, string valueType, Version cardVersion) =>
new ClientPidMapInfo().FromStringVcardInternal(value, finalArgs, altId, elementTypes, group, valueType, cardVersion);

internal override string ToStringVcardInternal(Version cardVersion) =>
$"{PidNum};{PidUri ?? ""}";

internal override BaseCardPartInfo FromStringVcardInternal(string value, string[] finalArgs, int altId, string[] elementTypes, string group, string valueType, Version cardVersion)
{
// Split the client PID map info
if (!value.Contains(";"))
throw new InvalidDataException($"Client PID map representation is invalid: {value}");

// Parse the info
string pidNumStr = value.Substring(0, value.IndexOf(";"));
string pidUriStr = value.RemoveSuffix($"{pidNumStr};");
if (!int.TryParse(pidNumStr, out int pidNum))
throw new InvalidDataException($"PID number {pidNumStr} is invalid");
if (!Uri.TryCreate(pidUriStr, UriKind.Absolute, out Uri uri))
throw new InvalidDataException($"PID URI {pidUriStr} is invalid");
pidUriStr = uri.ToString();

// Populate the fields
ClientPidMapInfo _source = new(altId, finalArgs, elementTypes, valueType, group, pidNum, pidUriStr);
return _source;
}

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

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

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

// Check all the properties
return
source.PidNum == target.PidNum &&
source.PidUri == target.PidUri
;
}

/// <inheritdoc/>
public override int GetHashCode()
{
int hashCode = -659626044;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + PidNum.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<string?>.Default.GetHashCode(PidUri);
return hashCode;
}

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

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

internal override bool EqualsInternal(BaseCardPartInfo source, BaseCardPartInfo target) =>
((ClientPidMapInfo)source) == ((ClientPidMapInfo)target);

internal ClientPidMapInfo() { }

internal ClientPidMapInfo(int altId, string[] arguments, string[] elementTypes, string valueType, string group, int pidNum, string pidUri) :
base(arguments, altId, elementTypes, valueType, group)
{
PidNum = pidNum;
PidUri = pidUri;
}
}
}
114 changes: 114 additions & 0 deletions VisualCard/Parts/Implementations/RelatedInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// 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.IO;

namespace VisualCard.Parts.Implementations
{
/// <summary>
/// Related URI info
/// </summary>
[DebuggerDisplay("Related URI = {Related}")]
public class RelatedInfo : BaseCardPartInfo, IEquatable<RelatedInfo>
{
/// <summary>
/// Encoded related URI
/// </summary>
public string? RelatedUri { get; }

internal static BaseCardPartInfo FromStringVcardStatic(string value, string[] finalArgs, int altId, string[] elementTypes, string group, string valueType, Version cardVersion) =>
new RelatedInfo().FromStringVcardInternal(value, finalArgs, altId, elementTypes, group, valueType, cardVersion);

internal override string ToStringVcardInternal(Version cardVersion) =>
RelatedUri ?? "";

internal override BaseCardPartInfo FromStringVcardInternal(string value, string[] finalArgs, int altId, string[] elementTypes, string group, string valueType, Version cardVersion)
{
// Try to parse the source to ensure that it conforms the IETF RFC 1738: Uniform Resource Locators
if (!Uri.TryCreate(value, UriKind.Absolute, out Uri uri))
throw new InvalidDataException($"source {value} is invalid");
value = uri.ToString();

// Populate the fields
RelatedInfo _source = new(altId, finalArgs, elementTypes, valueType, group, value);
return _source;
}

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

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

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

// Check all the properties
return
source.RelatedUri == target.RelatedUri
;
}

/// <inheritdoc/>
public override int GetHashCode()
{
int hashCode = 881496785;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<string?>.Default.GetHashCode(RelatedUri);
return hashCode;
}

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

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

internal override bool EqualsInternal(BaseCardPartInfo source, BaseCardPartInfo target) =>
((RelatedInfo)source) == ((RelatedInfo)target);

internal RelatedInfo() { }

internal RelatedInfo(int altId, string[] arguments, string[] elementTypes, string valueType, string group, string source) :
base(arguments, altId, elementTypes, valueType, group)
{
RelatedUri = source;
}
}
}

0 comments on commit 60ff9b1

Please sign in to comment.