|
4 | 4 | package com.azure.ai.formrecognizer.documentanalysis;
|
5 | 5 |
|
6 | 6 | import com.azure.ai.formrecognizer.documentanalysis.administration.models.OperationStatus;
|
| 7 | +import com.azure.ai.formrecognizer.documentanalysis.implementation.FormRecognizerClientImpl; |
| 8 | +import com.azure.ai.formrecognizer.documentanalysis.implementation.models.AnalyzeDocumentHeaders; |
| 9 | +import com.azure.ai.formrecognizer.documentanalysis.implementation.models.AnalyzeDocumentRequest; |
| 10 | +import com.azure.ai.formrecognizer.documentanalysis.implementation.models.AnalyzeResultOperation; |
| 11 | +import com.azure.ai.formrecognizer.documentanalysis.implementation.models.ErrorResponseException; |
| 12 | +import com.azure.ai.formrecognizer.documentanalysis.implementation.models.StringIndexType; |
| 13 | +import com.azure.ai.formrecognizer.documentanalysis.implementation.util.Transforms; |
7 | 14 | import com.azure.ai.formrecognizer.documentanalysis.models.AnalyzeDocumentOptions;
|
8 | 15 | import com.azure.ai.formrecognizer.documentanalysis.models.AnalyzeResult;
|
9 | 16 | import com.azure.ai.formrecognizer.documentanalysis.models.OperationResult;
|
10 | 17 | import com.azure.core.annotation.ReturnType;
|
11 | 18 | import com.azure.core.annotation.ServiceClient;
|
12 | 19 | import com.azure.core.annotation.ServiceMethod;
|
13 | 20 | import com.azure.core.exception.HttpResponseException;
|
| 21 | +import com.azure.core.http.rest.Response; |
| 22 | +import com.azure.core.http.rest.ResponseBase; |
14 | 23 | import com.azure.core.util.BinaryData;
|
15 | 24 | import com.azure.core.util.Context;
|
| 25 | +import com.azure.core.util.CoreUtils; |
| 26 | +import com.azure.core.util.logging.ClientLogger; |
| 27 | +import com.azure.core.util.polling.LongRunningOperationStatus; |
| 28 | +import com.azure.core.util.polling.PollResponse; |
| 29 | +import com.azure.core.util.polling.PollingContext; |
16 | 30 | import com.azure.core.util.polling.SyncPoller;
|
17 | 31 |
|
| 32 | +import java.util.List; |
| 33 | +import java.util.Objects; |
| 34 | +import java.util.function.BiFunction; |
| 35 | +import java.util.function.Function; |
| 36 | + |
| 37 | +import static com.azure.ai.formrecognizer.documentanalysis.implementation.util.Constants.DEFAULT_POLL_INTERVAL; |
| 38 | +import static com.azure.ai.formrecognizer.documentanalysis.implementation.util.Transforms.getHttpResponseException; |
| 39 | +import static com.azure.ai.formrecognizer.documentanalysis.implementation.util.Utility.enableSyncRestProxy; |
| 40 | +import static com.azure.ai.formrecognizer.documentanalysis.implementation.util.Utility.getAnalyzeDocumentOptions; |
| 41 | +import static com.azure.ai.formrecognizer.documentanalysis.implementation.util.Utility.getTracingContext; |
| 42 | + |
18 | 43 | /**
|
19 | 44 | * This class provides a synchronous client that contains the operations that apply to Azure Form Recognizer.
|
20 | 45 | * Operations allowed by the client are analyzing information from documents and images using custom-built document
|
|
35 | 60 | */
|
36 | 61 | @ServiceClient(builder = DocumentAnalysisClientBuilder.class)
|
37 | 62 | public final class DocumentAnalysisClient {
|
38 |
| - private final DocumentAnalysisAsyncClient client; |
| 63 | + private static final ClientLogger LOGGER = new ClientLogger(DocumentAnalysisClient.class); |
| 64 | + private final FormRecognizerClientImpl service; |
39 | 65 |
|
40 | 66 | /**
|
41 | 67 | * Create a {@link DocumentAnalysisClient client} that sends requests to the Document Analysis service's endpoint.
|
42 | 68 | * Each service call goes through the {@link DocumentAnalysisClientBuilder#pipeline http pipeline}.
|
43 | 69 | *
|
44 |
| - * @param client The {@link DocumentAnalysisClient} that the client routes its request through. |
| 70 | + * @param service The proxy service used to perform REST calls. |
45 | 71 | */
|
46 |
| - DocumentAnalysisClient(DocumentAnalysisAsyncClient client) { |
47 |
| - this.client = client; |
| 72 | + DocumentAnalysisClient(FormRecognizerClientImpl service) { |
| 73 | + this.service = service; |
48 | 74 | }
|
49 |
| - |
50 | 75 | /**
|
51 | 76 | * Analyzes data from documents with optical character recognition (OCR) and semantic values from a given document
|
52 | 77 | * using any of the prebuilt models or a custom-built analysis model.
|
@@ -128,8 +153,34 @@ public final class DocumentAnalysisClient {
|
128 | 153 | public SyncPoller<OperationResult, AnalyzeResult>
|
129 | 154 | beginAnalyzeDocumentFromUrl(String modelId, String documentUrl,
|
130 | 155 | AnalyzeDocumentOptions analyzeDocumentOptions, Context context) {
|
131 |
| - return client.beginAnalyzeDocumentFromUrl(documentUrl, modelId, |
132 |
| - analyzeDocumentOptions, context).getSyncPoller(); |
| 156 | + return beginAnalyzeDocumentFromUrlSync(documentUrl, modelId, |
| 157 | + analyzeDocumentOptions, context); |
| 158 | + } |
| 159 | + |
| 160 | + SyncPoller<OperationResult, AnalyzeResult> beginAnalyzeDocumentFromUrlSync(String documentUrl, String modelId, |
| 161 | + AnalyzeDocumentOptions analyzeDocumentOptions, Context context) { |
| 162 | + if (CoreUtils.isNullOrEmpty(documentUrl)) { |
| 163 | + throw LOGGER.logExceptionAsError(new IllegalArgumentException("'documentUrl' is required and cannot" |
| 164 | + + " be null or empty")); |
| 165 | + } |
| 166 | + if (CoreUtils.isNullOrEmpty(modelId)) { |
| 167 | + throw LOGGER.logExceptionAsError(new IllegalArgumentException("'modelId' is required and cannot" |
| 168 | + + " be null or empty")); |
| 169 | + } |
| 170 | + final AnalyzeDocumentOptions finalAnalyzeDocumentOptions = getAnalyzeDocumentOptions(analyzeDocumentOptions); |
| 171 | + context = enableSyncRestProxy(getTracingContext(context)); |
| 172 | + Context finalContext = context; |
| 173 | + return SyncPoller.createPoller( |
| 174 | + DEFAULT_POLL_INTERVAL, |
| 175 | + cxt -> new PollResponse<>(LongRunningOperationStatus.NOT_STARTED, analyzeActivationOperation(modelId, |
| 176 | + finalAnalyzeDocumentOptions.getPages(), |
| 177 | + finalAnalyzeDocumentOptions.getLocale(), |
| 178 | + null, |
| 179 | + documentUrl, |
| 180 | + finalContext).apply(cxt)), |
| 181 | + pollingOperation(modelId, finalContext), |
| 182 | + getCancellationIsNotSupported(), |
| 183 | + fetchingOperation(modelId, finalContext)); |
133 | 184 | }
|
134 | 185 |
|
135 | 186 | /**
|
@@ -214,6 +265,125 @@ public final class DocumentAnalysisClient {
|
214 | 265 | public SyncPoller<OperationResult, AnalyzeResult>
|
215 | 266 | beginAnalyzeDocument(String modelId, BinaryData document,
|
216 | 267 | AnalyzeDocumentOptions analyzeDocumentOptions, Context context) {
|
217 |
| - return client.beginAnalyzeDocument(modelId, document, analyzeDocumentOptions, context).getSyncPoller(); |
| 268 | + Objects.requireNonNull(document, "'document' is required and cannot be null."); |
| 269 | + if (CoreUtils.isNullOrEmpty(modelId)) { |
| 270 | + throw LOGGER.logExceptionAsError(new IllegalArgumentException("'modelId' is required and cannot" |
| 271 | + + " be null or empty")); |
| 272 | + } |
| 273 | + |
| 274 | + final AnalyzeDocumentOptions finalAnalyzeDocumentOptions = getAnalyzeDocumentOptions(analyzeDocumentOptions); |
| 275 | + context = enableSyncRestProxy(getTracingContext(context)); |
| 276 | + Context finalContext = context; |
| 277 | + return SyncPoller.createPoller( |
| 278 | + DEFAULT_POLL_INTERVAL, |
| 279 | + cxt -> new PollResponse<>(LongRunningOperationStatus.NOT_STARTED, analyzeActivationOperation(modelId, |
| 280 | + finalAnalyzeDocumentOptions.getPages(), |
| 281 | + finalAnalyzeDocumentOptions.getLocale(), |
| 282 | + document, |
| 283 | + null, |
| 284 | + finalContext).apply(cxt)), |
| 285 | + pollingOperation(modelId, finalContext), |
| 286 | + getCancellationIsNotSupported(), |
| 287 | + fetchingOperation(modelId, finalContext)); |
| 288 | + } |
| 289 | + |
| 290 | + private Function<PollingContext<OperationResult>, OperationResult> analyzeActivationOperation( |
| 291 | + String modelId, List<String> pages, String locale, BinaryData document, String documentUrl, Context context) { |
| 292 | + return (pollingContext) -> |
| 293 | + Transforms.toDocumentOperationResult(analyzeDocument(modelId, |
| 294 | + CoreUtils.isNullOrEmpty(pages) ? null : String.join(",", pages), |
| 295 | + locale, |
| 296 | + document, |
| 297 | + documentUrl, |
| 298 | + context) |
| 299 | + .getDeserializedHeaders().getOperationLocation()); |
| 300 | + } |
| 301 | + |
| 302 | + private ResponseBase<AnalyzeDocumentHeaders, Void> analyzeDocument(String modelId, String pages, String locale, |
| 303 | + BinaryData document, String documentUrl, Context context) { |
| 304 | + try { |
| 305 | + if (documentUrl == null) { |
| 306 | + return service.analyzeDocumentWithResponse(modelId, |
| 307 | + null, |
| 308 | + pages, |
| 309 | + locale, |
| 310 | + StringIndexType.UTF16CODE_UNIT, |
| 311 | + document, |
| 312 | + document.getLength(), |
| 313 | + context); |
| 314 | + } else { |
| 315 | + return service.analyzeDocumentWithResponse(modelId, |
| 316 | + pages, |
| 317 | + locale, |
| 318 | + StringIndexType.UTF16CODE_UNIT, |
| 319 | + new AnalyzeDocumentRequest().setUrlSource(documentUrl), |
| 320 | + context); |
| 321 | + } |
| 322 | + } catch (ErrorResponseException ex) { |
| 323 | + throw LOGGER.logExceptionAsError(getHttpResponseException(ex)); |
| 324 | + |
| 325 | + } |
| 326 | + } |
| 327 | + private BiFunction<PollingContext<OperationResult>, PollResponse<OperationResult>, OperationResult> |
| 328 | + getCancellationIsNotSupported() { |
| 329 | + return (pollingContext, activationResponse) -> { |
| 330 | + throw LOGGER.logExceptionAsError(new RuntimeException("Cancellation is not supported")); |
| 331 | + }; |
| 332 | + } |
| 333 | + |
| 334 | + private Function<PollingContext<OperationResult>, PollResponse<OperationResult>> |
| 335 | + pollingOperation(String modelId, Context finalContext) { |
| 336 | + return pollingContext -> { |
| 337 | + final PollResponse<OperationResult> operationResultPollResponse |
| 338 | + = pollingContext.getLatestResponse(); |
| 339 | + final String resultId = operationResultPollResponse.getValue().getOperationId(); |
| 340 | + Response<AnalyzeResultOperation> modelResponse; |
| 341 | + try { |
| 342 | + modelResponse = service.getAnalyzeDocumentResultWithResponse(modelId, resultId, finalContext); |
| 343 | + } catch (ErrorResponseException ex) { |
| 344 | + throw LOGGER.logExceptionAsError(Transforms.getHttpResponseException(ex)); |
| 345 | + } |
| 346 | + return processAnalyzeModelResponse(modelResponse, operationResultPollResponse); |
| 347 | + }; |
| 348 | + } |
| 349 | + |
| 350 | + private PollResponse<OperationResult> processAnalyzeModelResponse( |
| 351 | + Response<AnalyzeResultOperation> analyzeResultOperationResponse, |
| 352 | + PollResponse<OperationResult> operationResultPollResponse) { |
| 353 | + LongRunningOperationStatus status; |
| 354 | + switch (analyzeResultOperationResponse.getValue().getStatus()) { |
| 355 | + case NOT_STARTED: |
| 356 | + case RUNNING: |
| 357 | + status = LongRunningOperationStatus.IN_PROGRESS; |
| 358 | + break; |
| 359 | + case SUCCEEDED: |
| 360 | + status = LongRunningOperationStatus.SUCCESSFULLY_COMPLETED; |
| 361 | + break; |
| 362 | + case FAILED: |
| 363 | + throw LOGGER.logExceptionAsError(Transforms |
| 364 | + .mapResponseErrorToHttpResponseException(analyzeResultOperationResponse.getValue().getError())); |
| 365 | + default: |
| 366 | + status = LongRunningOperationStatus.fromString( |
| 367 | + analyzeResultOperationResponse.getValue().getStatus().toString(), true); |
| 368 | + break; |
| 369 | + } |
| 370 | + return new PollResponse<>(status, operationResultPollResponse.getValue()); |
| 371 | + } |
| 372 | + |
| 373 | + private Function<PollingContext<OperationResult>, AnalyzeResult> |
| 374 | + fetchingOperation( |
| 375 | + String modelId, Context finalContext) { |
| 376 | + return pollingContext -> { |
| 377 | + final String resultId = pollingContext.getLatestResponse().getValue().getOperationId(); |
| 378 | + try { |
| 379 | + return Transforms.toAnalyzeResultOperation(service.getAnalyzeDocumentResultWithResponse( |
| 380 | + modelId, |
| 381 | + resultId, |
| 382 | + finalContext) |
| 383 | + .getValue().getAnalyzeResult()); |
| 384 | + } catch (ErrorResponseException ex) { |
| 385 | + throw LOGGER.logExceptionAsError(Transforms.getHttpResponseException(ex)); |
| 386 | + } |
| 387 | + }; |
218 | 388 | }
|
219 | 389 | }
|
0 commit comments