1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4 
5 namespace System.ServiceModel.Discovery
6 {
7     using System;
8     using System.Diagnostics.CodeAnalysis;
9     using System.Globalization;
10     using System.Runtime;
11     using System.Xml;
12     using SR2 = System.ServiceModel.Discovery.SR;
13 
14     [Fx.Tag.XamlVisible(false)]
15     [SuppressMessage("Microsoft.Design", "CA1036:OverrideMethodsOnComparableTypes")]
16     public class DiscoveryMessageSequence :
17         IComparable<DiscoveryMessageSequence>,
18         IEquatable<DiscoveryMessageSequence>
19     {
DiscoveryMessageSequence()20         internal DiscoveryMessageSequence()
21         {
22         }
23 
DiscoveryMessageSequence(long instanceId, Uri sequenceId, long messageNumber)24         internal DiscoveryMessageSequence(long instanceId, Uri sequenceId, long messageNumber)
25         {
26             Fx.Assert((instanceId >= 0) && (instanceId <= UInt32.MaxValue), "The instanceId must be within UInt32 range");
27             Fx.Assert((messageNumber >= 0) && (messageNumber <= UInt32.MaxValue), "The messageNumber must be within UInt32 range");
28 
29             this.InstanceId = instanceId;
30             this.SequenceId = sequenceId;
31             this.MessageNumber = messageNumber;
32         }
33 
34         public long InstanceId
35         {
36             get;
37             private set;
38         }
39 
40         public Uri SequenceId
41         {
42             get;
43             private set;
44         }
45 
46         public long MessageNumber
47         {
48             get;
49             private set;
50         }
51 
operator ==(DiscoveryMessageSequence messageSequence1, DiscoveryMessageSequence messageSequence2)52         public static bool operator ==(DiscoveryMessageSequence messageSequence1, DiscoveryMessageSequence messageSequence2)
53         {
54             if (object.ReferenceEquals(messageSequence1, null) && object.ReferenceEquals(messageSequence2, null))
55             {
56                 return true;
57             }
58             if (object.ReferenceEquals(messageSequence1, null) || object.ReferenceEquals(messageSequence2, null))
59             {
60                 return false;
61             }
62             return messageSequence1.Equals(messageSequence2);
63         }
64 
operator !=(DiscoveryMessageSequence messageSequence1, DiscoveryMessageSequence messageSequence2)65         public static bool operator !=(DiscoveryMessageSequence messageSequence1, DiscoveryMessageSequence messageSequence2)
66         {
67             return !(messageSequence1 == messageSequence2);
68         }
69 
Equals(object obj)70         public override bool Equals(object obj)
71         {
72             DiscoveryMessageSequence other = obj as DiscoveryMessageSequence;
73             return this.Equals(other);
74         }
75 
Equals(DiscoveryMessageSequence other)76         public bool Equals(DiscoveryMessageSequence other)
77         {
78             if (object.ReferenceEquals(other, null))
79             {
80                 return false;
81             }
82             if (object.ReferenceEquals(this, other))
83             {
84                 return true;
85             }
86 
87             return (long.Equals(this.InstanceId, other.InstanceId) &&
88                 Uri.Equals(this.SequenceId, other.SequenceId) &&
89                 long.Equals(this.MessageNumber, other.MessageNumber));
90         }
91 
ToString()92         public override string ToString()
93         {
94             return SR.DiscoveryMessageSequenceToString(this.InstanceId, this.SequenceId, this.MessageNumber);
95         }
96 
CanCompareTo(DiscoveryMessageSequence other)97         public bool CanCompareTo(DiscoveryMessageSequence other)
98         {
99             if (object.ReferenceEquals(other, null))
100             {
101                 return false;
102             }
103             else
104             {
105                 return ((this.InstanceId != other.InstanceId) ||
106                     (Uri.Equals(this.SequenceId, other.SequenceId)));
107             }
108         }
109 
GetHashCode()110         public override int GetHashCode()
111         {
112             return string.Format(
113                 CultureInfo.InvariantCulture, "{0}:{1}:{2}",
114                 this.InstanceId,
115                 this.SequenceId,
116                 this.MessageNumber).GetHashCode();
117         }
118 
CompareTo(DiscoveryMessageSequence other)119         public int CompareTo(DiscoveryMessageSequence other)
120         {
121             if (object.ReferenceEquals(other, null))
122             {
123                 throw FxTrace.Exception.ArgumentNull("other");
124             }
125 
126             int result = this.InstanceId.CompareTo(other.InstanceId);
127             if (result == 0)
128             {
129                 if (!Uri.Equals(this.SequenceId, other.SequenceId))
130                 {
131                     throw FxTrace.Exception.Argument("other", SR2.DiscoveryIncompatibleMessageSequence);
132                 }
133 
134                 result = this.MessageNumber.CompareTo(other.MessageNumber);
135             }
136 
137             return result;
138         }
139 
140         [Fx.Tag.Throws(typeof(XmlException), "throws on incorrect xml data")]
ReadFrom(XmlReader reader)141         internal void ReadFrom(XmlReader reader)
142         {
143             if (reader == null)
144             {
145                 throw FxTrace.Exception.ArgumentNull("reader");
146             }
147 
148             string instanceIdString = reader.GetAttribute(ProtocolStrings.SchemaNames.AppSequenceInstanceId);
149 
150             this.InstanceId = SerializationUtility.ReadUInt(
151                 instanceIdString,
152                 SR2.DiscoveryXmlMissingAppSequenceInstanceId,
153                 SR2.DiscoveryXmlInvalidAppSequenceInstanceId);
154 
155             string sequenceIdString = reader.GetAttribute(ProtocolStrings.SchemaNames.AppSequenceSequenceId);
156 
157             if (sequenceIdString != null)
158             {
159                 try
160                 {
161                     this.SequenceId = new Uri(sequenceIdString, UriKind.RelativeOrAbsolute);
162                 }
163                 catch (FormatException fe)
164                 {
165                     throw FxTrace.Exception.AsError(new XmlException(SR2.DiscoveryXmlUriFormatError(sequenceIdString), fe));
166                 }
167             }
168 
169             string messageNumberString = reader.GetAttribute(ProtocolStrings.SchemaNames.AppSequenceMessageNumber);
170 
171             this.MessageNumber = SerializationUtility.ReadUInt(
172                 messageNumberString,
173                 SR2.DiscoveryXmlMissingAppSequenceMessageNumber,
174                 SR2.DiscoveryXmlInvalidAppSequenceMessageNumber);
175         }
176 
WriteTo(XmlWriter writer)177         internal void WriteTo(XmlWriter writer)
178         {
179             if (writer == null)
180             {
181                 throw FxTrace.Exception.ArgumentNull("writer");
182             }
183 
184             writer.WriteAttributeString(
185                 ProtocolStrings.SchemaNames.AppSequenceInstanceId,
186                 this.InstanceId.ToString(CultureInfo.InvariantCulture));
187 
188             if (this.SequenceId != null)
189             {
190                 writer.WriteAttributeString(
191                     ProtocolStrings.SchemaNames.AppSequenceSequenceId,
192                     this.SequenceId.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped));
193             }
194 
195             writer.WriteAttributeString(
196                 ProtocolStrings.SchemaNames.AppSequenceMessageNumber,
197                 this.MessageNumber.ToString(CultureInfo.InvariantCulture));
198         }
199     }
200 }
201