Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
348 changes: 348 additions & 0 deletions src/main/java/com/skyflow/VaultClient.java

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/main/java/com/skyflow/enums/MaskingMethod.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.skyflow.enums;

public enum MaskingMethod {
BLACKOUT("blackout"),
BLACKBOX("blackbox"),
BLUR("blur");

private final String maskingMethod;
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/skyflow/errors/ErrorMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,18 @@ public enum ErrorMessage {
InvalidEmptyTextInDeIdentify("%s0 Validation error. The text field is required string and must not be empty string. Specify a valid text."),
InvalidNullTextInReIdentify("%s0 Validation error. The text field is required string and must not be null. Specify a valid text."),
InvalidEmptyTextInReIdentify("%s0 Validation error. The text field is required string and must not be 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."),
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."),
;
private final String message;

Expand Down
71 changes: 64 additions & 7 deletions src/main/java/com/skyflow/errors/SkyflowException.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,37 @@ public SkyflowException(int httpCode, Throwable cause, Map<String, List<String>>
super(cause);
this.httpCode = httpCode;
setRequestId(responseHeaders);
setResponseBody(responseBody, responseHeaders);
// Determine if responseBody is a JSON string with "error" key or a plain string
if (isJsonWithErrorObject(responseBody)) {
setResponseBodyFromJson(responseBody, responseHeaders);
} else {
this.message = responseBody;
this.details = new JsonArray();
}
}

private void setResponseBody(String responseBody, Map<String, List<String>> responseHeaders) {
// Helper to check if responseBody is a JSON string with "error" key
private boolean isJsonWithErrorObject(String responseBody) {
try {
if (responseBody == null) return false;
JsonObject obj = JsonParser.parseString(responseBody).getAsJsonObject();
return obj.has("error");
} catch (Exception e) {
return false;
}
}

// Handles new error structure: {error={grpc_code=3, http_code=400, message=..., http_status=..., details=[]}}
private void setResponseBodyFromJson(String responseBody, Map<String, List<String>> responseHeaders) {
try {
if (responseBody != null) {
this.responseBody = JsonParser.parseString(responseBody).getAsJsonObject();
if (this.responseBody.get("error") != null) {
setGrpcCode();
setHttpStatus();
setMessage();
setDetails(responseHeaders);
if (this.responseBody.has("error")) {
JsonObject errorObj = this.responseBody.getAsJsonObject("error");
setGrpcCode(errorObj);
setHttpStatus(errorObj);
setMessage(errorObj);
setDetails(errorObj, responseHeaders);
}
}
} catch (JsonSyntaxException e) {
Expand All @@ -71,21 +90,43 @@ private void setRequestId(Map<String, List<String>> responseHeaders) {
}
}

// For legacy error structure
private void setMessage() {
JsonElement messageElement = ((JsonObject) responseBody.get("error")).get("message");
this.message = messageElement == null ? null : messageElement.getAsString();
}

// For new error structure
private void setMessage(JsonObject errorObj) {
JsonElement messageElement = errorObj.get("message");
this.message = messageElement == null ? null : messageElement.getAsString();
}

// For legacy error structure
private void setGrpcCode() {
JsonElement grpcElement = ((JsonObject) responseBody.get("error")).get("grpc_code");
this.grpcCode = grpcElement == null ? null : grpcElement.getAsInt();
}

// For new error structure
private void setGrpcCode(JsonObject errorObj) {
JsonElement grpcElement = errorObj.get("grpc_code");
this.grpcCode = grpcElement == null ? null : grpcElement.getAsInt();
}

// For legacy error structure
private void setHttpStatus() {
JsonElement statusElement = ((JsonObject) responseBody.get("error")).get("http_status");
this.httpStatus = statusElement == null ? null : statusElement.getAsString();
}

// For new error structure
private void setHttpStatus(JsonObject errorObj) {
JsonElement statusElement = errorObj.get("http_status");
this.httpStatus = statusElement == null ? null : statusElement.getAsString();
}

// For legacy error structure
private void setDetails(Map<String, List<String>> responseHeaders) {
JsonElement detailsElement = ((JsonObject) responseBody.get("error")).get("details");
List<String> errorFromClientHeader = responseHeaders.get("error-from-client");
Expand All @@ -101,6 +142,22 @@ private void setDetails(Map<String, List<String>> responseHeaders) {
}
}

// For new error structure
private void setDetails(JsonObject errorObj, Map<String, List<String>> responseHeaders) {
JsonElement detailsElement = errorObj.get("details");
List<String> errorFromClientHeader = responseHeaders.get("error-from-client");
if (detailsElement != null && detailsElement.isJsonArray()) {
this.details = detailsElement.getAsJsonArray();
}
if (errorFromClientHeader != null) {
this.details = this.details == null ? new JsonArray() : this.details;
String errorFromClient = errorFromClientHeader.get(0);
JsonObject detailObject = new JsonObject();
detailObject.addProperty("errorFromClient", errorFromClient);
this.details.add(detailObject);
}
}

public int getHttpCode() {
return httpCode;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private ClientOptions(
{
put("X-Fern-Language", "JAVA");
put("X-Fern-SDK-Name", "com.skyflow.fern:api-sdk");
put("X-Fern-SDK-Version", "0.0.202");
put("X-Fern-SDK-Version", "0.0.208");
}
});
this.headerSuppliers = headerSuppliers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.fasterxml.jackson.annotation.JsonValue;

public enum DeidentifyImageRequestMaskingMethod {
BLACKOUT("blackout"),
BLACKBOX("blackbox"),

BLUR("blur");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import com.fasterxml.jackson.annotation.JsonValue;

public enum DeidentifyStatusResponseOutputType {
BASE_64("base64"),
BASE_64("BASE64"),

EFS_PATH("efs_path");
EFS_PATH("EFS_PATH"),

UNKNOWN("UNKNOWN");

private final String value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
import com.fasterxml.jackson.annotation.JsonValue;

public enum DeidentifyStatusResponseStatus {
FAILED("failed"),
FAILED("FAILED"),

IN_PROGRESS("in_progress"),
IN_PROGRESS("IN_PROGRESS"),

SUCCESS("success");
SUCCESS("SUCCESS");

private final String value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@JsonDeserialize(builder = ReidentifyStringResponse.Builder.class)
public final class ReidentifyStringResponse {
private final Optional<String> processedText;
private final Optional<String> text;

private final Map<String, Object> additionalProperties;

private ReidentifyStringResponse(Optional<String> processedText, Map<String, Object> additionalProperties) {
this.processedText = processedText;
private ReidentifyStringResponse(Optional<String> text, Map<String, Object> additionalProperties) {
this.text = text;
this.additionalProperties = additionalProperties;
}

/**
* @return Re-identified text.
*/
@JsonProperty("processed_text")
public Optional<String> getProcessedText() {
return processedText;
@JsonProperty("text")
public Optional<String> getText() {
return text;
}

@java.lang.Override
Expand All @@ -49,12 +49,12 @@ public Map<String, Object> getAdditionalProperties() {
}

private boolean equalTo(ReidentifyStringResponse other) {
return processedText.equals(other.processedText);
return text.equals(other.text);
}

@java.lang.Override
public int hashCode() {
return Objects.hash(this.processedText);
return Objects.hash(this.text);
}

@java.lang.Override
Expand All @@ -68,31 +68,31 @@ public static Builder builder() {

@JsonIgnoreProperties(ignoreUnknown = true)
public static final class Builder {
private Optional<String> processedText = Optional.empty();
private Optional<String> text = Optional.empty();

@JsonAnySetter
private Map<String, Object> additionalProperties = new HashMap<>();

private Builder() {}

public Builder from(ReidentifyStringResponse other) {
processedText(other.getProcessedText());
text(other.getText());
return this;
}

@JsonSetter(value = "processed_text", nulls = Nulls.SKIP)
public Builder processedText(Optional<String> processedText) {
this.processedText = processedText;
@JsonSetter(value = "text", nulls = Nulls.SKIP)
public Builder text(Optional<String> text) {
this.text = text;
return this;
}

public Builder processedText(String processedText) {
this.processedText = Optional.ofNullable(processedText);
public Builder text(String text) {
this.text = Optional.ofNullable(text);
return this;
}

public ReidentifyStringResponse build() {
return new ReidentifyStringResponse(processedText, additionalProperties);
return new ReidentifyStringResponse(text, additionalProperties);
}
}
}
3 changes: 2 additions & 1 deletion src/main/java/com/skyflow/logs/ErrorLogs.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ public enum ErrorLogs {
INVALID_NULL_TEXT_IN_REIDENTIFY("Invalid %s1 request. The text field is required string and must not be null. Specify a valid text."),
INVALID_EMPTY_TEXT_IN_REIDENTIFY("Invalid %s1 request. The text field is required string and must not be empty string. Specify a valid text."),
REIDENTIFY_TEXT_REQUEST_REJECTED("ReIdentify text request resulted in failure."),

DEIDENTIFY_FILE_REQUEST_REJECTED("DeIdentify file request resulted in failure."),
GET_DETECT_RUN_REQUEST_REJECTED("Get detect run request resulted in failure."),
;

private final String log;
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/skyflow/logs/InfoLogs.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ public enum InfoLogs {
DEIDENTIFY_TEXT_REQUEST_RESOLVED("DeIdentify text request resolved."),
REIDENTIFY_TEXT_TRIGGERED("ReIdentify text method triggered."),
REIDENTIFY_TEXT_REQUEST_RESOLVED("ReIdentify text request resolved."),
DEIDENTIFY_FILE_TRIGGERED("DeIdentify file method triggered."),
VALIDATE_DEIDENTIFY_FILE_REQUEST("Validating deidentify file request."),
DEIDENTIFY_FILE_REQUEST_RESOLVED("DeIdentify file request resolved."),
DEIDENTIFY_FILE_SUCCESS("File deidentified successfully."),
GET_DETECT_RUN_TRIGGERED("Get detect run method triggered."),
VALIDATE_GET_DETECT_RUN_REQUEST("Validating get detect run request."),
;


Expand Down
76 changes: 74 additions & 2 deletions src/main/java/com/skyflow/utils/validations/Validations.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
import com.skyflow.utils.logger.LogUtil;
import com.skyflow.vault.connection.InvokeConnectionRequest;
import com.skyflow.vault.data.*;
import com.skyflow.vault.detect.DeidentifyTextRequest;
import com.skyflow.vault.detect.ReidentifyTextRequest;
import com.skyflow.vault.detect.*;
import com.skyflow.vault.tokens.ColumnValue;
import com.skyflow.vault.tokens.DetokenizeData;
import com.skyflow.vault.tokens.DetokenizeRequest;
import com.skyflow.vault.tokens.TokenizeRequest;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -792,4 +792,76 @@ private static void validateTokensMapWithTokenStrict(
}
}
}

public static void validateDeidentifyFileRequest(DeidentifyFileRequest request) throws SkyflowException {
if (request == null) {
throw new SkyflowException(ErrorMessage.EmptyRequestBody.getMessage());
}

File file = request.getFile();
if (file == null) {
throw new SkyflowException(ErrorMessage.InvalidNullFileInDeIdentifyFile.getMessage());
}
if (!file.exists() || !file.isFile()) {
throw new SkyflowException(ErrorMessage.FileNotFoundToDeidentify.getMessage());
}
if (!file.canRead()) {
throw new SkyflowException(ErrorMessage.FileNotReadableToDeidentify.getMessage());
}


// Validate pixelDensity and maxResolution
if (request.getPixelDensity() != null && request.getPixelDensity() <= 0) {
throw new SkyflowException(ErrorMessage.InvalidPixelDensityToDeidentifyFile.getMessage());
}
if (request.getMaxResolution() != null && request.getMaxResolution() <= 0) {
throw new SkyflowException(ErrorMessage.InvalidMaxResolution.getMessage());
}

// Validate AudioBleep
if (request.getBleep() != null) {
if (request.getBleep().getFrequency() == null || request.getBleep().getFrequency() <= 0) {
throw new SkyflowException(ErrorMessage.InvalidRequestBody.getMessage());
}
if (request.getBleep().getGain() == null || request.getBleep().getGain() < 0) {
throw new SkyflowException(ErrorMessage.InvalidRequestBody.getMessage());
}
if (request.getBleep().getStartPadding() == null || request.getBleep().getStartPadding() < 0) {
throw new SkyflowException(ErrorMessage.InvalidRequestBody.getMessage());
}
if (request.getBleep().getStopPadding() == null || request.getBleep().getStopPadding() < 0) {
throw new SkyflowException(ErrorMessage.InvalidRequestBody.getMessage());
}
}

// Validate outputDirectory if provided
if (request.getOutputDirectory() != null) {
File outDir = new File(request.getOutputDirectory());
if (!outDir.exists() || !outDir.isDirectory()) {
throw new SkyflowException(ErrorMessage.OutputDirectoryNotFound.getMessage());
}
if (!outDir.canWrite()) {
throw new SkyflowException(ErrorMessage.InvalidPermission.getMessage());
}
}

// Validate waitTime if provided
if (request.getWaitTime() != null && request.getWaitTime() <= 0) {
throw new SkyflowException(ErrorMessage.InvalidWaitTime.getMessage());
}
if(request.getWaitTime() > 64) {
throw new SkyflowException(ErrorMessage.WaitTimeExceedsLimit.getMessage());
}
}

public static void validateGetDetectRunRequest(GetDetectRunRequest request) throws SkyflowException {
if (request == null) {
throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyRequestBody.getMessage());
}

String runId = request.getRunId();
if (runId == null || runId.trim().isEmpty()) {
throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidOrEmptyRunId.getMessage());
}
}
}
Loading
Loading