Skip to content

Commit

Permalink
add - doc - Added MEMBER group property
Browse files Browse the repository at this point in the history
---

We've added MEMBER, a group property that lists group members and is crucial for group vCards.

---

Type: add
Breaking: False
Doc Required: True
Backport Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Sep 29, 2024
1 parent 14de3ee commit 229e0f1
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 0 deletions.
3 changes: 3 additions & 0 deletions VisualCard/Parsers/VcardConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,8 @@ internal static class VcardConstants
internal const string _contactUriSpecifier = "CONTACT-URI";
internal const string _altIdArgumentSpecifier = "ALTID=";
internal const string _prefArgumentSpecifier = "PREF=";

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

// Extensions are allowed
_ => true,
Expand Down Expand Up @@ -183,6 +184,7 @@ internal static string GetPrefixFromPartsArrayEnum(PartsArrayEnum partsArrayEnum
PartsArrayEnum.Source => VcardConstants._sourceSpecifier,
PartsArrayEnum.Url => VcardConstants._urlSpecifier,
PartsArrayEnum.ContactUri => VcardConstants._contactUriSpecifier,
PartsArrayEnum.Member => VcardConstants._memberSpecifier,

// Extensions are allowed
PartsArrayEnum.NonstandardNames => VcardConstants._xSpecifier,
Expand Down Expand Up @@ -259,6 +261,8 @@ internal static (PartsArrayEnum, PartCardinality) GetPartsArrayEnumFromType(Type
return (PartsArrayEnum.CalendarSchedulingRequestUrl, PartCardinality.Any);
else if (partsArrayType == typeof(ContactUriInfo))
return (PartsArrayEnum.ContactUri, PartCardinality.Any);
else if (partsArrayType == typeof(MemberInfo))
return (PartsArrayEnum.Member, PartCardinality.Any);

// Extensions are allowed
else if (partsArrayType == typeof(XNameInfo))
Expand Down Expand Up @@ -301,6 +305,7 @@ internal static (PartType type, object enumeration, Type? enumType, Func<string,
VcardConstants._calUriSpecifier => (PartType.PartsArray, PartsArrayEnum.CalendarUrl, typeof(CalendarUrlInfo), CalendarUrlInfo.FromStringVcardStatic, "", "", []),
VcardConstants._caladrUriSpecifier => (PartType.PartsArray, PartsArrayEnum.CalendarSchedulingRequestUrl, typeof(CalendarSchedulingRequestUrlInfo), CalendarSchedulingRequestUrlInfo.FromStringVcardStatic, "", "", []),
VcardConstants._contactUriSpecifier => (PartType.PartsArray, PartsArrayEnum.ContactUri, typeof(ContactUriInfo), ContactUriInfo.FromStringVcardStatic, "", "", []),
VcardConstants._memberSpecifier => (PartType.PartsArray, PartsArrayEnum.Member, typeof(MemberInfo), MemberInfo.FromStringVcardStatic, "", "", []),
VcardConstants._kindSpecifier => (PartType.Strings, StringsEnum.Kind, null, null, "", "", []),
VcardConstants._mailerSpecifier => (PartType.Strings, StringsEnum.Mailer, null, null, "", "", []),
VcardConstants._productIdSpecifier => (PartType.Strings, StringsEnum.ProductId, 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 @@ -153,6 +153,10 @@ public enum PartsArrayEnum
/// </summary>
ContactUri,
/// <summary>
/// The group member URI
/// </summary>
Member,
/// <summary>
/// The contact's extended IANA options (usually starts with SOMETHING:Value1;Value2...)
/// </summary>
IanaNames = int.MaxValue - 2,
Expand Down
114 changes: 114 additions & 0 deletions VisualCard/Parts/Implementations/MemberInfo.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>
/// Group member URI info
/// </summary>
[DebuggerDisplay("Member URI = {Member}")]
public class MemberInfo : BaseCardPartInfo, IEquatable<MemberInfo>
{
/// <summary>
/// Encoded group member URI
/// </summary>
public string? MemberUri { get; }

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

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

internal override BaseCardPartInfo FromStringVcardInternal(string value, string[] finalArgs, int altId, string[] elementTypes, 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
MemberInfo _source = new(altId, finalArgs, elementTypes, valueType, value);
return _source;
}

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

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

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

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

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

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

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

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

internal MemberInfo() { }

internal MemberInfo(int altId, string[] arguments, string[] elementTypes, string valueType, string source) :
base(arguments, altId, elementTypes, valueType)
{
MemberUri = source;
}
}
}

0 comments on commit 229e0f1

Please sign in to comment.