Skip to content

Commit 9f58ef3

Browse files
committed
[SampleCode][3/3]Implement LRO unary rpc method's sample code (#587)
1 parent 2bc28ca commit 9f58ef3

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
@@ -591,15 +591,10 @@ private static List<MethodDefinition> createMethodVariants(
591591
.setReturnType(methodOutputType)
592592
.build();
593593

594-
Optional<String> methodSampleCode = Optional.empty();
595-
if (!method.hasLro()) {
596-
// TODO(summerji): Remove the condition check once finished the implementation on lro sample
597-
// code.
598-
methodSampleCode =
599-
Optional.of(
600-
ServiceClientSampleCodeComposer.composeRpcMethodHeaderSampleCode(
601-
method, typeStore.get(clientName), signature, resourceNames, messageTypes));
602-
}
594+
Optional<String> methodSampleCode =
595+
Optional.of(
596+
ServiceClientSampleCodeComposer.composeRpcMethodHeaderSampleCode(
597+
method, typeStore.get(clientName), signature, resourceNames, messageTypes));
603598
MethodDefinition.Builder methodVariantBuilder =
604599
MethodDefinition.builder()
605600
.setHeaderCommentStatements(

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

+66
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ public static String composeRpcMethodHeaderSampleCode(
208208
composeUnaryPagedRpcMethodSampleCode(
209209
method, clientType, repeatedResponseType, arguments, resourceNames));
210210
}
211+
if (method.hasLro()) {
212+
return SampleCodeWriter.write(
213+
composeUnaryLroRpcMethodSampleCode(method, clientType, arguments, resourceNames));
214+
}
211215
return SampleCodeWriter.write(
212216
composeUnaryRpcMethodSampleCode(method, clientType, arguments, resourceNames));
213217
}
@@ -332,6 +336,68 @@ static TryCatchStatement composeUnaryPagedRpcMethodSampleCode(
332336
.build();
333337
}
334338

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

337403
// 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)