diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md b/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md index 91f8418fe692..bfa17d276024 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md @@ -1,6 +1,10 @@ # Release History ## 1.0.0-beta.3 (Unreleased) +- Rename parameters data and sourceUrl parameters found on methods for FormRecognizerClient to form and formUrl, respectively. +- Rename parameters for receipt API methods to receipt and receiptUrl. +- Raise `HttpResponseException` when a model with `ModelStatus.Invalid` is returned from the `beginTraining()` API's +- Fix `HttpResponseException` to include the error object thrown on invalid analyze status for recognize API's - Update FormField property `transactionTime` on `USReceipt` to return `LocalTime` instead of `String` - Rename model `PageRange` to `FormPageRange` - Rename property `startPageNumber` to `firstPageNumber` and `endPageNumber` to `lastPageNumber` in model `PageRange` diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/README.md b/sdk/formrecognizer/azure-ai-formrecognizer/README.md index 00122b6d0b18..17c53d18fa42 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/README.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/README.md @@ -28,7 +28,7 @@ from form documents. It includes the following main functionalities: ``` [//]: # ({x-version-update-end}) -### Create a Form Recognizer resource +#### Create a Form Recognizer resource Form Recognizer supports both [multi-service and single-service access][service_access]. Create a Cognitive Service's resource if you plan to access multiple cognitive services under a single endpoint/key. For Form Recognizer access only, create a Form Recognizer resource. diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClient.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClient.java index 8cb36fd83b35..daae4ed77bb1 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClient.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClient.java @@ -6,10 +6,9 @@ import com.azure.ai.formrecognizer.implementation.FormRecognizerClientImpl; import com.azure.ai.formrecognizer.implementation.models.AnalyzeOperationResult; import com.azure.ai.formrecognizer.implementation.models.ContentType; +import com.azure.ai.formrecognizer.models.ErrorInformation; import com.azure.ai.formrecognizer.implementation.models.OperationStatus; import com.azure.ai.formrecognizer.implementation.models.SourcePath; -import com.azure.ai.formrecognizer.models.ErrorInformation; -import com.azure.ai.formrecognizer.models.ErrorResponseException; import com.azure.ai.formrecognizer.models.FormContentType; import com.azure.ai.formrecognizer.models.FormPage; import com.azure.ai.formrecognizer.models.OperationResult; @@ -74,7 +73,7 @@ public final class FormRecognizerAsyncClient { } /** - * Recognizes and extracts form data from documents using optical character recognition (OCR) and a custom trained + * Recognizes form data from documents using optical character recognition (OCR) and a custom trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -82,20 +81,23 @@ public final class FormRecognizerAsyncClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeCustomFormsFromUrl#string-string} * - * @param fileSourceUrl The source URL to the input document. Size of the file must be less than 50 MB. + * @param formUrl The source URL to the input form. * @param modelId The UUID string format custom trained model Id to be used. * - * @return A {@link PollerFlux} that polls the extract custom form operation until it has completed, has failed, + * @return A {@link PollerFlux} that polls the recognize custom form operation until it has completed, has failed, * or has been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code formUrl}, {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> - beginRecognizeCustomFormsFromUrl(String fileSourceUrl, String modelId) { - return beginRecognizeCustomFormsFromUrl(fileSourceUrl, modelId, false, null); + beginRecognizeCustomFormsFromUrl(String formUrl, String modelId) { + return beginRecognizeCustomFormsFromUrl(formUrl, modelId, false, null); } /** - * Recognizes and extracts form data from documents using optical character recognition (OCR) and a custom trained + * Recognizes form data from documents using optical character recognition (OCR) and a custom trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -103,30 +105,33 @@ public final class FormRecognizerAsyncClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeCustomFormsFromUrl#string-string-boolean-Duration} * - * @param fileSourceUrl The source URL to the input document. Size of the file must be less than 50 MB. + * @param formUrl The source URL to the input form. * @param modelId The UUID string format custom trained model Id to be used. * @param includeTextDetails Include text lines and element references in the result. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link PollerFlux} that polls the extract custom form operation until it has completed, has failed, + * @return A {@link PollerFlux} that polls the recognize custom form operation until it has completed, has failed, * or has been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code formUrl}, {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> - beginRecognizeCustomFormsFromUrl(String fileSourceUrl, String modelId, boolean includeTextDetails, + beginRecognizeCustomFormsFromUrl(String formUrl, String modelId, boolean includeTextDetails, Duration pollInterval) { final Duration interval = pollInterval != null ? pollInterval : DEFAULT_DURATION; return new PollerFlux>( interval, - analyzeFormActivationOperation(fileSourceUrl, modelId, includeTextDetails), + analyzeFormActivationOperation(formUrl, modelId, includeTextDetails), createAnalyzeFormPollOperation(modelId), (activationResponse, context) -> Mono.error(new RuntimeException("Cancellation is not supported")), fetchAnalyzeFormResultOperation(modelId, includeTextDetails)); } /** - * Recognizes and extracts form data from documents using optical character recognition (OCR) and a custom trained + * Recognizes form data from documents using optical character recognition (OCR) and a custom trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -137,22 +142,25 @@ public final class FormRecognizerAsyncClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeCustomForms#Flux-string-long-FormContentType} * - * @param data The data of the document to be extract receipt information from. + * @param form The data of the form to recognize form information from. * @param modelId The UUID string format custom trained model Id to be used. * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * - * @return A {@link PollerFlux} that polls the extract receipt operation until it has completed, has failed, or has - * been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @return A {@link PollerFlux} that polls the recognize receipt operation until it has completed, has failed, + * or has been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code form}, {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> - beginRecognizeCustomForms(Flux data, String modelId, long length, FormContentType formContentType) { - return beginRecognizeCustomForms(data, modelId, length, formContentType, false, null); + beginRecognizeCustomForms(Flux form, String modelId, long length, FormContentType formContentType) { + return beginRecognizeCustomForms(form, modelId, length, formContentType, false, null); } /** - * Recognizes and extracts form data from documents using optical character recognition (OCR) and a custom trained + * Recognizes form data from documents using optical character recognition (OCR) and a custom trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -163,7 +171,7 @@ public final class FormRecognizerAsyncClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeCustomForms#Flux-string-long-FormContentType-boolean-Duration} * - * @param data The data of the document to be extract receipt information from. + * @param form The data of the form to recognize form information from. * @param modelId The UUID string format custom trained model Id to be used. * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param includeTextDetails Include text lines and element references in the result. @@ -171,24 +179,27 @@ public final class FormRecognizerAsyncClient { * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link PollerFlux} that polls the extract receipt operation until it has completed, has failed, or has - * been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @return A {@link PollerFlux} that polls the recognize receipt operation until it has completed, has failed, + * or has been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code form}, {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> - beginRecognizeCustomForms(Flux data, String modelId, long length, FormContentType formContentType, + beginRecognizeCustomForms(Flux form, String modelId, long length, FormContentType formContentType, boolean includeTextDetails, Duration pollInterval) { final Duration interval = pollInterval != null ? pollInterval : DEFAULT_DURATION; return new PollerFlux>( interval, - analyzeFormStreamActivationOperation(data, modelId, length, formContentType, includeTextDetails), + analyzeFormStreamActivationOperation(form, modelId, length, formContentType, includeTextDetails), createAnalyzeFormPollOperation(modelId), (activationResponse, context) -> Mono.error(new RuntimeException("Cancellation is not supported")), fetchAnalyzeFormResultOperation(modelId, includeTextDetails)); } /** - * Recognizes and extracts layout data from documents using optical character recognition (OCR) and a custom trained + * Recognizes layout data from documents using optical character recognition (OCR) and a custom trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -196,18 +207,21 @@ public final class FormRecognizerAsyncClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeContentFromUrl#string} * - * @param fileSourceUrl The source URL to the input document. Size of the file must be less than 50 MB. + * @param formUrl The source URL to the input form. * - * @return A {@link PollerFlux} that polls the extract custom form operation until it has completed, has failed, + * @return A {@link PollerFlux} that polls the recognize custom form operation until it has completed, has failed, * or has been cancelled. The completed operation returns a List of {@link FormPage}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code formUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) - public PollerFlux> beginRecognizeContentFromUrl(String fileSourceUrl) { - return beginRecognizeContentFromUrl(fileSourceUrl, null); + public PollerFlux> beginRecognizeContentFromUrl(String formUrl) { + return beginRecognizeContentFromUrl(formUrl, null); } /** - * Recognizes and extracts layout data using optical character recognition (OCR) and a prebuilt receipt trained + * Recognizes layout data using optical character recognition (OCR) and a prebuilt receipt trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -215,19 +229,22 @@ public PollerFlux> beginRecognizeContentFromUrl( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeContentFromUrl#string-Duration} * - * @param sourceUrl The source URL to the input document. Size of the file must be less than 50 MB. + * @param formUrl The source URL to the input form. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link PollerFlux} that polls the extract receipt operation until it has completed, has failed, or has - * been cancelled. The completed operation returns a List of {@link FormPage}. + * @return A {@link PollerFlux} that polls the recognize receipt operation until it has completed, has failed, + * or has been cancelled. The completed operation returns a List of {@link FormPage}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code formUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> - beginRecognizeContentFromUrl(String sourceUrl, Duration pollInterval) { + beginRecognizeContentFromUrl(String formUrl, Duration pollInterval) { final Duration interval = pollInterval != null ? pollInterval : DEFAULT_DURATION; return new PollerFlux>(interval, - contentAnalyzeActivationOperation(sourceUrl), + contentAnalyzeActivationOperation(formUrl), extractContentPollOperation(), (activationResponse, context) -> monoError(logger, new RuntimeException("Cancellation is not supported")), @@ -235,7 +252,7 @@ public PollerFlux> beginRecognizeContentFromUrl( } /** - * Recognizes and extracts layout data using optical character recognition (OCR) and a prebuilt receipt + * Recognizes layout data using optical character recognition (OCR) and a prebuilt receipt * trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -246,21 +263,24 @@ public PollerFlux> beginRecognizeContentFromUrl( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeContent#Flux-long-FormContentType} * - * @param data The data of the document to be extract receipt information from. + * @param form The data of the form to recognize content information from. * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * - * @return A {@link PollerFlux} that polls the extract receipt operation until it has completed, has failed, or has - * been cancelled. The completed operation returns a List of {@link FormPage}. + * @return A {@link PollerFlux} that polls the recognize receipt operation until it has completed, has failed, + * or has been cancelled. The completed operation returns a List of {@link FormPage}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code form} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> beginRecognizeContent( - Flux data, long length, FormContentType formContentType) { - return beginRecognizeContent(data, length, formContentType, null); + Flux form, long length, FormContentType formContentType) { + return beginRecognizeContent(form, length, formContentType, null); } /** - * Recognizes and extracts layout data using optical character recognition (OCR) and a prebuilt receipt + * Recognizes layout data using optical character recognition (OCR) and a prebuilt receipt * trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -271,21 +291,24 @@ public PollerFlux> beginRecognizeContent( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeContent#Flux-long-FormContentType-Duration} * - * @param data The data of the document to be extract receipt information from. + * @param form The data of the form to recognize content information from. * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link PollerFlux} that polls the extract receipt operation until it has completed, has failed, or has - * been cancelled. The completed operation returns a List of {@link FormPage}. + * @return A {@link PollerFlux} that polls the recognize receipt operation until it has completed, has failed, + * or has been cancelled. The completed operation returns a List of {@link FormPage}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code form} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> beginRecognizeContent( - Flux data, long length, FormContentType formContentType, Duration pollInterval) { + Flux form, long length, FormContentType formContentType, Duration pollInterval) { return new PollerFlux<>( pollInterval != null ? pollInterval : DEFAULT_DURATION, - contentStreamActivationOperation(data, length, formContentType), + contentStreamActivationOperation(form, length, formContentType), extractContentPollOperation(), (activationResponse, context) -> monoError(logger, new RuntimeException("Cancellation is not supported")), @@ -293,7 +316,7 @@ public PollerFlux> beginRecognizeContent( } /** - * Recognizes and extracts receipt data using optical character recognition (OCR) and a prebuilt receipt trained + * Recognizes receipt data using optical character recognition (OCR) and a prebuilt receipt trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -301,19 +324,22 @@ public PollerFlux> beginRecognizeContent( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeReceiptsFromUrl#string} * - * @param sourceUrl The source URL to the input document. Size of the file must be less than 50 MB. + * @param receiptUrl The source URL to the input receipt. * - * @return A {@link PollerFlux} that polls the extract receipt operation until it has completed, has failed, or has - * been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @return A {@link PollerFlux} that polls the recognize receipt operation until it has completed, has failed, + * or has been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code receiptUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> - beginRecognizeReceiptsFromUrl(String sourceUrl) { - return beginRecognizeReceiptsFromUrl(sourceUrl, false, null); + beginRecognizeReceiptsFromUrl(String receiptUrl) { + return beginRecognizeReceiptsFromUrl(receiptUrl, false, null); } /** - * Recognizes and extracts receipt data using optical character recognition (OCR) and a prebuilt receipt trained + * Recognizes receipt data using optical character recognition (OCR) and a prebuilt receipt trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -321,20 +347,23 @@ public PollerFlux> beginRecognizeContent( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeReceiptsFromUrl#string-boolean-Duration} * - * @param sourceUrl The source URL to the input document. Size of the file must be less than 50 MB. + * @param receiptUrl The source URL to the input receipt. * @param includeTextDetails Include text lines and element references in the result. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link PollerFlux} that polls the extract receipt operation until it has completed, has failed, or has - * been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @return A {@link PollerFlux} that polls the recognize receipt operation until it has completed, has failed, + * or has been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code receiptUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> - beginRecognizeReceiptsFromUrl(String sourceUrl, boolean includeTextDetails, Duration pollInterval) { + beginRecognizeReceiptsFromUrl(String receiptUrl, boolean includeTextDetails, Duration pollInterval) { final Duration interval = pollInterval != null ? pollInterval : DEFAULT_DURATION; return new PollerFlux>(interval, - receiptAnalyzeActivationOperation(sourceUrl, includeTextDetails), + receiptAnalyzeActivationOperation(receiptUrl, includeTextDetails), extractReceiptPollOperation(), (activationResponse, context) -> monoError(logger, new RuntimeException("Cancellation is not supported")), @@ -342,7 +371,7 @@ public PollerFlux> beginRecognizeContent( } /** - * Recognizes and extracts receipt data using optical character recognition (OCR) and a prebuilt receipt + * Recognizes receipt data using optical character recognition (OCR) and a prebuilt receipt * trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -353,21 +382,24 @@ public PollerFlux> beginRecognizeContent( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeReceipts#Flux-long-FormContentType} * - * @param data The data of the document to be extract receipt information from. + * @param receipt The data of the document to recognize receipt information from. * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * - * @return A {@link PollerFlux} that polls the extract receipt operation until it has completed, has failed, or has - * been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @return A {@link PollerFlux} that polls the recognize receipt operation until it has completed, has failed, + * or has been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code receipt} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> beginRecognizeReceipts( - Flux data, long length, FormContentType formContentType) { - return beginRecognizeReceipts(data, length, formContentType, false, null); + Flux receipt, long length, FormContentType formContentType) { + return beginRecognizeReceipts(receipt, length, formContentType, false, null); } /** - * Recognizes and extracts receipt data from documents using optical character recognition (OCR) + * Recognizes receipt data from documents using optical character recognition (OCR) * and a prebuilt receipt trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -378,24 +410,27 @@ public PollerFlux> beginRecognizeReceip *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerAsyncClient.beginRecognizeReceipts#Flux-long-FormContentType-boolean-Duration} * - * @param data The data of the document to be extract receipt information from. + * @param receipt The data of the receipt to recognize receipt information from. * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * @param includeTextDetails Include text lines and element references in the result. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link PollerFlux} that polls the extract receipt operation until it has completed, has failed, or has - * been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @return A {@link PollerFlux} that polls the recognize receipt operation until it has completed, has failed, + * or has been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code receipt} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PollerFlux> beginRecognizeReceipts( - Flux data, long length, FormContentType formContentType, boolean includeTextDetails, + Flux receipt, long length, FormContentType formContentType, boolean includeTextDetails, Duration pollInterval) { return new PollerFlux<>( pollInterval != null ? pollInterval : DEFAULT_DURATION, - receiptStreamActivationOperation(data, length, formContentType, includeTextDetails), + receiptStreamActivationOperation(receipt, length, formContentType, includeTextDetails), extractReceiptPollOperation(), (activationResponse, context) -> monoError(logger, new RuntimeException("Cancellation is not supported")), @@ -403,12 +438,12 @@ public PollerFlux> beginRecognizeReceip } private Function, Mono> receiptAnalyzeActivationOperation( - String sourceUrl, boolean includeTextDetails) { + String receiptUrl, boolean includeTextDetails) { return (pollingContext) -> { try { - Objects.requireNonNull(sourceUrl, "'sourceUrl' is required and cannot be null."); + Objects.requireNonNull(receiptUrl, "'receiptUrl' is required and cannot be null."); return service.analyzeReceiptAsyncWithResponseAsync(includeTextDetails, - new SourcePath().setSource(sourceUrl)) + new SourcePath().setSource(receiptUrl)) .map(response -> new OperationResult(parseModelId(response.getDeserializedHeaders().getOperationLocation()))); } catch (RuntimeException ex) { @@ -418,19 +453,19 @@ private Function, Mono> receipt } private Function, Mono> receiptStreamActivationOperation( - Flux data, long length, FormContentType formContentType, boolean includeTextDetails) { + Flux form, long length, FormContentType formContentType, boolean includeTextDetails) { return pollingContext -> { try { - Objects.requireNonNull(data, "'data' is required and cannot be null."); + Objects.requireNonNull(form, "'form' is required and cannot be null."); if (formContentType != null) { return service.analyzeReceiptAsyncWithResponseAsync( - ContentType.fromString(formContentType.toString()), data, length, includeTextDetails) + ContentType.fromString(formContentType.toString()), form, length, includeTextDetails) .map(response -> new OperationResult( parseModelId(response.getDeserializedHeaders().getOperationLocation()))); } else { - return detectContentType(data) + return detectContentType(form) .flatMap(contentType -> - service.analyzeReceiptAsyncWithResponseAsync(contentType, data, length, includeTextDetails) + service.analyzeReceiptAsyncWithResponseAsync(contentType, form, length, includeTextDetails) .map(response -> new OperationResult( parseModelId(response.getDeserializedHeaders().getOperationLocation())))); } @@ -463,7 +498,7 @@ private Function, Mono> receipt final UUID resultUid = UUID.fromString(pollingContext.getLatestResponse().getValue().getResultId()); return service.getAnalyzeReceiptResultWithResponseAsync(resultUid) .map(modelSimpleResponse -> { - throwIfAnalyzeStatusInvalid(modelSimpleResponse); + throwIfAnalyzeStatusInvalid(modelSimpleResponse.getValue()); return toReceipt(modelSimpleResponse.getValue().getAnalyzeResult(), includeTextDetails); }); } catch (RuntimeException ex) { @@ -473,11 +508,11 @@ private Function, Mono> receipt } private Function, Mono> contentAnalyzeActivationOperation( - String sourceUrl) { + String formUrl) { return (pollingContext) -> { try { - Objects.requireNonNull(sourceUrl, "'sourceUrl' is required and cannot be null."); - return service.analyzeLayoutAsyncWithResponseAsync(new SourcePath().setSource(sourceUrl)) + Objects.requireNonNull(formUrl, "'formUrl' is required and cannot be null."); + return service.analyzeLayoutAsyncWithResponseAsync(new SourcePath().setSource(formUrl)) .map(response -> new OperationResult(parseModelId(response.getDeserializedHeaders().getOperationLocation()))); } catch (RuntimeException ex) { @@ -487,19 +522,19 @@ private Function, Mono> content } private Function, Mono> contentStreamActivationOperation( - Flux data, long length, FormContentType formContentType) { + Flux form, long length, FormContentType formContentType) { return pollingContext -> { try { - Objects.requireNonNull(data, "'data' is required and cannot be null."); + Objects.requireNonNull(form, "'form' is required and cannot be null."); if (formContentType != null) { return service.analyzeLayoutAsyncWithResponseAsync( - ContentType.fromString(formContentType.toString()), data, length) + ContentType.fromString(formContentType.toString()), form, length) .map(response -> new OperationResult(parseModelId( response.getDeserializedHeaders().getOperationLocation()))); } else { - return detectContentType(data) + return detectContentType(form) .flatMap(contentType -> - service.analyzeLayoutAsyncWithResponseAsync(contentType, data, length) + service.analyzeLayoutAsyncWithResponseAsync(contentType, form, length) .map(response -> new OperationResult( parseModelId(response.getDeserializedHeaders().getOperationLocation())))); } @@ -532,7 +567,7 @@ private Function, Mono> content final UUID resultUid = UUID.fromString(pollingContext.getLatestResponse().getValue().getResultId()); return service.getAnalyzeLayoutResultWithResponseAsync(resultUid) .map(modelSimpleResponse -> { - throwIfAnalyzeStatusInvalid(modelSimpleResponse); + throwIfAnalyzeStatusInvalid(modelSimpleResponse.getValue()); return toRecognizedLayout(modelSimpleResponse.getValue().getAnalyzeResult(), true); }); } catch (RuntimeException ex) { @@ -550,7 +585,7 @@ private Function, Mono> content UUID modelUid = UUID.fromString(modelId); return service.getAnalyzeFormResultWithResponseAsync(modelUid, resultUid) .map(modelSimpleResponse -> { - throwIfAnalyzeStatusInvalid(modelSimpleResponse); + throwIfAnalyzeStatusInvalid(modelSimpleResponse.getValue()); return toRecognizedForm(modelSimpleResponse.getValue().getAnalyzeResult(), includeTextDetails); }); } catch (RuntimeException ex) { @@ -563,15 +598,14 @@ private Function, Mono> content * Helper method that throws a {@link HttpResponseException} if {@link AnalyzeOperationResult#getStatus()} is * {@link OperationStatus#FAILED}. * - * @param modelSimpleResponse The response returned from the service. + * @param analyzeResponse The response returned from the service. */ - private void throwIfAnalyzeStatusInvalid(SimpleResponse modelSimpleResponse) { - if (modelSimpleResponse.getValue().getStatus().equals(OperationStatus.FAILED)) { - List errorInformationList = - modelSimpleResponse.getValue().getAnalyzeResult().getErrors(); + private void throwIfAnalyzeStatusInvalid(AnalyzeOperationResult analyzeResponse) { + if (OperationStatus.FAILED.equals(analyzeResponse.getStatus())) { + List errorInformationList = analyzeResponse.getAnalyzeResult().getErrors(); if (!CoreUtils.isNullOrEmpty(errorInformationList)) { - throw logger.logExceptionAsError( - new ErrorResponseException(errorInformationList.get(0).getMessage(), null)); + throw logger.logExceptionAsError(new HttpResponseException("Analyze operation failed.", null, + errorInformationList)); } } } @@ -595,13 +629,13 @@ private void throwIfAnalyzeStatusInvalid(SimpleResponse } private Function, Mono> analyzeFormActivationOperation( - String fileSourceUrl, String modelId, boolean includeTextDetails) { + String formUrl, String modelId, boolean includeTextDetails) { return (pollingContext) -> { try { - Objects.requireNonNull(fileSourceUrl, "'fileSourceUrl' is required and cannot be null."); + Objects.requireNonNull(formUrl, "'formUrl' is required and cannot be null."); Objects.requireNonNull(modelId, "'modelId' is required and cannot be null."); return service.analyzeWithCustomModelWithResponseAsync(UUID.fromString(modelId), includeTextDetails, - new SourcePath().setSource(fileSourceUrl)) + new SourcePath().setSource(formUrl)) .map(response -> new OperationResult(parseModelId(response.getDeserializedHeaders().getOperationLocation()))); } catch (RuntimeException ex) { @@ -611,22 +645,22 @@ private Function, Mono> analyze } private Function, Mono> analyzeFormStreamActivationOperation( - Flux data, String modelId, long length, + Flux form, String modelId, long length, FormContentType formContentType, boolean includeTextDetails) { return pollingContext -> { try { - Objects.requireNonNull(data, "'data' is required and cannot be null."); + Objects.requireNonNull(form, "'form' is required and cannot be null."); Objects.requireNonNull(modelId, "'modelId' is required and cannot be null."); if (formContentType != null) { return service.analyzeWithCustomModelWithResponseAsync(UUID.fromString(modelId), - ContentType.fromString(formContentType.toString()), data, length, includeTextDetails) + ContentType.fromString(formContentType.toString()), form, length, includeTextDetails) .map(response -> new OperationResult(parseModelId( response.getDeserializedHeaders().getOperationLocation()))); } else { - return detectContentType(data) + return detectContentType(form) .flatMap(contentType -> - service.analyzeWithCustomModelWithResponseAsync(UUID.fromString(modelId), contentType, data, + service.analyzeWithCustomModelWithResponseAsync(UUID.fromString(modelId), contentType, form, length, includeTextDetails) .map(response -> new OperationResult( parseModelId(response.getDeserializedHeaders().getOperationLocation())))); diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClient.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClient.java index 27bd9d76ebf7..0700a8e22249 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClient.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClient.java @@ -4,6 +4,8 @@ package com.azure.ai.formrecognizer; import com.azure.ai.formrecognizer.implementation.Utility; +import com.azure.ai.formrecognizer.implementation.models.AnalyzeOperationResult; +import com.azure.ai.formrecognizer.implementation.models.OperationStatus; import com.azure.ai.formrecognizer.models.FormContentType; import com.azure.ai.formrecognizer.models.FormPage; import com.azure.ai.formrecognizer.models.OperationResult; @@ -12,6 +14,7 @@ import com.azure.core.annotation.ReturnType; import com.azure.core.annotation.ServiceClient; import com.azure.core.annotation.ServiceMethod; +import com.azure.core.exception.HttpResponseException; import com.azure.core.util.polling.SyncPoller; import reactor.core.publisher.Flux; @@ -22,7 +25,7 @@ /** * This class provides a synchronous client that contains all the operations that apply to Azure Form Recognizer. - * Operations allowed by the client are recognizing receipt data from documents, extracting layout information and + * Operations allowed by the client are recognizing receipt data from documents, recognizing layout information and * analyzing custom forms for predefined data. * *

Instantiating a synchronous Form Recognizer Client

@@ -45,7 +48,7 @@ public final class FormRecognizerClient { } /** - * Recognizes and extracts receipt data from documents using optical character recognition (OCR) + * Recognizes receipt data from documents using optical character recognition (OCR) * and a custom trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support

@@ -53,20 +56,23 @@ public final class FormRecognizerClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeCustomFormsFromUrl#string-string} * - * @param fileSourceUrl The source URL to the input document. Size of the file must be less than 20 MB. + * @param formUrl The source URL to the input form. * @param modelId The UUID string format custom trained model Id to be used. * - * @return A {@link SyncPoller} to poll the progress of the extract custom form operation until it has completed, + * @return A {@link SyncPoller} to poll the progress of the recognize custom form operation until it has completed, * has failed, or has been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code formUrl}, {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeCustomFormsFromUrl(String fileSourceUrl, String modelId) { - return beginRecognizeCustomFormsFromUrl(fileSourceUrl, modelId, false, null); + beginRecognizeCustomFormsFromUrl(String formUrl, String modelId) { + return beginRecognizeCustomFormsFromUrl(formUrl, modelId, false, null); } /** - * Recognizes and extracts receipt data from documents using optical character recognition (OCR) + * Recognizes receipt data from documents using optical character recognition (OCR) * and a custom trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support

@@ -74,25 +80,28 @@ public final class FormRecognizerClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeCustomFormsFromUrl#string-string-boolean-Duration} * - * @param fileSourceUrl The source URL to the input document. Size of the file must be less than 20 MB. + * @param formUrl The source URL to the input form. * @param modelId The UUID string format custom trained model Id to be used. * @param includeTextDetails Include text lines and element references in the result. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link SyncPoller} to poll the progress of the extract custom form operation until it has completed, + * @return A {@link SyncPoller} to poll the progress of the recognize custom form operation until it has completed, * has failed, or has been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code formUrl}, {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeCustomFormsFromUrl(String fileSourceUrl, String modelId, boolean includeTextDetails, + beginRecognizeCustomFormsFromUrl(String formUrl, String modelId, boolean includeTextDetails, Duration pollInterval) { - return client.beginRecognizeCustomFormsFromUrl(fileSourceUrl, modelId, includeTextDetails, pollInterval) + return client.beginRecognizeCustomFormsFromUrl(formUrl, modelId, includeTextDetails, pollInterval) .getSyncPoller(); } /** - * Recognizes and extracts form data from documents using optical character recognition (OCR) and a custom trained + * Recognizes form data from documents using optical character recognition (OCR) and a custom trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -100,22 +109,25 @@ public final class FormRecognizerClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeCustomForms#InputStream-string-long-FormContentType} * - * @param data The data of the document to be extract receipt information from. + * @param form The data of the form to recognize form information from. * @param modelId The UUID string format custom trained model Id to be used. - * @param length The exact length of the data. Size of the file must be less than 20 MB. + * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * - * @return A {@link SyncPoller} that polls the extract custom form operation until it has completed, + * @return A {@link SyncPoller} that polls the recognize custom form operation until it has completed, * has failed, or has been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code form}, {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeCustomForms(InputStream data, String modelId, long length, FormContentType formContentType) { - return beginRecognizeCustomForms(data, modelId, length, formContentType, false, null); + beginRecognizeCustomForms(InputStream form, String modelId, long length, FormContentType formContentType) { + return beginRecognizeCustomForms(form, modelId, length, formContentType, false, null); } /** - * Recognizes and extracts form data from documents using optical character recognition (OCR) and a custom trained + * Recognizes form data from documents using optical character recognition (OCR) and a custom trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -123,28 +135,31 @@ public final class FormRecognizerClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeCustomForms#InputStream-string-long-FormContentType-boolean-Duration} * - * @param data The data of the document to be extract receipt information from. + * @param form The data of the form to recognize form information from. * @param modelId The UUID string format custom trained model Id to be used. - * @param length The exact length of the data. Size of the file must be less than 20 MB. + * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * @param includeTextDetails Include text lines and element references in the result. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link SyncPoller} that polls the extract custom form operation until it has completed, + * @return A {@link SyncPoller} that polls the recognize custom form operation until it has completed, * has failed, or has been cancelled. The completed operation returns a List of {@link RecognizedForm}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code form}, {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeCustomForms(InputStream data, String modelId, long length, FormContentType formContentType, + beginRecognizeCustomForms(InputStream form, String modelId, long length, FormContentType formContentType, boolean includeTextDetails, Duration pollInterval) { - Flux buffer = Utility.toFluxByteBuffer(data); + Flux buffer = Utility.toFluxByteBuffer(form); return client.beginRecognizeCustomForms(buffer, modelId, length, formContentType, includeTextDetails, pollInterval).getSyncPoller(); } /** - * Recognizes and extracts layout data from documents using optical character recognition (OCR) and a custom trained + * Recognizes layout data from documents using optical character recognition (OCR) and a custom trained * model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -152,60 +167,69 @@ public final class FormRecognizerClient { *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeContentFromUrl#string} * - * @param fileSourceUrl The source URL to the input document. Size of the file must be less than 20 MB. + * @param formUrl The source URL to the input form. * - * @return A {@link SyncPoller} that polls the extract layout form operation until it has completed, has failed, + * @return A {@link SyncPoller} that polls the recognize layout form operation until it has completed, has failed, * or has been cancelled. The completed operation returns a List of {@link FormPage}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code formUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) - public SyncPoller> beginRecognizeContentFromUrl(String fileSourceUrl) { - return beginRecognizeContentFromUrl(fileSourceUrl, null); + public SyncPoller> beginRecognizeContentFromUrl(String formUrl) { + return beginRecognizeContentFromUrl(formUrl, null); } /** - * Recognizes and extracts layout data using optical character recognition (OCR) and a custom trained model. + * Recognizes layout data using optical character recognition (OCR) and a custom trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

* *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeContentFromUrl#string-Duration} * - * @param sourceUrl The source URL to the input document. Size of the file must be less than 20 MB. + * @param formUrl The source URL to the input form. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link SyncPoller} that polls the extract layout operation until it has completed, has + * @return A {@link SyncPoller} that polls the recognize layout operation until it has completed, has * failed, or has been cancelled. The completed operation returns a List of {@link FormPage}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code formUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeContentFromUrl(String sourceUrl, Duration pollInterval) { - return client.beginRecognizeContentFromUrl(sourceUrl, pollInterval).getSyncPoller(); + beginRecognizeContentFromUrl(String formUrl, Duration pollInterval) { + return client.beginRecognizeContentFromUrl(formUrl, pollInterval).getSyncPoller(); } /** - * Recognizes and extracts layout data using optical character recognition (OCR) and a custom trained model. + * Recognizes layout data using optical character recognition (OCR) and a custom trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

* *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeContent#InputStream-long-FormContentType} * - * @param data The data of the document to be extract receipt information from. - * @param length The exact length of the data. Size of the file must be less than 20 MB. + * @param form The data of the form to recognize content information from. + * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * - * @return A {@link SyncPoller} that polls the extract layout operation until it has completed, has failed, or has + * @return A {@link SyncPoller} that polls the recognize layout operation until it has completed, has failed, or has * been cancelled. The completed operation returns a List of {@link FormPage}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code form} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeContent(InputStream data, long length, FormContentType formContentType) { - return beginRecognizeContent(data, length, formContentType, null); + beginRecognizeContent(InputStream form, long length, FormContentType formContentType) { + return beginRecognizeContent(form, length, formContentType, null); } /** - * Recognizes and extracts layout data from the provided document data using optical character recognition (OCR) + * Recognizes layout data from the provided document data using optical character recognition (OCR) * and a prebuilt trained receipt model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support

@@ -213,25 +237,28 @@ public SyncPoller> beginRecognizeContentFromUrl( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeContent#InputStream-long-FormContentType-Duration} * - * @param data The data of the document to be extract receipt information from. - * @param length The exact length of the data. Size of the file must be less than 20 MB. + * @param form The data of the form to recognize content information from. + * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link SyncPoller} that polls the extract layout operation until it has completed, + * @return A {@link SyncPoller} that polls the recognize layout operation until it has completed, * has failed, or has been cancelled. The completed operation returns a List of {@link FormPage}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code form} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeContent(InputStream data, long length, FormContentType formContentType, Duration pollInterval) { - Flux buffer = Utility.toFluxByteBuffer(data); + beginRecognizeContent(InputStream form, long length, FormContentType formContentType, Duration pollInterval) { + Flux buffer = Utility.toFluxByteBuffer(form); return client.beginRecognizeContent(buffer, length, formContentType, pollInterval) .getSyncPoller(); } /** - * Recognizes and extracts receipt data from document susing optical character recognition (OCR) and a + * Recognizes receipt data from document using optical character recognition (OCR) and a * prebuilt receipt trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support

@@ -239,19 +266,22 @@ public SyncPoller> beginRecognizeContentFromUrl( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeReceiptsFromUrl#string} * - * @param sourceUrl The source URL to the input document. Size of the file must be less than 20 MB. + * @param receiptUrl The source URL to the input receipt. * - * @return A {@link SyncPoller} to poll the progress of the extract receipt operation until it has completed, + * @return A {@link SyncPoller} to poll the progress of the recognize receipt operation until it has completed, * has failed, or has been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code receiptUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeReceiptsFromUrl(String sourceUrl) { - return beginRecognizeReceiptsFromUrl(sourceUrl, false, null); + beginRecognizeReceiptsFromUrl(String receiptUrl) { + return beginRecognizeReceiptsFromUrl(receiptUrl, false, null); } /** - * Recognizes and extracts receipt data from documents using optical character recognition (OCR) and a + * Recognizes receipt data from documents using optical character recognition (OCR) and a * prebuilt receipt trained model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support

@@ -259,22 +289,25 @@ public SyncPoller> beginRecognizeContentFromUrl( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeReceiptsFromUrl#string-boolean-Duration} * - * @param sourceUrl The source URL to the input document. Size of the file must be less than 20 MB. + * @param receiptUrl The source URL to the input receipt. * @param includeTextDetails Include text lines and element references in the result. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link SyncPoller} to poll the progress of the extract receipt operation until it has completed, + * @return A {@link SyncPoller} to poll the progress of the recognize receipt operation until it has completed, * has failed, or has been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code receiptUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeReceiptsFromUrl(String sourceUrl, boolean includeTextDetails, Duration pollInterval) { - return client.beginRecognizeReceiptsFromUrl(sourceUrl, includeTextDetails, pollInterval).getSyncPoller(); + beginRecognizeReceiptsFromUrl(String receiptUrl, boolean includeTextDetails, Duration pollInterval) { + return client.beginRecognizeReceiptsFromUrl(receiptUrl, includeTextDetails, pollInterval).getSyncPoller(); } /** - * Recognizes and extracts data from the provided document data using optical character recognition (OCR) + * Recognizes data from the provided document data using optical character recognition (OCR) * and a prebuilt trained receipt model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support

@@ -282,21 +315,24 @@ public SyncPoller> beginRecognizeContentFromUrl( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeReceipts#InputStream-long-FormContentType} * - * @param data The data of the document to be extract receipt information from. - * @param length The exact length of the data. Size of the file must be less than 20 MB. + * @param receipt The data of the receipt to recognize receipt information from. + * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * - * @return A {@link SyncPoller} that polls the extract receipt operation until it has completed, + * @return A {@link SyncPoller} that polls the recognize receipt operation until it has completed, * has failed, or has been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code receipt} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeReceipts(InputStream data, long length, FormContentType formContentType) { - return beginRecognizeReceipts(data, length, formContentType, false, null); + beginRecognizeReceipts(InputStream receipt, long length, FormContentType formContentType) { + return beginRecognizeReceipts(receipt, length, formContentType, false, null); } /** - * Recognizes and extracts data from the providedd document data using optical character recognition (OCR) + * Recognizes data from the providedd document data using optical character recognition (OCR) * and a prebuilt trained receipt model. *

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support

@@ -304,21 +340,24 @@ public SyncPoller> beginRecognizeContentFromUrl( *

Code sample

* {@codesnippet com.azure.ai.formrecognizer.FormRecognizerClient.beginRecognizeReceipts#InputStream-long-FormContentType-boolean-Duration} * - * @param data The data of the document to be extract receipt information from. - * @param length The exact length of the data. Size of the file must be less than 20 MB. + * @param receipt The data of the receipt to recognize receipt information from. + * @param length The exact length of the data. Size of the file must be less than 50 MB. * @param formContentType Supported Media types including .pdf, .jpg, .png or .tiff type file stream. * @param includeTextDetails Include text lines and element references in the result. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * - * @return A {@link SyncPoller} that polls the extract receipt operation until it has completed, has failed, + * @return A {@link SyncPoller} that polls the recognize receipt operation until it has completed, has failed, * or has been cancelled. The completed operation returns a List of {@link RecognizedReceipt}. + * @throws HttpResponseException If recognize operation fails and the {@link AnalyzeOperationResult} returned with + * an {@link OperationStatus#FAILED}. + * @throws NullPointerException If {@code receipt} is {@code null}. */ @ServiceMethod(returns = ReturnType.COLLECTION) public SyncPoller> - beginRecognizeReceipts(InputStream data, long length, FormContentType formContentType, + beginRecognizeReceipts(InputStream receipt, long length, FormContentType formContentType, boolean includeTextDetails, Duration pollInterval) { - Flux buffer = Utility.toFluxByteBuffer(data); + Flux buffer = Utility.toFluxByteBuffer(receipt); return client.beginRecognizeReceipts(buffer, length, formContentType, includeTextDetails, pollInterval) .getSyncPoller(); } diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingAsyncClient.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingAsyncClient.java index a34b0cb65510..5c7099365be1 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingAsyncClient.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingAsyncClient.java @@ -12,6 +12,8 @@ import com.azure.ai.formrecognizer.implementation.models.CopyRequest; import com.azure.ai.formrecognizer.implementation.models.Model; import com.azure.ai.formrecognizer.implementation.models.OperationStatus; +import com.azure.ai.formrecognizer.implementation.models.ModelInfo; +import com.azure.ai.formrecognizer.implementation.models.ModelStatus; import com.azure.ai.formrecognizer.implementation.models.TrainRequest; import com.azure.ai.formrecognizer.implementation.models.TrainSourceFilter; import com.azure.ai.formrecognizer.models.AccountProperties; @@ -127,10 +129,12 @@ String getEndpoint() { * * @param trainingFilesUrl source URL parameter that is either an externally accessible Azure * storage blob container Uri (preferably a Shared Access Signature Uri). - * @param useTrainingLabels Boolean to specify the use of labeled files for training the model. + * @param useTrainingLabels boolean to specify the use of labeled files for training the model. * * @return A {@link PollerFlux} that polls the training model operation until it has completed, has failed, or has - * been cancelled. + * been cancelled. The completed operation returns a {@link CustomFormModel}. + * @throws HttpResponseException If training fails and model with {@link ModelStatus#INVALID} is created. + * @throws NullPointerException If {@code trainingFilesUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public PollerFlux beginTraining(String trainingFilesUrl, @@ -141,8 +145,7 @@ public PollerFlux beginTraining(String trainin /** * Create and train a custom model. *

Models are trained using documents that are of the following content type - - * 'application/pdf', 'image/jpeg', 'image/png', 'image/tiff'. - * Other type of content is ignored. + * 'application/pdf', 'image/jpeg', 'image/png', 'image/tiff'.Other type of content is ignored. *

*

The service does not support cancellation of the long running operation and returns with an * error message indicating absence of cancellation support.

@@ -152,13 +155,15 @@ public PollerFlux beginTraining(String trainin * * @param trainingFilesUrl an externally accessible Azure storage blob container Uri (preferably a * Shared Access Signature Uri). - * @param useTrainingLabels Boolean to specify the use of labeled files for training the model. + * @param useTrainingLabels boolean to specify the use of labeled files for training the model. * @param trainingFileFilter Filter to apply to the documents in the source path for training. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * * @return A {@link PollerFlux} that polls the extract receipt operation until it - * has completed, has failed, or has been cancelled. + * has completed, has failed, or has been cancelled. The completed operation returns a {@link CustomFormModel}. + * @throws HttpResponseException If training fails and model with {@link ModelStatus#INVALID} is created. + * @throws NullPointerException If {@code trainingFilesUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public PollerFlux beginTraining(String trainingFilesUrl, @@ -184,6 +189,7 @@ public PollerFlux beginTraining(String trainin * @param modelId The UUID string format model identifier. * * @return The detailed information for the specified model. + * @throws NullPointerException If {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono getCustomModel(String modelId) { @@ -199,6 +205,7 @@ public Mono getCustomModel(String modelId) { * @param modelId The UUID string format model identifier. * * @return A {@link Response} containing the requested {@link CustomFormModel model}. + * @throws NullPointerException If {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> getCustomModelWithResponse(String modelId) { @@ -261,6 +268,7 @@ Mono> getAccountPropertiesWithResponse(Context conte * @param modelId The UUID string format model identifier. * * @return An empty Mono. + * @throws NullPointerException If {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteModel(String modelId) { @@ -276,6 +284,7 @@ public Mono deleteModel(String modelId) { * @param modelId The UUID string format model identifier. * * @return A {@link Mono} containing containing status code and HTTP headers + * @throws NullPointerException If {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> deleteModelWithResponse(String modelId) { @@ -559,7 +568,10 @@ private Function, Mono> fetchTr try { final UUID modelUid = UUID.fromString(pollingContext.getLatestResponse().getValue().getResultId()); return service.getCustomModelWithResponseAsync(modelUid, true) - .map(modelSimpleResponse -> toCustomFormModel(modelSimpleResponse.getValue())); + .map(modelSimpleResponse -> { + throwIfModelStatusInvalid(modelSimpleResponse.getValue()); + return toCustomFormModel(modelSimpleResponse.getValue()); + }); } catch (RuntimeException ex) { return monoError(logger, ex); } @@ -583,13 +595,13 @@ private Function, Mono> fetchTr } private Function, Mono> getTrainingActivationOperation( - String fileSourceUrl, boolean includeSubFolders, String filePrefix, boolean useTrainingLabels) { + String trainingFilesUrl, boolean includeSubFolders, String filePrefix, boolean useTrainingLabels) { return (pollingContext) -> { try { - Objects.requireNonNull(fileSourceUrl, "'fileSourceUrl' cannot be null."); + Objects.requireNonNull(trainingFilesUrl, "'trainingFilesUrl' cannot be null."); TrainSourceFilter trainSourceFilter = new TrainSourceFilter().setIncludeSubFolders(includeSubFolders) .setPrefix(filePrefix); - TrainRequest serviceTrainRequest = new TrainRequest().setSource(fileSourceUrl). + TrainRequest serviceTrainRequest = new TrainRequest().setSource(trainingFilesUrl). setSourceFilter(trainSourceFilter).setUseLabelFile(useTrainingLabels); return service.trainCustomModelAsyncWithResponseAsync(serviceTrainRequest) .map(response -> @@ -638,4 +650,20 @@ private void throwIfCopyOperationStatusInvalid(CopyOperationResult copyResult) { } } + /** + * Helper method that throws a {@link HttpResponseException} if {@link ModelInfo#getStatus()} is + * {@link com.azure.ai.formrecognizer.implementation.models.ModelStatus#INVALID}. + * + * @param customModel The response returned from the service. + */ + private void throwIfModelStatusInvalid(Model customModel) { + if (ModelStatus.INVALID.equals(customModel.getModelInfo().getStatus())) { + List errorInformationList = customModel.getTrainResult().getErrors(); + if (!CoreUtils.isNullOrEmpty(errorInformationList)) { + throw logger.logExceptionAsError(new HttpResponseException( + String.format("Invalid model created with ID: %s", customModel.getModelInfo().getModelId()), + null, errorInformationList)); + } + } + } } diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClient.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClient.java index 0c1bf93f2156..321caea7b987 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClient.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClient.java @@ -5,6 +5,7 @@ import com.azure.ai.formrecognizer.FormRecognizerClient; import com.azure.ai.formrecognizer.FormRecognizerClientBuilder; +import com.azure.ai.formrecognizer.implementation.models.ModelStatus; import com.azure.ai.formrecognizer.models.AccountProperties; import com.azure.ai.formrecognizer.models.CopyAuthorization; import com.azure.ai.formrecognizer.models.CustomFormModel; @@ -14,6 +15,7 @@ import com.azure.core.annotation.ReturnType; import com.azure.core.annotation.ServiceClient; import com.azure.core.annotation.ServiceMethod; +import com.azure.core.exception.HttpResponseException; import com.azure.core.http.rest.PagedIterable; import com.azure.core.http.rest.Response; import com.azure.core.util.Context; @@ -73,10 +75,12 @@ public FormRecognizerClient getFormRecognizerClient() { * * @param trainingFilesUrl an externally accessible Azure storage blob container Uri (preferably a Shared Access * Signature Uri). - * @param useTrainingLabels Boolean to specify the use of labeled files for training the model. + * @param useTrainingLabels boolean to specify the use of labeled files for training the model. * * @return A {@link SyncPoller} that polls the training model operation until it has completed, has failed, or has * been cancelled. The completed operation returns a {@link CustomFormModel}. + * @throws HttpResponseException If training fails and model with {@link ModelStatus#INVALID} is created. + * @throws NullPointerException If {@code trainingFilesUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public SyncPoller beginTraining(String trainingFilesUrl, @@ -97,13 +101,15 @@ public SyncPoller beginTraining(String trainin * * @param trainingFilesUrl an externally accessible Azure storage blob container Uri (preferably a * Shared Access Signature Uri). - * @param useTrainingLabels Boolean to specify the use of labeled files for training the model. + * @param useTrainingLabels boolean to specify the use of labeled files for training the model. * @param trainingFileFilter Filter to apply to the documents in the source path for training. * @param pollInterval Duration between each poll for the operation status. If none is specified, a default of * 5 seconds is used. * * @return A {@link SyncPoller} that polls the extract receipt operation until it has completed, has failed, * or has been cancelled. The completed operation returns a {@link CustomFormModel}. + * @throws HttpResponseException If training fails and model with {@link ModelStatus#INVALID} is created. + * @throws NullPointerException If {@code trainingFilesUrl} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public SyncPoller beginTraining(String trainingFilesUrl, @@ -121,6 +127,7 @@ public SyncPoller beginTraining(String trainin * @param modelId The UUID string format model identifier. * * @return The detailed information for the specified model. + * @throws NullPointerException If {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public CustomFormModel getCustomModel(String modelId) { @@ -137,6 +144,7 @@ public CustomFormModel getCustomModel(String modelId) { * @param context Additional context that is passed through the Http pipeline during the service call. * * @return The detailed information for the specified model. + * @throws NullPointerException If {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public Response getCustomModelWithResponse(String modelId, Context context) { @@ -178,6 +186,7 @@ public Response getAccountPropertiesWithResponse(Context cont * {@codesnippet com.azure.ai.formrecognizer.training.FormTrainingClient.deleteModel#string} * * @param modelId The UUID string format model identifier. + * @throws NullPointerException If {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public void deleteModel(String modelId) { @@ -194,6 +203,7 @@ public void deleteModel(String modelId) { * @param context Additional context that is passed through the Http pipeline during the service call. * * @return A {@link Response} containing containing status code and HTTP headers + * @throws NullPointerException If {@code modelId} is {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public Response deleteModelWithResponse(String modelId, Context context) { diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java index 3a937108c677..981025cb4566 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java @@ -4,6 +4,7 @@ package com.azure.ai.formrecognizer; import com.azure.ai.formrecognizer.models.CustomFormModel; +import com.azure.ai.formrecognizer.models.ErrorInformation; import com.azure.ai.formrecognizer.models.ErrorResponseException; import com.azure.ai.formrecognizer.models.FormContentType; import com.azure.ai.formrecognizer.models.FormPage; @@ -13,6 +14,7 @@ import com.azure.ai.formrecognizer.training.FormTrainingAsyncClient; import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.exception.HttpResponseException; import com.azure.core.http.HttpClient; import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpLogOptions; @@ -44,7 +46,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; public class FormRecognizerAsyncClientTest extends FormRecognizerClientTestBase { - private FormRecognizerAsyncClient client; @BeforeAll @@ -457,4 +458,22 @@ public void recognizeContentFromDataMultiPage(HttpClient httpClient, FormRecogni }); } + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.formrecognizer.TestUtils#getTestParameters") + void recognizeCustomFormInvalidStatus(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { + client = getFormRecognizerAsyncClient(httpClient, serviceVersion); + invalidSourceUrlRunner((invalidSourceUrl) -> beginTrainingLabeledRunner((training, useTrainingLabels) -> { + SyncPoller syncPoller = + getFormTrainingAsyncClient(httpClient, serviceVersion).beginTraining(training, useTrainingLabels).getSyncPoller(); + syncPoller.waitForCompletion(); + CustomFormModel createdModel = syncPoller.getFinalResult(); + HttpResponseException httpResponseException = assertThrows(HttpResponseException.class, + () -> client.beginRecognizeCustomFormsFromUrl(invalidSourceUrl, createdModel.getModelId()).getSyncPoller().getFinalResult()); + ErrorInformation errorInformation = (ErrorInformation) ((List) httpResponseException.getValue()).get(0); + assertEquals("Analyze operation failed.", httpResponseException.getMessage()); + assertEquals(EXPECTED_INVALID_URL_ERROR_CODE, errorInformation.getCode()); + assertEquals(OCR_EXTRACTION_INVALID_URL_ERROR, errorInformation.getMessage()); + })); + } + } diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java index f26a702a5ba1..7d06965a0703 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java @@ -4,6 +4,7 @@ package com.azure.ai.formrecognizer; import com.azure.ai.formrecognizer.models.CustomFormModel; +import com.azure.ai.formrecognizer.models.ErrorInformation; import com.azure.ai.formrecognizer.models.ErrorResponseException; import com.azure.ai.formrecognizer.models.FormContentType; import com.azure.ai.formrecognizer.models.FormPage; @@ -13,6 +14,7 @@ import com.azure.ai.formrecognizer.training.FormTrainingClient; import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.exception.HttpResponseException; import com.azure.core.http.HttpClient; import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpLogOptions; @@ -350,6 +352,7 @@ public void recognizeContentFromDataMultiPage(HttpClient httpClient, FormRecogni validateContentResultData(syncPoller.getFinalResult(), false); }); } + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) @MethodSource("com.azure.ai.formrecognizer.TestUtils#getTestParameters") void recognizeCustomFormUrlMultiPageLabeled(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { @@ -419,4 +422,23 @@ public void recognizeContentFromUrlMultiPage(HttpClient httpClient, FormRecogniz validateContentResultData(syncPoller.getFinalResult(), false); }); } + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.formrecognizer.TestUtils#getTestParameters") + void recognizeCustomFormInvalidStatus(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { + client = getFormRecognizerClient(httpClient, serviceVersion); + invalidSourceUrlRunner((invalidSourceUrl) -> { + beginTrainingLabeledRunner((training, useTrainingLabels) -> { + SyncPoller syncPoller = + getFormTrainingClient(httpClient, serviceVersion).beginTraining(training, useTrainingLabels); + syncPoller.waitForCompletion(); + CustomFormModel createdModel = syncPoller.getFinalResult(); + HttpResponseException httpResponseException = assertThrows(HttpResponseException.class, + () -> client.beginRecognizeCustomFormsFromUrl(invalidSourceUrl, createdModel.getModelId()).getFinalResult()); + ErrorInformation errorInformation = (ErrorInformation) ((List) httpResponseException.getValue()).get(0); + assertEquals(EXPECTED_INVALID_URL_ERROR_CODE, errorInformation.getCode()); + assertEquals(OCR_EXTRACTION_INVALID_URL_ERROR, errorInformation.getMessage()); + }); + }); + } } diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java index 5cc89f106fd7..cc2741ff9013 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java @@ -68,6 +68,8 @@ public abstract class FormRecognizerClientTestBase extends TestBase { private static final String EXPECTED_MULTIPAGE_ADDRESS_VALUE = "123 Hobbit Lane 567 Main St. Redmond, WA Redmond, WA"; private static final String EXPECTED_MULTIPAGE_PHONE_NUMBER_VALUE = "+15555555555"; private static final String ITEMIZED_RECEIPT_VALUE = "Itemized"; + static final String OCR_EXTRACTION_INVALID_URL_ERROR = "OCR extraction error: [Wrong response code: InvalidImageURL. Message: Image URL is badly formatted..]"; + static final String EXPECTED_INVALID_URL_ERROR_CODE = "3003"; private static void validateReferenceElementsData(List expectedElements, List actualFormContentList, List readResults) { @@ -312,6 +314,9 @@ abstract void recognizeCustomFormMultiPageUnlabeled(HttpClient httpClient, @Test abstract void recognizeContentFromDataMultiPage(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion); + @Test + abstract void recognizeCustomFormInvalidStatus(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion); + void validateUSReceiptData(USReceipt actualRecognizedReceipt, boolean includeTextDetails) { final AnalyzeResult analyzeResult = getAnalyzeRawResponse().getAnalyzeResult(); List readResults = analyzeResult.getReadResults(); diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java index 802ac017b29c..1ecbcc6c9748 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java @@ -4,10 +4,12 @@ package com.azure.ai.formrecognizer; import com.azure.ai.formrecognizer.models.CustomFormModel; +import com.azure.ai.formrecognizer.models.ErrorInformation; import com.azure.ai.formrecognizer.models.OperationResult; import com.azure.ai.formrecognizer.training.FormTrainingAsyncClient; import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.exception.HttpResponseException; import com.azure.core.http.HttpClient; import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpLogOptions; @@ -21,6 +23,7 @@ import reactor.test.StepVerifier; import java.time.Duration; +import java.util.List; import static com.azure.ai.formrecognizer.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; import static com.azure.ai.formrecognizer.TestUtils.INVALID_KEY; @@ -351,4 +354,21 @@ public void beginTrainingUnlabeledResult(HttpClient httpClient, FormRecognizerSe // .verifyComplete() // ); // } + + /** + * Verifies the training operation throws HttpResponseException when an invalid status model is returned. + */ + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.formrecognizer.TestUtils#getTestParameters") + void beginTrainingInvalidModelStatus(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { + client = getFormTrainingAsyncClient(httpClient, serviceVersion); + beginTrainingInvalidModelStatusRunner((invalidTrainingFilesUrl, useTrainingLabels) -> { + HttpResponseException httpResponseException = assertThrows(HttpResponseException.class, + () -> client.beginTraining(invalidTrainingFilesUrl, useTrainingLabels).getSyncPoller().getFinalResult()); + ErrorInformation errorInformation = (ErrorInformation) ((List) httpResponseException.getValue()).get(0); + assertEquals(EXPECTED_INVALID_MODEL_STATUS_MESSAGE, httpResponseException.getMessage()); + assertEquals(EXPECTED_INVALID_MODEL_STATUS_ERROR_CODE, errorInformation.getCode()); + assertEquals(EXPECTED_INVALID_STATUS_ERROR_INFORMATION, errorInformation.getMessage()); + }); + } } diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java index 7dcb1cbd46d4..54e760b093ed 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java @@ -6,11 +6,13 @@ import com.azure.ai.formrecognizer.models.AccountProperties; import com.azure.ai.formrecognizer.models.CustomFormModel; import com.azure.ai.formrecognizer.models.CustomFormModelInfo; +import com.azure.ai.formrecognizer.models.ErrorInformation; import com.azure.ai.formrecognizer.models.ErrorResponseException; import com.azure.ai.formrecognizer.models.OperationResult; import com.azure.ai.formrecognizer.training.FormTrainingClient; import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.exception.HttpResponseException; import com.azure.core.http.HttpClient; import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpLogOptions; @@ -22,6 +24,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import java.util.List; + import static com.azure.ai.formrecognizer.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; import static com.azure.ai.formrecognizer.TestUtils.INVALID_KEY; import static com.azure.ai.formrecognizer.TestUtils.INVALID_MODEL_ID; @@ -33,7 +37,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class FormTrainingClientTest extends FormTrainingClientTestBase { - private FormTrainingClient client; private FormTrainingClient getFormTrainingClient(HttpClient httpClient, @@ -208,7 +211,7 @@ public void beginTrainingNullInput(HttpClient httpClient, FormRecognizerServiceV client = getFormTrainingClient(httpClient, serviceVersion); Exception exception = assertThrows(NullPointerException.class, () -> client.beginTraining(null, false)); - assertTrue(exception.getMessage().equals(NULL_SOURCE_URL_ERROR)); + assertEquals(exception.getMessage(), NULL_SOURCE_URL_ERROR); } /** @@ -302,4 +305,21 @@ public void beginTrainingUnlabeledResult(HttpClient httpClient, FormRecognizerSe // beginCopyRunner((resourceId, resourceRegion) -> validateCopyAuthorizationResult(resourceId, resourceRegion, // client.getCopyAuthorization(resourceId, resourceRegion))); // } + + /** + * Verifies the training operation throws HttpResponseException when an invalid status model is returned. + */ + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.formrecognizer.TestUtils#getTestParameters") + void beginTrainingInvalidModelStatus(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { + client = getFormTrainingClient(httpClient, serviceVersion); + beginTrainingInvalidModelStatusRunner((invalidTrainingFilesUrl, useTrainingLabels) -> { + HttpResponseException httpResponseException = assertThrows(HttpResponseException.class, + () -> client.beginTraining(invalidTrainingFilesUrl, useTrainingLabels).getFinalResult()); + ErrorInformation errorInformation = (ErrorInformation) ((List) httpResponseException.getValue()).get(0); + assertEquals(EXPECTED_INVALID_MODEL_STATUS_MESSAGE, httpResponseException.getMessage()); + assertEquals(EXPECTED_INVALID_MODEL_STATUS_ERROR_CODE, errorInformation.getCode()); + assertEquals(EXPECTED_INVALID_STATUS_ERROR_INFORMATION, errorInformation.getMessage()); + }); + } } diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java index 1ddc32492443..31f7d9263958 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java @@ -27,6 +27,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +import static com.azure.ai.formrecognizer.TestUtils.INVALID_RECEIPT_URL; import static com.azure.ai.formrecognizer.TestUtils.getSerializerAdapter; import static com.azure.ai.formrecognizer.implementation.models.ModelStatus.READY; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -40,6 +41,10 @@ public abstract class FormTrainingClientTestBase extends TestBase { "FORM_RECOGNIZER_TESTING_BLOB_CONTAINER_SAS_URL"; static final String AZURE_FORM_RECOGNIZER_API_KEY = "AZURE_FORM_RECOGNIZER_API_KEY"; static final String AZURE_FORM_RECOGNIZER_ENDPOINT = "AZURE_FORM_RECOGNIZER_ENDPOINT"; + static final String EXPECTED_INVALID_MODEL_STATUS_MESSAGE = "Invalid model created with ID: cae9d062-71e0-44a3-8630-70b32ae94f4d"; + static final String EXPECTED_INVALID_MODEL_STATUS_ERROR_CODE = "2012"; + static final String EXPECTED_INVALID_STATUS_ERROR_INFORMATION = "Unable to list blobs on the Azure blob storage account."; + private static final String RESOURCE_ID = "FORM_RECOGNIZER_TARGET_RESOURCE_ID"; private static final String RESOURCE_REGION = "FORM_RECOGNIZER_TARGET_RESOURCE_REGION"; @@ -196,6 +201,9 @@ private Model getRawModelResponse() { // @Test // abstract void copyAuthorization(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion); + @Test + abstract void beginTrainingInvalidModelStatus(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion); + void getCustomModelInvalidModelIdRunner(Consumer testRunner) { testRunner.accept(TestUtils.INVALID_MODEL_ID); } @@ -220,6 +228,10 @@ void beginCopyIncorrectRegionRunner(BiConsumer testRunner) { testRunner.accept(getTargetResourceId(), "westus2"); } + void beginTrainingInvalidModelStatusRunner(BiConsumer testRunner) { + testRunner.accept(INVALID_RECEIPT_URL, false); + } + /** * Get the string of API key value based on what running mode is on. * diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/TestUtils.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/TestUtils.java index 22e1191f71fc..0246d34ea30b 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/TestUtils.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/TestUtils.java @@ -43,7 +43,7 @@ final class TestUtils { static final String INVALID_SOURCE_URL_ERROR = "Status code 400, \"{\"error\":{\"code\":\"1003\"," + "\"message\":\"Parameter 'Source' is not a valid Uri.\"}}\""; static final String INVALID_MODEL_ID_ERROR = "Invalid UUID string: " + INVALID_MODEL_ID; - static final String NULL_SOURCE_URL_ERROR = "'fileSourceUrl' cannot be null."; + static final String NULL_SOURCE_URL_ERROR = "'trainingFilesUrl' cannot be null."; static final String INVALID_URL = "htttttttps://localhost:8080"; static final String VALID_HTTPS_LOCALHOST = "https://localhost:8080"; static final String RECEIPT_LOCAL_URL = "src/test/resources/sample_files/Test/contoso-allinone.jpg"; diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/beginTrainingInvalidModelStatus.json b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/beginTrainingInvalidModelStatus.json new file mode 100644 index 000000000000..a68a6498b1af --- /dev/null +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/beginTrainingInvalidModelStatus.json @@ -0,0 +1,64 @@ +{ + "networkCallRecords" : [ { + "Method" : "POST", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "bde9d573-7c29-4094-a69e-70c837aefc4d", + "Content-Type" : "application/json" + }, + "Response" : { + "x-envoy-upstream-service-time" : "226", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "1f0d14b9-a5b8-4bf3-9c0f-34a19fccb8a7", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "Date" : "Tue, 02 Jun 2020 08:03:16 GMT", + "Location" : "https://savaity-formrecognizer.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/cae9d062-71e0-44a3-8630-70b32ae94f4d" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models/cae9d062-71e0-44a3-8630-70b32ae94f4d?includeKeys=true", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "8610f4d8-c7c3-4fcb-9231-11415944d9e2" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-envoy-upstream-service-time" : "57", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "8c017874-7d7f-4231-8971-e7357ce70a74", + "retry-after" : "0", + "StatusCode" : "200", + "Body" : "{\"modelInfo\":{\"modelId\":\"cae9d062-71e0-44a3-8630-70b32ae94f4d\",\"status\":\"invalid\",\"createdDateTime\":\"2020-06-02T08:03:16Z\",\"lastUpdatedDateTime\":\"2020-06-02T08:03:17Z\"},\"keys\":{\"clusters\":{}},\"trainResult\":{\"trainingDocuments\":[],\"errors\":[{\"code\":\"2012\",\"message\":\"Unable to list blobs on the Azure blob storage account.\"}]}}", + "Date" : "Tue, 02 Jun 2020 08:03:21 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models/cae9d062-71e0-44a3-8630-70b32ae94f4d?includeKeys=true", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "57382837-8174-45d1-a1c7-7dea3615b0ab" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-envoy-upstream-service-time" : "5147", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "407c4eaa-01fa-4fdc-9000-19a1f709692f", + "retry-after" : "0", + "StatusCode" : "200", + "Body" : "{\"modelInfo\":{\"modelId\":\"cae9d062-71e0-44a3-8630-70b32ae94f4d\",\"status\":\"invalid\",\"createdDateTime\":\"2020-06-02T08:03:16Z\",\"lastUpdatedDateTime\":\"2020-06-02T08:03:17Z\"},\"keys\":{\"clusters\":{}},\"trainResult\":{\"trainingDocuments\":[],\"errors\":[{\"code\":\"2012\",\"message\":\"Unable to list blobs on the Azure blob storage account.\"}]}}", + "Date" : "Tue, 02 Jun 2020 08:03:27 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + } ], + "variables" : [ ] +} \ No newline at end of file diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/recognizeCustomFormInvalidStatus.json b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/recognizeCustomFormInvalidStatus.json new file mode 100644 index 000000000000..68c6860a4fc9 --- /dev/null +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/recognizeCustomFormInvalidStatus.json @@ -0,0 +1,164 @@ +{ + "networkCallRecords" : [ { + "Method" : "POST", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "55c245a0-6c1a-4d2a-9c44-21f1ce359c03", + "Content-Type" : "application/json" + }, + "Response" : { + "x-envoy-upstream-service-time" : "160", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "caa6f06a-5aef-4a9f-9d95-de22fd026193", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "Date" : "Tue, 02 Jun 2020 06:38:38 GMT", + "Location" : "https://savaity-formrecognizer.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/02d177f8-b86e-43be-92ea-3b586b0b0766" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models/02d177f8-b86e-43be-92ea-3b586b0b0766?includeKeys=true", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "22f92f41-b3a5-4302-bfd4-edf76ba9c80e" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-envoy-upstream-service-time" : "102", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "d00fa26d-d7a4-4b05-ac59-64f58468a8ec", + "retry-after" : "0", + "StatusCode" : "200", + "Body" : "{\"modelInfo\":{\"modelId\":\"02d177f8-b86e-43be-92ea-3b586b0b0766\",\"status\":\"creating\",\"createdDateTime\":\"2020-06-02T06:38:38Z\",\"lastUpdatedDateTime\":\"2020-06-02T06:38:38Z\"}}", + "Date" : "Tue, 02 Jun 2020 06:38:43 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models/02d177f8-b86e-43be-92ea-3b586b0b0766?includeKeys=true", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "a09ef757-69d6-41dc-a96b-68ee18251b0d" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-envoy-upstream-service-time" : "57", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "9c8ab16f-f885-4ffd-8eb7-bb112e5848b0", + "retry-after" : "0", + "StatusCode" : "200", + "Body" : "{\"modelInfo\":{\"modelId\":\"02d177f8-b86e-43be-92ea-3b586b0b0766\",\"status\":\"creating\",\"createdDateTime\":\"2020-06-02T06:38:38Z\",\"lastUpdatedDateTime\":\"2020-06-02T06:38:38Z\"}}", + "Date" : "Tue, 02 Jun 2020 06:38:48 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models/02d177f8-b86e-43be-92ea-3b586b0b0766?includeKeys=true", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "4b8746c6-72bb-425b-aee9-c81031e4ede1" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-envoy-upstream-service-time" : "65", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "f86e483a-0e61-4b58-aecf-781d33ab10c8", + "retry-after" : "0", + "StatusCode" : "200", + "Body" : "{\"modelInfo\":{\"modelId\":\"02d177f8-b86e-43be-92ea-3b586b0b0766\",\"status\":\"ready\",\"createdDateTime\":\"2020-06-02T06:38:38Z\",\"lastUpdatedDateTime\":\"2020-06-02T06:38:53Z\"},\"trainResult\":{\"averageModelAccuracy\":0.973,\"trainingDocuments\":[{\"documentName\":\"Form_1.jpg\",\"pages\":1,\"status\":\"succeeded\"},{\"documentName\":\"Form_2.jpg\",\"pages\":1,\"status\":\"succeeded\"},{\"documentName\":\"Form_3.jpg\",\"pages\":1,\"status\":\"succeeded\"},{\"documentName\":\"Form_4.jpg\",\"pages\":1,\"status\":\"succeeded\"},{\"documentName\":\"Form_5.jpg\",\"pages\":1,\"status\":\"succeeded\"}],\"fields\":[{\"fieldName\":\"CompanyAddress\",\"accuracy\":0.8},{\"fieldName\":\"CompanyName\",\"accuracy\":1.0},{\"fieldName\":\"CompanyPhoneNumber\",\"accuracy\":1.0},{\"fieldName\":\"DatedAs\",\"accuracy\":1.0},{\"fieldName\":\"Email\",\"accuracy\":0.8},{\"fieldName\":\"Merchant\",\"accuracy\":1.0},{\"fieldName\":\"PhoneNumber\",\"accuracy\":1.0},{\"fieldName\":\"PurchaseOrderNumber\",\"accuracy\":1.0},{\"fieldName\":\"Quantity\",\"accuracy\":1.0},{\"fieldName\":\"Signature\",\"accuracy\":1.0},{\"fieldName\":\"Subtotal\",\"accuracy\":1.0},{\"fieldName\":\"Tax\",\"accuracy\":1.0},{\"fieldName\":\"Total\",\"accuracy\":1.0},{\"fieldName\":\"VendorName\",\"accuracy\":1.0},{\"fieldName\":\"Website\",\"accuracy\":1.0}],\"errors\":[]}}", + "Date" : "Tue, 02 Jun 2020 06:38:54 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models/02d177f8-b86e-43be-92ea-3b586b0b0766?includeKeys=true", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "19f6e0d8-6e26-48f4-9940-fd0590f338de" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-envoy-upstream-service-time" : "62", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "a5c2aad6-d2ca-415b-b331-dedc5afc0d0e", + "retry-after" : "0", + "StatusCode" : "200", + "Body" : "{\"modelInfo\":{\"modelId\":\"02d177f8-b86e-43be-92ea-3b586b0b0766\",\"status\":\"ready\",\"createdDateTime\":\"2020-06-02T06:38:38Z\",\"lastUpdatedDateTime\":\"2020-06-02T06:38:53Z\"},\"trainResult\":{\"averageModelAccuracy\":0.973,\"trainingDocuments\":[{\"documentName\":\"Form_1.jpg\",\"pages\":1,\"status\":\"succeeded\"},{\"documentName\":\"Form_2.jpg\",\"pages\":1,\"status\":\"succeeded\"},{\"documentName\":\"Form_3.jpg\",\"pages\":1,\"status\":\"succeeded\"},{\"documentName\":\"Form_4.jpg\",\"pages\":1,\"status\":\"succeeded\"},{\"documentName\":\"Form_5.jpg\",\"pages\":1,\"status\":\"succeeded\"}],\"fields\":[{\"fieldName\":\"CompanyAddress\",\"accuracy\":0.8},{\"fieldName\":\"CompanyName\",\"accuracy\":1.0},{\"fieldName\":\"CompanyPhoneNumber\",\"accuracy\":1.0},{\"fieldName\":\"DatedAs\",\"accuracy\":1.0},{\"fieldName\":\"Email\",\"accuracy\":0.8},{\"fieldName\":\"Merchant\",\"accuracy\":1.0},{\"fieldName\":\"PhoneNumber\",\"accuracy\":1.0},{\"fieldName\":\"PurchaseOrderNumber\",\"accuracy\":1.0},{\"fieldName\":\"Quantity\",\"accuracy\":1.0},{\"fieldName\":\"Signature\",\"accuracy\":1.0},{\"fieldName\":\"Subtotal\",\"accuracy\":1.0},{\"fieldName\":\"Tax\",\"accuracy\":1.0},{\"fieldName\":\"Total\",\"accuracy\":1.0},{\"fieldName\":\"VendorName\",\"accuracy\":1.0},{\"fieldName\":\"Website\",\"accuracy\":1.0}],\"errors\":[]}}", + "Date" : "Tue, 02 Jun 2020 06:38:54 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + }, { + "Method" : "POST", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models/02d177f8-b86e-43be-92ea-3b586b0b0766/analyze?includeTextDetails=false", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "e5dc66e2-c467-49a0-bf13-8cf0760952a7", + "Content-Type" : "application/json" + }, + "Response" : { + "x-envoy-upstream-service-time" : "5130", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "dcadcfad-5d32-4e66-9cc8-3aaa5dd31a60", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "Operation-Location" : "https://savaity-formrecognizer.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/02d177f8-b86e-43be-92ea-3b586b0b0766/analyzeresults/575f9b2e-d900-407b-80be-d3aff5221135", + "Date" : "Tue, 02 Jun 2020 06:38:59 GMT" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models/02d177f8-b86e-43be-92ea-3b586b0b0766/analyzeResults/575f9b2e-d900-407b-80be-d3aff5221135", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "a120725d-6112-475d-88c7-51eb83f7fd70" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-envoy-upstream-service-time" : "5069", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "fbd88634-bfec-4e67-889b-3618535db21a", + "retry-after" : "0", + "StatusCode" : "200", + "Body" : "{\"status\":\"failed\",\"createdDateTime\":\"2020-06-02T06:39:00Z\",\"lastUpdatedDateTime\":\"2020-06-02T06:39:00Z\",\"analyzeResult\":{\"version\":\"2.0.0\",\"errors\":[{\"code\":\"3003\",\"message\":\"OCR extraction error: [Wrong response code: InvalidImageURL. Message: Image URL is badly formatted..]\"}]}}", + "Date" : "Tue, 02 Jun 2020 06:39:09 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models/02d177f8-b86e-43be-92ea-3b586b0b0766/analyzeResults/575f9b2e-d900-407b-80be-d3aff5221135", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.5; Windows 10 10.0)", + "x-ms-client-request-id" : "7bab7681-e42f-4cf7-a484-cadaadee7428" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-envoy-upstream-service-time" : "5120", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "b3517441-69ab-4d3f-9dfc-eacdd2539433", + "retry-after" : "0", + "StatusCode" : "200", + "Body" : "{\"status\":\"failed\",\"createdDateTime\":\"2020-06-02T06:39:00Z\",\"lastUpdatedDateTime\":\"2020-06-02T06:39:00Z\",\"analyzeResult\":{\"version\":\"2.0.0\",\"errors\":[{\"code\":\"3003\",\"message\":\"OCR extraction error: [Wrong response code: InvalidImageURL. Message: Image URL is badly formatted..]\"}]}}", + "Date" : "Tue, 02 Jun 2020 06:39:15 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + } ], + "variables" : [ ] +} \ No newline at end of file