/// <summary>
        /// Reads the &lt;saml:AuthzDecisionStatement> element or a 
        /// &lt;saml:Statement element that specifies an xsi:type of
        /// saml:AuthzDecisionStatementType.
        /// </summary>
        /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2AuthorizationDecisionStatement"/> element.</param>
        /// <returns>A <see cref="Saml2AuthorizationDecisionStatement"/> instance.</returns>
        protected virtual Saml2AuthorizationDecisionStatement ReadAuthorizationDecisionStatement(XmlReader reader)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

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

            try
            {
                // Need the attributes before we can instantiate
                Saml2AuthorizationDecisionStatement statement;
                SamlAccessDecision decision;
                Uri resource;

                // defer rejecting empty until processing xsi:type
                bool isEmpty = reader.IsEmptyElement;

                // @attributes
                string value;

                // @xsi:type
                XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.AuthzDecisionStatementType, Saml2Constants.Namespace, isStatementElement);

                // disallow empty, since xsi:type is ok
                if (isEmpty)
                {
                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID3061, Saml2Constants.Elements.AuthzDecisionStatement, Saml2Constants.Namespace));
                }

                // @Decision - required
                value = reader.GetAttribute(Saml2Constants.Attributes.Decision);
                if (string.IsNullOrEmpty(value))
                {
                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.Decision, Saml2Constants.Elements.AuthzDecisionStatement));
                }
                else if (StringComparer.Ordinal.Equals(SamlAccessDecision.Permit.ToString(), value))
                {
                    decision = SamlAccessDecision.Permit;
                }
                else if (StringComparer.Ordinal.Equals(SamlAccessDecision.Deny.ToString(), value))
                {
                    decision = SamlAccessDecision.Deny;
                }
                else if (StringComparer.Ordinal.Equals(SamlAccessDecision.Indeterminate.ToString(), value))
                {
                    decision = SamlAccessDecision.Indeterminate;
                }
                else
                {
                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4123, value));
                }

                // @Resource - required
                value = reader.GetAttribute(Saml2Constants.Attributes.Resource);
                if (null == value)
                {
                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.Resource, Saml2Constants.Elements.AuthzDecisionStatement));
                }
                else if (0 == value.Length)
                {
                    resource = Saml2AuthorizationDecisionStatement.EmptyResource;
                }
                else
                {
                    if (!UriUtil.CanCreateValidUri(value, UriKind.Absolute))
                    {
                        throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4121));
                    }

                    resource = new Uri(value);
                }

                // Content
                statement = new Saml2AuthorizationDecisionStatement(resource, decision);
                reader.Read();

                // <Action> 1-OO 
                do
                {
                    statement.Actions.Add(this.ReadAction(reader));
                }
                while (reader.IsStartElement(Saml2Constants.Elements.Action, Saml2Constants.Namespace));

                // <Evidence> 0-1
                if (reader.IsStartElement(Saml2Constants.Elements.Evidence, Saml2Constants.Namespace))
                {
                    statement.Evidence = this.ReadEvidence(reader);
                }

                reader.ReadEndElement();

                return statement;
            }
            catch (Exception e)
            {
                if (System.Runtime.Fx.IsFatal(e))
                    throw;
                
                Exception wrapped = TryWrapReadException(reader, e);
                if (null == wrapped)
                {
                    throw;
                }
                else
                {
                    throw wrapped;
                }
            }
        }
        /// <summary>
        /// Writes the &lt;saml:AuthzDecisionStatement> element.
        /// </summary>
        /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2AuthorizationDecisionStatement"/>.</param>
        /// <param name="data">The <see cref="Saml2AuthorizationDecisionStatement"/> to serialize.</param>
        protected virtual void WriteAuthorizationDecisionStatement(XmlWriter writer, Saml2AuthorizationDecisionStatement data)
        {
            if (null == writer)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
            }

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

#pragma warning suppress 56506 // actions are never null
            if (0 == data.Actions.Count)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR.GetString(SR.ID4122)));
            }

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

            // @Decision - required
            writer.WriteAttributeString(Saml2Constants.Attributes.Decision, data.Decision.ToString());

            // @Resource - required
#pragma warning suppress 56506 // Resource are never null
            writer.WriteAttributeString(Saml2Constants.Attributes.Resource, data.Resource.Equals(Saml2AuthorizationDecisionStatement.EmptyResource) ? data.Resource.ToString() : data.Resource.AbsoluteUri);

            // @Action 1-OO
            foreach (Saml2Action action in data.Actions)
            {
                this.WriteAction(writer, action);
            }

            // Evidence 0-1
            if (null != data.Evidence)
            {
                this.WriteEvidence(writer, data.Evidence);
            }

            // </AuthzDecisionStatement>
            writer.WriteEndElement();
        }
 /// <summary>
 /// Creates claims from a Saml2AuthorizationDecisionStatement.
 /// </summary>
 /// <param name="statement">The Saml2AuthorizationDecisionStatement.</param>
 /// <param name="subject">The subject.</param>
 /// <param name="issuer">The issuer.</param>
 protected virtual void ProcessAuthorizationDecisionStatement(Saml2AuthorizationDecisionStatement statement, ClaimsIdentity subject, string issuer)
 {
 }