From 445daf472b337520f108b485abfdbe8b20b16b01 Mon Sep 17 00:00:00 2001 From: Vadym Matsishevskyi <25311427+vam-google@users.noreply.github.com> Date: Mon, 6 Sep 2021 15:32:06 -0700 Subject: [PATCH] feat: REGAPIC Multitransport implementation (grpc+rest) (#833) 1) Fully backward compatible with grpc-only GAPIC 2) Strictly speaking not fully backward compatible with rest-only REGAPIC (but is compatible for practical cases). See below for details. 3) Introduces the concept of default transport (is necessary to preserve backward-compabitility). The default behavior assumes grpc transport. Needed to unblock DIREGAPIC LRO. To be reviewed after submission --- rules_java_gapic/java_gapic.bzl | 30 +- rules_java_gapic/java_gapic_pkg.bzl | 8 +- .../gradle/client_grpcrest.gradle.tmpl | 63 ++++ .../google/api/generator/gapic/BUILD.bazel | 1 + .../api/generator/gapic/composer/BUILD.bazel | 1 + .../generator/gapic/composer/Composer.java | 79 +++-- ...ctServiceCallableFactoryClassComposer.java | 2 +- .../AbstractServiceClientClassComposer.java | 122 ++++---- ...bstractServiceClientTestClassComposer.java | 12 +- .../AbstractServiceSettingsClassComposer.java | 76 +++-- .../AbstractServiceStubClassComposer.java | 86 +++--- ...tractServiceStubSettingsClassComposer.java | 278 ++++++++++++++---- ...ractTransportServiceStubClassComposer.java | 21 +- .../composer/common/TransportContext.java | 59 ++-- .../gapic/composer/grpc/GrpcContext.java | 25 +- .../grpc/ServiceClientTestClassComposer.java | 3 +- .../ServiceStubSettingsClassComposer.java | 117 ++------ .../gapic/composer/grpcrest/BUILD.bazel | 55 ++++ .../composer/grpcrest/GrpcRestContext.java | 95 ++++++ ...ttpJsonServiceClientTestClassComposer.java | 57 ++++ .../HttpJsonServiceStubClassComposer.java | 40 +++ .../grpcrest/ServiceClientClassComposer.java | 29 ++ .../ServiceSettingsClassComposer.java | 68 +++++ .../grpcrest/ServiceStubClassComposer.java | 47 +++ .../ServiceStubSettingsClassComposer.java | 200 +++++++++++++ ...onServiceCallableFactoryClassComposer.java | 2 +- .../gapic/composer/rest/RestContext.java | 26 +- .../rest/ServiceClientTestClassComposer.java | 7 +- .../ServiceStubSettingsClassComposer.java | 107 +------ .../gapic/composer/utils/ClassNames.java | 53 +++- .../api/generator/gapic/model/Transport.java | 2 - .../google/api/generator/gapic/BUILD.bazel | 1 + 32 files changed, 1308 insertions(+), 464 deletions(-) create mode 100644 rules_java_gapic/resources/gradle/client_grpcrest.gradle.tmpl create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpcrest/BUILD.bazel create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpcrest/GrpcRestContext.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceClientTestClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceStubClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceClientClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceSettingsClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubSettingsClassComposer.java diff --git a/rules_java_gapic/java_gapic.bzl b/rules_java_gapic/java_gapic.bzl index 65cb3617f7..91eb4ddb56 100644 --- a/rules_java_gapic/java_gapic.bzl +++ b/rules_java_gapic/java_gapic.bzl @@ -135,7 +135,7 @@ def _java_gapic_srcjar( if grpc_service_config: file_args_dict[grpc_service_config] = "grpc-service-config" - elif transport != "rest": + elif not transport or transport == "grpc": for keyword in NO_GRPC_CONFIG_ALLOWLIST: if keyword not in name: fail("Missing a gRPC service config file") @@ -230,16 +230,25 @@ def java_gapic_library( "@javax_annotation_javax_annotation_api//jar", ] - if transport == "rest": + if not transport or transport == "grpc": + actual_deps += [ + "@com_google_api_gax_java//gax-grpc:gax_grpc", + "@io_grpc_grpc_java//core:core", + "@io_grpc_grpc_java//protobuf:protobuf", + ] + elif transport == "rest": actual_deps += [ "@com_google_api_gax_java//gax-httpjson:gax_httpjson", ] - else: + elif transport == "grpc+rest": actual_deps += [ "@com_google_api_gax_java//gax-grpc:gax_grpc", "@io_grpc_grpc_java//core:core", "@io_grpc_grpc_java//protobuf:protobuf", + "@com_google_api_gax_java//gax-httpjson:gax_httpjson", ] + else: + fail("Unknown transport: %s" % transport) native.java_library( name = name, @@ -256,18 +265,29 @@ def java_gapic_library( "@junit_junit//jar", ] - if transport == "rest": + if not transport or transport == "grpc": + actual_test_deps += [ + "@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", + "@io_grpc_grpc_java//auth:auth", + "@io_grpc_grpc_netty_shaded//jar", + "@io_grpc_grpc_java//stub:stub", + "@io_opencensus_opencensus_contrib_grpc_metrics//jar", + ] + elif transport == "rest": actual_test_deps += [ "@com_google_api_gax_java//gax-httpjson:gax_httpjson_testlib", ] - else: + elif transport == "grpc+rest": actual_test_deps += [ "@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", "@io_grpc_grpc_java//auth:auth", "@io_grpc_grpc_netty_shaded//jar", "@io_grpc_grpc_java//stub:stub", "@io_opencensus_opencensus_contrib_grpc_metrics//jar", + "@com_google_api_gax_java//gax-httpjson:gax_httpjson_testlib", ] + else: + fail("Unknown transport: %s" % transport) _append_dep_without_duplicates(actual_test_deps, test_deps) _append_dep_without_duplicates(actual_test_deps, actual_deps) diff --git a/rules_java_gapic/java_gapic_pkg.bzl b/rules_java_gapic/java_gapic_pkg.bzl index a6bca826d2..0f2d805045 100644 --- a/rules_java_gapic/java_gapic_pkg.bzl +++ b/rules_java_gapic/java_gapic_pkg.bzl @@ -351,10 +351,12 @@ def java_gapic_assembly_gradle_pkg( grpc_target_dep = ["%s" % grpc_target] if client_deps: - if transport == "rest": - template_label = Label("//rules_java_gapic:resources/gradle/client_rest.gradle.tmpl") - else: + if not transport or transport == "rest": template_label = Label("//rules_java_gapic:resources/gradle/client_grpc.gradle.tmpl") + elif transport == "rest": + template_label = Label("//rules_java_gapic:resources/gradle/client_rest.gradle.tmpl") + elif transport == "grpc+rest": + template_label = Label("//rules_java_gapic:resources/gradle/client_grpcrest.gradle.tmpl") _java_gapic_gradle_pkg( name = client_target, diff --git a/rules_java_gapic/resources/gradle/client_grpcrest.gradle.tmpl b/rules_java_gapic/resources/gradle/client_grpcrest.gradle.tmpl new file mode 100644 index 0000000000..fe5aa44622 --- /dev/null +++ b/rules_java_gapic/resources/gradle/client_grpcrest.gradle.tmpl @@ -0,0 +1,63 @@ +buildscript { + repositories { + mavenCentral() + } +} + +apply plugin: 'java' + +description = 'GAPIC library for {{name}}' +group = 'com.google.cloud' +version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +repositories { + mavenCentral() + mavenLocal() +} + +compileJava.options.encoding = 'UTF-8' +javadoc.options.encoding = 'UTF-8' + +dependencies { + compile 'com.google.api:gax:{{version.gax}}' + testCompile 'com.google.api:gax:{{version.gax}}:testlib' + compile 'com.google.api:gax-grpc:{{version.gax_grpc}}' + testCompile 'com.google.api:gax-grpc:{{version.gax_grpc}}:testlib' + compile 'com.google.api:gax-httpjson:{{version.gax_httpjson}}' + testCompile 'com.google.api:gax-httpjson:{{version.gax_httpjson}}:testlib' + testCompile 'io.grpc:grpc-netty-shaded:{{version.io_grpc}}' + testCompile '{{maven.junit_junit}}' + {{extra_deps}} +} + +task smokeTest(type: Test) { + filter { + includeTestsMatching "*SmokeTest" + setFailOnNoMatchingTests false + } +} + +test { + exclude "**/*SmokeTest*" +} + +sourceSets { + main { + java { + srcDir 'src/main/java' + } + } +} + +clean { + delete 'all-jars' +} + +task allJars(type: Copy) { + dependsOn test, jar + into 'all-jars' + // Replace with `from configurations.testRuntime, jar` to include test dependencies + from configurations.runtime, jar +} diff --git a/src/main/java/com/google/api/generator/gapic/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/BUILD.bazel index 9f6eb8954e..60cbc46d03 100644 --- a/src/main/java/com/google/api/generator/gapic/BUILD.bazel +++ b/src/main/java/com/google/api/generator/gapic/BUILD.bazel @@ -9,6 +9,7 @@ filegroup( "//src/main/java/com/google/api/generator/gapic/composer/comment:comment_files", "//src/main/java/com/google/api/generator/gapic/composer/defaultvalue:defaultvalue_files", "//src/main/java/com/google/api/generator/gapic/composer/grpc:grpc_files", + "//src/main/java/com/google/api/generator/gapic/composer/grpcrest:grpcrest_files", "//src/main/java/com/google/api/generator/gapic/composer/resourcename:resourcename_files", "//src/main/java/com/google/api/generator/gapic/composer/rest:rest_files", "//src/main/java/com/google/api/generator/gapic/composer/samplecode:samplecode_files", diff --git a/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel index 3cfcae2c62..0f09405d04 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel +++ b/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel @@ -21,6 +21,7 @@ java_library( "//src/main/java/com/google/api/generator/gapic/composer/common", "//src/main/java/com/google/api/generator/gapic/composer/defaultvalue", "//src/main/java/com/google/api/generator/gapic/composer/grpc", + "//src/main/java/com/google/api/generator/gapic/composer/grpcrest", "//src/main/java/com/google/api/generator/gapic/composer/resourcename", "//src/main/java/com/google/api/generator/gapic/composer/rest", "//src/main/java/com/google/api/generator/gapic/composer/samplecode", diff --git a/src/main/java/com/google/api/generator/gapic/composer/Composer.java b/src/main/java/com/google/api/generator/gapic/composer/Composer.java index cee4b2bccc..4eefc2845a 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/Composer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/Composer.java @@ -15,7 +15,6 @@ package com.google.api.generator.gapic.composer; import com.google.api.generator.engine.ast.ClassDefinition; -import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.gapic.composer.comment.CommentComposer; import com.google.api.generator.gapic.composer.grpc.GrpcServiceCallableFactoryClassComposer; import com.google.api.generator.gapic.composer.grpc.GrpcServiceStubClassComposer; @@ -26,11 +25,11 @@ import com.google.api.generator.gapic.composer.grpc.ServiceSettingsClassComposer; import com.google.api.generator.gapic.composer.grpc.ServiceStubClassComposer; import com.google.api.generator.gapic.composer.grpc.ServiceStubSettingsClassComposer; +import com.google.api.generator.gapic.composer.grpcrest.HttpJsonServiceClientTestClassComposer; import com.google.api.generator.gapic.composer.resourcename.ResourceNameHelperClassComposer; import com.google.api.generator.gapic.composer.rest.HttpJsonServiceCallableFactoryClassComposer; import com.google.api.generator.gapic.composer.rest.HttpJsonServiceStubClassComposer; import com.google.api.generator.gapic.model.GapicClass; -import com.google.api.generator.gapic.model.GapicClass.Kind; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.GapicPackageInfo; import com.google.api.generator.gapic.model.Service; @@ -87,12 +86,30 @@ public static List generateStubClasses(GapicContext context) { clazzes.add( HttpJsonServiceCallableFactoryClassComposer.instance().generate(context, s)); clazzes.add(HttpJsonServiceStubClassComposer.instance().generate(context, s)); - } else { + } else if (context.transport() == Transport.GRPC) { clazzes.add(ServiceStubClassComposer.instance().generate(context, s)); clazzes.add(ServiceStubSettingsClassComposer.instance().generate(context, s)); clazzes.add( GrpcServiceCallableFactoryClassComposer.instance().generate(context, s)); clazzes.add(GrpcServiceStubClassComposer.instance().generate(context, s)); + } else if (context.transport() == Transport.GRPC_REST) { + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest.ServiceStubClassComposer + .instance() + .generate(context, s)); + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest + .ServiceStubSettingsClassComposer.instance() + .generate(context, s)); + clazzes.add( + GrpcServiceCallableFactoryClassComposer.instance().generate(context, s)); + clazzes.add(GrpcServiceStubClassComposer.instance().generate(context, s)); + clazzes.add( + HttpJsonServiceCallableFactoryClassComposer.instance().generate(context, s)); + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest + .HttpJsonServiceStubClassComposer.instance() + .generate(context, s)); } }); return clazzes; @@ -113,9 +130,18 @@ public static List generateClientSettingsClasses(GapicContext contex com.google.api.generator.gapic.composer.rest.ServiceSettingsClassComposer .instance() .generate(context, s)); - } else { + } else if (context.transport() == Transport.GRPC) { clazzes.add(ServiceClientClassComposer.instance().generate(context, s)); clazzes.add(ServiceSettingsClassComposer.instance().generate(context, s)); + } else if (context.transport() == Transport.GRPC_REST) { + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest.ServiceClientClassComposer + .instance() + .generate(context, s)); + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest.ServiceSettingsClassComposer + .instance() + .generate(context, s)); } }); return clazzes; @@ -127,7 +153,10 @@ public static List generateMockClasses(GapicContext context, List { if (context.transport() == Transport.REST) { // REST transport tests donot not use mock services. - } else { + } else if (context.transport() == Transport.GRPC) { + clazzes.add(MockServiceClassComposer.instance().generate(context, s)); + clazzes.add(MockServiceImplClassComposer.instance().generate(context, s)); + } else if (context.transport() == Transport.GRPC_REST) { clazzes.add(MockServiceClassComposer.instance().generate(context, s)); clazzes.add(MockServiceImplClassComposer.instance().generate(context, s)); } @@ -136,35 +165,25 @@ public static List generateMockClasses(GapicContext context, List generateTestClasses(GapicContext context) { - return context.services().stream() - .map( + List clazzes = new ArrayList<>(); + context + .services() + .forEach( s -> { if (context.transport() == Transport.REST) { - return com.google.api.generator.gapic.composer.rest.ServiceClientTestClassComposer - .instance() - .generate(context, s); - } else { - return ServiceClientTestClassComposer.instance().generate(context, s); + clazzes.add( + com.google.api.generator.gapic.composer.rest.ServiceClientTestClassComposer + .instance() + .generate(context, s)); + } else if (context.transport() == Transport.GRPC) { + clazzes.add(ServiceClientTestClassComposer.instance().generate(context, s)); + } else if (context.transport() == Transport.GRPC_REST) { + clazzes.add(ServiceClientTestClassComposer.instance().generate(context, s)); + clazzes.add(HttpJsonServiceClientTestClassComposer.instance().generate(context, s)); } - }) - .collect(Collectors.toList()); - } - - /** ====================== HELPERS ==================== */ - // TODO(miraleung): Add method list. - private static GapicClass generateGenericClass(Kind kind, String name, Service service) { - String pakkage = service.pakkage(); - if (kind.equals(Kind.STUB)) { - pakkage += ".stub"; - } + }); - ClassDefinition classDef = - ClassDefinition.builder() - .setPackageString(pakkage) - .setName(name) - .setScope(ScopeNode.PUBLIC) - .build(); - return GapicClass.create(kind, classDef); + return clazzes; } @VisibleForTesting diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java index b3f4c7ee74..4342a4aa80 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java @@ -257,7 +257,7 @@ protected MethodDefinition createGenericCallableMethod( .setVariable( Variable.builder() .setName("operationsStub") - .setType(getTransportContext().operationsStubType()) + .setType(getTransportContext().operationsStubTypes().get(0)) .build()) .setIsDecl(true) .build()); diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java index 18b9eeca81..e680530d5f 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java @@ -85,11 +85,14 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Function; @@ -132,7 +135,7 @@ public GapicClass generate(GapicContext context, Service service) { String className = ClassNames.getServiceClientClassName(service); GapicClass.Kind kind = Kind.MAIN; String pakkage = service.pakkage(); - boolean hasLroClient = hasLroMethods(service); + boolean hasLroClient = service.hasLroMethods(); Map> grpcRpcsToJavaMethodNames = new HashMap<>(); @@ -219,15 +222,6 @@ private List createClassMethods( return methods; } - private static boolean hasLroMethods(Service service) { - for (Method method : service.methods()) { - if (method.hasLro()) { - return true; - } - } - return false; - } - private List createFieldDeclarations( Service service, TypeStore typeStore, boolean hasLroClient) { Map fieldNameToTypes = new HashMap<>(); @@ -235,9 +229,12 @@ private List createFieldDeclarations( "settings", typeStore.get(ClassNames.getServiceSettingsClassName(service))); fieldNameToTypes.put("stub", typeStore.get(ClassNames.getServiceStubClassName(service))); if (hasLroClient) { - fieldNameToTypes.put( - getTransportContext().operationsClientName(), - getTransportContext().operationsClientType()); + Iterator opClientName = getTransportContext().operationsClientNames().iterator(); + Iterator opClientType = getTransportContext().operationsClientTypes().iterator(); + + while (opClientName.hasNext() && opClientType.hasNext()) { + fieldNameToTypes.put(opClientName.next(), opClientType.next()); + } } return fieldNameToTypes.entrySet().stream() @@ -364,7 +361,6 @@ private List createConstructorMethods( String settingsName = ClassNames.getServiceSettingsClassName(service); TypeNode thisClassType = typeStore.get(thisClientName); TypeNode stubSettingsType = typeStore.get(ClassNames.getServiceStubSettingsClassName(service)); - TypeNode operationsClientType = getTransportContext().operationsClientType(); TypeNode exceptionType = typeStore.get("IOException"); TypeNode settingsType = typeStore.get(settingsName); @@ -377,12 +373,6 @@ private List createConstructorMethods( .setType(typeStore.get(ClassNames.getServiceStubClassName(service))) .setName("stub") .build()); - VariableExpr operationsClientVarExpr = - VariableExpr.withVariable( - Variable.builder() - .setType(operationsClientType) - .setName(getTransportContext().operationsClientName()) - .build()); // Create the ServiceClient(ServiceSettings settings) ctor. List ctorAssignmentExprs = new ArrayList<>(); @@ -412,30 +402,10 @@ private List createConstructorMethods( .build()) .build()); - String operationsStubGetterName = - String.format( - "get%s", - JavaStyle.toUpperCamelCase(getTransportContext().transportOperationsStubName())); - - Expr clientArgExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(stubVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setMethodName(operationsStubGetterName) - .build(); - AssignmentExpr operationsClientAssignExpr = - AssignmentExpr.builder() - .setVariableExpr( - operationsClientVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType(operationsClientType) - .setMethodName("create") - .setArguments(clientArgExpr) - .setReturnType(operationsClientVarExpr.type()) - .build()) - .build(); + List operationsClientAssignExprs = + createOperationsClientAssignExprs(thisExpr, stubVarExpr); if (hasLroClient) { - ctorAssignmentExprs.add(operationsClientAssignExpr); + ctorAssignmentExprs.addAll(operationsClientAssignExprs); } methods.add( @@ -466,7 +436,7 @@ private List createConstructorMethods( .setValueExpr(stubVarExpr) .build()); if (hasLroClient) { - ctorAssignmentExprs.add(operationsClientAssignExpr); + ctorAssignmentExprs.addAll(operationsClientAssignExprs); } AnnotationNode betaAnnotation = AnnotationNode.builder() @@ -489,19 +459,69 @@ private List createConstructorMethods( return methods; } + private List createOperationsClientAssignExprs( + Expr thisExpr, VariableExpr stubVarExpr) { + List operationsClientAssignExprs = new ArrayList<>(); + + Iterator opClientTypesIt = getTransportContext().operationsClientTypes().iterator(); + Iterator opClientNamesIt = getTransportContext().operationsClientNames().iterator(); + Iterator opStubNamesIt = + getTransportContext().transportOperationsStubNames().iterator(); + + while (opClientTypesIt.hasNext() && opClientNamesIt.hasNext() && opStubNamesIt.hasNext()) { + TypeNode operationsClientType = opClientTypesIt.next(); + String opClientName = opClientNamesIt.next(); + String opStubName = opStubNamesIt.next(); + + VariableExpr operationsClientVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(operationsClientType).setName(opClientName).build()); + + String operationsStubGetterName = + String.format("get%s", JavaStyle.toUpperCamelCase(opStubName)); + + Expr clientArgExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(stubVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setMethodName(operationsStubGetterName) + .build(); + + AssignmentExpr operationsClientAssignExpr = + AssignmentExpr.builder() + .setVariableExpr( + operationsClientVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType(operationsClientType) + .setMethodName("create") + .setArguments(clientArgExpr) + .setReturnType(operationsClientVarExpr.type()) + .build()) + .build(); + operationsClientAssignExprs.add(operationsClientAssignExpr); + } + + return operationsClientAssignExprs; + } + private List createGetterMethods( Service service, TypeStore typeStore, boolean hasLroClient) { Map methodNameToTypes = new LinkedHashMap<>(); methodNameToTypes.put( "getSettings", typeStore.get(ClassNames.getServiceSettingsClassName(service))); methodNameToTypes.put("getStub", typeStore.get(ClassNames.getServiceStubClassName(service))); - String getOperationsClientMethodName = - String.format( - "get%s", - JavaStyle.toUpperCamelCase(getTransportContext().operationsClientName())); + + Set getOperationsClientMethodNames = new HashSet<>(); + if (hasLroClient) { - methodNameToTypes.put( - getOperationsClientMethodName, getTransportContext().operationsClientType()); + Iterator opClientNamesIt = getTransportContext().operationsClientNames().iterator(); + Iterator opClientTypesIt = getTransportContext().operationsClientTypes().iterator(); + + while (opClientNamesIt.hasNext() && opClientTypesIt.hasNext()) { + String opClientMethodName = String.format("get%s", JavaStyle.toUpperCamelCase(opClientNamesIt.next())); + getOperationsClientMethodNames.add(opClientMethodName); + methodNameToTypes.put(opClientMethodName, opClientTypesIt.next()); + } } AnnotationNode betaStubAnnotation = AnnotationNode.builder() @@ -517,7 +537,7 @@ private List createGetterMethods( TypeNode methodReturnType = e.getValue(); String returnVariableName = JavaStyle.toLowerCamelCase(methodName.substring(3)); MethodDefinition.Builder methodBuilder = MethodDefinition.builder(); - if (methodName.equals(getOperationsClientMethodName)) { + if (getOperationsClientMethodNames.contains(methodName)) { methodBuilder = methodBuilder.setHeaderCommentStatements( ServiceClientCommentComposer.GET_OPERATIONS_CLIENT_METHOD_COMMENT); diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java index b677c66a24..364dd183b3 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java @@ -109,12 +109,14 @@ public TransportContext getTransportContext() { @Override public GapicClass generate(GapicContext context, Service service) { + return generate(ClassNames.getServiceClientTestClassName(service), context, service); + } + + protected GapicClass generate(String className, GapicContext context, Service service) { Map resourceNames = context.helperResourceNames(); - Map messageTypes = context.messages(); String pakkage = service.pakkage(); TypeStore typeStore = new TypeStore(); addDynamicTypes(context, service, typeStore); - String className = ClassNames.getServiceClientTestClassName(service); GapicClass.Kind kind = Kind.MAIN; Map classMemberVarExprs = @@ -196,7 +198,8 @@ private List createTestAdminMethods( TypeStore typeStore) { List javaMethods = new ArrayList<>(); javaMethods.add( - createStartStaticServerMethod(service, context, classMemberVarExprs, typeStore)); + createStartStaticServerMethod( + service, context, classMemberVarExprs, typeStore, "newBuilder")); javaMethods.add(createStopServerMethod(service, classMemberVarExprs)); javaMethods.add(createSetUpMethod(service, classMemberVarExprs, typeStore)); javaMethods.add(createTearDownMethod(service, classMemberVarExprs)); @@ -207,7 +210,8 @@ protected abstract MethodDefinition createStartStaticServerMethod( Service service, GapicContext context, Map classMemberVarExprs, - TypeStore typeStore); + TypeStore typeStore, + String newBuilderMethod); protected abstract MethodDefinition createStopServerMethod( Service service, Map classMemberVarExprs); diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java index e59e689bb2..cd4f89cbb9 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java @@ -62,11 +62,13 @@ import com.google.api.generator.gapic.model.Service; import com.google.api.generator.gapic.utils.JavaStyle; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.google.longrunning.Operation; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.function.BiFunction; @@ -172,6 +174,7 @@ private List createClassMethods(Service service, TypeStore typ javaMethods.addAll(createSettingsGetterMethods(service, typeStore)); javaMethods.add(createCreatorMethod(service, typeStore)); javaMethods.addAll(createDefaultGetterMethods(service, typeStore)); + javaMethods.addAll(createNewBuilderMethods(service, typeStore, "newBuilder", "createDefault")); javaMethods.addAll(createBuilderHelperMethods(service, typeStore)); javaMethods.add(createConstructorMethod(service, typeStore)); return javaMethods; @@ -351,12 +354,19 @@ private List createDefaultGetterMethods(Service service, TypeS "defaultCredentialsProviderBuilder", typeMakerFn.apply(GoogleCredentialsProvider.Builder.class)), SettingsCommentComposer.DEFAULT_CREDENTIALS_PROVIDER_BUILDER_METHOD_COMMENT)); - javaMethods.add( - methodMakerFn.apply( - methodStarterFn.apply( - getTransportContext().defaultTransportProviderBuilderName(), - typeMakerFn.apply(getTransportContext().instantiatingChannelProviderClass())), - SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT)); + + Iterator providerBuilderNamesIt = + getTransportContext().defaultTransportProviderBuilderNames().iterator(); + Iterator> channelProviderClassesIt = + getTransportContext().instantiatingChannelProviderBuilderClasses().iterator(); + while (providerBuilderNamesIt.hasNext() && channelProviderClassesIt.hasNext()) { + javaMethods.add( + methodMakerFn.apply( + methodStarterFn.apply( + providerBuilderNamesIt.next(), + typeMakerFn.apply(channelProviderClassesIt.next())), + SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT)); + } javaMethods.add( methodStarterFn @@ -383,23 +393,31 @@ private List createDefaultGetterMethods(Service service, TypeS return javaMethods; } - private static List createBuilderHelperMethods( - Service service, TypeStore typeStore) { + protected List createNewBuilderMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { TypeNode builderType = typeStore.get(BUILDER_CLASS_NAME); - MethodDefinition newBuilderMethodOne = + return ImmutableList.of( MethodDefinition.builder() .setHeaderCommentStatements(SettingsCommentComposer.NEW_BUILDER_METHOD_COMMENT) .setScope(ScopeNode.PUBLIC) .setIsStatic(true) .setReturnType(builderType) - .setName("newBuilder") + .setName(newBuilderMethodName) .setReturnExpr( MethodInvocationExpr.builder() .setStaticReferenceType(builderType) - .setMethodName("createDefault") + .setMethodName(createDefaultMethodName) .setReturnType(builderType) .build()) - .build(); + .build()); + } + + private static List createBuilderHelperMethods( + Service service, TypeStore typeStore) { + TypeNode builderType = typeStore.get(BUILDER_CLASS_NAME); VariableExpr clientContextVarExpr = VariableExpr.withVariable( @@ -439,10 +457,10 @@ private static List createBuilderHelperMethods( .build()) .build(); - return Arrays.asList(newBuilderMethodOne, newBuilderMethodTwo, toBuilderMethod); + return Arrays.asList(newBuilderMethodTwo, toBuilderMethod); } - private static ClassDefinition createNestedBuilderClass(Service service, TypeStore typeStore) { + private ClassDefinition createNestedBuilderClass(Service service, TypeStore typeStore) { return ClassDefinition.builder() .setHeaderCommentStatements( SettingsCommentComposer.createBuilderClassComment( @@ -466,11 +484,12 @@ private static ClassDefinition createNestedBuilderClass(Service service, TypeSto .build(); } - private static List createNestedBuilderClassMethods( + private List createNestedBuilderClassMethods( Service service, TypeStore typeStore) { List javaMethods = new ArrayList<>(); javaMethods.addAll(createNestedBuilderConstructorMethods(service, typeStore)); - javaMethods.add(createNestedBuilderCreatorMethod(service, typeStore)); + javaMethods.addAll( + createNestedBuilderCreatorMethods(service, typeStore, "newBuilder", "createDefault")); javaMethods.add(createNestedBuilderStubSettingsBuilderMethod(service, typeStore)); javaMethods.add(createNestedBuilderApplyToAllUnaryMethod(service, typeStore)); javaMethods.addAll(createNestedBuilderSettingsGetterMethods(service, typeStore)); @@ -557,23 +576,28 @@ private static List createNestedBuilderConstructorMethods( return Arrays.asList(noArgCtor, clientContextCtor, settingsCtor, stubSettingsCtor); } - private static MethodDefinition createNestedBuilderCreatorMethod( - Service service, TypeStore typeStore) { + protected List createNestedBuilderCreatorMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { MethodInvocationExpr ctorArg = MethodInvocationExpr.builder() .setStaticReferenceType( typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) - .setMethodName("newBuilder") + .setMethodName(newBuilderMethodName) .build(); TypeNode builderType = typeStore.get(BUILDER_CLASS_NAME); - return MethodDefinition.builder() - .setScope(ScopeNode.PRIVATE) - .setIsStatic(true) - .setReturnType(builderType) - .setName("createDefault") - .setReturnExpr(NewObjectExpr.builder().setType(builderType).setArguments(ctorArg).build()) - .build(); + return ImmutableList.of( + MethodDefinition.builder() + .setScope(ScopeNode.PRIVATE) + .setIsStatic(true) + .setReturnType(builderType) + .setName(createDefaultMethodName) + .setReturnExpr( + NewObjectExpr.builder().setType(builderType).setArguments(ctorArg).build()) + .build()); } private static MethodDefinition createNestedBuilderStubSettingsBuilderMethod( diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java index 1b26732cff..38a8dd89a3 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java @@ -27,7 +27,6 @@ import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.ScopeNode; -import com.google.api.generator.engine.ast.Statement; import com.google.api.generator.engine.ast.ThrowExpr; import com.google.api.generator.engine.ast.TypeNode; import com.google.api.generator.gapic.composer.comment.StubCommentComposer; @@ -45,6 +44,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -115,14 +115,14 @@ private List createClassMethods( boolean hasLroClient = service.hasLroMethods(); List methods = new ArrayList<>(); if (hasLroClient) { - methods.add(createOperationsStubGetter(typeStore)); + methods.addAll(createOperationsStubGetters(typeStore)); } methods.addAll(createCallableGetters(service, messageTypes, typeStore)); methods.addAll(createBackgroundResourceMethodOverrides()); return methods; } - private static List createCallableGetters( + private List createCallableGetters( Service service, Map messageTypes, TypeStore typeStore) { // Use a traditional for-loop since the output cardinality is not necessarily 1:1 with that of // service.methods(). @@ -139,20 +139,19 @@ private static List createCallableGetters( return javaMethods; } - private static MethodDefinition createOperationCallableGetter( - Method method, TypeStore typeStore) { + private MethodDefinition createOperationCallableGetter(Method method, TypeStore typeStore) { return createCallableGetterHelper(method, typeStore, true, false); } - private static MethodDefinition createPagedCallableGetter(Method method, TypeStore typeStore) { + private MethodDefinition createPagedCallableGetter(Method method, TypeStore typeStore) { return createCallableGetterHelper(method, typeStore, false, true); } - private static MethodDefinition createCallableGetter(Method method, TypeStore typeStore) { + private MethodDefinition createCallableGetter(Method method, TypeStore typeStore) { return createCallableGetterHelper(method, typeStore, false, false); } - private static MethodDefinition createCallableGetterHelper( + private MethodDefinition createCallableGetterHelper( Method method, TypeStore typeStore, boolean isLroCallable, boolean isPaged) { TypeNode returnType; switch (method.stream()) { @@ -197,27 +196,24 @@ private static MethodDefinition createCallableGetterHelper( returnType = TypeNode.withReference(returnType.reference().copyAndSetGenerics(genericRefs)); - return MethodDefinition.builder() - .setAnnotations(annotations) - .setScope(ScopeNode.PUBLIC) - .setReturnType(returnType) - .setName(methodName) - .setBody(createThrowUOEBody(methodName, typeStore)) - .build(); + return createCallableGetterMethodDefinition(returnType, methodName, annotations, typeStore); } - private MethodDefinition createOperationsStubGetter(TypeStore typeStore) { - String methodName = - String.format( - "get%s", - JavaStyle.toUpperCamelCase(getTransportContext().transportOperationsStubName())); + private List createOperationsStubGetters(TypeStore typeStore) { + List getters = new ArrayList<>(); - return MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setReturnType(getTransportContext().operationsStubType()) - .setName(methodName) - .setBody(createThrowUOEBody(methodName, typeStore)) - .build(); + Iterator operationStubNameIt = + getTransportContext().transportOperationsStubNames().iterator(); + Iterator operationStubTypeIt = getTransportContext().operationsStubTypes().iterator(); + + while (operationStubNameIt.hasNext() && operationStubTypeIt.hasNext()) { + String methodName = + String.format("get%s", JavaStyle.toUpperCamelCase(operationStubNameIt.next())); + + getters.add(createOperationsStubGetterMethodDefinition(operationStubTypeIt.next(), methodName, typeStore)); + } + + return getters; } private static List createBackgroundResourceMethodOverrides() { @@ -262,13 +258,37 @@ private static TypeStore createTypes(Service service, Map messa return typeStore; } - private static List createThrowUOEBody(String methodName, TypeStore typeStore) { - return Arrays.asList( - ExprStatement.withExpr( - ThrowExpr.builder() - .setType(typeStore.get("UnsupportedOperationException")) - .setMessageExpr(String.format("Not implemented: %s()", methodName)) - .build())); + protected MethodDefinition createCallableGetterMethodDefinition( + TypeNode returnType, String methodName, List annotations, TypeStore typeStore) { + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setAnnotations(annotations) + .setName(methodName) + .setReturnType(returnType) + .setBody( + Arrays.asList( + ExprStatement.withExpr( + ThrowExpr.builder() + .setType(typeStore.get("UnsupportedOperationException")) + .setMessageExpr(String.format("Not implemented: %s()", methodName)) + .build()))) + .build(); + } + + protected MethodDefinition createOperationsStubGetterMethodDefinition( + TypeNode returnType, String methodName, TypeStore typeStore) { + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setReturnType(returnType) + .setName(methodName) + .setBody( + Arrays.asList( + ExprStatement.withExpr( + ThrowExpr.builder() + .setType(typeStore.get("UnsupportedOperationException")) + .setMessageExpr(String.format("Not implemented: %s()", methodName)) + .build()))) + .build(); } private static String getClientClassName(Service service) { diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java index 3df0394ddd..d61456e1ad 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java @@ -105,6 +105,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -225,11 +226,125 @@ protected MethodDefinition createDefaultCredentialsProviderBuilderMethod() { .build(); } - protected abstract MethodDefinition createDefaultTransportTransportProviderBuilderMethod(); + protected List createDefaultTransportTransportProviderBuilderMethods() { + // Create the defaultGrpcTransportProviderBuilder method. + Iterator> providerClassIt = + getTransportContext().instantiatingChannelProviderClasses().iterator(); + Iterator> providerBuilderClassIt = + getTransportContext().instantiatingChannelProviderBuilderClasses().iterator(); + Iterator builderNamesIt = + getTransportContext().defaultTransportProviderBuilderNames().iterator(); + + List methods = new ArrayList<>(); + + while (providerClassIt.hasNext() + && providerBuilderClassIt.hasNext() + && builderNamesIt.hasNext()) { + TypeNode returnType = + TypeNode.withReference(ConcreteReference.withClazz(providerBuilderClassIt.next())); + TypeNode channelProviderType = + TypeNode.withReference(ConcreteReference.withClazz(providerClassIt.next())); + + MethodInvocationExpr transportChannelProviderBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(channelProviderType) + .setMethodName("newBuilder") + .setReturnType(returnType) + .build(); + Expr returnExpr = + initializeTransportProviderBuilder(transportChannelProviderBuilderExpr, returnType); - protected abstract MethodDefinition createDefaultApiClientHeaderProviderBuilderMethod( + MethodDefinition method = + MethodDefinition.builder() + .setHeaderCommentStatements( + SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT) + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName(builderNamesIt.next()) + .setReturnExpr(returnExpr) + .build(); + methods.add(method); + } + + return methods; + } + + protected Expr initializeTransportProviderBuilder( + MethodInvocationExpr transportChannelProviderBuilderExpr, TypeNode returnType) { + return transportChannelProviderBuilderExpr; + } + + protected abstract List createApiClientHeaderProviderBuilderMethods( Service service, TypeStore typeStore); + protected MethodDefinition createApiClientHeaderProviderBuilderMethod( + Service service, + TypeStore typeStore, + String methodName, + TypeNode gaxPropertiesType, + String getTokenMethodName, + String getVersionMethodName) { + TypeNode returnType = + TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); + MethodInvocationExpr returnExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("ApiClientHeaderProvider")) + .setMethodName("newBuilder") + .build(); + + MethodInvocationExpr versionArgExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("GaxProperties")) + .setMethodName("getLibraryVersion") + .setArguments( + VariableExpr.builder() + .setVariable( + Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) + .setStaticReferenceType( + typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) + .build()) + .build(); + + returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(returnExpr) + .setMethodName("setGeneratedLibToken") + .setArguments(ValueExpr.withValue(StringObjectValue.withValue("gapic")), versionArgExpr) + .build(); + returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(returnExpr) + .setMethodName("setTransportToken") + .setArguments( + MethodInvocationExpr.builder() + .setStaticReferenceType(gaxPropertiesType) + .setMethodName(getTokenMethodName) + .build(), + MethodInvocationExpr.builder() + .setStaticReferenceType(gaxPropertiesType) + .setMethodName(getVersionMethodName) + .build()) + .setReturnType(returnType) + .build(); + + AnnotationNode annotation = + AnnotationNode.builder() + .setType(FIXED_TYPESTORE.get("BetaApi")) + .setDescription( + "The surface for customizing headers is not stable yet and may change in the" + + " future.") + .build(); + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(annotation)) + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName(methodName) + .setReturnExpr(returnExpr) + .build(); + } + public abstract MethodDefinition createDefaultTransportChannelProviderMethod(); private List createClassAnnotations(Service service) { @@ -843,6 +958,7 @@ private List createClassMethods( createMethodSettingsGetterMethods(methodSettingsMemberVarExprs, deprecatedSettingVarNames)); javaMethods.add(createCreateStubMethod(service, typeStore)); javaMethods.addAll(createDefaultHelperAndGetterMethods(service, typeStore)); + javaMethods.addAll(createNewBuilderMethods(service, typeStore, "newBuilder", "createDefault")); javaMethods.addAll(createBuilderHelperMethods(service, typeStore)); javaMethods.add(createClassConstructor(service, methodSettingsMemberVarExprs, typeStore)); return javaMethods; @@ -875,11 +991,7 @@ private static List createMethodSettingsGetterMethods( private MethodDefinition createCreateStubMethod(Service service, TypeStore typeStore) { // Set up the if-statement. - Expr tRansportNameExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(getTransportContext().transportChannelType()) - .setMethodName(getTransportContext().transportGetterName()) - .build(); + List bodyStatements = new ArrayList<>(); Expr getTransportNameExpr = MethodInvocationExpr.builder().setMethodName("getTransportChannelProvider").build(); @@ -889,31 +1001,48 @@ private MethodDefinition createCreateStubMethod(Service service, TypeStore typeS .setMethodName("getTransportName") .build(); - Expr ifConditionExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(getTransportNameExpr) - .setMethodName("equals") - .setArguments(tRansportNameExpr) - .setReturnType(TypeNode.BOOLEAN) - .build(); + Iterator channelTypesIt = getTransportContext().transportChannelTypes().iterator(); + Iterator getterNameIt = getTransportContext().transportGetterNames().iterator(); + Iterator serivceStubClassNameIt = + getTransportContext().classNames().getTransportServiceStubClassNames(service).iterator(); - Expr createExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType( - typeStore.get( - getTransportContext().classNames().getTransportServiceStubClassName(service))) - .setMethodName("create") - .setArguments( - ValueExpr.withValue( - ThisObjectValue.withType( - typeStore.get(ClassNames.getServiceStubSettingsClassName(service))))) - .build(); + while (channelTypesIt.hasNext() && getterNameIt.hasNext()) { + TypeNode channelType = channelTypesIt.next(); + String getterName = getterNameIt.next(); + String serivceStubClassName = serivceStubClassNameIt.next(); - IfStatement ifStatement = - IfStatement.builder() - .setConditionExpr(ifConditionExpr) - .setBody(Arrays.asList(ExprStatement.withExpr(ReturnExpr.withExpr(createExpr)))) - .build(); + Expr tRansportNameExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(channelType) + .setMethodName(getterName) + .build(); + + Expr ifConditionExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(getTransportNameExpr) + .setMethodName("equals") + .setArguments(tRansportNameExpr) + .setReturnType(TypeNode.BOOLEAN) + .build(); + + Expr createExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(typeStore.get(serivceStubClassName)) + .setMethodName("create") + .setArguments( + ValueExpr.withValue( + ThisObjectValue.withType( + typeStore.get(ClassNames.getServiceStubSettingsClassName(service))))) + .build(); + + IfStatement ifStatement = + IfStatement.builder() + .setConditionExpr(ifConditionExpr) + .setBody(Arrays.asList(ExprStatement.withExpr(ReturnExpr.withExpr(createExpr)))) + .build(); + + bodyStatements.add(ifStatement); + } // Set up exception throwing. Expr errorMessageExpr = @@ -930,6 +1059,8 @@ private MethodDefinition createCreateStubMethod(Service service, TypeStore typeS ExprStatement.withExpr( ThrowExpr.builder().setType(exceptionType).setMessageExpr(errorMessageExpr).build()); + bodyStatements.add(throwStatement); + // Put the method together. TypeNode returnType = typeStore.get(ClassNames.getServiceStubClassName(service)); AnnotationNode annotation = @@ -945,7 +1076,7 @@ private MethodDefinition createCreateStubMethod(Service service, TypeStore typeS .setReturnType(returnType) .setName("createStub") .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(IOException.class))) - .setBody(Arrays.asList(ifStatement, throwStatement)) + .setBody(bodyStatements) .build(); } @@ -1021,33 +1152,40 @@ private List createDefaultHelperAndGetterMethods( .build()); javaMethods.add(createDefaultCredentialsProviderBuilderMethod()); - javaMethods.add(createDefaultTransportTransportProviderBuilderMethod()); + javaMethods.addAll(createDefaultTransportTransportProviderBuilderMethods()); javaMethods.add(createDefaultTransportChannelProviderMethod()); - javaMethods.add(createDefaultApiClientHeaderProviderBuilderMethod(service, typeStore)); + javaMethods.addAll(createApiClientHeaderProviderBuilderMethods(service, typeStore)); return javaMethods; } - private static List createBuilderHelperMethods( - Service service, TypeStore typeStore) { - List javaMethods = new ArrayList<>(); + protected List createNewBuilderMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { // Create the newBuilder() method. final TypeNode builderReturnType = typeStore.get(NESTED_BUILDER_CLASS_NAME); - javaMethods.add( + return ImmutableList.of( MethodDefinition.builder() .setHeaderCommentStatements(SettingsCommentComposer.NEW_BUILDER_METHOD_COMMENT) .setScope(ScopeNode.PUBLIC) .setIsStatic(true) .setReturnType(builderReturnType) - .setName("newBuilder") + .setName(newBuilderMethodName) .setReturnExpr( MethodInvocationExpr.builder() .setStaticReferenceType(builderReturnType) - .setMethodName("createDefault") + .setMethodName(createDefaultMethodName) .setReturnType(builderReturnType) .build()) .build()); + } + protected List createBuilderHelperMethods( + Service service, TypeStore typeStore) { + List javaMethods = new ArrayList<>(); + final TypeNode builderReturnType = typeStore.get(NESTED_BUILDER_CLASS_NAME); // Create the newBuilder(ClientContext) method. Function newBuilderFn = argExpr -> NewObjectExpr.builder().setType(builderReturnType).setArguments(argExpr).build(); @@ -1247,7 +1385,7 @@ private List createNestedClassMethods( nestedClassMethods.addAll( createNestedClassConstructorMethods( service, serviceConfig, nestedMethodSettingsMemberVarExprs, typeStore)); - nestedClassMethods.add(createNestedClassCreateDefaultMethod(typeStore)); + nestedClassMethods.addAll(createNestedClassCreateDefaultMethods(typeStore)); nestedClassMethods.add(createNestedClassInitDefaultsMethod(service, serviceConfig, typeStore)); nestedClassMethods.add(createNestedClassApplyToAllUnaryMethodsMethod(superType, typeStore)); nestedClassMethods.add(createNestedClassUnaryMethodSettingsBuilderGetterMethod()); @@ -1585,7 +1723,22 @@ private static List createNestedClassConstructorMethods( return ctorMethods; } - private static MethodDefinition createNestedClassCreateDefaultMethod(TypeStore typeStore) { + protected List createNestedClassCreateDefaultMethods(TypeStore typeStore) { + return Collections.singletonList( + createNestedClassCreateDefaultMethod( + typeStore, + "createDefault", + "defaultTransportChannelProvider", + null, + "defaultApiClientHeaderProviderBuilder")); + } + + protected MethodDefinition createNestedClassCreateDefaultMethod( + TypeStore typeStore, + String methodName, + String defaultTransportChannelProvider, + String defaultTransportChannelProviderBuilder, + String defaultApiClientHeaderProviderBuilder) { List bodyStatements = new ArrayList<>(); // Initialize the builder: Builder builder = new Builder((ClientContext) null); @@ -1610,15 +1763,32 @@ private static MethodDefinition createNestedClassCreateDefaultMethod(TypeStore t bodyStatements.add(EMPTY_LINE_STATEMENT); List bodyExprs = new ArrayList<>(); - bodyExprs.add( - MethodInvocationExpr.builder() - .setExprReferenceExpr(builderVarExpr) - .setMethodName("setTransportChannelProvider") - .setArguments( - MethodInvocationExpr.builder() - .setMethodName("defaultTransportChannelProvider") - .build()) - .build()); + + if (defaultTransportChannelProvider != null) { + bodyExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(builderVarExpr) + .setMethodName("setTransportChannelProvider") + .setArguments( + MethodInvocationExpr.builder() + .setMethodName(defaultTransportChannelProvider) + .build()) + .build()); + } else { + bodyExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(builderVarExpr) + .setMethodName("setTransportChannelProvider") + .setArguments( + MethodInvocationExpr.builder() + .setExprReferenceExpr( + MethodInvocationExpr.builder() + .setMethodName(defaultTransportChannelProviderBuilder) + .build()) + .setMethodName("build") + .build()) + .build()); + } bodyExprs.add( MethodInvocationExpr.builder() @@ -1642,7 +1812,7 @@ private static MethodDefinition createNestedClassCreateDefaultMethod(TypeStore t MethodInvocationExpr.builder() .setExprReferenceExpr( MethodInvocationExpr.builder() - .setMethodName("defaultApiClientHeaderProviderBuilder") + .setMethodName(defaultApiClientHeaderProviderBuilder) .build()) .setMethodName("build") .build()) @@ -1685,7 +1855,7 @@ private static MethodDefinition createNestedClassCreateDefaultMethod(TypeStore t .setScope(ScopeNode.PRIVATE) .setIsStatic(true) .setReturnType(builderType) - .setName("createDefault") + .setName(methodName) .setBody(bodyStatements) .setReturnExpr(returnExpr) .build(); @@ -1869,10 +2039,12 @@ private TypeStore createDynamicTypes(Service service, String pakkage) { pakkage, Arrays.asList( thisClassName, - getTransportContext().classNames().getTransportServiceStubClassName(service), ClassNames.getServiceStubSettingsClassName(service), ClassNames.getServiceStubClassName(service))); + typeStore.putAll( + pakkage, getTransportContext().classNames().getTransportServiceStubClassNames(service)); + // Nested builder class. typeStore.put(pakkage, NESTED_BUILDER_CLASS_NAME, true, thisClassName); diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java index 14fe5da0fa..26b72a5739 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java @@ -145,12 +145,13 @@ public GapicClass generate(GapicContext context, Service service) { .setType(FIXED_TYPESTORE.get("BackgroundResource")) .build())); if (generateOperationsStubLogic(service)) { + // Transport-specific service stub may have only one element of the following, thus get(0). classMemberVarExprs.put( - getTransportContext().transportOperationsStubName(), + getTransportContext().transportOperationsStubNames().get(0), VariableExpr.withVariable( Variable.builder() - .setName(getTransportContext().transportOperationsStubName()) - .setType(getTransportContext().transportOperationsStubType()) + .setName(getTransportContext().transportOperationsStubNames().get(0)) + .setType(getTransportContext().transportOperationsStubTypes().get(0)) .build())); } classMemberVarExprs.put( @@ -210,7 +211,7 @@ protected List createOperationsStubGetterMethod( String methodName = String.format( "get%s", - JavaStyle.toUpperCamelCase(getTransportContext().transportOperationsStubName())); + JavaStyle.toUpperCamelCase(getTransportContext().transportOperationsStubNames().get(0))); return Arrays.asList( MethodDefinition.builder() @@ -388,7 +389,7 @@ protected List createClassMethods( Map callableClassMemberVarExprs, Map protoMethodNameToDescriptorVarExprs) { List javaMethods = new ArrayList<>(); - javaMethods.addAll(createStaticCreatorMethods(service, typeStore)); + javaMethods.addAll(createStaticCreatorMethods(service, typeStore, "newBuilder")); javaMethods.addAll( createConstructorMethods( service, @@ -400,14 +401,14 @@ protected List createClassMethods( createGetMethodDescriptorsMethod(service, typeStore, protoMethodNameToDescriptorVarExprs)); javaMethods.addAll( createOperationsStubGetterMethod( - service, classMemberVarExprs.get(getTransportContext().transportOperationsStubName()))); + service, classMemberVarExprs.get(getTransportContext().transportOperationsStubNames().get(0)))); javaMethods.addAll(createCallableGetterMethods(callableClassMemberVarExprs)); javaMethods.addAll( createStubOverrideMethods(classMemberVarExprs.get(BACKGROUND_RESOURCES_MEMBER_NAME))); return javaMethods; } - private List createStaticCreatorMethods(Service service, TypeStore typeStore) { + protected List createStaticCreatorMethods(Service service, TypeStore typeStore, String newBuilderMethod) { TypeNode creatorMethodReturnType = typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); Function, MethodDefinition.Builder> creatorMethodStarterFn = @@ -456,7 +457,7 @@ private List createStaticCreatorMethods(Service service, TypeS .build(); MethodInvocationExpr settingsBuilderMethodExpr = MethodInvocationExpr.builder() - .setMethodName("newBuilder") + .setMethodName(newBuilderMethod) .setStaticReferenceType(stubSettingsType) .build(); settingsBuilderMethodExpr = @@ -566,7 +567,7 @@ protected List createConstructorMethods( .build()) .setValueExpr(callableFactoryVarExpr) .build()); - VariableExpr operationsStubClassVarExpr = classMemberVarExprs.get(getTransportContext().transportOperationsStubName()); + VariableExpr operationsStubClassVarExpr = classMemberVarExprs.get(getTransportContext().transportOperationsStubNames().get(0)); if (generateOperationsStubLogic(service)) { secondCtorExprs.add( AssignmentExpr.builder() @@ -574,7 +575,7 @@ protected List createConstructorMethods( operationsStubClassVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) .setValueExpr( MethodInvocationExpr.builder() - .setStaticReferenceType(getTransportContext().transportOperationsStubType()) + .setStaticReferenceType(getTransportContext().transportOperationsStubTypes().get(0)) .setMethodName("create") .setArguments(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) .setReturnType(operationsStubClassVarExpr.type()) diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java b/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java index 9296c9b93c..507ff662ca 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java @@ -19,6 +19,8 @@ import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Transport; import com.google.auto.value.AutoValue; +import java.util.List; +import javax.annotation.Nullable; @AutoValue public abstract class TransportContext { @@ -28,35 +30,46 @@ public abstract class TransportContext { // For AbstractServiceStubClassComposer public abstract Transport transport(); + @Nullable public abstract String transportName(); + @Nullable public abstract Class callSettingsClass(); + @Nullable public abstract TypeNode stubCallableFactoryType(); + @Nullable public abstract Class methodDescriptorClass(); - public abstract TypeNode transportOperationsStubType(); + public abstract List transportOperationsStubTypes(); - public abstract String transportOperationsStubName(); + public abstract List transportOperationsStubNames(); // For AbstractServiceSettingsClassComposer - public abstract Class instantiatingChannelProviderClass(); + public abstract List> instantiatingChannelProviderClasses(); - public abstract String defaultTransportProviderBuilderName(); + public abstract List> instantiatingChannelProviderBuilderClasses(); + + public abstract List defaultTransportProviderBuilderNames(); + + public abstract List transportApiClientHeaderProviderBuilderNames(); // For AbstractServiceStubSettingsClassComposer - public abstract TypeNode transportChannelType(); + public abstract List transportChannelTypes(); - public abstract String transportGetterName(); + public abstract List transportGetterNames(); // For AbstractServiceCallableFactoryClassComposer + @Nullable public abstract TypeNode transportCallSettingsType(); + @Nullable public abstract TypeNode transportCallableFactoryType(); - public abstract TypeNode operationsStubType(); + public abstract List operationsStubTypes(); + @Nullable public abstract String transportCallSettingsName(); // For RetrySettingsComposer @@ -64,9 +77,9 @@ public abstract class TransportContext { public abstract TypeNode operationMetadataTransformerType(); - public abstract TypeNode operationsClientType(); + public abstract List operationsClientTypes(); - public abstract String operationsClientName(); + public abstract List operationsClientNames(); protected static TypeNode classToType(Class clazz) { return TypeNode.withReference(ConcreteReference.withClazz(clazz)); @@ -91,15 +104,21 @@ public abstract static class Builder { public abstract Builder setMethodDescriptorClass(Class methodDescriptorClass); - public abstract Builder setInstantiatingChannelProviderClass( - Class instantiatingChannelProviderClass); + public abstract Builder setInstantiatingChannelProviderClasses( + List> instantiatingChannelProviderClasses); + + public abstract Builder setInstantiatingChannelProviderBuilderClasses( + List> instantiatingChannelProviderBuilderClasses); + + public abstract Builder setDefaultTransportProviderBuilderNames( + List defaultTransportProviderBuilderNames); - public abstract Builder setDefaultTransportProviderBuilderName( - String defaultTransportProviderBuilderName); + public abstract Builder setTransportApiClientHeaderProviderBuilderNames( + List transportApiClientHeaderProviderBuilderNames); - public abstract Builder setTransportChannelType(TypeNode transportChannelType); + public abstract Builder setTransportChannelTypes(List transportChannelTypes); - public abstract Builder setTransportGetterName(String transportGetterName); + public abstract Builder setTransportGetterNames(List transportGetterNames); public abstract Builder setTransportCallSettingsType(TypeNode transportCallSettingsType); @@ -107,19 +126,19 @@ public abstract Builder setDefaultTransportProviderBuilderName( public abstract Builder setTransportCallSettingsName(String transportCallSettingsName); - public abstract Builder setTransportOperationsStubType(TypeNode transportOperationsStubType); + public abstract Builder setTransportOperationsStubTypes(List transportOperationsStubTypes); - public abstract Builder setTransportOperationsStubName(String transportOperationsStubName); + public abstract Builder setTransportOperationsStubNames(List transportOperationsStubNames); - public abstract Builder setOperationsStubType(TypeNode operationsStubType); + public abstract Builder setOperationsStubTypes(List operationsStubType); public abstract Builder setOperationResponseTransformerType(TypeNode operationResponseTransformerType); public abstract Builder setOperationMetadataTransformerType(TypeNode operationMetadataTransformerType); - public abstract Builder setOperationsClientType(TypeNode operationsClientType); + public abstract Builder setOperationsClientTypes(List operationsClientTypes); - public abstract Builder setOperationsClientName(String operationsClientName); + public abstract Builder setOperationsClientNames(List operationsClientNames); public abstract TransportContext build(); } diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java index 53a8d6f3ca..5f9b27963e 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java @@ -23,6 +23,7 @@ import com.google.api.generator.gapic.composer.common.TransportContext; import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Transport; +import com.google.common.collect.ImmutableList; import com.google.longrunning.OperationsClient; import com.google.longrunning.stub.GrpcOperationsStub; import com.google.longrunning.stub.OperationsStub; @@ -38,18 +39,24 @@ public abstract class GrpcContext extends TransportContext { .setCallSettingsClass(GrpcCallSettings.class) .setStubCallableFactoryType(classToType(GrpcStubCallableFactory.class)) .setMethodDescriptorClass(MethodDescriptor.class) - .setTransportOperationsStubType(classToType(GrpcOperationsStub.class)) - .setTransportOperationsStubName("operationsStub") + .setTransportOperationsStubTypes(ImmutableList.of(classToType(GrpcOperationsStub.class))) + .setTransportOperationsStubNames(ImmutableList.of("operationsStub")) // For grpc.ServiceSettingsClassComposer - .setInstantiatingChannelProviderClass(InstantiatingGrpcChannelProvider.Builder.class) - .setDefaultTransportProviderBuilderName("defaultGrpcTransportProviderBuilder") + .setInstantiatingChannelProviderClasses( + ImmutableList.of(InstantiatingGrpcChannelProvider.class)) + .setInstantiatingChannelProviderBuilderClasses( + ImmutableList.of(InstantiatingGrpcChannelProvider.Builder.class)) + .setDefaultTransportProviderBuilderNames( + ImmutableList.of("defaultGrpcTransportProviderBuilder")) + .setTransportApiClientHeaderProviderBuilderNames( + ImmutableList.of("defaultGrpcApiClientHeaderProviderBuilder")) // For grpc.ServiceStubSettingsClassComposer - .setTransportChannelType(classToType(GrpcTransportChannel.class)) - .setTransportGetterName("getGrpcTransportName") + .setTransportChannelTypes(ImmutableList.of(classToType(GrpcTransportChannel.class))) + .setTransportGetterNames(ImmutableList.of("getGrpcTransportName")) // For grpc.GrpcServiceCallableFactoryClassComposer .setTransportCallSettingsType(classToType(GrpcCallSettings.class)) .setTransportCallableFactoryType(classToType(GrpcCallableFactory.class)) - .setOperationsStubType(classToType(OperationsStub.class)) + .setOperationsStubTypes(ImmutableList.of(classToType(OperationsStub.class))) .setTransportCallSettingsName("grpcCallSettings") // For RetrySettingsComposer .setOperationResponseTransformerType( @@ -57,8 +64,8 @@ public abstract class GrpcContext extends TransportContext { .setOperationMetadataTransformerType( classToType(ProtoOperationTransformers.MetadataTransformer.class)) // For ServiceClientClassComposer - .setOperationsClientType(classToType(OperationsClient.class)) - .setOperationsClientName("operationsClient") + .setOperationsClientTypes(ImmutableList.of(classToType(OperationsClient.class))) + .setOperationsClientNames(ImmutableList.of("operationsClient")) .build(); public static TransportContext instance() { diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java index 636326d820..75bd4c0133 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java @@ -143,7 +143,8 @@ protected MethodDefinition createStartStaticServerMethod( Service service, GapicContext context, Map classMemberVarExprs, - TypeStore typeStore) { + TypeStore typeStore, + String newBuilderMethod) { VariableExpr serviceHelperVarExpr = classMemberVarExprs.get(SERVICE_HELPER_VAR_NAME); Function serviceToVarExprFn = s -> classMemberVarExprs.get(getMockServiceVarName(s)); diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java index 6d0b8e221d..a80feffcd5 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java @@ -18,14 +18,12 @@ import com.google.api.gax.grpc.GaxGrpcProperties; import com.google.api.gax.grpc.GrpcTransportChannel; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.generator.engine.ast.AnnotationNode; import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.Expr; import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.PrimitiveValue; import com.google.api.generator.engine.ast.ScopeNode; -import com.google.api.generator.engine.ast.StringObjectValue; import com.google.api.generator.engine.ast.TypeNode; import com.google.api.generator.engine.ast.ValueExpr; import com.google.api.generator.engine.ast.Variable; @@ -33,9 +31,9 @@ import com.google.api.generator.gapic.composer.comment.SettingsCommentComposer; import com.google.api.generator.gapic.composer.common.AbstractServiceStubSettingsClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; -import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Service; import java.util.Arrays; +import java.util.Collections; import java.util.List; public class ServiceStubSettingsClassComposer extends AbstractServiceStubSettingsClassComposer { @@ -62,37 +60,17 @@ private static TypeStore createStaticTypes() { } @Override - protected MethodDefinition createDefaultTransportTransportProviderBuilderMethod() { - // Create the defaultGrpcTransportProviderBuilder method. - TypeNode returnType = - TypeNode.withReference( - ConcreteReference.withClazz(InstantiatingGrpcChannelProvider.Builder.class)); - MethodInvocationExpr transportChannelProviderBuilderExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_GRPC_TYPESTORE.get(InstantiatingGrpcChannelProvider.class.getSimpleName())) - .setMethodName("newBuilder") - .build(); - transportChannelProviderBuilderExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(transportChannelProviderBuilderExpr) - .setMethodName("setMaxInboundMessageSize") - .setArguments( - VariableExpr.builder() - .setVariable( - Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build()) - .setStaticReferenceType(TypeNode.INT_OBJECT) - .build()) - .setReturnType(returnType) - .build(); - return MethodDefinition.builder() - .setHeaderCommentStatements( - SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) + protected Expr initializeTransportProviderBuilder( + MethodInvocationExpr transportChannelProviderBuilderExpr, TypeNode returnType) { + return MethodInvocationExpr.builder() + .setExprReferenceExpr(transportChannelProviderBuilderExpr) + .setMethodName("setMaxInboundMessageSize") + .setArguments( + VariableExpr.builder() + .setVariable(Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build()) + .setStaticReferenceType(TypeNode.INT_OBJECT) + .build()) .setReturnType(returnType) - .setName("defaultGrpcTransportProviderBuilder") - .setReturnExpr(transportChannelProviderBuilderExpr) .build(); } @@ -138,69 +116,16 @@ protected MethodDefinition createDefaultCredentialsProviderBuilderMethod() { } @Override - protected MethodDefinition createDefaultApiClientHeaderProviderBuilderMethod( + protected List createApiClientHeaderProviderBuilderMethods( Service service, TypeStore typeStore) { - // Create the defaultApiClientHeaderProviderBuilder method. - TypeNode returnType = - TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); - MethodInvocationExpr returnExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("ApiClientHeaderProvider")) - .setMethodName("newBuilder") - .build(); - - MethodInvocationExpr versionArgExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GaxProperties")) - .setMethodName("getLibraryVersion") - .setArguments( - VariableExpr.builder() - .setVariable( - Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) - .setStaticReferenceType( - typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) - .build()) - .build(); - - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setGeneratedLibToken") - .setArguments(ValueExpr.withValue(StringObjectValue.withValue("gapic")), versionArgExpr) - .build(); - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setTransportToken") - .setArguments( - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_GRPC_TYPESTORE.get(GaxGrpcProperties.class.getSimpleName())) - .setMethodName("getGrpcTokenName") - .build(), - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_GRPC_TYPESTORE.get(GaxGrpcProperties.class.getSimpleName())) - .setMethodName("getGrpcVersion") - .build()) - .setReturnType(returnType) - .build(); - - AnnotationNode annotation = - AnnotationNode.builder() - .setType(FIXED_TYPESTORE.get("BetaApi")) - .setDescription( - "The surface for customizing headers is not stable yet and may change in the" - + " future.") - .build(); - return MethodDefinition.builder() - .setAnnotations(Arrays.asList(annotation)) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setReturnType(returnType) - .setName("defaultApiClientHeaderProviderBuilder") - .setReturnExpr(returnExpr) - .build(); + return Collections.singletonList( + createApiClientHeaderProviderBuilderMethod( + service, + typeStore, + "defaultApiClientHeaderProviderBuilder", + FIXED_GRPC_TYPESTORE.get(GaxGrpcProperties.class.getSimpleName()), + "getGrpcTokenName", + "getGrpcVersion")); } @Override diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/BUILD.bazel new file mode 100644 index 0000000000..ea77aab100 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/BUILD.bazel @@ -0,0 +1,55 @@ +load("@rules_java//java:defs.bzl", "java_library") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "grpcrest_files", + srcs = glob(["*.java"]), +) + +java_library( + name = "grpcrest", + srcs = [ + ":grpcrest_files", + ], + deps = [ + "//:service_config_java_proto", + "//src/main/java/com/google/api/generator/engine/ast", + "//src/main/java/com/google/api/generator/engine/writer", + "//src/main/java/com/google/api/generator/gapic:status_java_proto", + "//src/main/java/com/google/api/generator/gapic/composer/comment", + "//src/main/java/com/google/api/generator/gapic/composer/common", + "//src/main/java/com/google/api/generator/gapic/composer/defaultvalue", + "//src/main/java/com/google/api/generator/gapic/composer/resourcename", + "//src/main/java/com/google/api/generator/gapic/composer/rest", + "//src/main/java/com/google/api/generator/gapic/composer/samplecode", + "//src/main/java/com/google/api/generator/gapic/composer/store", + "//src/main/java/com/google/api/generator/gapic/composer/utils", + "//src/main/java/com/google/api/generator/gapic/model", + "//src/main/java/com/google/api/generator/gapic/utils", + "//src/main/java/com/google/api/generator/util", + "@com_google_api_api_common//jar", + "@com_google_api_gax_java//gax", + "@com_google_api_gax_java//gax:gax_testlib", + "@com_google_api_gax_java//gax-grpc:gax_grpc", + "@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", + "@com_google_api_gax_java//gax-httpjson:gax_httpjson", + "@com_google_api_gax_java//gax-httpjson:gax_httpjson_testlib", + "@com_google_code_findbugs_jsr305//jar", + "@com_google_googleapis//gapic/metadata:metadata_java_proto", + "@com_google_googleapis//google/api:api_java_proto", + "@com_google_googleapis//google/longrunning:longrunning_java_proto", + "@com_google_googleapis//google/rpc:rpc_java_proto", + "@com_google_guava_guava//jar", + "@com_google_http_client_google_http_client//jar", + "@com_google_protobuf//:protobuf_java", + "@com_google_protobuf//:protobuf_java_util", + "@com_google_protobuf//java/core", + "@io_grpc_grpc_java//api", + "@io_grpc_grpc_java//protobuf", + "@io_grpc_grpc_java//stub", + "@javax_annotation_javax_annotation_api//jar", + "@junit_junit//jar", + "@org_threeten_threetenbp//jar", + ], +) diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/GrpcRestContext.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/GrpcRestContext.java new file mode 100644 index 0000000000..3f84bf3c97 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/GrpcRestContext.java @@ -0,0 +1,95 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.grpc.GrpcTransportChannel; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.api.gax.grpc.ProtoOperationTransformers; +import com.google.api.gax.httpjson.HttpJsonTransportChannel; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.httpjson.longrunning.stub.HttpJsonOperationsStub; +import com.google.api.generator.gapic.composer.common.TransportContext; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Transport; +import com.google.common.collect.ImmutableList; +import com.google.longrunning.OperationsClient; +import com.google.longrunning.stub.GrpcOperationsStub; +import com.google.longrunning.stub.OperationsStub; + +public abstract class GrpcRestContext extends TransportContext { + private static final TransportContext INSTANCE = + GrpcRestContext.builder() + .setClassNames(new ClassNames("Grpc", "HttpJson")) + .setTransport(Transport.GRPC_REST) + .setTransportName(null) + // For grpcrest.GrpcServiceStubClassComposer + .setCallSettingsClass(null) + .setStubCallableFactoryType(null) + .setMethodDescriptorClass(null) + .setTransportOperationsStubTypes( + ImmutableList.of( + classToType(GrpcOperationsStub.class), classToType(HttpJsonOperationsStub.class))) + .setTransportOperationsStubNames( + ImmutableList.of("operationsStub", "httpJsonOperationsStub")) + // For grpcrest.ServiceSettingsClassComposer + .setInstantiatingChannelProviderClasses( + ImmutableList.of( + InstantiatingGrpcChannelProvider.class, + InstantiatingHttpJsonChannelProvider.class)) + .setInstantiatingChannelProviderBuilderClasses( + ImmutableList.of( + InstantiatingGrpcChannelProvider.Builder.class, + InstantiatingHttpJsonChannelProvider.Builder.class)) + .setDefaultTransportProviderBuilderNames( + ImmutableList.of( + "defaultGrpcTransportProviderBuilder", "defaultHttpJsonTransportProviderBuilder")) + .setTransportApiClientHeaderProviderBuilderNames( + ImmutableList.of( + "defaultGrpcApiClientHeaderProviderBuilder", + "defaultHttpJsonApiClientHeaderProviderBuilder")) + // For grpcrest.ServiceStubSettingsClassComposer + .setTransportChannelTypes( + ImmutableList.of( + classToType(GrpcTransportChannel.class), + classToType(HttpJsonTransportChannel.class))) + .setTransportGetterNames( + ImmutableList.of("getGrpcTransportName", "getHttpJsonTransportName")) + // For grpcrest.GrpcServiceCallableFactoryClassComposer + .setTransportCallSettingsType(null) + .setTransportCallableFactoryType(null) + .setOperationsStubTypes( + ImmutableList.of( + classToType(OperationsStub.class), classToType(BackgroundResource.class))) + .setTransportCallSettingsName(null) + // For RetrySettingsComposer + // TODO: fix when LRO for REST RE FIXED + .setOperationResponseTransformerType( + classToType(ProtoOperationTransformers.ResponseTransformer.class)) + .setOperationMetadataTransformerType( + classToType(ProtoOperationTransformers.MetadataTransformer.class)) + // For ServiceClientClassComposer + .setOperationsClientTypes( + ImmutableList.of( + classToType(OperationsClient.class), + classToType(com.google.api.gax.httpjson.longrunning.OperationsClient.class))) + .setOperationsClientNames( + ImmutableList.of("operationsClient", "httpJsonOperationsClient")) + .build(); + + public static TransportContext instance() { + return INSTANCE; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceClientTestClassComposer.java new file mode 100644 index 0000000000..9f9bbafc05 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceClientTestClassComposer.java @@ -0,0 +1,57 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.common.AbstractServiceClientTestClassComposer; +import com.google.api.generator.gapic.composer.rest.ServiceClientTestClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.model.GapicClass; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.Service; +import java.util.Map; + +public class HttpJsonServiceClientTestClassComposer extends ServiceClientTestClassComposer { + private static final HttpJsonServiceClientTestClassComposer INSTANCE = + new HttpJsonServiceClientTestClassComposer(); + + protected HttpJsonServiceClientTestClassComposer() { + super(); + } + + public static AbstractServiceClientTestClassComposer instance() { + return INSTANCE; + } + + @Override + protected GapicClass generate(String className, GapicContext context, Service service) { + return super.generate( + getTransportContext().classNames().getServiceClientTestClassNames(service).get(0), + context, + service); + } + + @Override + protected MethodDefinition createStartStaticServerMethod( + Service service, + GapicContext context, + Map classMemberVarExprs, + TypeStore typeStore, + String newBuilderMethod) { + return super.createStartStaticServerMethod( + service, context, classMemberVarExprs, typeStore, "newHttpJsonBuilder"); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceStubClassComposer.java new file mode 100644 index 0000000000..7f99c81287 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceStubClassComposer.java @@ -0,0 +1,40 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.model.Service; +import java.util.List; + +public class HttpJsonServiceStubClassComposer + extends com.google.api.generator.gapic.composer.rest.HttpJsonServiceStubClassComposer { + private static final HttpJsonServiceStubClassComposer INSTANCE = + new HttpJsonServiceStubClassComposer(); + + protected HttpJsonServiceStubClassComposer() { + super(); + } + + public static HttpJsonServiceStubClassComposer instance() { + return INSTANCE; + } + + @Override + protected List createStaticCreatorMethods( + Service service, TypeStore typeStore, String newBuilderMethod) { + return super.createStaticCreatorMethods(service, typeStore, "newHttpJsonBuilder"); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceClientClassComposer.java new file mode 100644 index 0000000000..7529b002cf --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceClientClassComposer.java @@ -0,0 +1,29 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.gapic.composer.common.AbstractServiceClientClassComposer; + +public class ServiceClientClassComposer extends AbstractServiceClientClassComposer { + private static final ServiceClientClassComposer INSTANCE = new ServiceClientClassComposer(); + + protected ServiceClientClassComposer() { + super(GrpcRestContext.instance()); + } + + public static ServiceClientClassComposer instance() { + return INSTANCE; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceSettingsClassComposer.java new file mode 100644 index 0000000000..03ff5dc54a --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceSettingsClassComposer.java @@ -0,0 +1,68 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.gapic.composer.common.AbstractServiceSettingsClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.model.Service; +import java.util.ArrayList; +import java.util.List; + +public class ServiceSettingsClassComposer extends AbstractServiceSettingsClassComposer { + private static final ServiceSettingsClassComposer INSTANCE = new ServiceSettingsClassComposer(); + + protected ServiceSettingsClassComposer() { + super(GrpcRestContext.instance()); + } + + public static ServiceSettingsClassComposer instance() { + return INSTANCE; + } + + @Override + protected List createNestedBuilderCreatorMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { + List methods = new ArrayList<>(); + + methods.addAll( + super.createNestedBuilderCreatorMethods(service, typeStore, "newBuilder", "createDefault")); + methods.addAll( + super.createNestedBuilderCreatorMethods( + service, typeStore, "newHttpJsonBuilder", "createHttpJsonDefault")); + + return methods; + } + + @Override + protected List createNewBuilderMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { + List methods = new ArrayList<>(); + + methods.addAll( + super.createNewBuilderMethods(service, typeStore, "newBuilder", "createDefault")); + methods.addAll( + super.createNewBuilderMethods( + service, typeStore, "newHttpJsonBuilder", "createHttpJsonDefault")); + + return methods; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubClassComposer.java new file mode 100644 index 0000000000..6be0ef7ac2 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubClassComposer.java @@ -0,0 +1,47 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.ReturnExpr; +import com.google.api.generator.engine.ast.ScopeNode; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; + +public class ServiceStubClassComposer extends AbstractServiceStubClassComposer { + private static final ServiceStubClassComposer INSTANCE = new ServiceStubClassComposer(); + + protected ServiceStubClassComposer() { + super(GrpcRestContext.instance()); + } + + public static ServiceStubClassComposer instance() { + return INSTANCE; + } + + @Override + protected MethodDefinition createOperationsStubGetterMethodDefinition( + TypeNode returnType, String methodName, TypeStore typeStore) { + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setReturnType(returnType) + .setName(methodName) + .setReturnExpr(ReturnExpr.withExpr(ValueExpr.createNullExpr())) + .build(); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubSettingsClassComposer.java new file mode 100644 index 0000000000..6f65ced39c --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubSettingsClassComposer.java @@ -0,0 +1,200 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.grpc.GaxGrpcProperties; +import com.google.api.gax.httpjson.GaxHttpJsonProperties; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.MethodInvocationExpr; +import com.google.api.generator.engine.ast.PrimitiveValue; +import com.google.api.generator.engine.ast.ScopeNode; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.comment.SettingsCommentComposer; +import com.google.api.generator.gapic.composer.common.AbstractServiceStubSettingsClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Service; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; + +public class ServiceStubSettingsClassComposer extends AbstractServiceStubSettingsClassComposer { + private static final ServiceStubSettingsClassComposer INSTANCE = + new ServiceStubSettingsClassComposer(); + + public static ServiceStubSettingsClassComposer instance() { + return INSTANCE; + } + + protected ServiceStubSettingsClassComposer() { + super(GrpcRestContext.instance()); + } + + @Override + protected Expr initializeTransportProviderBuilder( + MethodInvocationExpr transportChannelProviderBuilderExpr, TypeNode returnType) { + if (!returnType.reference().isFromPackage("com.google.api.gax.grpc")) { + return transportChannelProviderBuilderExpr; + } + + return MethodInvocationExpr.builder() + .setExprReferenceExpr(transportChannelProviderBuilderExpr) + .setMethodName("setMaxInboundMessageSize") + .setArguments( + VariableExpr.builder() + .setVariable(Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build()) + .setStaticReferenceType(TypeNode.INT_OBJECT) + .build()) + .setReturnType(returnType) + .build(); + } + + @Override + protected MethodDefinition createDefaultCredentialsProviderBuilderMethod() { + TypeNode returnType = + TypeNode.withReference( + ConcreteReference.withClazz(GoogleCredentialsProvider.Builder.class)); + MethodInvocationExpr credsProviderBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("GoogleCredentialsProvider")) + .setMethodName("newBuilder") + .build(); + credsProviderBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(credsProviderBuilderExpr) + .setMethodName("setScopesToApply") + .setArguments(DEFAULT_SERVICE_SCOPES_VAR_EXPR) + .setReturnType(returnType) + .build(); + + // This section is specific to GAPIC clients. It sets UseJwtAccessWithScope value to true to + // enable self signed JWT feature. + credsProviderBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(credsProviderBuilderExpr) + .setMethodName("setUseJwtAccessWithScope") + .setArguments( + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.BOOLEAN).setValue("true").build())) + .setReturnType(returnType) + .build(); + + return MethodDefinition.builder() + .setHeaderCommentStatements( + SettingsCommentComposer.DEFAULT_CREDENTIALS_PROVIDER_BUILDER_METHOD_COMMENT) + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName("defaultCredentialsProviderBuilder") + .setReturnExpr(credsProviderBuilderExpr) + .build(); + } + + @Override + protected List createApiClientHeaderProviderBuilderMethods( + Service service, TypeStore typeStore) { + + TypeNode returnType = + TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); + + return ImmutableList.of( + createApiClientHeaderProviderBuilderMethod( + service, + typeStore, + "defaultGrpcApiClientHeaderProviderBuilder", + TypeNode.withReference(ConcreteReference.withClazz(GaxGrpcProperties.class)), + "getGrpcTokenName", + "getGrpcVersion"), + createApiClientHeaderProviderBuilderMethod( + service, + typeStore, + "defaultHttpJsonApiClientHeaderProviderBuilder", + TypeNode.withReference(ConcreteReference.withClazz(GaxHttpJsonProperties.class)), + "getHttpJsonTokenName", + "getHttpJsonVersion"), + MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName("defaultApiClientHeaderProviderBuilder") + .setReturnExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType( + typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) + .setMethodName("defaultGrpcApiClientHeaderProviderBuilder") + .setReturnType(returnType) + .build()) + .build()); + } + + @Override + public MethodDefinition createDefaultTransportChannelProviderMethod() { + TypeNode returnType = FIXED_TYPESTORE.get("TransportChannelProvider"); + MethodInvocationExpr transportProviderBuilderExpr = + MethodInvocationExpr.builder().setMethodName("defaultGrpcTransportProviderBuilder").build(); + transportProviderBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(transportProviderBuilderExpr) + .setMethodName("build") + .setReturnType(returnType) + .build(); + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName("defaultTransportChannelProvider") + .setReturnExpr(transportProviderBuilderExpr) + .build(); + } + + @Override + protected List createNestedClassCreateDefaultMethods(TypeStore typeStore) { + return ImmutableList.of( + createNestedClassCreateDefaultMethod( + typeStore, + "createDefault", + "defaultTransportChannelProvider", + null, + "defaultApiClientHeaderProviderBuilder"), + createNestedClassCreateDefaultMethod( + typeStore, + "createHttpJsonDefault", + null, + "defaultHttpJsonTransportProviderBuilder", + "defaultHttpJsonApiClientHeaderProviderBuilder")); + } + + @Override + protected List createNewBuilderMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { + List methods = new ArrayList<>(); + methods.addAll( + super.createNewBuilderMethods(service, typeStore, "newBuilder", "createDefault")); + methods.addAll( + super.createNewBuilderMethods( + service, typeStore, "newHttpJsonBuilder", "createHttpJsonDefault")); + return methods; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java index 75429dbdeb..1ed6296cfa 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java @@ -67,7 +67,7 @@ protected List createClassImplements(TypeStore typeStore) { .copyAndSetGenerics( Arrays.asList( MESSAGE_TYPE.reference(), - getTransportContext().operationsStubType().reference())))); + getTransportContext().operationsStubTypes().get(0).reference())))); } @Override diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java b/src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java index 682e68f1da..eab59215bf 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java @@ -27,6 +27,7 @@ import com.google.api.generator.gapic.composer.common.TransportContext; import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Transport; +import com.google.common.collect.ImmutableList; public abstract class RestContext extends TransportContext { private static final TransportContext INSTANCE = @@ -38,19 +39,26 @@ public abstract class RestContext extends TransportContext { .setCallSettingsClass(HttpJsonCallSettings.class) .setStubCallableFactoryType(classToType(HttpJsonStubCallableFactory.class)) .setMethodDescriptorClass(ApiMethodDescriptor.class) - .setTransportOperationsStubType(classToType(HttpJsonOperationsStub.class)) - .setTransportOperationsStubName("httpJsonOperationsStub") + .setTransportOperationsStubTypes( + ImmutableList.of(classToType(HttpJsonOperationsStub.class))) + .setTransportOperationsStubNames(ImmutableList.of("httpJsonOperationsStub")) // For httpjson.ServiceSettingsClassComposer - .setInstantiatingChannelProviderClass(InstantiatingHttpJsonChannelProvider.Builder.class) - .setDefaultTransportProviderBuilderName("defaultHttpJsonTransportProviderBuilder") + .setInstantiatingChannelProviderClasses( + ImmutableList.of(InstantiatingHttpJsonChannelProvider.class)) + .setInstantiatingChannelProviderBuilderClasses( + ImmutableList.of(InstantiatingHttpJsonChannelProvider.Builder.class)) + .setDefaultTransportProviderBuilderNames( + ImmutableList.of("defaultHttpJsonTransportProviderBuilder")) + .setTransportApiClientHeaderProviderBuilderNames( + ImmutableList.of("defaultHttpJsonApiClientHeaderProviderBuilder")) // For httpjson.ServiceStubSettingsClassComposer - .setTransportChannelType(classToType(HttpJsonTransportChannel.class)) - .setTransportGetterName("getHttpJsonTransportName") + .setTransportChannelTypes(ImmutableList.of(classToType(HttpJsonTransportChannel.class))) + .setTransportGetterNames(ImmutableList.of("getHttpJsonTransportName")) // For httpjson.HttpJsonServiceCallableFactoryClassComposer .setTransportCallSettingsType(classToType(HttpJsonCallSettings.class)) .setTransportCallableFactoryType(classToType(HttpJsonCallableFactory.class)) // TODO: set to com.google.api.gax.httpjson.longrunning.stub.OperationsStub.class - .setOperationsStubType(classToType(BackgroundResource.class)) + .setOperationsStubTypes(ImmutableList.of(classToType(BackgroundResource.class))) .setTransportCallSettingsName("httpJsonCallSettings") // For RetrySettingsComposer .setOperationResponseTransformerType( @@ -58,8 +66,8 @@ public abstract class RestContext extends TransportContext { .setOperationMetadataTransformerType( classToType(ProtoOperationTransformers.MetadataTransformer.class)) // For ServiceClientClassComposer - .setOperationsClientType(classToType(OperationsClient.class)) - .setOperationsClientName("httpJsonOperationsClient") + .setOperationsClientTypes(ImmutableList.of(classToType(OperationsClient.class))) + .setOperationsClientNames(ImmutableList.of("httpJsonOperationsClient")) .build(); public static TransportContext instance() { diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java index 868955f379..893777e057 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java @@ -73,7 +73,7 @@ protected ServiceClientTestClassComposer() { super(RestContext.instance()); } - public static ServiceClientTestClassComposer instance() { + public static AbstractServiceClientTestClassComposer instance() { return INSTANCE; } @@ -126,7 +126,8 @@ protected MethodDefinition createStartStaticServerMethod( Service service, GapicContext context, Map classMemberVarExprs, - TypeStore typeStore) { + TypeStore typeStore, + String newBuilderMethod) { VariableExpr mockServiceVarExpr = classMemberVarExprs.get(MOCK_SERVICE_VAR_NAME); VariableExpr clientVarExpr = classMemberVarExprs.get(CLIENT_VAR_NAME); @@ -168,7 +169,7 @@ protected MethodDefinition createStartStaticServerMethod( Expr settingsBuilderExpr = MethodInvocationExpr.builder() .setStaticReferenceType(settingsType) - .setMethodName("newBuilder") + .setMethodName(newBuilderMethod) .build(); Expr transportChannelProviderExpr = diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java index 9375399546..b12528ec3f 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java @@ -17,23 +17,16 @@ import com.google.api.gax.httpjson.GaxHttpJsonProperties; import com.google.api.gax.httpjson.HttpJsonTransportChannel; import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.generator.engine.ast.AnnotationNode; -import com.google.api.generator.engine.ast.ConcreteReference; import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.ScopeNode; -import com.google.api.generator.engine.ast.StringObjectValue; import com.google.api.generator.engine.ast.TypeNode; -import com.google.api.generator.engine.ast.ValueExpr; -import com.google.api.generator.engine.ast.Variable; -import com.google.api.generator.engine.ast.VariableExpr; -import com.google.api.generator.gapic.composer.comment.SettingsCommentComposer; import com.google.api.generator.gapic.composer.common.AbstractServiceStubSettingsClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; -import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Service; import java.util.Arrays; +import java.util.Collections; +import java.util.List; public class ServiceStubSettingsClassComposer extends AbstractServiceStubSettingsClassComposer { private static final ServiceStubSettingsClassComposer INSTANCE = @@ -58,94 +51,16 @@ private static TypeStore createStaticTypes() { } @Override - protected MethodDefinition createDefaultTransportTransportProviderBuilderMethod() { - // Create the defaultHttpJsonTransportProviderBuilder method. - TypeNode returnType = - TypeNode.withReference( - ConcreteReference.withClazz(InstantiatingHttpJsonChannelProvider.Builder.class)); - MethodInvocationExpr transportChannelProviderBuilderExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get( - InstantiatingHttpJsonChannelProvider.class.getSimpleName())) - .setMethodName("newBuilder") - .setReturnType(returnType) - .build(); - return MethodDefinition.builder() - .setHeaderCommentStatements( - SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setReturnType(returnType) - .setName("defaultHttpJsonTransportProviderBuilder") - .setReturnExpr(transportChannelProviderBuilderExpr) - .build(); - } - - @Override - protected MethodDefinition createDefaultApiClientHeaderProviderBuilderMethod( + protected List createApiClientHeaderProviderBuilderMethods( Service service, TypeStore typeStore) { - // Create the defaultApiClientHeaderProviderBuilder method. - TypeNode returnType = - TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); - MethodInvocationExpr returnExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("ApiClientHeaderProvider")) - .setMethodName("newBuilder") - .build(); - - MethodInvocationExpr versionArgExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GaxProperties")) - .setMethodName("getLibraryVersion") - .setArguments( - VariableExpr.builder() - .setVariable( - Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) - .setStaticReferenceType( - typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) - .build()) - .build(); - - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setGeneratedLibToken") - .setArguments(ValueExpr.withValue(StringObjectValue.withValue("gapic")), versionArgExpr) - .build(); - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setTransportToken") - .setArguments( - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get(GaxHttpJsonProperties.class.getSimpleName())) - .setMethodName("getHttpJsonTokenName") - .build(), - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get(GaxHttpJsonProperties.class.getSimpleName())) - .setMethodName("getHttpJsonVersion") - .build()) - .setReturnType(returnType) - .build(); - - AnnotationNode annotation = - AnnotationNode.builder() - .setType(FIXED_TYPESTORE.get("BetaApi")) - .setDescription( - "The surface for customizing headers is not stable yet and may change in the" - + " future.") - .build(); - return MethodDefinition.builder() - .setAnnotations(Arrays.asList(annotation)) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setReturnType(returnType) - .setName("defaultApiClientHeaderProviderBuilder") - .setReturnExpr(returnExpr) - .build(); + return Collections.singletonList( + createApiClientHeaderProviderBuilderMethod( + service, + typeStore, + "defaultApiClientHeaderProviderBuilder", + FIXED_REST_TYPESTORE.get(GaxHttpJsonProperties.class.getSimpleName()), + "getHttpJsonTokenName", + "getHttpJsonVersion")); } @Override diff --git a/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java b/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java index f1abb45a4c..c0b717fc0a 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java +++ b/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java @@ -15,6 +15,9 @@ package com.google.api.generator.gapic.composer.utils; import com.google.api.generator.gapic.model.Service; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; /** Provides Gapic class names. */ public class ClassNames { @@ -23,6 +26,7 @@ public class ClassNames { private static final String MOCK_SERVICE_IMPL_CLASS_NAME_PATTERN = "Mock%sImpl"; private static final String SERVICE_CLIENT_CLASS_NAME_PATTERN = "%sClient"; private static final String SERVICE_CLIENT_TEST_CLASS_NAME_PATTERN = "%sClientTest"; + private static final String SERVICE_CLIENT_TRANSPORT_TEST_CLASS_NAME_PATTERN = "%sClient%sTest"; private static final String SERVICE_SETTINGS_CLASS_NAME_PATTERN = "%sSettings"; private static final String SERVICE_STUB_SETTINGS_CLASS_NAME_PATTERN = "%sStubSettings"; private static final String SERVICE_STUB_CLASS_NAME_PATTERN = "%sStub"; @@ -30,10 +34,10 @@ public class ClassNames { private static final String TRANSPORT_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN = "%s%sCallableFactory"; - private final String transportPrefix; + private final List transportPrefixes; - public ClassNames(String transportPrefix) { - this.transportPrefix = transportPrefix; + public ClassNames(String... transportPrefixes) { + this.transportPrefixes = Arrays.asList(transportPrefixes); } public static String getServiceClientClassName(Service service) { @@ -59,23 +63,50 @@ public static String getServiceStubClassName(Service service) { } public String getTransportServiceCallableFactoryClassName(Service service) { - return String.format( - TRANSPORT_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN, - transportPrefix, - monolithBackwardsCompatibleName(service.name())); + return getTransportServiceCallableFactoryClassNames(service).get(0); + } + + public List getTransportServiceCallableFactoryClassNames(Service service) { + return transportPrefixes.stream() + .map( + prefix -> + String.format( + TRANSPORT_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN, + prefix, + monolithBackwardsCompatibleName(service.name()))) + .collect(Collectors.toList()); } public String getTransportServiceStubClassName(Service service) { - return String.format( - TRANSPORT_SERVICE_STUB_CLASS_NAME_PATTERN, - transportPrefix, - monolithBackwardsCompatibleName(service.name())); + return getTransportServiceStubClassNames(service).get(0); + } + + public List getTransportServiceStubClassNames(Service service) { + return transportPrefixes.stream() + .map( + prefix -> + String.format( + TRANSPORT_SERVICE_STUB_CLASS_NAME_PATTERN, + prefix, + monolithBackwardsCompatibleName(service.name()))) + .collect(Collectors.toList()); } public static String getServiceClientTestClassName(Service service) { return String.format(SERVICE_CLIENT_TEST_CLASS_NAME_PATTERN, service.overriddenName()); } + public List getServiceClientTestClassNames(Service service) { + return transportPrefixes.stream() + .map( + prefix -> + String.format( + SERVICE_CLIENT_TRANSPORT_TEST_CLASS_NAME_PATTERN, + service.overriddenName(), + prefix)) + .collect(Collectors.toList()); + } + public static String getMockServiceClassName(Service service) { return String.format(MOCK_SERVICE_CLASS_NAME_PATTERN, service.name()); } diff --git a/src/main/java/com/google/api/generator/gapic/model/Transport.java b/src/main/java/com/google/api/generator/gapic/model/Transport.java index aeb7b9361c..ae7820c8ed 100644 --- a/src/main/java/com/google/api/generator/gapic/model/Transport.java +++ b/src/main/java/com/google/api/generator/gapic/model/Transport.java @@ -17,8 +17,6 @@ public enum Transport { REST, GRPC, - // Never used in the context as is, must be split into two contexts (REST and GRPC respectively) - // instead. GRPC_REST; /** diff --git a/src/test/java/com/google/api/generator/gapic/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/BUILD.bazel index 40de9b259f..5c5f8983ad 100644 --- a/src/test/java/com/google/api/generator/gapic/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/BUILD.bazel @@ -6,6 +6,7 @@ filegroup( "//src/test/java/com/google/api/generator/gapic/composer:composer_files", "//src/test/java/com/google/api/generator/gapic/composer/defaultvalue:defaultvalue_files", "//src/test/java/com/google/api/generator/gapic/composer/grpc:grpc_files", + # "//src/test/java/com/google/api/generator/gapic/composer/grpcrest:grpcrest_files", "//src/test/java/com/google/api/generator/gapic/composer/resourcename:resourcename_files", "//src/test/java/com/google/api/generator/gapic/composer/rest:rest_files", "//src/test/java/com/google/api/generator/gapic/composer/samplecode:samplecode_files",