6262import com .google .api .generator .engine .ast .MethodDefinition ;
6363import com .google .api .generator .engine .ast .MethodInvocationExpr ;
6464import com .google .api .generator .engine .ast .NewObjectExpr ;
65+ import com .google .api .generator .engine .ast .NullObjectValue ;
6566import com .google .api .generator .engine .ast .Reference ;
6667import com .google .api .generator .engine .ast .ReferenceConstructorExpr ;
6768import com .google .api .generator .engine .ast .ReturnExpr ;
6869import com .google .api .generator .engine .ast .ScopeNode ;
6970import com .google .api .generator .engine .ast .Statement ;
7071import com .google .api .generator .engine .ast .StringObjectValue ;
72+ import com .google .api .generator .engine .ast .TernaryExpr ;
7173import com .google .api .generator .engine .ast .ThisObjectValue ;
7274import com .google .api .generator .engine .ast .ThrowExpr ;
7375import com .google .api .generator .engine .ast .TypeNode ;
9698import java .util .LinkedHashMap ;
9799import java .util .List ;
98100import java .util .Map ;
101+ import java .util .Objects ;
99102import java .util .function .Function ;
100103import java .util .stream .Collectors ;
101104import 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 (
0 commit comments