Skip to content
This repository was archived by the owner on May 14, 2026. It is now read-only.

Commit 8f04711

Browse files
authored
[ggj][codegen] feat: add descriptor fields to ServiceStubSettings (#226)
* feat: add factory var decl in ServiceStubSettings codegen * fix: prevent duplicate MethodDefinition annotations * feat: add descriptor fields to ServiceStubSettings codegen
1 parent 6aa7549 commit 8f04711

2 files changed

Lines changed: 242 additions & 12 deletions

File tree

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

Lines changed: 199 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,14 @@
6262
import com.google.api.generator.engine.ast.MethodDefinition;
6363
import com.google.api.generator.engine.ast.MethodInvocationExpr;
6464
import com.google.api.generator.engine.ast.NewObjectExpr;
65+
import com.google.api.generator.engine.ast.NullObjectValue;
6566
import com.google.api.generator.engine.ast.Reference;
6667
import com.google.api.generator.engine.ast.ReferenceConstructorExpr;
6768
import com.google.api.generator.engine.ast.ReturnExpr;
6869
import com.google.api.generator.engine.ast.ScopeNode;
6970
import com.google.api.generator.engine.ast.Statement;
7071
import com.google.api.generator.engine.ast.StringObjectValue;
72+
import com.google.api.generator.engine.ast.TernaryExpr;
7173
import com.google.api.generator.engine.ast.ThisObjectValue;
7274
import com.google.api.generator.engine.ast.ThrowExpr;
7375
import com.google.api.generator.engine.ast.TypeNode;
@@ -96,6 +98,7 @@
9698
import java.util.LinkedHashMap;
9799
import java.util.List;
98100
import java.util.Map;
101+
import java.util.Objects;
99102
import java.util.function.Function;
100103
import java.util.stream.Collectors;
101104
import javax.annotation.Generated;
@@ -265,7 +268,9 @@ private static List<Expr> createPagingStaticAssignExprs(
265268
Map<String, Message> messageTypes,
266269
Map<String, TypeNode> types) {
267270
// TODO(miraleung): Add a test case for several such statements.
268-
List<Expr> exprs = new ArrayList<>();
271+
List<Expr> descExprs = new ArrayList<>();
272+
List<Expr> factoryExprs = new ArrayList<>();
273+
269274
for (Method method : service.methods()) {
270275
if (!method.isPaged()) {
271276
continue;
@@ -290,7 +295,7 @@ private static List<Expr> createPagingStaticAssignExprs(
290295
method.outputType().reference().name(), method.name()));
291296

292297
// Create the PAGE_STR_DESC variable.
293-
TypeNode pagedListDescriptorType =
298+
TypeNode pagedListDescType =
294299
TypeNode.withReference(
295300
ConcreteReference.builder()
296301
.setClazz(PagedListDescriptor.class)
@@ -302,21 +307,203 @@ private static List<Expr> createPagingStaticAssignExprs(
302307
.build());
303308
String pageStrDescVarName =
304309
String.format(PAGE_STR_DESC_PATTERN, JavaStyle.toUpperSnakeCase(method.name()));
305-
VariableExpr pageStrDescVarExpr =
310+
311+
VariableExpr pagedListDescVarExpr =
306312
VariableExpr.withVariable(
307-
Variable.builder()
308-
.setType(pagedListDescriptorType)
309-
.setName(pageStrDescVarName)
310-
.build());
313+
Variable.builder().setType(pagedListDescType).setName(pageStrDescVarName).build());
311314

312-
Expr pagedListResponseFactoryAssignExpr =
315+
descExprs.add(
316+
createPagedListDescriptorAssignExpr(
317+
pagedListDescVarExpr, method, repeatedResponseType, types));
318+
factoryExprs.add(
313319
createPagedListResponseFactoryAssignExpr(
314-
pageStrDescVarExpr, method, repeatedResponseType, types);
315-
316-
exprs.add(pagedListResponseFactoryAssignExpr);
320+
pagedListDescVarExpr, method, repeatedResponseType, types));
317321
}
318322

319-
return exprs;
323+
descExprs.addAll(factoryExprs);
324+
return descExprs;
325+
}
326+
327+
private static Expr createPagedListDescriptorAssignExpr(
328+
VariableExpr pagedListDescVarExpr,
329+
Method method,
330+
TypeNode repeatedResponseType,
331+
Map<String, TypeNode> types) {
332+
MethodDefinition.Builder methodStarterBuilder =
333+
MethodDefinition.builder().setIsOverride(true).setScope(ScopeNode.PUBLIC);
334+
List<MethodDefinition> anonClassMethods = new ArrayList<>();
335+
336+
// Create emptyToken method.
337+
anonClassMethods.add(
338+
methodStarterBuilder
339+
.setReturnType(TypeNode.STRING)
340+
.setName("emptyToken")
341+
.setReturnExpr(ValueExpr.withValue(StringObjectValue.withValue("")))
342+
.build());
343+
344+
// Create injectToken method.
345+
VariableExpr payloadVarExpr =
346+
VariableExpr.withVariable(
347+
Variable.builder().setType(method.inputType()).setName("payload").build());
348+
VariableExpr strTokenVarExpr =
349+
VariableExpr.withVariable(
350+
Variable.builder().setType(TypeNode.STRING).setName("token").build());
351+
TypeNode returnType = method.inputType();
352+
Expr newBuilderExpr =
353+
MethodInvocationExpr.builder()
354+
.setStaticReferenceType(method.inputType())
355+
.setMethodName("newBuilder")
356+
.setArguments(payloadVarExpr)
357+
.build();
358+
Expr returnExpr =
359+
MethodInvocationExpr.builder()
360+
.setExprReferenceExpr(newBuilderExpr)
361+
.setMethodName("setPageToken")
362+
.setArguments(strTokenVarExpr)
363+
.build();
364+
returnExpr =
365+
MethodInvocationExpr.builder()
366+
.setExprReferenceExpr(returnExpr)
367+
.setMethodName("build")
368+
.setReturnType(returnType)
369+
.build();
370+
anonClassMethods.add(
371+
methodStarterBuilder
372+
.setReturnType(method.inputType())
373+
.setName("injectToken")
374+
.setArguments(
375+
Arrays.asList(payloadVarExpr, strTokenVarExpr).stream()
376+
.map(v -> v.toBuilder().setIsDecl(true).build())
377+
.collect(Collectors.toList()))
378+
.setReturnExpr(returnExpr)
379+
.build());
380+
381+
// Create injectPageSize method.
382+
VariableExpr pageSizeVarExpr =
383+
VariableExpr.withVariable(
384+
Variable.builder().setType(TypeNode.INT).setName("pageSize").build());
385+
// Re-declare for clarity and easier readeability.
386+
returnType = method.inputType();
387+
returnExpr =
388+
MethodInvocationExpr.builder()
389+
.setExprReferenceExpr(newBuilderExpr)
390+
.setMethodName("setPageSize")
391+
.setArguments(pageSizeVarExpr)
392+
.build();
393+
returnExpr =
394+
MethodInvocationExpr.builder()
395+
.setExprReferenceExpr(returnExpr)
396+
.setMethodName("build")
397+
.setReturnType(returnType)
398+
.build();
399+
anonClassMethods.add(
400+
methodStarterBuilder
401+
.setReturnType(method.inputType())
402+
.setName("injectPageSize")
403+
.setArguments(
404+
Arrays.asList(payloadVarExpr, pageSizeVarExpr).stream()
405+
.map(v -> v.toBuilder().setIsDecl(true).build())
406+
.collect(Collectors.toList()))
407+
.setReturnExpr(returnExpr)
408+
.build());
409+
410+
// TODO(miraleung): Test the edge cases where these proto fields aren't present.
411+
// Create extractPageSize method.
412+
returnType = TypeNode.INT_OBJECT;
413+
anonClassMethods.add(
414+
methodStarterBuilder
415+
.setReturnType(returnType)
416+
.setName("extractPageSize")
417+
.setArguments(payloadVarExpr.toBuilder().setIsDecl(true).build())
418+
.setReturnExpr(
419+
MethodInvocationExpr.builder()
420+
.setExprReferenceExpr(payloadVarExpr)
421+
.setMethodName("getPageSize")
422+
.setReturnType(returnType)
423+
.build())
424+
.build());
425+
426+
// Create extractNextToken method.
427+
returnType = TypeNode.STRING;
428+
payloadVarExpr =
429+
VariableExpr.withVariable(
430+
Variable.builder().setType(method.outputType()).setName("payload").build());
431+
anonClassMethods.add(
432+
methodStarterBuilder
433+
.setReturnType(returnType)
434+
.setName("extractNextToken")
435+
.setArguments(payloadVarExpr.toBuilder().setIsDecl(true).build())
436+
.setReturnExpr(
437+
MethodInvocationExpr.builder()
438+
.setExprReferenceExpr(payloadVarExpr)
439+
.setMethodName("getNextPageToken")
440+
.setReturnType(returnType)
441+
.build())
442+
.build());
443+
444+
// Create extractResources method.
445+
returnType =
446+
TypeNode.withReference(
447+
ConcreteReference.builder()
448+
.setClazz(Iterable.class)
449+
.setGenerics(Arrays.asList(repeatedResponseType.reference()))
450+
.build());
451+
Expr getResponsesListExpr =
452+
MethodInvocationExpr.builder()
453+
.setExprReferenceExpr(payloadVarExpr)
454+
.setMethodName("getResponsesList")
455+
.setReturnType(returnType)
456+
.build();
457+
Expr conditionExpr =
458+
MethodInvocationExpr.builder()
459+
.setStaticReferenceType(
460+
TypeNode.withReference(ConcreteReference.withClazz(Objects.class)))
461+
.setMethodName("equals")
462+
.setArguments(getResponsesListExpr, ValueExpr.withValue(NullObjectValue.create()))
463+
.setReturnType(TypeNode.BOOLEAN)
464+
.build();
465+
Expr thenExpr =
466+
MethodInvocationExpr.builder()
467+
.setStaticReferenceType(
468+
TypeNode.withReference(ConcreteReference.withClazz(ImmutableList.class)))
469+
.setGenerics(Arrays.asList(repeatedResponseType.reference()))
470+
.setMethodName("of")
471+
.setReturnType(returnType)
472+
.build();
473+
474+
returnExpr =
475+
TernaryExpr.builder()
476+
.setConditionExpr(conditionExpr)
477+
.setThenExpr(thenExpr)
478+
.setElseExpr(getResponsesListExpr)
479+
.build();
480+
anonClassMethods.add(
481+
methodStarterBuilder
482+
.setReturnType(returnType)
483+
.setName("extractResources")
484+
.setArguments(payloadVarExpr.toBuilder().setIsDecl(true).build())
485+
.setReturnExpr(returnExpr)
486+
.build());
487+
488+
// Create the anonymous class.
489+
AnonymousClassExpr pagedListDescAnonClassExpr =
490+
AnonymousClassExpr.builder()
491+
.setType(pagedListDescVarExpr.type())
492+
.setMethods(anonClassMethods)
493+
.build();
494+
495+
// Declare and assign the variable.
496+
return AssignmentExpr.builder()
497+
.setVariableExpr(
498+
pagedListDescVarExpr
499+
.toBuilder()
500+
.setIsDecl(true)
501+
.setScope(ScopeNode.PRIVATE)
502+
.setIsStatic(true)
503+
.setIsFinal(true)
504+
.build())
505+
.setValueExpr(pagedListDescAnonClassExpr)
506+
.build();
320507
}
321508

322509
private static Expr createPagedListResponseFactoryAssignExpr(

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public void generateServiceClasses() {
118118
+ "import com.google.showcase.v1beta1.WaitResponse;\n"
119119
+ "import java.io.IOException;\n"
120120
+ "import java.util.List;\n"
121+
+ "import java.util.Objects;\n"
121122
+ "import javax.annotation.Generated;\n"
122123
+ "\n"
123124
+ "@BetaApi\n"
@@ -139,6 +140,48 @@ public void generateServiceClasses() {
139140
+ " private final OperationCallSettings<WaitRequest, WaitResponse, WaitMetadata>\n"
140141
+ " waitOperationSettings;\n"
141142
+ " private final UnaryCallSettings<BlockRequest, BlockResponse> blockSettings;\n"
143+
+ " private static final PagedListDescriptor<PagedExpandRequest, PagedExpandResponse,"
144+
+ " EchoResponse>\n"
145+
+ " PAGED_EXPAND_PAGE_STR_DESC =\n"
146+
+ " new PagedListDescriptor<PagedExpandRequest, PagedExpandResponse,"
147+
+ " EchoResponse>() {\n"
148+
+ " @Override\n"
149+
+ " public String emptyToken() {\n"
150+
+ " return \"\";\n"
151+
+ " }\n"
152+
+ "\n"
153+
+ " @Override\n"
154+
+ " public PagedExpandRequest injectToken(PagedExpandRequest payload, String"
155+
+ " token) {\n"
156+
+ " return"
157+
+ " PagedExpandRequest.newBuilder(payload).setPageToken(token).build();\n"
158+
+ " }\n"
159+
+ "\n"
160+
+ " @Override\n"
161+
+ " public PagedExpandRequest injectPageSize(PagedExpandRequest payload, int"
162+
+ " pageSize) {\n"
163+
+ " return"
164+
+ " PagedExpandRequest.newBuilder(payload).setPageSize(pageSize).build();\n"
165+
+ " }\n"
166+
+ "\n"
167+
+ " @Override\n"
168+
+ " public Integer extractPageSize(PagedExpandRequest payload) {\n"
169+
+ " return payload.getPageSize();\n"
170+
+ " }\n"
171+
+ "\n"
172+
+ " @Override\n"
173+
+ " public String extractNextToken(PagedExpandResponse payload) {\n"
174+
+ " return payload.getNextPageToken();\n"
175+
+ " }\n"
176+
+ "\n"
177+
+ " @Override\n"
178+
+ " public Iterable<EchoResponse> extractResources(PagedExpandResponse"
179+
+ " payload) {\n"
180+
+ " return Objects.equals(payload.getResponsesList(), null)\n"
181+
+ " ? ImmutableList.<EchoResponse>of()\n"
182+
+ " : payload.getResponsesList();\n"
183+
+ " }\n"
184+
+ " };\n"
142185
+ " private static final PagedListResponseFactory<\n"
143186
+ " PagedExpandRequest, PagedExpandResponse, PagedExpandPagedResponse>\n"
144187
+ " PAGED_EXPAND_PAGE_STR_FACT =\n"

0 commit comments

Comments
 (0)