Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ public static void main(String[] args) {
while (!generateVideosOperation.done().filter(Boolean::booleanValue).isPresent()) {
try {
Thread.sleep(10000); // Sleep for 10 seconds.
generateVideosOperation =
client.operations.getVideosOperation(generateVideosOperation, null);
generateVideosOperation = client.operations.get(generateVideosOperation, null);
System.out.println("Waiting for operation to complete...");
} catch (InterruptedException e) {
System.out.println("Thread was interrupted while sleeping.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public static void main(String[] args) {
try {
Thread.sleep(10000); // Sleep for 10 seconds.
try {
operation = client.async.operations.getVideosOperation(operation, null).get();
operation = client.async.operations.get(operation, null).get();
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
Expand All @@ -115,7 +115,7 @@ public static void main(String[] args) {

Video generatedVideo =
operation.response().get().generatedVideos().get().get(0).video().get();
// Do something with the video.
System.out.println("Video URL: " + generatedVideo.uri().get());
})
.join();
}
Expand Down
30 changes: 21 additions & 9 deletions src/main/java/com/google/genai/AsyncOperations.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@

package com.google.genai;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.genai.Common.BuiltRequest;
import com.google.genai.types.FetchPredictOperationConfig;
import com.google.genai.types.GenerateVideosOperation;
import com.google.genai.types.GetOperationConfig;
import com.google.genai.types.Operation;
import java.util.concurrent.CompletableFuture;

/** Async module of {@link Operations} */
Expand All @@ -35,7 +37,7 @@ public AsyncOperations(ApiClient apiClient) {
this.operations = new Operations(apiClient);
}

CompletableFuture<GenerateVideosOperation> privateGetVideosOperation(
CompletableFuture<JsonNode> privateGetVideosOperation(
String operationName, GetOperationConfig config) {
BuiltRequest builtRequest =
operations.buildRequestForPrivateGetVideosOperation(operationName, config);
Expand All @@ -49,7 +51,7 @@ CompletableFuture<GenerateVideosOperation> privateGetVideosOperation(
});
}

CompletableFuture<GenerateVideosOperation> privateFetchPredictVideosOperation(
CompletableFuture<JsonNode> privateFetchPredictVideosOperation(
String operationName, String resourceName, FetchPredictOperationConfig config) {
BuiltRequest builtRequest =
operations.buildRequestForPrivateFetchPredictVideosOperation(
Expand All @@ -73,19 +75,29 @@ CompletableFuture<GenerateVideosOperation> privateFetchPredictVideosOperation(
*/
public CompletableFuture<GenerateVideosOperation> getVideosOperation(
GenerateVideosOperation operation, GetOperationConfig config) {
return get(operation, config);
}

/**
* Gets the status of an Operation.
*
* @param operation An Operation.
* @param config The configuration for getting the operation.
* @return An Operation with the updated status of the operation.
*/
public <T, U extends Operation<T, U>> CompletableFuture<U> get(
U operation, GetOperationConfig config) {
if (!operation.name().isPresent()) {
throw new Error("Operation name is required.");
throw new IllegalArgumentException("Operation name is required.");
}

if (this.apiClient.vertexAI()) {
String resourceName = operation.name().get().split("/operations/")[0];

FetchPredictOperationConfig fetchConfig = FetchPredictOperationConfig.builder().build();

return this.privateFetchPredictVideosOperation(
operation.name().get(), resourceName, fetchConfig);
return this.privateFetchPredictVideosOperation(operation.name().get(), resourceName, null)
.thenApplyAsync(response -> operation.fromApiResponse(response, true));
} else {
return this.privateGetVideosOperation(operation.name().get(), config);
return this.privateGetVideosOperation(operation.name().get(), config)
.thenApplyAsync(response -> operation.fromApiResponse(response, false));
}
}
}
5 changes: 3 additions & 2 deletions src/main/java/com/google/genai/JsonSerializable.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
/** A class that can be serialized to JSON and deserialized from JSON. */
public abstract class JsonSerializable {

static final ObjectMapper objectMapper = new ObjectMapper();
@InternalApi protected static final ObjectMapper objectMapper = new ObjectMapper();

/** Custom Jackson serializer for {@link java.time.Duration} to output "Xs" format. */
static class CustomDurationSerializer extends JsonSerializer<java.time.Duration> {
Expand Down Expand Up @@ -134,7 +134,8 @@ protected static <T extends JsonSerializable> T fromJsonString(
}

/** Deserializes a JsonNode to an object of the given type. */
static <T extends JsonSerializable> T fromJsonNode(JsonNode jsonNode, Class<T> clazz) {
@InternalApi
protected static <T extends JsonSerializable> T fromJsonNode(JsonNode jsonNode, Class<T> clazz) {
try {
return objectMapper.treeToValue(jsonNode, clazz);
} catch (JsonProcessingException e) {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/google/genai/LiveConverters.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/** Internal SDK converter functions. */
final class LiveConverters {
private final ApiClient apiClient;

Expand Down
58 changes: 23 additions & 35 deletions src/main/java/com/google/genai/Operations.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.google.genai.types.GetOperationConfig;
import com.google.genai.types.GetOperationParameters;
import com.google.genai.types.HttpOptions;
import com.google.genai.types.Operation;
import java.io.IOException;
import java.util.Optional;
import okhttp3.ResponseBody;
Expand Down Expand Up @@ -378,7 +379,7 @@ BuiltRequest buildRequestForPrivateGetVideosOperation(
}

/** A shared processResponse function for both sync and async methods. */
GenerateVideosOperation processResponseForPrivateGetVideosOperation(
JsonNode processResponseForPrivateGetVideosOperation(
ApiResponse response, GetOperationConfig config) {
ResponseBody responseBody = response.getBody();
String responseString;
Expand All @@ -388,21 +389,10 @@ GenerateVideosOperation processResponseForPrivateGetVideosOperation(
throw new GenAiIOException("Failed to read HTTP response.", e);
}

JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString);

if (this.apiClient.vertexAI()) {
responseNode = generateVideosOperationFromVertex(responseNode, null);
}

if (!this.apiClient.vertexAI()) {
responseNode = generateVideosOperationFromMldev(responseNode, null);
}

return JsonSerializable.fromJsonNode(responseNode, GenerateVideosOperation.class);
return JsonSerializable.stringToJsonNode(responseString);
}

GenerateVideosOperation privateGetVideosOperation(
String operationName, GetOperationConfig config) {
JsonNode privateGetVideosOperation(String operationName, GetOperationConfig config) {
BuiltRequest builtRequest = buildRequestForPrivateGetVideosOperation(operationName, config);

try (ApiResponse response =
Expand Down Expand Up @@ -457,7 +447,7 @@ BuiltRequest buildRequestForPrivateFetchPredictVideosOperation(
}

/** A shared processResponse function for both sync and async methods. */
GenerateVideosOperation processResponseForPrivateFetchPredictVideosOperation(
JsonNode processResponseForPrivateFetchPredictVideosOperation(
ApiResponse response, FetchPredictOperationConfig config) {
ResponseBody responseBody = response.getBody();
String responseString;
Expand All @@ -467,21 +457,10 @@ GenerateVideosOperation processResponseForPrivateFetchPredictVideosOperation(
throw new GenAiIOException("Failed to read HTTP response.", e);
}

JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString);

if (this.apiClient.vertexAI()) {
responseNode = generateVideosOperationFromVertex(responseNode, null);
}

if (!this.apiClient.vertexAI()) {
throw new UnsupportedOperationException(
"This method is only supported in the Vertex AI client.");
}

return JsonSerializable.fromJsonNode(responseNode, GenerateVideosOperation.class);
return JsonSerializable.stringToJsonNode(responseString);
}

GenerateVideosOperation privateFetchPredictVideosOperation(
JsonNode privateFetchPredictVideosOperation(
String operationName, String resourceName, FetchPredictOperationConfig config) {
BuiltRequest builtRequest =
buildRequestForPrivateFetchPredictVideosOperation(operationName, resourceName, config);
Expand All @@ -502,20 +481,29 @@ GenerateVideosOperation privateFetchPredictVideosOperation(
*/
public GenerateVideosOperation getVideosOperation(
GenerateVideosOperation operation, GetOperationConfig config) {
return get(operation, config);
}

/**
* Gets the status of an Operation.
*
* @param operation An Operation.
* @param config The configuration for getting the operation.
* @return An Operation with the updated status of the operation.
*/
public <T, U extends Operation<T, U>> U get(U operation, GetOperationConfig config) {
if (!operation.name().isPresent()) {
throw new Error("Operation name is required.");
throw new IllegalArgumentException("Operation name is required.");
}

if (this.apiClient.vertexAI()) {
String resourceName = operation.name().get().split("/operations/")[0];

FetchPredictOperationConfig fetchConfig = FetchPredictOperationConfig.builder().build();

return this.privateFetchPredictVideosOperation(
operation.name().get(), resourceName, fetchConfig);
JsonNode response =
this.privateFetchPredictVideosOperation(operation.name().get(), resourceName, null);
return operation.fromApiResponse(response, true);
} else {
return this.privateGetVideosOperation(operation.name().get(), config);
JsonNode response = this.privateGetVideosOperation(operation.name().get(), config);
return operation.fromApiResponse(response, false);
}
}
}
44 changes: 31 additions & 13 deletions src/main/java/com/google/genai/OperationsConverters.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,21 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.api.core.InternalApi;

final class OperationsConverters {
/** Internal SDK converter functions. */
@InternalApi
public final class OperationsConverters {
private final ApiClient apiClient;

public OperationsConverters(ApiClient apiClient) {
this.apiClient = apiClient;
}

@ExcludeFromGeneratedCoverageReport
ObjectNode fetchPredictOperationParametersToMldev(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode fetchPredictOperationParametersToMldev(
JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"operationName"}))) {
throw new IllegalArgumentException("operationName parameter is not supported in Gemini API.");
Expand All @@ -49,7 +54,9 @@ ObjectNode fetchPredictOperationParametersToMldev(JsonNode fromObject, ObjectNod
}

@ExcludeFromGeneratedCoverageReport
ObjectNode fetchPredictOperationParametersToVertex(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode fetchPredictOperationParametersToVertex(
JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"operationName"}) != null) {
Common.setValueByPath(
Expand All @@ -69,7 +76,8 @@ ObjectNode fetchPredictOperationParametersToVertex(JsonNode fromObject, ObjectNo
}

@ExcludeFromGeneratedCoverageReport
ObjectNode generateVideosOperationFromMldev(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode generateVideosOperationFromMldev(JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) {
Common.setValueByPath(
Expand Down Expand Up @@ -115,7 +123,9 @@ ObjectNode generateVideosOperationFromMldev(JsonNode fromObject, ObjectNode pare
}

@ExcludeFromGeneratedCoverageReport
ObjectNode generateVideosOperationFromVertex(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode generateVideosOperationFromVertex(
JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) {
Common.setValueByPath(
Expand Down Expand Up @@ -159,7 +169,8 @@ ObjectNode generateVideosOperationFromVertex(JsonNode fromObject, ObjectNode par
}

@ExcludeFromGeneratedCoverageReport
ObjectNode generateVideosResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode generateVideosResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"generatedSamples"}) != null) {
ArrayNode keyArray =
Expand Down Expand Up @@ -191,7 +202,8 @@ ObjectNode generateVideosResponseFromMldev(JsonNode fromObject, ObjectNode paren
}

@ExcludeFromGeneratedCoverageReport
ObjectNode generateVideosResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode generateVideosResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"videos"}) != null) {
ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"videos"});
Expand Down Expand Up @@ -222,7 +234,8 @@ ObjectNode generateVideosResponseFromVertex(JsonNode fromObject, ObjectNode pare
}

@ExcludeFromGeneratedCoverageReport
ObjectNode generatedVideoFromMldev(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode generatedVideoFromMldev(JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) {
Common.setValueByPath(
Expand All @@ -238,7 +251,8 @@ ObjectNode generatedVideoFromMldev(JsonNode fromObject, ObjectNode parentObject)
}

@ExcludeFromGeneratedCoverageReport
ObjectNode generatedVideoFromVertex(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode generatedVideoFromVertex(JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"_self"}) != null) {
Common.setValueByPath(
Expand All @@ -254,7 +268,8 @@ ObjectNode generatedVideoFromVertex(JsonNode fromObject, ObjectNode parentObject
}

@ExcludeFromGeneratedCoverageReport
ObjectNode getOperationParametersToMldev(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode getOperationParametersToMldev(JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"operationName"}) != null) {
Common.setValueByPath(
Expand All @@ -267,7 +282,8 @@ ObjectNode getOperationParametersToMldev(JsonNode fromObject, ObjectNode parentO
}

@ExcludeFromGeneratedCoverageReport
ObjectNode getOperationParametersToVertex(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode getOperationParametersToVertex(JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"operationName"}) != null) {
Common.setValueByPath(
Expand All @@ -280,7 +296,8 @@ ObjectNode getOperationParametersToVertex(JsonNode fromObject, ObjectNode parent
}

@ExcludeFromGeneratedCoverageReport
ObjectNode videoFromMldev(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode videoFromMldev(JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"uri"}) != null) {
Common.setValueByPath(
Expand All @@ -305,7 +322,8 @@ ObjectNode videoFromMldev(JsonNode fromObject, ObjectNode parentObject) {
}

@ExcludeFromGeneratedCoverageReport
ObjectNode videoFromVertex(JsonNode fromObject, ObjectNode parentObject) {
@InternalApi
public ObjectNode videoFromVertex(JsonNode fromObject, ObjectNode parentObject) {
ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode();
if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) {
Common.setValueByPath(
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/google/genai/TokensConverters.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/** Internal SDK converter functions. */
final class TokensConverters {
private final ApiClient apiClient;

Expand Down
Loading
Loading