protected override void WriteAudienceRestriction(XmlWriter writer, Saml2AudienceRestriction data)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            if (data.Audiences == null)
            {
                throw new ArgumentNullException("audience");
            }

            // GFIPM S2S 8.8.6.a Need to limit to just one Audience
            if ( !(data.Audiences.Count == 1) )
            {
                throw new InvalidOperationException("A Saml2AudienceRestriction must specify only one Audience.");
            }

            writer.WriteStartElement("AudienceRestriction", "urn:oasis:names:tc:SAML:2.0:assertion");
            
            Uri uri = data.Audiences[0];
            writer.WriteElementString("Audience", "urn:oasis:names:tc:SAML:2.0:assertion", uri.OriginalString);

            writer.WriteEndElement();
        }
        /// <summary>
        /// Writes the &lt;saml:AudienceRestriction> element.
        /// </summary>
        /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2AudienceRestriction"/>.</param>
        /// <param name="data">The <see cref="Saml2AudienceRestriction"/> to serialize.</param>
        protected virtual void WriteAudienceRestriction(XmlWriter writer, Saml2AudienceRestriction data)
        {
            if (null == writer)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
            }

            if (null == data)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data");
            }

            // Schema requires at least one audience.
            if (data.Audiences == null || 0 == data.Audiences.Count)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4159)));
            }

            // <AudienceRestriction>
            writer.WriteStartElement(Saml2Constants.Elements.AudienceRestriction, Saml2Constants.Namespace);

            // <Audience> - 1-OO
            foreach (Uri audience in data.Audiences)
            {
                // When writing out the audience uri we use the OriginalString property to preserve the value that was initially passed down during token creation as-is. 
                writer.WriteElementString(Saml2Constants.Elements.Audience, Saml2Constants.Namespace, audience.OriginalString);
            }

            // </AudienceRestriction>
            writer.WriteEndElement();
        }
        /// <summary>
        /// Reads the &lt;saml:AudienceRestriction> element or a 
        /// &lt;saml:Condition> element that specifies an xsi:type
        /// of saml:AudienceRestrictionType.
        /// </summary>
        /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2AudienceRestriction"/> element.</param>
        /// <returns>A <see cref="Saml2AudienceRestriction"/> instance.</returns>
        protected virtual Saml2AudienceRestriction ReadAudienceRestriction(XmlReader reader)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            // throw if wrong element
            bool isConditionElement = false;
            if (reader.IsStartElement(Saml2Constants.Elements.Condition, Saml2Constants.Namespace))
            {
                isConditionElement = true;
            }
            else if (!reader.IsStartElement(Saml2Constants.Elements.AudienceRestriction, Saml2Constants.Namespace))
            {
                reader.ReadStartElement(Saml2Constants.Elements.AudienceRestriction, Saml2Constants.Namespace);
            }

            try
            {
                Saml2AudienceRestriction audienceRestriction;
                bool isEmpty = reader.IsEmptyElement;

                // @attributes

                // @xsi:type -- if we're a <Condition> element, this declaration must be present
                XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.AudienceRestrictionType, Saml2Constants.Namespace, isConditionElement);

                // disallow empty
                if (isEmpty)
                {
                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID3061, reader.LocalName, reader.NamespaceURI));
                }

                // content
                reader.Read();

                // <Audience> - 1-OO
                if (!reader.IsStartElement(Saml2Constants.Elements.Audience, Saml2Constants.Namespace))
                {
                    reader.ReadStartElement(Saml2Constants.Elements.Audience, Saml2Constants.Namespace);
                }

                // We are now laxing the uri check for audience restriction to support interop partners 
                // This is a specific request from server : Bug 11850
                // ReadSimpleUriElement now has a flag that turns lax reading ON/OFF.
                audienceRestriction = new Saml2AudienceRestriction(ReadSimpleUriElement(reader, UriKind.RelativeOrAbsolute, true));
                while (reader.IsStartElement(Saml2Constants.Elements.Audience, Saml2Constants.Namespace))
                {
                    audienceRestriction.Audiences.Add(ReadSimpleUriElement(reader, UriKind.RelativeOrAbsolute, true));
                }

                reader.ReadEndElement();

                return audienceRestriction;
            }
            catch (Exception e)
            {
                if (System.Runtime.Fx.IsFatal(e))
                    throw;
                
                Exception wrapped = TryWrapReadException(reader, e);
                if (null == wrapped)
                {
                    throw;
                }
                else
                {
                    throw wrapped;
                }
            }
        }