diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-01-17 20:40:36 -0800 |
---|---|---|
committer | Andrew <andrewarnott@gmail.com> | 2009-01-17 20:40:36 -0800 |
commit | 07efff0df7929c836dfe38a0076cc7ee6ed316ff (patch) | |
tree | 377b83cb63b3bc7613a90c684088fb60f8894a89 | |
parent | f69dda1b9a4551597f3afebfcba684468604ce03 (diff) | |
download | DotNetOpenAuth-07efff0df7929c836dfe38a0076cc7ee6ed316ff.zip DotNetOpenAuth-07efff0df7929c836dfe38a0076cc7ee6ed316ff.tar.gz DotNetOpenAuth-07efff0df7929c836dfe38a0076cc7ee6ed316ff.tar.bz2 |
Added GetHashCode() methods to the AX classes, and fixed their Equals methods.
StyleCop clean.
9 files changed, 363 insertions, 110 deletions
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs index a765d57..aee9f30 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs @@ -20,6 +20,9 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Simulates an extension request and response. /// </summary> + /// <param name="protocol">The protocol to use in the roundtripping.</param> + /// <param name="requests">The extensions to add to the request message.</param> + /// <param name="responses">The extensions to add to the response message.</param> /// <remarks> /// This method relies on the extension objects' Equals methods to verify /// accurate transport. The Equals methods should be verified by separate tests. diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj index 626bc1f..736d273 100644 --- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj +++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj @@ -186,6 +186,7 @@ <Compile Include="OpenId\Extensions\AliasManager.cs" /> <Compile Include="OpenId\Extensions\AttributeExchange\AttributeRequest.cs" /> <Compile Include="OpenId\Extensions\AttributeExchange\AttributeValues.cs" /> + <Compile Include="OpenId\Extensions\AttributeExchange\AXUtilities.cs" /> <Compile Include="OpenId\Extensions\AttributeExchange\Constants.cs" /> <Compile Include="OpenId\Extensions\AttributeExchange\FetchRequest.cs" /> <Compile Include="OpenId\Extensions\AttributeExchange\FetchResponse.cs" /> diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXUtilities.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXUtilities.cs new file mode 100644 index 0000000..b9faedb --- /dev/null +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXUtilities.cs @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------- +// <copyright file="AXUtilities.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { + using System; + using System.Collections.Generic; + using System.Globalization; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// Helper methods shared by multiple messages in the Attribute Exchange extension. + /// </summary> + internal class AXUtilities { + /// <summary> + /// Serializes a set of attribute values to a dictionary of fields to send in the message. + /// </summary> + /// <param name="fields">The dictionary to fill with serialized attributes.</param> + /// <param name="attributes">The attributes.</param> + internal static void SerializeAttributes(IDictionary<string, string> fields, IEnumerable<AttributeValues> attributes) { + ErrorUtilities.VerifyArgumentNotNull(fields, "fields"); + ErrorUtilities.VerifyArgumentNotNull(attributes, "attributes"); + + AliasManager aliasManager = new AliasManager(); + foreach (var att in attributes) { + string alias = aliasManager.GetAlias(att.TypeUri); + fields.Add("type." + alias, att.TypeUri); + if (att.Values == null) { + continue; + } + if (att.Values.Count != 1) { + fields.Add("count." + alias, att.Values.Count.ToString(CultureInfo.InvariantCulture)); + for (int i = 0; i < att.Values.Count; i++) { + fields.Add(string.Format(CultureInfo.InvariantCulture, "value.{0}.{1}", alias, i + 1), att.Values[i]); + } + } else { + fields.Add("value." + alias, att.Values[0]); + } + } + } + + /// <summary> + /// Deserializes attribute values from an incoming set of message data. + /// </summary> + /// <param name="fields">The data coming in with the message.</param> + /// <returns>The attribute values found in the message.</returns> + internal static IEnumerable<AttributeValues> DeserializeAttributes(IDictionary<string, string> fields) { + AliasManager aliasManager = ParseAliases(fields); + foreach (string alias in aliasManager.Aliases) { + AttributeValues att = new AttributeValues(aliasManager.ResolveAlias(alias)); + int count = 1; + bool countSent = false; + string countString; + if (fields.TryGetValue("count." + alias, out countString)) { + if (!int.TryParse(countString, out count) || count <= 0) { + Logger.ErrorFormat("Failed to parse count.{0} value to a positive integer.", alias); + continue; + } + countSent = true; + } + if (countSent) { + for (int i = 1; i <= count; i++) { + string value; + if (fields.TryGetValue(string.Format(CultureInfo.InvariantCulture, "value.{0}.{1}", alias, i), out value)) { + att.Values.Add(value); + } else { + Logger.ErrorFormat("Missing value for attribute '{0}'.", att.TypeUri); + continue; + } + } + } else { + string value; + if (fields.TryGetValue("value." + alias, out value)) { + att.Values.Add(value); + } else { + Logger.ErrorFormat("Missing value for attribute '{0}'.", att.TypeUri); + continue; + } + } + yield return att; + } + } + + /// <summary> + /// Reads through the attributes included in the response to discover + /// the alias-TypeURI relationships. + /// </summary> + /// <param name="fields">The data included in the extension message.</param> + /// <returns>The alias manager that provides lookup between aliases and type URIs.</returns> + private static AliasManager ParseAliases(IDictionary<string, string> fields) { + ErrorUtilities.VerifyArgumentNotNull(fields, "fields"); + + AliasManager aliasManager = new AliasManager(); + const string TypePrefix = "type."; + foreach (var pair in fields) { + if (!pair.Key.StartsWith(TypePrefix, StringComparison.Ordinal)) { + continue; + } + string alias = pair.Key.Substring(TypePrefix.Length); + if (alias.IndexOfAny(FetchRequest.IllegalAliasCharacters) >= 0) { + Logger.ErrorFormat("Illegal characters in alias name '{0}'.", alias); + continue; + } + aliasManager.SetAlias(alias, pair.Value); + } + return aliasManager; + } + } +} diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs index 6520be8..2f8559d 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs @@ -89,6 +89,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// Used by a Provider to create a response to a request for an attribute's value(s) /// using a given array of strings. /// </summary> + /// <param name="values">The values for the requested attribute.</param> /// <returns> /// The newly created <see cref="AttributeValues"/> object that should be added to /// the <see cref="FetchResponse"/> object. @@ -129,5 +130,23 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return true; } + + /// <summary> + /// Serves as a hash function for a particular type. + /// </summary> + /// <returns> + /// A hash code for the current <see cref="T:System.Object"/>. + /// </returns> + public override int GetHashCode() { + int hashCode = this.IsRequired ? 1 : 0; + unchecked { + hashCode += this.Count; + if (this.TypeUri != null) { + hashCode += this.TypeUri.GetHashCode(); + } + } + + return hashCode; + } } } diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs index db333ef..e87e188 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs @@ -19,6 +19,18 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// <summary> /// Initializes a new instance of the <see cref="AttributeValues"/> class. /// </summary> + /// <param name="typeUri">The TypeURI that uniquely identifies the attribute.</param> + /// <param name="values">The values for the attribute.</param> + public AttributeValues(string typeUri, params string[] values) { + ErrorUtilities.VerifyNonZeroLength(typeUri, "typeUri"); + + this.TypeUri = typeUri; + this.Values = (IList<string>)values ?? EmptyList<string>.Instance; + } + + /// <summary> + /// Initializes a new instance of the <see cref="AttributeValues"/> class. + /// </summary> /// <remarks> /// This is internal because web sites should be using the /// <see cref="AttributeRequest.Respond"/> method to instantiate. @@ -39,18 +51,6 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { } /// <summary> - /// Initializes a new instance of the <see cref="AttributeValues"/> class. - /// </summary> - /// <param name="typeUri">The TypeURI that uniquely identifies the attribute.</param> - /// <param name="values">The values for the attribute.</param> - public AttributeValues(string typeUri, params string[] values) { - ErrorUtilities.VerifyNonZeroLength(typeUri, "typeUri"); - - this.TypeUri = typeUri; - this.Values = (IList<string>)values ?? EmptyList<string>.Instance; - } - - /// <summary> /// Gets the URI uniquely identifying the attribute whose value is being supplied. /// </summary> public string TypeUri { get; internal set; } @@ -60,6 +60,16 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// </summary> public IList<string> Values { get; private set; } + /// <summary> + /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>. + /// </summary> + /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param> + /// <returns> + /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false. + /// </returns> + /// <exception cref="T:System.NullReferenceException"> + /// The <paramref name="obj"/> parameter is null. + /// </exception> public override bool Equals(object obj) { AttributeValues other = obj as AttributeValues; if (other == null) { @@ -76,5 +86,26 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return true; } + + /// <summary> + /// Serves as a hash function for a particular type. + /// </summary> + /// <returns> + /// A hash code for the current <see cref="T:System.Object"/>. + /// </returns> + public override int GetHashCode() { + int hashCode = 0; + unchecked { + if (this.TypeUri != null) { + hashCode += this.TypeUri.GetHashCode(); + } + + foreach (string value in this.Values) { + hashCode += value.GetHashCode(); + } + } + + return hashCode; + } } } diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs index b29d873..8386bce 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs @@ -30,11 +30,22 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return null; }; + /// <summary> + /// Characters that may not appear in an attribute alias list. + /// </summary> + internal static readonly char[] IllegalAliasListCharacters = new[] { '.', '\n' }; + + /// <summary> + /// Characters that may not appear in an attribute Type URI alias. + /// </summary> + internal static readonly char[] IllegalAliasCharacters = new[] { '.', ',', ':' }; + + /// <summary> + /// The value for the 'mode' parameter. + /// </summary> [MessagePart("mode", IsRequired = true)] private const string Mode = "fetch_request"; - private static readonly char[] IllegalAliasListCharacters = new[] { '.', '\n' }; - /// <summary> /// The list of requested attributes. This field will never be null. /// </summary> @@ -78,8 +89,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { private string RequiredAliases { get; set; } /// <summary> - /// Used by the Relying Party to add a request for the values of a given attribute. + /// Adds a request for the values of a given attribute. + /// Applicable to Relying Parties. /// </summary> + /// <param name="attribute">The attribute.</param> public void AddAttribute(AttributeRequest attribute) { ErrorUtilities.VerifyArgumentNotNull(attribute, "attribute"); ErrorUtilities.VerifyArgumentNamed(!this.ContainsAttribute(attribute.TypeUri), "attribute", OpenIdStrings.AttributeAlreadyAdded, attribute.TypeUri); @@ -87,9 +100,13 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { } /// <summary> - /// Used by the Provider to find out whether the value(s) of a given attribute is requested. + /// Find out whether the value(s) of a given attribute are being requested by the Relying Party. + /// Applicable to Providers. /// </summary> - /// <returns>Null if the Relying Party did not ask for the values of the given attribute.</returns> + /// <param name="attributeTypeUri">The type URI of the attribute.</param> + /// <returns> + /// The details of a Relying Party's request for the given attribute; or <c>null</c> if the relyign party did not ask for the values of the given attribute. + /// </returns> public AttributeRequest GetAttribute(string attributeTypeUri) { return this.attributesRequested.SingleOrDefault(attribute => string.Equals(attribute.TypeUri, attributeTypeUri, StringComparison.Ordinal)); } @@ -110,6 +127,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return false; } + if (this.Version != other.Version) { + return false; + } + if (this.UpdateUrl != other.UpdateUrl) { return false; } @@ -121,6 +142,28 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return true; } + /// <summary> + /// Serves as a hash function for a particular type. + /// </summary> + /// <returns> + /// A hash code for the current <see cref="T:System.Object"/>. + /// </returns> + public override int GetHashCode() { + unchecked { + int hashCode = this.Version.GetHashCode(); + + if (this.UpdateUrl != null) { + hashCode += this.UpdateUrl.GetHashCode(); + } + + foreach (AttributeRequest att in this.Attributes) { + hashCode += att.GetHashCode(); + } + + return hashCode; + } + } + #region IMessageWithEvents Members /// <summary> @@ -240,6 +283,11 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { } } + /// <summary> + /// Splits a list of aliases by their commas. + /// </summary> + /// <param name="aliasList">The comma-delimited list of aliases. May be null or empty.</param> + /// <returns>The list of aliases. Never null, but may be empty.</returns> private static IList<string> ParseAliasList(string aliasList) { if (string.IsNullOrEmpty(aliasList)) { return EmptyList<string>.Instance; @@ -248,6 +296,13 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return aliasList.Split(','); } + /// <summary> + /// Determines whether some attribute has values in this fetch request. + /// </summary> + /// <param name="typeUri">The type URI of the attribute in question.</param> + /// <returns> + /// <c>true</c> if the specified attribute appears in the fetch request; otherwise, <c>false</c>. + /// </returns> private bool ContainsAttribute(string typeUri) { return this.GetAttribute(typeUri) != null; } diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs index 3411012..1b3c05b 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs @@ -31,6 +31,9 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return null; }; + /// <summary> + /// The value of the 'mode' parameter. + /// </summary> [MessagePart("mode", IsRequired = true)] private const string Mode = "fetch_response"; @@ -69,8 +72,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { public Uri UpdateUrl { get; set; } /// <summary> - /// Used by the Provider to add attributes to the response for the relying party. + /// Adds attributes to the response for the relying party. + /// Applicable to Providers. /// </summary> + /// <param name="attribute">The attribute and values to add to the response.</param> public void AddAttribute(AttributeValues attribute) { ErrorUtilities.VerifyArgumentNotNull(attribute, "attribute"); ErrorUtilities.VerifyArgumentNamed(!this.ContainsAttribute(attribute.TypeUri), "attribute", OpenIdStrings.AttributeAlreadyAdded, attribute.TypeUri); @@ -78,9 +83,12 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { } /// <summary> - /// Used by the Relying Party to get the value(s) returned by the OpenID Provider + /// Gets the value(s) returned by the OpenID Provider /// for a given attribute, or null if that attribute was not provided. + /// Applicable to Relying Parties. /// </summary> + /// <param name="attributeTypeUri">The type URI of the attribute.</param> + /// <returns>The values given by the Provider for the given attribute; or <c>null</c> if the attribute was not included in the message.</returns> public AttributeValues GetAttribute(string attributeTypeUri) { return this.attributesProvided.SingleOrDefault(attribute => string.Equals(attribute.TypeUri, attributeTypeUri, StringComparison.Ordinal)); } @@ -101,6 +109,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return false; } + if (this.Version != other.Version) { + return false; + } + if (this.UpdateUrl != other.UpdateUrl) { return false; } @@ -112,6 +124,28 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return true; } + /// <summary> + /// Serves as a hash function for a particular type. + /// </summary> + /// <returns> + /// A hash code for the current <see cref="T:System.Object"/>. + /// </returns> + public override int GetHashCode() { + unchecked { + int hashCode = this.Version.GetHashCode(); + + if (this.UpdateUrl != null) { + hashCode += this.UpdateUrl.GetHashCode(); + } + + foreach (AttributeValues value in this.Attributes) { + hashCode += value.GetHashCode(); + } + + return hashCode; + } + } + #region IMessageWithEvents Members /// <summary> @@ -120,7 +154,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// </summary> void IMessageWithEvents.OnSending() { var extraData = ((IMessage)this).ExtraData; - SerializeAttributes(extraData, this.attributesProvided); + AXUtilities.SerializeAttributes(extraData, this.attributesProvided); } /// <summary> @@ -129,72 +163,13 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// </summary> void IMessageWithEvents.OnReceiving() { var extraData = ((IMessage)this).ExtraData; - foreach (var att in DeserializeAttributes(extraData)) { + foreach (var att in AXUtilities.DeserializeAttributes(extraData)) { this.AddAttribute(att); } } #endregion - internal static void SerializeAttributes(IDictionary<string, string> fields, IEnumerable<AttributeValues> attributes) { - ErrorUtilities.VerifyArgumentNotNull(fields, "fields"); - ErrorUtilities.VerifyArgumentNotNull(attributes, "attributes"); - - AliasManager aliasManager = new AliasManager(); - foreach (var att in attributes) { - string alias = aliasManager.GetAlias(att.TypeUri); - fields.Add("type." + alias, att.TypeUri); - if (att.Values == null) { - continue; - } - if (att.Values.Count != 1) { - fields.Add("count." + alias, att.Values.Count.ToString(CultureInfo.InvariantCulture)); - for (int i = 0; i < att.Values.Count; i++) { - fields.Add(string.Format(CultureInfo.InvariantCulture, "value.{0}.{1}", alias, i + 1), att.Values[i]); - } - } else { - fields.Add("value." + alias, att.Values[0]); - } - } - } - - internal static IEnumerable<AttributeValues> DeserializeAttributes(IDictionary<string, string> fields) { - AliasManager aliasManager = ParseAliases(fields); - foreach (string alias in aliasManager.Aliases) { - AttributeValues att = new AttributeValues(aliasManager.ResolveAlias(alias)); - int count = 1; - bool countSent = false; - string countString; - if (fields.TryGetValue("count." + alias, out countString)) { - if (!int.TryParse(countString, out count) || count <= 0) { - Logger.ErrorFormat("Failed to parse count.{0} value to a positive integer.", alias); - continue; - } - countSent = true; - } - if (countSent) { - for (int i = 1; i <= count; i++) { - string value; - if (fields.TryGetValue(string.Format(CultureInfo.InvariantCulture, "value.{0}.{1}", alias, i), out value)) { - att.Values.Add(value); - } else { - Logger.ErrorFormat("Missing value for attribute '{0}'.", att.TypeUri); - continue; - } - } - } else { - string value; - if (fields.TryGetValue("value." + alias, out value)) { - att.Values.Add(value); - } else { - Logger.ErrorFormat("Missing value for attribute '{0}'.", att.TypeUri); - continue; - } - } - yield return att; - } - } - /// <summary> /// Checks the message state for conformity to the protocol specification /// and throws an exception if the message is invalid. @@ -216,24 +191,13 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { } } - private static AliasManager ParseAliases(IDictionary<string, string> fields) { - ErrorUtilities.VerifyArgumentNotNull(fields, "fields"); - - AliasManager aliasManager = new AliasManager(); - foreach (var pair in fields) { - if (!pair.Key.StartsWith("type.", StringComparison.Ordinal)) { - continue; - } - string alias = pair.Key.Substring(5); - if (alias.IndexOfAny(new[] { '.', ',', ':' }) >= 0) { - Logger.ErrorFormat("Illegal characters in alias name '{0}'.", alias); - continue; - } - aliasManager.SetAlias(alias, pair.Value); - } - return aliasManager; - } - + /// <summary> + /// Determines whether some attribute has values in this fetch response. + /// </summary> + /// <param name="typeUri">The type URI of the attribute in question.</param> + /// <returns> + /// <c>true</c> if the specified attribute appears in the fetch response; otherwise, <c>false</c>. + /// </returns> private bool ContainsAttribute(string typeUri) { return this.GetAttribute(typeUri) != null; } diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs index 8124039..41f5a2f 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs @@ -15,9 +15,6 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// The Attribute Exchange Store message, request leg. /// </summary> public sealed class StoreRequest : ExtensionBase, IMessageWithEvents { - [MessagePart("mode", IsRequired = true)] - private const string Mode = "store_request"; - /// <summary> /// The factory method that may be used in deserialization of this message. /// </summary> @@ -33,6 +30,12 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { }; /// <summary> + /// The value of the 'mode' parameter. + /// </summary> + [MessagePart("mode", IsRequired = true)] + private const string Mode = "store_request"; + + /// <summary> /// The list of provided attribute values. This field will never be null. /// </summary> private readonly List<AttributeValues> attributesProvided = new List<AttributeValues>(); @@ -52,9 +55,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { } /// <summary> - /// Used by the Relying Party to add a given attribute with one or more values - /// to the request for storage. + /// Adds a given attribute with one or more values to the request for storage. + /// Applicable to Relying Parties only. /// </summary> + /// <param name="attribute">The attribute values.</param> public void AddAttribute(AttributeValues attribute) { ErrorUtilities.VerifyArgumentNotNull(attribute, "attribute"); ErrorUtilities.VerifyArgumentNamed(!this.ContainsAttribute(attribute.TypeUri), "attribute", OpenIdStrings.AttributeAlreadyAdded, attribute.TypeUri); @@ -62,17 +66,21 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { } /// <summary> - /// Used by the Relying Party to add a given attribute with one or more values - /// to the request for storage. + /// Adds a given attribute with one or more values to the request for storage. + /// Applicable to Relying Parties only. /// </summary> + /// <param name="typeUri">The type URI of the attribute.</param> + /// <param name="values">The attribute values.</param> public void AddAttribute(string typeUri, params string[] values) { this.AddAttribute(new AttributeValues(typeUri, values)); } /// <summary> - /// Used by the Provider to gets the value(s) associated with a given attribute - /// that should be stored. + /// Gets the value(s) associated with a given attribute that should be stored. + /// Applicable to Providers only. /// </summary> + /// <param name="attributeTypeUri">The type URI of the attribute whose values are being sought.</param> + /// <returns>The attribute values.</returns> public AttributeValues GetAttribute(string attributeTypeUri) { return this.attributesProvided.SingleOrDefault(attribute => string.Equals(attribute.TypeUri, attributeTypeUri, StringComparison.Ordinal)); } @@ -87,7 +95,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { var fields = ((IMessage)this).ExtraData; fields.Clear(); - FetchResponse.SerializeAttributes(fields, this.attributesProvided); + AXUtilities.SerializeAttributes(fields, this.attributesProvided); } /// <summary> @@ -96,7 +104,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// </summary> void IMessageWithEvents.OnReceiving() { var fields = ((IMessage)this).ExtraData; - foreach (var att in FetchResponse.DeserializeAttributes(fields)) { + foreach (var att in AXUtilities.DeserializeAttributes(fields)) { this.AddAttribute(att); } } @@ -119,6 +127,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return false; } + if (this.Version != other.Version) { + return false; + } + if (!MessagingUtilities.AreEquivalentUnordered(this.Attributes.ToList(), other.Attributes.ToList())) { return false; } @@ -126,6 +138,29 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { return true; } + /// <summary> + /// Serves as a hash function for a particular type. + /// </summary> + /// <returns> + /// A hash code for the current <see cref="T:System.Object"/>. + /// </returns> + public override int GetHashCode() { + unchecked { + int hashCode = this.Version.GetHashCode(); + foreach (AttributeValues att in this.Attributes) { + hashCode += att.GetHashCode(); + } + return hashCode; + } + } + + /// <summary> + /// Determines whether some attribute has values in this store request. + /// </summary> + /// <param name="typeUri">The type URI of the attribute in question.</param> + /// <returns> + /// <c>true</c> if the specified attribute appears in the store request; otherwise, <c>false</c>. + /// </returns> private bool ContainsAttribute(string typeUri) { return this.GetAttribute(typeUri) != null; } diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs index c883433..97178b6 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs @@ -79,12 +79,26 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { [MessagePart("mode", IsRequired = true)] private string Mode { get; set; } + /// <summary> + /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>. + /// </summary> + /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param> + /// <returns> + /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false. + /// </returns> + /// <exception cref="T:System.NullReferenceException"> + /// The <paramref name="obj"/> parameter is null. + /// </exception> public override bool Equals(object obj) { var other = obj as StoreResponse; if (other == null) { return false; } + if (this.Version != other.Version) { + return false; + } + if (this.Succeeded != other.Succeeded) { return false; } @@ -97,6 +111,24 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { } /// <summary> + /// Serves as a hash function for a particular type. + /// </summary> + /// <returns> + /// A hash code for the current <see cref="T:System.Object"/>. + /// </returns> + public override int GetHashCode() { + unchecked { + int hashCode = this.Version.GetHashCode(); + hashCode += this.Succeeded ? 0 : 1; + if (this.FailureReason != null) { + hashCode += this.FailureReason.GetHashCode(); + } + + return hashCode; + } + } + + /// <summary> /// Checks the message state for conformity to the protocol specification /// and throws an exception if the message is invalid. /// </summary> @@ -113,7 +145,9 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { ErrorUtilities.VerifyProtocol( this.Mode == SuccessMode || this.Mode == FailureMode, - MessagingStrings.UnexpectedMessagePartValue, "mode", this.Mode); + MessagingStrings.UnexpectedMessagePartValue, + "mode", + this.Mode); } } } |