From f48fc471f2cf12f96834933365a28a8df6ac288f Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Thu, 28 Mar 2024 11:31:53 +0100 Subject: [PATCH] Drop EmailAddressCollection (#382) --- .../Email_address_collection_specs.cs | 21 - specs/Qowaiv.Specs/Qowaiv.Specs.csproj | 2 +- specs/Qowaiv.Specs/TestTools/Svo.cs | 3 - .../_Legacy/EmailAddressCollectionTest.cs | 258 ------------ src/Qowaiv/EmailAddressCollection.cs | 391 ------------------ .../Extensions/System.Linq.Enumerable.cs | 5 - src/Qowaiv/Qowaiv.csproj | 8 +- 7 files changed, 4 insertions(+), 684 deletions(-) delete mode 100644 specs/Qowaiv.Specs/Email_address_collection_specs.cs delete mode 100644 specs/Qowaiv.Specs/_Legacy/EmailAddressCollectionTest.cs delete mode 100644 src/Qowaiv/EmailAddressCollection.cs diff --git a/specs/Qowaiv.Specs/Email_address_collection_specs.cs b/specs/Qowaiv.Specs/Email_address_collection_specs.cs deleted file mode 100644 index 4690606c..00000000 --- a/specs/Qowaiv.Specs/Email_address_collection_specs.cs +++ /dev/null @@ -1,21 +0,0 @@ -#if NET8_0_OR_GREATER -#else -namespace Email_address_collection_specs; - -public class Supports_binary_serialization -{ - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.EmailAddressCollection); - round_tripped.Should().BeEquivalentTo(Svo.EmailAddressCollection); - } - [Test] - public void storing_string_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.EmailAddressCollection); - info.GetString("Value").Should().Be("info@qowaiv.org,test@qowaiv.org"); - } -} -#endif diff --git a/specs/Qowaiv.Specs/Qowaiv.Specs.csproj b/specs/Qowaiv.Specs/Qowaiv.Specs.csproj index 9667dfae..5605c4cf 100644 --- a/specs/Qowaiv.Specs/Qowaiv.Specs.csproj +++ b/specs/Qowaiv.Specs/Qowaiv.Specs.csproj @@ -32,9 +32,9 @@ - + diff --git a/specs/Qowaiv.Specs/TestTools/Svo.cs b/specs/Qowaiv.Specs/TestTools/Svo.cs index a54d062d..1affbe71 100644 --- a/specs/Qowaiv.Specs/TestTools/Svo.cs +++ b/specs/Qowaiv.Specs/TestTools/Svo.cs @@ -43,9 +43,6 @@ public static class Svo /// info@qowaiv.org public static readonly EmailAddress EmailAddress = EmailAddress.Parse("info@qowaiv.org"); - /// info@qowaiv.org,test@qowaiv.org" - public static EmailAddressCollection EmailAddressCollection => EmailAddressCollection.Parse("info@qowaiv.org,test@qowaiv.org"); - /// 1732.4 public static readonly Elo Elo = 1732.4; diff --git a/specs/Qowaiv.Specs/_Legacy/EmailAddressCollectionTest.cs b/specs/Qowaiv.Specs/_Legacy/EmailAddressCollectionTest.cs deleted file mode 100644 index 28ad1604..00000000 --- a/specs/Qowaiv.Specs/_Legacy/EmailAddressCollectionTest.cs +++ /dev/null @@ -1,258 +0,0 @@ -namespace Qowaiv.UnitTests; - -[TestFixture] -public class EmailAddressCollectionTest -{ - private static EmailAddressCollection GetTestInstance() - => EmailAddressCollection.Parse("info@qowaiv.org,test@qowaiv.org"); - - #region (XML) (De)serialization tests - - [Test] - public void DataContractSerializeDeserialize_TestStruct_AreEqual() - { - var input = GetTestInstance(); - var exp = GetTestInstance(); - var act = SerializeDeserialize.DataContract(input); - act.Should().BeEquivalentTo(exp); - } - - [Test] - public void XmlSerialize_TestStruct_AreEqual() - { - var act = Serialize.Xml(GetTestInstance()); - var exp = "info@qowaiv.org,test@qowaiv.org"; - act.Should().Be(exp); - } - - [Test] - public void XmlDeserialize_XmlString_AreEqual() - { - var act = Deserialize.Xml("info@qowaiv.org,test@qowaiv.org"); - act.Should().BeEquivalentTo(GetTestInstance()); - } - - [Test] - public void DataContractSerializeDeserialize_EmailAddressSerializeObject_AreEqual() - { - var input = new EmailAddressCollectionSerializeObject - { - Id = 17, - Obj = GetTestInstance(), - Date = new DateTime(1970, 02, 14, 00, 00, 000, DateTimeKind.Local), - }; - var exp = new EmailAddressCollectionSerializeObject - { - Id = 17, - Obj = GetTestInstance(), - Date = new DateTime(1970, 02, 14, 00, 00, 000, DateTimeKind.Local), - }; - var act = SerializeDeserialize.DataContract(input); - Assert.AreEqual(exp.Id, act.Id, "Id"); - CollectionAssert.AreEqual(exp.Obj, act.Obj, "Obj"); - Assert.AreEqual(exp.Date, act.Date, "Date"); - } - - [Test] - public void XmlSerializeDeserialize_Empty_AreEqual() - { - var input = new EmailAddressCollectionSerializeObject - { - Id = 17, - Obj = [], - Date = new DateTime(1970, 02, 14, 00, 00, 000, DateTimeKind.Local), - }; - var exp = new EmailAddressCollectionSerializeObject - { - Id = 17, - Obj = [], - Date = new DateTime(1970, 02, 14, 00, 00, 000, DateTimeKind.Local), - }; - var act = SerializeDeserialize.Xml(input); - Assert.AreEqual(exp.Id, act.Id, "Id"); - CollectionAssert.AreEqual(exp.Obj, act.Obj, "Obj"); - Assert.AreEqual(exp.Date, act.Date, "Date"); - } - - [Test] - public void GetSchema_None_IsNull() - { - IXmlSerializable obj = GetTestInstance(); - obj.GetSchema().Should().BeNull(); - } - - #endregion - - #region ToString - - [Test] - public void ToString_EmptyCollection_StringEmpty() - { - var collection = new EmailAddressCollection(); - - var exp = string.Empty; - var act = collection.ToString(); - - act.Should().Be(exp); - } - - [Test] - public void ToString_1Item_infoAtQowaivDotOrg() - { - var collection = new EmailAddressCollection(EmailAddress.Parse("info@qowaiv.org")); - - var exp = "info@qowaiv.org"; - var act = collection.ToString(); - - act.Should().Be(exp); - } - - [Test] - public void ToString_2Items_infoAtQowaivDotOrgCommaTestAtQowaivDotOrg() - { - var collection = new EmailAddressCollection(EmailAddress.Parse("info@qowaiv.org"), EmailAddress.Parse("test@qowaiv.org")); - - var exp = "info@qowaiv.org,test@qowaiv.org"; - var act = collection.ToString(); - - act.Should().Be(exp); - } - - [Test] - public void ToString_CustomFormatter_SupportsCustomFormatting() - { - var act = GetTestInstance().ToString("U", FormatProvider.CustomFormatter); - var exp = "Unit Test Formatter, value: 'INFO@QOWAIV.ORG,TEST@QOWAIV.ORG', format: 'U'"; - - act.Should().Be(exp); - } - - [Test] - public void ToString_TestStructFormatMailToF_AreEqual() - { - var act = GetTestInstance().ToString(@"mai\lto:f"); - var exp = "mailto:info@qowaiv.org,mailto:test@qowaiv.org"; - act.Should().Be(exp); - } - - #endregion - - #region Methods - - [Test] - public void Add_EmailAddressEmptyToEmptyCollection_DoesNotExtendTheCollection() - { - var exp = new EmailAddressCollection(); - var act = new EmailAddressCollection - { - EmailAddress.Empty - }; - - act.Should().BeEquivalentTo(exp); - } - - [Test] - public void Add_EmailAddressUnknownToEmptyCollection_DoesNotExtendTheCollection() - { - var exp = new EmailAddressCollection(); - var act = new EmailAddressCollection - { - EmailAddress.Unknown - }; - - act.Should().BeEquivalentTo(exp); - } - - [Test] - public void Add_EmailAddressEmptyToCollection_DoesNotExtendTheCollection() - { - var exp = GetTestInstance(); - var act = GetTestInstance(); - act.Add(EmailAddress.Empty); - - act.Should().BeEquivalentTo(exp); - } - - [Test] - public void Add_EmailAddressUnknownToCollection_DoesNotExtendTheCollection() - { - var exp = GetTestInstance(); - var act = GetTestInstance(); - act.Add(EmailAddress.Unknown); - - act.Should().BeEquivalentTo(exp); - } - - #endregion - - #region (Try)parse - - [Test] - public void TryParse_TestInstanceWithUnknownAdded_EqualsTestInstance() - { - var act = EmailAddressCollection.Parse("info@qowaiv.org,test@qowaiv.org,?"); - var exp = GetTestInstance(); - - act.Should().BeEquivalentTo(exp); - } - - [Test] - public void TryParse_Null_EmptyCollection() - { - EmailAddressCollection exp = []; - EmailAddressCollection.TryParse(null, out EmailAddressCollection act).Should().BeTrue(); - act.Should().BeEquivalentTo(exp); - } - - [Test] - public void TryParse_StringEmpty_EmptyCollection() - { - EmailAddressCollection exp = []; - EmailAddressCollection.TryParse(string.Empty, out EmailAddressCollection act).Should().BeTrue(); - act.Should().BeEquivalentTo(exp); - } - - [Test] - public void TryParse_Invalid_EmptyCollection() - { - var act = EmailAddressCollection.TryParse("invalid"); - var exp = new EmailAddressCollection(); - - act.Should().BeEquivalentTo(exp); - } - - [Test] - public void TryParse_SingleEmailAddress_CollectionWithOneItems() - { - var act = EmailAddressCollection.TryParse("svo@qowaiv.org"); - var exp = new EmailAddressCollection { EmailAddress.Parse("svo@qowaiv.org") }; - - act.Should().BeEquivalentTo(exp); - } - - #endregion - - #region Extensions - - [Test] - public void ToCollection_enumeration_of_EmailAddresses_EmailAddressCollection() - { - var collection = EmailAddressCollection.Parse("mail@qowaiv.org,info@qowaiv.org,test@qowaiv.org").AsEnumerable(); - - var act = collection.ToCollection(); - var exp = EmailAddressCollection.Parse("mail@qowaiv.org,info@qowaiv.org,test@qowaiv.org"); - - Assert.AreEqual(typeof(EmailAddressCollection), act.GetType(), "The outcome of to collection should be an email address collection."); - act.Should().BeEquivalentTo(exp); - } - - #endregion -} - -[Serializable] -public class EmailAddressCollectionSerializeObject -{ - public int Id { get; set; } - public EmailAddressCollection? Obj { get; set; } - public DateTime Date { get; set; } -} diff --git a/src/Qowaiv/EmailAddressCollection.cs b/src/Qowaiv/EmailAddressCollection.cs deleted file mode 100644 index eeb881dc..00000000 --- a/src/Qowaiv/EmailAddressCollection.cs +++ /dev/null @@ -1,391 +0,0 @@ -namespace Qowaiv; - -/// Represents a collection of unique email addresses. -/// -/// Empty and unknown email addresses can not be added. -/// -[Serializable] -[OpenApiDataType(description: "Comma separated list of email addresses defined by RFC 5322.", example: "info@qowaiv.org,test@test.com", type: "string", format: "email-collection", nullable: true)] -public class EmailAddressCollection : ISet, ISerializable, IXmlSerializable, IFormattable -#if NET8_0_OR_GREATER - , IParsable -#endif -{ - /// The email address separator is a comma. - /// - /// According to RFC 6068: http://tools.ietf.org/html/rfc6068. - /// - public const string Separator = ","; - - /// The separators used for parsing. - /// - /// Both comma and semicolon are supported. - /// - private static readonly char[] Separators = [',', ';']; - - /// The underlying hash set. - /// - /// The only proper way to block the adding of empty and unknown - /// email addresses was by overriding Add, which is not allowed if - /// derived from HasSet<EmailAddress>. - /// - /// So this construction is required. - /// - private readonly HashSet hashset = []; - - /// Initializes a new instance of the class. - public EmailAddressCollection() { } - - /// Initializes a new instance of the class. - /// - /// An array of email addresses. - /// - public EmailAddressCollection(params EmailAddress[] emails) - : this((IEnumerable)emails) { } - - /// Initializes a new instance of the class. - /// - /// An enumeration of email addresses. - /// - public EmailAddressCollection(IEnumerable emails) - : this() => AddRange(emails); - - /// Adds an email address to the current collection and returns - /// a value to indicate if the email address was successfully added. - /// - /// - /// The email address to add. - /// - [CollectionMutation] - public bool Add(EmailAddress item) - => !item.IsEmptyOrUnknown() - && hashset.Add(item); - - /// Keeps only the distinct set of email addresses in the collection. - public void AddRange(IEnumerable emails) - { - Guard.NotNull(emails); - foreach (var email in emails) - { - Add(email); - } - } - - /// Gets the number of email addresses in the collection. - [ExcludeFromCodeCoverage] - public int Count => hashset.Count; - - /// Returns false as this collection is not read only. - [ExcludeFromCodeCoverage] - public bool IsReadOnly => false; - - /// Adds an email address to the current collection. - [ExcludeFromCodeCoverage] - - void ICollection.Add(EmailAddress email) => Add(email); - - /// Clears all email addresses From current collection. - [ExcludeFromCodeCoverage] - public void Clear() => hashset.Clear(); - - /// Returns true if the collection contains the specified email address. - [ExcludeFromCodeCoverage] - [Pure] - public bool Contains(EmailAddress item) => hashset.Contains(item); - - /// Copies the email addresses of the collection to an - /// System.Array, starting at a particular System.Array index. - /// - [ExcludeFromCodeCoverage] - public void CopyTo(EmailAddress[] array, int arrayIndex) => hashset.CopyTo(array, arrayIndex); - - /// Removes the email address from the collection. - [ExcludeFromCodeCoverage] - [CollectionMutation] - public bool Remove(EmailAddress item) => hashset.Remove(item); - - /// Gets an enumerator to loop through all email addresses of the collection. - [ExcludeFromCodeCoverage] - [Pure] - public IEnumerator GetEnumerator() => hashset.GetEnumerator(); - - /// Gets an enumerator to loop through all email addresses of the collection. - [ExcludeFromCodeCoverage] - [Pure] - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// Removes all elements in the specified collection from the current set. - [ExcludeFromCodeCoverage] - public void ExceptWith(IEnumerable other) => hashset.ExceptWith(other); - - /// Modifies the current set so that it contains only elements that are also in a specified collection. - [ExcludeFromCodeCoverage] - public void IntersectWith(IEnumerable other) => hashset.IntersectWith(other); - - /// Determines whether the current set is a proper (strict) subset of a specified collection. - [ExcludeFromCodeCoverage] - [Pure] - public bool IsProperSubsetOf(IEnumerable other) => hashset.IsProperSubsetOf(other); - - /// Determines whether the current set is a proper (strict) superset of a specified collection. - [ExcludeFromCodeCoverage] - [Pure] - public bool IsProperSupersetOf(IEnumerable other) => hashset.IsProperSupersetOf(other); - - /// Determines whether a set is a subset of a specified collection. - [ExcludeFromCodeCoverage] - [Pure] - public bool IsSubsetOf(IEnumerable other) => hashset.IsSubsetOf(other); - - /// Determines whether a set is a superset of a specified collection. - [ExcludeFromCodeCoverage] - [Pure] - public bool IsSupersetOf(IEnumerable other) => hashset.IsSupersetOf(other); - - /// Determines whether the current set overlaps with the specified collection. - [ExcludeFromCodeCoverage] - [Pure] - public bool Overlaps(IEnumerable other) => hashset.Overlaps(other); - - /// Determines whether the current set and the specified collection contain the same elements. - [ExcludeFromCodeCoverage] - [Pure] - public bool SetEquals(IEnumerable other) => hashset.SetEquals(other); - - /// Modifies the current set so that it contains only elements that are present - /// either in the current set or in the specified collection, but not both. - /// - [ExcludeFromCodeCoverage] - public void SymmetricExceptWith(IEnumerable other) => hashset.SymmetricExceptWith(other); - - /// Modifies the current set so that it contains all elements that are present - /// in either the current set or the specified collection. - /// - [ExcludeFromCodeCoverage] - public void UnionWith(IEnumerable other) => hashset.UnionWith(other); - - /// Initializes a new instance of the class. - /// The serialization info. - /// The streaming context. - protected EmailAddressCollection(SerializationInfo info, StreamingContext context) - : this() - { - Guard.NotNull(info); - AddRange(Parse(info.GetString("Value"), CultureInfo.InvariantCulture)); - } - - /// Adds the underlying property of email address to the serialization info. - /// The serialization info. - /// The streaming context. - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { GetObjectData(info, context); } - - /// Adds the underlying property of email address to the serialization info. - /// - /// this is used by ISerializable.GetObjectData() so that it can be changed by derived classes. - /// - protected virtual void GetObjectData(SerializationInfo info, StreamingContext context) - { - Guard.NotNull(info); - info.AddValue("Value", ToString()); - } - - /// Gets the to (de) XML serialize an email address. - /// - /// Returns null as no schema is required. - /// - [Pure] - XmlSchema? IXmlSerializable.GetSchema() => GetSchema(); - - /// Gets the to (de) XML serialize an email address. - /// - /// this is used by IXmlSerializable.GetSchema() so that it can be changed by derived classes. - /// - [Pure] - protected virtual XmlSchema? GetSchema() => null; - - /// Reads the email address from an . - /// An XML reader. - void IXmlSerializable.ReadXml(XmlReader reader) { ReadXml(reader); } - - /// Reads the email address from an . - /// An XML reader. - /// - /// this is used by IXmlSerializable.ReadXml() so that it can be changed by derived classes. - /// - protected virtual void ReadXml(XmlReader reader) - { - Guard.NotNull(reader); - var s = reader.ReadElementString(); - var val = Parse(s, CultureInfo.InvariantCulture); - AddRange(val); - } - - /// Writes the email address to an . - /// An XML writer. - void IXmlSerializable.WriteXml(XmlWriter writer) => WriteXml(writer); - - /// Writes the email address to an . - /// - /// this is used by IXmlSerializable.WriteXml() so that it can be - /// changed by derived classes. - /// - protected virtual void WriteXml(XmlWriter writer) - { - Guard.NotNull(writer); - writer.WriteString(ToString(CultureInfo.InvariantCulture)); - } - - /// Deserializes the email address collection from a JSON string. - /// - /// The JSON number to deserialize. - /// - /// - /// The deserialized email address collection. - /// - [Pure] - public static EmailAddressCollection FromJson(string? json) => Parse(json, CultureInfo.InvariantCulture); - - /// Serializes the email address collection to a JSON node. - /// - /// The serialized JSON string. - /// - [Pure] - public virtual string? ToJson() => Count == 0 ? null : ToString(CultureInfo.InvariantCulture); - - /// Returns a that represents the current email address collection. - [Pure] - public override string ToString() => ToString(CultureInfo.CurrentCulture); - - /// Returns a formatted that represents the current email address collection. - /// - /// The format that describes the formatting. - /// - [Pure] - public string ToString(string? format) => ToString(format, CultureInfo.CurrentCulture); - - /// Returns a formatted that represents the current email address collection. - /// - /// The format provider. - /// - [Pure] - public string ToString(IFormatProvider? formatProvider) => ToString(string.Empty, formatProvider); - - /// Returns a formatted that represents the current email address collection. - /// - /// The format that describes the formatting. - /// - /// - /// The format provider. - /// - [Pure] - public string ToString(string? format, IFormatProvider? formatProvider) - => StringFormatter.TryApplyCustomFormatter(format, this, formatProvider, out string formatted) - ? formatted - : string.Join(Separator, this.Select(emailaddress => emailaddress.ToString(format, formatProvider))); - - /// Converts the string to an email address collection. - /// - /// A string containing an email address to convert. - /// - /// - /// An email address. - /// - /// - /// s is not in the correct format. - /// - [Pure] - public static EmailAddressCollection Parse(string? s) => Parse(s, CultureInfo.CurrentCulture); - - /// Converts the string to an email address collection. - /// - /// A string containing an email address to convert. - /// - /// - /// The specified format provider. - /// - /// - /// An email address. - /// - /// - /// s is not in the correct format. - /// - [Pure] - public static EmailAddressCollection Parse(string? s, IFormatProvider? provider) - => TryParse(s, provider, out EmailAddressCollection val) - ? val - : throw Unparsable.ForValue(s, QowaivMessages.FormatExceptionEmailAddressCollection); - - /// Converts the string to an email address collection. - /// A return value indicates whether the conversion succeeded. - /// - /// - /// A string containing an email address to convert. - /// - /// - /// The email address if the string was converted successfully, otherwise an empty EmailAddressCollection(). - /// - [Pure] - public static EmailAddressCollection TryParse(string? s) - { - if (TryParse(s, out EmailAddressCollection val)) - { - return val; - } - return []; - } - - /// Converts the string to an email address collection. - /// A return value indicates whether the conversion succeeded. - /// - /// - /// A string containing an email address to convert. - /// - /// - /// The result of the parsing. - /// - /// - /// True if the string was converted successfully, otherwise false. - /// - public static bool TryParse(string? s, out EmailAddressCollection result) - { - return TryParse(s, CultureInfo.CurrentCulture, out result); - } - - /// Converts the string to an email address collection. - /// A return value indicates whether the conversion succeeded. - /// - /// - /// A string containing an email address to convert. - /// - /// - /// The specified format provider. - /// - /// - /// The result of the parsing. - /// - /// - /// True if the string was converted successfully, otherwise false. - /// - public static bool TryParse(string? s, IFormatProvider? provider, out EmailAddressCollection result) - { - result = []; - if (s is { Length: > 0 }) - { - var strs = s.Split(Separators, StringSplitOptions.RemoveEmptyEntries).Select(str => str.Trim()); - foreach (var str in strs) - { - if (EmailAddress.TryParse(str, provider, out EmailAddress email)) - { - result.Add(email); - } - else - { - result.Clear(); - return false; - } - } - return result.Count != 0; - } - else return true; - } -} diff --git a/src/Qowaiv/Extensions/System.Linq.Enumerable.cs b/src/Qowaiv/Extensions/System.Linq.Enumerable.cs index 6d68905b..41e6d4fd 100644 --- a/src/Qowaiv/Extensions/System.Linq.Enumerable.cs +++ b/src/Qowaiv/Extensions/System.Linq.Enumerable.cs @@ -785,11 +785,6 @@ public static Money Sum(this IEnumerable source) public static StreamSize Sum(this IEnumerable streamSizes) => new(streamSizes.Sum(streamSize => (long)streamSize)); - /// Converts the enumeration into an . - [Pure] - public static EmailAddressCollection ToCollection(this IEnumerable adresses) - => new(adresses); - [Pure] private static InvalidOperationException NoElements() => new(QowaivMessages.InvalidOperationException_NoElements); } diff --git a/src/Qowaiv/Qowaiv.csproj b/src/Qowaiv/Qowaiv.csproj index 6d76f29b..6bc67cb0 100644 --- a/src/Qowaiv/Qowaiv.csproj +++ b/src/Qowaiv/Qowaiv.csproj @@ -5,15 +5,11 @@ netstandard2.0;net6.0;net8.0 true - 6.6.1 - Qowaiv - -v6.6.1 -- Add missing IParsable interface for Id. #372 7.0.0 Qowaiv v7.0.0 +- Drop email address collection. #382 (breaking) - Clock.Now returns DateTimeOffset. (breaking) - Clock.NowWithOffset is dropped. (breaking) - Extension methods on DateTimeOffset. @@ -39,6 +35,8 @@ v7.0.0 - Drop support for .NET 5 and .NET 7 STS's. #359 (breaking) - Deserializing ID's from JSON numeric nodes takes constrains into account. #374 - Move Qowaiv.Diagnostics.Contracs to a seperate package. (breaking) +v6.6.1 +- Add missing IParsable interface for Id. #372 v6.6.0 - Add former countries. #357 - Update display names countries (EN, DE, NL). #356