14
14
15
15
package com .google .api .generator .gapic .composer .rest ;
16
16
17
+ import com .google .api .HttpRule ;
17
18
import com .google .api .core .InternalApi ;
18
19
import com .google .api .gax .httpjson .ApiMethodDescriptor ;
19
20
import com .google .api .gax .httpjson .ApiMethodDescriptor .MethodType ;
63
64
import com .google .common .annotations .VisibleForTesting ;
64
65
import com .google .common .collect .BiMap ;
65
66
import com .google .common .collect .ImmutableList ;
67
+ import com .google .common .collect .ImmutableMap ;
66
68
import com .google .protobuf .TypeRegistry ;
67
69
import java .util .ArrayList ;
68
70
import java .util .Arrays ;
73
75
import java .util .Set ;
74
76
import java .util .function .BiFunction ;
75
77
import java .util .function .Function ;
78
+ import java .util .function .Predicate ;
76
79
import java .util .stream .Collectors ;
77
80
78
81
public class HttpJsonServiceStubClassComposer extends AbstractTransportServiceStubClassComposer {
79
-
80
82
private static final HttpJsonServiceStubClassComposer INSTANCE =
81
83
new HttpJsonServiceStubClassComposer ();
82
84
@@ -89,6 +91,7 @@ public class HttpJsonServiceStubClassComposer extends AbstractTransportServiceSt
89
91
.setType (FIXED_REST_TYPESTORE .get (TypeRegistry .class .getSimpleName ()))
90
92
.build ())
91
93
.build ();
94
+ private static final String LRO_NAME_PREFIX = "google.longrunning.Operations" ;
92
95
93
96
protected HttpJsonServiceStubClassComposer () {
94
97
super (RestContext .instance ());
@@ -109,7 +112,9 @@ private static TypeStore createStaticTypes() {
109
112
HttpJsonCallSettings .class ,
110
113
HttpJsonOperationSnapshot .class ,
111
114
HttpJsonStubCallableFactory .class ,
115
+ HttpRule .class ,
112
116
Map .class ,
117
+ ImmutableMap .class ,
113
118
ProtoMessageRequestFormatter .class ,
114
119
ProtoMessageResponseParser .class ,
115
120
ProtoRestSerializer .class ,
@@ -1075,6 +1080,7 @@ private List<Expr> getMethodTypeExpr(Method protoMethod) {
1075
1080
1076
1081
@ Override
1077
1082
protected List <Expr > createOperationsStubInitExpr (
1083
+ GapicContext context ,
1078
1084
Service service ,
1079
1085
Expr thisExpr ,
1080
1086
VariableExpr operationsStubClassVarExpr ,
@@ -1089,6 +1095,47 @@ protected List<Expr> createOperationsStubInitExpr(
1089
1095
arguments .add (TYPE_REGISTRY_VAR_EXPR );
1090
1096
}
1091
1097
1098
+ // If the Service contains custom HttpRules for Operations, we pass a map of the custom rules to
1099
+ // the Operations Client
1100
+ Map <String , HttpRule > operationCustomHttpRules = parseOperationsCustomHttpRules (context );
1101
+ if (operationCustomHttpRules .size () > 0 ) {
1102
+ Expr operationCustomHttpBindingsBuilderExpr =
1103
+ MethodInvocationExpr .builder ()
1104
+ .setStaticReferenceType (FIXED_REST_TYPESTORE .get (ImmutableMap .class .getSimpleName ()))
1105
+ .setMethodName ("builder" )
1106
+ .setGenerics (
1107
+ Arrays .asList (
1108
+ TypeNode .STRING .reference (),
1109
+ FIXED_REST_TYPESTORE .get (HttpRule .class .getSimpleName ()).reference ()))
1110
+ .build ();
1111
+
1112
+ // Sorting is done to ensure consistent ordering of the entries in the Custom HttpRule Map
1113
+ for (String selector :
1114
+ operationCustomHttpRules .keySet ().stream ().sorted ().collect (Collectors .toList ())) {
1115
+ HttpRule httpRule = operationCustomHttpRules .get (selector );
1116
+ Expr httpRuleBuilderExpr = createHttpRuleExpr (httpRule , true );
1117
+
1118
+ operationCustomHttpBindingsBuilderExpr =
1119
+ MethodInvocationExpr .builder ()
1120
+ .setExprReferenceExpr (operationCustomHttpBindingsBuilderExpr )
1121
+ .setMethodName ("put" )
1122
+ .setArguments (
1123
+ Arrays .asList (
1124
+ ValueExpr .withValue (StringObjectValue .withValue (selector )),
1125
+ httpRuleBuilderExpr ))
1126
+ .build ();
1127
+ }
1128
+
1129
+ operationCustomHttpBindingsBuilderExpr =
1130
+ MethodInvocationExpr .builder ()
1131
+ .setExprReferenceExpr (operationCustomHttpBindingsBuilderExpr )
1132
+ .setMethodName ("build" )
1133
+ .setReturnType (FIXED_REST_TYPESTORE .get (ImmutableMap .class .getSimpleName ()))
1134
+ .build ();
1135
+
1136
+ arguments .add (operationCustomHttpBindingsBuilderExpr );
1137
+ }
1138
+
1092
1139
return Collections .singletonList (
1093
1140
AssignmentExpr .builder ()
1094
1141
.setVariableExpr (
@@ -1103,6 +1150,73 @@ protected List<Expr> createOperationsStubInitExpr(
1103
1150
.build ());
1104
1151
}
1105
1152
1153
+ /* Build an Expr that creates an HttpRule. Creates a builder and adds the http verb, custom path, and any additional bindings. `additional_bindings` can only be nested one layer deep, so we only check once */
1154
+ private Expr createHttpRuleExpr (HttpRule httpRule , boolean checkAdditionalBindings ) {
1155
+ Expr httpRuleBuilderExpr =
1156
+ MethodInvocationExpr .builder ()
1157
+ .setStaticReferenceType (FIXED_REST_TYPESTORE .get (HttpRule .class .getSimpleName ()))
1158
+ .setMethodName ("newBuilder" )
1159
+ .build ();
1160
+
1161
+ httpRuleBuilderExpr =
1162
+ MethodInvocationExpr .builder ()
1163
+ .setExprReferenceExpr (httpRuleBuilderExpr )
1164
+ // toLowerCase as the PatternCase result is all uppercase
1165
+ .setMethodName (setMethodFormat (httpRule .getPatternCase ().toString ().toLowerCase ()))
1166
+ .setArguments (
1167
+ ValueExpr .withValue (
1168
+ StringObjectValue .withValue (getOperationsURIValueFromHttpRule (httpRule ))))
1169
+ .setReturnType (FIXED_REST_TYPESTORE .get (HttpRule .class .getSimpleName ()))
1170
+ .build ();
1171
+
1172
+ if (checkAdditionalBindings ) {
1173
+ for (HttpRule additionalBindings : httpRule .getAdditionalBindingsList ()) {
1174
+ httpRuleBuilderExpr =
1175
+ MethodInvocationExpr .builder ()
1176
+ .setExprReferenceExpr (httpRuleBuilderExpr )
1177
+ .setMethodName ("addAdditionalBindings" )
1178
+ .setArguments (Arrays .asList (createHttpRuleExpr (additionalBindings , false )))
1179
+ .build ();
1180
+ }
1181
+ }
1182
+
1183
+ httpRuleBuilderExpr =
1184
+ MethodInvocationExpr .builder ()
1185
+ .setExprReferenceExpr (httpRuleBuilderExpr )
1186
+ .setMethodName ("build" )
1187
+ .setReturnType (FIXED_REST_TYPESTORE .get (HttpRule .class .getSimpleName ()))
1188
+ .build ();
1189
+ return httpRuleBuilderExpr ;
1190
+ }
1191
+
1192
+ /* Parses the Service Yaml file's for custom HttpRules. Filter the HttpRules for ones that match Operations */
1193
+ Map <String , HttpRule > parseOperationsCustomHttpRules (GapicContext context ) {
1194
+ Predicate <HttpRule > predicate = x -> x .getSelector ().contains (LRO_NAME_PREFIX );
1195
+ com .google .api .Service service = context .serviceYamlProto ();
1196
+ if (service == null || service .getHttp () == null ) {
1197
+ return ImmutableMap .of ();
1198
+ }
1199
+ return service .getHttp ().getRulesList ().stream ()
1200
+ .filter (predicate )
1201
+ .collect (Collectors .toMap (HttpRule ::getSelector , x -> x ));
1202
+ }
1203
+
1204
+ /* This is meant to be used for the OperationsClient Mixin OperationsClient's RPCs are mapped to GET/POST/DELETE and this function only expects those HttpVerbs to be used */
1205
+ String getOperationsURIValueFromHttpRule (HttpRule httpRule ) {
1206
+ switch (httpRule .getPatternCase ().getNumber ()) {
1207
+ case 2 :
1208
+ return httpRule .getGet ();
1209
+ case 4 :
1210
+ return httpRule .getPost ();
1211
+ case 5 :
1212
+ return httpRule .getDelete ();
1213
+ default :
1214
+ throw new IllegalArgumentException (
1215
+ "Operations HttpRule should only contain GET/POST/DELETE. Invalid: "
1216
+ + httpRule .getSelector ());
1217
+ }
1218
+ }
1219
+
1106
1220
@ Override
1107
1221
protected List <Statement > createLongRunningClient (Service service , TypeStore typeStore ) {
1108
1222
Method pollingMethod = service .operationPollingMethod ();
0 commit comments