From 9df21dcc0bf2cf2af2f12e747f3929faa29eb7c9 Mon Sep 17 00:00:00 2001 From: DenovVasil Date: Wed, 2 Oct 2024 14:29:19 +0300 Subject: [PATCH] feat(comprehend): impl connector --- bundle/default-bundle/pom.xml | 4 + bundle/pom.xml | 5 + connectors/aws/aws-comprehend/LICENSE.txt | 5 + connectors/aws/aws-comprehend/README.md | 3 + .../aws-comprehend-outbound-connector.json | 684 +++++++++++++++++ ...-comprehend-outbound-connector-hybrid.json | 689 ++++++++++++++++++ connectors/aws/aws-comprehend/pom.xml | 78 ++ .../ComprehendConnectorFunction.java | 72 ++ .../caller/AsyncComprehendCaller.java | 118 +++ .../comprehend/caller/ComprehendCaller.java | 74 ++ .../caller/SyncComprehendCaller.java | 35 + .../model/ComprehendAsyncRequestData.java | 200 +++++ .../model/ComprehendDocumentReadAction.java | 13 + .../model/ComprehendDocumentReadMode.java | 13 + .../model/ComprehendInputFormat.java | 13 + .../comprehend/model/ComprehendRequest.java | 52 ++ .../model/ComprehendRequestData.java | 31 + .../model/ComprehendSyncRequestData.java | 128 ++++ .../supplier/ComprehendClientSupplier.java | 31 + ...tor.api.outbound.OutboundConnectorFunction | 1 + .../src/main/resources/icon.svg | 10 + .../ComprehendConnectorFunctionTest.java | 81 ++ .../comprehend/ComprehendTestUtils.java | 73 ++ .../caller/AsyncComprehendCallerTest.java | 148 ++++ .../caller/ComprehendCallerTest.java | 127 ++++ .../caller/SyncComprehendCallerTest.java | 75 ++ .../ComprehendClientSupplierTest.java | 47 ++ connectors/aws/pom.xml | 1 + 28 files changed, 2811 insertions(+) create mode 100644 connectors/aws/aws-comprehend/LICENSE.txt create mode 100644 connectors/aws/aws-comprehend/README.md create mode 100644 connectors/aws/aws-comprehend/element-templates/aws-comprehend-outbound-connector.json create mode 100644 connectors/aws/aws-comprehend/element-templates/hybrid/aws-comprehend-outbound-connector-hybrid.json create mode 100644 connectors/aws/aws-comprehend/pom.xml create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/ComprehendConnectorFunction.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/AsyncComprehendCaller.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/ComprehendCaller.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/SyncComprehendCaller.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendAsyncRequestData.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendDocumentReadAction.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendDocumentReadMode.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendInputFormat.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendRequest.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendRequestData.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendSyncRequestData.java create mode 100644 connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/supplier/ComprehendClientSupplier.java create mode 100644 connectors/aws/aws-comprehend/src/main/resources/META-INF/services/io.camunda.connector.api.outbound.OutboundConnectorFunction create mode 100644 connectors/aws/aws-comprehend/src/main/resources/icon.svg create mode 100644 connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/ComprehendConnectorFunctionTest.java create mode 100644 connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/ComprehendTestUtils.java create mode 100644 connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/AsyncComprehendCallerTest.java create mode 100644 connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/ComprehendCallerTest.java create mode 100644 connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/SyncComprehendCallerTest.java create mode 100644 connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/supplier/ComprehendClientSupplierTest.java diff --git a/bundle/default-bundle/pom.xml b/bundle/default-bundle/pom.xml index 6142feb3fd..bc65c8070b 100644 --- a/bundle/default-bundle/pom.xml +++ b/bundle/default-bundle/pom.xml @@ -109,6 +109,10 @@ io.camunda.connector connector-email + + io.camunda.connector + connector-aws-comprehend + diff --git a/bundle/pom.xml b/bundle/pom.xml index ab92668bef..b9e5665081 100644 --- a/bundle/pom.xml +++ b/bundle/pom.xml @@ -149,6 +149,11 @@ connector-email ${project.version} + + io.camunda.connector + connector-aws-comprehend + ${project.version} + diff --git a/connectors/aws/aws-comprehend/LICENSE.txt b/connectors/aws/aws-comprehend/LICENSE.txt new file mode 100644 index 0000000000..85fdd16e79 --- /dev/null +++ b/connectors/aws/aws-comprehend/LICENSE.txt @@ -0,0 +1,5 @@ +Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under one or more contributor license agreements and licensed to you under a proprietary license. +You may not use this file except in compliance with the proprietary license. +The proprietary license can be either the Camunda Self-Managed Free Edition license (available on Camunda’s website) or the Camunda Self-Managed Enterprise Edition license (a copy you obtain when you contact Camunda). +The Camunda Self-Managed Free Edition comes for free but only allows for usage of the software (file) in non-production environments. +If you want to use the software (file) in production, you need to purchase the Camunda Self-Managed Enterprise Edition. \ No newline at end of file diff --git a/connectors/aws/aws-comprehend/README.md b/connectors/aws/aws-comprehend/README.md new file mode 100644 index 0000000000..398a4711d9 --- /dev/null +++ b/connectors/aws/aws-comprehend/README.md @@ -0,0 +1,3 @@ +# AWS Comprehend Connector + +The **AWS Comprehend Connector** uses natural language processing (NLP) to extract insights about the content of documents. diff --git a/connectors/aws/aws-comprehend/element-templates/aws-comprehend-outbound-connector.json b/connectors/aws/aws-comprehend/element-templates/aws-comprehend-outbound-connector.json new file mode 100644 index 0000000000..d8608b4b71 --- /dev/null +++ b/connectors/aws/aws-comprehend/element-templates/aws-comprehend-outbound-connector.json @@ -0,0 +1,684 @@ +{ + "$schema" : "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json", + "name" : "AWS Comprehend Outbound Connector", + "id" : "io.camunda.connectors.AWSCOMPREHEND.v1", + "description" : "Execute Comprehend models", + "documentationRef" : "https://docs.camunda.io/docs/next/components/connectors/out-of-the-box-connectors/amazon-comprehend/", + "version" : 1, + "category" : { + "id" : "connectors", + "name" : "Connectors" + }, + "appliesTo" : [ "bpmn:Task" ], + "elementType" : { + "value" : "bpmn:ServiceTask" + }, + "groups" : [ { + "id" : "authentication", + "label" : "Authentication" + }, { + "id" : "configuration", + "label" : "Configuration" + }, { + "id" : "input", + "label" : "Configure input" + }, { + "id" : "output", + "label" : "Output mapping" + }, { + "id" : "error", + "label" : "Error handling" + }, { + "id" : "retries", + "label" : "Retries" + } ], + "properties" : [ { + "value" : "io.camunda:aws-comprehend:1", + "binding" : { + "property" : "type", + "type" : "zeebe:taskDefinition" + }, + "type" : "Hidden" + }, { + "id" : "authentication.type", + "label" : "Authentication", + "description" : "Specify AWS authentication strategy. Learn more at the documentation page", + "value" : "credentials", + "group" : "authentication", + "binding" : { + "name" : "authentication.type", + "type" : "zeebe:input" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Default Credentials Chain (Hybrid/Self-Managed only)", + "value" : "defaultCredentialsChain" + }, { + "name" : "Credentials", + "value" : "credentials" + } ] + }, { + "id" : "authentication.accessKey", + "label" : "Access key", + "description" : "Provide an IAM access key tailored to a user, equipped with the necessary permissions", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "authentication", + "binding" : { + "name" : "authentication.accessKey", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "authentication.type", + "equals" : "credentials", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "authentication.secretKey", + "label" : "Secret key", + "description" : "Provide a secret key of a user with permissions to invoke specified AWS Lambda function", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "authentication", + "binding" : { + "name" : "authentication.secretKey", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "authentication.type", + "equals" : "credentials", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "configuration.region", + "label" : "Region", + "description" : "Specify the AWS region", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "configuration", + "binding" : { + "name" : "configuration.region", + "type" : "zeebe:input" + }, + "type" : "String" + }, { + "id" : "configuration.endpoint", + "label" : "Endpoint", + "description" : "Specify endpoint if need to use custom endpoint", + "optional" : true, + "group" : "configuration", + "binding" : { + "name" : "configuration.endpoint", + "type" : "zeebe:input" + }, + "type" : "Hidden" + }, { + "id" : "input.type", + "label" : "Execution type", + "group" : "input", + "binding" : { + "name" : "input.type", + "type" : "zeebe:input" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Sync", + "value" : "sync" + }, { + "name" : "Async", + "value" : "async" + } ] + }, { + "id" : "input.text", + "label" : "Text", + "description" : "The document text to be analyzed.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.text", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.sync.documentReadAction", + "label" : "Document read action", + "description" : "Textract API operation that uses to extract text from PDF files and image files.", + "optional" : false, + "value" : "TEXTRACT_DETECT_DOCUMENT_TEXT", + "constraints" : { + "notEmpty" : true + }, + "group" : "input", + "binding" : { + "name" : "input.documentReadAction", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "tooltip" : "more info", + "type" : "Dropdown", + "choices" : [ { + "name" : "Detect document text", + "value" : "TEXTRACT_DETECT_DOCUMENT_TEXT" + }, { + "name" : "Analyze document", + "value" : "TEXTRACT_ANALYZE_DOCUMENT" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.sync.documentReadMode", + "label" : "Document read mode", + "description" : "Determines the text extraction actions for PDF files.", + "optional" : false, + "value" : "SERVICE_DEFAULT", + "constraints" : { + "notEmpty" : true + }, + "group" : "input", + "binding" : { + "name" : "input.documentReadMode", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Service default", + "value" : "SERVICE_DEFAULT" + }, { + "name" : "Force document read action", + "value" : "FORCE_DOCUMENT_READ_ACTION" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.sync.featureTypeTables", + "label" : "Analyze tables", + "optional" : false, + "value" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.featureTypeTables", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "Boolean" + }, { + "id" : "input.sync.featureTypeForms", + "label" : "Analyze forms", + "optional" : false, + "value" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.featureTypeForms", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "Boolean" + }, { + "id" : "input.endpointArn", + "label" : "Endpoint ARN", + "description" : "The Amazon Resource Number (ARN) of the endpoint.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.endpointArn", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.async.documentReadAction", + "label" : "Document read action", + "description" : "Textract API operation that uses to extract text from PDF files and image files.", + "optional" : false, + "value" : "TEXTRACT_DETECT_DOCUMENT_TEXT", + "constraints" : { + "notEmpty" : true + }, + "group" : "input", + "binding" : { + "name" : "input.documentReadAction", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "tooltip" : "more info", + "type" : "Dropdown", + "choices" : [ { + "name" : "Detect document text", + "value" : "TEXTRACT_DETECT_DOCUMENT_TEXT" + }, { + "name" : "Analyze document", + "value" : "TEXTRACT_ANALYZE_DOCUMENT" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.async.documentReadMode", + "label" : "Document read mode", + "description" : "Determines the text extraction actions for PDF files.", + "optional" : false, + "value" : "SERVICE_DEFAULT", + "constraints" : { + "notEmpty" : true + }, + "group" : "input", + "binding" : { + "name" : "input.documentReadMode", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Service default", + "value" : "SERVICE_DEFAULT" + }, { + "name" : "Force document read action", + "value" : "FORCE_DOCUMENT_READ_ACTION" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.async.featureTypeTables", + "label" : "Analyze tables", + "optional" : false, + "value" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.featureTypeTables", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "Boolean" + }, { + "id" : "input.async.featureTypeForms", + "label" : "Analyze forms", + "optional" : false, + "value" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.featureTypeForms", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "Boolean" + }, { + "id" : "input.inputS3Uri", + "label" : "Input S3 URI", + "description" : "The Amazon S3 URI for the input data.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.inputS3Uri", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.comprehendInputFormat", + "label" : "Input Format", + "description" : "Specifies how the text in an input file should be processed.", + "optional" : false, + "value" : "ONE_DOC_PER_FILE", + "group" : "input", + "binding" : { + "name" : "input.comprehendInputFormat", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Each file is considered a separate document", + "value" : "ONE_DOC_PER_FILE" + }, { + "name" : "Each line in a file is considered a separate document", + "value" : "ONE_DOC_PER_LINE" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.clientRequestToken", + "label" : "Client request token", + "description" : "A unique identifier for the request.", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.clientRequestToken", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.dataAccessRoleArn", + "label" : "Data Access Role ARN", + "description" : "The ARN of the IAM role that grants Amazon Comprehend read access to your input data.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.dataAccessRoleArn", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.documentClassifierArn", + "label" : "Document Classifier ARN", + "description" : "The ARN of the document classifier to use to process the job", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.documentClassifierArn", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.flywheelArn", + "label" : "Flywheel ARN", + "description" : "The ARN of the flywheel associated with the model.", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.flywheelArn", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.jobName", + "label" : "Job name", + "description" : "The identifier of the job", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.jobName", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.outputS3Uri", + "label" : "Output S3 URI", + "description" : "S3 location where the date will be written.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.outputS3Uri", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.outputKmsKeyId", + "label" : "Output Kms Key Id", + "description" : "KMS key id used for encrypt the output result.", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.outputKmsKeyId", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.tags", + "label" : "Tags", + "description" : "Tags to associate with the document classification job", + "optional" : true, + "feel" : "required", + "group" : "input", + "binding" : { + "name" : "input.tags", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.volumeKmsKeyId", + "label" : "Volume Kms Key Id", + "description" : "KMS that Amazon Comprehend uses to encrypt data on the storage volume attached to the ML compute instance.", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.volumeKmsKeyId", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.securityGroupIds", + "label" : "Security group ids", + "description" : "The ID number for a security group on an instance of your private VPC.", + "optional" : true, + "feel" : "required", + "group" : "input", + "binding" : { + "name" : "input.securityGroupIds", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.subnets", + "label" : "Subnets", + "description" : "The ID for each subnet being used in your private VPC.", + "optional" : true, + "feel" : "required", + "group" : "input", + "binding" : { + "name" : "input.subnets", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "resultVariable", + "label" : "Result variable", + "description" : "Name of variable to store the response in", + "group" : "output", + "binding" : { + "key" : "resultVariable", + "type" : "zeebe:taskHeader" + }, + "type" : "String" + }, { + "id" : "resultExpression", + "label" : "Result expression", + "description" : "Expression to map the response into process variables", + "feel" : "required", + "group" : "output", + "binding" : { + "key" : "resultExpression", + "type" : "zeebe:taskHeader" + }, + "type" : "Text" + }, { + "id" : "errorExpression", + "label" : "Error expression", + "description" : "Expression to handle errors. Details in the documentation.", + "feel" : "required", + "group" : "error", + "binding" : { + "key" : "errorExpression", + "type" : "zeebe:taskHeader" + }, + "type" : "Text" + }, { + "id" : "retryCount", + "label" : "Retries", + "description" : "Number of retries", + "value" : "3", + "feel" : "optional", + "group" : "retries", + "binding" : { + "property" : "retries", + "type" : "zeebe:taskDefinition" + }, + "type" : "String" + }, { + "id" : "retryBackoff", + "label" : "Retry backoff", + "description" : "ISO-8601 duration to wait between retries", + "value" : "PT0S", + "feel" : "optional", + "group" : "retries", + "binding" : { + "key" : "retryBackoff", + "type" : "zeebe:taskHeader" + }, + "type" : "String" + } ], + "icon" : { + "contents" : "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iODBweCIgaGVpZ2h0PSI4MHB4IiB2aWV3Qm94PSIwIDAgODAgODAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+SWNvbi1BcmNoaXRlY3R1cmUvNjQvQXJjaF9BbWF6b24tQ29tcHJlaGVuZF82NDwvdGl0bGU+CiAgICA8ZyBpZD0iSWNvbi1BcmNoaXRlY3R1cmUvNjQvQXJjaF9BbWF6b24tQ29tcHJlaGVuZF82NCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9Ikljb24tQXJjaGl0ZWN0dXJlLUJHLzY0L01hY2hpbmUtTGVhcm5pbmciIGZpbGw9IiM5OTY5ZjciPgogICAgICAgICAgICA8cmVjdCBpZD0iUmVjdGFuZ2xlIiB4PSIwIiB5PSIwIiB3aWR0aD0iODAiIGhlaWdodD0iODAiPjwvcmVjdD4KICAgICAgICA8L2c+CiAgICAgICAgPHBhdGggZD0iTTE2Ljk5OTk2NTMsNTQgTDMyLjk5OTg1NDIsNTQgTDMyLjk5OTg1NDIsNTIgTDE2Ljk5OTk2NTMsNTIgTDE2Ljk5OTk2NTMsNTQgWiBNMzMuOTk5ODQ3Myw0NyBMNDIuOTk5Nzg0OCw0NyBMNDIuOTk5Nzg0OCw0NSBMMzMuOTk5ODQ3Myw0NSBMMzMuOTk5ODQ3Myw0NyBaIE0xNi45OTk5NjUzLDQ3IEwzMS45OTk4NjEyLDQ3IEwzMS45OTk4NjEyLDQ1IEwxNi45OTk5NjUzLDQ1IEwxNi45OTk5NjUzLDQ3IFogTTE2Ljk5OTk2NTMsMjYgTDI5Ljk5OTg3NSwyNiBMMjkuOTk5ODc1LDI0IEwxNi45OTk5NjUzLDI0IEwxNi45OTk5NjUzLDI2IFogTTYzLjAxMDY0NTksNTQuMDc5IEM2Mi44OTc2NDY3LDU0LjE1NiA2Mi43NTI2NDc3LDU0LjIxOCA2Mi42MDM2NDg3LDU0LjI4NyBDNjIuMDc1NjUyNCw1NC41MzQgNjEuMzUyNjU3NCw1NC44NzMgNjEuMDYxNjU5NCw1NS42NTEgQzYxLjAyMDY1OTcsNTUuNzYzIDYwLjk5OTY1OTgsNTUuODgxIDYwLjk5OTY1OTgsNTYgTDYwLjk5OTY1OTgsNjAgTDU4Ljk5OTY3MzcsNjAgTDU4Ljk5OTY3MzcsNTEgTDYxLjk5OTY1MjksNTEgTDYxLjk5OTY1MjksNDkgTDUzLjk5OTcwODQsNDkgTDUzLjk5OTcwODQsNTEgTDU2Ljk5OTY4NzYsNTEgTDU2Ljk5OTY4NzYsNjAgTDU0Ljk5OTcwMTUsNjAgTDU0Ljk5OTcwMTUsNTYgQzU0Ljk5OTcwMTUsNTUuODgxIDU0Ljk3ODcwMTYsNTUuNzYzIDU0LjkzNjcwMTksNTUuNjUxIEM1NC42NDY3MDM5LDU0Ljg3MyA1My45MjM3MDksNTQuNTM0IDUzLjM5NTcxMjYsNTQuMjg3IEM1My4yNDY3MTM3LDU0LjIxOCA1My4xMDE3MTQ3LDU0LjE1NiA1Mi45ODg3MTU0LDU0LjA3OSBDNTAuMDI0NzM2LDUyLjAyNCA0OC41NDM3NDYzLDQ4LjUwNSA0OS4xMjQ3NDIzLDQ0Ljg5NiBDNDkuNzcyNzM3OCw0MC44NjMgNTMuMjA1NzEzOSwzNy42MjEgNTcuMjg2Njg1NiwzNy4xODggQzU3LjQ5NTY4NDIsMzcuMTY1IDU4LjUwNzY3NzEsMzcuMTY2IDU4LjcxMjY3NTcsMzcuMTg4IEM2Mi43OTM2NDc0LDM3LjYyMSA2Ni4yMjY2MjM1LDQwLjg2MyA2Ni44NzQ2MTksNDQuODk2IEM2Ny40NTU2MTUsNDguNTA1IDY1Ljk3NDYyNTMsNTIuMDI0IDYzLjAxMDY0NTksNTQuMDc5IEw2My4wMTA2NDU5LDU0LjA3OSBaIE02OC44NDk2MDUzLDQ0LjU3OSBDNjguMDYwNjEwOCwzOS42NyA2My44ODU2Mzk4LDM1LjcyNiA1OC45MjI2NzQyLDM1LjE5OCBDNTguNTc2Njc2NiwzNS4xNjIgNTcuNDIwNjg0NywzNS4xNjIgNTcuMDc2Njg3MSwzNS4xOTggTDU3LjA3NTY4NzEsMzUuMTk4IEM1Mi4xMTM3MjE1LDM1LjcyNiA0Ny45Mzg3NTA1LDM5LjY3IDQ3LjE0OTc1Niw0NC41NzkgQzQ2LjQ0NTc2MDksNDguOTU1IDQ4LjI0Njc0ODQsNTMuMjI1IDUxLjg1MDcyMzMsNTUuNzIyIEM1Mi4wNDU3MjIsNTUuODU3IDUyLjI5MDcyMDMsNTUuOTc5IDUyLjU0NzcxODUsNTYuMDk5IEM1Mi42ODQ3MTc2LDU2LjE2MyA1Mi44OTM3MTYxLDU2LjI2IDUyLjk5OTcxNTQsNTYuMzE0IEw1Mi45OTk3MTU0LDYxIEM1Mi45OTk3MTU0LDYxLjU1MiA1My40NDY3MTIzLDYyIDUzLjk5OTcwODQsNjIgTDYxLjk5OTY1MjksNjIgQzYyLjU1MjY0OSw2MiA2Mi45OTk2NDU5LDYxLjU1MiA2Mi45OTk2NDU5LDYxIEw2Mi45OTk2NDU5LDU2LjMzIEM2My4xMjA2NDUxLDU2LjI1MyA2My4zMTk2NDM3LDU2LjE2MSA2My40NTE2NDI4LDU2LjA5OSBDNjMuNzA4NjQxLDU1Ljk3OSA2My45NTM2MzkzLDU1Ljg1NyA2NC4xNDg2MzgsNTUuNzIyIEM2Ny43NTI2MTI5LDUzLjIyNSA2OS41NTM2MDA0LDQ4Ljk1NSA2OC44NDk2MDUzLDQ0LjU3OSBMNjguODQ5NjA1Myw0NC41NzkgWiBNNTkuNDY0NjcwNSw2NiBMNTYuNTM0NjkwOCw2NiBMNTUuODY3Njk1NSw2NSBMNjAuMTMxNjY1OSw2NSBMNTkuNDY0NjcwNSw2NiBaIE02MS45OTk2NTI5LDYzIEw1My45OTk3MDg0LDYzIEM1My42MzA3MTEsNjMgNTMuMjkxNzEzMyw2My4yMDMgNTMuMTE3NzE0NSw2My41MjggQzUyLjk0MzcxNTgsNjMuODU0IDUyLjk2MzcxNTYsNjQuMjQ4IDUzLjE2NzcxNDIsNjQuNTU1IEw1NS4xNjc3MDAzLDY3LjU1NSBDNTUuMzUzNjk5LDY3LjgzMyA1NS42NjU2OTY5LDY4IDU1Ljk5OTY5NDUsNjggTDU5Ljk5OTY2NjgsNjggQzYwLjMzMzY2NDUsNjggNjAuNjQ1NjYyMyw2Ny44MzMgNjAuODMxNjYxLDY3LjU1NSBMNjIuODMxNjQ3MSw2NC41NTUgQzYzLjAzNTY0NTcsNjQuMjQ4IDYzLjA1NTY0NTYsNjMuODU0IDYyLjg4MTY0NjgsNjMuNTI4IEM2Mi43MDc2NDgsNjMuMjAzIDYyLjM2ODY1MDMsNjMgNjEuOTk5NjUyOSw2MyBMNjEuOTk5NjUyOSw2MyBaIE0xNi45OTk5NjUzLDQwIEw0Mi45OTk3ODQ4LDQwIEw0Mi45OTk3ODQ4LDM4IEwxNi45OTk5NjUzLDM4IEwxNi45OTk5NjUzLDQwIFogTTI1Ljk5OTkwMjgsMzMgTDQyLjk5OTc4NDgsMzMgTDQyLjk5OTc4NDgsMzEgTDI1Ljk5OTkwMjgsMzEgTDI1Ljk5OTkwMjgsMzMgWiBNMTYuOTk5OTY1MywzMyBMMjMuOTk5OTE2NywzMyBMMjMuOTk5OTE2NywzMSBMMTYuOTk5OTY1MywzMSBMMTYuOTk5OTY1MywzMyBaIE0zNS45OTk4MzM0LDE1LjQxNCBMNDQuNTg1NzczOCwyNCBMMzUuOTk5ODMzNCwyNCBMMzUuOTk5ODMzNCwxNS40MTQgWiBNNDUuOTk5NzY0LDYxIEwxMy45OTk5ODYxLDYxIEwxMy45OTk5ODYxLDE0LjAwNSBMMzMuOTk5ODQ3MywxNCBMMzMuOTk5ODQ3MywyNSBDMzMuOTk5ODQ3MywyNS41NTIgMzQuNDQ2ODQ0MiwyNiAzNC45OTk4NDAzLDI2IEw0NS45OTk3NjQsMjYgTDQ1Ljk5OTc2NCwzOCBMNDcuOTk5NzUwMSwzOCBMNDcuOTk5NzUwMSwyNSBMNDcuOTkwNzUwMSwyNSBDNDcuOTg5NzUwMSwyNC43NCA0Ny44OTc3NTA4LDI0LjQ4NCA0Ny43MDY3NTIxLDI0LjI5MyBMMzUuNzA2ODM1NCwxMi4yOTMgQzM1LjUxNjgzNjcsMTIuMTAyIDM1LjI2MDgzODUsMTIuMDEgMzQuOTk5ODQwMywxMi4wMSBMMzQuOTk5ODQwMywxMiBMMTMsMTIuMDA1IEMxMi40NDY5OTY5LDEyLjAwNSAxMiwxMi40NTMgMTIsMTMuMDA1IEwxMiw2MiBDMTIsNjIuNTUyIDEyLjQ0Njk5NjksNjMgMTMsNjMgTDQ2Ljk5OTc1Nyw2MyBDNDcuNTUyNzUzMiw2MyA0Ny45OTk3NTAxLDYyLjU1MiA0Ny45OTk3NTAxLDYyIEw0Ny45OTk3NTAxLDU2IEw0NS45OTk3NjQsNTYgTDQ1Ljk5OTc2NCw2MSBaIiBpZD0iQW1hem9uLUNvbXByZWhlbmRfSWNvbl82NF9TcXVpZCIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgPC9nPgo8L3N2Zz4=" + } +} \ No newline at end of file diff --git a/connectors/aws/aws-comprehend/element-templates/hybrid/aws-comprehend-outbound-connector-hybrid.json b/connectors/aws/aws-comprehend/element-templates/hybrid/aws-comprehend-outbound-connector-hybrid.json new file mode 100644 index 0000000000..aa64e67904 --- /dev/null +++ b/connectors/aws/aws-comprehend/element-templates/hybrid/aws-comprehend-outbound-connector-hybrid.json @@ -0,0 +1,689 @@ +{ + "$schema" : "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json", + "name" : "Hybrid AWS Comprehend Outbound Connector", + "id" : "io.camunda.connectors.AWSCOMPREHEND.v1-hybrid", + "description" : "Execute Comprehend models", + "documentationRef" : "https://docs.camunda.io/docs/next/components/connectors/out-of-the-box-connectors/amazon-comprehend/", + "version" : 1, + "category" : { + "id" : "connectors", + "name" : "Connectors" + }, + "appliesTo" : [ "bpmn:Task" ], + "elementType" : { + "value" : "bpmn:ServiceTask" + }, + "groups" : [ { + "id" : "taskDefinitionType", + "label" : "Task definition type" + }, { + "id" : "authentication", + "label" : "Authentication" + }, { + "id" : "configuration", + "label" : "Configuration" + }, { + "id" : "input", + "label" : "Configure input" + }, { + "id" : "output", + "label" : "Output mapping" + }, { + "id" : "error", + "label" : "Error handling" + }, { + "id" : "retries", + "label" : "Retries" + } ], + "properties" : [ { + "id" : "taskDefinitionType", + "value" : "io.camunda:aws-comprehend:1", + "group" : "taskDefinitionType", + "binding" : { + "property" : "type", + "type" : "zeebe:taskDefinition" + }, + "type" : "String" + }, { + "id" : "authentication.type", + "label" : "Authentication", + "description" : "Specify AWS authentication strategy. Learn more at the documentation page", + "value" : "credentials", + "group" : "authentication", + "binding" : { + "name" : "authentication.type", + "type" : "zeebe:input" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Default Credentials Chain (Hybrid/Self-Managed only)", + "value" : "defaultCredentialsChain" + }, { + "name" : "Credentials", + "value" : "credentials" + } ] + }, { + "id" : "authentication.accessKey", + "label" : "Access key", + "description" : "Provide an IAM access key tailored to a user, equipped with the necessary permissions", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "authentication", + "binding" : { + "name" : "authentication.accessKey", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "authentication.type", + "equals" : "credentials", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "authentication.secretKey", + "label" : "Secret key", + "description" : "Provide a secret key of a user with permissions to invoke specified AWS Lambda function", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "authentication", + "binding" : { + "name" : "authentication.secretKey", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "authentication.type", + "equals" : "credentials", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "configuration.region", + "label" : "Region", + "description" : "Specify the AWS region", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "configuration", + "binding" : { + "name" : "configuration.region", + "type" : "zeebe:input" + }, + "type" : "String" + }, { + "id" : "configuration.endpoint", + "label" : "Endpoint", + "description" : "Specify endpoint if need to use custom endpoint", + "optional" : true, + "group" : "configuration", + "binding" : { + "name" : "configuration.endpoint", + "type" : "zeebe:input" + }, + "type" : "Hidden" + }, { + "id" : "input.type", + "label" : "Execution type", + "group" : "input", + "binding" : { + "name" : "input.type", + "type" : "zeebe:input" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Sync", + "value" : "sync" + }, { + "name" : "Async", + "value" : "async" + } ] + }, { + "id" : "input.text", + "label" : "Text", + "description" : "The document text to be analyzed.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.text", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.sync.documentReadAction", + "label" : "Document read action", + "description" : "Textract API operation that uses to extract text from PDF files and image files.", + "optional" : false, + "value" : "TEXTRACT_DETECT_DOCUMENT_TEXT", + "constraints" : { + "notEmpty" : true + }, + "group" : "input", + "binding" : { + "name" : "input.documentReadAction", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "tooltip" : "more info", + "type" : "Dropdown", + "choices" : [ { + "name" : "Detect document text", + "value" : "TEXTRACT_DETECT_DOCUMENT_TEXT" + }, { + "name" : "Analyze document", + "value" : "TEXTRACT_ANALYZE_DOCUMENT" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.sync.documentReadMode", + "label" : "Document read mode", + "description" : "Determines the text extraction actions for PDF files.", + "optional" : false, + "value" : "SERVICE_DEFAULT", + "constraints" : { + "notEmpty" : true + }, + "group" : "input", + "binding" : { + "name" : "input.documentReadMode", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Service default", + "value" : "SERVICE_DEFAULT" + }, { + "name" : "Force document read action", + "value" : "FORCE_DOCUMENT_READ_ACTION" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.sync.featureTypeTables", + "label" : "Analyze tables", + "optional" : false, + "value" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.featureTypeTables", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "Boolean" + }, { + "id" : "input.sync.featureTypeForms", + "label" : "Analyze forms", + "optional" : false, + "value" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.featureTypeForms", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "Boolean" + }, { + "id" : "input.endpointArn", + "label" : "Endpoint ARN", + "description" : "The Amazon Resource Number (ARN) of the endpoint.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.endpointArn", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "sync", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.async.documentReadAction", + "label" : "Document read action", + "description" : "Textract API operation that uses to extract text from PDF files and image files.", + "optional" : false, + "value" : "TEXTRACT_DETECT_DOCUMENT_TEXT", + "constraints" : { + "notEmpty" : true + }, + "group" : "input", + "binding" : { + "name" : "input.documentReadAction", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "tooltip" : "more info", + "type" : "Dropdown", + "choices" : [ { + "name" : "Detect document text", + "value" : "TEXTRACT_DETECT_DOCUMENT_TEXT" + }, { + "name" : "Analyze document", + "value" : "TEXTRACT_ANALYZE_DOCUMENT" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.async.documentReadMode", + "label" : "Document read mode", + "description" : "Determines the text extraction actions for PDF files.", + "optional" : false, + "value" : "SERVICE_DEFAULT", + "constraints" : { + "notEmpty" : true + }, + "group" : "input", + "binding" : { + "name" : "input.documentReadMode", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Service default", + "value" : "SERVICE_DEFAULT" + }, { + "name" : "Force document read action", + "value" : "FORCE_DOCUMENT_READ_ACTION" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.async.featureTypeTables", + "label" : "Analyze tables", + "optional" : false, + "value" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.featureTypeTables", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "Boolean" + }, { + "id" : "input.async.featureTypeForms", + "label" : "Analyze forms", + "optional" : false, + "value" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.featureTypeForms", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "Boolean" + }, { + "id" : "input.inputS3Uri", + "label" : "Input S3 URI", + "description" : "The Amazon S3 URI for the input data.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.inputS3Uri", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.comprehendInputFormat", + "label" : "Input Format", + "description" : "Specifies how the text in an input file should be processed.", + "optional" : false, + "value" : "ONE_DOC_PER_FILE", + "group" : "input", + "binding" : { + "name" : "input.comprehendInputFormat", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "Dropdown", + "choices" : [ { + "name" : "Each file is considered a separate document", + "value" : "ONE_DOC_PER_FILE" + }, { + "name" : "Each line in a file is considered a separate document", + "value" : "ONE_DOC_PER_LINE" + }, { + "name" : "None", + "value" : "NO_DATA" + } ] + }, { + "id" : "input.clientRequestToken", + "label" : "Client request token", + "description" : "A unique identifier for the request.", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.clientRequestToken", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.dataAccessRoleArn", + "label" : "Data Access Role ARN", + "description" : "The ARN of the IAM role that grants Amazon Comprehend read access to your input data.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.dataAccessRoleArn", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.documentClassifierArn", + "label" : "Document Classifier ARN", + "description" : "The ARN of the document classifier to use to process the job", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.documentClassifierArn", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.flywheelArn", + "label" : "Flywheel ARN", + "description" : "The ARN of the flywheel associated with the model.", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.flywheelArn", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.jobName", + "label" : "Job name", + "description" : "The identifier of the job", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.jobName", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.outputS3Uri", + "label" : "Output S3 URI", + "description" : "S3 location where the date will be written.", + "optional" : false, + "constraints" : { + "notEmpty" : true + }, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.outputS3Uri", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.outputKmsKeyId", + "label" : "Output Kms Key Id", + "description" : "KMS key id used for encrypt the output result.", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.outputKmsKeyId", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.tags", + "label" : "Tags", + "description" : "Tags to associate with the document classification job", + "optional" : true, + "feel" : "required", + "group" : "input", + "binding" : { + "name" : "input.tags", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.volumeKmsKeyId", + "label" : "Volume Kms Key Id", + "description" : "KMS that Amazon Comprehend uses to encrypt data on the storage volume attached to the ML compute instance.", + "optional" : true, + "feel" : "optional", + "group" : "input", + "binding" : { + "name" : "input.volumeKmsKeyId", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.securityGroupIds", + "label" : "Security group ids", + "description" : "The ID number for a security group on an instance of your private VPC.", + "optional" : true, + "feel" : "required", + "group" : "input", + "binding" : { + "name" : "input.securityGroupIds", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "input.subnets", + "label" : "Subnets", + "description" : "The ID for each subnet being used in your private VPC.", + "optional" : true, + "feel" : "required", + "group" : "input", + "binding" : { + "name" : "input.subnets", + "type" : "zeebe:input" + }, + "condition" : { + "property" : "input.type", + "equals" : "async", + "type" : "simple" + }, + "type" : "String" + }, { + "id" : "resultVariable", + "label" : "Result variable", + "description" : "Name of variable to store the response in", + "group" : "output", + "binding" : { + "key" : "resultVariable", + "type" : "zeebe:taskHeader" + }, + "type" : "String" + }, { + "id" : "resultExpression", + "label" : "Result expression", + "description" : "Expression to map the response into process variables", + "feel" : "required", + "group" : "output", + "binding" : { + "key" : "resultExpression", + "type" : "zeebe:taskHeader" + }, + "type" : "Text" + }, { + "id" : "errorExpression", + "label" : "Error expression", + "description" : "Expression to handle errors. Details in the documentation.", + "feel" : "required", + "group" : "error", + "binding" : { + "key" : "errorExpression", + "type" : "zeebe:taskHeader" + }, + "type" : "Text" + }, { + "id" : "retryCount", + "label" : "Retries", + "description" : "Number of retries", + "value" : "3", + "feel" : "optional", + "group" : "retries", + "binding" : { + "property" : "retries", + "type" : "zeebe:taskDefinition" + }, + "type" : "String" + }, { + "id" : "retryBackoff", + "label" : "Retry backoff", + "description" : "ISO-8601 duration to wait between retries", + "value" : "PT0S", + "feel" : "optional", + "group" : "retries", + "binding" : { + "key" : "retryBackoff", + "type" : "zeebe:taskHeader" + }, + "type" : "String" + } ], + "icon" : { + "contents" : "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iODBweCIgaGVpZ2h0PSI4MHB4IiB2aWV3Qm94PSIwIDAgODAgODAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+SWNvbi1BcmNoaXRlY3R1cmUvNjQvQXJjaF9BbWF6b24tQ29tcHJlaGVuZF82NDwvdGl0bGU+CiAgICA8ZyBpZD0iSWNvbi1BcmNoaXRlY3R1cmUvNjQvQXJjaF9BbWF6b24tQ29tcHJlaGVuZF82NCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9Ikljb24tQXJjaGl0ZWN0dXJlLUJHLzY0L01hY2hpbmUtTGVhcm5pbmciIGZpbGw9IiM5OTY5ZjciPgogICAgICAgICAgICA8cmVjdCBpZD0iUmVjdGFuZ2xlIiB4PSIwIiB5PSIwIiB3aWR0aD0iODAiIGhlaWdodD0iODAiPjwvcmVjdD4KICAgICAgICA8L2c+CiAgICAgICAgPHBhdGggZD0iTTE2Ljk5OTk2NTMsNTQgTDMyLjk5OTg1NDIsNTQgTDMyLjk5OTg1NDIsNTIgTDE2Ljk5OTk2NTMsNTIgTDE2Ljk5OTk2NTMsNTQgWiBNMzMuOTk5ODQ3Myw0NyBMNDIuOTk5Nzg0OCw0NyBMNDIuOTk5Nzg0OCw0NSBMMzMuOTk5ODQ3Myw0NSBMMzMuOTk5ODQ3Myw0NyBaIE0xNi45OTk5NjUzLDQ3IEwzMS45OTk4NjEyLDQ3IEwzMS45OTk4NjEyLDQ1IEwxNi45OTk5NjUzLDQ1IEwxNi45OTk5NjUzLDQ3IFogTTE2Ljk5OTk2NTMsMjYgTDI5Ljk5OTg3NSwyNiBMMjkuOTk5ODc1LDI0IEwxNi45OTk5NjUzLDI0IEwxNi45OTk5NjUzLDI2IFogTTYzLjAxMDY0NTksNTQuMDc5IEM2Mi44OTc2NDY3LDU0LjE1NiA2Mi43NTI2NDc3LDU0LjIxOCA2Mi42MDM2NDg3LDU0LjI4NyBDNjIuMDc1NjUyNCw1NC41MzQgNjEuMzUyNjU3NCw1NC44NzMgNjEuMDYxNjU5NCw1NS42NTEgQzYxLjAyMDY1OTcsNTUuNzYzIDYwLjk5OTY1OTgsNTUuODgxIDYwLjk5OTY1OTgsNTYgTDYwLjk5OTY1OTgsNjAgTDU4Ljk5OTY3MzcsNjAgTDU4Ljk5OTY3MzcsNTEgTDYxLjk5OTY1MjksNTEgTDYxLjk5OTY1MjksNDkgTDUzLjk5OTcwODQsNDkgTDUzLjk5OTcwODQsNTEgTDU2Ljk5OTY4NzYsNTEgTDU2Ljk5OTY4NzYsNjAgTDU0Ljk5OTcwMTUsNjAgTDU0Ljk5OTcwMTUsNTYgQzU0Ljk5OTcwMTUsNTUuODgxIDU0Ljk3ODcwMTYsNTUuNzYzIDU0LjkzNjcwMTksNTUuNjUxIEM1NC42NDY3MDM5LDU0Ljg3MyA1My45MjM3MDksNTQuNTM0IDUzLjM5NTcxMjYsNTQuMjg3IEM1My4yNDY3MTM3LDU0LjIxOCA1My4xMDE3MTQ3LDU0LjE1NiA1Mi45ODg3MTU0LDU0LjA3OSBDNTAuMDI0NzM2LDUyLjAyNCA0OC41NDM3NDYzLDQ4LjUwNSA0OS4xMjQ3NDIzLDQ0Ljg5NiBDNDkuNzcyNzM3OCw0MC44NjMgNTMuMjA1NzEzOSwzNy42MjEgNTcuMjg2Njg1NiwzNy4xODggQzU3LjQ5NTY4NDIsMzcuMTY1IDU4LjUwNzY3NzEsMzcuMTY2IDU4LjcxMjY3NTcsMzcuMTg4IEM2Mi43OTM2NDc0LDM3LjYyMSA2Ni4yMjY2MjM1LDQwLjg2MyA2Ni44NzQ2MTksNDQuODk2IEM2Ny40NTU2MTUsNDguNTA1IDY1Ljk3NDYyNTMsNTIuMDI0IDYzLjAxMDY0NTksNTQuMDc5IEw2My4wMTA2NDU5LDU0LjA3OSBaIE02OC44NDk2MDUzLDQ0LjU3OSBDNjguMDYwNjEwOCwzOS42NyA2My44ODU2Mzk4LDM1LjcyNiA1OC45MjI2NzQyLDM1LjE5OCBDNTguNTc2Njc2NiwzNS4xNjIgNTcuNDIwNjg0NywzNS4xNjIgNTcuMDc2Njg3MSwzNS4xOTggTDU3LjA3NTY4NzEsMzUuMTk4IEM1Mi4xMTM3MjE1LDM1LjcyNiA0Ny45Mzg3NTA1LDM5LjY3IDQ3LjE0OTc1Niw0NC41NzkgQzQ2LjQ0NTc2MDksNDguOTU1IDQ4LjI0Njc0ODQsNTMuMjI1IDUxLjg1MDcyMzMsNTUuNzIyIEM1Mi4wNDU3MjIsNTUuODU3IDUyLjI5MDcyMDMsNTUuOTc5IDUyLjU0NzcxODUsNTYuMDk5IEM1Mi42ODQ3MTc2LDU2LjE2MyA1Mi44OTM3MTYxLDU2LjI2IDUyLjk5OTcxNTQsNTYuMzE0IEw1Mi45OTk3MTU0LDYxIEM1Mi45OTk3MTU0LDYxLjU1MiA1My40NDY3MTIzLDYyIDUzLjk5OTcwODQsNjIgTDYxLjk5OTY1MjksNjIgQzYyLjU1MjY0OSw2MiA2Mi45OTk2NDU5LDYxLjU1MiA2Mi45OTk2NDU5LDYxIEw2Mi45OTk2NDU5LDU2LjMzIEM2My4xMjA2NDUxLDU2LjI1MyA2My4zMTk2NDM3LDU2LjE2MSA2My40NTE2NDI4LDU2LjA5OSBDNjMuNzA4NjQxLDU1Ljk3OSA2My45NTM2MzkzLDU1Ljg1NyA2NC4xNDg2MzgsNTUuNzIyIEM2Ny43NTI2MTI5LDUzLjIyNSA2OS41NTM2MDA0LDQ4Ljk1NSA2OC44NDk2MDUzLDQ0LjU3OSBMNjguODQ5NjA1Myw0NC41NzkgWiBNNTkuNDY0NjcwNSw2NiBMNTYuNTM0NjkwOCw2NiBMNTUuODY3Njk1NSw2NSBMNjAuMTMxNjY1OSw2NSBMNTkuNDY0NjcwNSw2NiBaIE02MS45OTk2NTI5LDYzIEw1My45OTk3MDg0LDYzIEM1My42MzA3MTEsNjMgNTMuMjkxNzEzMyw2My4yMDMgNTMuMTE3NzE0NSw2My41MjggQzUyLjk0MzcxNTgsNjMuODU0IDUyLjk2MzcxNTYsNjQuMjQ4IDUzLjE2NzcxNDIsNjQuNTU1IEw1NS4xNjc3MDAzLDY3LjU1NSBDNTUuMzUzNjk5LDY3LjgzMyA1NS42NjU2OTY5LDY4IDU1Ljk5OTY5NDUsNjggTDU5Ljk5OTY2NjgsNjggQzYwLjMzMzY2NDUsNjggNjAuNjQ1NjYyMyw2Ny44MzMgNjAuODMxNjYxLDY3LjU1NSBMNjIuODMxNjQ3MSw2NC41NTUgQzYzLjAzNTY0NTcsNjQuMjQ4IDYzLjA1NTY0NTYsNjMuODU0IDYyLjg4MTY0NjgsNjMuNTI4IEM2Mi43MDc2NDgsNjMuMjAzIDYyLjM2ODY1MDMsNjMgNjEuOTk5NjUyOSw2MyBMNjEuOTk5NjUyOSw2MyBaIE0xNi45OTk5NjUzLDQwIEw0Mi45OTk3ODQ4LDQwIEw0Mi45OTk3ODQ4LDM4IEwxNi45OTk5NjUzLDM4IEwxNi45OTk5NjUzLDQwIFogTTI1Ljk5OTkwMjgsMzMgTDQyLjk5OTc4NDgsMzMgTDQyLjk5OTc4NDgsMzEgTDI1Ljk5OTkwMjgsMzEgTDI1Ljk5OTkwMjgsMzMgWiBNMTYuOTk5OTY1MywzMyBMMjMuOTk5OTE2NywzMyBMMjMuOTk5OTE2NywzMSBMMTYuOTk5OTY1MywzMSBMMTYuOTk5OTY1MywzMyBaIE0zNS45OTk4MzM0LDE1LjQxNCBMNDQuNTg1NzczOCwyNCBMMzUuOTk5ODMzNCwyNCBMMzUuOTk5ODMzNCwxNS40MTQgWiBNNDUuOTk5NzY0LDYxIEwxMy45OTk5ODYxLDYxIEwxMy45OTk5ODYxLDE0LjAwNSBMMzMuOTk5ODQ3MywxNCBMMzMuOTk5ODQ3MywyNSBDMzMuOTk5ODQ3MywyNS41NTIgMzQuNDQ2ODQ0MiwyNiAzNC45OTk4NDAzLDI2IEw0NS45OTk3NjQsMjYgTDQ1Ljk5OTc2NCwzOCBMNDcuOTk5NzUwMSwzOCBMNDcuOTk5NzUwMSwyNSBMNDcuOTkwNzUwMSwyNSBDNDcuOTg5NzUwMSwyNC43NCA0Ny44OTc3NTA4LDI0LjQ4NCA0Ny43MDY3NTIxLDI0LjI5MyBMMzUuNzA2ODM1NCwxMi4yOTMgQzM1LjUxNjgzNjcsMTIuMTAyIDM1LjI2MDgzODUsMTIuMDEgMzQuOTk5ODQwMywxMi4wMSBMMzQuOTk5ODQwMywxMiBMMTMsMTIuMDA1IEMxMi40NDY5OTY5LDEyLjAwNSAxMiwxMi40NTMgMTIsMTMuMDA1IEwxMiw2MiBDMTIsNjIuNTUyIDEyLjQ0Njk5NjksNjMgMTMsNjMgTDQ2Ljk5OTc1Nyw2MyBDNDcuNTUyNzUzMiw2MyA0Ny45OTk3NTAxLDYyLjU1MiA0Ny45OTk3NTAxLDYyIEw0Ny45OTk3NTAxLDU2IEw0NS45OTk3NjQsNTYgTDQ1Ljk5OTc2NCw2MSBaIiBpZD0iQW1hem9uLUNvbXByZWhlbmRfSWNvbl82NF9TcXVpZCIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgPC9nPgo8L3N2Zz4=" + } +} \ No newline at end of file diff --git a/connectors/aws/aws-comprehend/pom.xml b/connectors/aws/aws-comprehend/pom.xml new file mode 100644 index 0000000000..f37eb0e18d --- /dev/null +++ b/connectors/aws/aws-comprehend/pom.xml @@ -0,0 +1,78 @@ + + 4.0.0 + + + io.camunda.connector + connector-aws-parent + 8.7.0-SNAPSHOT + ../pom.xml + + + connector-aws-comprehend + Camunda AWS Comprehend Connector + connector-aws-comprehend + jar + + + + Camunda Self-Managed Free Edition license + https://camunda.com/legal/terms/cloud-terms-and-conditions/camunda-cloud-self-managed-free-edition-terms/ + + + Camunda Self-Managed Enterprise Edition license + + + + + Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + under one or more contributor license agreements. Licensed under a proprietary license. + See the License.txt file for more information. You may not use this file + except in compliance with the proprietary license. + + + + + io.camunda.connector + connector-aws-base + ${project.version} + + + + com.amazonaws + aws-java-sdk-comprehend + ${version.aws-java-sdk} + + + + + + + + io.camunda.connector + element-template-generator-maven-plugin + ${project.version} + + + + io.camunda.connector.comprehend.ComprehendConnectorFunction + + + io.camunda.connectors.AWSCOMPREHEND.v1 + aws-comprehend-outbound-connector.json + + + true + + + + io.camunda.connector:connector-aws-base + + + + + + + + + diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/ComprehendConnectorFunction.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/ComprehendConnectorFunction.java new file mode 100644 index 0000000000..e45716a7b5 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/ComprehendConnectorFunction.java @@ -0,0 +1,72 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend; + +import io.camunda.connector.api.annotation.OutboundConnector; +import io.camunda.connector.api.outbound.OutboundConnectorContext; +import io.camunda.connector.api.outbound.OutboundConnectorFunction; +import io.camunda.connector.comprehend.caller.AsyncComprehendCaller; +import io.camunda.connector.comprehend.caller.SyncComprehendCaller; +import io.camunda.connector.comprehend.model.ComprehendAsyncRequestData; +import io.camunda.connector.comprehend.model.ComprehendRequest; +import io.camunda.connector.comprehend.model.ComprehendRequestData; +import io.camunda.connector.comprehend.model.ComprehendSyncRequestData; +import io.camunda.connector.comprehend.supplier.ComprehendClientSupplier; +import io.camunda.connector.generator.java.annotation.ElementTemplate; + +@OutboundConnector( + name = "AWS Comprehend", + inputVariables = {"authentication", "configuration", "input"}, + type = "io.camunda:aws-comprehend:1") +@ElementTemplate( + id = "io.camunda.connectors.AWSCOMPREHEND.v1", + name = "AWS Comprehend Outbound Connector", + description = "Execute Comprehend models", + inputDataClass = ComprehendRequest.class, + version = 1, + propertyGroups = { + @ElementTemplate.PropertyGroup(id = "authentication", label = "Authentication"), + @ElementTemplate.PropertyGroup(id = "configuration", label = "Configuration"), + @ElementTemplate.PropertyGroup(id = "input", label = "Configure input") + }, + documentationRef = + "https://docs.camunda.io/docs/next/components/connectors/out-of-the-box-connectors/amazon-comprehend/", + icon = "icon.svg") +public class ComprehendConnectorFunction implements OutboundConnectorFunction { + + private final ComprehendClientSupplier clientSupplier; + + private final SyncComprehendCaller syncComprehendCaller; + + private final AsyncComprehendCaller asyncComprehendCaller; + + public ComprehendConnectorFunction( + ComprehendClientSupplier clientSupplier, + SyncComprehendCaller syncComprehendCaller, + AsyncComprehendCaller asyncComprehendCaller) { + this.clientSupplier = clientSupplier; + this.syncComprehendCaller = syncComprehendCaller; + this.asyncComprehendCaller = asyncComprehendCaller; + } + + public ComprehendConnectorFunction() { + this.clientSupplier = new ComprehendClientSupplier(); + this.syncComprehendCaller = new SyncComprehendCaller(); + this.asyncComprehendCaller = new AsyncComprehendCaller(); + } + + @Override + public Object execute(OutboundConnectorContext context) { + var request = context.bindVariables(ComprehendRequest.class); + ComprehendRequestData requestData = request.getInput(); + if (requestData instanceof ComprehendSyncRequestData syncRequestData) { + return syncComprehendCaller.call(clientSupplier.getSyncClient(request), syncRequestData); + } + return asyncComprehendCaller.call( + clientSupplier.getAsyncClient(request), (ComprehendAsyncRequestData) requestData); + } +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/AsyncComprehendCaller.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/AsyncComprehendCaller.java new file mode 100644 index 0000000000..b209b576a7 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/AsyncComprehendCaller.java @@ -0,0 +1,118 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.caller; + +import com.amazonaws.services.comprehend.AmazonComprehendClient; +import com.amazonaws.services.comprehend.model.*; +import com.amazonaws.util.CollectionUtils; +import io.camunda.connector.comprehend.model.ComprehendAsyncRequestData; +import io.camunda.connector.comprehend.model.ComprehendInputFormat; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AsyncComprehendCaller + implements ComprehendCaller { + + public static final String VPC_CONFIG_EXCEPTION_MSG = + "Or both VpcConfig fields SecurityGroupIds and Subnets or none"; + + private static final Logger LOGGER = LoggerFactory.getLogger(AsyncComprehendCaller.class); + + @Override + public StartDocumentClassificationJobResult call( + AmazonComprehendClient client, ComprehendAsyncRequestData asyncRequest) { + LOGGER.debug( + "Starting async comprehend task for document classification with request data: {}", + asyncRequest); + var docClassificationRequest = new StartDocumentClassificationJobRequest(); + + if (StringUtils.isNotBlank(asyncRequest.clientRequestToken())) { + docClassificationRequest.withClientRequestToken(asyncRequest.clientRequestToken()); + } + + docClassificationRequest.withDataAccessRoleArn(asyncRequest.dataAccessRoleArn()); + + if (StringUtils.isNotBlank(asyncRequest.documentClassifierArn())) { + docClassificationRequest.withDocumentClassifierArn(asyncRequest.documentClassifierArn()); + } + + if (StringUtils.isNotBlank(asyncRequest.flywheelArn())) { + docClassificationRequest.withFlywheelArn(asyncRequest.flywheelArn()); + } + + docClassificationRequest.withInputDataConfig(prepareInputConfig(asyncRequest)); + + if (StringUtils.isNotBlank(asyncRequest.jobName())) { + docClassificationRequest.withJobName(asyncRequest.jobName()); + } + + docClassificationRequest.withOutputDataConfig(prepareOutputDataConf(asyncRequest)); + + if (asyncRequest.tags() != null && !asyncRequest.tags().isEmpty()) { + docClassificationRequest.withTags(prepareTags(asyncRequest)); + } + + if (StringUtils.isNotBlank(asyncRequest.volumeKmsKeyId())) { + docClassificationRequest.withVolumeKmsKeyId(asyncRequest.volumeKmsKeyId()); + } + + docClassificationRequest.withVpcConfig(prepareVpcConfig(asyncRequest)); + + return client.startDocumentClassificationJob(docClassificationRequest); + } + + private InputDataConfig prepareInputConfig(ComprehendAsyncRequestData request) { + var inputConfig = + new InputDataConfig() + .withS3Uri(request.inputS3Uri()) + .withDocumentReaderConfig(prepareDocumentReaderConfig(request).orElse(null)); + + if (request.comprehendInputFormat() != ComprehendInputFormat.NO_DATA) { + inputConfig.withInputFormat(request.comprehendInputFormat().name()); + } + + return inputConfig; + } + + private OutputDataConfig prepareOutputDataConf(ComprehendAsyncRequestData request) { + var outputConf = new OutputDataConfig().withS3Uri(request.outputS3Uri()); + + if (StringUtils.isNotBlank(request.outputKmsKeyId())) { + outputConf.withKmsKeyId(request.outputKmsKeyId()); + } + + return outputConf; + } + + private List prepareTags(ComprehendAsyncRequestData request) { + return request.tags().entrySet().stream().filter(Objects::nonNull).map(this::creatTag).toList(); + } + + private Tag creatTag(Map.Entry entry) { + return new Tag().withKey(entry.getKey()).withValue(entry.getValue()); + } + + private VpcConfig prepareVpcConfig(ComprehendAsyncRequestData request) { + List groupIds = request.securityGroupIds(); + List subnets = request.subnets(); + + if (CollectionUtils.isNullOrEmpty(groupIds) && CollectionUtils.isNullOrEmpty(subnets)) { + return null; + } + + if (!CollectionUtils.isNullOrEmpty(groupIds) && !CollectionUtils.isNullOrEmpty(subnets)) { + return new VpcConfig().withSecurityGroupIds(groupIds).withSubnets(subnets); + } else { + LOGGER.warn(VPC_CONFIG_EXCEPTION_MSG); + throw new IllegalArgumentException(VPC_CONFIG_EXCEPTION_MSG); + } + } +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/ComprehendCaller.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/ComprehendCaller.java new file mode 100644 index 0000000000..37be1c9541 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/ComprehendCaller.java @@ -0,0 +1,74 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.caller; + +import static io.camunda.connector.comprehend.model.ComprehendDocumentReadAction.TEXTRACT_ANALYZE_DOCUMENT; + +import com.amazonaws.AmazonWebServiceResult; +import com.amazonaws.ResponseMetadata; +import com.amazonaws.services.comprehend.AmazonComprehendClient; +import com.amazonaws.services.comprehend.model.DocumentReadFeatureTypes; +import com.amazonaws.services.comprehend.model.DocumentReaderConfig; +import io.camunda.connector.comprehend.model.ComprehendDocumentReadAction; +import io.camunda.connector.comprehend.model.ComprehendDocumentReadMode; +import io.camunda.connector.comprehend.model.ComprehendRequestData; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public interface ComprehendCaller< + T extends AmazonWebServiceResult, R extends ComprehendRequestData> { + + String READ_ACTION_WITHOUT_FEATURES_EX = + "If you chose TEXTRACT_ANALYZE_DOCUMENT as the read action, " + + "you must specify one feature types"; + + Logger LOGGER = LoggerFactory.getLogger(ComprehendCaller.class); + + int INITIAL_FEATURES_CAPACITY = 2; + + T call(AmazonComprehendClient client, R requestData); + + default Optional prepareDocumentReaderConfig( + ComprehendRequestData requestData) { + if (requestData.getDocumentReadAction() == (ComprehendDocumentReadAction.NO_DATA)) { + return Optional.empty(); + } + + var documentReaderConfig = + new DocumentReaderConfig() + .withDocumentReadAction(requestData.getDocumentReadAction().name()); + + if (requestData.getDocumentReadMode() != (ComprehendDocumentReadMode.NO_DATA)) { + documentReaderConfig.withDocumentReadMode(requestData.getDocumentReadMode().name()); + } + + if (requestData.getDocumentReadAction() == TEXTRACT_ANALYZE_DOCUMENT) { + List features = prepareFeatures(requestData); + if (features.isEmpty()) { + LOGGER.warn("DocumentReadAction: TEXTRACT_ANALYZE_DOCUMENT, but features not selected."); + throw new IllegalArgumentException(READ_ACTION_WITHOUT_FEATURES_EX); + } + documentReaderConfig.withFeatureTypes(features); + } + + return Optional.of(documentReaderConfig); + } + + default List prepareFeatures(ComprehendRequestData requestData) { + List features = new ArrayList<>(INITIAL_FEATURES_CAPACITY); + if (requestData.getFeatureTypeForms()) { + features.add(DocumentReadFeatureTypes.FORMS.name()); + } + if (requestData.getFeatureTypeTables()) { + features.add(DocumentReadFeatureTypes.TABLES.name()); + } + return features; + } +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/SyncComprehendCaller.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/SyncComprehendCaller.java new file mode 100644 index 0000000000..9351e5fff7 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/caller/SyncComprehendCaller.java @@ -0,0 +1,35 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.caller; + +import com.amazonaws.services.comprehend.AmazonComprehendClient; +import com.amazonaws.services.comprehend.model.ClassifyDocumentRequest; +import com.amazonaws.services.comprehend.model.ClassifyDocumentResult; +import io.camunda.connector.comprehend.model.ComprehendSyncRequestData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SyncComprehendCaller + implements ComprehendCaller { + + private static final Logger LOGGER = LoggerFactory.getLogger(SyncComprehendCaller.class); + + @Override + public ClassifyDocumentResult call( + AmazonComprehendClient client, ComprehendSyncRequestData requestData) { + LOGGER.debug( + "Starting sync comprehend task for document classification with request data: {}", + requestData); + ClassifyDocumentRequest classifyDocumentRequest = + new ClassifyDocumentRequest() + .withText(requestData.text()) + .withEndpointArn(requestData.endpointArn()) + .withDocumentReaderConfig(prepareDocumentReaderConfig(requestData).orElse(null)); + + return client.classifyDocument(classifyDocumentRequest); + } +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendAsyncRequestData.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendAsyncRequestData.java new file mode 100644 index 0000000000..61b1e579bf --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendAsyncRequestData.java @@ -0,0 +1,200 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.camunda.connector.feel.annotation.FEEL; +import io.camunda.connector.generator.dsl.Property; +import io.camunda.connector.generator.java.annotation.TemplateProperty; +import io.camunda.connector.generator.java.annotation.TemplateSubType; +import jakarta.validation.constraints.NotNull; +import java.util.List; +import java.util.Map; + +@JsonIgnoreProperties(ignoreUnknown = true) +@TemplateSubType(id = "async", label = "Async") +public record ComprehendAsyncRequestData( + @TemplateProperty( + id = "async.documentReadAction", + label = "Document read action", + group = "input", + type = TemplateProperty.PropertyType.Dropdown, + defaultValue = "TEXTRACT_DETECT_DOCUMENT_TEXT", + feel = Property.FeelMode.disabled, + constraints = @TemplateProperty.PropertyConstraints(notEmpty = true), + choices = { + @TemplateProperty.DropdownPropertyChoice( + value = "TEXTRACT_DETECT_DOCUMENT_TEXT", + label = "Detect document text"), + @TemplateProperty.DropdownPropertyChoice( + value = "TEXTRACT_ANALYZE_DOCUMENT", + label = "Analyze document"), + @TemplateProperty.DropdownPropertyChoice(value = "NO_DATA", label = "None") + }, + description = + "Textract API operation that uses to extract text from PDF files and image files.", + tooltip = + "more info") + @NotNull + ComprehendDocumentReadAction documentReadAction, + @TemplateProperty( + id = "async.documentReadMode", + label = "Document read mode", + group = "input", + type = TemplateProperty.PropertyType.Dropdown, + defaultValue = "SERVICE_DEFAULT", + feel = Property.FeelMode.disabled, + constraints = @TemplateProperty.PropertyConstraints(notEmpty = true), + choices = { + @TemplateProperty.DropdownPropertyChoice( + value = "SERVICE_DEFAULT", + label = "Service default"), + @TemplateProperty.DropdownPropertyChoice( + value = "FORCE_DOCUMENT_READ_ACTION", + label = "Force document read action"), + @TemplateProperty.DropdownPropertyChoice(value = "NO_DATA", label = "None"), + }, + description = "Determines the text extraction actions for PDF files.") + @NotNull + ComprehendDocumentReadMode documentReadMode, + @TemplateProperty( + id = "async.featureTypeTables", + label = "Analyze tables", + group = "input", + type = TemplateProperty.PropertyType.Boolean, + defaultValueType = TemplateProperty.DefaultValueType.Boolean, + defaultValue = "false") + @NotNull + boolean featureTypeTables, + @TemplateProperty( + id = "async.featureTypeForms", + label = "Analyze forms", + group = "input", + type = TemplateProperty.PropertyType.Boolean, + defaultValueType = TemplateProperty.DefaultValueType.Boolean, + defaultValue = "false") + @NotNull + boolean featureTypeForms, + @TemplateProperty( + label = "Input S3 URI", + group = "input", + description = "The Amazon S3 URI for the input data.") + @NotNull + String inputS3Uri, + @TemplateProperty( + label = "Input Format", + group = "input", + type = TemplateProperty.PropertyType.Dropdown, + feel = Property.FeelMode.disabled, + defaultValue = "ONE_DOC_PER_FILE", + choices = { + @TemplateProperty.DropdownPropertyChoice( + value = "ONE_DOC_PER_FILE", + label = "Each file is considered a separate document"), + @TemplateProperty.DropdownPropertyChoice( + value = "ONE_DOC_PER_LINE", + label = "Each line in a file is considered a separate document"), + @TemplateProperty.DropdownPropertyChoice(value = "NO_DATA", label = "None") + }, + description = "Specifies how the text in an input file should be processed.") + ComprehendInputFormat comprehendInputFormat, + @TemplateProperty( + group = "input", + label = "Client request token", + description = "A unique identifier for the request.", + optional = true) + String clientRequestToken, + @TemplateProperty( + group = "input", + label = "Data Access Role ARN", + description = + "The ARN of the IAM role that grants Amazon Comprehend read access to your input data.") + @NotNull + String dataAccessRoleArn, + @TemplateProperty( + group = "input", + label = "Document Classifier ARN", + description = "The ARN of the document classifier to use to process the job", + optional = true) + String documentClassifierArn, + @TemplateProperty( + group = "input", + label = "Flywheel ARN", + description = "The ARN of the flywheel associated with the model.", + optional = true) + String flywheelArn, + @TemplateProperty( + group = "input", + label = "Job name", + description = "The identifier of the job", + optional = true) + String jobName, + @TemplateProperty( + group = "input", + label = "Output S3 URI", + description = "S3 location where the date will be written.") + @NotNull + String outputS3Uri, + @TemplateProperty( + group = "input", + label = "Output Kms Key Id", + description = "KMS key id used for encrypt the output result.", + optional = true) + String outputKmsKeyId, + @FEEL + @TemplateProperty( + group = "input", + label = "Tags", + description = "Tags to associate with the document classification job", + optional = true, + feel = Property.FeelMode.required) + Map tags, + @TemplateProperty( + group = "input", + label = "Volume Kms Key Id", + description = + "KMS that Amazon Comprehend uses to encrypt data on the storage volume " + + "attached to the ML compute instance.", + optional = true) + String volumeKmsKeyId, + @FEEL + @TemplateProperty( + group = "input", + label = "Security group ids", + description = "The ID number for a security group on an instance of your private VPC.", + optional = true, + feel = Property.FeelMode.required) + List securityGroupIds, + @FEEL + @TemplateProperty( + group = "input", + label = "Subnets", + description = "The ID for each subnet being used in your private VPC.", + optional = true, + feel = Property.FeelMode.required) + List subnets) + implements ComprehendRequestData { + @Override + public ComprehendDocumentReadAction getDocumentReadAction() { + return documentReadAction; + } + + @Override + public ComprehendDocumentReadMode getDocumentReadMode() { + return documentReadMode; + } + + @Override + public boolean getFeatureTypeTables() { + return featureTypeTables; + } + + @Override + public boolean getFeatureTypeForms() { + return featureTypeForms; + } +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendDocumentReadAction.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendDocumentReadAction.java new file mode 100644 index 0000000000..221525a677 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendDocumentReadAction.java @@ -0,0 +1,13 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.model; + +public enum ComprehendDocumentReadAction { + TEXTRACT_DETECT_DOCUMENT_TEXT, + TEXTRACT_ANALYZE_DOCUMENT, + NO_DATA +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendDocumentReadMode.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendDocumentReadMode.java new file mode 100644 index 0000000000..31834747ad --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendDocumentReadMode.java @@ -0,0 +1,13 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.model; + +public enum ComprehendDocumentReadMode { + SERVICE_DEFAULT, + FORCE_DOCUMENT_READ_ACTION, + NO_DATA +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendInputFormat.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendInputFormat.java new file mode 100644 index 0000000000..8ce61cb0d2 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendInputFormat.java @@ -0,0 +1,13 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.model; + +public enum ComprehendInputFormat { + ONE_DOC_PER_FILE, + ONE_DOC_PER_LINE, + NO_DATA; +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendRequest.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendRequest.java new file mode 100644 index 0000000000..3155410953 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendRequest.java @@ -0,0 +1,52 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.model; + +import io.camunda.connector.aws.model.impl.AwsBaseRequest; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +public class ComprehendRequest extends AwsBaseRequest { + @Valid @NotNull private ComprehendRequestData input; + + public ComprehendRequest() {} + + public ComprehendRequestData getInput() { + return input; + } + + public void setInput(ComprehendRequestData input) { + this.input = input; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + ComprehendRequest that = (ComprehendRequest) o; + + return new EqualsBuilder().appendSuper(super.equals(o)).append(input, that.input).isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37).appendSuper(super.hashCode()).append(input).toHashCode(); + } + + @Override + public String toString() { + return "ComprehendRequest{" + "input=" + input + '}'; + } +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendRequestData.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendRequestData.java new file mode 100644 index 0000000000..e8c5411f29 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendRequestData.java @@ -0,0 +1,31 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.camunda.connector.generator.java.annotation.TemplateDiscriminatorProperty; + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") +@JsonSubTypes({ + @JsonSubTypes.Type(value = ComprehendSyncRequestData.class, name = "sync"), + @JsonSubTypes.Type(value = ComprehendAsyncRequestData.class, name = "async") +}) +@JsonIgnoreProperties(ignoreUnknown = true) +@TemplateDiscriminatorProperty(name = "type", group = "input", label = "Execution type") +public sealed interface ComprehendRequestData + permits ComprehendSyncRequestData, ComprehendAsyncRequestData { + + ComprehendDocumentReadAction getDocumentReadAction(); + + ComprehendDocumentReadMode getDocumentReadMode(); + + boolean getFeatureTypeTables(); + + boolean getFeatureTypeForms(); +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendSyncRequestData.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendSyncRequestData.java new file mode 100644 index 0000000000..f0fc56bcd4 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/model/ComprehendSyncRequestData.java @@ -0,0 +1,128 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.camunda.connector.generator.dsl.Property; +import io.camunda.connector.generator.java.annotation.TemplateProperty; +import io.camunda.connector.generator.java.annotation.TemplateSubType; +import jakarta.validation.constraints.NotNull; + +@JsonIgnoreProperties(ignoreUnknown = true) +@TemplateSubType(id = "sync", label = "Sync") +public record ComprehendSyncRequestData( + @TemplateProperty( + group = "input", + label = "Text", + description = "The document text to be analyzed.") + @NotNull + String text, + @TemplateProperty( + id = "sync.documentReadAction", + label = "Document read action", + group = "input", + type = TemplateProperty.PropertyType.Dropdown, + defaultValue = "TEXTRACT_DETECT_DOCUMENT_TEXT", + feel = Property.FeelMode.disabled, + constraints = @TemplateProperty.PropertyConstraints(notEmpty = true), + choices = { + @TemplateProperty.DropdownPropertyChoice( + value = "TEXTRACT_DETECT_DOCUMENT_TEXT", + label = "Detect document text"), + @TemplateProperty.DropdownPropertyChoice( + value = "TEXTRACT_ANALYZE_DOCUMENT", + label = "Analyze document"), + @TemplateProperty.DropdownPropertyChoice(value = "NO_DATA", label = "None") + }, + description = + "Textract API operation that uses to extract text from PDF files and image files.", + tooltip = + "more info") + @NotNull + ComprehendDocumentReadAction documentReadAction, + @TemplateProperty( + id = "sync.documentReadMode", + label = "Document read mode", + group = "input", + type = TemplateProperty.PropertyType.Dropdown, + defaultValue = "SERVICE_DEFAULT", + feel = Property.FeelMode.disabled, + constraints = @TemplateProperty.PropertyConstraints(notEmpty = true), + choices = { + @TemplateProperty.DropdownPropertyChoice( + value = "SERVICE_DEFAULT", + label = "Service default"), + @TemplateProperty.DropdownPropertyChoice( + value = "FORCE_DOCUMENT_READ_ACTION", + label = "Force document read action"), + @TemplateProperty.DropdownPropertyChoice(value = "NO_DATA", label = "None"), + }, + description = "Determines the text extraction actions for PDF files.") + @NotNull + ComprehendDocumentReadMode documentReadMode, + @TemplateProperty( + id = "sync.featureTypeTables", + label = "Analyze tables", + group = "input", + type = TemplateProperty.PropertyType.Boolean, + defaultValueType = TemplateProperty.DefaultValueType.Boolean, + defaultValue = "false") + @NotNull + boolean featureTypeTables, + @TemplateProperty( + id = "sync.featureTypeForms", + label = "Analyze forms", + group = "input", + type = TemplateProperty.PropertyType.Boolean, + defaultValueType = TemplateProperty.DefaultValueType.Boolean, + defaultValue = "false") + @NotNull + boolean featureTypeForms, + @TemplateProperty( + group = "input", + label = "Endpoint ARN", + description = "The Amazon Resource Number (ARN) of the endpoint.") + @NotNull + String endpointArn) + implements ComprehendRequestData { + @Override + public ComprehendDocumentReadAction getDocumentReadAction() { + return documentReadAction; + } + + @Override + public ComprehendDocumentReadMode getDocumentReadMode() { + return documentReadMode; + } + + @Override + public boolean getFeatureTypeTables() { + return featureTypeTables; + } + + @Override + public boolean getFeatureTypeForms() { + return featureTypeForms; + } + + @Override + public String toString() { + return "ComprehendSyncRequestData{" + + ", documentReadAction=" + + documentReadAction + + ", documentReadMode=" + + documentReadMode + + ", featureTypeTables=" + + featureTypeTables + + ", featureTypeForms=" + + featureTypeForms + + ", endpointArn='" + + endpointArn + + '\'' + + '}'; + } +} diff --git a/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/supplier/ComprehendClientSupplier.java b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/supplier/ComprehendClientSupplier.java new file mode 100644 index 0000000000..22ecabfe85 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/java/io/camunda/connector/comprehend/supplier/ComprehendClientSupplier.java @@ -0,0 +1,31 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.supplier; + +import com.amazonaws.services.comprehend.AmazonComprehendAsyncClient; +import com.amazonaws.services.comprehend.AmazonComprehendClient; +import io.camunda.connector.aws.CredentialsProviderSupport; +import io.camunda.connector.comprehend.model.ComprehendRequest; + +public class ComprehendClientSupplier { + + public AmazonComprehendClient getSyncClient(ComprehendRequest comprehendRequest) { + return (AmazonComprehendClient) + AmazonComprehendClient.builder() + .withCredentials(CredentialsProviderSupport.credentialsProvider(comprehendRequest)) + .withRegion(comprehendRequest.getConfiguration().region()) + .build(); + } + + public AmazonComprehendAsyncClient getAsyncClient(ComprehendRequest comprehendRequest) { + return (AmazonComprehendAsyncClient) + AmazonComprehendAsyncClient.asyncBuilder() + .withCredentials(CredentialsProviderSupport.credentialsProvider(comprehendRequest)) + .withRegion(comprehendRequest.getConfiguration().region()) + .build(); + } +} diff --git a/connectors/aws/aws-comprehend/src/main/resources/META-INF/services/io.camunda.connector.api.outbound.OutboundConnectorFunction b/connectors/aws/aws-comprehend/src/main/resources/META-INF/services/io.camunda.connector.api.outbound.OutboundConnectorFunction new file mode 100644 index 0000000000..f8287cd853 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/resources/META-INF/services/io.camunda.connector.api.outbound.OutboundConnectorFunction @@ -0,0 +1 @@ +io.camunda.connector.comprehend.ComprehendConnectorFunction \ No newline at end of file diff --git a/connectors/aws/aws-comprehend/src/main/resources/icon.svg b/connectors/aws/aws-comprehend/src/main/resources/icon.svg new file mode 100644 index 0000000000..bcf8e06888 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/main/resources/icon.svg @@ -0,0 +1,10 @@ + + + Icon-Architecture/64/Arch_Amazon-Comprehend_64 + + + + + + + \ No newline at end of file diff --git a/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/ComprehendConnectorFunctionTest.java b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/ComprehendConnectorFunctionTest.java new file mode 100644 index 0000000000..03379e1e56 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/ComprehendConnectorFunctionTest.java @@ -0,0 +1,81 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import com.amazonaws.services.comprehend.AmazonComprehendAsyncClient; +import com.amazonaws.services.comprehend.AmazonComprehendClient; +import com.amazonaws.services.comprehend.model.ClassifyDocumentRequest; +import com.amazonaws.services.comprehend.model.ClassifyDocumentResult; +import com.amazonaws.services.comprehend.model.StartDocumentClassificationJobRequest; +import com.amazonaws.services.comprehend.model.StartDocumentClassificationJobResult; +import io.camunda.connector.comprehend.caller.AsyncComprehendCaller; +import io.camunda.connector.comprehend.caller.SyncComprehendCaller; +import io.camunda.connector.comprehend.model.ComprehendRequest; +import io.camunda.connector.comprehend.supplier.ComprehendClientSupplier; +import io.camunda.connector.test.outbound.OutboundConnectorContextBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class ComprehendConnectorFunctionTest { + + @Mock private ComprehendClientSupplier clientSupplier; + private ComprehendConnectorFunction comprehendConnectorFunction; + + @BeforeEach + void setUp() { + comprehendConnectorFunction = + new ComprehendConnectorFunction( + clientSupplier, new SyncComprehendCaller(), new AsyncComprehendCaller()); + } + + @Test + void executeSyncRequest() { + var outBounderContext = prepareConnectorContext(ComprehendTestUtils.SYNC_EXECUTION_JSON); + + AmazonComprehendClient syncClient = Mockito.mock(AmazonComprehendClient.class); + when(syncClient.classifyDocument(any(ClassifyDocumentRequest.class))) + .thenReturn(new ClassifyDocumentResult()); + + when(clientSupplier.getSyncClient(any(ComprehendRequest.class))).thenReturn(syncClient); + + var result = comprehendConnectorFunction.execute(outBounderContext); + assertThat(result).isInstanceOf(ClassifyDocumentResult.class); + } + + @Test + void executeAsyncRequest() { + var outBounderContext = prepareConnectorContext(ComprehendTestUtils.ASYNC_EXECUTION_JSON); + + AmazonComprehendAsyncClient asyncClient = Mockito.mock(AmazonComprehendAsyncClient.class); + when(asyncClient.startDocumentClassificationJob( + any(StartDocumentClassificationJobRequest.class))) + .thenReturn(new StartDocumentClassificationJobResult()); + + when(clientSupplier.getAsyncClient(any(ComprehendRequest.class))).thenReturn(asyncClient); + + var result = comprehendConnectorFunction.execute(outBounderContext); + assertThat(result).isInstanceOf(StartDocumentClassificationJobResult.class); + } + + private OutboundConnectorContextBuilder.TestConnectorContext prepareConnectorContext( + String json) { + return OutboundConnectorContextBuilder.create() + .secret("ACCESS_KEY", ComprehendTestUtils.ACTUAL_ACCESS_KEY) + .secret("SECRET_KEY", ComprehendTestUtils.ACTUAL_SECRET_KEY) + .variables(json) + .build(); + } +} diff --git a/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/ComprehendTestUtils.java b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/ComprehendTestUtils.java new file mode 100644 index 0000000000..02aff10c1b --- /dev/null +++ b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/ComprehendTestUtils.java @@ -0,0 +1,73 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend; + +public class ComprehendTestUtils { + + public static final String ACTUAL_ACCESS_KEY = "DDDCCCBBBBAAAA"; + public static final String ACTUAL_SECRET_KEY = "AAAABBBBCCCDDD"; + + public static final String SYNC_EXECUTION_JSON = + """ + { + "input":{ + "accept":"application/json", + "type":"sync", + "documentReadAction":"TEXTRACT_DETECT_DOCUMENT_TEXT", + "documentReadMode":"SERVICE_DEFAULT", + "featureTypeTables":true, + "featureTypeForms":true, + "text":"plain text", + "endpointArn":"endpoint" + }, + "configuration":{ + "region":"eu-central-1" + }, + "authentication":{ + "type":"defaultCredentialsChain", + "accessKey":"{{secrets.ACCESS_KEY}}", + "secretKey":"{{secrets.SECRET_KEY}}" + } + } + + """; + + public static final String ASYNC_EXECUTION_JSON = + """ + { + "input":{ + "accept":"application/json", + "type":"async", + "documentReadAction":"TEXTRACT_DETECT_DOCUMENT_TEXT", + "documentReadMode":"SERVICE_DEFAULT", + "featureTypeTables":true, + "featureTypeForms":true, + "inputS3Uri":"input", + "comprehendInputFormat":"ONE_DOC_PER_FILE", + "clientRequestToken":"token", + "dataAccessRoleArn":"arn", + "documentClassifierArn":"arn", + "flywheelArn":"arn", + "jobName":"job", + "outputS3Uri":"output", + "outputKmsKeyId":"kms", + "tags": {"status": "active"}, + "volumeKmsKeyId": "volumeKms", + "securityGroupIds": ["sc-1"], + "subnets":["sb-1"] + }, + "configuration":{ + "region":"eu-central-1" + }, + "authentication":{ + "type":"defaultCredentialsChain", + "accessKey":"{{secrets.ACCESS_KEY}}", + "secretKey":"{{secrets.SECRET_KEY}}" + } + } + """; +} diff --git a/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/AsyncComprehendCallerTest.java b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/AsyncComprehendCallerTest.java new file mode 100644 index 0000000000..85b70e4b7d --- /dev/null +++ b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/AsyncComprehendCallerTest.java @@ -0,0 +1,148 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.caller; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.amazonaws.services.comprehend.AmazonComprehendClient; +import com.amazonaws.services.comprehend.model.*; +import io.camunda.connector.comprehend.model.ComprehendAsyncRequestData; +import io.camunda.connector.comprehend.model.ComprehendDocumentReadAction; +import io.camunda.connector.comprehend.model.ComprehendDocumentReadMode; +import io.camunda.connector.comprehend.model.ComprehendInputFormat; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class AsyncComprehendCallerTest { + + private final AsyncComprehendCaller asyncCaller = new AsyncComprehendCaller(); + + @Test + void callWithAllFields() { + String tagKey = "key"; + String tagValue = "value"; + var asyncRequest = + new ComprehendAsyncRequestData( + ComprehendDocumentReadAction.TEXTRACT_ANALYZE_DOCUMENT, + ComprehendDocumentReadMode.SERVICE_DEFAULT, + true, + true, + "input", + ComprehendInputFormat.ONE_DOC_PER_FILE, + "token", + "roleArn", + "classifierArn", + "flywheelArn", + "jobName", + "output", + "outputKms", + Map.of(tagKey, tagValue), + "volumeKms", + List.of("seg-1"), + List.of("subnet-1")); + + var docClassificationRequest = + new StartDocumentClassificationJobRequest() + .withClientRequestToken(asyncRequest.clientRequestToken()) + .withDataAccessRoleArn(asyncRequest.dataAccessRoleArn()) + .withDocumentClassifierArn(asyncRequest.documentClassifierArn()) + .withFlywheelArn(asyncRequest.flywheelArn()) + .withInputDataConfig( + new InputDataConfig() + .withS3Uri(asyncRequest.inputS3Uri()) + .withDocumentReaderConfig( + asyncCaller.prepareDocumentReaderConfig(asyncRequest).get()) + .withInputFormat(asyncRequest.comprehendInputFormat().name())) + .withJobName(asyncRequest.jobName()) + .withOutputDataConfig( + new OutputDataConfig() + .withS3Uri(asyncRequest.outputS3Uri()) + .withKmsKeyId(asyncRequest.outputKmsKeyId())) + .withTags(List.of(new Tag().withKey(tagKey).withValue(tagValue))) + .withVolumeKmsKeyId(asyncRequest.volumeKmsKeyId()) + .withVpcConfig( + new VpcConfig() + .withSecurityGroupIds(asyncRequest.securityGroupIds()) + .withSubnets(asyncRequest.subnets())); + var client = Mockito.mock(AmazonComprehendClient.class); + + when(client.startDocumentClassificationJob(docClassificationRequest)).thenReturn(null); + asyncCaller.call(client, asyncRequest); + + verify(client).startDocumentClassificationJob(docClassificationRequest); + } + + @Test + void callWithMandatoryFields() { + var asyncRequest = + new ComprehendAsyncRequestData( + ComprehendDocumentReadAction.NO_DATA, + ComprehendDocumentReadMode.NO_DATA, + false, + false, + "input", + ComprehendInputFormat.NO_DATA, + "", + "roleArn", + "", + "", + "", + "output", + "", + Map.of(), + "", + List.of(), + List.of()); + + var docClassificationRequest = + new StartDocumentClassificationJobRequest() + .withDataAccessRoleArn(asyncRequest.dataAccessRoleArn()) + .withInputDataConfig(new InputDataConfig().withS3Uri(asyncRequest.inputS3Uri())) + .withOutputDataConfig(new OutputDataConfig().withS3Uri(asyncRequest.outputS3Uri())); + + var client = Mockito.mock(AmazonComprehendClient.class); + when(client.startDocumentClassificationJob(docClassificationRequest)).thenReturn(null); + asyncCaller.call(client, asyncRequest); + + verify(client).startDocumentClassificationJob(docClassificationRequest); + } + + @Test + void callWithPartiallyFilledVPCShouldThrowEx() { + var asyncRequest = + new ComprehendAsyncRequestData( + ComprehendDocumentReadAction.NO_DATA, + ComprehendDocumentReadMode.NO_DATA, + false, + false, + "input", + ComprehendInputFormat.NO_DATA, + "", + "roleArn", + "", + "", + "", + "output", + "", + Map.of(), + "", + List.of("seg-1"), + List.of()); + + AmazonComprehendClient asyncClient = Mockito.mock(AmazonComprehendClient.class); + + Exception ex = + assertThrows( + IllegalArgumentException.class, () -> asyncCaller.call(asyncClient, asyncRequest)); + assertThat(ex.getMessage()).isEqualTo(AsyncComprehendCaller.VPC_CONFIG_EXCEPTION_MSG); + } +} diff --git a/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/ComprehendCallerTest.java b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/ComprehendCallerTest.java new file mode 100644 index 0000000000..292d0603b4 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/ComprehendCallerTest.java @@ -0,0 +1,127 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.caller; + +import static io.camunda.connector.comprehend.caller.ComprehendCaller.READ_ACTION_WITHOUT_FEATURES_EX; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import com.amazonaws.services.comprehend.model.DocumentReadFeatureTypes; +import com.amazonaws.services.comprehend.model.DocumentReaderConfig; +import com.amazonaws.services.comprehend.model.StartDocumentClassificationJobResult; +import io.camunda.connector.comprehend.model.ComprehendDocumentReadAction; +import io.camunda.connector.comprehend.model.ComprehendDocumentReadMode; +import io.camunda.connector.comprehend.model.ComprehendSyncRequestData; +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.Test; + +class ComprehendCallerTest { + + private final ComprehendCaller + caller = (a1, a2) -> null; + + @Test + void prepareDocumentReaderConfigWithEmptyReadActionReturnEmpty() { + ComprehendSyncRequestData request = prepareSyncData(true, true); + Optional documentReader = caller.prepareDocumentReaderConfig(request); + assertThat(documentReader).isEmpty(); + } + + @Test + void + prepareDocumentReaderConfigWithTextractAnalyzeDocActionWithoutSelectedFeaturesShouldThrowEx() { + var request = + new ComprehendSyncRequestData( + "text", + ComprehendDocumentReadAction.TEXTRACT_ANALYZE_DOCUMENT, + ComprehendDocumentReadMode.NO_DATA, + false, + false, + "arn"); + + Exception ex = + assertThrows( + IllegalArgumentException.class, () -> caller.prepareDocumentReaderConfig(request)); + assertThat(ex.getMessage()).isEqualTo(READ_ACTION_WITHOUT_FEATURES_EX); + } + + @Test + void + prepareDocumentReaderConfigWithReadActionNonEqualTextractAnalyzeDocActionShouldNotAddFeatures() { + var request = + new ComprehendSyncRequestData( + "text", + ComprehendDocumentReadAction.TEXTRACT_DETECT_DOCUMENT_TEXT, + ComprehendDocumentReadMode.NO_DATA, + true, + true, + "arn"); + + Optional readerConfig = caller.prepareDocumentReaderConfig(request); + assertThat(readerConfig) + .contains( + new DocumentReaderConfig() + .withDocumentReadAction(request.getDocumentReadAction().name())); + } + + @Test + void prepareDocumentReaderConfigWithALLSelectedFields() { + var request = + new ComprehendSyncRequestData( + "text", + ComprehendDocumentReadAction.TEXTRACT_ANALYZE_DOCUMENT, + ComprehendDocumentReadMode.SERVICE_DEFAULT, + true, + true, + "arn"); + Optional readerConfig = caller.prepareDocumentReaderConfig(request); + assertThat(readerConfig) + .contains( + new DocumentReaderConfig() + .withDocumentReadAction(request.getDocumentReadAction().name()) + .withDocumentReadMode(request.getDocumentReadMode().name()) + .withFeatureTypes( + List.of( + DocumentReadFeatureTypes.FORMS.name(), + DocumentReadFeatureTypes.TABLES.name()))); + } + + @Test + void prepareFeaturesWithAllUnselectedFeatures() { + ComprehendSyncRequestData request = prepareSyncData(false, false); + List features = caller.prepareFeatures(request); + + assertThat(features.size()).isZero(); + } + + @Test + void prepareFeaturesWithAllSelectedFeatures() { + ComprehendSyncRequestData request = prepareSyncData(true, true); + List features = caller.prepareFeatures(request); + + assertThat(features.size()).isEqualTo(2); + } + + @Test + void prepareFeaturesWithOneSelectedFeature() { + ComprehendSyncRequestData request = prepareSyncData(true, false); + List features = caller.prepareFeatures(request); + + assertThat(features.size()).isOne(); + } + + private ComprehendSyncRequestData prepareSyncData(boolean tables, boolean forms) { + return new ComprehendSyncRequestData( + "text", + ComprehendDocumentReadAction.NO_DATA, + ComprehendDocumentReadMode.NO_DATA, + tables, + forms, + "arn::"); + } +} diff --git a/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/SyncComprehendCallerTest.java b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/SyncComprehendCallerTest.java new file mode 100644 index 0000000000..41218e6a15 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/caller/SyncComprehendCallerTest.java @@ -0,0 +1,75 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.caller; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.amazonaws.services.comprehend.AmazonComprehendClient; +import com.amazonaws.services.comprehend.model.ClassifyDocumentRequest; +import com.amazonaws.services.comprehend.model.ClassifyDocumentResult; +import io.camunda.connector.comprehend.model.ComprehendDocumentReadAction; +import io.camunda.connector.comprehend.model.ComprehendDocumentReadMode; +import io.camunda.connector.comprehend.model.ComprehendSyncRequestData; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class SyncComprehendCallerTest { + + private final SyncComprehendCaller syncCaller = new SyncComprehendCaller(); + + @Test + void callWithNonEmptyReadConf() { + var syncRequest = + new ComprehendSyncRequestData( + "text", + ComprehendDocumentReadAction.TEXTRACT_ANALYZE_DOCUMENT, + ComprehendDocumentReadMode.SERVICE_DEFAULT, + true, + true, + "arn::"); + + var expectedClassifyDocumentRequest = + new ClassifyDocumentRequest() + .withText(syncRequest.text()) + .withEndpointArn(syncRequest.endpointArn()) + .withDocumentReaderConfig(syncCaller.prepareDocumentReaderConfig(syncRequest).get()); + + AmazonComprehendClient syncClient = Mockito.mock(AmazonComprehendClient.class); + when(syncClient.classifyDocument(expectedClassifyDocumentRequest)) + .thenReturn(new ClassifyDocumentResult()); + + syncCaller.call(syncClient, syncRequest); + + verify(syncClient).classifyDocument(expectedClassifyDocumentRequest); + } + + @Test + void callWithEmptyReadConfig() { + var syncRequest = + new ComprehendSyncRequestData( + "text", + ComprehendDocumentReadAction.NO_DATA, + ComprehendDocumentReadMode.NO_DATA, + false, + false, + "arn::"); + + var expectedClassifyDocumentRequest = + new ClassifyDocumentRequest() + .withText(syncRequest.text()) + .withEndpointArn(syncRequest.endpointArn()); + + AmazonComprehendClient syncClient = Mockito.mock(AmazonComprehendClient.class); + when(syncClient.classifyDocument(expectedClassifyDocumentRequest)) + .thenReturn(new ClassifyDocumentResult()); + + syncCaller.call(syncClient, syncRequest); + + verify(syncClient).classifyDocument(expectedClassifyDocumentRequest); + } +} diff --git a/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/supplier/ComprehendClientSupplierTest.java b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/supplier/ComprehendClientSupplierTest.java new file mode 100644 index 0000000000..9940e2e151 --- /dev/null +++ b/connectors/aws/aws-comprehend/src/test/java/io/camunda/connector/comprehend/supplier/ComprehendClientSupplierTest.java @@ -0,0 +1,47 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.comprehend.supplier; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.amazonaws.services.comprehend.AmazonComprehendAsyncClient; +import com.amazonaws.services.comprehend.AmazonComprehendClient; +import io.camunda.connector.aws.model.impl.AwsBaseConfiguration; +import io.camunda.connector.comprehend.model.ComprehendRequest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ComprehendClientSupplierTest { + + private ComprehendRequest request; + + private ComprehendClientSupplier clientSupplier; + + @BeforeEach + public void setUp() { + request = new ComprehendRequest(); + request.setConfiguration(new AwsBaseConfiguration("region", "")); + + clientSupplier = new ComprehendClientSupplier(); + } + + @Test + void getSyncClient() { + var amazonComprehendClient = clientSupplier.getSyncClient(request); + + assertThat(amazonComprehendClient).isNotNull(); + assertThat(amazonComprehendClient).isInstanceOf(AmazonComprehendClient.class); + } + + @Test + void getAsyncClient() { + var amazonComprehendAsyncClient = clientSupplier.getAsyncClient(request); + + assertThat(amazonComprehendAsyncClient).isNotNull(); + assertThat(amazonComprehendAsyncClient).isInstanceOf(AmazonComprehendAsyncClient.class); + } +} diff --git a/connectors/aws/pom.xml b/connectors/aws/pom.xml index fdffb6d515..bd2cc77c92 100644 --- a/connectors/aws/pom.xml +++ b/connectors/aws/pom.xml @@ -25,6 +25,7 @@ aws-sqs aws-sagemaker aws-bedrock + aws-comprehend aws-textract