Skip to content

Commit d553c43

Browse files
authored
[ggj][codegen] feat: add ServiceClient.MethodPage list method inner class (#326)
* feat: add protobuf comment parser util * fix: add basic proto build rules * feat: add header comments to ServiceClient * fix: build protoc at test time * fix!: wrap protobuf location and process comments * feat: add comment parsing to methods and fields * fix: test * feat: add protobuf comments to ServiceClient * fix: solidify codegen method order with TypeNode/MethodArg and Comparable * fix: clean up tests * fix: ServiceClient member variables and method calls * fix: ServiceStubSettings builder type * fix: ServiceSettings Builder construction * fix: ServiceStub callable types * feat: java_gapic_library rule impl * fix: remove debugging comments * feat: add gradle assembly Bazel rules * feat: add java_gapic_test Bazel rule * fix: use Java packages for resname codegen * fix: build resnames separately and extract into proto/ dir * fix: remove debug printf * feat: add ServiceClient.MethodPagedResponse inner class * feat: add ServiceClient.MethodPage inner class
1 parent cf6e629 commit d553c43

File tree

2 files changed

+205
-19
lines changed

2 files changed

+205
-19
lines changed

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

+175-19
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.api.core.BetaApi;
2121
import com.google.api.gax.core.BackgroundResource;
2222
import com.google.api.gax.longrunning.OperationFuture;
23+
import com.google.api.gax.paging.AbstractPage;
2324
import com.google.api.gax.paging.AbstractPagedListResponse;
2425
import com.google.api.gax.rpc.BidiStreamingCallable;
2526
import com.google.api.gax.rpc.ClientStreamingCallable;
@@ -43,6 +44,7 @@
4344
import com.google.api.generator.engine.ast.ReferenceConstructorExpr;
4445
import com.google.api.generator.engine.ast.ScopeNode;
4546
import com.google.api.generator.engine.ast.Statement;
47+
import com.google.api.generator.engine.ast.SuperObjectValue;
4648
import com.google.api.generator.engine.ast.TernaryExpr;
4749
import com.google.api.generator.engine.ast.ThisObjectValue;
4850
import com.google.api.generator.engine.ast.TypeNode;
@@ -75,6 +77,7 @@
7577
import java.util.Map;
7678
import java.util.Objects;
7779
import java.util.concurrent.TimeUnit;
80+
import java.util.function.Function;
7881
import java.util.stream.Collectors;
7982
import javax.annotation.Generated;
8083

@@ -892,37 +895,43 @@ private static List<ClassDefinition> createNestedPagingClasses(
892895
if (!method.isPaged()) {
893896
continue;
894897
}
895-
nestedClasses.add(createNestedRpcPagedResponseClass(method, messageTypes, types));
898+
// Find the repeated field.
899+
Message methodOutputMessage = messageTypes.get(method.outputType().reference().name());
900+
TypeNode repeatedResponseType = null;
901+
for (Field field : methodOutputMessage.fields()) {
902+
if (field.isRepeated() && !field.isMap()) {
903+
Reference repeatedGenericRef = field.type().reference().generics().get(0);
904+
repeatedResponseType = TypeNode.withReference(repeatedGenericRef);
905+
break;
906+
}
907+
}
908+
909+
Preconditions.checkNotNull(
910+
repeatedResponseType,
911+
String.format(
912+
"No repeated field found on message %s for method %s",
913+
methodOutputMessage.name(), method.name()));
914+
915+
nestedClasses.add(
916+
createNestedRpcPagedResponseClass(method, repeatedResponseType, messageTypes, types));
917+
nestedClasses.add(
918+
createNestedRpcPageClass(method, repeatedResponseType, messageTypes, types));
896919
}
897920

898921
return nestedClasses;
899922
}
900923

901924
private static ClassDefinition createNestedRpcPagedResponseClass(
902-
Method method, Map<String, Message> messageTypes, Map<String, TypeNode> types) {
925+
Method method,
926+
TypeNode repeatedResponseType,
927+
Map<String, Message> messageTypes,
928+
Map<String, TypeNode> types) {
903929
Preconditions.checkState(
904930
method.isPaged(), String.format("Expected method %s to be paged", method.name()));
905931

906932
String className = String.format("%sPagedResponse", JavaStyle.toUpperCamelCase(method.name()));
907933
TypeNode thisClassType = types.get(className);
908934

909-
// Find the repeated field.
910-
Message methodOutputMessage = messageTypes.get(method.outputType().reference().name());
911-
TypeNode repeatedResponseType = null;
912-
for (Field field : methodOutputMessage.fields()) {
913-
if (field.isRepeated() && !field.isMap()) {
914-
Reference repeatedGenericRef = field.type().reference().generics().get(0);
915-
repeatedResponseType = TypeNode.withReference(repeatedGenericRef);
916-
break;
917-
}
918-
}
919-
920-
Preconditions.checkNotNull(
921-
repeatedResponseType,
922-
String.format(
923-
"No repeated field found on message %s for method %s",
924-
methodOutputMessage.name(), method.name()));
925-
926935
String upperJavaMethodName = JavaStyle.toUpperCamelCase(method.name());
927936
TypeNode methodPageType = types.get(String.format("%sPage", upperJavaMethodName));
928937
TypeNode classExtendsType =
@@ -1108,6 +1117,153 @@ private static ClassDefinition createNestedRpcPagedResponseClass(
11081117
.build();
11091118
}
11101119

1120+
private static ClassDefinition createNestedRpcPageClass(
1121+
Method method,
1122+
TypeNode repeatedResponseType,
1123+
Map<String, Message> messageTypes,
1124+
Map<String, TypeNode> types) {
1125+
Preconditions.checkState(
1126+
method.isPaged(), String.format("Expected method %s to be paged", method.name()));
1127+
1128+
String upperJavaMethodName = JavaStyle.toUpperCamelCase(method.name());
1129+
String className = String.format("%sPage", upperJavaMethodName);
1130+
TypeNode classType = types.get(className);
1131+
TypeNode classExtendsType =
1132+
TypeNode.withReference(
1133+
ConcreteReference.builder()
1134+
.setClazz(AbstractPage.class)
1135+
.setGenerics(
1136+
Arrays.asList(
1137+
method.inputType(),
1138+
method.outputType(),
1139+
repeatedResponseType,
1140+
classType)
1141+
.stream()
1142+
.map(t -> t.reference())
1143+
.collect(Collectors.toList()))
1144+
.build());
1145+
1146+
// Private constructor.
1147+
VariableExpr contextVarExpr =
1148+
VariableExpr.withVariable(
1149+
Variable.builder()
1150+
.setName("context")
1151+
.setType(
1152+
TypeNode.withReference(
1153+
ConcreteReference.builder()
1154+
.setClazz(PageContext.class)
1155+
.setGenerics(
1156+
Arrays.asList(
1157+
method.inputType(),
1158+
method.outputType(),
1159+
repeatedResponseType)
1160+
.stream()
1161+
.map(t -> t.reference())
1162+
.collect(Collectors.toList()))
1163+
.build()))
1164+
.build());
1165+
VariableExpr responseVarExpr =
1166+
VariableExpr.withVariable(
1167+
Variable.builder().setName("response").setType(method.outputType()).build());
1168+
MethodDefinition privateCtor =
1169+
MethodDefinition.constructorBuilder()
1170+
.setScope(ScopeNode.PRIVATE)
1171+
.setReturnType(classType)
1172+
.setArguments(
1173+
Arrays.asList(contextVarExpr, responseVarExpr).stream()
1174+
.map(e -> e.toBuilder().setIsDecl(true).build())
1175+
.collect(Collectors.toList()))
1176+
.setBody(
1177+
Arrays.asList(
1178+
ExprStatement.withExpr(
1179+
ReferenceConstructorExpr.superBuilder()
1180+
.setType(classExtendsType)
1181+
.setArguments(contextVarExpr, responseVarExpr)
1182+
.build())))
1183+
.build();
1184+
1185+
// createEmptyPage method.
1186+
ValueExpr nullExpr = ValueExpr.withValue(NullObjectValue.create());
1187+
MethodDefinition createEmptyPageMethod =
1188+
MethodDefinition.builder()
1189+
.setScope(ScopeNode.PRIVATE)
1190+
.setIsStatic(true)
1191+
.setReturnType(classType)
1192+
.setName("createEmptyPage")
1193+
.setReturnExpr(
1194+
NewObjectExpr.builder().setType(classType).setArguments(nullExpr, nullExpr).build())
1195+
.build();
1196+
1197+
// createPage method.
1198+
MethodDefinition createPageMethod =
1199+
MethodDefinition.builder()
1200+
.setIsOverride(true)
1201+
.setScope(ScopeNode.PROTECTED)
1202+
.setReturnType(classType)
1203+
.setName("createPage")
1204+
.setArguments(
1205+
Arrays.asList(contextVarExpr, responseVarExpr).stream()
1206+
.map(e -> e.toBuilder().setIsDecl(true).build())
1207+
.collect(Collectors.toList()))
1208+
.setReturnExpr(
1209+
NewObjectExpr.builder()
1210+
.setType(classType)
1211+
.setArguments(contextVarExpr, responseVarExpr)
1212+
.build())
1213+
.build();
1214+
1215+
// createPageAsync method.
1216+
Function<TypeNode, TypeNode> futureTypeFn =
1217+
t ->
1218+
TypeNode.withReference(
1219+
ConcreteReference.builder()
1220+
.setClazz(ApiFuture.class)
1221+
.setGenerics(Arrays.asList(t.reference()))
1222+
.build());
1223+
VariableExpr futureResponseVarExpr =
1224+
VariableExpr.withVariable(
1225+
Variable.builder()
1226+
.setName("futureResponse")
1227+
.setType(futureTypeFn.apply(method.outputType()))
1228+
.build());
1229+
TypeNode futurePageType = futureTypeFn.apply(classType);
1230+
MethodDefinition createPageAsyncMethod =
1231+
MethodDefinition.builder()
1232+
.setIsOverride(true)
1233+
.setScope(ScopeNode.PUBLIC)
1234+
.setReturnType(futurePageType)
1235+
.setName("createPageAsync")
1236+
.setArguments(
1237+
Arrays.asList(contextVarExpr, futureResponseVarExpr).stream()
1238+
.map(e -> e.toBuilder().setIsDecl(true).build())
1239+
.collect(Collectors.toList()))
1240+
.setReturnExpr(
1241+
MethodInvocationExpr.builder()
1242+
.setExprReferenceExpr(
1243+
ValueExpr.withValue(SuperObjectValue.withType(classExtendsType)))
1244+
.setMethodName("createPageAsync")
1245+
.setArguments(contextVarExpr, futureResponseVarExpr)
1246+
.setReturnType(futurePageType)
1247+
.build())
1248+
.build();
1249+
1250+
// Build the class.
1251+
List<MethodDefinition> javaMethods = new ArrayList<>();
1252+
javaMethods.add(privateCtor);
1253+
javaMethods.add(createEmptyPageMethod);
1254+
javaMethods.add(createPageMethod);
1255+
javaMethods.add(createPageAsyncMethod);
1256+
1257+
return ClassDefinition.builder()
1258+
.setIsNested(true)
1259+
.setScope(ScopeNode.PUBLIC)
1260+
.setIsStatic(true)
1261+
.setExtendsType(classExtendsType)
1262+
.setName(className)
1263+
.setMethods(javaMethods)
1264+
.build();
1265+
}
1266+
11111267
private static Map<String, TypeNode> createTypes(
11121268
Service service, Map<String, Message> messageTypes) {
11131269
Map<String, TypeNode> types = new HashMap<>();

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

+30
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public void generateServiceClasses() {
7070
+ "import com.google.api.core.BetaApi;\n"
7171
+ "import com.google.api.gax.core.BackgroundResource;\n"
7272
+ "import com.google.api.gax.longrunning.OperationFuture;\n"
73+
+ "import com.google.api.gax.paging.AbstractPage;\n"
7374
+ "import com.google.api.gax.paging.AbstractPagedListResponse;\n"
7475
+ "import com.google.api.gax.rpc.BidiStreamingCallable;\n"
7576
+ "import com.google.api.gax.rpc.ClientStreamingCallable;\n"
@@ -475,5 +476,34 @@ public void generateServiceClasses() {
475476
+ " super(page, PagedExpandFixedSizeCollection.createEmptyCollection());\n"
476477
+ " }\n"
477478
+ " }\n"
479+
+ "\n"
480+
+ " public static class PagedExpandPage\n"
481+
+ " extends AbstractPage<PagedExpandRequest, PagedExpandResponse, EchoResponse,"
482+
+ " PagedExpandPage> {\n"
483+
+ "\n"
484+
+ " private PagedExpandPage(\n"
485+
+ " PageContext<PagedExpandRequest, PagedExpandResponse, EchoResponse> context,\n"
486+
+ " PagedExpandResponse response) {\n"
487+
+ " super(context, response);\n"
488+
+ " }\n"
489+
+ "\n"
490+
+ " private static PagedExpandPage createEmptyPage() {\n"
491+
+ " return new PagedExpandPage(null, null);\n"
492+
+ " }\n"
493+
+ "\n"
494+
+ " @Override\n"
495+
+ " protected PagedExpandPage createPage(\n"
496+
+ " PageContext<PagedExpandRequest, PagedExpandResponse, EchoResponse> context,\n"
497+
+ " PagedExpandResponse response) {\n"
498+
+ " return new PagedExpandPage(context, response);\n"
499+
+ " }\n"
500+
+ "\n"
501+
+ " @Override\n"
502+
+ " public ApiFuture<PagedExpandPage> createPageAsync(\n"
503+
+ " PageContext<PagedExpandRequest, PagedExpandResponse, EchoResponse> context,\n"
504+
+ " ApiFuture<PagedExpandResponse> futureResponse) {\n"
505+
+ " return super.createPageAsync(context, futureResponse);\n"
506+
+ " }\n"
507+
+ " }\n"
478508
+ "}\n";
479509
}

0 commit comments

Comments
 (0)