From 134e34c6fefc644279780b812e0cb1b6fc6acea7 Mon Sep 17 00:00:00 2001 From: summerji Date: Mon, 14 Dec 2020 21:07:37 -0800 Subject: [PATCH 1/7] Implemente LRO Operation Callable Method sample code --- .../composer/ServiceClientClassComposer.java | 44 +++++++-- .../ServiceClientCommentComposer.java | 7 +- .../ServiceClientSampleCodeComposer.java | 96 ++++++++++++++++++ .../gapic/composer/goldens/EchoClient.golden | 14 ++- .../goldens/asset/AssetServiceClient.java | 16 +++ .../goldens/redis/CloudRedisClient.java | 97 +++++++++++++++++++ 6 files changed, 264 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java index ccd8cafaf2..e9ec95a840 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java @@ -500,7 +500,8 @@ private static List 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)); @@ -680,25 +681,44 @@ private static MethodDefinition createMethodDefaultMethod( } private static MethodDefinition createLroCallableMethod( - Service service, Method method, Map types) { - return createCallableMethod(service, method, types, CallableMethodKind.LRO); + Service service, + Method method, + Map types, + Map messageTypes, + Map resourceNames) { + return createCallableMethod( + service, method, CallableMethodKind.LRO, types, messageTypes, resourceNames); } private static MethodDefinition createCallableMethod( Service service, Method method, Map types) { - return createCallableMethod(service, method, types, CallableMethodKind.REGULAR); + return createCallableMethod( + service, + method, + CallableMethodKind.REGULAR, + types, + Collections.emptyMap(), + Collections.emptyMap()); } private static MethodDefinition createPagedCallableMethod( Service service, Method method, Map types) { - return createCallableMethod(service, method, types, CallableMethodKind.PAGED); + return createCallableMethod( + service, + method, + CallableMethodKind.PAGED, + types, + Collections.emptyMap(), + Collections.emptyMap()); } private static MethodDefinition createCallableMethod( Service service, Method method, + CallableMethodKind callableMethodKind, Map types, - CallableMethodKind callableMethodKind) { + Map messageTypes, + Map resourceNames) { TypeNode rawCallableReturnType = null; if (callableMethodKind.equals(CallableMethodKind.LRO)) { rawCallableReturnType = types.get("OperationCallable"); @@ -740,9 +760,19 @@ private static MethodDefinition createCallableMethod( .setReturnType(returnType) .build(); + Optional sampleCode = Optional.empty(); + // TODO (summerji): Implement sample code for CallableMethodKind.PAGED and + // CallableMethodKind.REGULAR + if (callableMethodKind.equals(CallableMethodKind.LRO)) { + sampleCode = + Optional.of( + ServiceClientSampleCodeComposer.composeRpcLroCallableMethodHeaderSampleCode( + method, types.get(getClientClassName(service)), resourceNames, messageTypes)); + } + return MethodDefinition.builder() .setHeaderCommentStatements( - ServiceClientCommentComposer.createRpcCallableMethodHeaderComment(method)) + ServiceClientCommentComposer.createRpcCallableMethodHeaderComment(method, sampleCode)) .setScope(ScopeNode.PUBLIC) .setIsFinal(true) .setName(methodName) diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientCommentComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientCommentComposer.java index c3b9158d9b..c5ee9a98d6 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientCommentComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientCommentComposer.java @@ -215,7 +215,8 @@ static CommentStatement createMethodSettingsArgComment(String serviceName) { return toSimpleComment(String.format(CREATE_METHOD_SETTINGS_ARG_PATTERN, serviceName)); } - static List createRpcCallableMethodHeaderComment(Method method) { + static List createRpcCallableMethodHeaderComment( + Method method, Optional sampleCode) { JavaDocComment.Builder methodJavadocBuilder = JavaDocComment.builder(); if (method.hasDescription()) { @@ -224,7 +225,9 @@ static List 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, diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java index b60c329ab5..6d59f71051 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java @@ -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; @@ -289,6 +290,101 @@ public static String composeRpcDefaultMethodHeaderSampleCode( .build()); } + public static String composeRpcLroCallableMethodHeaderSampleCode( + Method method, + TypeNode clientType, + Map resourceNames, + Map 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); + List bodyExprs = new ArrayList<>(); + bodyExprs.add( + AssignmentExpr.builder() + .setVariableExpr(requestVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(requestBuilderExpr) + .build()); + 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 bodyStatements = + bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList()); + bodyExprs.clear(); + bodyStatements.add(CommentStatement.withComment(LineComment.withComment("Do something;"))); + 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 composeUnaryRpcMethodSampleCodeBodyStatements( Method method, VariableExpr clientVarExpr, diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden b/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden index 15d93be4eb..6e1e81732d 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden @@ -504,7 +504,19 @@ public class EchoClient implements BackgroundResource { } // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** Sample code: */ + /** + * Sample code: + * + *
{@code
+   * try (EchoClient echoClient = EchoClient.create()) {
+   *   WaitRequest request = WaitRequest.newBuilder().build();
+   *   OperationFuture future =
+   *       echoClient.waitOperationCallable().futureCall(request);
+   *   // Do something;
+   *   WaitResponse response = future.get();
+   * }
+   * }
+ */ public final OperationCallable waitOperationCallable() { return stub.waitOperationCallable(); } diff --git a/test/integration/goldens/asset/AssetServiceClient.java b/test/integration/goldens/asset/AssetServiceClient.java index 24702ea4f4..ecfe104374 100644 --- a/test/integration/goldens/asset/AssetServiceClient.java +++ b/test/integration/goldens/asset/AssetServiceClient.java @@ -202,6 +202,22 @@ public final OperationFuture exportAs * export operation usually finishes within 5 minutes. * *

Sample code: + * + *

{@code
+   * try (AssetServiceClient assetServiceClient = AssetServiceClient.create()) {
+   *   ExportAssetsRequest request =
+   *       ExportAssetsRequest.newBuilder()
+   *           .setParent(FeedName.ofProjectFeedName("[PROJECT]", "[FEED]").toString())
+   *           .setReadTime(Timestamp.newBuilder().build())
+   *           .addAllAssetTypes(new ArrayList())
+   *           .setOutputConfig(OutputConfig.newBuilder().build())
+   *           .build();
+   *   OperationFuture future =
+   *       assetServiceClient.exportAssetsOperationCallable().futureCall(request);
+   *   // Do something;
+   *   ExportAssetsResponse response = future.get();
+   * }
+   * }
*/ public final OperationCallable exportAssetsOperationCallable() { diff --git a/test/integration/goldens/redis/CloudRedisClient.java b/test/integration/goldens/redis/CloudRedisClient.java index 72ebd6d532..40b756ba86 100644 --- a/test/integration/goldens/redis/CloudRedisClient.java +++ b/test/integration/goldens/redis/CloudRedisClient.java @@ -561,6 +561,21 @@ public final OperationFuture createInstanceAsync( * call DeleteOperation. * *

Sample code: + * + *

{@code
+   * try (CloudRedisClient cloudRedisClient = CloudRedisClient.create()) {
+   *   CreateInstanceRequest request =
+   *       CreateInstanceRequest.newBuilder()
+   *           .setParent(LocationName.of("[PROJECT]", "[LOCATION]").toString())
+   *           .setInstanceId("instanceId902024336")
+   *           .setInstance(Instance.newBuilder().build())
+   *           .build();
+   *   OperationFuture future =
+   *       cloudRedisClient.createInstanceOperationCallable().futureCall(request);
+   *   // Do something;
+   *   Instance response = future.get();
+   * }
+   * }
*/ public final OperationCallable createInstanceOperationCallable() { @@ -658,6 +673,20 @@ public final OperationFuture updateInstanceAsync( * DeleteOperation. * *

Sample code: + * + *

{@code
+   * try (CloudRedisClient cloudRedisClient = CloudRedisClient.create()) {
+   *   UpdateInstanceRequest request =
+   *       UpdateInstanceRequest.newBuilder()
+   *           .setUpdateMask(FieldMask.newBuilder().build())
+   *           .setInstance(Instance.newBuilder().build())
+   *           .build();
+   *   OperationFuture future =
+   *       cloudRedisClient.updateInstanceOperationCallable().futureCall(request);
+   *   // Do something;
+   *   Instance response = future.get();
+   * }
+   * }
*/ public final OperationCallable updateInstanceOperationCallable() { @@ -765,6 +794,20 @@ public final OperationFuture upgradeInstanceAsync( * Upgrades Redis instance to the newer Redis version specified in the request. * *

Sample code: + * + *

{@code
+   * try (CloudRedisClient cloudRedisClient = CloudRedisClient.create()) {
+   *   UpgradeInstanceRequest request =
+   *       UpgradeInstanceRequest.newBuilder()
+   *           .setName(InstanceName.of("[PROJECT]", "[LOCATION]", "[INSTANCE]").toString())
+   *           .setRedisVersion("redisVersion-1972584739")
+   *           .build();
+   *   OperationFuture future =
+   *       cloudRedisClient.upgradeInstanceOperationCallable().futureCall(request);
+   *   // Do something;
+   *   Instance response = future.get();
+   * }
+   * }
*/ public final OperationCallable upgradeInstanceOperationCallable() { @@ -856,6 +899,20 @@ public final OperationFuture importInstanceAsync( * call DeleteOperation. * *

Sample code: + * + *

{@code
+   * try (CloudRedisClient cloudRedisClient = CloudRedisClient.create()) {
+   *   ImportInstanceRequest request =
+   *       ImportInstanceRequest.newBuilder()
+   *           .setName("name3373707")
+   *           .setInputConfig(InputConfig.newBuilder().build())
+   *           .build();
+   *   OperationFuture future =
+   *       cloudRedisClient.importInstanceOperationCallable().futureCall(request);
+   *   // Do something;
+   *   Instance response = future.get();
+   * }
+   * }
*/ public final OperationCallable importInstanceOperationCallable() { @@ -950,6 +1007,20 @@ public final OperationFuture exportInstanceAsync( * call DeleteOperation. * *

Sample code: + * + *

{@code
+   * try (CloudRedisClient cloudRedisClient = CloudRedisClient.create()) {
+   *   ExportInstanceRequest request =
+   *       ExportInstanceRequest.newBuilder()
+   *           .setName("name3373707")
+   *           .setOutputConfig(OutputConfig.newBuilder().build())
+   *           .build();
+   *   OperationFuture future =
+   *       cloudRedisClient.exportInstanceOperationCallable().futureCall(request);
+   *   // Do something;
+   *   Instance response = future.get();
+   * }
+   * }
*/ public final OperationCallable exportInstanceOperationCallable() { @@ -1068,6 +1139,19 @@ public final OperationFuture failoverInstanceAsync( * Cloud Memorystore for Redis instance. * *

Sample code: + * + *

{@code
+   * try (CloudRedisClient cloudRedisClient = CloudRedisClient.create()) {
+   *   FailoverInstanceRequest request =
+   *       FailoverInstanceRequest.newBuilder()
+   *           .setName(InstanceName.of("[PROJECT]", "[LOCATION]", "[INSTANCE]").toString())
+   *           .build();
+   *   OperationFuture future =
+   *       cloudRedisClient.failoverInstanceOperationCallable().futureCall(request);
+   *   // Do something;
+   *   Instance response = future.get();
+   * }
+   * }
*/ public final OperationCallable failoverInstanceOperationCallable() { @@ -1161,6 +1245,19 @@ public final OperationFuture deleteInstanceAsync( * Deletes a specific Redis instance. Instance stops serving and data is deleted. * *

Sample code: + * + *

{@code
+   * try (CloudRedisClient cloudRedisClient = CloudRedisClient.create()) {
+   *   DeleteInstanceRequest request =
+   *       DeleteInstanceRequest.newBuilder()
+   *           .setName(InstanceName.of("[PROJECT]", "[LOCATION]", "[INSTANCE]").toString())
+   *           .build();
+   *   OperationFuture future =
+   *       cloudRedisClient.deleteInstanceOperationCallable().futureCall(request);
+   *   // Do something;
+   *   future.get();
+   * }
+   * }
*/ public final OperationCallable deleteInstanceOperationCallable() { From fd01194021edea4e7781f68b9a5488b29752178b Mon Sep 17 00:00:00 2001 From: summerji Date: Tue, 15 Dec 2020 13:59:49 -0800 Subject: [PATCH 2/7] Add todo comment --- .../generator/gapic/composer/ServiceClientClassComposer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java index e9ec95a840..c6b3d19fc1 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java @@ -692,6 +692,7 @@ private static MethodDefinition createLroCallableMethod( private static MethodDefinition createCallableMethod( Service service, Method method, Map types) { + // TODO(summerji): Implement sample code for callable method and pass in actual map of Messages and ResourceNames return createCallableMethod( service, method, @@ -703,6 +704,7 @@ private static MethodDefinition createCallableMethod( private static MethodDefinition createPagedCallableMethod( Service service, Method method, Map types) { + // TODO(summerji): Implement sample code for paged callable method and pass in actual map of Messages and ResourceNames return createCallableMethod( service, method, From 3a73ee277ccf78d5f14e0833ceebb5013f019614 Mon Sep 17 00:00:00 2001 From: summerji Date: Thu, 17 Dec 2020 00:08:11 -0800 Subject: [PATCH 3/7] Add unit test --- .../composer/ServiceClientClassComposer.java | 13 ++- .../ServiceClientSampleCodeComposer.java | 11 +- .../ServiceClientSampleCodeComposerTest.java | 108 ++++++++++++++++++ 3 files changed, 124 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java index c6b3d19fc1..e90223575f 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java @@ -692,7 +692,8 @@ private static MethodDefinition createLroCallableMethod( private static MethodDefinition createCallableMethod( Service service, Method method, Map types) { - // TODO(summerji): Implement sample code for callable method and pass in actual map of Messages and ResourceNames + // TODO(summerji): Implement sample code for callable method and pass in actual map of Messages + // and ResourceNames return createCallableMethod( service, method, @@ -704,7 +705,8 @@ private static MethodDefinition createCallableMethod( private static MethodDefinition createPagedCallableMethod( Service service, Method method, Map types) { - // TODO(summerji): Implement sample code for paged callable method and pass in actual map of Messages and ResourceNames + // TODO(summerji): Implement sample code for paged callable method and pass in actual map of + // Messages and ResourceNames return createCallableMethod( service, method, @@ -768,8 +770,11 @@ private static MethodDefinition createCallableMethod( if (callableMethodKind.equals(CallableMethodKind.LRO)) { sampleCode = Optional.of( - ServiceClientSampleCodeComposer.composeRpcLroCallableMethodHeaderSampleCode( - method, types.get(getClientClassName(service)), resourceNames, messageTypes)); + ServiceClientSampleCodeComposer.composeLroCallableMethodHeaderSampleCode( + method, + types.get(ClassNames.getServiceClientClassName(service)), + resourceNames, + messageTypes)); } return MethodDefinition.builder() diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java index 6d59f71051..b2fa6c9e02 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java @@ -290,7 +290,7 @@ public static String composeRpcDefaultMethodHeaderSampleCode( .build()); } - public static String composeRpcLroCallableMethodHeaderSampleCode( + public static String composeLroCallableMethodHeaderSampleCode( Method method, TypeNode clientType, Map resourceNames, @@ -310,12 +310,15 @@ public static String composeRpcLroCallableMethodHeaderSampleCode( Expr requestBuilderExpr = DefaultValueComposer.createSimpleMessageBuilderExpr( requestMessage, resourceNames, messageTypes); - List bodyExprs = new ArrayList<>(); - bodyExprs.add( + AssignmentExpr requestAssignmentExpr = AssignmentExpr.builder() .setVariableExpr(requestVarExpr.toBuilder().setIsDecl(true).build()) .setValueExpr(requestBuilderExpr) - .build()); + .build(); + + List bodyExprs = new ArrayList<>(); + bodyExprs.add(requestAssignmentExpr); + TypeNode operationFutureType = TypeNode.withReference( ConcreteReference.builder() diff --git a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java index 3e5d82a8b0..b89c138163 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java @@ -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 resourceNames = Parser.parseResourceNames(echoFileDescriptor); + Map 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 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 resourceNames = Parser.parseResourceNames(echoFileDescriptor); + Map 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 future =\n", + " echoClient.waitOperationCallable().futureCall(request);\n", + " // Do something;\n", + " future.get();\n", + "}"); + assertEquals(results, expected); + } } From 6719f882b9272a7a9c92626d549d4af42bbb8733 Mon Sep 17 00:00:00 2001 From: summerji Date: Thu, 17 Dec 2020 00:27:15 -0800 Subject: [PATCH 4/7] add comments --- .../gapic/composer/ServiceClientClassComposer.java | 5 +++-- .../composer/ServiceClientSampleCodeComposer.java | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java index e90223575f..1634f121b7 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java @@ -692,8 +692,9 @@ private static MethodDefinition createLroCallableMethod( private static MethodDefinition createCallableMethod( Service service, Method method, Map types) { - // TODO(summerji): Implement sample code for callable method and pass in actual map of Messages - // and ResourceNames + // 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, diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java index b2fa6c9e02..0c8acf717c 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java @@ -319,6 +319,9 @@ public static String composeLroCallableMethodHeaderSampleCode( List bodyExprs = new ArrayList<>(); bodyExprs.add(requestAssignmentExpr); + // Create OperationFuture variable expr with invoking client's lro callable method. + // e.g. OperationFuture future = + // echoClient.waitOperationCallable().futureCall(request); TypeNode operationFutureType = TypeNode.withReference( ConcreteReference.builder() @@ -348,10 +351,16 @@ public static String composeLroCallableMethodHeaderSampleCode( .setVariableExpr(operationFutureVarExpr.toBuilder().setIsDecl(true).build()) .setValueExpr(rpcMethodInvocationExpr) .build()); + List 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) @@ -380,6 +389,7 @@ public static String composeLroCallableMethodHeaderSampleCode( bodyStatements.addAll( bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); bodyExprs.clear(); + return SampleCodeWriter.write( TryCatchStatement.builder() .setTryResourceExpr(assignClientVariableWithCreateMethodExpr(clientVarExpr)) From b7b7b2ee2d559dc89090f867e87c285b65b8d094 Mon Sep 17 00:00:00 2001 From: summerji Date: Thu, 17 Dec 2020 16:31:37 -0800 Subject: [PATCH 5/7] address the comments --- .../composer/ServiceClientSampleCodeComposer.java | 8 ++++---- .../ServiceClientSampleCodeComposerTest.java | 4 ++-- .../gapic/composer/goldens/EchoClient.golden | 2 +- .../goldens/asset/AssetServiceClient.java | 2 +- .../goldens/redis/CloudRedisClient.java | 14 +++++++------- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java index 0c8acf717c..d26a1f129a 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java @@ -319,7 +319,7 @@ public static String composeLroCallableMethodHeaderSampleCode( List bodyExprs = new ArrayList<>(); bodyExprs.add(requestAssignmentExpr); - // Create OperationFuture variable expr with invoking client's lro callable method. + // Create OperationFuture variable expr with invoking client's LRO callable method. // e.g. OperationFuture future = // echoClient.waitOperationCallable().futureCall(request); TypeNode operationFutureType = @@ -356,9 +356,9 @@ public static String composeLroCallableMethodHeaderSampleCode( bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList()); bodyExprs.clear(); // Add a line comment - bodyStatements.add(CommentStatement.withComment(LineComment.withComment("Do something;"))); + bodyStatements.add(CommentStatement.withComment(LineComment.withComment("Do something."))); - // Assign response variable with invoking client's lro method. + // 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 = @@ -494,7 +494,7 @@ private static List composeUnaryLroRpcMethodSampleCodeBodyStatements( VariableExpr clientVarExpr, List rpcMethodArgVarExprs, List bodyExprs) { - // Assign response variable with invoking client's lro method. + // Assign response variable with invoking client's LRO method. // e.g. if return void, echoClient.waitAsync(ttl).get(); or, // e.g. if return other type, WaitResponse response = echoClient.waitAsync(ttl).get(); Expr invokeLroGetMethodExpr = diff --git a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java index b89c138163..441bea4c65 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java @@ -1448,7 +1448,7 @@ public void validComposeLroCallableMethodHeaderSampleCode_withReturnResponse() { " WaitRequest request = WaitRequest.newBuilder().build();\n", " OperationFuture future =\n", " echoClient.waitOperationCallable().futureCall(request);\n", - " // Do something;\n", + " // Do something.\n", " WaitResponse response = future.get();\n", "}"); assertEquals(results, expected); @@ -1500,7 +1500,7 @@ public void validComposeLroCallableMethodHeaderSampleCode_withReturnVoid() { " WaitRequest request = WaitRequest.newBuilder().build();\n", " OperationFuture future =\n", " echoClient.waitOperationCallable().futureCall(request);\n", - " // Do something;\n", + " // Do something.\n", " future.get();\n", "}"); assertEquals(results, expected); diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden b/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden index 6e1e81732d..b9585ec489 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden @@ -512,7 +512,7 @@ public class EchoClient implements BackgroundResource { * WaitRequest request = WaitRequest.newBuilder().build(); * OperationFuture future = * echoClient.waitOperationCallable().futureCall(request); - * // Do something; + * // Do something. * WaitResponse response = future.get(); * } * } diff --git a/test/integration/goldens/asset/AssetServiceClient.java b/test/integration/goldens/asset/AssetServiceClient.java index ecfe104374..6a39beb127 100644 --- a/test/integration/goldens/asset/AssetServiceClient.java +++ b/test/integration/goldens/asset/AssetServiceClient.java @@ -214,7 +214,7 @@ public final OperationFuture exportAs * .build(); * OperationFuture future = * assetServiceClient.exportAssetsOperationCallable().futureCall(request); - * // Do something; + * // Do something. * ExportAssetsResponse response = future.get(); * } * } diff --git a/test/integration/goldens/redis/CloudRedisClient.java b/test/integration/goldens/redis/CloudRedisClient.java index 40b756ba86..bf6aba5541 100644 --- a/test/integration/goldens/redis/CloudRedisClient.java +++ b/test/integration/goldens/redis/CloudRedisClient.java @@ -572,7 +572,7 @@ public final OperationFuture createInstanceAsync( * .build(); * OperationFuture future = * cloudRedisClient.createInstanceOperationCallable().futureCall(request); - * // Do something; + * // Do something. * Instance response = future.get(); * } * } @@ -683,7 +683,7 @@ public final OperationFuture updateInstanceAsync( * .build(); * OperationFuture future = * cloudRedisClient.updateInstanceOperationCallable().futureCall(request); - * // Do something; + * // Do something. * Instance response = future.get(); * } * } @@ -804,7 +804,7 @@ public final OperationFuture upgradeInstanceAsync( * .build(); * OperationFuture future = * cloudRedisClient.upgradeInstanceOperationCallable().futureCall(request); - * // Do something; + * // Do something. * Instance response = future.get(); * } * } @@ -909,7 +909,7 @@ public final OperationFuture importInstanceAsync( * .build(); * OperationFuture future = * cloudRedisClient.importInstanceOperationCallable().futureCall(request); - * // Do something; + * // Do something. * Instance response = future.get(); * } * } @@ -1017,7 +1017,7 @@ public final OperationFuture exportInstanceAsync( * .build(); * OperationFuture future = * cloudRedisClient.exportInstanceOperationCallable().futureCall(request); - * // Do something; + * // Do something. * Instance response = future.get(); * } * } @@ -1148,7 +1148,7 @@ public final OperationFuture failoverInstanceAsync( * .build(); * OperationFuture future = * cloudRedisClient.failoverInstanceOperationCallable().futureCall(request); - * // Do something; + * // Do something. * Instance response = future.get(); * } * } @@ -1254,7 +1254,7 @@ public final OperationFuture deleteInstanceAsync( * .build(); * OperationFuture future = * cloudRedisClient.deleteInstanceOperationCallable().futureCall(request); - * // Do something; + * // Do something. * future.get(); * } * } From 4bc25482658c1cab75f55b8a74f9a4f1b09f4eeb Mon Sep 17 00:00:00 2001 From: summerji Date: Thu, 17 Dec 2020 12:26:01 -0800 Subject: [PATCH 6/7] Implement Paged Callable Method --- .../composer/ServiceClientClassComposer.java | 27 ++-- .../ServiceClientSampleCodeComposer.java | 116 ++++++++++++++++++ .../gapic/composer/goldens/EchoClient.golden | 41 ++++++- .../composer/goldens/IdentityClient.golden | 19 ++- .../goldens/asset/AssetServiceClient.java | 38 ++++++ .../goldens/library/LibraryServiceClient.java | 31 +++++ .../goldens/logging/ConfigClient.java | 52 ++++++++ .../goldens/logging/LoggingClient.java | 50 ++++++++ .../goldens/logging/MetricsClient.java | 16 +++ .../goldens/redis/CloudRedisClient.java | 17 +++ 10 files changed, 394 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java index 1634f121b7..424e1d23c4 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java @@ -504,7 +504,8 @@ private static List createServiceMethods( createLroCallableMethod(service, method, types, messageTypes, resourceNames)); } if (method.isPaged()) { - javaMethods.add(createPagedCallableMethod(service, method, types)); + javaMethods.add( + createPagedCallableMethod(service, method, types, messageTypes, resourceNames)); } javaMethods.add(createCallableMethod(service, method, types)); } @@ -705,16 +706,13 @@ private static MethodDefinition createCallableMethod( } private static MethodDefinition createPagedCallableMethod( - Service service, Method method, Map types) { - // TODO(summerji): Implement sample code for paged callable method and pass in actual map of - // Messages and ResourceNames + Service service, + Method method, + Map types, + Map messageTypes, + Map resourceNames) { return createCallableMethod( - service, - method, - CallableMethodKind.PAGED, - types, - Collections.emptyMap(), - Collections.emptyMap()); + service, method, CallableMethodKind.PAGED, types, messageTypes, resourceNames); } private static MethodDefinition createCallableMethod( @@ -777,6 +775,15 @@ private static MethodDefinition createCallableMethod( resourceNames, messageTypes)); } + if (callableMethodKind.equals(CallableMethodKind.PAGED)) { + sampleCode = + Optional.of( + ServiceClientSampleCodeComposer.composePagedCallableMethodHeaderSampleCode( + method, + types.get(ClassNames.getServiceClientClassName(service)), + resourceNames, + messageTypes)); + } return MethodDefinition.builder() .setHeaderCommentStatements( diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java index d26a1f129a..59ecd59a4f 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java @@ -14,6 +14,7 @@ package com.google.api.generator.gapic.composer; +import com.google.api.core.ApiFuture; import com.google.api.gax.core.FixedCredentialsProvider; import com.google.api.gax.longrunning.OperationFuture; import com.google.api.generator.engine.ast.AssignmentExpr; @@ -398,6 +399,121 @@ public static String composeLroCallableMethodHeaderSampleCode( .build()); } + public static String composePagedCallableMethodHeaderSampleCode( + Method method, + TypeNode clientType, + Map resourceNames, + Map 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 bodyExprs = new ArrayList<>(); + bodyExprs.add(requestAssignmentExpr); + + // Find the repeated field. + Message methodOutputMessage = messageTypes.get(method.outputType().reference().simpleName()); + Field repeatedPagedResultsField = methodOutputMessage.findAndUnwrapFirstRepeatedField(); + Preconditions.checkNotNull( + repeatedPagedResultsField, + String.format( + "No repeated field found on message %s for method %s", + methodOutputMessage.name(), method.name())); + TypeNode repeatedResponseType = repeatedPagedResultsField.type(); + + // Create ApiFuture Variable Expression with assign value by invoking client paged callable + // method. + // e.g. ApiFuture future = + // configServiceV2Client.listExclusionsPagedCallable().futureCall(request); + TypeNode apiFutureType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(ApiFuture.class) + .setGenerics(repeatedResponseType.reference()) + .build()); + VariableExpr apiFutureVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("future").setType(apiFutureType).build()); + MethodInvocationExpr pagedCallableFutureMethodExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(clientVarExpr) + .setMethodName( + String.format("%sPagedCallable", JavaStyle.toLowerCamelCase(method.name()))) + .build(); + pagedCallableFutureMethodExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(pagedCallableFutureMethodExpr) + .setMethodName("futureCall") + .setArguments(requestVarExpr) + .setReturnType(apiFutureType) + .build(); + AssignmentExpr apiFutureAssignmentExpr = + AssignmentExpr.builder() + .setVariableExpr(apiFutureVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(pagedCallableFutureMethodExpr) + .build(); + bodyExprs.add(apiFutureAssignmentExpr); + + List bodyStatements = + bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList()); + bodyExprs.clear(); + + // Add line comment + bodyStatements.add(CommentStatement.withComment(LineComment.withComment("Do something."))); + + // For-loop on repeated response element + // e.g. for (ListExclusionsResponse element : future.get().iterateAll()) { + // // doThingsWith(element); + // } + VariableExpr repeatedResponseVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("element").setType(repeatedResponseType).build()); + MethodInvocationExpr futureGetIterateAllMethodExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(apiFutureVarExpr) + .setMethodName("get") + .build(); + futureGetIterateAllMethodExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(futureGetIterateAllMethodExpr) + .setMethodName("iterateAll") + .setReturnType(repeatedResponseType) + .build(); + CommentStatement lineCommentStatement = + CommentStatement.withComment(LineComment.withComment("doThingsWith(element);")); + ForStatement repeatedResponseForStatement = + ForStatement.builder() + .setLocalVariableExpr(repeatedResponseVarExpr.toBuilder().setIsDecl(true).build()) + .setCollectionExpr(futureGetIterateAllMethodExpr) + .setBody(Arrays.asList(lineCommentStatement)) + .build(); + bodyStatements.add(repeatedResponseForStatement); + + return SampleCodeWriter.write( + TryCatchStatement.builder() + .setTryResourceExpr(assignClientVariableWithCreateMethodExpr(clientVarExpr)) + .setTryBody(bodyStatements) + .setIsSampleCode(true) + .build()); + } + private static List composeUnaryRpcMethodSampleCodeBodyStatements( Method method, VariableExpr clientVarExpr, diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden b/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden index b9585ec489..8aee6f2f12 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden @@ -377,7 +377,25 @@ public class EchoClient implements BackgroundResource { } // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** Sample code: */ + /** + * Sample code: + * + *
{@code
+   * try (EchoClient echoClient = EchoClient.create()) {
+   *   PagedExpandRequest request =
+   *       PagedExpandRequest.newBuilder()
+   *           .setContent("content951530617")
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future = echoClient.pagedExpandPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (EchoResponse element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
+ */ public final UnaryCallable pagedExpandPagedCallable() { return stub.pagedExpandPagedCallable(); @@ -435,7 +453,26 @@ public class EchoClient implements BackgroundResource { } // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** Sample code: */ + /** + * Sample code: + * + *
{@code
+   * try (EchoClient echoClient = EchoClient.create()) {
+   *   PagedExpandRequest request =
+   *       PagedExpandRequest.newBuilder()
+   *           .setContent("content951530617")
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future =
+   *       echoClient.simplePagedExpandPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (EchoResponse element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
+ */ public final UnaryCallable simplePagedExpandPagedCallable() { return stub.simplePagedExpandPagedCallable(); diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/IdentityClient.golden b/src/test/java/com/google/api/generator/gapic/composer/goldens/IdentityClient.golden index cfc332034f..07dc235155 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/goldens/IdentityClient.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/goldens/IdentityClient.golden @@ -405,7 +405,24 @@ public class IdentityClient implements BackgroundResource { } // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** Sample code: */ + /** + * Sample code: + * + *
{@code
+   * try (IdentityClient identityClient = IdentityClient.create()) {
+   *   ListUsersRequest request =
+   *       ListUsersRequest.newBuilder()
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future = identityClient.listUsersPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (User element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
+ */ public final UnaryCallable listUsersPagedCallable() { return stub.listUsersPagedCallable(); } diff --git a/test/integration/goldens/asset/AssetServiceClient.java b/test/integration/goldens/asset/AssetServiceClient.java index 6a39beb127..89dd018fdb 100644 --- a/test/integration/goldens/asset/AssetServiceClient.java +++ b/test/integration/goldens/asset/AssetServiceClient.java @@ -737,6 +737,26 @@ public final SearchAllResourcesPagedResponse searchAllResources( * on the desired scope, otherwise the request will be rejected. * *

Sample code: + * + *

{@code
+   * try (AssetServiceClient assetServiceClient = AssetServiceClient.create()) {
+   *   SearchAllResourcesRequest request =
+   *       SearchAllResourcesRequest.newBuilder()
+   *           .setScope("scope109264468")
+   *           .setQuery("query107944136")
+   *           .addAllAssetTypes(new ArrayList())
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .setOrderBy("orderBy-1207110587")
+   *           .build();
+   *   ApiFuture future =
+   *       assetServiceClient.searchAllResourcesPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (ResourceSearchResult element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable searchAllResourcesPagedCallable() { @@ -858,6 +878,24 @@ public final SearchAllIamPoliciesPagedResponse searchAllIamPolicies( * permission on the desired scope, otherwise the request will be rejected. * *

Sample code: + * + *

{@code
+   * try (AssetServiceClient assetServiceClient = AssetServiceClient.create()) {
+   *   SearchAllIamPoliciesRequest request =
+   *       SearchAllIamPoliciesRequest.newBuilder()
+   *           .setScope("scope109264468")
+   *           .setQuery("query107944136")
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future =
+   *       assetServiceClient.searchAllIamPoliciesPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (IamPolicySearchResult element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable searchAllIamPoliciesPagedCallable() { diff --git a/test/integration/goldens/library/LibraryServiceClient.java b/test/integration/goldens/library/LibraryServiceClient.java index 67c5a4a57b..7a569548f2 100644 --- a/test/integration/goldens/library/LibraryServiceClient.java +++ b/test/integration/goldens/library/LibraryServiceClient.java @@ -324,6 +324,21 @@ public final ListShelvesPagedResponse listShelves(ListShelvesRequest request) { * necessarily be added to the end of this list. * *

Sample code: + * + *

{@code
+   * try (LibraryServiceClient libraryServiceClient = LibraryServiceClient.create()) {
+   *   ListShelvesRequest request =
+   *       ListShelvesRequest.newBuilder()
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future = libraryServiceClient.listShelvesPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (Shelf element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable listShelvesPagedCallable() { @@ -827,6 +842,22 @@ public final ListBooksPagedResponse listBooks(ListBooksRequest request) { * exist. * *

Sample code: + * + *

{@code
+   * try (LibraryServiceClient libraryServiceClient = LibraryServiceClient.create()) {
+   *   ListBooksRequest request =
+   *       ListBooksRequest.newBuilder()
+   *           .setName("name3373707")
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future = libraryServiceClient.listBooksPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (Book element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable listBooksPagedCallable() { return stub.listBooksPagedCallable(); diff --git a/test/integration/goldens/logging/ConfigClient.java b/test/integration/goldens/logging/ConfigClient.java index 8f3b649b27..0deaeb413b 100644 --- a/test/integration/goldens/logging/ConfigClient.java +++ b/test/integration/goldens/logging/ConfigClient.java @@ -366,6 +366,24 @@ public final ListBucketsPagedResponse listBuckets(ListBucketsRequest request) { * Lists buckets (Beta). * *

Sample code: + * + *

{@code
+   * try (ConfigClient configClient = ConfigClient.create()) {
+   *   ListBucketsRequest request =
+   *       ListBucketsRequest.newBuilder()
+   *           .setParent(
+   *               LogBucketName.ofProjectLocationBucketName("[PROJECT]", "[LOCATION]", "[BUCKET]")
+   *                   .toString())
+   *           .setPageToken("pageToken873572522")
+   *           .setPageSize(883849137)
+   *           .build();
+   *   ApiFuture future = configClient.listBucketsPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (LogBucket element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable listBucketsPagedCallable() { @@ -633,6 +651,22 @@ public final ListSinksPagedResponse listSinks(ListSinksRequest request) { * Lists sinks. * *

Sample code: + * + *

{@code
+   * try (ConfigClient configClient = ConfigClient.create()) {
+   *   ListSinksRequest request =
+   *       ListSinksRequest.newBuilder()
+   *           .setParent(LogSinkName.ofProjectSinkName("[PROJECT]", "[SINK]").toString())
+   *           .setPageToken("pageToken873572522")
+   *           .setPageSize(883849137)
+   *           .build();
+   *   ApiFuture future = configClient.listSinksPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (LogSink element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable listSinksPagedCallable() { return stub.listSinksPagedCallable(); @@ -1424,6 +1458,24 @@ public final ListExclusionsPagedResponse listExclusions(ListExclusionsRequest re * Lists all the exclusions in a parent resource. * *

Sample code: + * + *

{@code
+   * try (ConfigClient configClient = ConfigClient.create()) {
+   *   ListExclusionsRequest request =
+   *       ListExclusionsRequest.newBuilder()
+   *           .setParent(
+   *               LogExclusionName.ofProjectExclusionName("[PROJECT]", "[EXCLUSION]").toString())
+   *           .setPageToken("pageToken873572522")
+   *           .setPageSize(883849137)
+   *           .build();
+   *   ApiFuture future =
+   *       configClient.listExclusionsPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (LogExclusion element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable listExclusionsPagedCallable() { diff --git a/test/integration/goldens/logging/LoggingClient.java b/test/integration/goldens/logging/LoggingClient.java index db2dcc3bdc..45467735be 100644 --- a/test/integration/goldens/logging/LoggingClient.java +++ b/test/integration/goldens/logging/LoggingClient.java @@ -535,6 +535,24 @@ public final ListLogEntriesPagedResponse listLogEntries(ListLogEntriesRequest re * Logs](https://cloud.google.com/logging/docs/export). * *

Sample code: + * + *

{@code
+   * try (LoggingClient loggingClient = LoggingClient.create()) {
+   *   ListLogEntriesRequest request =
+   *       ListLogEntriesRequest.newBuilder()
+   *           .addAllResourceNames(new ArrayList())
+   *           .setFilter("filter-1274492040")
+   *           .setOrderBy("orderBy-1207110587")
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future = loggingClient.listLogEntriesPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (LogEntry element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable listLogEntriesPagedCallable() { @@ -587,6 +605,22 @@ public final ListMonitoredResourceDescriptorsPagedResponse listMonitoredResource * Lists the descriptors for monitored resource types used by Logging. * *

Sample code: + * + *

{@code
+   * try (LoggingClient loggingClient = LoggingClient.create()) {
+   *   ListMonitoredResourceDescriptorsRequest request =
+   *       ListMonitoredResourceDescriptorsRequest.newBuilder()
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future =
+   *       loggingClient.listMonitoredResourceDescriptorsPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (MonitoredResourceDescriptor element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable< ListMonitoredResourceDescriptorsRequest, ListMonitoredResourceDescriptorsPagedResponse> @@ -774,6 +808,22 @@ public final ListLogsPagedResponse listLogs(ListLogsRequest request) { * entries are listed. * *

Sample code: + * + *

{@code
+   * try (LoggingClient loggingClient = LoggingClient.create()) {
+   *   ListLogsRequest request =
+   *       ListLogsRequest.newBuilder()
+   *           .setParent(LogName.ofProjectLogName("[PROJECT]", "[LOG]").toString())
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future = loggingClient.listLogsPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (String element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable listLogsPagedCallable() { return stub.listLogsPagedCallable(); diff --git a/test/integration/goldens/logging/MetricsClient.java b/test/integration/goldens/logging/MetricsClient.java index c3a53ec4b8..0c5310dc93 100644 --- a/test/integration/goldens/logging/MetricsClient.java +++ b/test/integration/goldens/logging/MetricsClient.java @@ -231,6 +231,22 @@ public final ListLogMetricsPagedResponse listLogMetrics(ListLogMetricsRequest re * Lists logs-based metrics. * *

Sample code: + * + *

{@code
+   * try (MetricsClient metricsClient = MetricsClient.create()) {
+   *   ListLogMetricsRequest request =
+   *       ListLogMetricsRequest.newBuilder()
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
+   *           .setPageToken("pageToken873572522")
+   *           .setPageSize(883849137)
+   *           .build();
+   *   ApiFuture future = metricsClient.listLogMetricsPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (LogMetric element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable listLogMetricsPagedCallable() { diff --git a/test/integration/goldens/redis/CloudRedisClient.java b/test/integration/goldens/redis/CloudRedisClient.java index bf6aba5541..e8701aa91d 100644 --- a/test/integration/goldens/redis/CloudRedisClient.java +++ b/test/integration/goldens/redis/CloudRedisClient.java @@ -298,6 +298,23 @@ public final ListInstancesPagedResponse listInstances(ListInstancesRequest reque * are queried, and the results are aggregated. * *

Sample code: + * + *

{@code
+   * try (CloudRedisClient cloudRedisClient = CloudRedisClient.create()) {
+   *   ListInstancesRequest request =
+   *       ListInstancesRequest.newBuilder()
+   *           .setParent(LocationName.of("[PROJECT]", "[LOCATION]").toString())
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .build();
+   *   ApiFuture future =
+   *       cloudRedisClient.listInstancesPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (Instance element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }
*/ public final UnaryCallable listInstancesPagedCallable() { From 943f746b0fa3d6a478f1e3f7ea74d831557a278f Mon Sep 17 00:00:00 2001 From: summerji Date: Thu, 17 Dec 2020 16:53:59 -0800 Subject: [PATCH 7/7] Add unit tests --- .../ServiceClientSampleCodeComposerTest.java | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) diff --git a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java index 441bea4c65..f06dc49390 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java @@ -1505,4 +1505,180 @@ public void validComposeLroCallableMethodHeaderSampleCode_withReturnVoid() { "}"); assertEquals(results, expected); } + + // ================================Paged Callable Method Sample Code ====================// + @Test + public void validComposePagedCallableMethodHeaderSampleCode() { + FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor(); + Map resourceNames = Parser.parseResourceNames(echoFileDescriptor); + Map messageTypes = Parser.parseMessages(echoFileDescriptor); + TypeNode clientType = + TypeNode.withReference( + VaporReference.builder() + .setName("EchoClient") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + TypeNode inputType = + TypeNode.withReference( + VaporReference.builder() + .setName("PagedExpandRequest") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + TypeNode outputType = + TypeNode.withReference( + VaporReference.builder() + .setName("PagedExpandResponse") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + Method method = + Method.builder() + .setName("PagedExpand") + .setInputType(inputType) + .setOutputType(outputType) + .setIsPaged(true) + .build(); + String results = + ServiceClientSampleCodeComposer.composePagedCallableMethodHeaderSampleCode( + method, clientType, resourceNames, messageTypes); + String expected = + LineFormatter.lines( + "try (EchoClient echoClient = EchoClient.create()) {\n", + " PagedExpandRequest request =\n", + " PagedExpandRequest.newBuilder()\n", + " .setContent(\"content951530617\")\n", + " .setPageSize(883849137)\n", + " .setPageToken(\"pageToken873572522\")\n", + " .build();\n", + " ApiFuture future = echoClient.pagedExpandPagedCallable().futureCall(request);\n", + " // Do something.\n", + " for (EchoResponse element : future.get().iterateAll()) {\n", + " // doThingsWith(element);\n", + " }\n", + "}"); + assertEquals(results, expected); + } + + @Test + public void invalidComposePagedCallableMethodHeaderSampleCode_inputTypeNotExistInMessage() { + FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor(); + Map resourceNames = Parser.parseResourceNames(echoFileDescriptor); + Map messageTypes = Parser.parseMessages(echoFileDescriptor); + TypeNode clientType = + TypeNode.withReference( + VaporReference.builder() + .setName("EchoClient") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + TypeNode inputType = + TypeNode.withReference( + VaporReference.builder() + .setName("NotExistRequest") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + TypeNode outputType = + TypeNode.withReference( + VaporReference.builder() + .setName("PagedExpandResponse") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + Method method = + Method.builder() + .setName("PagedExpand") + .setInputType(inputType) + .setOutputType(outputType) + .setIsPaged(true) + .build(); + assertThrows( + NullPointerException.class, + () -> + ServiceClientSampleCodeComposer.composePagedCallableMethodHeaderSampleCode( + method, clientType, resourceNames, messageTypes)); + } + + @Test + public void invalidComposePagedCallableMethodHeaderSampleCode_noExistMethodResponse() { + FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor(); + Map resourceNames = Parser.parseResourceNames(echoFileDescriptor); + Map messageTypes = Parser.parseMessages(echoFileDescriptor); + TypeNode clientType = + TypeNode.withReference( + VaporReference.builder() + .setName("EchoClient") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + TypeNode inputType = + TypeNode.withReference( + VaporReference.builder() + .setName("EchoRequest") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + TypeNode outputType = + TypeNode.withReference( + VaporReference.builder() + .setName("NoExistResponse") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + Method method = + Method.builder() + .setName("PagedExpand") + .setInputType(inputType) + .setOutputType(outputType) + .setIsPaged(true) + .build(); + assertThrows( + NullPointerException.class, + () -> + ServiceClientSampleCodeComposer.composePagedCallableMethodHeaderSampleCode( + method, clientType, resourceNames, messageTypes)); + } + + @Test + public void invalidComposePagedCallableMethodHeaderSampleCode_noRepeatedResponse() { + FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor(); + Map resourceNames = Parser.parseResourceNames(echoFileDescriptor); + Map messageTypes = Parser.parseMessages(echoFileDescriptor); + TypeNode clientType = + TypeNode.withReference( + VaporReference.builder() + .setName("EchoClient") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + TypeNode inputType = + TypeNode.withReference( + VaporReference.builder() + .setName("EchoRequest") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + TypeNode outputType = + TypeNode.withReference( + VaporReference.builder() + .setName("NoRepeatedResponse") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build()); + Method method = + Method.builder() + .setName("PagedExpand") + .setInputType(inputType) + .setOutputType(outputType) + .setIsPaged(true) + .build(); + Field responseField = Field.builder().setName("response").setType(TypeNode.STRING).build(); + Message noRepeatedResponseMessage = + Message.builder() + .setName("NoRepeatedResponse") + .setType( + TypeNode.withReference( + VaporReference.builder() + .setName("NoRepeatedResponse") + .setPakkage(SHOWCASE_PACKAGE_NAME) + .build())) + .setFields(Arrays.asList(responseField)) + .build(); + messageTypes.put("NoRepeatedResponse", noRepeatedResponseMessage); + assertThrows( + NullPointerException.class, + () -> + ServiceClientSampleCodeComposer.composePagedCallableMethodHeaderSampleCode( + method, clientType, resourceNames, messageTypes)); + } }