16
16
17
17
import com .google .api .ClientProto ;
18
18
import com .google .api .DocumentationRule ;
19
+ import com .google .api .FieldBehavior ;
20
+ import com .google .api .FieldBehaviorProto ;
21
+ import com .google .api .FieldInfo .Format ;
22
+ import com .google .api .FieldInfoProto ;
19
23
import com .google .api .HttpRule ;
24
+ import com .google .api .MethodSettings ;
20
25
import com .google .api .ResourceDescriptor ;
21
26
import com .google .api .ResourceProto ;
22
27
import com .google .api .generator .engine .ast .TypeNode ;
47
52
import com .google .common .collect .BiMap ;
48
53
import com .google .common .collect .HashBiMap ;
49
54
import com .google .common .collect .ImmutableList ;
55
+ import com .google .common .collect .ImmutableMap ;
50
56
import com .google .common .collect .ImmutableSet ;
51
57
import com .google .common .collect .Maps ;
52
58
import com .google .longrunning .OperationInfo ;
@@ -493,6 +499,7 @@ public static List<Service> parseService(
493
499
messageTypes ,
494
500
resourceNames ,
495
501
serviceConfigOpt ,
502
+ serviceYamlProtoOpt ,
496
503
outputArgResourceNames ,
497
504
transport ))
498
505
.build ();
@@ -683,9 +690,15 @@ static List<Method> parseMethods(
683
690
Map <String , Message > messageTypes ,
684
691
Map <String , ResourceName > resourceNames ,
685
692
Optional <GapicServiceConfig > serviceConfigOpt ,
693
+ Optional <com .google .api .Service > serviceYamlProtoOpt ,
686
694
Set <ResourceName > outputArgResourceNames ,
687
695
Transport transport ) {
688
696
List <Method > methods = new ArrayList <>();
697
+
698
+ // Parse the serviceYaml for autopopulated methods and fields once and put into a map
699
+ Map <String , List <String >> autoPopulatedMethodsWithFields =
700
+ parseAutoPopulatedMethodsAndFields (serviceYamlProtoOpt );
701
+
689
702
for (MethodDescriptor protoMethod : serviceDescriptor .getMethods ()) {
690
703
// Parse the method.
691
704
TypeNode inputType = TypeParser .parseType (protoMethod .getInputType ());
@@ -699,6 +712,12 @@ static List<Method> parseMethods(
699
712
}
700
713
}
701
714
715
+ // Associate the autopopulated fields with the correct method
716
+ List <String > autoPopulatedFields = new ArrayList <>();
717
+ if (autoPopulatedMethodsWithFields .containsKey (protoMethod .getFullName ())) {
718
+ autoPopulatedFields = autoPopulatedMethodsWithFields .get (protoMethod .getFullName ());
719
+ }
720
+
702
721
boolean isDeprecated = false ;
703
722
if (protoMethod .getOptions ().hasDeprecated ()) {
704
723
isDeprecated = protoMethod .getOptions ().getDeprecated ();
@@ -743,6 +762,7 @@ static List<Method> parseMethods(
743
762
resourceNames ,
744
763
outputArgResourceNames ))
745
764
.setHttpBindings (httpBindings )
765
+ .setAutoPopulatedFields (autoPopulatedFields )
746
766
.setRoutingHeaderRule (routingHeaderRule )
747
767
.setIsBatching (isBatching )
748
768
.setPageSizeFieldName (parsePageSizeFieldName (protoMethod , messageTypes , transport ))
@@ -970,6 +990,8 @@ private static Field parseField(
970
990
FieldOptions fieldOptions = fieldDescriptor .getOptions ();
971
991
MessageOptions messageOptions = messageDescriptor .getOptions ();
972
992
ResourceReference resourceReference = null ;
993
+ boolean isRequired = false ;
994
+ Format fieldInfoFormat = null ;
973
995
if (fieldOptions .hasExtension (ResourceProto .resourceReference )) {
974
996
com .google .api .ResourceReference protoResourceReference =
975
997
fieldOptions .getExtension (ResourceProto .resourceReference );
@@ -1000,6 +1022,16 @@ private static Field parseField(
1000
1022
}
1001
1023
}
1002
1024
1025
+ if (fieldOptions .hasExtension (FieldInfoProto .fieldInfo )) {
1026
+ fieldInfoFormat = fieldOptions .getExtension (FieldInfoProto .fieldInfo ).getFormat ();
1027
+ }
1028
+ if (fieldOptions .getExtensionCount (FieldBehaviorProto .fieldBehavior ) > 0 ) {
1029
+ if (fieldOptions
1030
+ .getExtension (FieldBehaviorProto .fieldBehavior )
1031
+ .contains (FieldBehavior .REQUIRED )) ;
1032
+ isRequired = true ;
1033
+ }
1034
+
1003
1035
Field .Builder fieldBuilder = Field .builder ();
1004
1036
if (fieldDescriptor .getFile ().toProto ().hasSourceCodeInfo ()) {
1005
1037
SourceCodeInfoLocation protoFieldLocation =
@@ -1030,6 +1062,8 @@ private static Field parseField(
1030
1062
fieldDescriptor .getContainingOneof () != null
1031
1063
&& fieldDescriptor .getContainingOneof ().isSynthetic ())
1032
1064
.setIsRepeated (fieldDescriptor .isRepeated ())
1065
+ .setIsRequired (isRequired )
1066
+ .setFieldInfoFormat (fieldInfoFormat )
1033
1067
.setIsMap (fieldDescriptor .isMapField ())
1034
1068
.setResourceReference (resourceReference )
1035
1069
.build ();
@@ -1124,4 +1158,25 @@ static String parseNestedProtoTypeName(String fullyQualifiedName) {
1124
1158
.collect (Collectors .toList ());
1125
1159
return String .join ("." , nestedTypeComponents );
1126
1160
}
1161
+
1162
+ /**
1163
+ * Converts a serviceYaml file to a map of methods and autopopulated fields. Note: this does NOT
1164
+ * currently support wildcards in MethodSettings.selectors.
1165
+ */
1166
+ @ VisibleForTesting
1167
+ static Map <String , List <String >> parseAutoPopulatedMethodsAndFields (
1168
+ Optional <com .google .api .Service > serviceYamlProtoOpt ) {
1169
+ if (!hasMethodSettings (serviceYamlProtoOpt )) {
1170
+ return ImmutableMap .<String , List <String >>builder ().build ();
1171
+ }
1172
+ return serviceYamlProtoOpt .get ().getPublishing ().getMethodSettingsList ().stream ()
1173
+ .collect (
1174
+ Collectors .toMap (
1175
+ MethodSettings ::getSelector , MethodSettings ::getAutoPopulatedFieldsList ));
1176
+ }
1177
+
1178
+ @ VisibleForTesting
1179
+ static boolean hasMethodSettings (Optional <com .google .api .Service > serviceYamlProtoOpt ) {
1180
+ return serviceYamlProtoOpt .isPresent () && serviceYamlProtoOpt .get ().hasPublishing ();
1181
+ }
1127
1182
}
0 commit comments