/// <summary>
 /// Helper method that allows the SDK to throw the appropriate
 /// HealthServiceException based on the status code indicating the error
 /// type.
 /// </summary>
 /// 
 /// <param name="errorCode">
 /// The status code representing the error which occurred.
 /// </param>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal static HealthServiceException GetHealthServiceException(
     HealthServiceStatusCode errorCode,
     HealthServiceResponseError error)
 {
     HealthServiceException e = null;
     switch (errorCode)
     {
         case HealthServiceStatusCode.CredentialTokenExpired:
             e = new HealthServiceCredentialTokenExpiredException(error);
             break;
         case HealthServiceStatusCode.AuthenticatedSessionTokenExpired:
             e = new HealthServiceAuthenticatedSessionTokenExpiredException(error);
             break;
         case HealthServiceStatusCode.InvalidPerson:
             e = new HealthServiceInvalidPersonException(error);
             break;
         case HealthServiceStatusCode.InvalidRecord:
             e = new HealthServiceInvalidRecordException(error);
             break;
         case HealthServiceStatusCode.AccessDenied:
             e = new HealthServiceAccessDeniedException(error);
             break;
         case HealthServiceStatusCode.InvalidApplicationAuthorization:
             e = new HealthServiceInvalidApplicationAuthorizationException(error);
             break;
         case HealthServiceStatusCode.DuplicateCredentialFound:
             e = new HealthServiceApplicationDuplicateCredentialException(error);
             break;
         case HealthServiceStatusCode.MailAddressMalformed:
             e = new HealthServiceMailAddressMalformedException(error);
             break;
         case HealthServiceStatusCode.PasswordNotStrong:
             e = new HealthServicePasswordNotStrongException(error);
             break;
         case HealthServiceStatusCode.RecordQuotaExceeded:
             e = new HealthServiceRecordQuotaExceededException(error);
             break;
         case HealthServiceStatusCode.OtherDataItemSizeLimitExceeded :
             e = new HealthServiceOtherDataSizeLimitExceededException(error);
             break;
         default:
             e = new HealthServiceException(errorCode, error);
             break;
     }
     return e;
 }
        /// <summary>
        /// Helper method that allows the SDK to throw the appropriate
        /// HealthServiceException based on the status code returned by 
        /// HealthVault.
        /// </summary>
        /// 
        /// <param name="errorCodeId">
        /// The integer status code returned by HealthVault representing the 
        /// error which occurred.
        ///</param>
        /// <param name="error">
        /// Information about an error that occurred while processing
        /// the request.
        /// </param>
        /// 
        internal static HealthServiceException GetHealthServiceException(int errorCodeId,
            HealthServiceResponseError error)
        {
            HealthServiceException e = null;
            HealthServiceStatusCode errorCode =
                HealthServiceStatusCodeManager.GetStatusCode(errorCodeId);

            if (errorCode != HealthServiceStatusCode.UnmappedError)
            {
                e = GetHealthServiceException(errorCode, error);
            }
            else
            {
                e = new HealthServiceException(errorCodeId, error);
            }

            return e;
        }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceMailAddressMalformedException"/> 
 /// class with the specified error information to represent a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.MailAddressMalformed"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type.
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceMailAddressMalformedException(
     HealthServiceResponseError error)
     : base(HealthServiceStatusCode.MailAddressMalformed, error)
 {
 }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceAuthenticatedSessionTokenExpiredException"/> 
 /// class with the specified error information representing a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.AuthenticatedSessionTokenExpired"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type. This error indicates that the 
 /// authorization token supplied to HealthVault is malformed or 
 /// otherwise faulty.
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceAuthenticatedSessionTokenExpiredException(HealthServiceResponseError error)
     : base(HealthServiceStatusCode.AuthenticatedSessionTokenExpired, error)
 {
 }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceAuthenticatedSessionTokenExpiredException"/> 
 /// class with the specified error information representing a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.CredentialTokenExpired"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type. This error indicates that the 
 /// authorization token supplied to HealthVault is malformed or 
 /// otherwise faulty.
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceCredentialTokenExpiredException(HealthServiceResponseError error)
     : base(HealthServiceStatusCode.CredentialTokenExpired, error)
 {
 }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceInvalidApplicationAuthorizationException"/> 
 /// class with the specified error information to represent a 
 /// HealthVault error code of 
 /// <see cref="Microsoft.Health.HealthServiceStatusCode.InvalidApplicationAuthorization"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type. The error indicates that the 
 /// application does not have an entry in the authorized application 
 /// information and as such is not authorized to perform the task.
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceInvalidApplicationAuthorizationException(HealthServiceResponseError error)
     : base(HealthServiceStatusCode.InvalidApplicationAuthorization, error)
 {
 }
        /// <summary>
        /// Gets the <see cref="HealthRecordInfo"/> for the first health record 
        /// that has a relationship of <see cref="RelationshipType.Self"/> with the 
        /// person.
        /// </summary>
        /// 
        /// <returns>
        /// The first <see cref="HealthRecordInfo"/> having the 
        /// <see cref="RelationshipType.Self"/> relationship with the person.
        /// </returns>
        /// 
        /// <remarks>
        /// Since a person may have more than one or no 
        /// <see cref="RelationshipType.Self"/> records, this method returns an 
        /// error if the person does not have a self record, but it returns 
        /// the first self record if they have multiple records. There is no 
        /// guarantee that the first record will always be the same one.
        /// </remarks>
        /// 
        /// <exception cref="HealthServiceException">
        /// The person does not have an authorized record with the 
        /// <see cref="RelationshipType.Self"/> relationship that is in the
        /// Active state with the authorization expiration
        /// date anytime in the future.
        /// </exception>
        /// 
        public HealthRecordInfo GetSelfRecord()
        {
            HealthRecordInfo selfRecord = null;

            foreach (HealthRecordInfo authRecord in AuthorizedRecords.Values)
            {
                if (authRecord.RelationshipType == RelationshipType.Self
                    && authRecord.DateAuthorizationExpires > DateTime.UtcNow)
                {
                    selfRecord = authRecord;
                    break;
                }
            }

            if (selfRecord == null)
            {
                HealthServiceResponseError error = new HealthServiceResponseError();
                error.Message =
                    ResourceRetriever.GetResourceString(
                        "SelfRecordNotFound");

                HealthServiceException e =
                    HealthServiceExceptionHelper.GetHealthServiceException(
                        HealthServiceStatusCode.RecordNotFound,
                        error);
                throw e;
            }
            return selfRecord;
        }
        /// <summary>
        /// Gets a single health record item from the associated record by 
        /// using the item identifier.
        /// </summary>
        /// 
        /// <param name="itemId">
        /// The unique identifier for the health record item.
        /// </param>
        /// 
        /// <param name="sections">
        /// The data sections of the health record item that should be retrieved.
        /// </param>
        /// 
        /// <returns>
        /// An instance of a <see cref="Microsoft.Health.HealthRecordItem"/> 
        /// representing the health record item with the specified identifier.
        /// </returns>
        /// 
        /// <remarks>
        /// This method accesses the HealthVault service across the network.
        /// <br/><br/>
        /// All filters are cleared and replaced with a single filter
        /// for the specified item.
        /// </remarks>
        /// 
        /// <exception cref="HealthServiceException">
        /// The server returned something other than a code of 
        /// HealthServiceStatusCode.OK, or the result count did not equal one (1).
        /// -or-
        /// <see cref="Microsoft.Health.HealthRecordSearcher.Filters"/> is empty
        /// or contains invalid filters.
        /// </exception>
        /// 
        public HealthRecordItem GetSingleItem(
            Guid itemId,
            HealthRecordItemSections sections)
        {
            // Create a new searcher to get the item.
            HealthRecordSearcher searcher = new HealthRecordSearcher(Record);

            HealthRecordFilter filter = new HealthRecordFilter();
            filter.ItemIds.Add(itemId);
            filter.View.Sections = sections;
            filter.CurrentVersionOnly = true;

            searcher.Filters.Add(filter);

            ReadOnlyCollection<HealthRecordItemCollection> resultSet =
                HealthVaultPlatform.GetMatchingItems(Record.Connection, Record, searcher);

            // Check in case HealthVault returned invalid data.
            if (resultSet.Count > 1)
            {
                HealthServiceResponseError error = new HealthServiceResponseError();
                error.Message =
                    ResourceRetriever.GetResourceString(
                        "GetSingleThingTooManyResults");

                HealthServiceException e =
                    HealthServiceExceptionHelper.GetHealthServiceException(
                        HealthServiceStatusCode.MoreThanOneThingReturned,
                        error);
                throw e;
            }

            HealthRecordItem result = null;
            if (resultSet.Count == 1)
            {
                HealthRecordItemCollection resultGroup = resultSet[0];

                if (resultGroup.Count > 1)
                {
                    HealthServiceResponseError error = new HealthServiceResponseError();
                    error.Message =
                        ResourceRetriever.GetResourceString(
                            "GetSingleThingTooManyResults");

                    HealthServiceException e =
                        HealthServiceExceptionHelper.GetHealthServiceException(
                            HealthServiceStatusCode.MoreThanOneThingReturned,
                            error);
                    throw e;
                }

                if (resultGroup.Count == 1)
                {
                    result = resultGroup[0];
                }
            }
            return result;
        }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceRecordQuotaExceededException"/> 
 /// class with the specified error information to represent a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.RecordQuotaExceeded"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type.
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceRecordQuotaExceededException(
     HealthServiceResponseError error)
     : base(HealthServiceStatusCode.RecordQuotaExceeded, error)
 {
 }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceInvalidRecordException"/> 
 /// class with the specified error information to represent a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.InvalidRecord"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type. The error indicates that the 
 /// specified record is nonexistent.
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceInvalidRecordException(HealthServiceResponseError error)
     : base(HealthServiceStatusCode.InvalidRecord, error)
 {
 }
        private static HealthServiceResponseError HandleErrorResponse(XmlReader reader)
        {
            HealthServiceResponseError error = new HealthServiceResponseError();

            // <error>
            if (String.Equals(reader.Name, "error", StringComparison.Ordinal))
            {
                // <message>
                if (!SDKHelper.ReadUntil(reader, "message"))
                {
                    throw new MissingFieldException("response", "message");
                }
                error.Message = reader.ReadElementString();

                // <context>
                SDKHelper.SkipToElement(reader);
                if (String.Equals(reader.Name, "context", StringComparison.Ordinal))
                {
                    HealthServiceErrorContext errorContext = new HealthServiceErrorContext();

                    // <server-name>
                    if (SDKHelper.ReadUntil(reader, "server-name"))
                    {
                        errorContext.ServerName = reader.ReadElementString();
                    }
                    else
                    {
                        throw new MissingFieldException("context", "server-name");
                    }

                    // <server-ip>
                    Collection<IPAddress> ipAddresses = new Collection<IPAddress>();

                    SDKHelper.SkipToElement(reader);
                    while (reader.Name.Equals("server-ip", StringComparison.Ordinal))
                    {
                        string ipAddressString = reader.ReadElementString();
                        IPAddress ipAddress = null;
                        if (IPAddress.TryParse(ipAddressString, out ipAddress))
                        {
                            ipAddresses.Add(ipAddress);
                        }
                        SDKHelper.SkipToElement(reader);
                    }
                    errorContext.SetServerIpAddresses(ipAddresses);

                    // <exception>
                    if (reader.Name.Equals("exception", StringComparison.Ordinal))
                    {
                        errorContext.InnerException = reader.ReadElementString();
                        SDKHelper.SkipToElement(reader);
                    }
                    else
                    {
                        throw new MissingFieldException("context", "exception");
                    }
                    error.Context = errorContext;
                }

                // <error-info>
                if (SDKHelper.ReadUntil(reader, "error-info"))
                {
                    error.ErrorInfo = reader.ReadElementString();
                    SDKHelper.SkipToElement(reader);
                }

            }
            return error;
        }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceOtherDataSizeLimitExceededException"/> 
 /// class with the specified error information to represent a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.OtherDataItemSizeLimitExceeded"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type. 
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceOtherDataSizeLimitExceededException(HealthServiceResponseError error)
     : base(HealthServiceStatusCode.OtherDataItemSizeLimitExceeded, error)
 {
 }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceAccessDeniedException"/> 
 /// class with the specified error information to represent a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.AccessDenied"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type. 
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceAccessDeniedException(HealthServiceResponseError error)
     : base(HealthServiceStatusCode.AccessDenied, error)
 {
 }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceEmailNotValidatedException"/> 
 /// class with the specified error information to represent a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.EmailNotValidated"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type.
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceEmailNotValidatedException(
     HealthServiceResponseError error)
     : base(HealthServiceStatusCode.EmailNotValidated, error)
 {
 }
        /// <summary>
        /// Generates the XML for the parameters for the "GetThings" request.
        /// </summary>
        /// 
        /// <returns>
        /// An XML string defining the parameters for the "GetThings" call.
        /// </returns>
        /// 
        /// <exception cref="HealthServiceException">
        /// No filters have been specified.
        /// </exception>
        ///         
        internal string GetParametersXml()
        {
            if (Filters.Count == 0)
            {
                HealthServiceResponseError error = new HealthServiceResponseError();
                error.Message =
                    ResourceRetriever.GetResourceString(
                        "HealthRecordSearcherNoFilters");

                HealthServiceException e =
                    HealthServiceExceptionHelper.GetHealthServiceException(
                        HealthServiceStatusCode.InvalidFilter, error);
                throw e;

            }

            StringBuilder parameters = new StringBuilder(128);

            XmlWriterSettings settings = SDKHelper.XmlUnicodeWriterSettings;

            using (XmlWriter writer = XmlWriter.Create(parameters, settings))
            {
                foreach (HealthRecordFilter filter in Filters)
                {
                    // Add all filters
                    filter.AddFilterXml(writer);
                }
                writer.Flush();
            }
            return parameters.ToString();
        }
        /// <summary>
        /// Updates the <see cref="HealthRecordInfo"/> instance with data from 
        /// the server using the <see cref="HealthRecordAccessor.Id"/>.
        /// </summary>
        /// 
        /// <remarks>
        /// This method accesses the HealthVault service across the network.
        /// </remarks>
        /// 
        /// <exception cref="InvalidOperationException">
        /// This method is called and the 
        /// <see cref="HealthRecordAccessor.Connection"/> 
        /// object of the <see cref="HealthRecordInfo"/> is not an 
        /// <see cref="AuthenticatedConnection"/>.
        /// </exception>
        /// 
        public void Refresh()
        {
            AuthenticatedConnection connection =
                Connection as AuthenticatedConnection;
            if (connection == null)
            {
                OfflineWebApplicationConnection offlineAuthConnection =
                    Connection as OfflineWebApplicationConnection;

                Validator.ThrowInvalidIfNull(offlineAuthConnection, "ConnectionIsNeitherAuthenticatedNorOffline");
            }

            Collection<HealthRecordInfo> records =
                HealthVaultPlatform.GetAuthorizedRecords(Connection, new Guid[] { this.Id });

            if (records.Count == 0)
            {
                HealthServiceResponseError error = new HealthServiceResponseError();
                error.Message =
                    ResourceRetriever.FormatResourceString(
                        "RecordNotFoundException",
                        this.Id);

                HealthServiceException e =
                    HealthServiceExceptionHelper.GetHealthServiceException(
                        HealthServiceStatusCode.RecordNotFound,
                        error);
                throw e;
            }

            HealthRecordInfo thisRecord = records[0];
            this._custodian = thisRecord.IsCustodian;
            this._name = thisRecord.Name;
            this._relationshipName = thisRecord.RelationshipName;
            this._relationshipType = thisRecord.RelationshipType;
            this._dateAuthorizationExpires = thisRecord.DateAuthorizationExpires;
            this._quotaInBytes = thisRecord.QuotaInBytes;
            this._quotaUsedInBytes = thisRecord.QuotaUsedInBytes;
            this._state = thisRecord.State;
            this._dateCreated = thisRecord.DateCreated;
            this._displayName = thisRecord.DisplayName;
            this._authExpired = thisRecord.HasAuthorizationExpired;

            this._updated = true;
        }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceApplicationDuplicateCredentialException"/> 
 /// class with the specified error information to represent a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.DuplicateCredentialFound"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type.
 /// </remarks>
 /// 
 /// <param name="error">
 /// Information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceApplicationDuplicateCredentialException(
     HealthServiceResponseError error)
     : base(HealthServiceStatusCode.DuplicateCredentialFound, error)
 {
 }
 /// <summary>
 /// Creates an instance of the <see cref="HealthServiceInvalidPersonException"/> 
 /// class with the specified error information to represent a 
 /// HealthVault error code of 
 /// <see cref = "Microsoft.Health.HealthServiceStatusCode.InvalidPerson"/>.
 /// </summary>
 /// 
 /// <remarks>
 /// This constructor is internal to the SDK. Application developers 
 /// using the SDK should catch instances of this exception instead of 
 /// throwing new exceptions of this type. The error indicates that 
 /// the person specified in the request is either nonexistent or inactive.
 /// </remarks>
 /// 
 /// <param name="error">
 /// information about an error that occurred while processing
 /// the request.
 /// </param>
 /// 
 internal HealthServiceInvalidPersonException(HealthServiceResponseError error)
     : base(HealthServiceStatusCode.InvalidPerson, error)
 {
 }