/// <summary>
 /// Initializes a new instance of the <see cref="XacmlContextSubject"/> class.
 /// </summary>
 /// <param name="attributes">The attribute.</param>
 public XacmlContextSubject(XacmlContextAttribute attribute)
     : this(new XacmlContextAttribute[] { attribute }) {
     Contract.Requires<ArgumentNullException>(attribute != null);
 }
        protected virtual XacmlContextAttribute ReadContextAttribute(XmlReader reader) {
            Contract.Requires<ArgumentNullException>(reader != null, "reader");
            Contract.Requires<XmlException>(reader.IsStartElement(XacmlConstants.ElementNames.Attribute, this.version.NamespaceContext));

            // Read attributes
            Uri attributeId = this.ReadAttribute<Uri>(reader, XacmlConstants.AttributeNames.AttributeId, isRequered: true);
            Uri dataType = this.ReadAttribute<Uri>(reader, XacmlConstants.AttributeNames.DataType, isRequered: true);
            string issuer = this.ReadAttribute<string>(reader, XacmlConstants.AttributeNames.Issuer, isRequered: false);
            DateTime? issueInstant = null;
            string issueInstantString = this.ReadAttribute<string>(reader, XacmlConstants.AttributeNames.IssueInstant, isRequered: false);
            if (!string.IsNullOrWhiteSpace(issueInstantString)) {
                issueInstant = XmlConvert.ToDateTime(issueInstantString, XmlDateTimeSerializationMode.Local);
            }

            reader.ReadStartElement(XacmlConstants.ElementNames.Attribute, this.version.NamespaceContext);
            // Read elements

            XacmlContextAttributeValue attrVal = this.ReadRequired(XacmlConstants.ElementNames.AttributeValue, this.version.NamespaceContext, this.ReadContextAttributeValue, reader);

            XacmlContextAttribute result = new XacmlContextAttribute(attributeId, dataType, attrVal) {
                Issuer = issuer,
                IssueInstant = issueInstant
            };

            reader.ReadEndElement();

            return result;
        }
        /// <summary>
        /// Writes the context attribute.
        /// </summary>
        /// <param name="writer">The writer.</param>
        /// <param name="attr">The attribute.</param>
        /// <exception cref="XacmlSerializationException">IssueInstant obsolleten from version 2.0</exception>
        protected override void WriteContextAttribute(XmlWriter writer, XacmlContextAttribute attr) {
            writer.WriteStartElement(XacmlConstants.Prefixes.Context, XacmlConstants.ElementNames.Attribute, this.version.NamespaceContext);

            writer.WriteAttributeString(XacmlConstants.AttributeNames.AttributeId, attr.AttributeId.ToString());
            writer.WriteAttributeString(XacmlConstants.AttributeNames.DataType, attr.DataType.ToString());

            if (!string.IsNullOrEmpty(attr.Issuer)) {
                writer.WriteAttributeString(XacmlConstants.AttributeNames.Issuer, attr.Issuer);
            }

            if (attr.IssueInstant != null) {
                throw Diagnostic.DiagnosticTools.ExceptionUtil.ThrowHelperError(new XacmlSerializationException("IssueInstant obsolleten from version 2.0"));
            }

            foreach (var value in attr.AttributeValues) {
                this.WriteContextAttributeValue(writer, value);
            }

            writer.WriteEndElement();
        }
        protected virtual void WriteContextAttribute(XmlWriter writer, XacmlContextAttribute attr) {
            Contract.Requires<ArgumentNullException>(writer != null);
            Contract.Requires<ArgumentNullException>(attr != null);

            writer.WriteStartElement(XacmlConstants.Prefixes.Context, XacmlConstants.ElementNames.Attribute, this.version.NamespaceContext);

            writer.WriteAttributeString(XacmlConstants.AttributeNames.AttributeId, attr.AttributeId.ToString());
            writer.WriteAttributeString(XacmlConstants.AttributeNames.DataType, attr.DataType.ToString());

            if (!string.IsNullOrEmpty(attr.Issuer)) {
                writer.WriteAttributeString(XacmlConstants.AttributeNames.Issuer, attr.Issuer);
            }

            if (attr.IssueInstant != null) {
                writer.WriteAttributeString(XacmlConstants.AttributeNames.IssueInstant, attr.IssueInstant.ToString());
            }

            if (attr.AttributeValues.Count > 1) {
                throw Diagnostic.DiagnosticTools.ExceptionUtil.ThrowHelperError(new XacmlSerializationException("AttributeValues shoul be 1 in version 1.0"));
            }

            this.WriteContextAttributeValue(writer, attr.AttributeValues.First());

            writer.WriteEndElement();
        }
        /// <summary>
        /// Reads the context attribute.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns></returns>
        protected override XacmlContextAttribute ReadContextAttribute(XmlReader reader) {
            Contract.Requires<ArgumentNullException>(reader != null, "reader");
            Contract.Requires<XmlException>(reader.IsStartElement(XacmlConstants.ElementNames.Attribute, this.version.NamespaceContext));

            // Read attributes
            Uri attributeId = this.ReadAttribute<Uri>(reader, XacmlConstants.AttributeNames.AttributeId, isRequered: true);
            Uri dataType = this.ReadAttribute<Uri>(reader, XacmlConstants.AttributeNames.DataType, isRequered: true);
            string issuer = this.ReadAttribute<string>(reader, XacmlConstants.AttributeNames.Issuer, isRequered: false);

            reader.ReadStartElement(XacmlConstants.ElementNames.Attribute, this.version.NamespaceContext);
            // Read elements

            ICollection<XacmlContextAttributeValue> attrValues = new List<XacmlContextAttributeValue>();
            this.ReadList(attrValues, XacmlConstants.ElementNames.AttributeValue, this.version.NamespaceContext, ReadContextAttributeValue, reader, isRequired: true);

            XacmlContextAttribute result = new XacmlContextAttribute(attributeId, dataType, attrValues) {
                Issuer = issuer
            };

            reader.ReadEndElement();

            return result;
        }