Skip to content

Commit 0a89829

Browse files
authored
feat: Add support for rest numeric enums. (#1020)
See b/232457244 for exact requirements. In short, this PR added four things: 1. Add a flag to the Java microgenerator Bazel plugin to determine whether we need to generate a client library that supports rest numeric enums. This flag is to make sure we only generate client libraries with numeric enums for the services that have already upgraded to the latest ESF. See go/gapic-numericenum-release for details. 2. Serialize enum object to int if the above flag is set to true 3. Add a query parameter $alt=json;enum-encoding=int to every request if the above flag is set to true so that the backend will return response with numeric enums. 4. Upgrade gax-java to the latest
1 parent 5d94f1d commit 0a89829

File tree

13 files changed

+137
-36
lines changed

13 files changed

+137
-36
lines changed

WORKSPACE

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jvm_maven_import_external(
3333
# which in its turn, prioritizes actual generated clients runtime dependencies
3434
# over the generator dependencies.
3535

36-
_gax_java_version = "2.12.2"
36+
_gax_java_version = "2.19.0"
3737

3838
http_archive(
3939
name = "com_google_api_gax_java",

rules_java_gapic/java_gapic.bzl

+8
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ def _java_gapic_srcjar(
189189
service_yaml,
190190
# possible values are: "grpc", "rest", "grpc+rest"
191191
transport,
192+
rest_numeric_enums,
192193
# Can be used to provide a java_library with a customized generator,
193194
# like the one which dumps descriptor to a file for future debugging.
194195
java_generator_name = "java_gapic",
@@ -213,6 +214,9 @@ def _java_gapic_srcjar(
213214
if transport:
214215
opt_args.append("transport=%s" % transport)
215216

217+
if rest_numeric_enums:
218+
opt_args.append("rest-numeric-enums")
219+
216220
# Produces the GAPIC metadata file if this flag is set. to any value.
217221
# Protoc invocation: --java_gapic_opt=metadata
218222
plugin_args = ["metadata"]
@@ -240,6 +244,7 @@ def java_gapic_library(
240244
test_deps = [],
241245
# possible values are: "grpc", "rest", "grpc+rest"
242246
transport = None,
247+
rest_numeric_enums = False,
243248
**kwargs):
244249
srcjar_name = name + "_srcjar"
245250
raw_srcjar_name = srcjar_name + "_raw"
@@ -251,6 +256,7 @@ def java_gapic_library(
251256
gapic_yaml = gapic_yaml,
252257
service_yaml = service_yaml,
253258
transport = transport,
259+
rest_numeric_enums = rest_numeric_enums,
254260
java_generator_name = "java_gapic",
255261
**kwargs
256262
)
@@ -391,6 +397,7 @@ def java_generator_request_dump(
391397
gapic_yaml = None,
392398
service_yaml = None,
393399
transport = None,
400+
rest_numeric_enums = False,
394401
**kwargs):
395402
_java_gapic_srcjar(
396403
name = name,
@@ -399,6 +406,7 @@ def java_generator_request_dump(
399406
gapic_yaml = gapic_yaml,
400407
service_yaml = service_yaml,
401408
transport = transport,
409+
rest_numeric_enums = rest_numeric_enums,
402410
java_generator_name = "code_generator_request_dumper",
403411
**kwargs
404412
)

src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java

+14-6
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ public GapicClass generate(GapicContext context, Service service) {
187187
protoMethodNameToDescriptorVarExprs,
188188
callableClassMemberVarExprs,
189189
classMemberVarExprs,
190-
messageTypes);
190+
messageTypes,
191+
context.restNumericEnumsEnabled());
191192

192193
StubCommentComposer commentComposer =
193194
new StubCommentComposer(getTransportContext().transportNames().get(0));
@@ -225,7 +226,8 @@ protected abstract Statement createMethodDescriptorVariableDecl(
225226
Service service,
226227
Method protoMethod,
227228
VariableExpr methodDescriptorVarExpr,
228-
Map<String, Message> messageTypes);
229+
Map<String, Message> messageTypes,
230+
boolean restNumericEnumsEnabled);
229231

230232
protected boolean generateOperationsStubLogic(Service service) {
231233
return true;
@@ -274,7 +276,8 @@ protected List<Statement> createClassStatements(
274276
Map<String, VariableExpr> protoMethodNameToDescriptorVarExprs,
275277
Map<String, VariableExpr> callableClassMemberVarExprs,
276278
Map<String, VariableExpr> classMemberVarExprs,
277-
Map<String, Message> messageTypes) {
279+
Map<String, Message> messageTypes,
280+
boolean restNumericEnumsEnabled) {
278281
List<Statement> classStatements = new ArrayList<>();
279282

280283
classStatements.addAll(createTypeRegistry(service));
@@ -284,7 +287,7 @@ protected List<Statement> createClassStatements(
284287

285288
for (Statement statement :
286289
createMethodDescriptorVariableDecls(
287-
service, protoMethodNameToDescriptorVarExprs, messageTypes)) {
290+
service, protoMethodNameToDescriptorVarExprs, messageTypes, restNumericEnumsEnabled)) {
288291
classStatements.add(statement);
289292
classStatements.add(EMPTY_LINE_STATEMENT);
290293
}
@@ -301,13 +304,18 @@ protected List<Statement> createClassStatements(
301304
protected List<Statement> createMethodDescriptorVariableDecls(
302305
Service service,
303306
Map<String, VariableExpr> protoMethodNameToDescriptorVarExprs,
304-
Map<String, Message> messageTypes) {
307+
Map<String, Message> messageTypes,
308+
boolean restNumericEnumsEnabled) {
305309
return service.methods().stream()
306310
.filter(this::isSupportedMethod)
307311
.map(
308312
m ->
309313
createMethodDescriptorVariableDecl(
310-
service, m, protoMethodNameToDescriptorVarExprs.get(m.name()), messageTypes))
314+
service,
315+
m,
316+
protoMethodNameToDescriptorVarExprs.get(m.name()),
317+
messageTypes,
318+
restNumericEnumsEnabled))
311319
.collect(Collectors.toList());
312320
}
313321

src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ protected Statement createMethodDescriptorVariableDecl(
9595
Service service,
9696
Method protoMethod,
9797
VariableExpr methodDescriptorVarExpr,
98-
Map<String, Message> messageTypes) {
98+
Map<String, Message> messageTypes,
99+
boolean restNumericEnumsEnabled) {
99100
MethodInvocationExpr methodDescriptorMaker =
100101
MethodInvocationExpr.builder()
101102
.setMethodName("newBuilder")

src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java

+42-8
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ protected Statement createMethodDescriptorVariableDecl(
129129
Service service,
130130
Method protoMethod,
131131
VariableExpr methodDescriptorVarExpr,
132-
Map<String, Message> messageTypes) {
132+
Map<String, Message> messageTypes,
133+
boolean restNumericEnumsEnabled) {
133134
MethodInvocationExpr expr =
134135
MethodInvocationExpr.builder()
135136
.setMethodName("newBuilder")
@@ -152,7 +153,11 @@ protected Statement createMethodDescriptorVariableDecl(
152153
expr = methodMaker.apply("setHttpMethod", getHttpMethodTypeExpr(protoMethod)).apply(expr);
153154
expr = methodMaker.apply("setType", getMethodTypeExpr(protoMethod)).apply(expr);
154155
expr =
155-
methodMaker.apply("setRequestFormatter", getRequestFormatterExpr(protoMethod)).apply(expr);
156+
methodMaker
157+
.apply(
158+
"setRequestFormatter",
159+
getRequestFormatterExpr(protoMethod, restNumericEnumsEnabled))
160+
.apply(expr);
156161
expr = methodMaker.apply("setResponseParser", setResponseParserExpr(protoMethod)).apply(expr);
157162

158163
if (protoMethod.isOperationPollingMethod() || protoMethod.hasLro()) {
@@ -320,7 +325,7 @@ protected List<MethodDefinition> createGetMethodDescriptorsMethod(
320325
.build();
321326
}
322327

323-
private List<Expr> getRequestFormatterExpr(Method protoMethod) {
328+
private List<Expr> getRequestFormatterExpr(Method protoMethod, boolean restNumericEnumsEnabled) {
324329
BiFunction<String, List<Expr>, Function<MethodInvocationExpr, MethodInvocationExpr>>
325330
methodMaker = getMethodMaker();
326331

@@ -351,7 +356,8 @@ private List<Expr> getRequestFormatterExpr(Method protoMethod) {
351356
protoMethod,
352357
extractorVarType,
353358
protoMethod.httpBindings().pathParameters(),
354-
"putPathParam")))
359+
"putPathParam",
360+
restNumericEnumsEnabled)))
355361
.apply(expr);
356362

357363
if (!protoMethod.httpBindings().lowerCamelAdditionalPatterns().isEmpty()) {
@@ -387,7 +393,8 @@ private List<Expr> getRequestFormatterExpr(Method protoMethod) {
387393
protoMethod,
388394
extractorVarType,
389395
protoMethod.httpBindings().queryParameters(),
390-
"putQueryParam")))
396+
"putQueryParam",
397+
restNumericEnumsEnabled)))
391398
.apply(expr);
392399

393400
extractorVarType = TypeNode.STRING;
@@ -404,7 +411,8 @@ private List<Expr> getRequestFormatterExpr(Method protoMethod) {
404411
? protoMethod.httpBindings().pathParameters()
405412
: protoMethod.httpBindings().bodyParameters(),
406413
"toBody",
407-
asteriskBody)))
414+
asteriskBody,
415+
restNumericEnumsEnabled)))
408416
.apply(expr);
409417
expr = methodMaker.apply("build", Collections.emptyList()).apply(expr);
410418

@@ -771,7 +779,8 @@ private Expr createBodyFieldsExtractorClassInstance(
771779
TypeNode extractorReturnType,
772780
Set<HttpBinding> httpBindingFieldNames,
773781
String serializerMethodName,
774-
boolean asteriskBody) {
782+
boolean asteriskBody,
783+
boolean restNumericEnumEnabled) {
775784
List<Statement> bodyStatements = new ArrayList<>();
776785

777786
Expr returnExpr = null;
@@ -844,6 +853,13 @@ private Expr createBodyFieldsExtractorClassInstance(
844853
paramsPutArgs.add(ValueExpr.withValue(StringObjectValue.withValue(bodyParamName)));
845854
paramsPutArgs.add(prevExpr);
846855

856+
PrimitiveValue primitiveValue =
857+
PrimitiveValue.builder()
858+
.setType(TypeNode.BOOLEAN)
859+
.setValue(String.valueOf(restNumericEnumEnabled))
860+
.build();
861+
paramsPutArgs.add(ValueExpr.withValue(primitiveValue));
862+
847863
returnExpr =
848864
MethodInvocationExpr.builder()
849865
.setExprReferenceExpr(serializerExpr)
@@ -866,7 +882,8 @@ private Expr createFieldsExtractorClassInstance(
866882
Method method,
867883
TypeNode extractorReturnType,
868884
Set<HttpBinding> httpBindingFieldNames,
869-
String serializerMethodName) {
885+
String serializerMethodName,
886+
boolean restNumericEnumsEnabled) {
870887
List<Statement> bodyStatements = new ArrayList<>();
871888

872889
VariableExpr fieldsVarExpr =
@@ -980,6 +997,23 @@ private Expr createFieldsExtractorClassInstance(
980997
}
981998
}
982999

1000+
if (restNumericEnumsEnabled && serializerMethodName.equals("putQueryParam")) {
1001+
ImmutableList.Builder<Expr> paramsPutArgs = ImmutableList.builder();
1002+
1003+
paramsPutArgs.add(fieldsVarExpr);
1004+
paramsPutArgs.add(ValueExpr.withValue(StringObjectValue.withValue("$alt")));
1005+
paramsPutArgs.add(ValueExpr.withValue(StringObjectValue.withValue("json;enum-encoding=int")));
1006+
1007+
Expr paramsPutExpr =
1008+
MethodInvocationExpr.builder()
1009+
.setExprReferenceExpr(serializerVarExpr)
1010+
.setMethodName(serializerMethodName)
1011+
.setArguments(paramsPutArgs.build())
1012+
.setReturnType(extractorReturnType)
1013+
.build();
1014+
bodyStatements.add(ExprStatement.withExpr(paramsPutExpr));
1015+
}
1016+
9831017
// Overrides FieldsExtractor
9841018
// (https://github.com/googleapis/gax-java/blob/12b18ee255d3fabe13bb3969df40753b29f830d5/gax-httpjson/src/main/java/com/google/api/gax/httpjson/FieldsExtractor.java).
9851019
return LambdaExpr.builder()

src/main/java/com/google/api/generator/gapic/model/GapicContext.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public abstract class GapicContext {
4747

4848
public abstract boolean gapicMetadataEnabled();
4949

50+
public abstract boolean restNumericEnumsEnabled();
51+
5052
public GapicMetadata gapicMetadata() {
5153
return gapicMetadata;
5254
}
@@ -81,7 +83,8 @@ static GapicMetadata defaultGapicMetadata() {
8183
public static Builder builder() {
8284
return new AutoValue_GapicContext.Builder()
8385
.setMixinServices(Collections.emptyList())
84-
.setGapicMetadataEnabled(false);
86+
.setGapicMetadataEnabled(false)
87+
.setRestNumericEnumsEnabled(false);
8588
}
8689

8790
@AutoValue.Builder
@@ -108,6 +111,8 @@ public Builder setHelperResourceNames(Set<ResourceName> helperResourceNames) {
108111

109112
public abstract Builder setGapicMetadataEnabled(boolean gapicMetadataEnabled);
110113

114+
public abstract Builder setRestNumericEnumsEnabled(boolean restNumericEnumsEnabled);
115+
111116
public abstract Builder setTransport(Transport transport);
112117

113118
abstract ImmutableMap<String, ResourceName> resourceNames();

src/main/java/com/google/api/generator/gapic/protoparser/Parser.java

+2
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public static GapicContext parse(CodeGeneratorRequest request) {
120120
Optional<String> transportOpt = PluginArgumentParser.parseTransport(request);
121121

122122
boolean willGenerateMetadata = PluginArgumentParser.hasMetadataFlag(request);
123+
boolean willGenerateNumericEnum = PluginArgumentParser.hasNumericEnumFlag(request);
123124

124125
Optional<String> serviceConfigPathOpt = PluginArgumentParser.parseJsonConfigPath(request);
125126
Optional<GapicServiceConfig> serviceConfigOpt =
@@ -216,6 +217,7 @@ public static GapicContext parse(CodeGeneratorRequest request) {
216217
.setGapicMetadataEnabled(willGenerateMetadata)
217218
.setServiceYamlProto(serviceYamlProtoOpt.orElse(null))
218219
.setTransport(transport)
220+
.setRestNumericEnumsEnabled(willGenerateNumericEnum)
219221
.build();
220222
}
221223

src/main/java/com/google/api/generator/gapic/protoparser/PluginArgumentParser.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class PluginArgumentParser {
2929
@VisibleForTesting static final String KEY_GRPC_SERVICE_CONFIG = "grpc-service-config";
3030
@VisibleForTesting static final String KEY_GAPIC_CONFIG = "gapic-config";
3131
@VisibleForTesting static final String KEY_METADATA = "metadata";
32+
@VisibleForTesting static final String KEY_NUMERIC_ENUM = "rest-numeric-enums";
3233
@VisibleForTesting static final String KEY_SERVICE_YAML_CONFIG = "api-service-config";
3334
@VisibleForTesting static final String KEY_TRANSPORT = "transport";
3435

@@ -53,7 +54,11 @@ static Optional<String> parseTransport(CodeGeneratorRequest request) {
5354
}
5455

5556
static boolean hasMetadataFlag(CodeGeneratorRequest request) {
56-
return hasMetadataFlag(request.getParameter());
57+
return hasFlag(request.getParameter(), KEY_METADATA);
58+
}
59+
60+
static boolean hasNumericEnumFlag(CodeGeneratorRequest request) {
61+
return hasFlag(request.getParameter(), KEY_NUMERIC_ENUM);
5762
}
5863

5964
/** Expects a comma-separated list of file paths. */
@@ -89,8 +94,8 @@ private static Optional<String> parseConfigArgument(String pluginProtocArgument,
8994
}
9095

9196
@VisibleForTesting
92-
static boolean hasMetadataFlag(String pluginProtocArgument) {
93-
return Arrays.stream(pluginProtocArgument.split(COMMA)).anyMatch(s -> s.equals(KEY_METADATA));
97+
static boolean hasFlag(String pluginProtocArgument, String flagKey) {
98+
return Arrays.stream(pluginProtocArgument.split(COMMA)).anyMatch(s -> s.equals(flagKey));
9499
}
95100

96101
private static Optional<String> parseFileArgument(

0 commit comments

Comments
 (0)