").deidentifyText(deidentifyTextRequest);
-
- // Step 5: Print the response
- System.out.println("Deidentify text Response: " + deidentifyTextResponse);
- }
-}
-
-```
-
-## An [example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/detect/DeidentifyTextExample.java) of deidentify text:
-```java
-import java.util.ArrayList;
-import java.util.List;
-
-import com.skyflow.enums.DetectEntities;
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.vault.detect.DateTransformation;
-import com.skyflow.vault.detect.DeidentifyTextRequest;
-import com.skyflow.vault.detect.DeidentifyTextResponse;
-import com.skyflow.vault.detect.TokenFormat;
-import com.skyflow.vault.detect.Transformations;
-
-/**
- * Skyflow Deidentify Text Example
- *
- * This example demonstrates how to use the Skyflow SDK to deidentify text data
- * across multiple vaults. It includes:
- * 1. Setting up credentials and vault configurations.
- * 2. Creating a Skyflow client with multiple vaults.
- * 3. Performing deidentify of text with various options.
- * 4. Handling responses and errors.
- */
-
-public class DeidentifyTextExample {
- public static void main(String[] args) throws SkyflowException {
-
- // Step 1: Initialize the Skyflow client by configuring the credentials & vault config.
-
- // Step 2: Configuring the different options for deidentify
-
- // Replace with the entity you want to detect
- List detectEntitiesList = new ArrayList<>();
- detectEntitiesList.add(DetectEntities.SSN);
- detectEntitiesList.add(DetectEntities.CREDIT_CARD);
-
- // Replace with the entity you want to detect with vault token
- List vaultTokenList = new ArrayList<>();
- vaultTokenList.add(DetectEntities.SSN);
- vaultTokenList.add(DetectEntities.CREDIT_CARD);
-
- // Configure Token Format
- TokenFormat tokenFormat = TokenFormat.builder()
- .vaultToken(vaultTokenList)
- .build();
-
- // Configure Transformation for deidentified entities
- List detectEntitiesTransformationList = new ArrayList<>();
- detectEntitiesTransformationList.add(DetectEntities.DOB); // Replace with the entity you want to transform
-
- DateTransformation dateTransformation = new DateTransformation(20, 5, detectEntitiesTransformationList);
- Transformations transformations = new Transformations(dateTransformation);
-
- // Step 3: invoking Deidentify text on the vault
- try {
- // Create a deidentify text request for the vault
- DeidentifyTextRequest deidentifyTextRequest = DeidentifyTextRequest.builder()
- .text("My SSN is 123-45-6789 and my card is 4111 1111 1111 1111.") // Replace with your deidentify text
- .entities(detectEntitiesList)
- .tokenFormat(tokenFormat)
- .transformations(transformations)
- .build();
- // Replace `9f27764a10f7946fe56b3258e117` with the actual vault id
- DeidentifyTextResponse deidentifyTextResponse = skyflowClient.detect("9f27764a10f7946fe56b3258e117").deidentifyText(deidentifyTextRequest);
-
- System.out.println("Deidentify text Response: " + deidentifyTextResponse);
- } catch (SkyflowException e) {
- System.err.println("Error occurred during deidentify: ");
- e.printStackTrace(); // Print the exception for debugging purposes
- }
- }
-}
-```
-
-Sample Response:
-```json
-{
- "processedText": "My SSN is [SSN_IWdexZe] and my card is [CREDIT_CARD_rUzMjdQ].",
- "entities": [
- {
- "token": "SSN_IWdexZe",
- "value": "123-45-6789",
- "textIndex": {
- "start": 10,
- "end": 21
- },
- "processedIndex": {
- "start": 10,
- "end": 23
- },
- "entity": "SSN",
- "scores": {
- "SSN": 0.9384
- }
- },
- {
- "token": "CREDIT_CARD_rUzMjdQ",
- "value": "4111 1111 1111 1111",
- "textIndex": {
- "start": 37,
- "end": 56
- },
- "processedIndex": {
- "start": 39,
- "end": 60
- },
- "entity": "CREDIT_CARD",
- "scores": {
- "CREDIT_CARD": 0.9051
- }
- }
- ],
- "wordCount": 9,
- "charCount": 57
-}
-```
-
-## Reidentify Text
-To reidentify text, use the `reidentifyText` method. [`ReidentifyTextRequest`](docs/api_reference.md#reidentifytextrequest) accepts the redacted/deidentified text and optional entity lists controlling which entities to reveal, mask, or keep redacted. Returns a [`ReidentifyTextResponse`](docs/api_reference.md#reidentifytextresponse).
-
-### Construct an reidentify text request
-
-```java
-import com.skyflow.enums.DetectEntities;
-import com.skyflow.vault.detect.ReidentifyTextRequest;
-import com.skyflow.vault.detect.ReidentifyTextResponse;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This example demonstrates how to build a reidentify text request.
- */
-public class ReidentifyTextSchema {
- public static void main(String[] args) {
- // Step 1: Initialize the Skyflow client by configuring the credentials & vault config.
-
- // Step 2: Configuring the different options for reidentify
- List maskedEntity = new ArrayList<>();
- maskedEntity.add(DetectEntities.CREDIT_CARD); // Replace with the entity you want to mask
-
- List plainTextEntity = new ArrayList<>();
- plainTextEntity.add(DetectEntities.SSN); // Replace with the entity you want to keep in plain text
-
- // List redactedEntity = new ArrayList<>();
- // redactedEntity.add(DetectEntities.SSN); // Replace with the entity you want to redact
-
-
- // Step 3: Create a reidentify text request with the configured entities
- ReidentifyTextRequest reidentifyTextRequest = ReidentifyTextRequest.builder()
- .text("My SSN is [SSN_IWdexZe] and my card is [CREDIT_CARD_rUzMjdQ].") // Replace with your deidentify text
- .maskedEntities(maskedEntity)
-// .redactedEntities(redactedEntity)
- .plainTextEntities(plainTextEntity)
- .build();
-
- // Step 4: Invoke reidentify text on the vault
- ReidentifyTextResponse reidentifyTextResponse = skyflowClient.detect("").reidentifyText(reidentifyTextRequest);
- System.out.println("Reidentify text Response: " + reidentifyTextResponse);
- }
-}
-```
-
-## An [example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/detect/ReidentifyTextExample.java) of Reidentify text
-
-```java
-import com.skyflow.enums.DetectEntities;
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.vault.detect.ReidentifyTextRequest;
-import com.skyflow.vault.detect.ReidentifyTextResponse;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Skyflow Reidentify Text Example
- *
- * This example demonstrates how to use the Skyflow SDK to reidentify text data
- * across multiple vaults. It includes:
- * 1. Setting up credentials and vault configurations.
- * 2. Creating a Skyflow client with multiple vaults.
- * 3. Performing reidentify of text with various options.
- * 4. Handling responses and errors.
- */
-
-public class ReidentifyTextExample {
- public static void main(String[] args) throws SkyflowException {
- // Step 1: Initialize the Skyflow client by configuring the credentials & vault config.
-
- // Step 2: Configuring the different options for reidentify
- List maskedEntity = new ArrayList<>();
- maskedEntity.add(DetectEntities.CREDIT_CARD); // Replace with the entity you want to mask
-
- List plainTextEntity = new ArrayList<>();
- plainTextEntity.add(DetectEntities.SSN); // Replace with the entity you want to keep in plain text
-
- try {
- // Step 3: Create a reidentify text request with the configured options
- ReidentifyTextRequest reidentifyTextRequest = ReidentifyTextRequest.builder()
- .text("My SSN is [SSN_IWdexZe] and my card is [CREDIT_CARD_rUzMjdQ].") // Replace with your deidentify text
- .maskedEntities(maskedEntity)
- .plainTextEntities(plainTextEntity)
- .build();
-
- // Step 4: Invoke Reidentify text on the vault
- // Replace `9f27764a10f7946fe56b3258e117` with the actual vault id
- ReidentifyTextResponse reidentifyTextResponse = skyflowClient.detect("9f27764a10f7946fe56b3258e117").reidentifyText(reidentifyTextRequest);
-
- // Handle the response from the reidentify text request
- System.out.println("Reidentify text Response: " + reidentifyTextResponse);
- } catch (SkyflowException e) {
- System.err.println("Error occurred during reidentify : ");
- e.printStackTrace();
- }
- }
-}
-```
-
-Sample Response:
-
-```json
-{
- "processedText":"My SSN is 123-45-6789 and my card is XXXXX1111."
-}
-```
-
-## Deidentify file
-To deidentify files, use the `deidentifyFile` method. [`DeidentifyFileRequest`](docs/api_reference.md#deidentifyfilerequest) accepts a [`FileInput`](docs/api_reference.md#fileinput) and optional parameters controlling entity detection, masking, output format, and async wait time. Supports images, PDFs, audio, documents, spreadsheets, and presentations. Returns a [`DeidentifyFileResponse`](docs/api_reference.md#deidentifyfileresponse).
-
-### AudioBleep
-
-[`AudioBleep`](docs/api_reference.md#audiobleep) controls how detected sensitive audio segments are replaced with a bleep tone. Used in `DeidentifyFileRequest.builder().bleep(audioBleep)` for audio files.
-
-```java
-import com.skyflow.vault.detect.AudioBleep;
-
-AudioBleep audioBleep = AudioBleep.builder()
- .frequency(1000D) // bleep tone frequency in Hz
- .gain(0.5D) // bleep tone gain (volume level)
- .startPadding(0.2D) // silence padding before the bleep (seconds)
- .stopPadding(0.2D) // silence padding after the bleep (seconds)
- .build();
-```
-
-### Construct an deidentify file request
-
-```java
-import com.skyflow.config.Credentials;
-import com.skyflow.config.VaultConfig;
-import com.skyflow.enums.Env;
-import com.skyflow.enums.LogLevel;
-import com.skyflow.enums.MaskingMethod;
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.vault.detect.DeidentifyFileRequest;
-import com.skyflow.vault.detect.DeidentifyFileResponse;
-
-import java.io.File;
-
-/**
- * This example demonstrates how to build a deidentify file request.
- */
-
-public class DeidentifyFileSchema {
-
- public static void main(String[] args) {
- // Step 1: Initialize the Skyflow client by configuring the credentials & vault config.
-
- // Step 2: Create a deidentify file request with all options
-
- // Create file object
- File file = new File(""); // Replace with the path to the file you want to deidentify
-
- // Create file input using the file object
- FileInput fileInput = FileInput.builder()
- .file(file)
- // .filePath("") // Alternatively, you can use .filePath()
- .build();
-
- // Output configuration
- String outputDirectory = ""; // Replace with the desired output directory to save the deidentified file
-
- // Entities to detect
- // List detectEntities = new ArrayList<>();
- // detectEntities.add(DetectEntities.IP_ADDRESS); // Replace with the entities you want to detect
-
- // Image-specific options
- // Boolean outputProcessedImage = true; // Include processed image in output
- // Boolean outputOcrText = true; // Include OCR text in output
- MaskingMethod maskingMethod = MaskingMethod.BLACKBOX; // Masking method for images
-
- // PDF-specific options
- // Integer pixelDensity = 15; // Pixel density for PDF processing
- // Integer maxResolution = 2000; // Max resolution for PDF
-
- // Audio-specific options
- // Boolean outputProcessedAudio = true; // Include processed audio
- // DetectOutputTranscriptions outputTanscription = DetectOutputTranscriptions.PLAINTEXT_TRANSCRIPTION; // Transcription type
-
- // Audio bleep configuration
- // AudioBleep audioBleep = AudioBleep.builder()
- // .frequency(5D) // Pitch in Hz
- // .startPadding(7D) // Padding at start (seconds)
- // .stopPadding(8D) // Padding at end (seconds)
- // .build();
-
- Integer waitTime = 20; // Max wait time for response (max 64 seconds)
-
- DeidentifyFileRequest deidentifyFileRequest = DeidentifyFileRequest.builder()
- .file(fileInput)
- .waitTime(waitTime)
- .entities(detectEntities)
- .outputDirectory(outputDirectory)
- .maskingMethod(maskingMethod)
- // .outputProcessedImage(outputProcessedImage)
- // .outputOcrText(outputOcrText)
- // .pixelDensity(pixelDensity)
- // .maxResolution(maxResolution)
- // .outputProcessedAudio(outputProcessedAudio)
- // .outputTranscription(outputTanscription)
- // .bleep(audioBleep)
- .build();
-
-
- DeidentifyFileResponse deidentifyFileResponse = skyflowClient.detect("").deidentifyFile(deidentifyFileRequest);
- System.out.println("Deidentify file response: " + deidentifyFileResponse.toString());
- }
-}
-```
-
-## An [example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/detect/DeidentifyFileExample.java) of Deidentify file
-
-```java
-import java.io.File;
-
-import com.skyflow.enums.MaskingMethod;
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.vault.detect.DeidentifyFileRequest;
-import com.skyflow.vault.detect.DeidentifyFileResponse;
-
-/**
- * Skyflow Deidentify File Example
- *
- * This example demonstrates how to use the Skyflow SDK to deidentify file
- * It has all available options for deidentifying files.
- * Supported file types: images (jpg, png, etc.), pdf, audio (mp3, wav), documents, spreadsheets, presentations, structured text.
- * It includes:
- * 1. Configure credentials
- * 2. Set up vault configuration
- * 3. Create a deidentify file request with all options
- * 4. Call deidentifyFile to deidentify file.
- * 5. Handle response and errors
- */
-public class DeidentifyFileExample {
-
- public static void main(String[] args) throws SkyflowException {
- // Step 1: Initialize the Skyflow client by configuring the credentials & vault config.
- try {
- // Step 2: Create a deidentify file request with all options
-
-
- // Create file object
- File file = new File("sensitive-folder/personal-info.txt"); // Replace with the path to the file you want to deidentify
-
- // Create file input using the file object
- FileInput fileInput = FileInput.builder()
- .file(file)
- // .filePath("") // Alternatively, you can use .filePath()
- .build();
-
- // Output configuration
- String outputDirectory = "deidentified-file/"; // Replace with the desired output directory to save the deidentified file
-
- // Entities to detect
- // List detectEntities = new ArrayList<>();
- // detectEntities.add(DetectEntities.IP_ADDRESS); // Replace with the entities you want to detect
-
- // Image-specific options
- // Boolean outputProcessedImage = true; // Include processed image in output
- // Boolean outputOcrText = true; // Include OCR text in output
- MaskingMethod maskingMethod = MaskingMethod.BLACKBOX; // Masking method for images
-
- Integer waitTime = 20; // Max wait time for response (max 64 seconds)
-
- DeidentifyFileRequest deidentifyFileRequest = DeidentifyFileRequest.builder()
- .file(fileInput)
- .waitTime(waitTime)
- .outputDirectory(outputDirectory)
- .maskingMethod(maskingMethod)
- .build();
-
- // Step 3: Invoking deidentifyFile
- // Replace `9f27764a10f7946fe56b3258e117` with the actual vault id
- DeidentifyFileResponse deidentifyFileResponse = skyflowClient.detect("9f27764a10f7946fe56b3258e117").deidentifyFile(deidentifyFileRequest);
- System.out.println("Deidentify file response: " + deidentifyFileResponse.toString());
- } catch (SkyflowException e) {
- System.err.println("Error occurred during deidentify file: ");
- e.printStackTrace();
- }
- }
-}
-
-```
-
-Sample response:
-
-```json
-{
- "file": {
- "name": "deidentified.txt",
- "size": 33,
- "type": "",
- "lastModified": 1751355183039
- },
- "fileBase64": "bXkgY2FyZCBudW1iZXIgaXMgW0NSRURJVF",
- "type": "redacted_file",
- "extension": "txt",
- "wordCount": 11,
- "charCount": 61,
- "sizeInKb": 0,
- "entities": [
- {
- "file": "bmFtZTogW05BTUVfMV0gCm==",
- "type": "entities",
- "extension": "json"
- }
- ],
- "runId": "undefined",
- "status": "success"
-}
-
-```
-
-**Supported file types:**
-- Documents: `doc`, `docx`, `pdf`
-- PDFs: `pdf`
-- Images: `bmp`, `jpeg`, `jpg`, `png`, `tif`, `tiff`
-- Structured text: `json`, `xml`
-- Spreadsheets: `csv`, `xls`, `xlsx`
-- Presentations: `ppt`, `pptx`
-- Audio: `mp3`, `wav`
-
-**Note:**
-- Transformations cannot be applied to Documents, Images, or PDFs file formats.
-
-- The `waitTime` option must be ≤ 64 seconds; otherwise, an error is thrown.
-
-- If the API takes more than 64 seconds to process the file, it will return only the run ID in the response.
-
-Sample response (when the API takes more than 64 seconds):
-```json
-{
- "file": null,
- "fileBase64": null,
- "type": null,
- "extension": null,
- "wordCount": null,
- "charCount": null,
- "sizeInKb": null,
- "durationInSeconds": null,
- "pageCount": null,
- "slideCount": null,
- "entities": null,
- "runId": "1273a8c6-c498-4293-a9d6-389864cd3a44",
- "status": "IN_PROGRESS",
- "errors": null
-}
-```
-
-## Get run:
-To retrieve the results of a previously started file deidentification operation, use the `getDetectRun` method. [`GetDetectRunRequest`](docs/api_reference.md#getdetectrunrequest) accepts the `runId` returned from a prior `deidentifyFile` call. Returns a [`DeidentifyFileResponse`](docs/api_reference.md#deidentifyfileresponse).
-
-### Construct an get run request
-
-```java
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.vault.detect.DeidentifyFileResponse;
-import com.skyflow.vault.detect.GetDetectRunRequest;
-
-/**
- * Skyflow Get Detect Run Example
- */
-
-public class GetDetectRunSchema {
-
- public static void main(String[] args) {
- try {
- // Step 1: Initialize the Skyflow client by configuring the credentials & vault config.
-
- // Step 2: Create a get detect run request
- GetDetectRunRequest getDetectRunRequest = GetDetectRunRequest.builder()
- .runId("") // Replace with the runId from deidentifyFile call
- .build();
-
- // Step 3: Call getDetectRun to poll for file processing results
- // Replace with your actual vault ID
- DeidentifyFileResponse deidentifyFileResponse = skyflowClient.detect("").getDetectRun(getDetectRunRequest);
- System.out.println("Get Detect Run Response: " + deidentifyFileResponse);
- } catch (SkyflowException e) {
- System.err.println("Error occurred during get detect run: ");
- e.printStackTrace();
- }
- }
-}
-
-```
-
-## An [example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/detect/GetDetectRunExample.java) of get run
-```java
-import com.skyflow.config.Credentials;
-import com.skyflow.config.VaultConfig;
-import com.skyflow.enums.Env;
-import com.skyflow.enums.LogLevel;
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.vault.detect.DeidentifyFileResponse;
-import com.skyflow.vault.detect.GetDetectRunRequest;
-
-/**
- * Skyflow Get Detect Run Example
- *
- * This example demonstrates how to:
- * 1. Configure credentials
- * 2. Set up vault configuration
- * 3. Create a get detect run request
- * 4. Call getDetectRun to poll for file processing results
- * 5. Handle response and errors
- */
-public class GetDetectRunExample {
- public static void main(String[] args) throws SkyflowException {
- // Step 1: Initialize the Skyflow client by configuring the credentials & vault config.
- try {
-
- // Step 2: Create a get detect run request
- GetDetectRunRequest getDetectRunRequest = GetDetectRunRequest.builder()
- .runId("e0038196-4a20-422b-bad7-e0477117f9bb") // Replace with the runId from deidentifyFile call
- .build();
-
- // Step 3: Call getDetectRun to poll for file processing results
- // Replace `9f27764a10f7946fe56b3258e117` with the actual vault id
- DeidentifyFileResponse deidentifyFileResponse = skyflowClient.detect("9f27764a10f7946fe56b3258e117").getDetectRun(getDetectRunRequest);
- System.out.println("Get Detect Run Response: " + deidentifyFileResponse);
- } catch (SkyflowException e) {
- System.err.println("Error occurred during get detect run: ");
- e.printStackTrace();
- }
- }
-}
-```
-
-Sample Response:
-
-```json
-{
- "file": "bmFtZTogW05BTET0JfMV0K",
- "type": "redacted_file",
- "extension": "txt",
- "wordCount": 11,
- "charCount": 61,
- "sizeInKb": 0.0,
- "entities": [
- {
- "file": "gW05BTUVfMV0gCmNhcmQ0K",
- "type": "entities",
- "extension": "json"
- }
- ],
- "runId": "e0038196-4a20-422b-bad7-e0477117f9bb",
- "status": "success"
-}
-
-```
-
-## Detect response types
-
-The Detect API returns structured objects for detected entities. See the API Reference for full attribute lists: [`EntityInfo`](docs/api_reference.md#entityinfo), [`TextIndex`](docs/api_reference.md#textindex), [`FileEntityInfo`](docs/api_reference.md#fileentityinfo), [`FileInfo`](docs/api_reference.md#fileinfo).
-
-### EntityInfo and TextIndex
-
-[`EntityInfo`](docs/api_reference.md#entityinfo) appears in `DeidentifyTextResponse.getEntities()`. Each entry includes the detected entity type, original value, replacement token, character positions ([`TextIndex`](docs/api_reference.md#textindex)), and confidence scores.
-
-```java
-DeidentifyTextResponse response = skyflowClient.detect("").deidentifyText(request);
-
-for (EntityInfo entity : response.getEntities()) {
- System.out.println("Entity : " + entity.getEntity());
- System.out.println("Value : " + entity.getValue());
- System.out.println("Token : " + entity.getToken());
- System.out.println("Start : " + entity.getTextIndex().getStart());
- System.out.println("End : " + entity.getTextIndex().getEnd());
- System.out.println("Score : " + entity.getScores().get(entity.getEntity()));
-}
-```
-
-### FileEntityInfo and FileInfo
-
-[`FileEntityInfo`](docs/api_reference.md#fileentityinfo) appears in `DeidentifyFileResponse.getEntities()`. [`FileInfo`](docs/api_reference.md#fileinfo) is returned by `DeidentifyFileResponse.getFile()` and contains file metadata.
-
-## Detect enums
-
-See the API Reference for full value descriptions: [`TokenType`](docs/api_reference.md#tokentype), [`DeidentifyFileStatus`](docs/api_reference.md#deidentifyfilestatus), [`DetectOutputTranscriptions`](docs/api_reference.md#detectoutputtranscriptions), [`MaskingMethod`](docs/api_reference.md#maskingmethod), [`DetectEntities`](docs/api_reference.md#detectentities).
-
-### TokenType
-
-[`TokenType`](docs/api_reference.md#tokentype) controls how detected entities are tokenized. Used in `TokenFormat.builder()`.
-
-```java
-import com.skyflow.enums.TokenType;
-
-TokenFormat tokenFormat = TokenFormat.builder()
- .vaultToken(vaultTokenList) // uses VAULT_TOKEN
- .entityOnly(entityOnlyList) // uses ENTITY_ONLY
- .entityUniqueCounter(entityUniqueCounterList) // uses ENTITY_UNIQUE_COUNTER
- .build();
-```
-
-### DeidentifyFileStatus
-
-[`DeidentifyFileStatus`](docs/api_reference.md#deidentifyfilestatus) is returned in `DeidentifyFileResponse.getStatus()` to indicate async processing state.
-
-```java
-import com.skyflow.enums.DeidentifyFileStatus;
-
-DeidentifyFileResponse response = skyflowClient.detect("").getDetectRun(request);
-if (DeidentifyFileStatus.SUCCESS.value().equals(response.getStatus())) {
- // safe to read response.getFile()
-} else if (DeidentifyFileStatus.IN_PROGRESS.value().equals(response.getStatus())) {
- // poll again using the runId
-}
-```
-
-### DetectOutputTranscriptions
-
-[`DetectOutputTranscriptions`](docs/api_reference.md#detectoutputtranscriptions) controls the transcription format for audio file deidentification.
-
-```java
-import com.skyflow.enums.DetectOutputTranscriptions;
-
-DeidentifyFileRequest request = DeidentifyFileRequest.builder()
- .file(fileInput)
- .outputTranscription(DetectOutputTranscriptions.TRANSCRIPTION)
- .build();
-```
-
-# Connections
-
-Skyflow Connections is a gateway service that uses tokenization to securely send and receive data between your systems and first- or third-party services. The [connections](https://github.com/skyflowapi/skyflow-java/tree/main/src/main/java/com/skyflow/vault/connection) module invokes both inbound and/or outbound connections.
-
-- **Inbound connections**: Act as intermediaries between your client and server, tokenizing sensitive data before it reaches your backend, ensuring downstream services handle only tokenized data.
-- **Outbound connections**: Enable secure extraction of data from the vault and transfer it to third-party services via your backend server, such as processing checkout or card issuance flows.
-
-## ConnectionController
-
-`ConnectionController` is the class returned by `skyflowClient.connection()` and `skyflowClient.connection(connectionId)`. All connection operations are called on this object.
-
-```java
-// Uses the default (first configured) connection
-ConnectionController connection = skyflowClient.connection();
-
-// Uses a specific connection by ID
-ConnectionController connection = skyflowClient.connection("");
-```
-
-**Methods:**
-
-| Method | Parameters | Returns | Description |
-|--------|-----------|---------|-------------|
-| `invoke(InvokeConnectionRequest)` | [`InvokeConnectionRequest`](docs/api_reference.md#invokeconnectionrequest) | [`InvokeConnectionResponse`](docs/api_reference.md#invokeconnectionresponse) | Invoke an inbound or outbound connection |
-
-## Invoke a connection
-
-To invoke a connection, use the `invoke` method of the Skyflow client.
-
-### Construct an invoke connection request
-
-```java
-import com.skyflow.enums.RequestMethod;
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.vault.connection.InvokeConnectionRequest;
-import com.skyflow.vault.connection.InvokeConnectionResponse;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * This example demonstrates how to invoke an external connection using the Skyflow SDK, along with corresponding InvokeConnectionRequest schema.
- *
- */
-public class InvokeConnectionSchema {
- public static void main(String[] args) {
- try {
- // Initialize Skyflow client
- // Step 1: Define the request body parameters
- // These are the values you want to send in the request body
- Map requestBody = new HashMap<>();
- requestBody.put("", "");
- requestBody.put("", "");
-
- // Step 2: Define the request headers
- // Add any required headers that need to be sent with the request
- Map requestHeaders = new HashMap<>();
- requestHeaders.put("", "");
- requestHeaders.put("", "");
-
- // Step 3: Define the path parameters
- // Path parameters are part of the URL and typically used in RESTful APIs
- Map pathParams = new HashMap<>();
- pathParams.put("", "");
- pathParams.put("", "");
-
- // Step 4: Define the query parameters
- // Query parameters are included in the URL after a '?' and are used to filter or modify the response
- Map queryParams = new HashMap<>();
- queryParams.put("", "");
- queryParams.put("", "");
-
- // Step 5: Build the InvokeConnectionRequest using the provided parameters
- InvokeConnectionRequest invokeConnectionRequest = InvokeConnectionRequest.builder()
- .method(RequestMethod.POST) // The HTTP method to use for the request (POST in this case)
- .requestBody(requestBody) // The body of the request
- .requestHeaders(requestHeaders) // The headers to include in the request
- .pathParams(pathParams) // The path parameters for the URL
- .queryParams(queryParams) // The query parameters to append to the URL
- .build();
-
- // Step 6: Invoke the connection using the request
- // Replace "" with the actual connection ID you are using
- InvokeConnectionResponse invokeConnectionResponse = skyflowClient.connection("").invoke(invokeConnectionRequest);
-
- // Step 7: Print the response from the invoked connection
- // This response contains the result of the request sent to the external system
- System.out.println(invokeConnectionResponse);
-
- } catch (SkyflowException e) {
- // Step 8: Handle any exceptions that occur during the connection invocation
- System.out.println("Error occurred: ");
- e.printStackTrace(); // Print the exception stack trace for debugging
- }
- }
-}
-```
-
-`method` accepts any [`RequestMethod`](docs/api_reference.md#requestmethod) value (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`). See [`InvokeConnectionRequest`](docs/api_reference.md#invokeconnectionrequest) in the API Reference for all builder options.
-
-**pathParams, queryParams, requestHeader, requestBody** are the JSON objects represented as HashMaps, that will be sent through the connection integration url.
-
-### An [example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/connection/InvokeConnectionExample.java) of invokeConnection
-
-```java
-import com.skyflow.Skyflow;
-import com.skyflow.config.ConnectionConfig;
-import com.skyflow.config.Credentials;
-import com.skyflow.enums.LogLevel;
-import com.skyflow.enums.RequestMethod;
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.vault.connection.InvokeConnectionRequest;
-import com.skyflow.vault.connection.InvokeConnectionResponse;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * This example demonstrates how to invoke an external connection using the Skyflow SDK.
- * It configures a connection, sets up the request, and sends a POST request to the external service.
- *
- * 1. Initialize Skyflow client with connection details.
- * 2. Define the request body, headers, and method.
- * 3. Execute the connection request.
- * 4. Print the response from the invoked connection.
- */
-public class InvokeConnectionExample {
- public static void main(String[] args) {
- try {
- // Initialize Skyflow client
- // Step 1: Set up credentials and connection configuration
- // Load credentials from a JSON file (you need to provide the correct path)
- Credentials credentials = new Credentials();
- credentials.setPath("/path/to/credentials.json");
-
- // Define the connection configuration (URL and credentials)
- ConnectionConfig connectionConfig = new ConnectionConfig();
- connectionConfig.setConnectionId(""); // Replace with actual connection ID
- connectionConfig.setConnectionUrl("https://connection.url.com"); // Replace with actual connection URL
- connectionConfig.setCredentials(credentials); // Set credentials for the connection
-
- // Initialize the Skyflow client with the connection configuration
- Skyflow skyflowClient = Skyflow.builder()
- .setLogLevel(LogLevel.DEBUG) // Set log level to DEBUG for detailed logs
- .addConnectionConfig(connectionConfig) // Add connection configuration to client
- .build(); // Build the Skyflow client instance
-
- // Step 2: Define the request body and headers
- // Map for request body parameters
- Map requestBody = new HashMap<>();
- requestBody.put("card_number", "4337-1696-5866-0865"); // Example card number
- requestBody.put("ssn", "524-41-4248"); // Example SSN
-
- // Map for request headers
- Map requestHeaders = new HashMap<>();
- requestHeaders.put("Content-Type", "application/json"); // Set content type for the request
-
- // Step 3: Build the InvokeConnectionRequest with required parameters
- // Set HTTP method to POST, include the request body and headers
- InvokeConnectionRequest invokeConnectionRequest = InvokeConnectionRequest.builder()
- .method(RequestMethod.POST) // HTTP POST method
- .requestBody(requestBody) // Add request body parameters
- .requestHeaders(requestHeaders) // Add headers
- .build(); // Build the request
-
- // Step 4: Invoke the connection and capture the response
- // Replace "" with the actual connection ID
- InvokeConnectionResponse invokeConnectionResponse = skyflowClient.connection("").invoke(invokeConnectionRequest);
-
- // Step 5: Print the response from the connection invocation
- System.out.println(invokeConnectionResponse); // Print the response to the console
-
- } catch (SkyflowException e) {
- // Step 6: Handle any exceptions that occur during the connection invocation
- System.out.println("Error occurred: ");
- e.printStackTrace(); // Print the exception stack trace for debugging
- }
- }
-}
-```
-
-Sample response:
-
-```json
-{
- "data": {
- "card_number": "4337-1696-5866-0865",
- "ssn": "524-41-4248"
- },
- "metadata": {
- "requestId": "4a3453b5-7aa4-4373-98d7-cf102b1f6f97"
- }
-}
-```
-
-# Authenticate with bearer tokens
-
-This section covers methods for generating and managing tokens to authenticate API calls:
-
-- **Generate a bearer token**:
- Enable the creation of bearer tokens using service account credentials. These tokens, valid for 60 minutes, provide secure access to Vault services and management APIs based on the service account's permissions. Use this for general API calls when you only need basic authentication without additional context or role-based restrictions.
-- **Generate a bearer token with context**:
- Support embedding context values into bearer tokens, enabling dynamic access control and the ability to track end-user identity. These tokens include context claims and allow flexible authorization for Vault services. Use this when policies depend on specific contextual attributes or when tracking end-user identity is required.
-- **Generate a scoped bearer token**:
- Facilitate the creation of bearer tokens with role-specific access, ensuring permissions are limited to the operations allowed by the designated role. This is particularly useful for service accounts with multiple roles. Use this to enforce fine-grained role-based access control, ensuring tokens only grant permissions for a specific role.
-- **Generate signed data tokens**:
- Add an extra layer of security by digitally signing data tokens with the service account's private key. These signed tokens can be securely detokenized, provided the necessary bearer token and permissions are available. Use this to add cryptographic protection to sensitive data, enabling secure detokenization with verified integrity and authenticity.
-
-## Generate a bearer token
-
-The [Service Account](https://github.com/skyflowapi/skyflow-java/tree/main/src/main/java/com/skyflow/serviceaccount/util) Java module generates service account tokens using a service account credentials file, which is provided when a service account is created. The tokens generated by this module are valid for 60 minutes and can be used to make API calls to the [Data](https://docs.skyflow.com/record/) and [Management](https://docs.skyflow.com/management/) APIs, depending on the permissions assigned to the service account.
-
-The `BearerToken` utility class generates bearer tokens using a credentials JSON file. Alternatively, you can pass the credentials as a string.
-
-[Example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/serviceaccount/BearerTokenGenerationExample.java):
-
-```java
-/**
- * Example program to generate a Bearer Token using Skyflow's BearerToken utility.
- * The token can be generated in two ways:
- * 1. Using the file path to a credentials.json file.
- * 2. Using the JSON content of the credentials file as a string.
- */
-public class BearerTokenGenerationExample {
- public static void main(String[] args) {
- // Variable to store the generated token
- String token = null;
-
- // Example 1: Generate Bearer Token using a credentials.json file
- try {
- // Specify the full file path to the credentials.json file
- String filePath = "";
-
- // Check if the token is either not initialized or has expired
- if (Token.isExpired(token)) {
- // Create a BearerToken object using the credentials file
- BearerToken bearerToken = BearerToken.builder()
- .setCredentials(new File(filePath)) // Set credentials from the file path
- .build();
-
- // Generate a new Bearer Token
- token = bearerToken.getBearerToken();
- }
-
- // Print the generated Bearer Token to the console
- System.out.println("Generated Bearer Token (from file): " + token);
- } catch (SkyflowException e) {
- // Handle any exceptions encountered during the token generation process
- e.printStackTrace();
- }
-
- // Example 2: Generate Bearer Token using the credentials JSON as a string
- try {
- // Provide the credentials JSON content as a string
- String fileContents = "";
-
- // Check if the token is either not initialized or has expired
- if (Token.isExpired(token)) {
- // Create a BearerToken object using the credentials string
- BearerToken bearerToken = BearerToken.builder()
- .setCredentials(fileContents) // Set credentials from the string
- .build();
-
- // Generate a new Bearer Token
- token = bearerToken.getBearerToken();
- }
-
- // Print the generated Bearer Token to the console
- System.out.println("Generated Bearer Token (from string): " + token);
- } catch (SkyflowException e) {
- // Handle any exceptions encountered during the token generation process
- e.printStackTrace();
- }
- }
-}
-```
-
-## Generate bearer tokens with context
-
-**Context-aware authorization** embeds context values into a bearer token during its generation so you can reference those values in your policies. This enables more flexible access controls, such as helping you track end-user identity when making API calls using service accounts, and facilitates using signed data tokens during detokenization.
-
-A service account with the `context_id` identifier generates bearer tokens containing context information, represented as a JWT claim in a Skyflow-generated bearer token. Tokens generated from such service accounts include a `context_identifier` claim, are valid for 60 minutes, and can be used to make API calls to the Data and Management APIs, depending on the service account's permissions.
-
-The `setCtx()` method accepts either a **String** or a **`Map`**:
-
-**String context** — use when your policy references a single context value:
-
-```java
-BearerToken token = BearerToken.builder()
- .setCredentials(new File(filePath))
- .setCtx("user_12345")
- .build();
-```
-
-**JSON object context** — use when your policy needs multiple context values for conditional data access. Each key in the `Map` maps to a Skyflow CEL policy variable under `request.context.*`:
-
-```java
-Map ctx = new HashMap<>();
-ctx.put("role", "admin");
-ctx.put("department", "finance");
-ctx.put("user_id", "user_12345");
-
-BearerToken token = BearerToken.builder()
- .setCredentials(new File(filePath))
- .setCtx(ctx)
- .build();
-```
-
-With the map above, your Skyflow policies can reference `request.context.role`, `request.context.department`, and `request.context.user_id` to make conditional access decisions.
-
-You can also set context on `Credentials` for automatic token generation:
-
-```java
-// String context
-Credentials credentials = new Credentials();
-credentials.setPath("path/to/credentials.json");
-credentials.setContext("user_12345");
-
-// Map context
-Map ctx = new HashMap<>();
-ctx.put("role", "admin");
-ctx.put("department", "finance");
-credentials.setContext(ctx);
-```
-
-> **Note:** `getContext()` returns `Object` — callers should use `instanceof` if they need to inspect the type.
-
-Context map keys must contain only alphanumeric characters and underscores (`[a-zA-Z0-9_]`). Invalid keys will throw a `SkyflowException`.
-
-[Full example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/serviceaccount/BearerTokenGenerationWithContextExample.java)
-
-See Skyflow's [context-aware authorization](https://docs.skyflow.com) and [conditional data access](https://docs.skyflow.com) docs for policy variable syntax like `request.context.*`.
-
-## Generate scoped bearer tokens
-
-A service account with multiple roles can generate bearer tokens with access limited to a specific role by specifying the appropriate `roleID`. This can be used to limit access to specific roles for services with multiple responsibilities, such as segregating access for billing and analytics. The generated bearer tokens are valid for 60 minutes and can only execute operations permitted by the permissions associated with the designated role.
-
-[Example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/serviceaccount/ScopedTokenGenerationExample.java):
-
-```java
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.serviceaccount.util.BearerToken;
-
-import java.io.File;
-import java.util.ArrayList;
-
-/**
- * Example program to generate a Scoped Token using Skyflow's BearerToken utility.
- * The token is generated by providing the file path to the credentials.json file
- * and specifying roles associated with the token.
- */
-public class ScopedTokenGenerationExample {
- public static void main(String[] args) {
- // Variable to store the generated scoped token
- String scopedToken = null;
-
- // Example: Generate Scoped Token by specifying the credentials.json file path
- try {
- // Create a list of roles that the generated token will be scoped to
- ArrayList roles = new ArrayList<>();
- roles.add("ROLE_ID"); // Add a specific role to the list (e.g., "ROLE_ID")
-
- // Specify the full file path to the service account's credentials.json file
- String filePath = "";
-
- // Create a BearerToken object using the credentials file and associated roles
- BearerToken bearerToken = BearerToken.builder()
- .setCredentials(new File(filePath)) // Set credentials using the credentials.json file
- .setRoles(roles) // Set the roles that the token should be scoped to
- .build(); // Build the BearerToken object
-
- // Retrieve the generated scoped token
- scopedToken = bearerToken.getBearerToken();
-
- // Print the generated scoped token to the console
- System.out.println(scopedToken);
- } catch (SkyflowException e) {
- // Handle exceptions that may occur during token generation
- e.printStackTrace();
- }
- }
-}
-```
-
-Notes:
-
-- You can pass either the file path of a service account key credentials file or the service account key credentials as a string to the `setCredentials` method of the `BearerTokenBuilder` class.
-- If both a file path and a string are provided, the last method used takes precedence.
-- To generate multiple bearer tokens concurrently using threads, refer to the following [example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/serviceaccount/BearerTokenGenerationUsingThreadsExample.java).
-
-## Generate Signed Data Tokens
-
-Skyflow generates data tokens when sensitive data is inserted into the vault. These data tokens can be digitally signed
-with the private key of the service account credentials, which adds an additional layer of protection. Signed tokens can
-be detokenized by passing the signed data token and a bearer token generated from service account credentials. The
-service account must have appropriate permissions and context to detokenize the signed data tokens.
-
-The `setCtx()` method on `SignedDataTokensBuilder` also accepts either a **String** or a **`Map`**, using the same format as bearer tokens:
-
-```java
-// String context
-SignedDataTokens signedToken = SignedDataTokens.builder()
- .setCredentials(new File(filePath))
- .setCtx("user_12345")
- .setTimeToLive(30)
- .setDataTokens(dataTokens)
- .build();
-
-// JSON object context
-Map ctx = new HashMap<>();
-ctx.put("role", "analyst");
-ctx.put("department", "research");
-
-SignedDataTokens signedToken = SignedDataTokens.builder()
- .setCredentials(new File(filePath))
- .setCtx(ctx)
- .setTimeToLive(30)
- .setDataTokens(dataTokens)
- .build();
-```
-
-[Full example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/serviceaccount/SignedTokenGenerationExample.java)
-
-Response:
-
-```json
-[
- {
- "dataToken": "5530-4316-0674-5748",
- "signedDataToken": "signed_token_eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJzLCpZjA"
- }
-]
-```
-
-Notes:
-
-- You can provide either the file path to a service account key credentials file or the service account key credentials as a string to the `setCredentials` method of the `SignedDataTokensBuilder` class.
-- If both a file path and a string are passed to the `setCredentials` method, the most recently specified input takes precedence.
-- The `time-to-live` (TTL) value should be specified in seconds.
-- By default, the TTL value is set to 60 seconds.
-
-## Bearer token expiry edge case
-When you use bearer tokens for authentication and API requests in SDKs, there's the potential for a token to expire after the token is verified as valid but before the actual API call is made, causing the request to fail unexpectedly due to the token's expiration. An error from this edge case would look something like this:
-
-```txt
-message: Authentication failed. Bearer token is expired. Use a valid bearer token. See https://docs.skyflow.com/api-authentication/
-```
-
-If you encounter this kind of error, retry the request. During the retry, the SDK detects that the previous bearer token has expired and generates a new one for the current and subsequent requests.
-
-#### [Example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/serviceaccount/BearerTokenExpiryExample.java):
-
-```java
-package com.example.serviceaccount;
-
-import com.skyflow.Skyflow;
-import com.skyflow.config.Credentials;
-import com.skyflow.config.VaultConfig;
-import com.skyflow.enums.Env;
-import com.skyflow.enums.LogLevel;
-import com.skyflow.enums.RedactionType;
-import com.skyflow.errors.SkyflowException;
-import com.skyflow.vault.tokens.DetokenizeRequest;
-import com.skyflow.vault.tokens.DetokenizeResponse;
-import io.github.cdimascio.dotenv.Dotenv;
-import java.util.ArrayList;
-
-/**
- * This example demonstrates how to configure and use the Skyflow SDK
- * to detokenize sensitive data stored in a Skyflow vault.
- * It includes setting up credentials, configuring the vault, and
- * making a detokenization request. The code also implements a retry
- * mechanism to handle unauthorized access errors (HTTP 401).
- */
-public class DetokenizeExample {
- public static void main(String[] args) {
- try {
- // Setting up credentials for accessing the Skyflow vault
- Credentials vaultCredentials = new Credentials();
- vaultCredentials.setCredentialsString("");
-
- // Configuring the Skyflow vault with necessary details
- VaultConfig vaultConfig = new VaultConfig();
- vaultConfig.setVaultId(""); // Vault ID
- vaultConfig.setClusterId(""); // Cluster ID
- vaultConfig.setEnv(Env.PROD); // Environment (e.g., DEV, PROD)
- vaultConfig.setCredentials(vaultCredentials); // Setting credentials
-
- // Creating a Skyflow client instance with the configured vault
- Skyflow skyflowClient = Skyflow.builder()
- .setLogLevel(LogLevel.ERROR) // Setting log level to ERROR
- .addVaultConfig(vaultConfig) // Adding vault configuration
- .build();
-
- // Attempting to detokenize data using the Skyflow client
- try {
- detokenizeData(skyflowClient);
- } catch (SkyflowException e) {
- // Retry detokenization if the error is due to unauthorized access (HTTP 401)
- if (e.getHttpCode() == 401) {
- detokenizeData(skyflowClient);
- } else {
- // Rethrow the exception for other error codes
- throw e;
- }
- }
- } catch (SkyflowException e) {
- // Handling any exceptions that occur during the process
- System.out.println("An error occurred: " + e.getMessage());
- }
- }
-
- /**
- * Method to detokenize data using the Skyflow client.
- * It sends a detokenization request with a list of tokens and prints the response.
- *
- * @param skyflowClient The Skyflow client instance used for detokenization.
- * @throws SkyflowException If an error occurs during the detokenization process.
- */
- public static void detokenizeData(Skyflow skyflowClient) throws SkyflowException {
- // Creating a list of tokens to be detokenized
- ArrayList tokenList = new ArrayList<>();
- tokenList.add(""); // First token
- tokenList.add(""); // Second token
-
- // Building a detokenization request with the token list and configuration
- DetokenizeRequest detokenizeRequest = DetokenizeRequest.builder()
- .tokens(tokenList) // Adding tokens to the request
- .continueOnError(false) // Stop on error
- .redactionType(RedactionType.PLAIN_TEXT) // Redaction type (e.g., PLAIN_TEXT)
- .build();
-
- // Sending the detokenization request and receiving the response
- DetokenizeResponse detokenizeResponse = skyflowClient.vault().detokenize(detokenizeRequest);
-
- // Printing the detokenized response
- System.out.println(detokenizeResponse);
- }
-}
-```
-
-# Client Management
-
-After the `Skyflow` client is built you can add, retrieve, update, or remove vault and connection configurations at runtime — without rebuilding the client.
-
-## Vault configuration management
-
-```java
-import com.skyflow.config.VaultConfig;
-
-// Add a new vault at runtime
-skyflowClient.addVaultConfig(newVaultConfig);
-
-// Retrieve the config for a specific vault
-VaultConfig config = skyflowClient.getVaultConfig("");
-
-// Update an existing vault config (match by vaultId)
-skyflowClient.updateVaultConfig(updatedVaultConfig);
-
-// Remove a vault from the client
-skyflowClient.removeVaultConfig("");
-```
-
-## Connection configuration management
-
-```java
-import com.skyflow.config.ConnectionConfig;
-
-// Add a new connection at runtime
-skyflowClient.addConnectionConfig(newConnectionConfig);
-
-// Retrieve the config for a specific connection
-ConnectionConfig config = skyflowClient.getConnectionConfig("");
-
-// Update an existing connection config (match by connectionId)
-skyflowClient.updateConnectionConfig(updatedConnectionConfig);
-
-// Remove a connection from the client
-skyflowClient.removeConnectionConfig("");
-```
-
-## Credentials and log level management
-
-```java
-// Replace the Skyflow-level credentials used when vault/connection configs
-// do not specify their own credentials
-skyflowClient.updateSkyflowCredentials(newCredentials);
-
-// Update the log level after the client has been built
-skyflowClient.updateLogLevel(LogLevel.DEBUG);
-
-// Read the current log level
-LogLevel currentLevel = skyflowClient.getLogLevel();
-```
-
-**Client management method reference:**
-
-| Method | Returns | Description |
-|--------|---------|-------------|
-| `addVaultConfig(VaultConfig)` | `Skyflow` | Add a vault configuration |
-| `getVaultConfig(String vaultId)` | `VaultConfig` | Retrieve a vault configuration by ID |
-| `updateVaultConfig(VaultConfig)` | `Skyflow` | Replace a vault configuration (matched by `vaultId`) |
-| `removeVaultConfig(String vaultId)` | `Skyflow` | Remove a vault configuration |
-| `addConnectionConfig(ConnectionConfig)` | `Skyflow` | Add a connection configuration |
-| `getConnectionConfig(String connectionId)` | `ConnectionConfig` | Retrieve a connection configuration by ID |
-| `updateConnectionConfig(ConnectionConfig)` | `Skyflow` | Replace a connection configuration |
-| `removeConnectionConfig(String connectionId)` | `Skyflow` | Remove a connection configuration |
-| `updateSkyflowCredentials(Credentials)` | `Skyflow` | Replace the client-level credentials |
-| `updateLogLevel(LogLevel)` | `Skyflow` | Change the log level after initialization |
-| `getLogLevel()` | `LogLevel` | Return the current log level |
-
-All mutating methods return the `Skyflow` instance for chaining and throw `SkyflowException` on validation errors.
-
-# Error Handling
-
-The SDK uses `SkyflowException` for all errors — both client-side validation errors and server-side API errors.
-
-## Catching SkyflowException
-
-Wrap SDK calls in a `try/catch` block and catch `SkyflowException` to handle Skyflow-specific errors separately from unexpected exceptions:
-
-```java
-import com.skyflow.errors.SkyflowException;
-
-try {
- InsertResponse response = skyflowClient.vault().insert(insertRequest);
-} catch (SkyflowException e) {
- System.err.println("Skyflow error:");
- System.err.println(" HTTP code : " + e.getHttpCode());
- System.err.println(" Message : " + e.getMessage());
- System.err.println(" Request ID: " + e.getRequestId());
- System.err.println(" Details : " + e.getDetails());
-} catch (Exception e) {
- System.err.println("Unexpected error: " + e.getMessage());
-}
-```
-
-## SkyflowException properties
-
-| Property | Method | Description |
-|---|---|---|
-| HTTP status code | `getHttpCode()` | Integer status code (e.g. `400`, `404`, `500`). |
-| Message | `getMessage()` | Human-readable description of the error. |
-| HTTP status string | `getHttpStatus()` | Status string from the server (e.g. `"BAD_REQUEST"`). |
-| gRPC code | `getGrpcCode()` | gRPC status code from the server. |
-| Request ID | `getRequestId()` | The `x-request-id` header — useful for support escalations. |
-| Details | `getDetails()` | `JsonArray` of additional error context from the server. Empty array for validation errors, `null` if the server response omitted the field. |
-
-**Validation errors** (missing table name, empty token list, etc.) are thrown before any network call:
-- `httpCode` is always `400`
-- `requestId` and `grpcCode` are `null`
-- `details` is an empty array
-
-**API errors** are returned by the Skyflow server and have all fields populated from the response body and headers.
-
-# Logging
-
-The SDK provides logging with Java's built-in logging library. By default, the SDK's logging level is set to `LogLevel.ERROR`. This can be changed using the `setLogLevel(logLevel)` method, as shown below:
-
-Currently, the following five log levels are supported:
+## Which package do I want?
-- `DEBUG`**:**
- When `LogLevel.DEBUG` is passed, logs at all levels will be printed (DEBUG, INFO, WARN, ERROR).
-- `INFO`**:**
- When `LogLevel.INFO` is passed, INFO logs for every event that occurs during SDK flow execution will be printed, along with WARN and ERROR logs.
-- `WARN`**:**
- When `LogLevel.WARN` is passed, only WARN and ERROR logs will be printed.
-- `ERROR`**:**
- When `LogLevel.ERROR` is passed, only ERROR logs will be printed.
-- `OFF`**:**
- `LogLevel.OFF` can be used to turn off all logging from the Skyflow Java SDK.
+| Package | Artifact | README | Vault Type | Version line |
+|---|---|---|---|---|
+| **skyvault** | `com.skyflow:skyflow-java` | [skyvault/README.md](skyvault/README.md) | Privacy DB | 2.x |
+| **flowvault** | `com.skyflow:skyflow-flowvault-java` | [flowvault/README.md](flowvault/README.md) | Flow DB | 1.x |
-**Note:** The ranking of logging levels is as follows: `DEBUG` \< `INFO` \< `WARN` \< `ERROR` \< `OFF`.
+`flowvault` shares auth/client setup with `skyvault` — both depend on the `common` module.
-```java
-import com.skyflow.Skyflow;
-import com.skyflow.config.Credentials;
-import com.skyflow.config.VaultConfig;
-import com.skyflow.enums.Env;
-import com.skyflow.enums.LogLevel;
-import com.skyflow.errors.SkyflowException;
+> **The two artifacts are versioned independently.** `flowvault` is a new SDK starting at `1.0.0`; its lower version number reflects a first release, not an older or lesser SDK than `skyvault` 2.x. Upgrade each on its own version line.
-/**
- * This example demonstrates how to configure the Skyflow client with custom log levels
- * and authentication credentials (either token, credentials string, or other methods).
- * It also shows how to configure a vault connection using specific parameters.
- *
- * 1. Set up credentials with a Bearer token or credentials string.
- * 2. Define the Vault configuration.
- * 3. Build the Skyflow client with the chosen configuration and set log level.
- * 4. Example of changing the log level from ERROR (default) to INFO.
- */
-public class ChangeLogLevel {
- public static void main(String[] args) throws SkyflowException {
- // Step 1: Set up credentials - either pass token or use credentials string
- // In this case, we are using a Bearer token for authentication
- Credentials credentials = new Credentials();
- credentials.setToken(""); // Replace with actual Bearer token
+> Migrating from v1? See skyvault's **[Migration Guide](docs/migrate_to_v2.md)**. V1 is in maintenance mode and will reach End of Life on October 31, 2026.
- // Step 2: Define the Vault configuration
- // Configure the vault with necessary details like vault ID, cluster ID, and environment
- VaultConfig config = new VaultConfig();
- config.setVaultId(""); // Replace with actual Vault ID (primary vault)
- config.setClusterId(""); // Replace with actual Cluster ID (from vault URL)
- config.setEnv(Env.PROD); // Set the environment (default is PROD)
- config.setCredentials(credentials); // Set credentials for the vault (either token or credentials)
+## Repository layout
- // Step 3: Define additional Skyflow credentials (optional, if needed for credentials string)
- // Create a JSON object to hold your Skyflow credentials
- JsonObject credentialsObject = new JsonObject();
- credentialsObject.addProperty("clientId", ""); // Replace with your client ID
- credentialsObject.addProperty("clientName", ""); // Replace with your client name
- credentialsObject.addProperty("tokenUri", ""); // Replace with your token URI
- credentialsObject.addProperty("keyId", ""); // Replace with your key ID
- credentialsObject.addProperty("privateKey", ""); // Replace with your private key
+The root `pom.xml` (`packaging=pom`) aggregates this Maven reactor:
- // Convert the credentials object to a string format to be used for generating a Bearer Token
- Credentials skyflowCredentials = new Credentials();
- skyflowCredentials.setCredentialsString(credentialsObject.toString()); // Set credentials string
+- `common/` — shared client, credentials, config, and error-handling code used by both `skyvault` and `flowvault`
+- `skyvault/` — the `skyflow-java` SDK ([README](skyvault/README.md))
+- `flowvault/` — the `skyflow-flowvault-java` SDK ([README](flowvault/README.md))
- // Step 4: Build the Skyflow client with the chosen configuration and log level
- Skyflow skyflowClient = Skyflow.builder()
- .addVaultConfig(config) // Add the Vault configuration
- .addSkyflowCredentials(skyflowCredentials) // Use Skyflow credentials if no token is passed
- .setLogLevel(LogLevel.INFO) // Set log level to INFO (default is ERROR)
- .build(); // Build the Skyflow client
+## Documentation
- // Now, the Skyflow client is ready to use with the specified log level and credentials
- System.out.println("Skyflow client has been successfully configured with log level: INFO.");
- }
-}
-```
+- [skyvault API Reference](docs/api_reference.md) — full list of request builder methods, response getters, enums, and service-account utilities
+- [Migrate from v1 to v2](docs/migrate_to_v2.md)
-# Reporting a Vulnerability
+## Reporting a Vulnerability
If you discover a potential security issue in this project, please reach out to us at **security@skyflow.com**. Please do not create public GitHub issues or Pull Requests, as malicious actors could potentially view them.
diff --git a/codecov.yml b/codecov.yml
index 05c58c3e..0191c11b 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -1,52 +1,146 @@
-comment: false
+# Post a summary on every PR, broken down by flag (module) and component so all three of
+# common / skyvault / flowvault are visible at a glance. require_changes: false keeps the
+# comment on PRs that touch only one module, so the other two still report their coverage.
+comment:
+ layout: "header, diff, flags, components, files, footer"
+ behavior: default
+ require_changes: false
+# A project + patch status per module, so each of the three gets its own PR check rather
+# than being averaged into one repo-wide number. informational keeps them advisory - they
+# report the delta without blocking the merge.
+coverage:
+ status:
+ project:
+ default:
+ target: auto
+ threshold: 1%
+ common:
+ flags:
+ - common
+ target: auto
+ threshold: 1%
+ informational: true
+ skyvault:
+ flags:
+ - skyvault
+ target: auto
+ threshold: 1%
+ informational: true
+ flowvault:
+ flags:
+ - flowvault
+ target: auto
+ threshold: 1%
+ informational: true
+ patch:
+ default:
+ target: auto
+ threshold: 1%
+ informational: true
+
+# One flag per Maven module. Each module is uploaded separately in CI so its coverage is
+# reported on its own rather than merged into a single repo-wide number. carryforward keeps
+# the last known coverage for a module when a run does not upload it (e.g. a partial build).
+flags:
+ common:
+ paths:
+ - common/src/main/java/
+ carryforward: true
+ skyvault:
+ paths:
+ - skyvault/src/main/java/
+ carryforward: true
+ flowvault:
+ paths:
+ - flowvault/src/main/java/
+ carryforward: true
+
+# Components give two independent breakdowns of the same coverage data:
+# - one per module, so a drop can be traced to common / skyvault / flowvault
+# - one per package, so a drop can be traced to controllers / data / utils / ...
+#
+# Package paths are prefixed with **/ (quoted - a bare leading * is a YAML alias) so they
+# match every module. All three modules share the com.skyflow package name, so the JaCoCo
+# reports are rewritten in CI to carry their module's source root; without that, a path like
+# com/skyflow/config/VaultConfig.java is ambiguous and Codecov attributes it to a single
+# module while the others report no data. See the "Qualify JaCoCo report paths" CI step.
component_management:
default_rules:
statuses:
- type: project
target: auto
individual_components:
+ # -- per module ------------------------------------------------------------
+ - component_id: module_common
+ name: "Module: common"
+ paths:
+ - "common/src/main/java/**"
+ - component_id: module_skyvault
+ name: "Module: skyvault"
+ paths:
+ - "skyvault/src/main/java/**"
+ - component_id: module_flowvault
+ name: "Module: flowvault"
+ paths:
+ - "flowvault/src/main/java/**"
+ # -- per package, across all modules ---------------------------------------
- component_id: service_account
name: Service Account
paths:
- - src/main/java/com/skyflow/serviceaccount/**
+ - "**/src/main/java/com/skyflow/serviceaccount/**"
- component_id: vault_data
name: Vault Data
paths:
- - src/main/java/com/skyflow/vault/data/**
+ - "**/src/main/java/com/skyflow/vault/data/**"
- component_id: vault_tokens
name: Vault Tokens
paths:
- - src/main/java/com/skyflow/vault/tokens/**
+ - "**/src/main/java/com/skyflow/vault/tokens/**"
- component_id: vault_connection
name: Vault Connection
paths:
- - src/main/java/com/skyflow/vault/connection/**
+ - "**/src/main/java/com/skyflow/vault/connection/**"
- component_id: vault_controller
name: Vault Controller
paths:
- - src/main/java/com/skyflow/vault/controller/**
+ - "**/src/main/java/com/skyflow/vault/controller/**"
- component_id: vault_detect
name: Detect
paths:
- - src/main/java/com/skyflow/vault/detect/**
+ - "**/src/main/java/com/skyflow/vault/detect/**"
- component_id: vault_audit
name: Audit
paths:
- - src/main/java/com/skyflow/vault/audit/**
+ - "**/src/main/java/com/skyflow/vault/audit/**"
- component_id: vault_bin
name: BIN Lookup
paths:
- - src/main/java/com/skyflow/vault/bin/**
+ - "**/src/main/java/com/skyflow/vault/bin/**"
- component_id: config
name: Config
paths:
- - src/main/java/com/skyflow/config/**
+ - "**/src/main/java/com/skyflow/config/**"
- component_id: utils
name: Utils
paths:
- - src/main/java/com/skyflow/utils/**
+ - "**/src/main/java/com/skyflow/utils/**"
- component_id: errors
name: Errors
paths:
- - src/main/java/com/skyflow/errors/**
+ - "**/src/main/java/com/skyflow/errors/**"
+ - component_id: enums
+ name: Enums
+ paths:
+ - "**/src/main/java/com/skyflow/enums/**"
+ - component_id: logs
+ name: Logs
+ paths:
+ - "**/src/main/java/com/skyflow/logs/**"
+
+# Generated REST/auth clients and sample code are not hand-written and are already excluded
+# from the JaCoCo reports by the root pom; ignore them here too so they never skew a target.
+ignore:
+ - "**/src/main/java/com/skyflow/generated/**"
+ - "**/samples/**"
+ - "**/src/test/**"
diff --git a/common/pom.xml b/common/pom.xml
new file mode 100644
index 00000000..72fff275
--- /dev/null
+++ b/common/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ com.skyflow
+ skyflow
+ 1.0.0
+ ../pom.xml
+
+
+ common
+ 1.0.0
+ ${project.groupId}:${project.artifactId}
+
+
+
+ true
+ 8
+ 8
+ UTF-8
+
+
\ No newline at end of file
diff --git a/common/src/main/java/com/skyflow/BaseSkyflow.java b/common/src/main/java/com/skyflow/BaseSkyflow.java
new file mode 100644
index 00000000..d02dc45a
--- /dev/null
+++ b/common/src/main/java/com/skyflow/BaseSkyflow.java
@@ -0,0 +1,214 @@
+package com.skyflow;
+
+import com.skyflow.config.BaseVaultConfig;
+import com.skyflow.config.Credentials;
+import com.skyflow.enums.LogLevel;
+import com.skyflow.errors.ErrorCode;
+import com.skyflow.errors.ErrorMessage;
+import com.skyflow.errors.SkyflowException;
+import com.skyflow.logs.ErrorLogs;
+import com.skyflow.logs.InfoLogs;
+import com.skyflow.utils.BaseUtils;
+import com.skyflow.utils.logger.LogUtil;
+import com.skyflow.utils.validations.BaseValidations;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+abstract class BaseSkyflow, V extends BaseVaultConfig> implements ISkyflow {
+ protected final BaseSkyflowClientBuilder builder;
+
+ protected BaseSkyflow(BaseSkyflowClientBuilder builder) {
+ this.builder = builder;
+ LogUtil.printInfoLog(InfoLogs.CLIENT_INITIALIZED.getLog());
+ }
+
+ protected abstract Self self();
+
+ @Override
+ public Self addVaultConfig(V vaultConfig) throws SkyflowException {
+ this.builder.addVaultConfigTemplate(vaultConfig);
+ return self();
+ }
+
+ public V getVaultConfig(String vaultId) {
+ return this.builder.vaultConfigMap.get(vaultId);
+ }
+
+ @Override
+ public Self updateVaultConfig(V vaultConfig) throws SkyflowException {
+ this.builder.updateVaultConfigTemplate(vaultConfig);
+ return self();
+ }
+
+ @Override
+ public Self removeVaultConfig(String vaultId) throws SkyflowException {
+ this.builder.removeVaultConfigTemplate(vaultId);
+ return self();
+ }
+
+ @Override
+ public Self updateSkyflowCredentials(Credentials credentials) throws SkyflowException {
+ this.builder.addSkyflowCredentialsTemplate(credentials);
+ return self();
+ }
+
+ @Override
+ public Self setLogLevel(LogLevel logLevel) {
+ this.builder.setLogLevel(logLevel);
+ return self();
+ }
+
+ @Override
+ public LogLevel getLogLevel() {
+ return this.builder.logLevel;
+ }
+
+ protected static T resolveOrThrow(Map map, String key,
+ ErrorLogs errorLog, ErrorMessage errorMessage) throws SkyflowException {
+ T value = key != null ? map.get(key) : map.values().stream().findFirst().orElse(null);
+ if (value == null) {
+ // The log line carries a %s1 placeholder for the id. Callers that resolve the single
+ // configured entry pass no key, so say so rather than emitting the raw placeholder.
+ LogUtil.printErrorLog(BaseUtils.parameterizedString(
+ errorLog.getLog(), key != null ? key : "not specified"));
+ throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), errorMessage.getMessage());
+ }
+ return value;
+ }
+
+ abstract static class BaseSkyflowClientBuilder {
+ protected final LinkedHashMap vaultConfigMap = new LinkedHashMap<>();
+ protected Credentials skyflowCredentials;
+ protected LogLevel logLevel = LogLevel.ERROR;
+
+ protected BaseSkyflowClientBuilder() {
+ }
+
+ public BaseSkyflowClientBuilder addVaultConfig(V vaultConfig) throws SkyflowException {
+ addVaultConfigTemplate(vaultConfig);
+ return this;
+ }
+
+ public BaseSkyflowClientBuilder updateVaultConfig(V vaultConfig) throws SkyflowException {
+ updateVaultConfigTemplate(vaultConfig);
+ return this;
+ }
+
+ public BaseSkyflowClientBuilder removeVaultConfig(String vaultId) throws SkyflowException {
+ removeVaultConfigTemplate(vaultId);
+ return this;
+ }
+
+ public BaseSkyflowClientBuilder addSkyflowCredentials(Credentials credentials) throws SkyflowException {
+ addSkyflowCredentialsTemplate(credentials);
+ return this;
+ }
+
+ protected BaseSkyflowClientBuilder setLogLevel(LogLevel logLevel) {
+ this.logLevel = logLevel == null ? LogLevel.ERROR : logLevel;
+ LogUtil.setupLogger(this.logLevel);
+ LogUtil.printInfoLog(BaseUtils.parameterizedString(
+ InfoLogs.CURRENT_LOG_LEVEL.getLog(), String.valueOf(this.logLevel)
+ ));
+ return this;
+ }
+
+ protected final void addVaultConfigTemplate(V vaultConfig) throws SkyflowException {
+ LogUtil.printInfoLog(InfoLogs.VALIDATING_VAULT_CONFIG.getLog());
+ validateVaultConfig(vaultConfig);
+ V vaultConfigCopy = cloneVaultConfig(vaultConfig);
+ String vaultId = extractVaultId(vaultConfigCopy);
+ if (hasVaultClient(vaultId)) {
+ LogUtil.printErrorLog(BaseUtils.parameterizedString(
+ ErrorLogs.VAULT_CONFIG_EXISTS.getLog(), vaultId
+ ));
+ throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(),
+ ErrorMessage.VaultIdAlreadyInConfigList.getMessage());
+ }
+ onVaultConfigAdded(vaultConfigCopy);
+ this.vaultConfigMap.put(vaultId, vaultConfigCopy);
+ }
+
+ protected final void updateVaultConfigTemplate(V vaultConfig) throws SkyflowException {
+ LogUtil.printInfoLog(InfoLogs.VALIDATING_VAULT_CONFIG.getLog());
+ validateVaultConfig(vaultConfig);
+ String vaultId = extractVaultId(vaultConfig);
+ if (!hasVaultClient(vaultId)) {
+ LogUtil.printErrorLog(BaseUtils.parameterizedString(
+ ErrorLogs.VAULT_CONFIG_DOES_NOT_EXIST.getLog(), vaultId
+ ));
+ throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.VaultIdNotInConfigList.getMessage());
+ }
+ V previousConfig = this.vaultConfigMap.get(vaultId);
+ V merged = mergeVaultConfig(vaultConfig, cloneVaultConfig(previousConfig));
+ onVaultConfigUpdated(merged);
+ this.vaultConfigMap.put(vaultId, merged);
+ }
+
+ protected final void removeVaultConfigTemplate(String vaultId) throws SkyflowException {
+ if (!hasVaultClient(vaultId)) {
+ LogUtil.printErrorLog(BaseUtils.parameterizedString(ErrorLogs.VAULT_CONFIG_DOES_NOT_EXIST.getLog(), vaultId));
+ throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.VaultIdNotInConfigList.getMessage());
+ }
+ onVaultConfigRemoved(vaultId);
+ this.vaultConfigMap.remove(vaultId);
+ }
+
+ protected final void addSkyflowCredentialsTemplate(Credentials credentials) throws SkyflowException {
+ BaseValidations.validateCredentials(credentials);
+ Credentials credentialsCopy;
+ try {
+ credentialsCopy = (Credentials) credentials.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new SkyflowException(e.getMessage(), e);
+ }
+ onCredentialsUpdated(credentialsCopy);
+ this.skyflowCredentials = credentialsCopy;
+ }
+
+ protected abstract void validateVaultConfig(V vaultConfig) throws SkyflowException;
+
+ protected abstract boolean hasVaultClient(String vaultId);
+
+ @SuppressWarnings("unchecked")
+ protected final V cloneVaultConfig(V vaultConfig) throws SkyflowException {
+ try {
+ return (V) vaultConfig.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new SkyflowException(e.getMessage(), e);
+ }
+ }
+
+ protected final String extractVaultId(V vaultConfig) {
+ return vaultConfig.getVaultId();
+ }
+
+ protected final V mergeVaultConfig(V incoming, V existing) throws SkyflowException {
+ if (incoming.getEnv() != null) {
+ existing.setEnv(incoming.getEnv());
+ }
+ if (incoming.getClusterId() != null) {
+ existing.setClusterId(incoming.getClusterId());
+ }
+ if (incoming.getCredentials() != null) {
+ try {
+ existing.setCredentials((Credentials) incoming.getCredentials().clone());
+ } catch (CloneNotSupportedException e) {
+ throw new SkyflowException(e.getMessage(), e);
+ }
+ }
+ return existing;
+ }
+
+ protected abstract void onVaultConfigAdded(V vaultConfig) throws SkyflowException;
+
+ protected abstract void onVaultConfigUpdated(V updatedConfig) throws SkyflowException;
+
+ protected abstract void onVaultConfigRemoved(String vaultId) throws SkyflowException;
+
+ protected abstract void onCredentialsUpdated(Credentials credentials) throws SkyflowException;
+ }
+
+}
diff --git a/common/src/main/java/com/skyflow/BaseVaultClient.java b/common/src/main/java/com/skyflow/BaseVaultClient.java
new file mode 100644
index 00000000..3d5b0d32
--- /dev/null
+++ b/common/src/main/java/com/skyflow/BaseVaultClient.java
@@ -0,0 +1,114 @@
+package com.skyflow;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.skyflow.config.BaseCredentials;
+import com.skyflow.config.BaseVaultConfig;
+import com.skyflow.errors.ErrorCode;
+import com.skyflow.errors.ErrorMessage;
+import com.skyflow.errors.SkyflowException;
+import com.skyflow.logs.ErrorLogs;
+import com.skyflow.logs.InfoLogs;
+import com.skyflow.serviceaccount.util.Token;
+import com.skyflow.utils.BaseConstants;
+import com.skyflow.utils.BaseUtils;
+import com.skyflow.utils.logger.LogUtil;
+import com.skyflow.utils.validations.BaseValidations;
+import io.github.cdimascio.dotenv.Dotenv;
+import io.github.cdimascio.dotenv.DotenvException;
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+
+class BaseVaultClient {
+ protected V vaultConfig;
+ protected OkHttpClient sharedHttpClient;
+ protected String currentVaultURL;
+ protected BaseCredentials commonCredentials;
+ protected BaseCredentials finalCredentials;
+ protected String token;
+ protected String apiKey;
+
+ protected BaseVaultClient(V vaultConfig, BaseCredentials credentials) {
+ this.vaultConfig = vaultConfig;
+ this.commonCredentials = credentials;
+ }
+
+ protected V getVaultConfig() {
+ return vaultConfig;
+ }
+
+ protected OkHttpClient buildSharedHttpClient(Supplier tokenSupplier) {
+ return new OkHttpClient.Builder()
+ .connectionPool(new ConnectionPool(10, 1, TimeUnit.MINUTES))
+ .addInterceptor(chain -> {
+ Request requestWithAuth = chain.request().newBuilder()
+ .header("Authorization", "Bearer " + tokenSupplier.get())
+ .build();
+ return chain.proceed(requestWithAuth);
+ })
+ .build();
+ }
+
+ protected synchronized void prioritiseCredentials(BaseCredentials vaultSpecificCredentials) throws SkyflowException {
+ try {
+ BaseCredentials original = this.finalCredentials;
+ if (vaultSpecificCredentials != null) {
+ this.finalCredentials = vaultSpecificCredentials;
+ } else if (this.commonCredentials != null) {
+ this.finalCredentials = this.commonCredentials;
+ } else {
+ String sysCredentials = System.getenv(BaseConstants.ENV_CREDENTIALS_KEY_NAME);
+ if (sysCredentials == null) {
+ Dotenv dotenv = Dotenv.load();
+ sysCredentials = dotenv.get(BaseConstants.ENV_CREDENTIALS_KEY_NAME);
+ }
+ if (sysCredentials == null) {
+ throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyCredentials.getMessage());
+ } else {
+ this.finalCredentials = new BaseCredentials();
+ this.finalCredentials.setCredentialsString(sysCredentials);
+ }
+ }
+ if (original != null && !original.equals(this.finalCredentials)) {
+ token = null;
+ apiKey = null;
+ }
+ } catch (DotenvException e) {
+ throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyCredentials.getMessage());
+ } catch (SkyflowException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected synchronized void setBearerToken(BaseCredentials vaultSpecificCredentials) throws SkyflowException {
+ prioritiseCredentials(vaultSpecificCredentials);
+ BaseValidations.validateCredentials(this.finalCredentials);
+ if (this.finalCredentials.getApiKey() != null) {
+ LogUtil.printInfoLog(InfoLogs.USE_API_KEY.getLog());
+ token = this.finalCredentials.getApiKey();
+ } else if (token == null || token.trim().isEmpty()) {
+ token = BaseUtils.generateBearerToken(this.finalCredentials);
+ } else if (Token.isExpired(token)) {
+ LogUtil.printInfoLog(InfoLogs.BEARER_TOKEN_EXPIRED.getLog());
+ token = BaseUtils.generateBearerToken(this.finalCredentials);
+ } else {
+ LogUtil.printInfoLog(InfoLogs.REUSE_BEARER_TOKEN.getLog());
+ }
+ }
+
+ protected static SkyflowException wrapApiException(int statusCode, Throwable cause,
+ Map> headers,
+ Object responseBody, ErrorLogs errorLog) {
+ LogUtil.printErrorLog(errorLog.getLog());
+ Gson gson = new GsonBuilder().serializeNulls().create();
+ return new SkyflowException(statusCode, cause, headers, gson.toJson(responseBody));
+ }
+}
diff --git a/common/src/main/java/com/skyflow/ISkyflow.java b/common/src/main/java/com/skyflow/ISkyflow.java
new file mode 100644
index 00000000..1c29b780
--- /dev/null
+++ b/common/src/main/java/com/skyflow/ISkyflow.java
@@ -0,0 +1,20 @@
+package com.skyflow;
+
+import com.skyflow.config.BaseCredentials;
+import com.skyflow.config.BaseVaultConfig;
+import com.skyflow.enums.LogLevel;
+import com.skyflow.errors.SkyflowException;
+
+public interface ISkyflow, V extends BaseVaultConfig, C extends BaseCredentials> {
+ Self addVaultConfig(V vaultConfig) throws SkyflowException;
+
+ Self updateVaultConfig(V vaultConfig) throws SkyflowException;
+
+ Self removeVaultConfig(String vaultId) throws SkyflowException;
+
+ Self updateSkyflowCredentials(C credentials) throws SkyflowException;
+
+ Self setLogLevel(LogLevel logLevel);
+
+ LogLevel getLogLevel();
+}
diff --git a/src/main/java/com/skyflow/config/Credentials.java b/common/src/main/java/com/skyflow/config/BaseCredentials.java
similarity index 71%
rename from src/main/java/com/skyflow/config/Credentials.java
rename to common/src/main/java/com/skyflow/config/BaseCredentials.java
index c2594ef6..48ab70dc 100644
--- a/src/main/java/com/skyflow/config/Credentials.java
+++ b/common/src/main/java/com/skyflow/config/BaseCredentials.java
@@ -1,20 +1,21 @@
package com.skyflow.config;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Map;
-public class Credentials {
+public class BaseCredentials implements Cloneable {
private String path;
private ArrayList roles;
- private Object context;
private String credentialsString;
private String token;
private String apiKey;
+ private Object context;
- public Credentials() {
+ public BaseCredentials() {
this.path = null;
- this.context = null;
this.credentialsString = null;
+ this.context = null;
}
public String getPath() {
@@ -33,18 +34,6 @@ public void setRoles(ArrayList roles) {
this.roles = roles;
}
- public Object getContext() {
- return context;
- }
-
- public void setContext(String context) {
- this.context = context;
- }
-
- public void setContext(Map context) {
- this.context = context;
- }
-
public String getCredentialsString() {
return credentialsString;
}
@@ -68,4 +57,28 @@ public String getApiKey() {
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
+ public Object getContext() {
+ return context;
+ }
+
+ public void setContext(String context) {
+ this.context = context;
+ }
+
+ public void setContext(Map context) {
+ this.context = context;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object clone() throws CloneNotSupportedException {
+ BaseCredentials copy = (BaseCredentials) super.clone();
+ if (this.roles != null) {
+ copy.roles = new ArrayList<>(this.roles);
+ }
+ if (this.context instanceof Map) {
+ copy.context = new HashMap<>((Map) this.context);
+ }
+ return copy;
+ }
}
diff --git a/src/main/java/com/skyflow/config/VaultConfig.java b/common/src/main/java/com/skyflow/config/BaseVaultConfig.java
similarity index 71%
rename from src/main/java/com/skyflow/config/VaultConfig.java
rename to common/src/main/java/com/skyflow/config/BaseVaultConfig.java
index 4f61af2a..fb1a2a6b 100644
--- a/src/main/java/com/skyflow/config/VaultConfig.java
+++ b/common/src/main/java/com/skyflow/config/BaseVaultConfig.java
@@ -2,13 +2,13 @@
import com.skyflow.enums.Env;
-public class VaultConfig {
+public class BaseVaultConfig implements Cloneable {
private String vaultId;
private String clusterId;
private Env env;
private Credentials credentials;
- public VaultConfig() {
+ public BaseVaultConfig() {
this.vaultId = null;
this.clusterId = null;
this.env = Env.PROD;
@@ -46,4 +46,14 @@ public Credentials getCredentials() {
public void setCredentials(Credentials credentials) {
this.credentials = credentials;
}
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ BaseVaultConfig cloned = (BaseVaultConfig) super.clone();
+ if (this.credentials != null) {
+ cloned.credentials = (Credentials) this.credentials.clone();
+ }
+ return cloned;
+ }
+
}
diff --git a/common/src/main/java/com/skyflow/config/Credentials.java b/common/src/main/java/com/skyflow/config/Credentials.java
new file mode 100644
index 00000000..b0d6b888
--- /dev/null
+++ b/common/src/main/java/com/skyflow/config/Credentials.java
@@ -0,0 +1,7 @@
+package com.skyflow.config;
+
+public class Credentials extends BaseCredentials {
+ public Credentials() {
+ super();
+ }
+}
diff --git a/src/main/java/com/skyflow/enums/Env.java b/common/src/main/java/com/skyflow/enums/Env.java
similarity index 100%
rename from src/main/java/com/skyflow/enums/Env.java
rename to common/src/main/java/com/skyflow/enums/Env.java
diff --git a/src/main/java/com/skyflow/enums/LogLevel.java b/common/src/main/java/com/skyflow/enums/LogLevel.java
similarity index 100%
rename from src/main/java/com/skyflow/enums/LogLevel.java
rename to common/src/main/java/com/skyflow/enums/LogLevel.java
diff --git a/src/main/java/com/skyflow/errors/ErrorCode.java b/common/src/main/java/com/skyflow/errors/ErrorCode.java
similarity index 100%
rename from src/main/java/com/skyflow/errors/ErrorCode.java
rename to common/src/main/java/com/skyflow/errors/ErrorCode.java
diff --git a/common/src/main/java/com/skyflow/errors/ErrorMessage.java b/common/src/main/java/com/skyflow/errors/ErrorMessage.java
new file mode 100644
index 00000000..2f52addf
--- /dev/null
+++ b/common/src/main/java/com/skyflow/errors/ErrorMessage.java
@@ -0,0 +1,223 @@
+package com.skyflow.errors;
+
+import com.skyflow.utils.SdkVersion;
+
+public enum ErrorMessage {
+ // Client initialization
+ VaultIdAlreadyInConfigList("%s0 Validation error. VaultId is present in an existing config. Specify a new vaultId in config."),
+ VaultIdNotInConfigList("%s0 Validation error. VaultId is missing from the config. Specify the vaultIds from configs."),
+ OnlySingleVaultConfigAllowed("%s0 Validation error. A vault config already exists. Cannot add another vault config."),
+ ConnectionIdAlreadyInConfigList("%s0 Validation error. ConnectionId is present in an existing config. Specify a connectionId in config."),
+ ConnectionIdNotInConfigList("%s0 Validation error. ConnectionId is missing from the config. Specify the connectionIds from configs."),
+ EmptyCredentials("%s0 Validation error. Invalid credentials. Credentials must not be empty."),
+ TableSpecifiedInRequestAndRecordObject("%s0 Validation error. Table name cannot be specified at both the request and record levels. Please specify the table name in only one place."),
+ UpsertTableRequestAtRecordLevel("%s0 Validation error. Table name should be present at each record level when upsert is present at record level."),
+ UpsertTableRequestAtRequestLevel("%s0 Validation error. Upsert should be present at each record level when table name is present at record level."),
+ TableNotSpecifiedInRequestAndRecordObject("%s0 Validation error. Table name is missing. Table name should be specified at one place either at the request level or record level. Please specify the table name at one place."),
+ // Vault config
+ InvalidVaultId("%s0 Initialization failed. Invalid vault ID. Specify a valid vault ID."),
+ EmptyVaultId("%s0 Initialization failed. Invalid vault ID. Vault ID must not be empty."),
+ InvalidClusterId("%s0 Initialization failed. Invalid cluster ID. Specify cluster ID."),
+ EmptyClusterId("%s0 Initialization failed. Invalid cluster ID. Specify a valid cluster ID."),
+ EmptyVaultUrl("%s0 Initialization failed. Vault URL is empty. Specify a valid vault URL."),
+ InvalidVaultUrlFormat("%s0 Initialization failed. Vault URL must start with 'https://'."),
+ EitherVaultUrlOrClusterIdRequired("%s0 Initialization failed. Specify either 'clusterId' or 'vaultURL'."),
+
+ // Connection config
+ InvalidConnectionId("%s0 Initialization failed. Invalid connection ID. Specify a valid connection ID."),
+ EmptyConnectionId("%s0 Initialization failed. Invalid connection ID. Connection ID must not be empty."),
+ InvalidConnectionUrl("%s0 Initialization failed. Invalid connection URL. Specify a valid connection URL."),
+ EmptyConnectionUrl("%s0 Initialization failed. Invalid connection URL. Connection URL must not be empty."),
+ InvalidConnectionUrlFormat("%s0 Initialization failed. Connection URL is not a valid URL. Specify a valid connection URL."),
+
+ // Credentials
+ MultipleTokenGenerationMeansPassed("%s0 Initialization failed. Invalid credentials. Specify only one from 'path', 'credentialsString', 'token' or 'apiKey'."),
+ NoTokenGenerationMeansPassed("%s0 Initialization failed. Invalid credentials. Specify any one from 'path', 'credentialsString', 'token' or 'apiKey'."),
+ EmptyCredentialFilePath("%s0 Initialization failed. Invalid credentials. Credentials file path must not be empty."),
+ EmptyCredentialsString("%s0 Initialization failed. Invalid credentials. Credentials string must not be empty."),
+ EmptyToken("%s0 Initialization failed. Invalid credentials. Token must not be empty."),
+ EmptyApikey("%s0 Initialization failed. Invalid credentials. Api key must not be empty."),
+ InvalidApikey("%s0 Initialization failed. Invalid credentials. Specify valid api key."),
+ EmptyRoles("%s0 Initialization failed. Invalid roles. Specify at least one role."),
+ EmptyRoleInRoles("%s0 Initialization failed. Invalid role. Specify a valid role."),
+ EmptyContext("%s0 Initialization failed. Invalid context. Specify a valid context."),
+ InvalidContextType("%s0 Initialization failed. Invalid context type. Specify context as a String or Map."),
+ InvalidContextMapKey("%s0 Initialization failed. Invalid key '%s1' in context map. Keys must contain only alphanumeric characters and underscores."),
+
+ // Bearer token generation
+ FileNotFound("%s0 Initialization failed. Credential file not found at %s1. Verify the file path."),
+ FileInvalidJson("%s0 Initialization failed. File at %s1 is not in valid JSON format. Verify the file contents."),
+ CredentialsStringInvalidJson("%s0 Initialization failed. Credentials string is not in valid JSON format. Verify the credentials string contents."),
+ InvalidCredentials("%s0 Initialization failed. Invalid credentials provided. Specify valid credentials."),
+ MissingPrivateKey("%s0 Initialization failed. Unable to read private key in credentials. Verify your private key."),
+ MissingClientId("%s0 Initialization failed. Unable to read client ID in credentials. Verify your client ID."),
+ MissingKeyId("%s0 Initialization failed. Unable to read key ID in credentials. Verify your key ID."),
+ MissingTokenUri("%s0 Initialization failed. Unable to read token URI in credentials. Verify your token URI."),
+ InvalidTokenUri("%s0 Initialization failed. Token URI in not a valid URL in credentials. Verify your token URI."),
+ JwtInvalidFormat("%s0 Initialization failed. Invalid private key format. Verify your credentials."),
+ InvalidAlgorithm("%s0 Initialization failed. Invalid algorithm to parse private key. Specify valid algorithm."),
+ InvalidKeySpec("%s0 Initialization failed. Unable to parse RSA private key. Verify your credentials."),
+ JwtDecodeError("%s0 Validation error. Invalid access token. Verify your credentials."),
+ MissingAccessToken("%s0 Validation error. Access token not present in the response from bearer token generation. Verify your credentials."),
+ MissingTokenType("%s0 Validation error. Token type not present in the response from bearer token generation. Verify your credentials."),
+ BearerTokenExpired("%s0 Validation error. Bearer token is invalid or expired. Please provide a valid bearer token."),
+
+ // Insert
+ InsertRequestNull("%s0 Validation error. InsertRequest object is null. Specify a valid InsertRequest object."),
+ TableKeyError("%s0 Validation error. 'table' key is missing from the payload. Specify a 'table' key."),
+ EmptyTable("%s0 Validation error. 'table' can't be empty. Specify a table."),
+ ValuesKeyError("%s0 Validation error. 'values' key is missing from the payload. Specify a 'values' key."),
+ EmptyRecords("%s0 Validation error. 'records' can't be empty. Specify records."),
+ EmptyKeyInRecords("%s0 Validation error. Invalid key in data in records. Specify a valid key."),
+ EmptyValueInRecords("%s0 Validation error. Invalid value in records. Specify a valid value."),
+ RecordsKeyError("%s0 Validation error. 'records' key is missing from the payload. Specify a 'records' key."),
+ EmptyValues("%s0 Validation error. 'values' can't be empty. Specify values."),
+ EmptyKeyInValues("%s0 Validation error. Invalid key in values. Specify a valid key."),
+ EmptyValueInValues("%s0 Validation error. Invalid value in values. Specify a valid value."),
+ TokensKeyError("%s0 Validation error. 'tokens' key is missing from the payload. Specify a 'tokens' key."),
+ EmptyTokens("%s0 Validation error. The 'tokens' field is empty. Specify tokens for one or more fields."),
+ EmptyKeyInTokens("%s0 Validation error. Invalid key tokens. Specify a valid key."),
+ EmptyValueInTokens("%s0 Validation error. Invalid value in tokens. Specify a valid value."),
+ EmptyUpsert("%s0 Validation error. 'upsert' key can't be empty. Specify an upsert column."),
+ InvalidUpsertUpdateType("%s0 Validation error. Invalid upsert updateType. Specify either 'UPDATE' or 'REPLACE'."),
+ EmptyUpsertValues("%s0 Validation error. Upsert column values can't be empty. Specify at least one upsert column."),
+ HomogenousNotSupportedWithUpsert("%s0 Validation error. 'homogenous' is not supported with 'upsert'. Specify either 'homogenous' or 'upsert'."),
+ TokensPassedForTokenModeDisable("%s0 Validation error. 'tokenMode' wasn't specified. Set 'tokenMode' to 'ENABLE' to insert tokens."),
+ NoTokensWithTokenMode("%s0 Validation error. Tokens weren't specified for records while 'tokenMode' was %s1. Specify tokens."),
+ MismatchOfFieldsAndTokens("%s0 Validation error. 'fields' and 'tokens' have different columns names. Verify that 'fields' and 'tokens' columns match."),
+ InsufficientTokensPassedForTokenModeEnableStrict("%s0 Validation error. 'tokenMode' is set to 'ENABLE_STRICT', but some fields are missing tokens. Specify tokens for all fields."),
+ BatchInsertPartialSuccess("%s0 Insert operation completed with partial success."),
+ BatchInsertFailure("%s0 Insert operation failed."),
+ RecordSizeExceedError("%s0 Maximum number of records exceeded. The limit is 10000."),
+
+ // Detokenize
+ InvalidDetokenizeData("%s0 Validation error. Invalid detokenize data. Specify valid detokenize data."),
+ EmptyDetokenizeData("%s0 Validation error. Invalid data tokens. Specify at least one data token."),
+ EmptyTokenInDetokenizeData("%s0 Validation error. Invalid data tokens. Specify a valid data token."),
+ TokensSizeExceedError("%s0 Maximum number of tokens exceeded. The limit is 10000."),
+
+ // Delete Tokens
+ DeleteTokensRequestNull("%s0 Validation error. DeleteTokensRequest object is null. Specify a valid DeleteTokensRequest object."),
+ EmptyDeleteTokensData("%s0 Validation error. Tokens list is empty. Specify at least one token to delete."),
+ EmptyTokenInDeleteTokensData("%s0 Validation error. Invalid token in delete tokens request. Specify a valid token."),
+ DeleteTokensSizeExceedError("%s0 Maximum number of tokens exceeded. The limit is 10000."),
+
+ // Get
+ IdsKeyError("%s0 Validation error. 'ids' key is missing from the payload. Specify an 'ids' key."),
+ EmptyIds("%s0 Validation error. 'ids' can't be empty. Specify at least one id."),
+ EmptyIdInIds("%s0 Validation error. Invalid id in 'ids'. Specify a valid id."),
+ EmptyFields("%s0 Validation error. Fields are empty in get payload. Specify at least one field."),
+ EmptyFieldInFields("%s0 Validation error. Invalid field in 'fields'. Specify a valid field."),
+ RedactionKeyError("%s0 Validation error. 'redaction' key is missing from the payload. Specify a 'redaction' key."),
+ RedactionWithTokensNotSupported("%s0 Validation error. 'redaction' can't be used when 'returnTokens' is specified. Remove 'redaction' from payload if 'returnTokens' is specified."),
+ TokensGetColumnNotSupported("%s0 Validation error. Column name and/or column values can't be used when 'returnTokens' is specified. Remove unique column values or 'returnTokens' from the payload."),
+ EmptyOffset("%s0 Validation error. 'offset' can't be empty. Specify an offset."),
+ EmptyLimit("%s0 Validation error. 'limit' can't be empty. Specify a limit."),
+ UniqueColumnOrIdsKeyError("%s0 Validation error. 'ids' or 'columnName' key is missing from the payload. Specify the ids or unique 'columnName' in payload."),
+ BothIdsAndColumnDetailsSpecified("%s0 Validation error. Both Skyflow IDs and column details can't be specified. Either specify Skyflow IDs or unique column details."),
+ ColumnNameKeyError("%s0 Validation error. 'columnName' isn't specified whereas 'columnValues' are specified. Either add 'columnName' or remove 'columnValues'."),
+ EmptyColumnName("%s0 Validation error. 'columnName' can't be empty. Specify a column name."),
+ ColumnValuesKeyErrorGet("%s0 Validation error. 'columnValues' aren't specified whereas 'columnName' is specified. Either add 'columnValues' or remove 'columnName'."),
+ EmptyColumnValues("%s0 Validation error. 'columnValues' can't be empty. Specify at least one column value"),
+ EmptyValueInColumnValues("%s0 Validation error. Invalid value in column values. Specify a valid column value."),
+ IdsOrUniqueValuesKeyError("%s0 Validation error. 'ids' or 'uniqueValues' key is missing from the payload. Specify ids or uniqueValues in payload."),
+ BothIdsAndUniqueValuesSpecified("%s0 Validation error. Both Skyflow IDs and unique values can't be specified. Either specify Skyflow IDs or unique values."),
+ EmptyUniqueValues("%s0 Validation error. 'uniqueValues' can't be empty. Specify at least one unique value."),
+ EmptyUniqueValueInUniqueValues("%s0 Validation error. Invalid unique value in 'uniqueValues'. Specify a valid unique value."),
+ NullColumnRedactions("%s0 Validation error. Column redaction object can not be null. Specify a valid column redaction object."),
+ NullColumnNameInColumnRedaction("%s0 Validation error. Column name can not be null or empty in column redaction. Specify a valid column name."),
+ NullRedactionInColumnRedaction("%s0 Validation error. Redaction can not be null or empty in column redaction. Specify a valid redaction."),
+ BothSingleTableFieldsAndRecordsSpecified("%s0 Validation error. Both single-table lookup fields ('table', 'ids', 'fields', 'uniqueValues', 'columnRedactions') and 'records' can't be specified. Either specify single-table fields or 'records'."),
+ NullGetRecordRequest("%s0 Validation error. Record in 'records' is null. Specify a valid record."),
+
+ TokenKeyError("%s0 Validation error. 'token' key is missing from the payload. Specify a 'token' key."),
+ PartialSuccess("%s0 Validation error. Check 'SkyflowError.data' for details."),
+
+ // Update
+ DataKeyError("%s0 Validation error. 'data' key is missing from the payload. Specify a 'data' key."),
+ EmptyData("%s0 Validation error. 'data' can't be empty. Specify data."),
+ SkyflowIdKeyError("%s0 Validation error. 'skyflow_id' is missing from the data payload. Specify a 'skyflow_id'."),
+ InvalidSkyflowIdType("%s0 Validation error. Invalid type for 'skyflow_id' in data payload. Specify 'skyflow_id' as a string."),
+ EmptySkyflowId("%s0 Validation error. 'skyflow_id' can't be empty. Specify a skyflow id."),
+
+ // Query
+ QueryKeyError("%s0 Validation error. 'query' key is missing from the payload. Specify a 'query' key."),
+ EmptyQuery("%s0 Validation error. 'query' can't be empty. Specify a query"),
+
+ // Tokenize
+ ColumnValuesKeyErrorTokenize("%s0 Validation error. 'columnValues' key is missing from the payload. Specify a 'columnValues' key."),
+ EmptyColumnGroupInColumnValue("%s0 Validation error. Invalid column group in column value. Specify a valid column group."),
+ TokenizeRequestNull("%s0 Validation error. TokenizeRequest object is null. Specify a valid TokenizeRequest object."),
+ EmptyTokenizeData("%s0 Validation error. Tokenize data is empty. Specify at least one tokenize record."),
+ TokenizeRecordNull("%s0 Validation error. TokenizeRecord in the list is null. Specify a valid TokenizeRecord object."),
+ EmptyValueInTokenizeRecord("%s0 Validation error. Value in TokenizeRecord is null or empty. Specify a valid value."),
+ EmptyTokenGroupNamesInTokenizeRecord("%s0 Validation error. TokenGroupNames in TokenizeRecord is null or empty. Specify at least one token group name."),
+ EmptyTokenGroupNameInTokenizeRecord("%s0 Validation error. Token group name in TokenizeRecord is null or empty. Specify a valid token group name."),
+ TokenizeDataSizeExceedError("%s0 Maximum number of tokenize records exceeded. The limit is 10000."),
+ MissingIndexInBulkTokenizeRecord("%s0 Validation error. Index in BulkTokenizeRequestRecord is null. Specify an index for every record."),
+ DuplicateIndexInBulkTokenizeRecord("%s0 Validation error. Duplicate index in BulkTokenizeRequestRecord. Specify a unique index for every record."),
+
+ // Connection
+ InvalidRequestHeaders("%s0 Validation error. Request headers aren't valid. Specify valid request headers."),
+ EmptyRequestHeaders("%s0 Validation error. Request headers are empty. Specify valid request headers."),
+ InvalidPathParams("%s0 Validation error. Path parameters aren't valid. Specify valid path parameters."),
+ EmptyPathParams("%s0 Validation error. Path parameters are empty. Specify valid path parameters."),
+ InvalidQueryParams("%s0 Validation error. Query parameters aren't valid. Specify valid query parameters."),
+ EmptyQueryParams("%s0 Validation error. Query parameters are empty. Specify valid query parameters."),
+ InvalidRequestBody("%s0 Validation error. Invalid request body. Specify the request body as an object."),
+ EmptyRequestBody("%s0 Validation error. Request body can't be empty. Specify a valid request body."),
+
+ // File upload
+ ColumnNameKeyErrorFileUpload("%s0 Validation error. columnName is missing from the payload. Specify a columnName key."),
+ MissingFileSourceInUploadFileRequest("%s0 Validation error. Provide exactly one of filePath, base64, or fileObject."),
+ FileNameMustBeProvidedWithFileObject("%s0 Validation error. fileName must be provided when using fileObject."),
+ InvalidFileObject("%s0 Validation error. Invalid file object in file upload request. Specify a valid file object."),
+ InvalidBase64("%s0 Validation error. Invalid base64 string in file upload request. Specify a valid base64 string."),
+
+ // detect
+ InvalidTextInDeIdentify("%s0 Validation error. The text field is required and must be a non-empty string. Specify a valid text."),
+ InvalidTextInReIdentify("%s0 Validation error. The text field is required and must be a non-empty string. Specify a valid text."),
+
+ //Detect Files
+ InvalidNullFileInDeIdentifyFile("%s0 Validation error. The file field is required and must not be null. Specify a valid file object."),
+ InvalidFilePath("%s0 Validation error. The file path is invalid. Specify a valid file path."),
+ BothFileAndFilePathProvided("%s0 Validation error. Both file and filePath are provided. Specify either file object or filePath, not both."),
+ FileNotFoundToDeidentify("%s0 Validation error. The file to deidentify was not found at the specified path. Verify the file path and try again."),
+ FileNotReadableToDeidentify("%s0 Validation error. The file to deidentify is not readable. Check the file permissions and try again."),
+ InvalidPixelDensityToDeidentifyFile("%s0 Validation error. Should be a positive integer. Specify a valid pixel density."),
+ InvalidMaxResolution("%s0 Validation error. Should be a positive integer. Specify a valid max resolution."),
+ OutputDirectoryNotFound("%s0 Validation error. The output directory for deidentified files was not found at the specified path. Verify the output directory path and try again."),
+ InvalidPermission("%s0 Validation error. The output directory for deidentified files is not writable. Check the directory permissions and try again."),
+ InvalidWaitTime("%s0 Validation error. The wait time for deidentify file operation should be a positive integer. Specify a valid wait time."),
+ WaitTimeExceedsLimit("%s0 Validation error. The wait time for deidentify file operation exceeds the maximum limit of 64 seconds. Specify a wait time less than or equal to 60 seconds."),
+ InvalidOrEmptyRunId("%s0 Validation error. The run ID is invalid or empty. Specify a valid run ID."),
+ FailedToEncodeFile("%s0 Validation error. Failed to encode the file. Ensure the file is in a supported format and try again."),
+ FailedToDecodeFileFromResponse("%s0 Failed to decode the file from the response. Ensure the response is valid and try again."),
+ EmptyFileAndFilePathInDeIdentifyFile("%s0 Validation error. Both file and filePath are empty. Specify either file object or filePath, not both."),
+ VaultTokenFormatIsNotAllowedForFiles("%s0 Validation error. Vault token format is not allowed for deidentify file request."),
+ PollingForResultsFailed("%s0 API error. Polling for results failed. Unable to retrieve the deidentified file"),
+ FailedToSaveProcessedFile("%s0 Validation error. Failed to save the processed file. Ensure the output directory is valid and writable."),
+ InvalidAudioFileType("%s0 Validation error. The file type is not supported. Specify a valid file type mp3 or wav."),
+ // Generic
+ ErrorOccurred("%s0 API error. Error occurred."),
+
+ DetokenizeRequestNull("%s0 Validation error. DetokenizeRequest object is null. Specify a valid DetokenizeRequest object."),
+
+ NullTokenGroupRedactions("%s0 Validation error. TokenGroupRedaction in the list is null. Specify a valid TokenGroupRedactions object."),
+
+ NullRedactionInTokenGroup("%s0 Validation error. Redaction in TokenGroupRedactions is null or empty. Specify a valid redaction."),
+
+ NullTokenGroupNameInTokenGroup("%s0 Validation error. TokenGroupName in TokenGroupRedactions is null or empty. Specify a valid tokenGroupName."),
+ InvalidRecord("%s0 Validation error. InsertRecord object in the list is invalid. Specify a valid InsertRecord object."),
+ ;
+
+ private final String message;
+
+ ErrorMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message.replace("%s0", SdkVersion.getSdkPrefix());
+ }
+}
diff --git a/src/main/java/com/skyflow/errors/HttpStatus.java b/common/src/main/java/com/skyflow/errors/HttpStatus.java
similarity index 100%
rename from src/main/java/com/skyflow/errors/HttpStatus.java
rename to common/src/main/java/com/skyflow/errors/HttpStatus.java
diff --git a/src/main/java/com/skyflow/errors/SkyflowException.java b/common/src/main/java/com/skyflow/errors/SkyflowException.java
similarity index 95%
rename from src/main/java/com/skyflow/errors/SkyflowException.java
rename to common/src/main/java/com/skyflow/errors/SkyflowException.java
index 6fedf9c3..2b043f92 100644
--- a/src/main/java/com/skyflow/errors/SkyflowException.java
+++ b/common/src/main/java/com/skyflow/errors/SkyflowException.java
@@ -4,7 +4,7 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
-import com.skyflow.utils.Constants;
+import com.skyflow.utils.BaseConstants;
import java.util.List;
import java.util.Map;
@@ -27,7 +27,7 @@
* Typical error-handling pattern:
*
{@code
* try {
- * InsertResponse response = vault.insert(request);
+ * response = vault.insert(request);
* } catch (SkyflowException e) {
* System.err.println("HTTP " + e.getHttpCode() + " — " + e.getMessage());
* if (e.getRequestId() != null) {
@@ -113,7 +113,7 @@ public String getRequestId() {
}
private void setRequestId(Map> responseHeaders) {
- List ids = responseHeaders.get(Constants.REQUEST_ID_HEADER_KEY);
+ List ids = responseHeaders.get(BaseConstants.REQUEST_ID_HEADER_KEY);
this.requestId = ids == null ? null : ids.get(0);
}
@@ -134,10 +134,11 @@ private void setHttpStatus() {
/**
* Returns the HTTP status code (e.g. 400, 404, 500).
- * Defaults to 400 when the server returned a non-positive code.
+ * Defaults to 400 when the server returned a non-positive code, and 0 when the
+ * exception carries no HTTP code at all (e.g. it wraps a local failure).
*/
public int getHttpCode() {
- return httpCode;
+ return httpCode == null ? 0 : httpCode;
}
/**
@@ -151,7 +152,7 @@ public JsonArray getDetails() {
private void setDetails(Map> responseHeaders) {
JsonElement detailsElement = ((JsonObject) responseBody.get("error")).get("details");
- List errorFromClientHeader = responseHeaders.get(Constants.ERROR_FROM_CLIENT_HEADER_KEY);
+ List errorFromClientHeader = responseHeaders.get(BaseConstants.ERROR_FROM_CLIENT_HEADER_KEY);
if (detailsElement != null) {
this.details = detailsElement.getAsJsonArray();
}
diff --git a/common/src/main/java/com/skyflow/generated/auth/rest/ApiClient.java b/common/src/main/java/com/skyflow/generated/auth/rest/ApiClient.java
new file mode 100644
index 00000000..a1dd3aae
--- /dev/null
+++ b/common/src/main/java/com/skyflow/generated/auth/rest/ApiClient.java
@@ -0,0 +1,29 @@
+/**
+ * This file was auto-generated by Fern from our API Definition.
+ */
+package com.skyflow.generated.auth.rest;
+
+import com.skyflow.generated.auth.rest.core.ClientOptions;
+import com.skyflow.generated.auth.rest.core.Suppliers;
+import com.skyflow.generated.auth.rest.resources.authentication.AuthenticationClient;
+
+import java.util.function.Supplier;
+
+public class ApiClient {
+ protected final ClientOptions clientOptions;
+
+ protected final Supplier authenticationClient;
+
+ public ApiClient(ClientOptions clientOptions) {
+ this.clientOptions = clientOptions;
+ this.authenticationClient = Suppliers.memoize(() -> new AuthenticationClient(clientOptions));
+ }
+
+ public AuthenticationClient authentication() {
+ return this.authenticationClient.get();
+ }
+
+ public static ApiClientBuilder builder() {
+ return new ApiClientBuilder();
+ }
+}
diff --git a/common/src/main/java/com/skyflow/generated/auth/rest/ApiClientBuilder.java b/common/src/main/java/com/skyflow/generated/auth/rest/ApiClientBuilder.java
new file mode 100644
index 00000000..aed3ed24
--- /dev/null
+++ b/common/src/main/java/com/skyflow/generated/auth/rest/ApiClientBuilder.java
@@ -0,0 +1,67 @@
+/**
+ * This file was auto-generated by Fern from our API Definition.
+ */
+package com.skyflow.generated.auth.rest;
+
+import com.skyflow.generated.auth.rest.core.ClientOptions;
+import com.skyflow.generated.auth.rest.core.Environment;
+import okhttp3.OkHttpClient;
+
+public final class ApiClientBuilder {
+ private ClientOptions.Builder clientOptionsBuilder = ClientOptions.builder();
+
+ private String token = null;
+
+ private Environment environment = Environment.PRODUCTION;
+
+ /**
+ * Sets token
+ */
+ public ApiClientBuilder token(String token) {
+ this.token = token;
+ return this;
+ }
+
+ public ApiClientBuilder environment(Environment environment) {
+ this.environment = environment;
+ return this;
+ }
+
+ public ApiClientBuilder url(String url) {
+ this.environment = Environment.custom(url);
+ return this;
+ }
+
+ /**
+ * Sets the timeout (in seconds) for the client. Defaults to 60 seconds.
+ */
+ public ApiClientBuilder timeout(int timeout) {
+ this.clientOptionsBuilder.timeout(timeout);
+ return this;
+ }
+
+ /**
+ * Sets the maximum number of retries for the client. Defaults to 2 retries.
+ */
+ public ApiClientBuilder maxRetries(int maxRetries) {
+ this.clientOptionsBuilder.maxRetries(maxRetries);
+ return this;
+ }
+
+ /**
+ * Sets the underlying OkHttp client
+ */
+ public ApiClientBuilder httpClient(OkHttpClient httpClient) {
+ this.clientOptionsBuilder.httpClient(httpClient);
+ return this;
+ }
+
+ public ApiClient build() {
+ if (token == null) {
+ throw new RuntimeException("Please provide token");
+ }
+ this.clientOptionsBuilder.addHeader("Authorization", "Bearer " + this.token);
+ clientOptionsBuilder.environment(this.environment);
+ return new ApiClient(clientOptionsBuilder.build());
+ }
+}
diff --git a/common/src/main/java/com/skyflow/generated/auth/rest/AsyncApiClient.java b/common/src/main/java/com/skyflow/generated/auth/rest/AsyncApiClient.java
new file mode 100644
index 00000000..748eb02e
--- /dev/null
+++ b/common/src/main/java/com/skyflow/generated/auth/rest/AsyncApiClient.java
@@ -0,0 +1,29 @@
+/**
+ * This file was auto-generated by Fern from our API Definition.
+ */
+package com.skyflow.generated.auth.rest;
+
+import com.skyflow.generated.auth.rest.core.ClientOptions;
+import com.skyflow.generated.auth.rest.core.Suppliers;
+import com.skyflow.generated.auth.rest.resources.authentication.AsyncAuthenticationClient;
+
+import java.util.function.Supplier;
+
+public class AsyncApiClient {
+ protected final ClientOptions clientOptions;
+
+ protected final Supplier authenticationClient;
+
+ public AsyncApiClient(ClientOptions clientOptions) {
+ this.clientOptions = clientOptions;
+ this.authenticationClient = Suppliers.memoize(() -> new AsyncAuthenticationClient(clientOptions));
+ }
+
+ public AsyncAuthenticationClient authentication() {
+ return this.authenticationClient.get();
+ }
+
+ public static AsyncApiClientBuilder builder() {
+ return new AsyncApiClientBuilder();
+ }
+}
diff --git a/common/src/main/java/com/skyflow/generated/auth/rest/AsyncApiClientBuilder.java b/common/src/main/java/com/skyflow/generated/auth/rest/AsyncApiClientBuilder.java
new file mode 100644
index 00000000..2e30d45a
--- /dev/null
+++ b/common/src/main/java/com/skyflow/generated/auth/rest/AsyncApiClientBuilder.java
@@ -0,0 +1,67 @@
+/**
+ * This file was auto-generated by Fern from our API Definition.
+ */
+package com.skyflow.generated.auth.rest;
+
+import com.skyflow.generated.auth.rest.core.ClientOptions;
+import com.skyflow.generated.auth.rest.core.Environment;
+import okhttp3.OkHttpClient;
+
+public final class AsyncApiClientBuilder {
+ private ClientOptions.Builder clientOptionsBuilder = ClientOptions.builder();
+
+ private String token = null;
+
+ private Environment environment = Environment.PRODUCTION;
+
+ /**
+ * Sets token
+ */
+ public AsyncApiClientBuilder token(String token) {
+ this.token = token;
+ return this;
+ }
+
+ public AsyncApiClientBuilder environment(Environment environment) {
+ this.environment = environment;
+ return this;
+ }
+
+ public AsyncApiClientBuilder url(String url) {
+ this.environment = Environment.custom(url);
+ return this;
+ }
+
+ /**
+ * Sets the timeout (in seconds) for the client. Defaults to 60 seconds.
+ */
+ public AsyncApiClientBuilder timeout(int timeout) {
+ this.clientOptionsBuilder.timeout(timeout);
+ return this;
+ }
+
+ /**
+ * Sets the maximum number of retries for the client. Defaults to 2 retries.
+ */
+ public AsyncApiClientBuilder maxRetries(int maxRetries) {
+ this.clientOptionsBuilder.maxRetries(maxRetries);
+ return this;
+ }
+
+ /**
+ * Sets the underlying OkHttp client
+ */
+ public AsyncApiClientBuilder httpClient(OkHttpClient httpClient) {
+ this.clientOptionsBuilder.httpClient(httpClient);
+ return this;
+ }
+
+ public AsyncApiClient build() {
+ if (token == null) {
+ throw new RuntimeException("Please provide token");
+ }
+ this.clientOptionsBuilder.addHeader("Authorization", "Bearer " + this.token);
+ clientOptionsBuilder.environment(this.environment);
+ return new AsyncApiClient(clientOptionsBuilder.build());
+ }
+}
diff --git a/common/src/main/java/com/skyflow/generated/auth/rest/core/ApiClientApiException.java b/common/src/main/java/com/skyflow/generated/auth/rest/core/ApiClientApiException.java
new file mode 100644
index 00000000..53d67f0b
--- /dev/null
+++ b/common/src/main/java/com/skyflow/generated/auth/rest/core/ApiClientApiException.java
@@ -0,0 +1,74 @@
+/**
+ * This file was auto-generated by Fern from our API Definition.
+ */
+package com.skyflow.generated.auth.rest.core;
+
+import okhttp3.Response;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This exception type will be thrown for any non-2XX API responses.
+ */
+public class ApiClientApiException extends ApiClientException {
+ /**
+ * The error code of the response that triggered the exception.
+ */
+ private final int statusCode;
+
+ /**
+ * The body of the response that triggered the exception.
+ */
+ private final Object body;
+
+ private final Map> headers;
+
+ public ApiClientApiException(String message, int statusCode, Object body) {
+ super(message);
+ this.statusCode = statusCode;
+ this.body = body;
+ this.headers = new HashMap<>();
+ }
+
+ public ApiClientApiException(String message, int statusCode, Object body, Response rawResponse) {
+ super(message);
+ this.statusCode = statusCode;
+ this.body = body;
+ this.headers = new HashMap<>();
+ rawResponse.headers().forEach(header -> {
+ String key = header.component1();
+ String value = header.component2();
+ this.headers.computeIfAbsent(key, _str -> new ArrayList<>()).add(value);
+ });
+ }
+
+ /**
+ * @return the statusCode
+ */
+ public int statusCode() {
+ return this.statusCode;
+ }
+
+ /**
+ * @return the body
+ */
+ public Object body() {
+ return this.body;
+ }
+
+ /**
+ * @return the headers
+ */
+ public Map> headers() {
+ return this.headers;
+ }
+
+ @Override
+ public String toString() {
+ return "ApiClientApiException{" + "message: " + getMessage() + ", statusCode: " + statusCode + ", body: " + body
+ + "}";
+ }
+}
diff --git a/common/src/main/java/com/skyflow/generated/auth/rest/core/ApiClientException.java b/common/src/main/java/com/skyflow/generated/auth/rest/core/ApiClientException.java
new file mode 100644
index 00000000..f08afa2e
--- /dev/null
+++ b/common/src/main/java/com/skyflow/generated/auth/rest/core/ApiClientException.java
@@ -0,0 +1,17 @@
+/**
+ * This file was auto-generated by Fern from our API Definition.
+ */
+package com.skyflow.generated.auth.rest.core;
+
+/**
+ * This class serves as the base exception for all errors in the SDK.
+ */
+public class ApiClientException extends RuntimeException {
+ public ApiClientException(String message) {
+ super(message);
+ }
+
+ public ApiClientException(String message, Exception e) {
+ super(message, e);
+ }
+}
diff --git a/common/src/main/java/com/skyflow/generated/auth/rest/core/ApiClientHttpResponse.java b/common/src/main/java/com/skyflow/generated/auth/rest/core/ApiClientHttpResponse.java
new file mode 100644
index 00000000..8a28d22f
--- /dev/null
+++ b/common/src/main/java/com/skyflow/generated/auth/rest/core/ApiClientHttpResponse.java
@@ -0,0 +1,38 @@
+/**
+ * This file was auto-generated by Fern from our API Definition.
+ */
+package com.skyflow.generated.auth.rest.core;
+
+import okhttp3.Response;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public final class ApiClientHttpResponse {
+
+ private final T body;
+
+ private final Map> headers;
+
+ public ApiClientHttpResponse(T body, Response rawResponse) {
+ this.body = body;
+
+ Map> headers = new HashMap<>();
+ rawResponse.headers().forEach(header -> {
+ String key = header.component1();
+ String value = header.component2();
+ headers.computeIfAbsent(key, _str -> new ArrayList<>()).add(value);
+ });
+ this.headers = headers;
+ }
+
+ public T body() {
+ return this.body;
+ }
+
+ public Map> headers() {
+ return headers;
+ }
+}
diff --git a/common/src/main/java/com/skyflow/generated/auth/rest/core/ClientOptions.java b/common/src/main/java/com/skyflow/generated/auth/rest/core/ClientOptions.java
new file mode 100644
index 00000000..4eee6b92
--- /dev/null
+++ b/common/src/main/java/com/skyflow/generated/auth/rest/core/ClientOptions.java
@@ -0,0 +1,171 @@
+/**
+ * This file was auto-generated by Fern from our API Definition.
+ */
+package com.skyflow.generated.auth.rest.core;
+
+import okhttp3.OkHttpClient;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+
+public final class ClientOptions {
+ private final Environment environment;
+
+ private final Map headers;
+
+ private final Map> headerSuppliers;
+
+ private final OkHttpClient httpClient;
+
+ private final int timeout;
+
+ private ClientOptions(
+ Environment environment,
+ Map headers,
+ Map> headerSuppliers,
+ OkHttpClient httpClient,
+ int timeout) {
+ this.environment = environment;
+ this.headers = new HashMap<>();
+ this.headers.putAll(headers);
+ this.headers.putAll(new HashMap() {
+ {
+ put("X-Fern-Language", "JAVA");
+ put("X-Fern-SDK-Name", "com.skyflow.generated.rest.fern:api-sdk");
+ put("X-Fern-SDK-Version", "0.0.279");
+ }
+ });
+ this.headerSuppliers = headerSuppliers;
+ this.httpClient = httpClient;
+ this.timeout = timeout;
+ }
+
+ public Environment environment() {
+ return this.environment;
+ }
+
+ public Map headers(RequestOptions requestOptions) {
+ Map values = new HashMap<>(this.headers);
+ headerSuppliers.forEach((key, supplier) -> {
+ values.put(key, supplier.get());
+ });
+ if (requestOptions != null) {
+ values.putAll(requestOptions.getHeaders());
+ }
+ return values;
+ }
+
+ public int timeout(RequestOptions requestOptions) {
+ if (requestOptions == null) {
+ return this.timeout;
+ }
+ return requestOptions.getTimeout().orElse(this.timeout);
+ }
+
+ public OkHttpClient httpClient() {
+ return this.httpClient;
+ }
+
+ public OkHttpClient httpClientWithTimeout(RequestOptions requestOptions) {
+ if (requestOptions == null) {
+ return this.httpClient;
+ }
+ return this.httpClient
+ .newBuilder()
+ .callTimeout(requestOptions.getTimeout().get(), requestOptions.getTimeoutTimeUnit())
+ .connectTimeout(0, TimeUnit.SECONDS)
+ .writeTimeout(0, TimeUnit.SECONDS)
+ .readTimeout(0, TimeUnit.SECONDS)
+ .build();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private Environment environment;
+
+ private final Map headers = new HashMap<>();
+
+ private final Map> headerSuppliers = new HashMap<>();
+
+ private int maxRetries = 2;
+
+ private Optional timeout = Optional.empty();
+
+ private OkHttpClient httpClient = null;
+
+ public Builder environment(Environment environment) {
+ this.environment = environment;
+ return this;
+ }
+
+ public Builder addHeader(String key, String value) {
+ this.headers.put(key, value);
+ return this;
+ }
+
+ public Builder addHeader(String key, Supplier