1414
1515package com .google .api .generator .gapic .protoparser ;
1616
17+ import com .google .api .ClientLibrarySettings ;
1718import com .google .api .ClientProto ;
1819import com .google .api .DocumentationRule ;
1920import com .google .api .FieldBehavior ;
8485import java .util .Optional ;
8586import java .util .Set ;
8687import java .util .function .Function ;
88+ import java .util .logging .Level ;
8789import java .util .logging .Logger ;
8890import java .util .stream .Collectors ;
8991import java .util .stream .IntStream ;
@@ -160,11 +162,11 @@ public static GapicContext parse(CodeGeneratorRequest request) {
160162 messages = updateResourceNamesInMessages (messages , resourceNames .values ());
161163
162164 // Contains only resource names that are actually used. Usage refers to the presence of a
163- // request message's field in an RPC's method_signature annotation. That is, resource name
164- // definitions
165- // or references that are simply defined, but not used in such a manner, will not have
166- // corresponding Java helper
167- // classes generated.
165+ // request message's field in an RPC's method_signature annotation. That is, resource name
166+ // definitions or references that are simply defined, but not used in such a manner,
167+ // will not have corresponding Java helper classes generated.
168+ // If selective api generation is configured via service yaml, Java helper classes are only
169+ // generated if resource names are actually used by methods selected to generate .
168170 Set <ResourceName > outputArgResourceNames = new HashSet <>();
169171 List <Service > mixinServices = new ArrayList <>();
170172 Transport transport = Transport .parse (transportOpt .orElse (Transport .GRPC .toString ()));
@@ -425,6 +427,71 @@ public static List<Service> parseService(
425427 Transport .GRPC );
426428 }
427429
430+ static boolean shouldIncludeMethodInGeneration (
431+ MethodDescriptor method ,
432+ Optional <com .google .api .Service > serviceYamlProtoOpt ,
433+ String protoPackage ) {
434+ // default to include all when no service yaml or no library setting section.
435+ if (!serviceYamlProtoOpt .isPresent ()
436+ || serviceYamlProtoOpt .get ().getPublishing ().getLibrarySettingsCount () == 0 ) {
437+ return true ;
438+ }
439+ List <ClientLibrarySettings > librarySettingsList =
440+ serviceYamlProtoOpt .get ().getPublishing ().getLibrarySettingsList ();
441+ // Validate for logging purpose, this should be validated upstream.
442+ // If library_settings.version does not match with proto package name
443+ // Give warnings and disregard this config. default to include all.
444+ if (!librarySettingsList .get (0 ).getVersion ().isEmpty ()
445+ && !protoPackage .equals (librarySettingsList .get (0 ).getVersion ())) {
446+ if (LOGGER .isLoggable (Level .WARNING )) {
447+ LOGGER .warning (
448+ String .format (
449+ "Service yaml config is misconfigured. Version in "
450+ + "publishing.library_settings (%s) does not match proto package (%s)."
451+ + "Disregarding selective generation settings." ,
452+ librarySettingsList .get (0 ).getVersion (), protoPackage ));
453+ }
454+ return true ;
455+ }
456+ // librarySettingsList is technically a list, but is processed upstream and
457+ // only leave with 1 element. Otherwise, it is a misconfiguration and
458+ // should be caught upstream.
459+ List <String > includeMethodsList =
460+ librarySettingsList
461+ .get (0 )
462+ .getJavaSettings ()
463+ .getCommon ()
464+ .getSelectiveGapicGeneration ()
465+ .getMethodsList ();
466+ // default to include all when nothing specified, this could be no java section
467+ // specified in library setting, or the method list is empty
468+ if (includeMethodsList .isEmpty ()) {
469+ return true ;
470+ }
471+
472+ return includeMethodsList .contains (method .getFullName ());
473+ }
474+
475+ private static boolean isEmptyService (
476+ ServiceDescriptor serviceDescriptor ,
477+ Optional <com .google .api .Service > serviceYamlProtoOpt ,
478+ String protoPackage ) {
479+ List <MethodDescriptor > methodsList = serviceDescriptor .getMethods ();
480+ List <MethodDescriptor > methodListSelected =
481+ methodsList .stream ()
482+ .filter (
483+ method ->
484+ shouldIncludeMethodInGeneration (method , serviceYamlProtoOpt , protoPackage ))
485+ .collect (Collectors .toList ());
486+ if (methodListSelected .isEmpty ()) {
487+ LOGGER .log (
488+ Level .WARNING ,
489+ "Service {0} has no RPC methods and will not be generated" ,
490+ serviceDescriptor .getName ());
491+ }
492+ return methodListSelected .isEmpty ();
493+ }
494+
428495 public static List <Service > parseService (
429496 FileDescriptor fileDescriptor ,
430497 Map <String , Message > messageTypes ,
@@ -433,19 +500,11 @@ public static List<Service> parseService(
433500 Optional <GapicServiceConfig > serviceConfigOpt ,
434501 Set <ResourceName > outputArgResourceNames ,
435502 Transport transport ) {
436-
503+ String protoPackage = fileDescriptor . getPackage ();
437504 return fileDescriptor .getServices ().stream ()
438505 .filter (
439- serviceDescriptor -> {
440- List <MethodDescriptor > methodsList = serviceDescriptor .getMethods ();
441- if (methodsList .isEmpty ()) {
442- LOGGER .warning (
443- String .format (
444- "Service %s has no RPC methods and will not be generated" ,
445- serviceDescriptor .getName ()));
446- }
447- return !methodsList .isEmpty ();
448- })
506+ serviceDescriptor ->
507+ !isEmptyService (serviceDescriptor , serviceYamlProtoOpt , protoPackage ))
449508 .map (
450509 s -> {
451510 // Workaround for a missing default_host and oauth_scopes annotation from a service
@@ -498,6 +557,8 @@ public static List<Service> parseService(
498557 String pakkage = TypeParser .getPackage (fileDescriptor );
499558 String originalJavaPackage = pakkage ;
500559 // Override Java package with that specified in gapic.yaml.
560+ // this override is deprecated and legacy support only
561+ // see go/client-user-guide#configure-long-running-operation-polling-timeouts-optional
501562 if (serviceConfigOpt .isPresent ()
502563 && serviceConfigOpt .get ().getLanguageSettingsOpt ().isPresent ()) {
503564 GapicLanguageSettings languageSettings =
@@ -518,6 +579,7 @@ public static List<Service> parseService(
518579 .setMethods (
519580 parseMethods (
520581 s ,
582+ protoPackage ,
521583 pakkage ,
522584 messageTypes ,
523585 resourceNames ,
@@ -709,6 +771,7 @@ public static Map<String, ResourceName> parseResourceNames(
709771 @ VisibleForTesting
710772 static List <Method > parseMethods (
711773 ServiceDescriptor serviceDescriptor ,
774+ String protoPackage ,
712775 String servicePackage ,
713776 Map <String , Message > messageTypes ,
714777 Map <String , ResourceName > resourceNames ,
@@ -721,8 +784,10 @@ static List<Method> parseMethods(
721784 // Parse the serviceYaml for autopopulated methods and fields once and put into a map
722785 Map <String , List <String >> autoPopulatedMethodsWithFields =
723786 parseAutoPopulatedMethodsAndFields (serviceYamlProtoOpt );
724-
725787 for (MethodDescriptor protoMethod : serviceDescriptor .getMethods ()) {
788+ if (!shouldIncludeMethodInGeneration (protoMethod , serviceYamlProtoOpt , protoPackage )) {
789+ continue ;
790+ }
726791 // Parse the method.
727792 TypeNode inputType = TypeParser .parseType (protoMethod .getInputType ());
728793 Method .Builder methodBuilder = Method .builder ();
0 commit comments