< Summary

Class:Azure.AI.FormRecognizer.Models.RecognizeContentOperation
Assembly:Azure.AI.FormRecognizer
File(s):C:\Git\azure-sdk-for-net\sdk\formrecognizer\Azure.AI.FormRecognizer\src\RecognizeContentOperation.cs
Covered lines:38
Uncovered lines:11
Coverable lines:49
Total lines:222
Line coverage:77.5% (38 of 49)
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%
.ctor(...)-100%100%
.ctor(...)-100%100%
GetRawResponse()-100%100%
WaitForCompletionAsync(...)-0%100%
WaitForCompletionAsync(...)-100%100%
UpdateStatus(...)-0%100%
UpdateStatusAsync()-100%100%
UpdateStatusAsync()-65.22%75%
ConvertValue(...)-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\formrecognizer\Azure.AI.FormRecognizer\src\RecognizeContentOperation.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.Diagnostics;
 7using System.Linq;
 8using System.Threading;
 9using System.Threading.Tasks;
 10using Azure.Core;
 11using Azure.Core.Pipeline;
 12
 13namespace Azure.AI.FormRecognizer.Models
 14{
 15    /// <summary>
 16    /// Tracks the status of a long-running operation for recognizing layout elements from forms.
 17    /// </summary>
 18    public class RecognizeContentOperation : Operation<FormPageCollection>
 19    {
 20        /// <summary>Provides communication with the Form Recognizer Azure Cognitive Service through its REST API.</summ
 21        private readonly ServiceRestClient _serviceClient;
 22
 23        /// <summary>Provides tools for exception creation in case of failure.</summary>
 24        private readonly ClientDiagnostics _diagnostics;
 25
 26        private RequestFailedException _requestFailedException;
 27
 28        /// <summary>The last HTTP response received from the server. <c>null</c> until the first response is received.<
 29        private Response _response;
 30
 31        /// <summary>The result of the long-running operation. <c>null</c> until result is received on status update.</s
 32        private FormPageCollection _value;
 33
 34        /// <summary><c>true</c> if the long-running operation has completed. Otherwise, <c>false</c>.</summary>
 35        private bool _hasCompleted;
 36
 37        /// <summary>
 38        /// Gets an ID representing the operation that can be used to poll for the status
 39        /// of the long-running operation.
 40        /// </summary>
 18441        public override string Id { get; }
 42
 43        /// <summary>
 44        /// Final result of the long-running operation.
 45        /// </summary>
 46        /// <remarks>
 47        /// This property can be accessed only after the operation completes successfully (HasValue is true).
 48        /// </remarks>
 49        public override FormPageCollection Value
 50        {
 51            get
 52            {
 6053                if (HasCompleted && !HasValue)
 54#pragma warning disable CA1065 // Do not raise exceptions in unexpected locations
 055                    throw _requestFailedException;
 56#pragma warning restore CA1065 // Do not raise exceptions in unexpected locations
 57                else
 6058                    return OperationHelpers.GetValue(ref _value);
 59            }
 60        }
 61
 62        /// <summary>
 63        /// Returns true if the long-running operation completed.
 64        /// </summary>
 23665        public override bool HasCompleted => _hasCompleted;
 66
 67        /// <summary>
 68        /// Returns true if the long-running operation completed successfully and has produced final result (accessible 
 69        /// </summary>
 8070        public override bool HasValue => _value != null;
 71
 72        /// <summary>
 73        /// Initializes a new instance of the <see cref="RecognizeContentOperation"/> class.
 74        /// </summary>
 75        /// <param name="operationId">The ID of this operation.</param>
 76        /// <param name="client">The client used to check for completion.</param>
 877        public RecognizeContentOperation(string operationId, FormRecognizerClient client)
 78        {
 79            // TODO: Add argument validation here.
 80
 881            Id = operationId;
 882            _serviceClient = client.ServiceClient;
 883            _diagnostics = client.Diagnostics;
 884        }
 85
 86        /// <summary>
 87        /// Initializes a new instance of the <see cref="RecognizeContentOperation"/> class.
 88        /// </summary>
 89        /// <param name="serviceClient">The client for communicating with the Form Recognizer Azure Cognitive Service th
 90        /// <param name="diagnostics">The client diagnostics for exception creation in case of failure.</param>
 91        /// <param name="operationLocation">The address of the long-running operation. It can be obtained from the respo
 5692        internal RecognizeContentOperation(ServiceRestClient serviceClient, ClientDiagnostics diagnostics, string operat
 93        {
 5694            _serviceClient = serviceClient;
 5695            _diagnostics = diagnostics;
 96
 97            // TODO: Add validation here
 98            // https://github.com/Azure/azure-sdk-for-net/issues/10385
 5699            Id = operationLocation.Split('/').Last();
 56100        }
 101
 102        /// <summary>
 103        /// The last HTTP response received from the server.
 104        /// </summary>
 105        /// <remarks>
 106        /// The last response returned from the server during the lifecycle of this instance.
 107        /// An instance of <see cref="RecognizeContentOperation"/> sends requests to a server in UpdateStatusAsync, Upda
 108        /// Responses from these requests can be accessed using GetRawResponse.
 109        /// </remarks>
 220110        public override Response GetRawResponse() => _response;
 111
 112        /// <summary>
 113        /// Periodically calls the server till the long-running operation completes.
 114        /// </summary>
 115        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the periodical service calls.</pa
 116        /// <returns>The last HTTP response received from the server.</returns>
 117        /// <remarks>
 118        /// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result
 119        /// </remarks>
 120        public override ValueTask<Response<FormPageCollection>> WaitForCompletionAsync(CancellationToken cancellationTok
 0121            this.DefaultWaitForCompletionAsync(cancellationToken);
 122
 123        /// <summary>
 124        /// Periodically calls the server till the long-running operation completes.
 125        /// </summary>
 126        /// <param name="pollingInterval">
 127        /// The interval between status requests to the server.
 128        /// The interval can change based on information returned from the server.
 129        /// For example, the server might communicate to the client that there is not reason to poll for status change s
 130        /// </param>
 131        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the periodical service calls.</pa
 132        /// <returns>The last HTTP response received from the server.</returns>
 133        /// <remarks>
 134        /// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result
 135        /// </remarks>
 136        public override ValueTask<Response<FormPageCollection>> WaitForCompletionAsync(TimeSpan pollingInterval, Cancell
 40137            this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken);
 138
 139        /// <summary>
 140        /// Calls the server to get updated status of the long-running operation.
 141        /// </summary>
 142        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the service call.</param>
 143        /// <returns>The HTTP response received from the server.</returns>
 144        /// <remarks>
 145        /// This operation will update the value returned from GetRawResponse and might update HasCompleted, HasValue, a
 146        /// </remarks>
 147        public override Response UpdateStatus(CancellationToken cancellationToken = default) =>
 0148            UpdateStatusAsync(false, cancellationToken).EnsureCompleted();
 149
 150        /// <summary>
 151        /// Calls the server to get updated status of the long-running operation.
 152        /// </summary>
 153        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the service call.</param>
 154        /// <returns>The HTTP response received from the server.</returns>
 155        /// <remarks>
 156        /// This operation will update the value returned from GetRawResponse and might update HasCompleted, HasValue, a
 157        /// </remarks>
 158        public override async ValueTask<Response> UpdateStatusAsync(CancellationToken cancellationToken = default) =>
 180159            await UpdateStatusAsync(true, cancellationToken).ConfigureAwait(false);
 160
 161        /// <summary>
 162        /// Calls the server to get updated status of the long-running operation.
 163        /// </summary>
 164        /// <param name="async">When <c>true</c>, the method will be executed asynchronously; otherwise, it will execute
 165        /// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the service call.</param>
 166        /// <returns>The HTTP response received from the server.</returns>
 167        private async ValueTask<Response> UpdateStatusAsync(bool async, CancellationToken cancellationToken)
 168        {
 180169            if (!_hasCompleted)
 170            {
 180171                using DiagnosticScope scope = _diagnostics.CreateScope($"{nameof(RecognizeContentOperation)}.{nameof(Upd
 180172                scope.Start();
 173
 174                try
 175                {
 180176                    Response<AnalyzeOperationResult> update = async
 180177                        ? await _serviceClient.GetAnalyzeLayoutResultAsync(new Guid(Id), cancellationToken).ConfigureAwa
 180178                        : _serviceClient.GetAnalyzeLayoutResult(new Guid(Id), cancellationToken);
 179
 180180                    _response = update.GetRawResponse();
 181
 180182                    if (update.Value.Status == OperationStatus.Succeeded)
 183                    {
 184                        // we need to first assign a vaue and then mark the operation as completed to avoid race conditi
 40185                        _value = ConvertValue(update.Value.AnalyzeResult.PageResults, update.Value.AnalyzeResult.ReadRes
 40186                        _hasCompleted = true;
 187                    }
 140188                    else if (update.Value.Status == OperationStatus.Failed)
 189                    {
 0190                        _requestFailedException = await ClientCommon
 0191                            .CreateExceptionForFailedOperationAsync(async, _diagnostics, _response, update.Value.Analyze
 0192                            .ConfigureAwait(false);
 0193                        _hasCompleted = true;
 0194                        throw _requestFailedException;
 195                    }
 180196                }
 0197                catch (Exception e)
 198                {
 0199                    scope.Failed(e);
 0200                    throw;
 201                }
 180202            }
 203
 180204            return GetRawResponse();
 180205        }
 206
 207        private static FormPageCollection ConvertValue(IReadOnlyList<PageResult> pageResults, IReadOnlyList<ReadResult> 
 208        {
 209            Debug.Assert(pageResults.Count == readResults.Count);
 210
 40211            List<FormPage> pages = new List<FormPage>();
 40212            List<ReadResult> rawPages = readResults.ToList();
 213
 192214            for (var pageIndex = 0; pageIndex < pageResults.Count; pageIndex++)
 215            {
 56216                pages.Add(new FormPage(pageResults[pageIndex], rawPages, pageIndex));
 217            }
 218
 40219            return new FormPageCollection(pages);
 220        }
 221    }
 222}