Skip to content

Commit 4ebfb92

Browse files
[SampleCode][3/3]Implement LRO unary rpc method's sample code (#587)
1 parent 8dea44b commit 4ebfb92

File tree

5 files changed

+412
-10
lines changed

5 files changed

+412
-10
lines changed

src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java

+4-9
Original file line numberDiff line numberDiff line change
@@ -565,15 +565,10 @@ private static List<MethodDefinition> createMethodVariants(
565565
.setReturnType(methodOutputType)
566566
.build();
567567

568-
Optional<String> methodSampleCode = Optional.empty();
569-
if (!method.hasLro()) {
570-
// TODO(summerji): Remove the condition check once finished the implementation on lro sample
571-
// code.
572-
methodSampleCode =
573-
Optional.of(
574-
ServiceClientSampleCodeComposer.composeRpcMethodHeaderSampleCode(
575-
method, types.get(clientName), signature, resourceNames, messageTypes));
576-
}
568+
Optional<String> methodSampleCode =
569+
Optional.of(
570+
ServiceClientSampleCodeComposer.composeRpcMethodHeaderSampleCode(
571+
method, types.get(clientName), signature, resourceNames, messageTypes));
577572
MethodDefinition.Builder methodVariantBuilder =
578573
MethodDefinition.builder()
579574
.setHeaderCommentStatements(

src/main/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposer.java

+66
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ public static String composeRpcMethodHeaderSampleCode(
210210
composeUnaryPagedRpcMethodSampleCode(
211211
method, clientType, repeatedResponseType, arguments, resourceNames));
212212
}
213+
if (method.hasLro()) {
214+
return SampleCodeWriter.write(
215+
composeUnaryLroRpcMethodSampleCode(method, clientType, arguments, resourceNames));
216+
}
213217
return SampleCodeWriter.write(
214218
composeUnaryRpcMethodSampleCode(method, clientType, arguments, resourceNames));
215219
}
@@ -334,6 +338,68 @@ static TryCatchStatement composeUnaryPagedRpcMethodSampleCode(
334338
.build();
335339
}
336340

341+
@VisibleForTesting
342+
static TryCatchStatement composeUnaryLroRpcMethodSampleCode(
343+
Method method,
344+
TypeNode clientType,
345+
List<MethodArgument> arguments,
346+
Map<String, ResourceName> resourceNames) {
347+
VariableExpr clientVarExpr =
348+
VariableExpr.withVariable(
349+
Variable.builder()
350+
.setName(JavaStyle.toLowerCamelCase(clientType.reference().name()))
351+
.setType(clientType)
352+
.build());
353+
List<VariableExpr> rpcMethodArgVarExprs = createRpcMethodArgumentVariableExprs(arguments);
354+
List<Expr> rpcMethodArgDefaultValueExprs =
355+
createRpcMethodArgumentDefaultValueExprs(arguments, resourceNames);
356+
List<Expr> bodyExprs =
357+
createAssignmentsForVarExprsWithValueExprs(
358+
rpcMethodArgVarExprs, rpcMethodArgDefaultValueExprs);
359+
// Assign response variable with invoking client's lro method.
360+
// e.g. if return void, echoClient.waitAsync(ttl).get(); or,
361+
// e.g. if return other type, WaitResponse response = echoClient.waitAsync(ttl).get();
362+
Expr invokeLroMethodExpr =
363+
MethodInvocationExpr.builder()
364+
.setExprReferenceExpr(clientVarExpr)
365+
.setMethodName(String.format("%sAsync", JavaStyle.toLowerCamelCase(method.name())))
366+
.setArguments(
367+
rpcMethodArgVarExprs.stream().map(e -> (Expr) e).collect(Collectors.toList()))
368+
.build();
369+
Expr getResponseMethodExpr =
370+
MethodInvocationExpr.builder()
371+
.setExprReferenceExpr(invokeLroMethodExpr)
372+
.setMethodName("get")
373+
.setReturnType(method.lro().responseType())
374+
.build();
375+
boolean returnsVoid = isProtoEmptyType(method.lro().responseType());
376+
if (returnsVoid) {
377+
bodyExprs.add(getResponseMethodExpr);
378+
} else {
379+
VariableExpr responseVarExpr =
380+
VariableExpr.builder()
381+
.setVariable(
382+
Variable.builder()
383+
.setName("response")
384+
.setType(method.lro().responseType())
385+
.build())
386+
.setIsDecl(true)
387+
.build();
388+
bodyExprs.add(
389+
AssignmentExpr.builder()
390+
.setVariableExpr(responseVarExpr)
391+
.setValueExpr(getResponseMethodExpr)
392+
.build());
393+
}
394+
395+
return TryCatchStatement.builder()
396+
.setTryResourceExpr(assignClientVariableWithCreateMethodExpr(clientVarExpr))
397+
.setTryBody(
398+
bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList()))
399+
.setIsSampleCode(true)
400+
.build();
401+
}
402+
337403
// ==================================Helpers===================================================//
338404

339405
// Create a list of RPC method arguments' variable expressions.

src/test/java/com/google/api/generator/gapic/composer/ServiceClientSampleCodeComposerTest.java

+212-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.google.api.generator.engine.ast.VaporReference;
2424
import com.google.api.generator.gapic.composer.samplecode.SampleCodeWriter;
2525
import com.google.api.generator.gapic.model.Field;
26+
import com.google.api.generator.gapic.model.LongrunningOperation;
2627
import com.google.api.generator.gapic.model.Message;
2728
import com.google.api.generator.gapic.model.Method;
2829
import com.google.api.generator.gapic.model.MethodArgument;
@@ -40,6 +41,8 @@
4041

4142
public class ServiceClientSampleCodeComposerTest {
4243
private static final String SHOWCASE_PACKAGE_NAME = "com.google.showcase.v1beta1";
44+
private static final String LRO_PACKAGE_NAME = "com.google.longrunning";
45+
private static final String PROTO_PACKAGE_NAME = "com.google.protobuf";
4346

4447
// =======================================RPC Method Header Sample Code=======================//
4548
@Test
@@ -128,6 +131,76 @@ public void validComposeRpcMethodHeaderSampleCode_pagedUnaryRpc() {
128131
assertEquals(expected, results);
129132
}
130133

134+
@Test
135+
public void validComposeRpcMethodHeaderSampleCode_lroUnaryRpc() {
136+
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
137+
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
138+
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
139+
TypeNode clientType =
140+
TypeNode.withReference(
141+
VaporReference.builder()
142+
.setName("EchoClient")
143+
.setPakkage(SHOWCASE_PACKAGE_NAME)
144+
.build());
145+
TypeNode inputType =
146+
TypeNode.withReference(
147+
VaporReference.builder()
148+
.setName("WaitRequest")
149+
.setPakkage(SHOWCASE_PACKAGE_NAME)
150+
.build());
151+
TypeNode outputType =
152+
TypeNode.withReference(
153+
VaporReference.builder().setName("Operation").setPakkage(LRO_PACKAGE_NAME).build());
154+
TypeNode responseType =
155+
TypeNode.withReference(
156+
VaporReference.builder()
157+
.setName("WaitResponse")
158+
.setPakkage(SHOWCASE_PACKAGE_NAME)
159+
.build());
160+
TypeNode metadataType =
161+
TypeNode.withReference(
162+
VaporReference.builder()
163+
.setName("WaitMetadata")
164+
.setPakkage(SHOWCASE_PACKAGE_NAME)
165+
.build());
166+
LongrunningOperation lro = LongrunningOperation.withTypes(responseType, metadataType);
167+
TypeNode ttlTypeNode =
168+
TypeNode.withReference(
169+
VaporReference.builder().setName("Duration").setPakkage(PROTO_PACKAGE_NAME).build());
170+
MethodArgument ttl =
171+
MethodArgument.builder()
172+
.setName("ttl")
173+
.setType(ttlTypeNode)
174+
.setField(
175+
Field.builder()
176+
.setName("ttl")
177+
.setType(ttlTypeNode)
178+
.setIsMessage(true)
179+
.setIsContainedInOneof(true)
180+
.build())
181+
.build();
182+
List<MethodArgument> arguments = Arrays.asList(ttl);
183+
Method method =
184+
Method.builder()
185+
.setName("Wait")
186+
.setInputType(inputType)
187+
.setOutputType(outputType)
188+
.setLro(lro)
189+
.setMethodSignatures(Arrays.asList(arguments))
190+
.build();
191+
192+
String results =
193+
ServiceClientSampleCodeComposer.composeRpcMethodHeaderSampleCode(
194+
method, clientType, arguments, resourceNames, messageTypes);
195+
String expected =
196+
LineFormatter.lines(
197+
"try (EchoClient echoClient = EchoClient.create()) {\n",
198+
" Duration ttl = Duration.newBuilder().build();\n",
199+
" WaitResponse response = echoClient.waitAsync(ttl).get();\n",
200+
"}");
201+
assertEquals(results, expected);
202+
}
203+
131204
@Test
132205
public void invalidComposeRpcMethodHeaderSampleCode_noMatchedRepeatedResponseTypeInPagedMethod() {
133206
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
@@ -770,7 +843,7 @@ public void composeUnaryRpcMethodSampleCode_methodReturnVoid() {
770843
.build());
771844
TypeNode outputType =
772845
TypeNode.withReference(
773-
VaporReference.builder().setName("Empty").setPakkage("com.google.protobuf").build());
846+
VaporReference.builder().setName("Empty").setPakkage(PROTO_PACKAGE_NAME).build());
774847
List<List<MethodArgument>> methodSignatures =
775848
Arrays.asList(
776849
Arrays.asList(
@@ -921,4 +994,142 @@ public void composeUnaryPagedRpcMethodSampleCode_noMethodArguments() {
921994
"}");
922995
assertEquals(results, expected);
923996
}
997+
998+
// ===================================Unary LRO RPC Method Sample Code ======================//
999+
@Test
1000+
public void composeUnaryLroRpcMethodSampleCode_lroReturnResponseType() {
1001+
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
1002+
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
1003+
TypeNode clientType =
1004+
TypeNode.withReference(
1005+
VaporReference.builder()
1006+
.setName("EchoClient")
1007+
.setPakkage(SHOWCASE_PACKAGE_NAME)
1008+
.build());
1009+
TypeNode inputType =
1010+
TypeNode.withReference(
1011+
VaporReference.builder()
1012+
.setName("WaitRequest")
1013+
.setPakkage(SHOWCASE_PACKAGE_NAME)
1014+
.build());
1015+
TypeNode outputType =
1016+
TypeNode.withReference(
1017+
VaporReference.builder().setName("Operation").setPakkage(LRO_PACKAGE_NAME).build());
1018+
TypeNode responseType =
1019+
TypeNode.withReference(
1020+
VaporReference.builder()
1021+
.setName("WaitResponse")
1022+
.setPakkage(SHOWCASE_PACKAGE_NAME)
1023+
.build());
1024+
TypeNode metadataType =
1025+
TypeNode.withReference(
1026+
VaporReference.builder()
1027+
.setName("WaitMetadata")
1028+
.setPakkage(SHOWCASE_PACKAGE_NAME)
1029+
.build());
1030+
LongrunningOperation lro = LongrunningOperation.withTypes(responseType, metadataType);
1031+
TypeNode ttlTypeNode =
1032+
TypeNode.withReference(
1033+
VaporReference.builder().setName("Duration").setPakkage(PROTO_PACKAGE_NAME).build());
1034+
MethodArgument ttl =
1035+
MethodArgument.builder()
1036+
.setName("ttl")
1037+
.setType(ttlTypeNode)
1038+
.setField(
1039+
Field.builder()
1040+
.setName("ttl")
1041+
.setType(ttlTypeNode)
1042+
.setIsMessage(true)
1043+
.setIsContainedInOneof(true)
1044+
.build())
1045+
.build();
1046+
List<MethodArgument> arguments = Arrays.asList(ttl);
1047+
Method method =
1048+
Method.builder()
1049+
.setName("Wait")
1050+
.setInputType(inputType)
1051+
.setOutputType(outputType)
1052+
.setLro(lro)
1053+
.setMethodSignatures(Arrays.asList(arguments))
1054+
.build();
1055+
1056+
String results =
1057+
SampleCodeWriter.write(
1058+
ServiceClientSampleCodeComposer.composeUnaryLroRpcMethodSampleCode(
1059+
method, clientType, arguments, resourceNames));
1060+
String expected =
1061+
LineFormatter.lines(
1062+
"try (EchoClient echoClient = EchoClient.create()) {\n",
1063+
" Duration ttl = Duration.newBuilder().build();\n",
1064+
" WaitResponse response = echoClient.waitAsync(ttl).get();\n",
1065+
"}");
1066+
assertEquals(results, expected);
1067+
}
1068+
1069+
@Test
1070+
public void composeUnaryLroRpcMethodSampleCode_lroReturnVoid() {
1071+
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
1072+
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
1073+
TypeNode clientType =
1074+
TypeNode.withReference(
1075+
VaporReference.builder()
1076+
.setName("EchoClient")
1077+
.setPakkage(SHOWCASE_PACKAGE_NAME)
1078+
.build());
1079+
TypeNode inputType =
1080+
TypeNode.withReference(
1081+
VaporReference.builder()
1082+
.setName("WaitRequest")
1083+
.setPakkage(SHOWCASE_PACKAGE_NAME)
1084+
.build());
1085+
TypeNode outputType =
1086+
TypeNode.withReference(
1087+
VaporReference.builder().setName("Operation").setPakkage(LRO_PACKAGE_NAME).build());
1088+
TypeNode responseType =
1089+
TypeNode.withReference(
1090+
VaporReference.builder().setName("Empty").setPakkage(PROTO_PACKAGE_NAME).build());
1091+
TypeNode metadataType =
1092+
TypeNode.withReference(
1093+
VaporReference.builder()
1094+
.setName("WaitMetadata")
1095+
.setPakkage(SHOWCASE_PACKAGE_NAME)
1096+
.build());
1097+
LongrunningOperation lro = LongrunningOperation.withTypes(responseType, metadataType);
1098+
TypeNode ttlTypeNode =
1099+
TypeNode.withReference(
1100+
VaporReference.builder().setName("Duration").setPakkage(PROTO_PACKAGE_NAME).build());
1101+
MethodArgument ttl =
1102+
MethodArgument.builder()
1103+
.setName("ttl")
1104+
.setType(ttlTypeNode)
1105+
.setField(
1106+
Field.builder()
1107+
.setName("ttl")
1108+
.setType(ttlTypeNode)
1109+
.setIsMessage(true)
1110+
.setIsContainedInOneof(true)
1111+
.build())
1112+
.build();
1113+
List<MethodArgument> arguments = Arrays.asList(ttl);
1114+
Method method =
1115+
Method.builder()
1116+
.setName("Wait")
1117+
.setInputType(inputType)
1118+
.setOutputType(outputType)
1119+
.setLro(lro)
1120+
.setMethodSignatures(Arrays.asList(arguments))
1121+
.build();
1122+
1123+
String results =
1124+
SampleCodeWriter.write(
1125+
ServiceClientSampleCodeComposer.composeUnaryLroRpcMethodSampleCode(
1126+
method, clientType, arguments, resourceNames));
1127+
String expected =
1128+
LineFormatter.lines(
1129+
"try (EchoClient echoClient = EchoClient.create()) {\n",
1130+
" Duration ttl = Duration.newBuilder().build();\n",
1131+
" echoClient.waitAsync(ttl).get();\n",
1132+
"}");
1133+
assertEquals(results, expected);
1134+
}
9241135
}

src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden

+18
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,15 @@ public class EchoClient implements BackgroundResource {
403403

404404
// AUTO-GENERATED DOCUMENTATION AND METHOD.
405405
/**
406+
* Sample code:
407+
*
408+
* <pre>{@code
409+
* try (EchoClient echoClient = EchoClient.create()) {
410+
* Duration ttl = Duration.newBuilder().build();
411+
* WaitResponse response = echoClient.waitAsync(ttl).get();
412+
* }
413+
* }</pre>
414+
*
406415
* @param ttl
407416
* @throws com.google.api.gax.rpc.ApiException if the remote call fails
408417
*/
@@ -413,6 +422,15 @@ public class EchoClient implements BackgroundResource {
413422

414423
// AUTO-GENERATED DOCUMENTATION AND METHOD.
415424
/**
425+
* Sample code:
426+
*
427+
* <pre>{@code
428+
* try (EchoClient echoClient = EchoClient.create()) {
429+
* Timestamp endTime = Timestamp.newBuilder().build();
430+
* WaitResponse response = echoClient.waitAsync(endTime).get();
431+
* }
432+
* }</pre>
433+
*
416434
* @param endTime
417435
* @throws com.google.api.gax.rpc.ApiException if the remote call fails
418436
*/

0 commit comments

Comments
 (0)