1515package com .google .api .generator .gapic .protoparser ;
1616
1717import com .google .api .ClientProto ;
18+ import com .google .api .DocumentationRule ;
19+ import com .google .api .HttpRule ;
1820import com .google .api .ResourceDescriptor ;
1921import com .google .api .ResourceProto ;
2022import com .google .api .generator .engine .ast .TypeNode ;
@@ -239,6 +241,33 @@ public static List<Service> parseServices(
239241 .filter (a -> MIXIN_ALLOWLIST .contains (a .getName ()))
240242 .map (a -> a .getName ())
241243 .collect (Collectors .toSet ());
244+ // Holds the methods to be mixed in.
245+ // Key: proto_package.ServiceName.RpcName.
246+ // Value: HTTP rules, which clobber those in the proto.
247+ // Assumes that http.rules.selector always specifies RPC names in the above format.
248+ Map <String , List <String >> mixedInMethodsToHttpRules = new HashMap <>();
249+ Map <String , String > mixedInMethodsToDocs = new HashMap <>();
250+ // Parse HTTP rules and documentation, which will override the proto.
251+ if (serviceYamlProtoOpt .isPresent ()) {
252+ for (HttpRule httpRule : serviceYamlProtoOpt .get ().getHttp ().getRulesList ()) {
253+ Optional <List <String >> httpBindingsOpt = HttpRuleParser .parseHttpRule (httpRule );
254+ if (!httpBindingsOpt .isPresent ()) {
255+ continue ;
256+ }
257+ for (String rpcFullNameRaw : httpRule .getSelector ().split ("," )) {
258+ String rpcFullName = rpcFullNameRaw .trim ();
259+ mixedInMethodsToHttpRules .put (rpcFullName , httpBindingsOpt .get ());
260+ }
261+ }
262+ for (DocumentationRule docRule :
263+ serviceYamlProtoOpt .get ().getDocumentation ().getRulesList ()) {
264+ for (String rpcFullNameRaw : docRule .getSelector ().split ("," )) {
265+ String rpcFullName = rpcFullNameRaw .trim ();
266+ mixedInMethodsToDocs .put (rpcFullName , docRule .getDescription ());
267+ }
268+ }
269+ }
270+
242271 Set <String > apiDefinedRpcs = new HashSet <>();
243272 for (Service service : services ) {
244273 if (blockedCodegenMixinApis .contains (service )) {
@@ -252,28 +281,55 @@ public static List<Service> parseServices(
252281 if (servicesContainBlocklistedApi && !mixedInApis .isEmpty ()) {
253282 for (int i = 0 ; i < services .size (); i ++) {
254283 Service originalService = services .get (i );
255- List <Method > updatedMethods = new ArrayList <>(originalService .methods ());
284+ List <Method > updatedOriginalServiceMethods = new ArrayList <>(originalService .methods ());
256285 // If mixin APIs are present, add the methods to all other services.
257286 for (Service mixinService : blockedCodegenMixinApis ) {
258- if (! mixedInApis . contains (
259- String . format ( "%s.%s" , mixinService . protoPakkage (), mixinService . name ()) )) {
287+ final String mixinServiceFullName = serviceFullNameFn . apply ( mixinService );
288+ if (! mixedInApis . contains ( mixinServiceFullName )) {
260289 continue ;
261290 }
262- mixinService
263- .methods ()
291+ Function <Method , String > methodToFullProtoNameFn =
292+ m -> String .format ("%s.%s" , mixinServiceFullName , m .name ());
293+ // Filter mixed-in methods based on those listed in the HTTP rules section of
294+ // service.yaml.
295+ List <Method > updatedMixinMethods =
296+ mixinService .methods ().stream ()
297+ // Mixin method inclusion is based on the HTTP rules list in service.yaml.
298+ .filter (
299+ m -> mixedInMethodsToHttpRules .containsKey (methodToFullProtoNameFn .apply (m )))
300+ .map (
301+ m -> {
302+ // HTTP rules and RPC documentation in the service.yaml file take
303+ // precedence.
304+ String fullMethodName = methodToFullProtoNameFn .apply (m );
305+ List <String > httpBindings =
306+ mixedInMethodsToHttpRules .containsKey (fullMethodName )
307+ ? mixedInMethodsToHttpRules .get (fullMethodName )
308+ : m .httpBindings ();
309+ String docs =
310+ mixedInMethodsToDocs .containsKey (fullMethodName )
311+ ? mixedInMethodsToDocs .get (fullMethodName )
312+ : m .description ();
313+ return m .toBuilder ()
314+ .setHttpBindings (httpBindings )
315+ .setDescription (docs )
316+ .build ();
317+ })
318+ .collect (Collectors .toList ());
319+ // Overridden RPCs defined in the protos take precedence.
320+ updatedMixinMethods .stream ()
321+ .filter (m -> !apiDefinedRpcs .contains (m .name ()))
264322 .forEach (
265- m -> {
266- // Overridden RPCs defined in the protos take precedence.
267- if (!apiDefinedRpcs .contains (m .name ())) {
268- updatedMethods .add (
323+ m ->
324+ updatedOriginalServiceMethods .add (
269325 m .toBuilder ()
270326 .setMixedInApiName (serviceFullNameFn .apply (mixinService ))
271- .build ());
272- }
273- });
274- outputMixinServiceSet .add (mixinService );
327+ .build ()));
328+ outputMixinServiceSet .add (
329+ mixinService .toBuilder ().setMethods (updatedMixinMethods ).build ());
275330 }
276- services .set (i , originalService .toBuilder ().setMethods (updatedMethods ).build ());
331+ services .set (
332+ i , originalService .toBuilder ().setMethods (updatedOriginalServiceMethods ).build ());
277333 }
278334 }
279335
0 commit comments