< Summary

Class:Azure.AI.FormRecognizer.Models.RecognizeReceiptsOperation
Assembly:Azure.AI.FormRecognizer
File(s):C:\Git\azure-sdk-for-net\sdk\formrecognizer\Azure.AI.FormRecognizer\src\RecognizeReceiptsOperation.cs
Covered lines:37
Uncovered lines:11
Coverable lines:48
Total lines:216
Line coverage:77% (37 of 48)
Covered branches:11
Total branches:14
Branch coverage:78.5% (11 of 14)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
get_Id()-100%100%
get_Value()-66.67%75%
get_HasCompleted()-100%100%
get_HasValue()-100%100%
GetRawResponse()-100%100%
.ctor(...)-100%100%
.ctor(...)-100%100%
WaitForCompletionAsync(...)-0%100%
WaitForCompletionAsync(...)-100%100%
UpdateStatus(...)-0%100%
UpdateStatusAsync()-100%100%
UpdateStatusAsync()-65.22%75%
ConvertToRecognizedForms(...)-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\formrecognizer\Azure.AI.FormRecognizer\src\RecognizeReceiptsOperation.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Linq;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using Azure.Core;
 10using Azure.Core.Pipeline;
 11
 12namespace Azure.AI.FormRecognizer.Models
 13{
 14    /// <summary>
 15    /// Tracks the status of a long-running operation for recognizing values from receipts.
 16    /// </summary>
 17    public class RecognizeReceiptsOperation : Operation<RecognizedFormCollection>
 18    {
 19        /// <summary>Provides communication with the Form Recognizer Azure Cognitive Service through its REST API.</summ
 20        private readonly ServiceRestClient _serviceClient;
 21
 22        /// <summary>Provides tools for exception creation in case of failure.</summary>
 23        private readonly ClientDiagnostics _diagnostics;
 24
 25        private RequestFailedException _requestFailedException;
 26
 27        /// <summary>The last HTTP response received from the server. <c>null</c> until the first response is received.<
 28        private Response _response;
 29
 30        /// <summary>The result of the long-running operation. <c>null</c> until result is received on status update.</s
 31        private RecognizedFormCollection _value;
 32
 33        /// <summary><c>true</c> if the long-running operation has completed. Otherwise, <c>false</c>.</summary>
 34        private bool _hasCompleted;
 35
 36        /// <summary>
 37        /// Gets an ID representing the operation that can be used to poll for the status
 38        /// of the long-running operation.
 39        /// </summary>
 14840        public override string Id { get; }
 41
 42        /// <summary>
 43        /// Final result of the long-running operation.
 44        /// </summary>
 45        /// <remarks>
 46        /// This property can be accessed only after the operation completes successfully (HasValue is true).
 47        /// </remarks>
 48        public override RecognizedFormCollection Value
 49        {
 50            get
 51            {
 5652                if (HasCompleted && !HasValue)
 53#pragma warning disable CA1065 // Do not raise exceptions in unexpected locations
 054                    throw _requestFailedException;
 55#pragma warning restore CA1065 // Do not raise exceptions in unexpected locations
 56                else
 5657                    return OperationHelpers.GetValue(ref _value);
 58            }
 59        }
 60
 61        /// <summary>
 62        /// Returns true if the long-running operation completed.
 63        /// </summary>
 19664        public override bool HasCompleted => _hasCompleted;
 65
 66        /// <summary>
 67        /// Returns true if the long-running operation completed successfully and has produced final result (accessible 
 68        /// </summary>
 7669        public override bool HasValue => _value != null;
 70
 71        /// <summary>
 72        /// The last HTTP response received from the server.
 73        /// </summary>
 74        /// <remarks>
 75        /// The last response returned from the server during the lifecycle of this instance.
 76        /// An instance of <see cref="RecognizeReceiptsOperation"/> sends requests to a server in UpdateStatusAsync, Upd
 77        /// Responses from these requests can be accessed using GetRawResponse.
 78        /// </remarks>
 18079        public override Response GetRawResponse() => _response;
 80
 81        /// <summary>
 82        /// Initializes a new instance of the <see cref="RecognizeReceiptsOperation"/> class.
 83        /// </summary>
 84        /// <param name="operationId">The ID of this operation.</param>
 85        /// <param name="client">The client used to check for completion.</param>
 886        public RecognizeReceiptsOperation(string operationId, FormRecognizerClient client)
 87        {
 88            // TODO: Add argument validation here.
 89
 890            Id = operationId;
 891            _serviceClient = client.ServiceClient;
 892            _diagnostics = client.Diagnostics;
 893        }
 94
 95        /// <summary>
 96        /// Initializes a new instance of the <see cref="RecognizeReceiptsOperation"/> class.
 97        /// </summary>
 98        /// <param name="serviceClient">The client for communicating with the Form Recognizer Azure Cognitive Service th
 99        /// <param name="diagnostics">The client diagnostics for exception creation in case of failure.</param>
 100        /// <param name="operationLocation">The address of the long-running operation. It can be obtained from the respo
 52101        internal RecognizeReceiptsOperation(ServiceRestClient serviceClient, ClientDiagnostics diagnostics, string opera
 102        {
 52103            _serviceClient = serviceClient;
 52104            _diagnostics = diagnostics;
 105
 106            // TODO: Add validation here
 107            // https://github.com/Azure/azure-sdk-for-net/issues/10385
 52108            Id = operationLocation.Split('/').Last();
 52109        }
 110
 111        /// <summary>
 112        /// Periodically calls the server till the long-running operation completes.
 113        /// </summary>
 114        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the periodical service calls.</pa
 115        /// <returns>The last HTTP response received from the server.</returns>
 116        /// <remarks>
 117        /// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result
 118        /// </remarks>
 119        public override ValueTask<Response<RecognizedFormCollection>> WaitForCompletionAsync(CancellationToken cancellat
 0120            this.DefaultWaitForCompletionAsync(cancellationToken);
 121
 122        /// <summary>
 123        /// Periodically calls the server till the long-running operation completes.
 124        /// </summary>
 125        /// <param name="pollingInterval">
 126        /// The interval between status requests to the server.
 127        /// The interval can change based on information returned from the server.
 128        /// For example, the server might communicate to the client that there is not reason to poll for status change s
 129        /// </param>
 130        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the periodical service calls.</pa
 131        /// <returns>The last HTTP response received from the server.</returns>
 132        /// <remarks>
 133        /// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result
 134        /// </remarks>
 135        public override ValueTask<Response<RecognizedFormCollection>> WaitForCompletionAsync(TimeSpan pollingInterval, C
 36136            this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken);
 137
 138        /// <summary>
 139        /// Calls the server to get updated status of the long-running operation.
 140        /// </summary>
 141        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the service call.</param>
 142        /// <returns>The HTTP response received from the server.</returns>
 143        /// <remarks>
 144        /// This operation will update the value returned from GetRawResponse and might update HasCompleted, HasValue, a
 145        /// </remarks>
 146        public override Response UpdateStatus(CancellationToken cancellationToken = default) =>
 0147            UpdateStatusAsync(false, cancellationToken).EnsureCompleted();
 148
 149        /// <summary>
 150        /// Calls the server to get updated status of the long-running operation.
 151        /// </summary>
 152        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the service call.</param>
 153        /// <returns>The HTTP response received from the server.</returns>
 154        /// <remarks>
 155        /// This operation will update the value returned from GetRawResponse and might update HasCompleted, HasValue, a
 156        /// </remarks>
 157        public override async ValueTask<Response> UpdateStatusAsync(CancellationToken cancellationToken = default) =>
 144158            await UpdateStatusAsync(true, cancellationToken).ConfigureAwait(false);
 159
 160        /// <summary>
 161        /// Calls the server to get updated status of the long-running operation.
 162        /// </summary>
 163        /// <param name="async">When <c>true</c>, the method will be executed asynchronously; otherwise, it will execute
 164        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the service call.</param>
 165        /// <returns>The HTTP response received from the server.</returns>
 166        private async ValueTask<Response> UpdateStatusAsync(bool async, CancellationToken cancellationToken)
 167        {
 144168            if (!_hasCompleted)
 169            {
 144170                using DiagnosticScope scope = _diagnostics.CreateScope($"{nameof(RecognizeReceiptsOperation)}.{nameof(Up
 144171                scope.Start();
 172
 173                try
 174                {
 144175                    Response<AnalyzeOperationResult> update = async
 144176                        ? await _serviceClient.GetAnalyzeReceiptResultAsync(new Guid(Id), cancellationToken).ConfigureAw
 144177                        : _serviceClient.GetAnalyzeReceiptResult(new Guid(Id), cancellationToken);
 178
 144179                    _response = update.GetRawResponse();
 180
 144181                    if (update.Value.Status == OperationStatus.Succeeded)
 182                    {
 183                        // We need to first assign a value and then mark the operation as completed to avoid a race cond
 36184                        _value = ConvertToRecognizedForms(update.Value.AnalyzeResult);
 36185                        _hasCompleted = true;
 186                    }
 108187                    else if (update.Value.Status == OperationStatus.Failed)
 188                    {
 0189                        _requestFailedException = await ClientCommon
 0190                            .CreateExceptionForFailedOperationAsync(async, _diagnostics, _response, update.Value.Analyze
 0191                            .ConfigureAwait(false);
 0192                        _hasCompleted = true;
 0193                        throw _requestFailedException;
 194                    }
 144195                }
 0196                catch (Exception e)
 197                {
 0198                    scope.Failed(e);
 0199                    throw;
 200                }
 144201            }
 202
 144203            return GetRawResponse();
 144204        }
 205
 206        private static RecognizedFormCollection ConvertToRecognizedForms(AnalyzeResult analyzeResult)
 207        {
 36208            List<RecognizedForm> receipts = new List<RecognizedForm>();
 176209            for (int i = 0; i < analyzeResult.DocumentResults.Count; i++)
 210            {
 52211                receipts.Add(new RecognizedForm(analyzeResult.DocumentResults[i], analyzeResult.PageResults, analyzeResu
 212            }
 36213            return new RecognizedFormCollection(receipts);
 214        }
 215    }
 216}