Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,8 @@ private static List<MethodDefinition> createServiceMethods(
resourceNames));
}
if (method.hasLro()) {
javaMethods.add(createLroCallableMethod(service, method, types));
javaMethods.add(
createLroCallableMethod(service, method, types, messageTypes, resourceNames));
}
if (method.isPaged()) {
javaMethods.add(createPagedCallableMethod(service, method, types));
Expand Down Expand Up @@ -680,25 +681,49 @@ private static MethodDefinition createMethodDefaultMethod(
}

private static MethodDefinition createLroCallableMethod(
Service service, Method method, Map<String, TypeNode> types) {
return createCallableMethod(service, method, types, CallableMethodKind.LRO);
Service service,
Method method,
Map<String, TypeNode> types,
Map<String, Message> messageTypes,
Map<String, ResourceName> resourceNames) {
return createCallableMethod(
service, method, CallableMethodKind.LRO, types, messageTypes, resourceNames);
}

private static MethodDefinition createCallableMethod(
Service service, Method method, Map<String, TypeNode> types) {
return createCallableMethod(service, method, types, CallableMethodKind.REGULAR);
// TODO(summerji): Implement sample code for callable methods which include stream methods and
// unary methods,
// and pass in actual map of Messages and ResourceNames
return createCallableMethod(
service,
method,
CallableMethodKind.REGULAR,
types,
Collections.emptyMap(),
Collections.emptyMap());
}

private static MethodDefinition createPagedCallableMethod(
Service service, Method method, Map<String, TypeNode> types) {
return createCallableMethod(service, method, types, CallableMethodKind.PAGED);
// TODO(summerji): Implement sample code for paged callable method and pass in actual map of
// Messages and ResourceNames
return createCallableMethod(
service,
method,
CallableMethodKind.PAGED,
types,
Collections.emptyMap(),
Collections.emptyMap());
}

private static MethodDefinition createCallableMethod(
Service service,
Method method,
CallableMethodKind callableMethodKind,
Map<String, TypeNode> types,
CallableMethodKind callableMethodKind) {
Map<String, Message> messageTypes,
Map<String, ResourceName> resourceNames) {
TypeNode rawCallableReturnType = null;
if (callableMethodKind.equals(CallableMethodKind.LRO)) {
rawCallableReturnType = types.get("OperationCallable");
Expand Down Expand Up @@ -740,9 +765,22 @@ private static MethodDefinition createCallableMethod(
.setReturnType(returnType)
.build();

Optional<String> sampleCode = Optional.empty();
// TODO (summerji): Implement sample code for CallableMethodKind.PAGED and
// CallableMethodKind.REGULAR
if (callableMethodKind.equals(CallableMethodKind.LRO)) {
sampleCode =
Optional.of(
ServiceClientSampleCodeComposer.composeLroCallableMethodHeaderSampleCode(
method,
types.get(ClassNames.getServiceClientClassName(service)),
resourceNames,
messageTypes));
}

return MethodDefinition.builder()
.setHeaderCommentStatements(
ServiceClientCommentComposer.createRpcCallableMethodHeaderComment(method))
ServiceClientCommentComposer.createRpcCallableMethodHeaderComment(method, sampleCode))
.setScope(ScopeNode.PUBLIC)
.setIsFinal(true)
.setName(methodName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ static CommentStatement createMethodSettingsArgComment(String serviceName) {
return toSimpleComment(String.format(CREATE_METHOD_SETTINGS_ARG_PATTERN, serviceName));
}

static List<CommentStatement> createRpcCallableMethodHeaderComment(Method method) {
static List<CommentStatement> createRpcCallableMethodHeaderComment(
Method method, Optional<String> sampleCode) {
JavaDocComment.Builder methodJavadocBuilder = JavaDocComment.builder();

if (method.hasDescription()) {
Expand All @@ -224,7 +225,9 @@ static List<CommentStatement> createRpcCallableMethodHeaderComment(Method method
}

methodJavadocBuilder.addParagraph(METHOD_DESCRIPTION_SAMPLE_CODE_SUMMARY_STRING);
// TODO(summerji): Add sample code here.
if (sampleCode.isPresent()) {
methodJavadocBuilder.addSampleCode(sampleCode.get());
}

return Arrays.asList(
CommentComposer.AUTO_GENERATED_METHOD_COMMENT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package com.google.api.generator.gapic.composer;

import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.api.generator.engine.ast.AssignmentExpr;
import com.google.api.generator.engine.ast.CommentStatement;
import com.google.api.generator.engine.ast.ConcreteReference;
Expand Down Expand Up @@ -289,6 +290,114 @@ public static String composeRpcDefaultMethodHeaderSampleCode(
.build());
}

public static String composeLroCallableMethodHeaderSampleCode(
Method method,
TypeNode clientType,
Map<String, ResourceName> resourceNames,
Map<String, Message> messageTypes) {
VariableExpr clientVarExpr =
VariableExpr.withVariable(
Variable.builder()
.setName(JavaStyle.toLowerCamelCase(clientType.reference().name()))
.setType(clientType)
.build());
// Assign method's request variable with the default value.
VariableExpr requestVarExpr =
VariableExpr.withVariable(
Variable.builder().setName("request").setType(method.inputType()).build());
Message requestMessage = messageTypes.get(method.inputType().reference().simpleName());
Preconditions.checkNotNull(requestMessage);
Expr requestBuilderExpr =
DefaultValueComposer.createSimpleMessageBuilderExpr(
requestMessage, resourceNames, messageTypes);
AssignmentExpr requestAssignmentExpr =
AssignmentExpr.builder()
.setVariableExpr(requestVarExpr.toBuilder().setIsDecl(true).build())
.setValueExpr(requestBuilderExpr)
.build();

List<Expr> bodyExprs = new ArrayList<>();
bodyExprs.add(requestAssignmentExpr);

// Create OperationFuture variable expr with invoking client's lro callable method.
// e.g. OperationFuture<Empty, WaitMetadata> future =
// echoClient.waitOperationCallable().futureCall(request);
TypeNode operationFutureType =
TypeNode.withReference(
ConcreteReference.builder()
.setClazz(OperationFuture.class)
.setGenerics(
method.lro().responseType().reference(),
method.lro().metadataType().reference())
.build());
VariableExpr operationFutureVarExpr =
VariableExpr.withVariable(
Variable.builder().setName("future").setType(operationFutureType).build());
MethodInvocationExpr rpcMethodInvocationExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(clientVarExpr)
.setMethodName(
String.format("%sOperationCallable", JavaStyle.toLowerCamelCase(method.name())))
.build();
rpcMethodInvocationExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(rpcMethodInvocationExpr)
.setMethodName("futureCall")
.setArguments(requestVarExpr)
.setReturnType(operationFutureType)
.build();
bodyExprs.add(
AssignmentExpr.builder()
.setVariableExpr(operationFutureVarExpr.toBuilder().setIsDecl(true).build())
.setValueExpr(rpcMethodInvocationExpr)
.build());

List<Statement> bodyStatements =
bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList());
bodyExprs.clear();
// Add a line comment
bodyStatements.add(CommentStatement.withComment(LineComment.withComment("Do something;")));

// Assign response variable with invoking client's lro method.
// e.g. if return void, future.get(); or,
// e.g. if return other type, WaitResponse response = future.get();
MethodInvocationExpr futureGetMethodExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(operationFutureVarExpr)
.setMethodName("get")
.setReturnType(method.lro().responseType())
.build();
boolean returnVoid = isProtoEmptyType(method.lro().responseType());
if (returnVoid) {
bodyExprs.add(futureGetMethodExpr);
} else {
VariableExpr responseVarExpr =
VariableExpr.builder()
.setVariable(
Variable.builder()
.setName("response")
.setType(method.lro().responseType())
.build())
.setIsDecl(true)
.build();
bodyExprs.add(
AssignmentExpr.builder()
.setVariableExpr(responseVarExpr)
.setValueExpr(futureGetMethodExpr)
.build());
}
bodyStatements.addAll(
bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList()));
bodyExprs.clear();

return SampleCodeWriter.write(
TryCatchStatement.builder()
.setTryResourceExpr(assignClientVariableWithCreateMethodExpr(clientVarExpr))
.setTryBody(bodyStatements)
.setIsSampleCode(true)
.build());
}

private static List<Statement> composeUnaryRpcMethodSampleCodeBodyStatements(
Method method,
VariableExpr clientVarExpr,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1397,4 +1397,112 @@ public void validComposeRpcDefaultMethodHeaderSampleCode_pureUnaryReturnResponse
"}");
assertEquals(results, expected);
}

// ================================LRO Callable Method Sample Code ====================//
@Test
public void validComposeLroCallableMethodHeaderSampleCode_withReturnResponse() {
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
TypeNode clientType =
TypeNode.withReference(
VaporReference.builder()
.setName("EchoClient")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
TypeNode inputType =
TypeNode.withReference(
VaporReference.builder()
.setName("WaitRequest")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
TypeNode outputType =
TypeNode.withReference(
VaporReference.builder().setName("Operation").setPakkage(LRO_PACKAGE_NAME).build());
TypeNode responseType =
TypeNode.withReference(
VaporReference.builder()
.setName("WaitResponse")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
TypeNode metadataType =
TypeNode.withReference(
VaporReference.builder()
.setName("WaitMetadata")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
LongrunningOperation lro = LongrunningOperation.withTypes(responseType, metadataType);
Method method =
Method.builder()
.setName("Wait")
.setInputType(inputType)
.setOutputType(outputType)
.setLro(lro)
.build();
String results =
ServiceClientSampleCodeComposer.composeLroCallableMethodHeaderSampleCode(
method, clientType, resourceNames, messageTypes);
String expected =
LineFormatter.lines(
"try (EchoClient echoClient = EchoClient.create()) {\n",
" WaitRequest request = WaitRequest.newBuilder().build();\n",
" OperationFuture<WaitResponse, WaitMetadata> future =\n",
" echoClient.waitOperationCallable().futureCall(request);\n",
" // Do something;\n",
" WaitResponse response = future.get();\n",
"}");
assertEquals(results, expected);
}

@Test
public void validComposeLroCallableMethodHeaderSampleCode_withReturnVoid() {
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
TypeNode clientType =
TypeNode.withReference(
VaporReference.builder()
.setName("EchoClient")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
TypeNode inputType =
TypeNode.withReference(
VaporReference.builder()
.setName("WaitRequest")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
TypeNode outputType =
TypeNode.withReference(
VaporReference.builder().setName("Operation").setPakkage(LRO_PACKAGE_NAME).build());
TypeNode responseType =
TypeNode.withReference(
VaporReference.builder().setName("Empty").setPakkage(PROTO_PACKAGE_NAME).build());
TypeNode metadataType =
TypeNode.withReference(
VaporReference.builder()
.setName("WaitMetadata")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
LongrunningOperation lro = LongrunningOperation.withTypes(responseType, metadataType);
Method method =
Method.builder()
.setName("Wait")
.setInputType(inputType)
.setOutputType(outputType)
.setLro(lro)
.build();
String results =
ServiceClientSampleCodeComposer.composeLroCallableMethodHeaderSampleCode(
method, clientType, resourceNames, messageTypes);
String expected =
LineFormatter.lines(
"try (EchoClient echoClient = EchoClient.create()) {\n",
" WaitRequest request = WaitRequest.newBuilder().build();\n",
" OperationFuture<Empty, WaitMetadata> future =\n",
" echoClient.waitOperationCallable().futureCall(request);\n",
" // Do something;\n",
" future.get();\n",
"}");
assertEquals(results, expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,19 @@ public class EchoClient implements BackgroundResource {
}

// AUTO-GENERATED DOCUMENTATION AND METHOD.
/** Sample code: */
/**
* Sample code:
*
* <pre>{@code
* try (EchoClient echoClient = EchoClient.create()) {
* WaitRequest request = WaitRequest.newBuilder().build();
* OperationFuture<WaitResponse, WaitMetadata> future =
* echoClient.waitOperationCallable().futureCall(request);
* // Do something;
* WaitResponse response = future.get();
* }
* }</pre>
*/
public final OperationCallable<WaitRequest, WaitResponse, WaitMetadata> waitOperationCallable() {
return stub.waitOperationCallable();
}
Expand Down
16 changes: 16 additions & 0 deletions test/integration/goldens/asset/AssetServiceClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,22 @@ public final OperationFuture<ExportAssetsResponse, ExportAssetsRequest> exportAs
* export operation usually finishes within 5 minutes.
*
* <p>Sample code:
*
* <pre>{@code
* try (AssetServiceClient assetServiceClient = AssetServiceClient.create()) {
* ExportAssetsRequest request =
* ExportAssetsRequest.newBuilder()
* .setParent(FeedName.ofProjectFeedName("[PROJECT]", "[FEED]").toString())
* .setReadTime(Timestamp.newBuilder().build())
* .addAllAssetTypes(new ArrayList<String>())
* .setOutputConfig(OutputConfig.newBuilder().build())
* .build();
* OperationFuture<ExportAssetsResponse, ExportAssetsRequest> future =
* assetServiceClient.exportAssetsOperationCallable().futureCall(request);
* // Do something;
* ExportAssetsResponse response = future.get();
* }
* }</pre>
*/
public final OperationCallable<ExportAssetsRequest, ExportAssetsResponse, ExportAssetsRequest>
exportAssetsOperationCallable() {
Expand Down
Loading