From 200fce7eb91db005524d722a09656fccb7a040cd Mon Sep 17 00:00:00 2001 From: Vadym Matsishevskyi <25311427+vam-google@users.noreply.github.com> Date: Tue, 7 Sep 2021 00:30:29 -0700 Subject: [PATCH] chore: Merge multitransport client and fixes (#836) * feat: enable self signed jwt for gapic clients (#794) * feat: enable self signed jwt for gapic clients * resolve comments * update gax version * update goldens * update golden files * chore: release 2.1.0 (#827) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> * feat: REGAPIC initial implementation (#824) This includes: 1) Proper GRPC transcoding 2) Mimimal REST Operations (go make it compilable) 3) Rely on resource names for tests values generation (to not fail http url path validation) 4) Empty Server Streaming method implementation * 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 * chore: merge DIREGAPIC LRO with multitransport changes from master * fix: fix Stub.longRunningClient() issues for DIREGAPIC LRO * fix: [bazel] fix rest transport handling in assembly rule (#835) Co-authored-by: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- WORKSPACE | 2 +- repositories.bzl | 4 +- rules_java_gapic/java_gapic.bzl | 30 +- rules_java_gapic/java_gapic_pkg.bzl | 8 +- .../resources/gradle/assembly.gradle.tmpl | 4 +- .../resources/gradle/client_grpc.gradle.tmpl | 4 +- .../gradle/client_grpcrest.gradle.tmpl | 63 + .../resources/gradle/client_rest.gradle.tmpl | 4 +- .../resources/gradle/grpc.gradle.tmpl | 4 +- .../resources/gradle/proto.gradle.tmpl | 4 +- .../google/api/generator/gapic/BUILD.bazel | 1 + .../api/generator/gapic/composer/BUILD.bazel | 1 + .../generator/gapic/composer/Composer.java | 94 +- ...ctServiceCallableFactoryClassComposer.java | 2 +- ...> AbstractServiceClientClassComposer.java} | 146 ++- ...bstractServiceClientTestClassComposer.java | 19 +- .../AbstractServiceSettingsClassComposer.java | 76 +- .../AbstractServiceStubClassComposer.java | 1058 +++------------- ...tractServiceStubSettingsClassComposer.java | 288 ++++- ...ractTransportServiceStubClassComposer.java | 1077 +++++++++++++++++ .../common/RetrySettingsComposer.java | 14 +- .../common/ServiceStubClassComposer.java | 283 ----- .../composer/common/TransportContext.java | 68 +- .../defaultvalue/DefaultValueComposer.java | 26 +- .../gapic/composer/grpc/GrpcContext.java | 30 +- .../grpc/GrpcServiceStubClassComposer.java | 17 +- .../grpc/ServiceClientClassComposer.java | 30 + .../grpc/ServiceClientTestClassComposer.java | 9 +- .../grpc/ServiceStubClassComposer.java | 30 + .../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 | 16 +- .../HttpJsonServiceStubClassComposer.java | 268 ++-- .../gapic/composer/rest/RestContext.java | 33 +- .../rest/ServiceClientClassComposer.java | 30 + .../rest/ServiceClientTestClassComposer.java | 27 +- .../rest/ServiceStubClassComposer.java | 30 + .../ServiceStubSettingsClassComposer.java | 107 +- .../ServiceClientSampleCodeComposer.java | 2 +- .../gapic/composer/utils/ClassNames.java | 53 +- .../generator/gapic/model/HttpBindings.java | 4 + .../api/generator/gapic/model/Service.java | 18 + .../api/generator/gapic/model/Transport.java | 2 - .../gapic/protoparser/HttpRuleParser.java | 1 + .../google/api/generator/gapic/BUILD.bazel | 1 + .../gapic/composer/common/BUILD.bazel | 2 - .../common/RetrySettingsComposerTest.java | 5 +- .../generator/gapic/composer/grpc/BUILD.bazel | 2 + .../ServiceClientClassComposerTest.java | 10 +- .../ServiceStubClassComposerTest.java | 3 +- .../goldens/BookshopClient.golden | 0 .../goldens/DeprecatedServiceClient.golden | 0 .../goldens/DeprecatedServiceStub.golden | 0 .../goldens/EchoClient.golden | 0 .../{common => grpc}/goldens/EchoStub.golden | 0 .../goldens/IdentityClient.golden | 0 .../ServiceStubSettingsClassComposerTest.java | 2 +- .../goldens/ComplianceStubSettings.golden | 531 ++------ .../HttpJsonComplianceCallableFactory.golden | 16 +- .../goldens/HttpJsonComplianceStub.golden | 3 +- .../cloud/compute/v1/AddressesClient.java | 4 + .../compute/v1/RegionOperationsClient.java | 106 ++ .../v1/RegionOperationsClientTest.java | 69 ++ .../compute/v1/RegionOperationsSettings.java | 10 + .../cloud/compute/v1/gapic_metadata.json | 3 + .../cloud/compute/v1/stub/AddressesStub.java | 4 - .../v1/stub/AddressesStubSettings.java | 2 +- .../v1/stub/HttpJsonAddressesStub.java | 9 +- ...tpJsonRegionOperationsCallableFactory.java | 16 +- .../v1/stub/HttpJsonRegionOperationsStub.java | 48 + .../compute/v1/stub/RegionOperationsStub.java | 12 + .../v1/stub/RegionOperationsStubSettings.java | 30 +- 79 files changed, 3410 insertions(+), 2173 deletions(-) create mode 100644 rules_java_gapic/resources/gradle/client_grpcrest.gradle.tmpl rename src/main/java/com/google/api/generator/gapic/composer/common/{ServiceClientClassComposer.java => AbstractServiceClientClassComposer.java} (94%) create mode 100644 src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java delete mode 100644 src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposer.java 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 create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubClassComposer.java rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/ServiceClientClassComposerTest.java (89%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/ServiceStubClassComposerTest.java (94%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/BookshopClient.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/DeprecatedServiceClient.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/DeprecatedServiceStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/EchoClient.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/EchoStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/IdentityClient.golden (100%) diff --git a/WORKSPACE b/WORKSPACE index cc406611a9..50cac18478 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -33,7 +33,7 @@ jvm_maven_import_external( # which in its turn, prioritizes actual generated clients runtime dependencies # over the generator dependencies. -_gax_java_version = "2.3.0" +_gax_java_version = "2.4.0" http_archive( name = "com_google_api_gax_java", diff --git a/repositories.bzl b/repositories.bzl index f2074f578d..6091b21171 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -70,9 +70,9 @@ def gapic_generator_java_repositories(): _maybe( http_archive, name = "com_google_googleapis_discovery", - strip_prefix = "googleapis-discovery-2872d382ff767518e63d59ececf5d6f9224b21b4", + strip_prefix = "googleapis-discovery-bb8a053b93ef8698297c41634aa9201f7e075277", urls = [ - "https://github.com/vam-google/googleapis-discovery/archive/2872d382ff767518e63d59ececf5d6f9224b21b4.zip", + "https://github.com/vam-google/googleapis-discovery/archive/bb8a053b93ef8698297c41634aa9201f7e075277.zip", ], ) 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..eb109db524 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 == "grpc": 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/assembly.gradle.tmpl b/rules_java_gapic/resources/gradle/assembly.gradle.tmpl index 3c0e59ee69..336a7a5c05 100644 --- a/rules_java_gapic/resources/gradle/assembly.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/assembly.gradle.tmpl @@ -12,8 +12,8 @@ subprojects { apply plugin: 'java' apply plugin: 'maven' - sourceCompatibility = 1.7 - targetCompatibility = 1.7 + sourceCompatibility = 1.8 + targetCompatibility = 1.8 test { testLogging { diff --git a/rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl b/rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl index 137f38d6f2..5ed53f6401 100644 --- a/rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl @@ -9,8 +9,8 @@ apply plugin: 'java' description = 'GAPIC library for {{name}}' group = 'com.google.cloud' version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() 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/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl b/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl index ef16323736..20fab62963 100644 --- a/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl @@ -9,8 +9,8 @@ apply plugin: 'java' description = 'GAPIC library for {{name}}' group = 'com.google.cloud' version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/rules_java_gapic/resources/gradle/grpc.gradle.tmpl b/rules_java_gapic/resources/gradle/grpc.gradle.tmpl index d5dfa3f3de..fbae0add76 100644 --- a/rules_java_gapic/resources/gradle/grpc.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/grpc.gradle.tmpl @@ -9,8 +9,8 @@ apply plugin: 'java' description = 'GRPC library for {{name}}' group = 'com.google.api.grpc' version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/rules_java_gapic/resources/gradle/proto.gradle.tmpl b/rules_java_gapic/resources/gradle/proto.gradle.tmpl index ad5e20fc33..27f0bf8448 100644 --- a/rules_java_gapic/resources/gradle/proto.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/proto.gradle.tmpl @@ -9,8 +9,8 @@ apply plugin: 'java' description = 'PROTO library for {{name}}' group = 'com.google.api.grpc' version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() 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 5c191b0a27..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,22 +15,21 @@ 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.common.ServiceClientClassComposer; -import com.google.api.generator.gapic.composer.common.ServiceStubClassComposer; import com.google.api.generator.gapic.composer.grpc.GrpcServiceCallableFactoryClassComposer; import com.google.api.generator.gapic.composer.grpc.GrpcServiceStubClassComposer; import com.google.api.generator.gapic.composer.grpc.MockServiceClassComposer; import com.google.api.generator.gapic.composer.grpc.MockServiceImplClassComposer; +import com.google.api.generator.gapic.composer.grpc.ServiceClientClassComposer; import com.google.api.generator.gapic.composer.grpc.ServiceClientTestClassComposer; 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; @@ -76,8 +75,10 @@ public static List generateStubClasses(GapicContext context) { .services() .forEach( s -> { - clazzes.add(ServiceStubClassComposer.instance().generate(context, s)); if (context.transport() == Transport.REST) { + clazzes.add( + com.google.api.generator.gapic.composer.rest.ServiceStubClassComposer.instance() + .generate(context, s)); clazzes.add( com.google.api.generator.gapic.composer.rest.ServiceStubSettingsClassComposer .instance() @@ -85,11 +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; @@ -101,14 +121,27 @@ public static List generateClientSettingsClasses(GapicContext contex .services() .forEach( s -> { - clazzes.add(ServiceClientClassComposer.instance().generate(context, s)); if (context.transport() == Transport.REST) { + clazzes.add( + com.google.api.generator.gapic.composer.rest.ServiceClientClassComposer + .instance() + .generate(context, s)); clazzes.add( 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; @@ -120,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)); } @@ -129,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 ea3898051c..f4e31a962e 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 @@ -299,7 +299,7 @@ protected MethodDefinition createGenericCallableMethod( protected TypeNode getOperationsStubType(Service service) { TypeNode opeationsStubType = service.operationServiceStubType(); if (opeationsStubType == null) { - opeationsStubType = getTransportContext().operationsStubType(); + opeationsStubType = getTransportContext().operationsStubTypes().get(0); } return opeationsStubType; } diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java similarity index 94% rename from src/main/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java index 4f804822f1..6a9ec1b17a 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java @@ -85,19 +85,21 @@ 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; import java.util.stream.Collectors; import javax.annotation.Generated; -public class ServiceClientClassComposer implements ClassComposer { - private static final ServiceClientClassComposer INSTANCE = new ServiceClientClassComposer(); +public abstract class AbstractServiceClientClassComposer implements ClassComposer { private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; private static final String CALLABLE_NAME_PATTERN = "%sCallable"; private static final String PAGED_CALLABLE_NAME_PATTERN = "%sPagedCallable"; @@ -115,10 +117,14 @@ private enum CallableMethodKind { PAGED, } - private ServiceClientClassComposer() {} + private final TransportContext transportContext; - public static ServiceClientClassComposer instance() { - return INSTANCE; + protected AbstractServiceClientClassComposer(TransportContext transportContext) { + this.transportContext = transportContext; + } + + protected TransportContext getTransportContext() { + return transportContext; } @Override @@ -129,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 = exposeOperationsClient(service); + boolean hasLroClient = service.hasStandardLroMethods(); Map> grpcRpcsToJavaMethodNames = new HashMap<>(); @@ -198,7 +204,7 @@ private static List createClassHeaderComments( service, classMethodSampleCode, credentialsSampleCode, endpointSampleCode); } - private static List createClassMethods( + private List createClassMethods( Service service, Map messageTypes, TypeStore typeStore, @@ -216,23 +222,19 @@ private static List createClassMethods( return methods; } - private static boolean exposeOperationsClient(Service service) { - for (Method method : service.methods()) { - if (method.hasLro() && method.lro().operationServiceStubType() == null) { - return true; - } - } - return false; - } - - private static List createFieldDeclarations( + private List createFieldDeclarations( Service service, TypeStore typeStore, boolean hasLroClient) { Map fieldNameToTypes = new HashMap<>(); fieldNameToTypes.put( "settings", typeStore.get(ClassNames.getServiceSettingsClassName(service))); fieldNameToTypes.put("stub", typeStore.get(ClassNames.getServiceStubClassName(service))); if (hasLroClient) { - fieldNameToTypes.put("operationsClient", typeStore.get("OperationsClient")); + 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() @@ -352,14 +354,13 @@ private static List createStaticCreatorMethods( return methods; } - private static List createConstructorMethods( + private List createConstructorMethods( Service service, TypeStore typeStore, boolean hasLroClient) { List methods = new ArrayList<>(); String thisClientName = ClassNames.getServiceClientClassName(service); String settingsName = ClassNames.getServiceSettingsClassName(service); TypeNode thisClassType = typeStore.get(thisClientName); TypeNode stubSettingsType = typeStore.get(ClassNames.getServiceStubSettingsClassName(service)); - TypeNode operationsClientType = typeStore.get("OperationsClient"); TypeNode exceptionType = typeStore.get("IOException"); TypeNode settingsType = typeStore.get(settingsName); @@ -372,9 +373,6 @@ private static List createConstructorMethods( .setType(typeStore.get(ClassNames.getServiceStubClassName(service))) .setName("stub") .build()); - VariableExpr operationsClientVarExpr = - VariableExpr.withVariable( - Variable.builder().setType(operationsClientType).setName("operationsClient").build()); // Create the ServiceClient(ServiceSettings settings) ctor. List ctorAssignmentExprs = new ArrayList<>(); @@ -404,25 +402,10 @@ private static List createConstructorMethods( .build()) .build()); - Expr clientArgExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(stubVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setMethodName("getOperationsStub") - .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( @@ -453,7 +436,7 @@ private static List createConstructorMethods( .setValueExpr(stubVarExpr) .build()); if (hasLroClient) { - ctorAssignmentExprs.add(operationsClientAssignExpr); + ctorAssignmentExprs.addAll(operationsClientAssignExprs); } AnnotationNode betaAnnotation = AnnotationNode.builder() @@ -476,15 +459,70 @@ private static List createConstructorMethods( return methods; } - private static List createGetterMethods( + 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 = "getOperationsClient"; + + Set getOperationsClientMethodNames = new HashSet<>(); + if (hasLroClient) { - methodNameToTypes.put(getOperationsClientMethodName, typeStore.get("OperationsClient")); + 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() @@ -500,7 +538,7 @@ private static 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); @@ -708,6 +746,7 @@ private static MethodDefinition createMethodDefaultMethod( method.isPaged() ? typeStore.get(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, method.name())) : method.outputType(); + List annotations = new ArrayList<>(); if (method.hasLro()) { LongrunningOperation lro = method.lro(); methodOutputType = @@ -718,6 +757,13 @@ private static MethodDefinition createMethodDefaultMethod( .copyAndSetGenerics( Arrays.asList( lro.responseType().reference(), lro.metadataType().reference()))); + if (method.hasLro() && method.lro().operationServiceStubType() != null) { + annotations.add( + AnnotationNode.withTypeAndDescription( + typeStore.get("BetaApi"), + "The surface for long-running operations is not stable yet and may change in the" + + " future.")); + } } // Construct the method that accepts a request proto. @@ -759,8 +805,7 @@ private static MethodDefinition createMethodDefaultMethod( .setArguments(Arrays.asList(requestArgVarExpr)); if (method.isDeprecated()) { - methodBuilder = - methodBuilder.setAnnotations(Arrays.asList(AnnotationNode.withType(TypeNode.DEPRECATED))); + annotations.add(AnnotationNode.withType(TypeNode.DEPRECATED)); } if (isProtoEmptyType(methodOutputType)) { @@ -772,6 +817,9 @@ private static MethodDefinition createMethodDefaultMethod( methodBuilder = methodBuilder.setReturnExpr(callableMethodExpr).setReturnType(methodOutputType); } + + methodBuilder.setAnnotations(annotations); + return methodBuilder.build(); } @@ -1681,8 +1729,6 @@ private static void createVaporTypes(Service service, TypeStore typeStore) { ClassNames.getServiceClientClassName(service)); } - // LRO Gapic-generated types. - typeStore.put("com.google.longrunning", "OperationsClient"); // Pagination types. typeStore.putAll( service.pakkage(), 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 7d01cfbca3..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); @@ -470,7 +474,7 @@ private MethodDefinition createRpcTestMethod( VariableExpr.withVariable( Variable.builder().setType(methodArg.type()).setName(methodArgName).build()); argExprs.add(varExpr); - Expr valExpr = DefaultValueComposer.createDefaultValue(methodArg, resourceNames); + Expr valExpr = createDefaultValue(methodArg, resourceNames); methodExprs.add( AssignmentExpr.builder() .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) @@ -735,6 +739,9 @@ protected abstract List createStreamingRpcExceptionTestStatements( Map resourceNames, Map messageTypes); + protected abstract Expr createDefaultValue( + MethodArgument methodArg, Map resourceNames); + protected List createRpcExceptionTestStatements( Method method, List methodSignature, @@ -766,7 +773,7 @@ protected List createRpcExceptionTestStatements( VariableExpr.withVariable( Variable.builder().setType(methodArg.type()).setName(methodArgName).build()); argVarExprs.add(varExpr); - Expr valExpr = DefaultValueComposer.createDefaultValue(methodArg, resourceNames); + Expr valExpr = createDefaultValue(methodArg, resourceNames); tryBodyExprs.add( AssignmentExpr.builder() .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) 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 8935e0b00c..c54ccbde39 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 @@ -16,39 +16,27 @@ import com.google.api.core.BetaApi; import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.core.BackgroundResourceAggregation; import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientContext; import com.google.api.gax.rpc.ClientStreamingCallable; +import com.google.api.gax.rpc.LongRunningClient; import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.RequestParamsExtractor; import com.google.api.gax.rpc.ServerStreamingCallable; import com.google.api.gax.rpc.UnaryCallable; import com.google.api.generator.engine.ast.AnnotationNode; -import com.google.api.generator.engine.ast.AssignmentExpr; import com.google.api.generator.engine.ast.ClassDefinition; -import com.google.api.generator.engine.ast.CommentStatement; import com.google.api.generator.engine.ast.ConcreteReference; -import com.google.api.generator.engine.ast.EmptyLineStatement; -import com.google.api.generator.engine.ast.Expr; import com.google.api.generator.engine.ast.ExprStatement; -import com.google.api.generator.engine.ast.JavaDocComment; import com.google.api.generator.engine.ast.MethodDefinition; -import com.google.api.generator.engine.ast.MethodInvocationExpr; -import com.google.api.generator.engine.ast.NewObjectExpr; -import com.google.api.generator.engine.ast.ReferenceConstructorExpr; +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.ThisObjectValue; import com.google.api.generator.engine.ast.ThrowExpr; -import com.google.api.generator.engine.ast.TryCatchStatement; import com.google.api.generator.engine.ast.TypeNode; -import com.google.api.generator.engine.ast.ValueExpr; -import com.google.api.generator.engine.ast.VaporReference; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.gapic.composer.comment.StubCommentComposer; import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.composer.utils.PackageChecker; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicClass.Kind; @@ -57,40 +45,20 @@ import com.google.api.generator.gapic.model.Method; 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.common.collect.ImmutableMap; import com.google.longrunning.Operation; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.function.BiFunction; -import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.Generated; public abstract class AbstractServiceStubClassComposer implements ClassComposer { - private static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create(); - - private static final String METHOD_DESCRIPTOR_NAME_PATTERN = "%sMethodDescriptor"; + private static final String DOT = "."; private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; - private static final String PAGED_CALLABLE_CLASS_MEMBER_PATTERN = "%sPagedCallable"; - - private static final String BACKGROUND_RESOURCES_MEMBER_NAME = "backgroundResources"; - private static final String CALLABLE_NAME = "Callable"; - private static final String CALLABLE_FACTORY_MEMBER_NAME = "callableFactory"; - private static final String CALLABLE_CLASS_MEMBER_PATTERN = "%sCallable"; - private static final String OPERATION_CALLABLE_CLASS_MEMBER_PATTERN = "%sOperationCallable"; - private static final String OPERATION_CALLABLE_NAME = "OperationCallable"; - private static final String OPERATIONS_STUB_MEMBER_NAME = "operationsStub"; - private static final String PAGED_CALLABLE_NAME = "PagedCallable"; - - protected static final TypeStore FIXED_TYPESTORE = createStaticTypes(); private final TransportContext transportContext; @@ -98,271 +66,38 @@ protected AbstractServiceStubClassComposer(TransportContext transportContext) { this.transportContext = transportContext; } - public TransportContext getTransportContext() { + protected TransportContext getTransportContext() { return transportContext; } - private static TypeStore createStaticTypes() { - List concreteClazzes = - Arrays.asList( - BackgroundResource.class, - BackgroundResourceAggregation.class, - BetaApi.class, - BidiStreamingCallable.class, - ClientContext.class, - ClientStreamingCallable.class, - Generated.class, - ImmutableMap.class, - InterruptedException.class, - IOException.class, - Operation.class, - OperationCallable.class, - RequestParamsExtractor.class, - ServerStreamingCallable.class, - TimeUnit.class, - UnaryCallable.class); - return new TypeStore(concreteClazzes); - } - @Override public GapicClass generate(GapicContext context, Service service) { - String pakkage = service.pakkage() + ".stub"; - TypeStore typeStore = createDynamicTypes(service, pakkage); - String className = getTransportContext().classNames().getTransportServiceStubClassName(service); - GapicClass.Kind kind = Kind.STUB; - - Map protoMethodNameToDescriptorVarExprs = - createProtoMethodNameToDescriptorClassMembers( - service, getTransportContext().methodDescriptorClass()); - - Map callableClassMemberVarExprs = - createCallableClassMembers(service, typeStore); - - Map classMemberVarExprs = new LinkedHashMap<>(); - classMemberVarExprs.put( - BACKGROUND_RESOURCES_MEMBER_NAME, - VariableExpr.withVariable( - Variable.builder() - .setName(BACKGROUND_RESOURCES_MEMBER_NAME) - .setType(FIXED_TYPESTORE.get("BackgroundResource")) - .build())); - - - TypeNode opeationsStubType = getTransportOperationsStubType(service); - if (opeationsStubType != null) { - classMemberVarExprs.put( - OPERATIONS_STUB_MEMBER_NAME, - VariableExpr.withVariable( - Variable.builder() - .setName(OPERATIONS_STUB_MEMBER_NAME) - .setType(opeationsStubType) - .build())); - } - - boolean operationPollingMethod = checkOperationPollingMethod(service); - if(operationPollingMethod) { - VariableExpr longRunningVarExpr = declareLongRunningClient(); - if (longRunningVarExpr != null) { - classMemberVarExprs.put("longRunningClient", longRunningVarExpr); - } - } - - classMemberVarExprs.put( - CALLABLE_FACTORY_MEMBER_NAME, - VariableExpr.withVariable( - Variable.builder() - .setName(CALLABLE_FACTORY_MEMBER_NAME) - .setType(getTransportContext().stubCallableFactoryType()) - .build())); - Map messageTypes = context.messages(); - List classStatements = - createClassStatements( - service, - protoMethodNameToDescriptorVarExprs, - callableClassMemberVarExprs, - classMemberVarExprs, - messageTypes); - - StubCommentComposer commentComposer = - new StubCommentComposer(getTransportContext().transportName()); + TypeStore typeStore = createTypes(service, messageTypes); + String className = ClassNames.getServiceStubClassName(service); + GapicClass.Kind kind = Kind.STUB; + String pakkage = String.format("%s.stub", service.pakkage()); ClassDefinition classDef = ClassDefinition.builder() .setPackageString(pakkage) .setHeaderCommentStatements( - commentComposer.createTransportServiceStubClassHeaderComments( + StubCommentComposer.createServiceStubClassHeaderComments( service.name(), service.isDeprecated())) - .setAnnotations(createClassAnnotations(service)) - .setScope(ScopeNode.PUBLIC) + .setAnnotations(createClassAnnotations(service, typeStore)) + .setIsAbstract(true) + .setImplementsTypes(createClassImplements(typeStore)) .setName(className) - .setExtendsType( - typeStore.get(getTransportContext().classNames().getServiceStubClassName(service))) - .setStatements(classStatements) - .setMethods( - createClassMethods( - service, - typeStore, - classMemberVarExprs, - callableClassMemberVarExprs, - protoMethodNameToDescriptorVarExprs)) + .setMethods(createClassMethods(service, messageTypes, typeStore)) + .setScope(ScopeNode.PUBLIC) .build(); return GapicClass.create(kind, classDef); } - protected abstract Statement createMethodDescriptorVariableDecl( - Service service, Method protoMethod, VariableExpr methodDescriptorVarExpr, Map messageTypes); - - protected abstract List createOperationsStubGetterMethod( - VariableExpr operationsStubVarExpr); - - protected abstract Expr createTransportSettingsInitExpr( - Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr); - - protected List createGetMethodDescriptorsMethod( - Service service, - TypeStore typeStore, - Map protoMethodNameToDescriptorVarExprs) { - return Arrays.asList(); - } - - protected List createClassStatements( - Service service, - Map protoMethodNameToDescriptorVarExprs, - Map callableClassMemberVarExprs, - Map classMemberVarExprs, - Map messageTypes) { - List classStatements = new ArrayList<>(); - for (Statement statement : - createMethodDescriptorVariableDecls(service, protoMethodNameToDescriptorVarExprs, messageTypes)) { - classStatements.add(statement); - classStatements.add(EMPTY_LINE_STATEMENT); - } - - classStatements.addAll(createClassMemberFieldDeclarations(callableClassMemberVarExprs)); - classStatements.add(EMPTY_LINE_STATEMENT); - - classStatements.addAll(createClassMemberFieldDeclarations(classMemberVarExprs)); - return classStatements; - } - - protected List createMethodDescriptorVariableDecls( - Service service, Map protoMethodNameToDescriptorVarExprs, Map messageTypes) { - return service.methods().stream() - .map( - m -> - createMethodDescriptorVariableDecl( - service, m, protoMethodNameToDescriptorVarExprs.get(m.name()), messageTypes)) - .collect(Collectors.toList()); - } - - private static List createClassMemberFieldDeclarations( - Map fieldNameToVarExprs) { - return fieldNameToVarExprs.values().stream() - .map( - v -> - ExprStatement.withExpr( - v.toBuilder() - .setIsDecl(true) - .setScope(ScopeNode.PRIVATE) - .setIsFinal(true) - .build())) - .collect(Collectors.toList()); - } - - protected Map createProtoMethodNameToDescriptorClassMembers( - Service service, Class descriptorClass) { - return service.methods().stream() - .collect( - Collectors.toMap( - Method::name, - m -> - VariableExpr.withVariable( - Variable.builder() - .setName( - String.format( - METHOD_DESCRIPTOR_NAME_PATTERN, - JavaStyle.toLowerCamelCase(m.name()))) - .setType( - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(descriptorClass) - .setGenerics( - Arrays.asList( - m.inputType().reference(), - m.outputType().reference())) - .build())) - .build()), - (u, v) -> { - throw new IllegalStateException(); - }, - LinkedHashMap::new)); - } - - private Map createCallableClassMembers( - Service service, TypeStore typeStore) { - Map callableClassMembers = new LinkedHashMap<>(); - // Using a for-loop because the output cardinality is not a 1:1 mapping to the input set. - for (Method protoMethod : service.methods()) { - String javaStyleProtoMethodName = JavaStyle.toLowerCamelCase(protoMethod.name()); - String callableName = String.format(CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); - callableClassMembers.put( - callableName, - VariableExpr.withVariable( - Variable.builder() - .setName(callableName) - .setType(getCallableType(protoMethod)) - .build())); - if (protoMethod.hasLro()) { - callableName = - String.format(OPERATION_CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); - callableClassMembers.put( - callableName, - VariableExpr.withVariable( - Variable.builder() - .setName(callableName) - .setType( - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(OperationCallable.class) - .setGenerics( - Arrays.asList( - protoMethod.inputType().reference(), - protoMethod.lro().responseType().reference(), - protoMethod.lro().metadataType().reference())) - .build())) - .build())); - } - if (protoMethod.isPaged()) { - callableName = String.format(PAGED_CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); - callableClassMembers.put( - callableName, - VariableExpr.withVariable( - Variable.builder() - .setName(callableName) - .setType( - TypeNode.withReference( - getCallableType(protoMethod) - .reference() - .copyAndSetGenerics( - Arrays.asList( - protoMethod.inputType().reference(), - typeStore - .get( - String.format( - PAGED_RESPONSE_TYPE_NAME_PATTERN, - protoMethod.name())) - .reference())))) - .build())); - } - } - return callableClassMembers; - } - - protected List createClassAnnotations(Service service) { + private static List createClassAnnotations(Service service, TypeStore typeStore) { List annotations = new ArrayList<>(); if (!PackageChecker.isGaApi(service.pakkage())) { - annotations.add(AnnotationNode.withType(FIXED_TYPESTORE.get("BetaApi"))); + annotations.add(AnnotationNode.withType(typeStore.get("BetaApi"))); } if (service.isDeprecated()) { @@ -371,589 +106,169 @@ protected List createClassAnnotations(Service service) { annotations.add( AnnotationNode.builder() - .setType(FIXED_TYPESTORE.get("Generated")) + .setType(typeStore.get("Generated")) .setDescription("by gapic-generator-java") .build()); return annotations; } - protected List createClassMethods( - Service service, - TypeStore typeStore, - Map classMemberVarExprs, - Map callableClassMemberVarExprs, - Map protoMethodNameToDescriptorVarExprs) { - List javaMethods = new ArrayList<>(); - javaMethods.addAll(createStaticCreatorMethods(service, typeStore)); - javaMethods.addAll( - createConstructorMethods( - service, - typeStore, - classMemberVarExprs, - callableClassMemberVarExprs, - protoMethodNameToDescriptorVarExprs)); - javaMethods.addAll( - createGetMethodDescriptorsMethod(service, typeStore, protoMethodNameToDescriptorVarExprs)); - javaMethods.addAll( - createOperationsStubGetterMethod(classMemberVarExprs.get(OPERATIONS_STUB_MEMBER_NAME))); - javaMethods.addAll(createCallableGetterMethods(callableClassMemberVarExprs)); - javaMethods.addAll( - createStubOverrideMethods(classMemberVarExprs.get(BACKGROUND_RESOURCES_MEMBER_NAME), service)); - return javaMethods; + private static List createClassImplements(TypeStore typeStore) { + return Arrays.asList(typeStore.get("BackgroundResource")); } - private List createStaticCreatorMethods(Service service, TypeStore typeStore) { - TypeNode creatorMethodReturnType = - typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); - Function, MethodDefinition.Builder> creatorMethodStarterFn = - argList -> - MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setIsFinal(true) - .setReturnType(creatorMethodReturnType) - .setName("create") - .setArguments( - argList.stream() - .map(v -> v.toBuilder().setIsDecl(true).build()) - .collect(Collectors.toList())) - .setThrowsExceptions( - Arrays.asList( - TypeNode.withReference(ConcreteReference.withClazz(IOException.class)))); - - Function, Expr> instantiatorExprFn = - argList -> - NewObjectExpr.builder().setType(creatorMethodReturnType).setArguments(argList).build(); - - TypeNode stubSettingsType = - typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); - VariableExpr settingsVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("settings").setType(stubSettingsType).build()); - - TypeNode clientContextType = FIXED_TYPESTORE.get("ClientContext"); - VariableExpr clientContextVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("clientContext").setType(clientContextType).build()); - - VariableExpr callableFactoryVarExpr = - VariableExpr.withVariable( - Variable.builder() - .setName("callableFactory") - .setType(getTransportContext().stubCallableFactoryType()) - .build()); - - MethodInvocationExpr clientContextCreateMethodExpr = - MethodInvocationExpr.builder() - .setMethodName("create") - .setStaticReferenceType(clientContextType) - .setArguments(Arrays.asList(settingsVarExpr)) - .build(); - MethodInvocationExpr settingsBuilderMethodExpr = - MethodInvocationExpr.builder() - .setMethodName("newBuilder") - .setStaticReferenceType(stubSettingsType) - .build(); - settingsBuilderMethodExpr = - MethodInvocationExpr.builder() - .setMethodName("build") - .setExprReferenceExpr(settingsBuilderMethodExpr) - .build(); + private List createClassMethods( + Service service, Map messageTypes, TypeStore typeStore) { + List methods = new ArrayList<>(); + if (service.hasStandardLroMethods()) { + TypeNode operationsStubType = service.operationServiceStubType(); + methods.addAll(createOperationsStubGetters(typeStore, operationsStubType)); + } - return Arrays.asList( - creatorMethodStarterFn - .apply(Arrays.asList(settingsVarExpr)) - .setReturnExpr( - instantiatorExprFn.apply( - Arrays.asList(settingsVarExpr, clientContextCreateMethodExpr))) - .build(), - creatorMethodStarterFn - .apply(Arrays.asList(clientContextVarExpr)) - .setReturnExpr( - instantiatorExprFn.apply( - Arrays.asList(settingsBuilderMethodExpr, clientContextVarExpr))) - .build(), - creatorMethodStarterFn - .apply(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) - .setReturnExpr( - instantiatorExprFn.apply( - Arrays.asList( - settingsBuilderMethodExpr, clientContextVarExpr, callableFactoryVarExpr))) - .build()); + if (service.operationPollingMethod() != null) { + methods.addAll(createLongRunningClientGetters(typeStore)); + } + methods.addAll(createCallableGetters(service, messageTypes, typeStore)); + methods.addAll(createBackgroundResourceMethodOverrides()); + return methods; } - protected List createConstructorMethods( - Service service, - TypeStore typeStore, - Map classMemberVarExprs, - Map callableClassMemberVarExprs, - Map protoMethodNameToDescriptorVarExprs) { - TypeNode stubSettingsType = - typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); - VariableExpr settingsVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("settings").setType(stubSettingsType).build()); - - TypeNode clientContextType = FIXED_TYPESTORE.get("ClientContext"); - VariableExpr clientContextVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("clientContext").setType(clientContextType).build()); - - VariableExpr callableFactoryVarExpr = - VariableExpr.withVariable( - Variable.builder() - .setName("callableFactory") - .setType(getTransportContext().stubCallableFactoryType()) - .build()); - - TypeNode thisClassType = - typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); - TypeNode ioExceptionType = - TypeNode.withReference(ConcreteReference.withClazz(IOException.class)); - - BiFunction, List, MethodDefinition> ctorMakerFn = - (args, body) -> - MethodDefinition.constructorBuilder() - .setScope(ScopeNode.PROTECTED) - .setReturnType(thisClassType) - .setHeaderCommentStatements(Arrays.asList(createProtectedCtorComment(service))) - .setArguments( - args.stream() - .map(v -> v.toBuilder().setIsDecl(true).build()) - .collect(Collectors.toList())) - .setThrowsExceptions(Arrays.asList(ioExceptionType)) - .setBody(body) - .build(); - - // First constructor method. - MethodDefinition firstCtor = - ctorMakerFn.apply( - Arrays.asList(settingsVarExpr, clientContextVarExpr), - Arrays.asList( - ExprStatement.withExpr( - ReferenceConstructorExpr.thisBuilder() - .setType(thisClassType) - .setArguments( - settingsVarExpr, - clientContextVarExpr, - NewObjectExpr.builder() - .setType( - typeStore.get( - getTransportContext() - .classNames() - .getTransportServiceCallableFactoryClassName(service))) - .build()) - .build()))); - - Expr thisExpr = - ValueExpr.withValue( - ThisObjectValue.withType( - typeStore.get( - getTransportContext().classNames().getTransportServiceStubClassName(service)))); - // Body of the second constructor method. - List secondCtorStatements = new ArrayList<>(); - List secondCtorExprs = new ArrayList<>(); - secondCtorExprs.add( - AssignmentExpr.builder() - .setVariableExpr( - classMemberVarExprs.get("callableFactory").toBuilder() - .setExprReferenceExpr(thisExpr) - .build()) - .setValueExpr(callableFactoryVarExpr) - .build()); - VariableExpr operationsStubClassVarExpr = classMemberVarExprs.get(OPERATIONS_STUB_MEMBER_NAME); - - TypeNode opeationsStubType = getTransportOperationsStubType(service); - if (opeationsStubType != null) { - secondCtorExprs.add( - AssignmentExpr.builder() - .setVariableExpr( - operationsStubClassVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType(opeationsStubType) - .setMethodName("create") - .setArguments(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) - .setReturnType(operationsStubClassVarExpr.type()) - .build()) - .build()); + 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(). + List javaMethods = new ArrayList<>(); + for (Method method : service.methods()) { + if (method.hasLro()) { + javaMethods.add(createOperationCallableGetter(method, typeStore)); + } + if (method.isPaged()) { + javaMethods.add(createPagedCallableGetter(method, typeStore)); + } + javaMethods.add(createCallableGetter(method, typeStore)); } - secondCtorStatements.addAll( - secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - secondCtorExprs.clear(); - secondCtorStatements.add(EMPTY_LINE_STATEMENT); - - // Transport settings local variables. - Map javaStyleMethodNameToTransportSettingsVarExprs = - service.methods().stream() - .collect( - Collectors.toMap( - m -> JavaStyle.toLowerCamelCase(m.name()), - m -> - VariableExpr.withVariable( - Variable.builder() - .setName( - String.format( - "%sTransportSettings", - JavaStyle.toLowerCamelCase(m.name()))) - .setType( - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(getTransportContext().callSettingsClass()) - .setGenerics( - Arrays.asList( - m.inputType().reference(), - m.outputType().reference())) - .build())) - .build()))); - - secondCtorExprs.addAll( - service.methods().stream() - .map( - m -> - createTransportSettingsInitExpr( - m, - javaStyleMethodNameToTransportSettingsVarExprs.get( - JavaStyle.toLowerCamelCase(m.name())), - protoMethodNameToDescriptorVarExprs.get(m.name()))) - .collect(Collectors.toList())); - secondCtorStatements.addAll( - secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - secondCtorExprs.clear(); - secondCtorStatements.add(EMPTY_LINE_STATEMENT); - - // Initialize Callable variables. - secondCtorExprs.addAll( - callableClassMemberVarExprs.entrySet().stream() - .map( - e -> - createCallableInitExpr( - e.getKey(), - e.getValue(), - callableFactoryVarExpr, - settingsVarExpr, - clientContextVarExpr, - operationsStubClassVarExpr, - thisExpr, - javaStyleMethodNameToTransportSettingsVarExprs)) - .collect(Collectors.toList())); - secondCtorStatements.addAll( - secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - secondCtorExprs.clear(); - secondCtorStatements.add(EMPTY_LINE_STATEMENT); - - - secondCtorStatements.addAll(createLongRunningClient(service, typeStore)); - - // Instantiate backgroundResources. - MethodInvocationExpr getBackgroundResourcesMethodExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(clientContextVarExpr) - .setMethodName("getBackgroundResources") - .build(); - - VariableExpr backgroundResourcesVarExpr = classMemberVarExprs.get("backgroundResources"); - secondCtorExprs.add( - AssignmentExpr.builder() - .setVariableExpr( - backgroundResourcesVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - NewObjectExpr.builder() - .setType(FIXED_TYPESTORE.get("BackgroundResourceAggregation")) - .setArguments(Arrays.asList(getBackgroundResourcesMethodExpr)) - .build()) - .build()); - secondCtorStatements.addAll( - secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - secondCtorExprs.clear(); - - // Second constructor method. - MethodDefinition secondCtor = - ctorMakerFn.apply( - Arrays.asList(settingsVarExpr, clientContextVarExpr, callableFactoryVarExpr), - secondCtorStatements); + return javaMethods; + } - return Arrays.asList(firstCtor, secondCtor); + private MethodDefinition createOperationCallableGetter( + Method method, TypeStore typeStore) { + return createCallableGetterHelper(method, typeStore, true, false); } - protected List createLongRunningClient(Service service, TypeStore typeStore) { - return ImmutableList.of(); + private MethodDefinition createPagedCallableGetter(Method method, TypeStore typeStore) { + return createCallableGetterHelper(method, typeStore, false, true); } - protected VariableExpr declareLongRunningClient() { - return null; + private MethodDefinition createCallableGetter(Method method, TypeStore typeStore) { + return createCallableGetterHelper(method, typeStore, false, false); } - private static Expr createCallableInitExpr( - String callableVarName, - VariableExpr callableVarExpr, - VariableExpr callableFactoryVarExpr, - VariableExpr settingsVarExpr, - VariableExpr clientContextVarExpr, - VariableExpr operationsStubClassVarExpr, - Expr thisExpr, - Map javaStyleMethodNameToTransportSettingsVarExprs) { - boolean isOperation = callableVarName.endsWith(OPERATION_CALLABLE_NAME); - boolean isPaged = callableVarName.endsWith(PAGED_CALLABLE_NAME); - int sublength = 0; - if (isOperation) { - sublength = OPERATION_CALLABLE_NAME.length(); - } else if (isPaged) { - sublength = PAGED_CALLABLE_NAME.length(); - } else { - sublength = CALLABLE_NAME.length(); - } - String javaStyleMethodName = callableVarName.substring(0, callableVarName.length() - sublength); - List creatorMethodArgVarExprs = null; - Expr transportSettingsVarExpr = - javaStyleMethodNameToTransportSettingsVarExprs.get(javaStyleMethodName); - if (transportSettingsVarExpr == null && isOperation) { - // Try again, in case the name dtection above was inaccurate. - isOperation = false; - sublength = CALLABLE_NAME.length(); - javaStyleMethodName = callableVarName.substring(0, callableVarName.length() - sublength); - transportSettingsVarExpr = - javaStyleMethodNameToTransportSettingsVarExprs.get(javaStyleMethodName); + private MethodDefinition createCallableGetterHelper( + Method method, TypeStore typeStore, boolean isLroCallable, boolean isPaged) { + TypeNode returnType; + switch (method.stream()) { + case CLIENT: + returnType = typeStore.get("ClientStreamingCallable"); + break; + case SERVER: + returnType = typeStore.get("ServerStreamingCallable"); + break; + case BIDI: + returnType = typeStore.get("BidiStreamingCallable"); + break; + case NONE: + // Fall through. + default: + returnType = typeStore.get(isLroCallable ? "OperationCallable" : "UnaryCallable"); } - Preconditions.checkNotNull( - transportSettingsVarExpr, + + String methodName = String.format( - "No transport settings variable found for method name %s", javaStyleMethodName)); - if (isOperation) { - creatorMethodArgVarExprs = - Arrays.asList( - transportSettingsVarExpr, - MethodInvocationExpr.builder() - .setExprReferenceExpr(settingsVarExpr) - .setMethodName(String.format("%sOperationSettings", javaStyleMethodName)) - .build(), - clientContextVarExpr, - operationsStubClassVarExpr); + "%s%sCallable", + JavaStyle.toLowerCamelCase(method.name()), + (isLroCallable ? "Operation" : isPaged ? "Paged" : "")); + List genericRefs = new ArrayList<>(); + genericRefs.add(method.inputType().reference()); + if (method.hasLro() && isLroCallable) { + genericRefs.add(method.lro().responseType().reference()); + genericRefs.add(method.lro().metadataType().reference()); + } else if (isPaged) { + genericRefs.add( + typeStore + .get(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, method.name())) + .reference()); } else { - creatorMethodArgVarExprs = - Arrays.asList( - transportSettingsVarExpr, - MethodInvocationExpr.builder() - .setExprReferenceExpr(settingsVarExpr) - .setMethodName(String.format("%sSettings", javaStyleMethodName)) - .build(), - clientContextVarExpr); + genericRefs.add(method.outputType().reference()); } - String callableCreatorMethodName = getCallableCreatorMethodName(callableVarExpr.type()); - return AssignmentExpr.builder() - .setVariableExpr(callableVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(callableFactoryVarExpr) - .setMethodName(callableCreatorMethodName) - .setArguments(creatorMethodArgVarExprs) - .setReturnType(callableVarExpr.type()) - .build()) - .build(); - } - - private static String getCallableCreatorMethodName(TypeNode callableVarExprType) { - final String typeName = callableVarExprType.reference().name(); - String streamName = "Unary"; + List annotations = + method.isDeprecated() + ? Arrays.asList(AnnotationNode.withType(TypeNode.DEPRECATED)) + : Collections.emptyList(); - // Special handling for pagination methods. - if (callableVarExprType.reference().generics().size() == 2 - && callableVarExprType.reference().generics().get(1).name().endsWith("PagedResponse")) { - streamName = "Paged"; - } else { - if (typeName.startsWith("Client")) { - streamName = "ClientStreaming"; - } else if (typeName.startsWith("Server")) { - streamName = "ServerStreaming"; - } else if (typeName.startsWith("Bidi")) { - streamName = "BidiStreaming"; - } else if (typeName.startsWith("Operation")) { - streamName = "Operation"; - } - } - return String.format("create%sCallable", streamName); - } + returnType = TypeNode.withReference(returnType.reference().copyAndSetGenerics(genericRefs)); - private static List createCallableGetterMethods( - Map callableClassMemberVarExprs) { - return callableClassMemberVarExprs.entrySet().stream() - .map( - e -> - MethodDefinition.builder() - .setIsOverride(true) - .setScope(ScopeNode.PUBLIC) - .setReturnType(e.getValue().type()) - .setName(e.getKey()) - .setReturnExpr(e.getValue()) - .build()) - .collect(Collectors.toList()); + return createCallableGetterMethodDefinition(returnType, methodName, annotations, typeStore); } - private List createStubOverrideMethods( - VariableExpr backgroundResourcesVarExpr, Service service) { - Function methodMakerStarterFn = - methodName -> - MethodDefinition.builder() - .setIsOverride(true) - .setScope(ScopeNode.PUBLIC) - .setName(methodName); - - Function voidMethodMakerFn = - methodName -> - methodMakerStarterFn - .apply(methodName) - .setReturnType(TypeNode.VOID) - .setBody( - Arrays.asList( - ExprStatement.withExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(backgroundResourcesVarExpr) - .setMethodName(methodName) - .build()))) - .build(); + private List createOperationsStubGetters(TypeStore typeStore, TypeNode operationsStubType) { + List getters = new ArrayList<>(); - Function booleanMethodMakerFn = - methodName -> - methodMakerStarterFn - .apply(methodName) - .setReturnType(TypeNode.BOOLEAN) - .setReturnExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(backgroundResourcesVarExpr) - .setMethodName(methodName) - .setReturnType(TypeNode.BOOLEAN) - .build()) - .build(); + Iterator operationStubNameIt = + getTransportContext().transportOperationsStubNames().iterator(); + Iterator operationStubTypeIt = getTransportContext().operationsStubTypes().iterator(); - // Generate the close() method: - // @Override - // public final void close() { - // try { - // backgroundResources.close(); - // } catch (RuntimeException e) { - // throw e; - // } catch (Exception e) { - // throw new IllegalStateException("Failed to close resource", e); - // } - // } + while (operationStubNameIt.hasNext() && operationStubTypeIt.hasNext()) { + String methodName = + String.format("get%s", JavaStyle.toUpperCamelCase(operationStubNameIt.next())); + //TODO: refactor this + TypeNode actualOperationsStubType = operationStubTypeIt.next(); + if (operationsStubType != null) { + actualOperationsStubType = operationsStubType; + } - VariableExpr catchRuntimeExceptionVarExpr = - VariableExpr.builder() - .setVariable( - Variable.builder() - .setType(TypeNode.withExceptionClazz(RuntimeException.class)) - .setName("e") - .build()) - .build(); - VariableExpr catchExceptionVarExpr = - VariableExpr.builder() - .setVariable( - Variable.builder() - .setType(TypeNode.withExceptionClazz(Exception.class)) - .setName("e") - .build()) - .build(); - List javaMethods = new ArrayList<>(); - if (service.operationPollingMethod() != null) { - javaMethods.addAll(createLongRunningClientGetter()); + getters.add(createOperationsStubGetterMethodDefinition(actualOperationsStubType, methodName, typeStore)); } - javaMethods.add( - methodMakerStarterFn - .apply("close") - .setIsFinal(true) - .setReturnType(TypeNode.VOID) - .setBody( - Arrays.asList( - TryCatchStatement.builder() - .setTryBody( - Arrays.asList( - ExprStatement.withExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(backgroundResourcesVarExpr) - .setMethodName("close") - .build()))) - .addCatch( - catchRuntimeExceptionVarExpr.toBuilder().setIsDecl(true).build(), - Arrays.asList( - ExprStatement.withExpr( - ThrowExpr.builder() - .setThrowExpr(catchRuntimeExceptionVarExpr) - .build()))) - .addCatch( - catchExceptionVarExpr.toBuilder().setIsDecl(true).build(), - Arrays.asList( - ExprStatement.withExpr( - ThrowExpr.builder() - .setType( - TypeNode.withExceptionClazz( - IllegalStateException.class)) - .setMessageExpr(String.format("Failed to close resource")) - .setCauseExpr(catchExceptionVarExpr) - .build()))) - .build())) - .build()); - javaMethods.add(voidMethodMakerFn.apply("shutdown")); - javaMethods.add(booleanMethodMakerFn.apply("isShutdown")); - javaMethods.add(booleanMethodMakerFn.apply("isTerminated")); - javaMethods.add(voidMethodMakerFn.apply("shutdownNow")); - List awaitTerminationArgs = - Arrays.asList( - VariableExpr.withVariable( - Variable.builder().setName("duration").setType(TypeNode.LONG).build()), - VariableExpr.withVariable( - Variable.builder() - .setName("unit") - .setType(FIXED_TYPESTORE.get("TimeUnit")) - .build())); - javaMethods.add( - methodMakerStarterFn - .apply("awaitTermination") - .setReturnType(TypeNode.BOOLEAN) - .setArguments( - awaitTerminationArgs.stream() - .map(v -> v.toBuilder().setIsDecl(true).build()) - .collect(Collectors.toList())) - .setThrowsExceptions(Arrays.asList(FIXED_TYPESTORE.get("InterruptedException"))) - .setReturnExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(backgroundResourcesVarExpr) - .setMethodName("awaitTermination") - .setArguments( - awaitTerminationArgs.stream() - .map(v -> (Expr) v) - .collect(Collectors.toList())) - .setReturnType(TypeNode.BOOLEAN) - .build()) - .build()); - return javaMethods; + return getters; } - private boolean checkOperationPollingMethod(Service service) { - for(Method method : service.methods()) { - if(method.isOperationPollingMethod()) { - return true; - } - } - return false; + private List createLongRunningClientGetters(TypeStore typeStore) { + return ImmutableList.of(createCallableGetterMethodDefinition( + TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class)), + "longRunningClient", + ImmutableList.of(AnnotationNode.withType(typeStore.get("BetaApi"))), + typeStore)); } - protected List createLongRunningClientGetter() { - return Collections.emptyList(); + private static List createBackgroundResourceMethodOverrides() { + MethodDefinition closeMethod = + MethodDefinition.builder() + .setIsOverride(true) + .setScope(ScopeNode.PUBLIC) + .setIsAbstract(true) + .setReturnType(TypeNode.VOID) + .setName("close") + .build(); + return Arrays.asList(closeMethod); } - private TypeStore createDynamicTypes(Service service, String stubPakkage) { - TypeStore typeStore = new TypeStore(); - typeStore.putAll( - stubPakkage, + private static TypeStore createTypes(Service service, Map messageTypes) { + List concreteClazzes = Arrays.asList( - getTransportContext().classNames().getTransportServiceStubClassName(service), - getTransportContext().classNames().getServiceStubSettingsClassName(service), - getTransportContext().classNames().getServiceStubClassName(service), - getTransportContext() - .classNames() - .getTransportServiceCallableFactoryClassName(service))); + BackgroundResource.class, + BetaApi.class, + BidiStreamingCallable.class, + ClientStreamingCallable.class, + Generated.class, + Operation.class, + OperationCallable.class, + ServerStreamingCallable.class, + UnaryCallable.class, + UnsupportedOperationException.class); + TypeStore typeStore = new TypeStore(concreteClazzes); + + typeStore.put("com.google.longrunning.stub", "OperationsStub"); + // Pagination types. typeStore.putAll( service.pakkage(), @@ -962,68 +277,45 @@ private TypeStore createDynamicTypes(Service service, String stubPakkage) { .map(m -> String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, m.name())) .collect(Collectors.toList()), true, - getTransportContext().classNames().getServiceClientClassName(service)); - return typeStore; - } + ClassNames.getServiceClientClassName(service)); - private static TypeNode getCallableType(Method protoMethod) { - TypeNode callableType = FIXED_TYPESTORE.get("UnaryCallable"); - switch (protoMethod.stream()) { - case CLIENT: - callableType = FIXED_TYPESTORE.get("ClientStreamingCallable"); - break; - case SERVER: - callableType = FIXED_TYPESTORE.get("ServerStreamingCallable"); - break; - case BIDI: - callableType = FIXED_TYPESTORE.get("BidiStreamingCallable"); - break; - case NONE: - // Fall through - default: - // Fall through - } - - return TypeNode.withReference( - callableType - .reference() - .copyAndSetGenerics( - Arrays.asList( - protoMethod.inputType().reference(), protoMethod.outputType().reference()))); + return typeStore; } - private CommentStatement createProtectedCtorComment(Service service) { - return CommentStatement.withComment( - JavaDocComment.withComment( - String.format( - "Constructs an instance of %s, using the given settings. This is protected so that" - + " it is easy to make a subclass, but otherwise, the static factory methods" - + " should be preferred.", - getTransportContext().classNames().getTransportServiceStubClassName(service)))); + 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 String getProtoRpcFullMethodName(Service protoService, Method protoMethod) { - if (protoMethod.isMixin()) { - return String.format("%s/%s", protoMethod.mixedInApiName(), protoMethod.name()); - } - - return String.format( - "%s.%s/%s", protoService.protoPakkage(), protoService.name(), protoMethod.name()); + 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(); } - protected TypeNode getTransportOperationsStubType(Service service) { - TypeNode transportOpeationsStubType = service.operationServiceStubType(); - if (transportOpeationsStubType == null) { - transportOpeationsStubType = getTransportContext().transportOperationsStubType(); - } - else { - transportOpeationsStubType = TypeNode.withReference( - VaporReference.builder() - .setName("HttpJson" + transportOpeationsStubType.reference().simpleName()) - .setPakkage(transportOpeationsStubType.reference().pakkage()) - .build()); - } - - return transportOpeationsStubType; + private static String getClientClassName(Service service) { + return String.format("%sClient", service.overriddenName()); } } 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 c999fccb9d..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(); @@ -1136,7 +1274,7 @@ private static MethodDefinition createClassConstructor( .build(); } - private static ClassDefinition createNestedBuilderClass( + private ClassDefinition createNestedBuilderClass( Service service, @Nullable GapicServiceConfig serviceConfig, TypeStore typeStore) { // TODO(miraleung): Robustify this against a null serviceConfig. String thisClassName = ClassNames.getServiceStubSettingsClassName(service); @@ -1236,7 +1374,7 @@ private static List createNestedClassStatements( return statements; } - private static List createNestedClassMethods( + private List createNestedClassMethods( Service service, GapicServiceConfig serviceConfig, TypeNode superType, @@ -1247,7 +1385,7 @@ private static 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()); @@ -1258,7 +1396,7 @@ private static List createNestedClassMethods( return nestedClassMethods; } - private static MethodDefinition createNestedClassInitDefaultsMethod( + private MethodDefinition createNestedClassInitDefaultsMethod( Service service, @Nullable GapicServiceConfig serviceConfig, TypeStore typeStore) { // TODO(miraleung): Robustify this against a null serviceConfig. TypeNode builderType = typeStore.get(NESTED_BUILDER_CLASS_NAME); @@ -1313,7 +1451,9 @@ private static MethodDefinition createNestedClassInitDefaultsMethod( method, builderVarExpr, NESTED_RETRYABLE_CODE_DEFINITIONS_VAR_EXPR, - NESTED_RETRY_PARAM_DEFINITIONS_VAR_EXPR))); + NESTED_RETRY_PARAM_DEFINITIONS_VAR_EXPR, + getTransportContext().operationResponseTransformerType(), + getTransportContext().operationMetadataTransformerType()))); bodyStatements.add(EMPTY_LINE_STATEMENT); } @@ -1583,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); @@ -1608,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() @@ -1640,7 +1812,7 @@ private static MethodDefinition createNestedClassCreateDefaultMethod(TypeStore t MethodInvocationExpr.builder() .setExprReferenceExpr( MethodInvocationExpr.builder() - .setMethodName("defaultApiClientHeaderProviderBuilder") + .setMethodName(defaultApiClientHeaderProviderBuilder) .build()) .setMethodName("build") .build()) @@ -1683,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(); @@ -1867,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 new file mode 100644 index 0000000000..3aa79a452f --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java @@ -0,0 +1,1077 @@ +// Copyright 2020 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.common; + +import com.google.api.core.BetaApi; +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.core.BackgroundResourceAggregation; +import com.google.api.gax.rpc.BidiStreamingCallable; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.ClientStreamingCallable; +import com.google.api.gax.rpc.LongRunningClient; +import com.google.api.gax.rpc.OperationCallable; +import com.google.api.gax.rpc.RequestParamsExtractor; +import com.google.api.gax.rpc.ServerStreamingCallable; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.ClassDefinition; +import com.google.api.generator.engine.ast.CommentStatement; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.EmptyLineStatement; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.ExprStatement; +import com.google.api.generator.engine.ast.JavaDocComment; +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.MethodInvocationExpr; +import com.google.api.generator.engine.ast.NewObjectExpr; +import com.google.api.generator.engine.ast.ReferenceConstructorExpr; +import com.google.api.generator.engine.ast.ScopeNode; +import com.google.api.generator.engine.ast.Statement; +import com.google.api.generator.engine.ast.ThisObjectValue; +import com.google.api.generator.engine.ast.ThrowExpr; +import com.google.api.generator.engine.ast.TryCatchStatement; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.engine.ast.VaporReference; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.comment.StubCommentComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.PackageChecker; +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.Message; +import com.google.api.generator.gapic.model.Method; +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.common.collect.ImmutableMap; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.annotation.Generated; + +public abstract class AbstractTransportServiceStubClassComposer implements ClassComposer { + private static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create(); + + private static final String METHOD_DESCRIPTOR_NAME_PATTERN = "%sMethodDescriptor"; + private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; + private static final String PAGED_CALLABLE_CLASS_MEMBER_PATTERN = "%sPagedCallable"; + + private static final String BACKGROUND_RESOURCES_MEMBER_NAME = "backgroundResources"; + private static final String CALLABLE_NAME = "Callable"; + private static final String CALLABLE_FACTORY_MEMBER_NAME = "callableFactory"; + private static final String CALLABLE_CLASS_MEMBER_PATTERN = "%sCallable"; + private static final String OPERATION_CALLABLE_CLASS_MEMBER_PATTERN = "%sOperationCallable"; + private static final String OPERATION_CALLABLE_NAME = "OperationCallable"; + // private static final String OPERATIONS_STUB_MEMBER_NAME = "operationsStub"; + private static final String PAGED_CALLABLE_NAME = "PagedCallable"; + + protected static final TypeStore FIXED_TYPESTORE = createStaticTypes(); + + private final TransportContext transportContext; + + protected AbstractTransportServiceStubClassComposer(TransportContext transportContext) { + this.transportContext = transportContext; + } + + public TransportContext getTransportContext() { + return transportContext; + } + + private static TypeStore createStaticTypes() { + List concreteClazzes = + Arrays.asList( + BackgroundResource.class, + BackgroundResourceAggregation.class, + BetaApi.class, + BidiStreamingCallable.class, + ClientContext.class, + ClientStreamingCallable.class, + Generated.class, + ImmutableMap.class, + InterruptedException.class, + IOException.class, + Operation.class, + OperationCallable.class, + RequestParamsExtractor.class, + ServerStreamingCallable.class, + TimeUnit.class, + UnaryCallable.class); + return new TypeStore(concreteClazzes); + } + + @Override + public GapicClass generate(GapicContext context, Service service) { + String pakkage = service.pakkage() + ".stub"; + TypeStore typeStore = createDynamicTypes(service, pakkage); + String className = getTransportContext().classNames().getTransportServiceStubClassName(service); + GapicClass.Kind kind = Kind.STUB; + + Map protoMethodNameToDescriptorVarExprs = + createProtoMethodNameToDescriptorClassMembers( + service, getTransportContext().methodDescriptorClass()); + + Map callableClassMemberVarExprs = + createCallableClassMembers(service, typeStore); + + Map classMemberVarExprs = new LinkedHashMap<>(); + classMemberVarExprs.put( + BACKGROUND_RESOURCES_MEMBER_NAME, + VariableExpr.withVariable( + Variable.builder() + .setName(BACKGROUND_RESOURCES_MEMBER_NAME) + .setType(FIXED_TYPESTORE.get("BackgroundResource")) + .build())); + if (generateOperationsStubLogic(service)) { + // Transport-specific service stub may have only one element of the following, thus get(0). + TypeNode opeationsStubType = getTransportOperationsStubType(service); + classMemberVarExprs.put( + getTransportContext().transportOperationsStubNames().get(0), + VariableExpr.withVariable( + Variable.builder() + .setName(getTransportContext().transportOperationsStubNames().get(0)) + .setType(opeationsStubType) + .build())); + } + + boolean operationPollingMethod = checkOperationPollingMethod(service); + if(operationPollingMethod) { + VariableExpr longRunningVarExpr = declareLongRunningClient(); + if (longRunningVarExpr != null) { + classMemberVarExprs.put("longRunningClient", longRunningVarExpr); + } + } + + classMemberVarExprs.put( + CALLABLE_FACTORY_MEMBER_NAME, + VariableExpr.withVariable( + Variable.builder() + .setName(CALLABLE_FACTORY_MEMBER_NAME) + .setType(getTransportContext().stubCallableFactoryType()) + .build())); + + Map messageTypes = context.messages(); + List classStatements = + createClassStatements( + service, + protoMethodNameToDescriptorVarExprs, + callableClassMemberVarExprs, + classMemberVarExprs, + messageTypes); + + StubCommentComposer commentComposer = + new StubCommentComposer(getTransportContext().transportName()); + + ClassDefinition classDef = + ClassDefinition.builder() + .setPackageString(pakkage) + .setHeaderCommentStatements( + commentComposer.createTransportServiceStubClassHeaderComments( + service.name(), service.isDeprecated())) + .setAnnotations(createClassAnnotations(service)) + .setScope(ScopeNode.PUBLIC) + .setName(className) + .setExtendsType( + typeStore.get(getTransportContext().classNames().getServiceStubClassName(service))) + .setStatements(classStatements) + .setMethods( + createClassMethods( + service, + typeStore, + classMemberVarExprs, + callableClassMemberVarExprs, + protoMethodNameToDescriptorVarExprs)) + .build(); + return GapicClass.create(kind, classDef); + } + + protected abstract Statement createMethodDescriptorVariableDecl( + Service service, Method protoMethod, VariableExpr methodDescriptorVarExpr, Map messageTypes); + + protected boolean generateOperationsStubLogic(Service service) { + return true; + } + + protected List createOperationsStubGetterMethod( + Service service, VariableExpr operationsStubVarExpr) { + if (!generateOperationsStubLogic(service)) { + return Collections.emptyList(); + } + + String methodName = + String.format( + "get%s", + JavaStyle.toUpperCamelCase(getTransportContext().transportOperationsStubNames().get(0))); + + return Arrays.asList( + MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setReturnType(operationsStubVarExpr.type()) + .setName(methodName) + .setReturnExpr(operationsStubVarExpr) + .build()); + } + + protected abstract Expr createTransportSettingsInitExpr( + Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr); + + protected List createGetMethodDescriptorsMethod( + Service service, + TypeStore typeStore, + Map protoMethodNameToDescriptorVarExprs) { + return Arrays.asList(); + } + + protected List createClassStatements( + Service service, + Map protoMethodNameToDescriptorVarExprs, + Map callableClassMemberVarExprs, + Map classMemberVarExprs, + Map messageTypes) { + List classStatements = new ArrayList<>(); + for (Statement statement : + createMethodDescriptorVariableDecls(service, protoMethodNameToDescriptorVarExprs, messageTypes)) { + classStatements.add(statement); + classStatements.add(EMPTY_LINE_STATEMENT); + } + + classStatements.addAll(createClassMemberFieldDeclarations(callableClassMemberVarExprs)); + classStatements.add(EMPTY_LINE_STATEMENT); + + classStatements.addAll(createClassMemberFieldDeclarations(classMemberVarExprs)); + return classStatements; + } + + protected List createMethodDescriptorVariableDecls( + Service service, Map protoMethodNameToDescriptorVarExprs, Map messageTypes) { + return service.methods().stream() + .map( + m -> + createMethodDescriptorVariableDecl( + service, m, protoMethodNameToDescriptorVarExprs.get(m.name()), messageTypes)) + .collect(Collectors.toList()); + } + + private static List createClassMemberFieldDeclarations( + Map fieldNameToVarExprs) { + return fieldNameToVarExprs.values().stream() + .map( + v -> + ExprStatement.withExpr( + v.toBuilder() + .setIsDecl(true) + .setScope(ScopeNode.PRIVATE) + .setIsFinal(true) + .build())) + .collect(Collectors.toList()); + } + + protected Map createProtoMethodNameToDescriptorClassMembers( + Service service, Class descriptorClass) { + return service.methods().stream() + .collect( + Collectors.toMap( + Method::name, + m -> + VariableExpr.withVariable( + Variable.builder() + .setName( + String.format( + METHOD_DESCRIPTOR_NAME_PATTERN, + JavaStyle.toLowerCamelCase(m.name()))) + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(descriptorClass) + .setGenerics( + Arrays.asList( + m.inputType().reference(), + m.outputType().reference())) + .build())) + .build()), + (u, v) -> { + throw new IllegalStateException(); + }, + LinkedHashMap::new)); + } + + private Map createCallableClassMembers( + Service service, TypeStore typeStore) { + Map callableClassMembers = new LinkedHashMap<>(); + // Using a for-loop because the output cardinality is not a 1:1 mapping to the input set. + for (Method protoMethod : service.methods()) { + String javaStyleProtoMethodName = JavaStyle.toLowerCamelCase(protoMethod.name()); + String callableName = String.format(CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); + callableClassMembers.put( + callableName, + VariableExpr.withVariable( + Variable.builder() + .setName(callableName) + .setType(getCallableType(protoMethod)) + .build())); + if (protoMethod.hasLro()) { + callableName = + String.format(OPERATION_CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); + callableClassMembers.put( + callableName, + VariableExpr.withVariable( + Variable.builder() + .setName(callableName) + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(OperationCallable.class) + .setGenerics( + Arrays.asList( + protoMethod.inputType().reference(), + protoMethod.lro().responseType().reference(), + protoMethod.lro().metadataType().reference())) + .build())) + .build())); + } + if (protoMethod.isPaged()) { + callableName = String.format(PAGED_CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); + callableClassMembers.put( + callableName, + VariableExpr.withVariable( + Variable.builder() + .setName(callableName) + .setType( + TypeNode.withReference( + getCallableType(protoMethod) + .reference() + .copyAndSetGenerics( + Arrays.asList( + protoMethod.inputType().reference(), + typeStore + .get( + String.format( + PAGED_RESPONSE_TYPE_NAME_PATTERN, + protoMethod.name())) + .reference())))) + .build())); + } + } + return callableClassMembers; + } + + protected List createClassAnnotations(Service service) { + List annotations = new ArrayList<>(); + if (!PackageChecker.isGaApi(service.pakkage())) { + annotations.add(AnnotationNode.withType(FIXED_TYPESTORE.get("BetaApi"))); + } + + if (service.isDeprecated()) { + annotations.add(AnnotationNode.withType(TypeNode.DEPRECATED)); + } + + annotations.add( + AnnotationNode.builder() + .setType(FIXED_TYPESTORE.get("Generated")) + .setDescription("by gapic-generator-java") + .build()); + return annotations; + } + + protected List createClassMethods( + Service service, + TypeStore typeStore, + Map classMemberVarExprs, + Map callableClassMemberVarExprs, + Map protoMethodNameToDescriptorVarExprs) { + List javaMethods = new ArrayList<>(); + javaMethods.addAll(createStaticCreatorMethods(service, typeStore, "newBuilder")); + javaMethods.addAll( + createConstructorMethods( + service, + typeStore, + classMemberVarExprs, + callableClassMemberVarExprs, + protoMethodNameToDescriptorVarExprs)); + javaMethods.addAll( + createGetMethodDescriptorsMethod(service, typeStore, protoMethodNameToDescriptorVarExprs)); + javaMethods.addAll( + createOperationsStubGetterMethod( + service, classMemberVarExprs.get(getTransportContext().transportOperationsStubNames().get(0)))); + javaMethods.addAll(createCallableGetterMethods(callableClassMemberVarExprs)); + javaMethods.addAll( + createStubOverrideMethods(classMemberVarExprs.get(BACKGROUND_RESOURCES_MEMBER_NAME), service)); + return javaMethods; + } + + protected List createStaticCreatorMethods(Service service, TypeStore typeStore, String newBuilderMethod) { + TypeNode creatorMethodReturnType = + typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); + Function, MethodDefinition.Builder> creatorMethodStarterFn = + argList -> + MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setIsFinal(true) + .setReturnType(creatorMethodReturnType) + .setName("create") + .setArguments( + argList.stream() + .map(v -> v.toBuilder().setIsDecl(true).build()) + .collect(Collectors.toList())) + .setThrowsExceptions( + Arrays.asList( + TypeNode.withReference(ConcreteReference.withClazz(IOException.class)))); + + Function, Expr> instantiatorExprFn = + argList -> + NewObjectExpr.builder().setType(creatorMethodReturnType).setArguments(argList).build(); + + TypeNode stubSettingsType = + typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); + VariableExpr settingsVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("settings").setType(stubSettingsType).build()); + + TypeNode clientContextType = FIXED_TYPESTORE.get("ClientContext"); + VariableExpr clientContextVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("clientContext").setType(clientContextType).build()); + + VariableExpr callableFactoryVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setName("callableFactory") + .setType(getTransportContext().stubCallableFactoryType()) + .build()); + + MethodInvocationExpr clientContextCreateMethodExpr = + MethodInvocationExpr.builder() + .setMethodName("create") + .setStaticReferenceType(clientContextType) + .setArguments(Arrays.asList(settingsVarExpr)) + .build(); + MethodInvocationExpr settingsBuilderMethodExpr = + MethodInvocationExpr.builder() + .setMethodName(newBuilderMethod) + .setStaticReferenceType(stubSettingsType) + .build(); + settingsBuilderMethodExpr = + MethodInvocationExpr.builder() + .setMethodName("build") + .setExprReferenceExpr(settingsBuilderMethodExpr) + .build(); + + return Arrays.asList( + creatorMethodStarterFn + .apply(Arrays.asList(settingsVarExpr)) + .setReturnExpr( + instantiatorExprFn.apply( + Arrays.asList(settingsVarExpr, clientContextCreateMethodExpr))) + .build(), + creatorMethodStarterFn + .apply(Arrays.asList(clientContextVarExpr)) + .setReturnExpr( + instantiatorExprFn.apply( + Arrays.asList(settingsBuilderMethodExpr, clientContextVarExpr))) + .build(), + creatorMethodStarterFn + .apply(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) + .setReturnExpr( + instantiatorExprFn.apply( + Arrays.asList( + settingsBuilderMethodExpr, clientContextVarExpr, callableFactoryVarExpr))) + .build()); + } + + protected List createConstructorMethods( + Service service, + TypeStore typeStore, + Map classMemberVarExprs, + Map callableClassMemberVarExprs, + Map protoMethodNameToDescriptorVarExprs) { + TypeNode stubSettingsType = + typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); + VariableExpr settingsVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("settings").setType(stubSettingsType).build()); + + TypeNode clientContextType = FIXED_TYPESTORE.get("ClientContext"); + VariableExpr clientContextVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("clientContext").setType(clientContextType).build()); + + VariableExpr callableFactoryVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setName("callableFactory") + .setType(getTransportContext().stubCallableFactoryType()) + .build()); + + TypeNode thisClassType = + typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); + TypeNode ioExceptionType = + TypeNode.withReference(ConcreteReference.withClazz(IOException.class)); + + BiFunction, List, MethodDefinition> ctorMakerFn = + (args, body) -> + MethodDefinition.constructorBuilder() + .setScope(ScopeNode.PROTECTED) + .setReturnType(thisClassType) + .setHeaderCommentStatements(Arrays.asList(createProtectedCtorComment(service))) + .setArguments( + args.stream() + .map(v -> v.toBuilder().setIsDecl(true).build()) + .collect(Collectors.toList())) + .setThrowsExceptions(Arrays.asList(ioExceptionType)) + .setBody(body) + .build(); + + // First constructor method. + MethodDefinition firstCtor = + ctorMakerFn.apply( + Arrays.asList(settingsVarExpr, clientContextVarExpr), + Arrays.asList( + ExprStatement.withExpr( + ReferenceConstructorExpr.thisBuilder() + .setType(thisClassType) + .setArguments( + settingsVarExpr, + clientContextVarExpr, + NewObjectExpr.builder() + .setType( + typeStore.get( + getTransportContext() + .classNames() + .getTransportServiceCallableFactoryClassName(service))) + .build()) + .build()))); + + Expr thisExpr = + ValueExpr.withValue( + ThisObjectValue.withType( + typeStore.get( + getTransportContext().classNames().getTransportServiceStubClassName(service)))); + // Body of the second constructor method. + List secondCtorStatements = new ArrayList<>(); + List secondCtorExprs = new ArrayList<>(); + secondCtorExprs.add( + AssignmentExpr.builder() + .setVariableExpr( + classMemberVarExprs.get("callableFactory").toBuilder() + .setExprReferenceExpr(thisExpr) + .build()) + .setValueExpr(callableFactoryVarExpr) + .build()); + VariableExpr operationsStubClassVarExpr = classMemberVarExprs.get(getTransportContext().transportOperationsStubNames().get(0)); + //TODO: refactor this + if (generateOperationsStubLogic(service)) { + TypeNode opeationsStubType = getTransportOperationsStubType(service); + secondCtorExprs.add( + AssignmentExpr.builder() + .setVariableExpr( + operationsStubClassVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType(opeationsStubType) + .setMethodName("create") + .setArguments(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) + .setReturnType(operationsStubClassVarExpr.type()) + .build()) + .build()); + } + secondCtorStatements.addAll( + secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + secondCtorExprs.clear(); + secondCtorStatements.add(EMPTY_LINE_STATEMENT); + + // Transport settings local variables. + Map javaStyleMethodNameToTransportSettingsVarExprs = + service.methods().stream() + .collect( + Collectors.toMap( + m -> JavaStyle.toLowerCamelCase(m.name()), + m -> + VariableExpr.withVariable( + Variable.builder() + .setName( + String.format( + "%sTransportSettings", + JavaStyle.toLowerCamelCase(m.name()))) + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(getTransportContext().callSettingsClass()) + .setGenerics( + Arrays.asList( + m.inputType().reference(), + m.outputType().reference())) + .build())) + .build()))); + + secondCtorExprs.addAll( + service.methods().stream() + .map( + m -> + createTransportSettingsInitExpr( + m, + javaStyleMethodNameToTransportSettingsVarExprs.get( + JavaStyle.toLowerCamelCase(m.name())), + protoMethodNameToDescriptorVarExprs.get(m.name()))) + .collect(Collectors.toList())); + secondCtorStatements.addAll( + secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + secondCtorExprs.clear(); + secondCtorStatements.add(EMPTY_LINE_STATEMENT); + + // Initialize Callable variables. + secondCtorExprs.addAll( + callableClassMemberVarExprs.entrySet().stream() + .map( + e -> + createCallableInitExpr( + e.getKey(), + e.getValue(), + callableFactoryVarExpr, + settingsVarExpr, + clientContextVarExpr, + operationsStubClassVarExpr, + thisExpr, + javaStyleMethodNameToTransportSettingsVarExprs)) + .collect(Collectors.toList())); + secondCtorStatements.addAll( + secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + secondCtorExprs.clear(); + secondCtorStatements.add(EMPTY_LINE_STATEMENT); + + + secondCtorStatements.addAll(createLongRunningClient(service, typeStore)); + + // Instantiate backgroundResources. + MethodInvocationExpr getBackgroundResourcesMethodExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(clientContextVarExpr) + .setMethodName("getBackgroundResources") + .build(); + + VariableExpr backgroundResourcesVarExpr = classMemberVarExprs.get("backgroundResources"); + secondCtorExprs.add( + AssignmentExpr.builder() + .setVariableExpr( + backgroundResourcesVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr( + NewObjectExpr.builder() + .setType(FIXED_TYPESTORE.get("BackgroundResourceAggregation")) + .setArguments(Arrays.asList(getBackgroundResourcesMethodExpr)) + .build()) + .build()); + secondCtorStatements.addAll( + secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + secondCtorExprs.clear(); + + // Second constructor method. + MethodDefinition secondCtor = + ctorMakerFn.apply( + Arrays.asList(settingsVarExpr, clientContextVarExpr, callableFactoryVarExpr), + secondCtorStatements); + + return Arrays.asList(firstCtor, secondCtor); + } + + protected List createLongRunningClient(Service service, TypeStore typeStore) { + return ImmutableList.of(); + } + + protected VariableExpr declareLongRunningClient() { + return null; + } + + private Expr createCallableInitExpr( + String callableVarName, + VariableExpr callableVarExpr, + VariableExpr callableFactoryVarExpr, + VariableExpr settingsVarExpr, + VariableExpr clientContextVarExpr, + VariableExpr operationsStubClassVarExpr, + Expr thisExpr, + Map javaStyleMethodNameToTransportSettingsVarExprs) { + boolean isOperation = callableVarName.endsWith(OPERATION_CALLABLE_NAME); + boolean isPaged = callableVarName.endsWith(PAGED_CALLABLE_NAME); + int sublength = 0; + if (isOperation) { + sublength = OPERATION_CALLABLE_NAME.length(); + } else if (isPaged) { + sublength = PAGED_CALLABLE_NAME.length(); + } else { + sublength = CALLABLE_NAME.length(); + } + String javaStyleMethodName = callableVarName.substring(0, callableVarName.length() - sublength); + List creatorMethodArgVarExprs = null; + Expr transportSettingsVarExpr = + javaStyleMethodNameToTransportSettingsVarExprs.get(javaStyleMethodName); + if (transportSettingsVarExpr == null && isOperation) { + // Try again, in case the name dtection above was inaccurate. + isOperation = false; + sublength = CALLABLE_NAME.length(); + javaStyleMethodName = callableVarName.substring(0, callableVarName.length() - sublength); + transportSettingsVarExpr = + javaStyleMethodNameToTransportSettingsVarExprs.get(javaStyleMethodName); + } + Preconditions.checkNotNull( + transportSettingsVarExpr, + String.format( + "No transport settings variable found for method name %s", javaStyleMethodName)); + if (isOperation) { + creatorMethodArgVarExprs = + Arrays.asList( + transportSettingsVarExpr, + MethodInvocationExpr.builder() + .setExprReferenceExpr(settingsVarExpr) + .setMethodName(String.format("%sOperationSettings", javaStyleMethodName)) + .build(), + clientContextVarExpr, + operationsStubClassVarExpr); + } else { + creatorMethodArgVarExprs = + Arrays.asList( + transportSettingsVarExpr, + MethodInvocationExpr.builder() + .setExprReferenceExpr(settingsVarExpr) + .setMethodName(String.format("%sSettings", javaStyleMethodName)) + .build(), + clientContextVarExpr); + } + + Optional callableCreatorMethodName = + getCallableCreatorMethodName(callableVarExpr.type()); + + Expr initExpr; + if (callableCreatorMethodName.isPresent()) { + initExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(callableFactoryVarExpr) + .setMethodName(callableCreatorMethodName.get()) + .setArguments(creatorMethodArgVarExprs) + .setReturnType(callableVarExpr.type()) + .build(); + } else { + initExpr = ValueExpr.createNullExpr(); + } + + return AssignmentExpr.builder() + .setVariableExpr(callableVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr(initExpr) + .build(); + } + + protected Optional getCallableCreatorMethodName(TypeNode callableVarExprType) { + final String typeName = callableVarExprType.reference().name(); + String streamName = "Unary"; + + // Special handling for pagination methods. + if (callableVarExprType.reference().generics().size() == 2 + && callableVarExprType.reference().generics().get(1).name().endsWith("PagedResponse")) { + streamName = "Paged"; + } else { + if (typeName.startsWith("Client")) { + streamName = "ClientStreaming"; + } else if (typeName.startsWith("Server")) { + streamName = "ServerStreaming"; + } else if (typeName.startsWith("Bidi")) { + streamName = "BidiStreaming"; + } else if (typeName.startsWith("Operation")) { + streamName = "Operation"; + } + } + return Optional.of(String.format("create%sCallable", streamName)); + } + + private static List createCallableGetterMethods( + Map callableClassMemberVarExprs) { + return callableClassMemberVarExprs.entrySet().stream() + .map( + e -> + MethodDefinition.builder() + .setIsOverride(true) + .setScope(ScopeNode.PUBLIC) + .setReturnType(e.getValue().type()) + .setName(e.getKey()) + .setReturnExpr(e.getValue()) + .build()) + .collect(Collectors.toList()); + } + + private List createStubOverrideMethods( + VariableExpr backgroundResourcesVarExpr, Service service) { + Function methodMakerStarterFn = + methodName -> + MethodDefinition.builder() + .setIsOverride(true) + .setScope(ScopeNode.PUBLIC) + .setName(methodName); + + Function voidMethodMakerFn = + methodName -> + methodMakerStarterFn + .apply(methodName) + .setReturnType(TypeNode.VOID) + .setBody( + Arrays.asList( + ExprStatement.withExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(backgroundResourcesVarExpr) + .setMethodName(methodName) + .build()))) + .build(); + + Function booleanMethodMakerFn = + methodName -> + methodMakerStarterFn + .apply(methodName) + .setReturnType(TypeNode.BOOLEAN) + .setReturnExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(backgroundResourcesVarExpr) + .setMethodName(methodName) + .setReturnType(TypeNode.BOOLEAN) + .build()) + .build(); + + // Generate the close() method: + // @Override + // public final void close() { + // try { + // backgroundResources.close(); + // } catch (RuntimeException e) { + // throw e; + // } catch (Exception e) { + // throw new IllegalStateException("Failed to close resource", e); + // } + // } + + VariableExpr catchRuntimeExceptionVarExpr = + VariableExpr.builder() + .setVariable( + Variable.builder() + .setType(TypeNode.withExceptionClazz(RuntimeException.class)) + .setName("e") + .build()) + .build(); + VariableExpr catchExceptionVarExpr = + VariableExpr.builder() + .setVariable( + Variable.builder() + .setType(TypeNode.withExceptionClazz(Exception.class)) + .setName("e") + .build()) + .build(); + List javaMethods = new ArrayList<>(); + if (service.operationPollingMethod() != null) { + javaMethods.addAll(createLongRunningClientGetters()); + } + javaMethods.add( + methodMakerStarterFn + .apply("close") + .setIsFinal(true) + .setReturnType(TypeNode.VOID) + .setBody( + Arrays.asList( + TryCatchStatement.builder() + .setTryBody( + Arrays.asList( + ExprStatement.withExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(backgroundResourcesVarExpr) + .setMethodName("close") + .build()))) + .addCatch( + catchRuntimeExceptionVarExpr.toBuilder().setIsDecl(true).build(), + Arrays.asList( + ExprStatement.withExpr( + ThrowExpr.builder() + .setThrowExpr(catchRuntimeExceptionVarExpr) + .build()))) + .addCatch( + catchExceptionVarExpr.toBuilder().setIsDecl(true).build(), + Arrays.asList( + ExprStatement.withExpr( + ThrowExpr.builder() + .setType( + TypeNode.withExceptionClazz( + IllegalStateException.class)) + .setMessageExpr(String.format("Failed to close resource")) + .setCauseExpr(catchExceptionVarExpr) + .build()))) + .build())) + .build()); + javaMethods.add(voidMethodMakerFn.apply("shutdown")); + javaMethods.add(booleanMethodMakerFn.apply("isShutdown")); + javaMethods.add(booleanMethodMakerFn.apply("isTerminated")); + javaMethods.add(voidMethodMakerFn.apply("shutdownNow")); + + List awaitTerminationArgs = + Arrays.asList( + VariableExpr.withVariable( + Variable.builder().setName("duration").setType(TypeNode.LONG).build()), + VariableExpr.withVariable( + Variable.builder() + .setName("unit") + .setType(FIXED_TYPESTORE.get("TimeUnit")) + .build())); + javaMethods.add( + methodMakerStarterFn + .apply("awaitTermination") + .setReturnType(TypeNode.BOOLEAN) + .setArguments( + awaitTerminationArgs.stream() + .map(v -> v.toBuilder().setIsDecl(true).build()) + .collect(Collectors.toList())) + .setThrowsExceptions(Arrays.asList(FIXED_TYPESTORE.get("InterruptedException"))) + .setReturnExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(backgroundResourcesVarExpr) + .setMethodName("awaitTermination") + .setArguments( + awaitTerminationArgs.stream() + .map(v -> (Expr) v) + .collect(Collectors.toList())) + .setReturnType(TypeNode.BOOLEAN) + .build()) + .build()); + return javaMethods; + } + + private boolean checkOperationPollingMethod(Service service) { + for(Method method : service.methods()) { + if(method.isOperationPollingMethod()) { + return true; + } + } + return false; + } + + protected List createLongRunningClientGetters() { + VariableExpr longRunningClient = + VariableExpr.withVariable( + Variable.builder() + .setName("longRunningClient") + .setType( + TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) + .build()); + + return ImmutableList.of( + MethodDefinition.builder() + .setName("longRunningClient") + .setScope(ScopeNode.PUBLIC) + .setIsOverride(true) + .setReturnType( + TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) + .setReturnExpr(longRunningClient) + .build()); + } + + private TypeStore createDynamicTypes(Service service, String stubPakkage) { + TypeStore typeStore = new TypeStore(); + typeStore.putAll( + stubPakkage, + Arrays.asList( + getTransportContext().classNames().getTransportServiceStubClassName(service), + getTransportContext().classNames().getServiceStubSettingsClassName(service), + getTransportContext().classNames().getServiceStubClassName(service), + getTransportContext() + .classNames() + .getTransportServiceCallableFactoryClassName(service))); + // Pagination types. + typeStore.putAll( + service.pakkage(), + service.methods().stream() + .filter(m -> m.isPaged()) + .map(m -> String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, m.name())) + .collect(Collectors.toList()), + true, + getTransportContext().classNames().getServiceClientClassName(service)); + return typeStore; + } + + private static TypeNode getCallableType(Method protoMethod) { + TypeNode callableType = FIXED_TYPESTORE.get("UnaryCallable"); + switch (protoMethod.stream()) { + case CLIENT: + callableType = FIXED_TYPESTORE.get("ClientStreamingCallable"); + break; + case SERVER: + callableType = FIXED_TYPESTORE.get("ServerStreamingCallable"); + break; + case BIDI: + callableType = FIXED_TYPESTORE.get("BidiStreamingCallable"); + break; + case NONE: + // Fall through + default: + // Fall through + } + + return TypeNode.withReference( + callableType + .reference() + .copyAndSetGenerics( + Arrays.asList( + protoMethod.inputType().reference(), protoMethod.outputType().reference()))); + } + + private CommentStatement createProtectedCtorComment(Service service) { + return CommentStatement.withComment( + JavaDocComment.withComment( + String.format( + "Constructs an instance of %s, using the given settings. This is protected so that" + + " it is easy to make a subclass, but otherwise, the static factory methods" + + " should be preferred.", + getTransportContext().classNames().getTransportServiceStubClassName(service)))); + } + + protected String getProtoRpcFullMethodName(Service protoService, Method protoMethod) { + if (protoMethod.isMixin()) { + return String.format("%s/%s", protoMethod.mixedInApiName(), protoMethod.name()); + } + + return String.format( + "%s.%s/%s", protoService.protoPakkage(), protoService.name(), protoMethod.name()); + } + + protected TypeNode getTransportOperationsStubType(Service service) { + TypeNode transportOpeationsStubType = service.operationServiceStubType(); + if (transportOpeationsStubType == null) { + transportOpeationsStubType = getTransportContext().transportOperationsStubTypes().get(0); + } + else { + transportOpeationsStubType = TypeNode.withReference( + VaporReference.builder() + .setName("HttpJson" + transportOpeationsStubType.reference().simpleName()) + .setPakkage(transportOpeationsStubType.reference().pakkage()) + .build()); + } + + return transportOpeationsStubType; + } +} \ No newline at end of file diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java index 4a20961399..4497495d67 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java @@ -248,7 +248,9 @@ public static Expr createLroSettingsBuilderExpr( Method method, VariableExpr builderVarExpr, VariableExpr retryableCodeDefsVarExpr, - VariableExpr retryParamDefsVarExpr) { + VariableExpr retryParamDefsVarExpr, + TypeNode operationResponseTransformer, + TypeNode operationMetadataTransformer) { Preconditions.checkState( method.hasLro(), String.format( @@ -325,10 +327,7 @@ public static Expr createLroSettingsBuilderExpr( .setMethodName("setResponseTransformer") .setArguments( MethodInvocationExpr.builder() - .setStaticReferenceType( - TypeNode.withReference( - ConcreteReference.withClazz( - ProtoOperationTransformers.ResponseTransformer.class))) + .setStaticReferenceType(operationResponseTransformer) .setMethodName("create") .setArguments(classFieldRefFn.apply(method.lro().responseType())) .build()) @@ -339,10 +338,7 @@ public static Expr createLroSettingsBuilderExpr( .setMethodName("setMetadataTransformer") .setArguments( MethodInvocationExpr.builder() - .setStaticReferenceType( - TypeNode.withReference( - ConcreteReference.withClazz( - ProtoOperationTransformers.MetadataTransformer.class))) + .setStaticReferenceType(operationMetadataTransformer) .setMethodName("create") .setArguments(classFieldRefFn.apply(method.lro().metadataType())) .build()) diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java deleted file mode 100644 index 1c8bed3ccb..0000000000 --- a/src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2020 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.common; - -import com.google.api.core.BetaApi; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.generator.engine.ast.AnnotationNode; -import com.google.api.generator.engine.ast.ClassDefinition; -import com.google.api.generator.engine.ast.ExprStatement; -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; -import com.google.api.generator.gapic.composer.store.TypeStore; -import com.google.api.generator.gapic.composer.utils.ClassNames; -import com.google.api.generator.gapic.composer.utils.PackageChecker; -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.Message; -import com.google.api.generator.gapic.model.Method; -import com.google.api.generator.gapic.model.Service; -import com.google.api.generator.gapic.utils.JavaStyle; -import com.google.longrunning.Operation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import javax.annotation.Generated; - -public class ServiceStubClassComposer implements ClassComposer { - private static final ServiceStubClassComposer INSTANCE = new ServiceStubClassComposer(); - private static final String DOT = "."; - private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; - - private ServiceStubClassComposer() {} - - public static ServiceStubClassComposer instance() { - return INSTANCE; - } - - @Override - public GapicClass generate(GapicContext context, Service service) { - Map messageTypes = context.messages(); - TypeStore typeStore = createTypes(service, messageTypes); - String className = ClassNames.getServiceStubClassName(service); - GapicClass.Kind kind = Kind.STUB; - String pakkage = String.format("%s.stub", service.pakkage()); - - ClassDefinition classDef = - ClassDefinition.builder() - .setPackageString(pakkage) - .setHeaderCommentStatements( - StubCommentComposer.createServiceStubClassHeaderComments( - service.name(), service.isDeprecated())) - .setAnnotations(createClassAnnotations(service, typeStore)) - .setIsAbstract(true) - .setImplementsTypes(createClassImplements(typeStore)) - .setName(className) - .setMethods(createClassMethods(service, messageTypes, typeStore)) - .setScope(ScopeNode.PUBLIC) - .build(); - return GapicClass.create(kind, classDef); - } - - private static List createClassAnnotations(Service service, TypeStore typeStore) { - List annotations = new ArrayList<>(); - if (!PackageChecker.isGaApi(service.pakkage())) { - annotations.add(AnnotationNode.withType(typeStore.get("BetaApi"))); - } - - if (service.isDeprecated()) { - annotations.add(AnnotationNode.withType(TypeNode.DEPRECATED)); - } - - annotations.add( - AnnotationNode.builder() - .setType(typeStore.get("Generated")) - .setDescription("by gapic-generator-java") - .build()); - return annotations; - } - - private static List createClassImplements(TypeStore typeStore) { - return Arrays.asList(typeStore.get("BackgroundResource")); - } - - private static List createClassMethods( - Service service, Map messageTypes, TypeStore typeStore) { - boolean hasLroClient = hasLroMethods(service); - List methods = new ArrayList<>(); - if (hasLroClient) { - TypeNode operationsStubType = service.operationServiceStubType(); - if (operationsStubType == null) { - operationsStubType = typeStore.get("OperationsStub"); - } - methods.add(createOperationsStubGetter(typeStore, operationsStubType)); - } - methods.addAll(createCallableGetters(service, messageTypes, typeStore)); - methods.addAll(createBackgroundResourceMethodOverrides()); - return methods; - } - - private static 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(). - List javaMethods = new ArrayList<>(); - for (Method method : service.methods()) { - if (method.hasLro()) { - javaMethods.add(createOperationCallableGetter(method, typeStore)); - } - if (method.isPaged()) { - javaMethods.add(createPagedCallableGetter(method, typeStore)); - } - javaMethods.add(createCallableGetter(method, typeStore)); - } - return javaMethods; - } - - private static MethodDefinition createOperationCallableGetter( - Method method, TypeStore typeStore) { - return createCallableGetterHelper(method, typeStore, true, false); - } - - private static MethodDefinition createPagedCallableGetter(Method method, TypeStore typeStore) { - return createCallableGetterHelper(method, typeStore, false, true); - } - - private static MethodDefinition createCallableGetter(Method method, TypeStore typeStore) { - return createCallableGetterHelper(method, typeStore, false, false); - } - - private static MethodDefinition createCallableGetterHelper( - Method method, TypeStore typeStore, boolean isLroCallable, boolean isPaged) { - TypeNode returnType; - switch (method.stream()) { - case CLIENT: - returnType = typeStore.get("ClientStreamingCallable"); - break; - case SERVER: - returnType = typeStore.get("ServerStreamingCallable"); - break; - case BIDI: - returnType = typeStore.get("BidiStreamingCallable"); - break; - case NONE: - // Fall through. - default: - returnType = typeStore.get(isLroCallable ? "OperationCallable" : "UnaryCallable"); - } - - String methodName = - String.format( - "%s%sCallable", - JavaStyle.toLowerCamelCase(method.name()), - (isLroCallable ? "Operation" : isPaged ? "Paged" : "")); - List genericRefs = new ArrayList<>(); - genericRefs.add(method.inputType().reference()); - if (method.hasLro() && isLroCallable) { - genericRefs.add(method.lro().responseType().reference()); - genericRefs.add(method.lro().metadataType().reference()); - } else if (isPaged) { - genericRefs.add( - typeStore - .get(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, method.name())) - .reference()); - } else { - genericRefs.add(method.outputType().reference()); - } - - List annotations = - method.isDeprecated() - ? Arrays.asList(AnnotationNode.withType(TypeNode.DEPRECATED)) - : Collections.emptyList(); - - returnType = TypeNode.withReference(returnType.reference().copyAndSetGenerics(genericRefs)); - - return MethodDefinition.builder() - .setAnnotations(annotations) - .setScope(ScopeNode.PUBLIC) - .setReturnType(returnType) - .setName(methodName) - .setBody(createThrowUOEBody(methodName, typeStore)) - .build(); - } - - private static MethodDefinition createOperationsStubGetter(TypeStore typeStore, TypeNode operationsStubType) { - String methodName = "getOperationsStub"; - return MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setReturnType(operationsStubType) - .setName(methodName) - .setBody(createThrowUOEBody(methodName, typeStore)) - .build(); - } - - private static List createBackgroundResourceMethodOverrides() { - MethodDefinition closeMethod = - MethodDefinition.builder() - .setIsOverride(true) - .setScope(ScopeNode.PUBLIC) - .setIsAbstract(true) - .setReturnType(TypeNode.VOID) - .setName("close") - .build(); - return Arrays.asList(closeMethod); - } - - private static boolean hasLroMethods(Service service) { - for (Method method : service.methods()) { - if (method.hasLro()) { - return true; - } - } - return false; - } - - private static TypeStore createTypes(Service service, Map messageTypes) { - List concreteClazzes = - Arrays.asList( - BackgroundResource.class, - BetaApi.class, - BidiStreamingCallable.class, - ClientStreamingCallable.class, - Generated.class, - Operation.class, - OperationCallable.class, - ServerStreamingCallable.class, - UnaryCallable.class, - UnsupportedOperationException.class); - TypeStore typeStore = new TypeStore(concreteClazzes); - - typeStore.put("com.google.longrunning.stub", "OperationsStub"); - - // Pagination types. - typeStore.putAll( - service.pakkage(), - service.methods().stream() - .filter(m -> m.isPaged()) - .map(m -> String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, m.name())) - .collect(Collectors.toList()), - true, - ClassNames.getServiceClientClassName(service)); - - 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())); - } - - private static String getClientClassName(Service service) { - return String.format("%sClient", service.overriddenName()); - } -} 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 4058fbafbf..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,7 @@ 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 @@ -29,36 +30,57 @@ 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(); - @Nullable - public abstract TypeNode transportOperationsStubType(); + public abstract List transportOperationsStubTypes(); + + 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 + public abstract TypeNode operationResponseTransformerType(); + + public abstract TypeNode operationMetadataTransformerType(); + + public abstract List operationsClientTypes(); + + public abstract List operationsClientNames(); + protected static TypeNode classToType(Class clazz) { return TypeNode.withReference(ConcreteReference.withClazz(clazz)); } @@ -82,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); @@ -98,9 +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 setTransportOperationsStubNames(List transportOperationsStubNames); + + public abstract Builder setOperationsStubTypes(List operationsStubType); + + public abstract Builder setOperationResponseTransformerType(TypeNode operationResponseTransformerType); + + public abstract Builder setOperationMetadataTransformerType(TypeNode operationMetadataTransformerType); + + public abstract Builder setOperationsClientTypes(List operationsClientTypes); - public abstract Builder setOperationsStubType(TypeNode operationsStubType); + public abstract Builder setOperationsClientNames(List operationsClientNames); public abstract TransportContext build(); } diff --git a/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java b/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java index 75562d680c..5af2722fd7 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java @@ -58,8 +58,11 @@ public class DefaultValueComposer { TypeNode.withReference(ConcreteReference.withClazz(ByteString.class)); public static Expr createDefaultValue( - MethodArgument methodArg, Map resourceNames) { - if (methodArg.isResourceNameHelper()) { + MethodArgument methodArg, + Map resourceNames, + boolean forceResourceNameInitializer) { + if (methodArg.isResourceNameHelper() + || (forceResourceNameInitializer && methodArg.field().hasResourceReference())) { Preconditions.checkState( methodArg.field().hasResourceReference(), String.format( @@ -72,10 +75,21 @@ public static Expr createDefaultValue( String.format( "No resource name found for reference %s", methodArg.field().resourceReference().resourceTypeString())); - return createDefaultValue( - resourceName, - resourceNames.values().stream().collect(Collectors.toList()), - methodArg.field().name()); + Expr defValue = + createDefaultValue( + resourceName, + resourceNames.values().stream().collect(Collectors.toList()), + methodArg.field().name()); + + if (!methodArg.isResourceNameHelper() && methodArg.field().hasResourceReference()) { + defValue = + MethodInvocationExpr.builder() + .setExprReferenceExpr(defValue) + .setMethodName("toString") + .setReturnType(TypeNode.STRING) + .build(); + } + return defValue; } if (methodArg.type().equals(methodArg.field().type())) { 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 9a291669e2..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 @@ -19,9 +19,12 @@ import com.google.api.gax.grpc.GrpcStubCallableFactory; 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.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; import io.grpc.MethodDescriptor; @@ -36,18 +39,33 @@ public abstract class GrpcContext extends TransportContext { .setCallSettingsClass(GrpcCallSettings.class) .setStubCallableFactoryType(classToType(GrpcStubCallableFactory.class)) .setMethodDescriptorClass(MethodDescriptor.class) - .setTransportOperationsStubType(classToType(GrpcOperationsStub.class)) + .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( + classToType(ProtoOperationTransformers.ResponseTransformer.class)) + .setOperationMetadataTransformerType( + classToType(ProtoOperationTransformers.MetadataTransformer.class)) + // For ServiceClientClassComposer + .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/GrpcServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java index 3fc25a95b2..f3ad194c51 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java @@ -22,7 +22,6 @@ import com.google.api.generator.engine.ast.Expr; import com.google.api.generator.engine.ast.ExprStatement; import com.google.api.generator.engine.ast.LambdaExpr; -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.Statement; @@ -31,7 +30,7 @@ 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.common.AbstractServiceStubClassComposer; +import com.google.api.generator.gapic.composer.common.AbstractTransportServiceStubClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.model.HttpBindings.HttpBinding; import com.google.api.generator.gapic.model.Message; @@ -53,7 +52,7 @@ import java.util.function.Function; import java.util.stream.Collectors; -public class GrpcServiceStubClassComposer extends AbstractServiceStubClassComposer { +public class GrpcServiceStubClassComposer extends AbstractTransportServiceStubClassComposer { private static final GrpcServiceStubClassComposer INSTANCE = new GrpcServiceStubClassComposer(); // Legacy support for the original reroute_to_grpc_interface option in gapic.yaml. These two APIs @@ -193,18 +192,6 @@ protected EnumRefExpr getMethodDescriptorMethodTypeExpr(Method protoMethod) { .build(); } - @Override - protected List createOperationsStubGetterMethod( - VariableExpr operationsStubVarExpr) { - return Arrays.asList( - MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setReturnType(operationsStubVarExpr.type()) - .setName("getOperationsStub") - .setReturnExpr(operationsStubVarExpr) - .build()); - } - @Override protected Expr createTransportSettingsInitExpr( Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr) { diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposer.java new file mode 100644 index 0000000000..9b95e9c280 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposer.java @@ -0,0 +1,30 @@ +/* + * 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.grpc; + +import com.google.api.generator.gapic.composer.common.AbstractServiceClientClassComposer; + +public class ServiceClientClassComposer extends AbstractServiceClientClassComposer { + private static final ServiceClientClassComposer INSTANCE = new ServiceClientClassComposer(); + + protected ServiceClientClassComposer() { + super(GrpcContext.instance()); + } + + public static ServiceClientClassComposer instance() { + return 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 15b05ee765..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)); @@ -1055,6 +1056,12 @@ protected List createStreamingRpcExceptionTestStatements( return statements; } + @Override + protected Expr createDefaultValue( + MethodArgument methodArg, Map resourceNames) { + return DefaultValueComposer.createDefaultValue(methodArg, resourceNames, false); + } + @Override protected List createRpcLroExceptionTestCatchBody( VariableExpr exceptionExpr, boolean isStreaming) { diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposer.java new file mode 100644 index 0000000000..1e11c5087d --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposer.java @@ -0,0 +1,30 @@ +/* + * 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.grpc; + +import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; + +public class ServiceStubClassComposer extends AbstractServiceStubClassComposer { + private static final ServiceStubClassComposer INSTANCE = new ServiceStubClassComposer(); + + protected ServiceStubClassComposer() { + super(GrpcContext.instance()); + } + + public static ServiceStubClassComposer instance() { + return INSTANCE; + } +} 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 7f8a966859..a7b525239e 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 @@ -27,13 +27,14 @@ import com.google.api.generator.engine.ast.NewObjectExpr; import com.google.api.generator.engine.ast.Statement; import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; import com.google.api.generator.engine.ast.VaporReference; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.gapic.composer.common.AbstractServiceCallableFactoryClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.model.Service; -import com.google.longrunning.Operation; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -45,7 +46,7 @@ public class HttpJsonServiceCallableFactoryClassComposer new HttpJsonServiceCallableFactoryClassComposer(); private static final TypeNode DEFAULT_OPERATION_TYPE = - TypeNode.withReference(ConcreteReference.withClazz(Operation.class)); + TypeNode.withReference(ConcreteReference.withClazz(Object.class)); private HttpJsonServiceCallableFactoryClassComposer() { super(RestContext.instance()); @@ -127,7 +128,16 @@ protected MethodDefinition createOperationCallableMethod(Service service, TypeSt .collect(Collectors.toList()), Arrays.asList(betaAnnotation)); - List createOperationCallableBody = new ArrayList(2); + List createOperationCallableBody = new ArrayList<>(); + if (service.operationServiceStubType() == null) { + // It is an Operation polling service, it cannot contain LRO methods + return method + .toBuilder() + .setBody(ImmutableList.of()) + .setReturnExpr(ValueExpr.createNullExpr()) + .build(); + } + List arguments = new ArrayList<>(method.arguments()); Variable httpJsonCallSettingsVar = arguments.get(0).variable(); diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java index 39974fe44a..fb45703936 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java @@ -49,8 +49,7 @@ import com.google.api.generator.engine.ast.VaporReference; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; -import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; -import com.google.api.generator.gapic.composer.common.TransportContext; +import com.google.api.generator.gapic.composer.common.AbstractTransportServiceStubClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.model.HttpBindings.HttpBinding; import com.google.api.generator.gapic.model.Message; @@ -66,12 +65,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; -public class HttpJsonServiceStubClassComposer extends AbstractServiceStubClassComposer { +public class HttpJsonServiceStubClassComposer extends AbstractTransportServiceStubClassComposer { private static final HttpJsonServiceStubClassComposer INSTANCE = new HttpJsonServiceStubClassComposer(); @@ -101,6 +101,11 @@ private static TypeStore createStaticTypes() { ProtoRestSerializer.class)); } + @Override + protected boolean generateOperationsStubLogic(Service service) { + return service.hasLroMethods(); + } + @Override protected Statement createMethodDescriptorVariableDecl( Service service, @@ -172,12 +177,11 @@ protected Statement createMethodDescriptorVariableDecl( @Override protected List createOperationsStubGetterMethod( - VariableExpr operationsStubVarExpr) { - return Collections.emptyList(); - } - - public HttpJsonServiceStubClassComposer(TransportContext transportContext) { - super(transportContext); + Service service, VariableExpr operationsStubVarExpr) { + if (!service.hasStandardLroMethods()) { + return Collections.emptyList(); + } + return super.createOperationsStubGetterMethod(service, operationsStubVarExpr); } @Override @@ -348,16 +352,20 @@ private List getRequestFormatterExpr(Method protoMethod) { .apply(expr); extractorVarType = TypeNode.STRING; + boolean asteriskBody = protoMethod.httpBindings().isAsteriskBody(); expr = methodMaker .apply( "setRequestBodyExtractor", Arrays.asList( - createFieldsExtractorClassInstance( + createBodyFieldsExtractorClassInstance( protoMethod, extractorVarType, - protoMethod.httpBindings().bodyParameters(), - "toBody"))) + asteriskBody + ? protoMethod.httpBindings().pathParameters() + : protoMethod.httpBindings().bodyParameters(), + "toBody", + asteriskBody))) .apply(expr); expr = methodMaker.apply("build", Collections.emptyList()).apply(expr); @@ -699,71 +707,148 @@ private List setPollingRequestFactoryExpr( .build()); } - private Expr createFieldsExtractorClassInstance( + private Expr createBodyFieldsExtractorClassInstance( Method method, TypeNode extractorReturnType, Set httpBindingFieldNames, - String serializerMethodName) { + String serializerMethodName, + boolean asteriskBody) { List bodyStatements = new ArrayList<>(); Expr returnExpr = null; - VariableExpr fieldsVarExpr = null; - Expr serializerExpr = null; - if (extractorReturnType.isProtoPrimitiveType()) { - serializerExpr = + Expr serializerExpr = + MethodInvocationExpr.builder() + .setMethodName("create") + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) + .build(); + + VariableExpr requestVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(method.inputType()).setName("request").build()); + Expr bodyRequestExpr = requestVarExpr; + String requestMethodPrefix = "get"; + String bodyParamName = null; + + if (asteriskBody) { + bodyRequestExpr = MethodInvocationExpr.builder() - .setMethodName("create") - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) + .setExprReferenceExpr(requestVarExpr) + .setMethodName("toBuilder") .build(); - if (httpBindingFieldNames.isEmpty()) { - returnExpr = ValueExpr.createNullExpr(); + // In case of `body: "*"` case we send the whole request message as a body, minus the fields + // in the path, therefore the "clear" prefix here. + requestMethodPrefix = "clear"; + } + + Expr prevExpr = bodyRequestExpr; + for (HttpBinding httpBindingFieldName : httpBindingFieldNames) { + // Handle foo.bar cases by descending into the subfields. + MethodInvocationExpr.Builder requestFieldMethodExprBuilder = + MethodInvocationExpr.builder().setExprReferenceExpr(prevExpr); + bodyParamName = JavaStyle.toLowerCamelCase(httpBindingFieldName.name()); + String[] descendantFields = httpBindingFieldName.name().split("\\."); + if (asteriskBody && descendantFields.length > 1) { + // This is the `body: "*"` case, do not clean nested body fields as it a very rare, not + // well-defined case, and it is generally safer to send more than less in such case. + continue; } + for (int i = 0; i < descendantFields.length; i++) { + String currFieldName = descendantFields[i]; + String bindingFieldMethodName = + String.format("%s%s", requestMethodPrefix, JavaStyle.toUpperCamelCase(currFieldName)); + requestFieldMethodExprBuilder = + requestFieldMethodExprBuilder.setMethodName(bindingFieldMethodName); + + if (i < descendantFields.length - 1) { + requestFieldMethodExprBuilder = + MethodInvocationExpr.builder() + .setExprReferenceExpr(requestFieldMethodExprBuilder.build()); + } + } + prevExpr = requestFieldMethodExprBuilder.build(); + } + + if (httpBindingFieldNames.isEmpty() && !asteriskBody) { + returnExpr = ValueExpr.createNullExpr(); } else { - fieldsVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("fields").setType(extractorReturnType).build()); - Expr fieldsAssignExpr = - AssignmentExpr.builder() - .setVariableExpr(fieldsVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr( - NewObjectExpr.builder() - .setType(FIXED_REST_TYPESTORE.get(HashMap.class.getSimpleName())) - .setIsGeneric(true) - .build()) + ImmutableList.Builder paramsPutArgs = ImmutableList.builder(); + if (asteriskBody) { + prevExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(prevExpr) + .setMethodName("build") + .build(); + bodyParamName = "*"; + } + paramsPutArgs.add(ValueExpr.withValue(StringObjectValue.withValue(bodyParamName))); + paramsPutArgs.add(prevExpr); + + returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(serializerExpr) + .setMethodName(serializerMethodName) + .setArguments(paramsPutArgs.build()) + .setReturnType(extractorReturnType) .build(); + } + + // Overrides FieldsExtractor + // (https://github.com/googleapis/gax-java/blob/12b18ee255d3fabe13bb3969df40753b29f830d5/gax-httpjson/src/main/java/com/google/api/gax/httpjson/FieldsExtractor.java). + return LambdaExpr.builder() + .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) + .setBody(bodyStatements) + .setReturnExpr(returnExpr) + .build(); + } - bodyStatements.add(ExprStatement.withExpr(fieldsAssignExpr)); - returnExpr = fieldsVarExpr; + private Expr createFieldsExtractorClassInstance( + Method method, + TypeNode extractorReturnType, + Set httpBindingFieldNames, + String serializerMethodName) { + List bodyStatements = new ArrayList<>(); - TypeNode serializerVarType = - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(ProtoRestSerializer.class) - .setGenerics(method.inputType().reference()) - .build()); + VariableExpr fieldsVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("fields").setType(extractorReturnType).build()); + Expr fieldsAssignExpr = + AssignmentExpr.builder() + .setVariableExpr(fieldsVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + NewObjectExpr.builder() + .setType(FIXED_REST_TYPESTORE.get(HashMap.class.getSimpleName())) + .setIsGeneric(true) + .build()) + .build(); - VariableExpr serializerVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("serializer").setType(serializerVarType).build()); + bodyStatements.add(ExprStatement.withExpr(fieldsAssignExpr)); - Expr serializerAssignExpr = - AssignmentExpr.builder() - .setVariableExpr(serializerVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) - .setMethodName("create") - .setReturnType(serializerVarType) - .build()) - .build(); + TypeNode serializerVarType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(ProtoRestSerializer.class) + .setGenerics(method.inputType().reference()) + .build()); - serializerExpr = serializerVarExpr; + VariableExpr serializerVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("serializer").setType(serializerVarType).build()); - bodyStatements.add(ExprStatement.withExpr(serializerAssignExpr)); - } + Expr serializerAssignExpr = + AssignmentExpr.builder() + .setVariableExpr(serializerVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) + .setMethodName("create") + .setReturnType(serializerVarType) + .build()) + .build(); + + bodyStatements.add(ExprStatement.withExpr(serializerAssignExpr)); VariableExpr requestVarExpr = VariableExpr.withVariable( @@ -806,9 +891,9 @@ private Expr createFieldsExtractorClassInstance( MethodInvocationExpr requestHasExpr = requestFieldHasExprBuilder.build(); ImmutableList.Builder paramsPutArgs = ImmutableList.builder(); - if (fieldsVarExpr != null) { - paramsPutArgs.add(fieldsVarExpr); - } + + paramsPutArgs.add(fieldsVarExpr); + paramsPutArgs.add( ValueExpr.withValue( StringObjectValue.withValue( @@ -817,24 +902,20 @@ private Expr createFieldsExtractorClassInstance( Expr paramsPutExpr = MethodInvocationExpr.builder() - .setExprReferenceExpr(serializerExpr) + .setExprReferenceExpr(serializerVarExpr) .setMethodName(serializerMethodName) .setArguments(paramsPutArgs.build()) .setReturnType(extractorReturnType) .build(); - if (fieldsVarExpr == null) { - returnExpr = paramsPutExpr; + if (httpBindingFieldName.isOptional()) { + bodyStatements.add( + IfStatement.builder() + .setConditionExpr(requestHasExpr) + .setBody(Arrays.asList(ExprStatement.withExpr(paramsPutExpr))) + .build()); } else { - if (httpBindingFieldName.isOptional()) { - bodyStatements.add( - IfStatement.builder() - .setConditionExpr(requestHasExpr) - .setBody(Arrays.asList(ExprStatement.withExpr(paramsPutExpr))) - .build()); - } else { - bodyStatements.add(ExprStatement.withExpr(paramsPutExpr)); - } + bodyStatements.add(ExprStatement.withExpr(paramsPutExpr)); } } @@ -843,7 +924,7 @@ private Expr createFieldsExtractorClassInstance( return LambdaExpr.builder() .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) .setBody(bodyStatements) - .setReturnExpr(returnExpr) + .setReturnExpr(fieldsVarExpr) .build(); } @@ -942,24 +1023,25 @@ protected VariableExpr declareLongRunningClient() { .build()); } - @Override - protected List createLongRunningClientGetter() { - VariableExpr longRunningClient = - VariableExpr.withVariable( - Variable.builder() - .setName("longRunningClient") - .setType( - TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) - .build()); + protected Optional getCallableCreatorMethodName(TypeNode callableVarExprType) { + final String typeName = callableVarExprType.reference().name(); + String streamName = "Unary"; - return ImmutableList.of( - MethodDefinition.builder() - .setName("longRunningClient") - .setScope(ScopeNode.PUBLIC) - .setIsOverride(true) - .setReturnType( - TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) - .setReturnExpr(longRunningClient) - .build()); + // Special handling for pagination methods. + if (callableVarExprType.reference().generics().size() == 2 + && callableVarExprType.reference().generics().get(1).name().endsWith("PagedResponse")) { + streamName = "Paged"; + } else { + if (typeName.startsWith("Client")) { + return Optional.empty(); // not supported in REST transport + } else if (typeName.startsWith("Server")) { + return Optional.empty(); // not supported in REST transport (for now) + } else if (typeName.startsWith("Bidi")) { + return Optional.empty(); // not supported in REST transport + } else if (typeName.startsWith("Operation")) { + streamName = "Operation"; + } + } + return Optional.of(String.format("create%sCallable", streamName)); } } 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 fc5b385427..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 @@ -21,9 +21,13 @@ import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; import com.google.api.gax.httpjson.HttpJsonTransportChannel; import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.httpjson.ProtoOperationTransformers; +import com.google.api.gax.httpjson.longrunning.OperationsClient; +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; public abstract class RestContext extends TransportContext { private static final TransportContext INSTANCE = @@ -35,18 +39,35 @@ public abstract class RestContext extends TransportContext { .setCallSettingsClass(HttpJsonCallSettings.class) .setStubCallableFactoryType(classToType(HttpJsonStubCallableFactory.class)) .setMethodDescriptorClass(ApiMethodDescriptor.class) - .setTransportOperationsStubType(null) + .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)) - .setOperationsStubType(classToType(BackgroundResource.class)) + // TODO: set to com.google.api.gax.httpjson.longrunning.stub.OperationsStub.class + .setOperationsStubTypes(ImmutableList.of(classToType(BackgroundResource.class))) .setTransportCallSettingsName("httpJsonCallSettings") + // For RetrySettingsComposer + .setOperationResponseTransformerType( + classToType(ProtoOperationTransformers.ResponseTransformer.class)) + .setOperationMetadataTransformerType( + classToType(ProtoOperationTransformers.MetadataTransformer.class)) + // For ServiceClientClassComposer + .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/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientClassComposer.java new file mode 100644 index 0000000000..9b5f996db7 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientClassComposer.java @@ -0,0 +1,30 @@ +/* + * 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.rest; + +import com.google.api.generator.gapic.composer.common.AbstractServiceClientClassComposer; + +public class ServiceClientClassComposer extends AbstractServiceClientClassComposer { + private static final ServiceClientClassComposer INSTANCE = new ServiceClientClassComposer(); + + protected ServiceClientClassComposer() { + super(RestContext.instance()); + } + + public static ServiceClientClassComposer instance() { + return 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 5eed17f8f2..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 @@ -39,6 +39,7 @@ import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.gapic.composer.common.AbstractServiceClientTestClassComposer; +import com.google.api.generator.gapic.composer.defaultvalue.DefaultValueComposer; 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.GapicContext; @@ -72,7 +73,7 @@ protected ServiceClientTestClassComposer() { super(RestContext.instance()); } - public static ServiceClientTestClassComposer instance() { + public static AbstractServiceClientTestClassComposer instance() { return INSTANCE; } @@ -125,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); @@ -167,7 +169,7 @@ protected MethodDefinition createStartStaticServerMethod( Expr settingsBuilderExpr = MethodInvocationExpr.builder() .setStaticReferenceType(settingsType) - .setMethodName("newBuilder") + .setMethodName(newBuilderMethod) .build(); Expr transportChannelProviderExpr = @@ -420,7 +422,18 @@ protected MethodDefinition createStreamingRpcTestMethod( Map classMemberVarExprs, Map resourceNames, Map messageTypes) { - return null; + // Add some actual statements once implemented + List methodStatements = new ArrayList<>(); + + String testMethodName = String.format("%sTest", JavaStyle.toLowerCamelCase(method.name())); + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(TEST_ANNOTATION)) + .setScope(ScopeNode.PUBLIC) + .setReturnType(TypeNode.VOID) + .setName(testMethodName) + .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(Exception.class))) + .setBody(methodStatements) + .build(); } @Override @@ -513,6 +526,12 @@ protected List createStreamingRpcExceptionTestStatements( return Collections.emptyList(); } + @Override + protected Expr createDefaultValue( + MethodArgument methodArg, Map resourceNames) { + return DefaultValueComposer.createDefaultValue(methodArg, resourceNames, true); + } + @Override protected List createRpcLroExceptionTestCatchBody( VariableExpr exceptionExpr, boolean isStreaming) { diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubClassComposer.java new file mode 100644 index 0000000000..704fac96b6 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubClassComposer.java @@ -0,0 +1,30 @@ +/* + * 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.rest; + +import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; + +public class ServiceStubClassComposer extends AbstractServiceStubClassComposer { + private static final ServiceStubClassComposer INSTANCE = new ServiceStubClassComposer(); + + protected ServiceStubClassComposer() { + super(RestContext.instance()); + } + + public static ServiceStubClassComposer instance() { + return INSTANCE; + } +} 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/samplecode/ServiceClientSampleCodeComposer.java b/src/main/java/com/google/api/generator/gapic/composer/samplecode/ServiceClientSampleCodeComposer.java index ac8d805b59..5572bde8e3 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/samplecode/ServiceClientSampleCodeComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/samplecode/ServiceClientSampleCodeComposer.java @@ -1310,7 +1310,7 @@ private static List createRpcMethodArgumentDefaultValueExprs( .map( arg -> !isStringTypedResourceName(arg, resourceNames) - ? DefaultValueComposer.createDefaultValue(arg, resourceNames) + ? DefaultValueComposer.createDefaultValue(arg, resourceNames, false) : stringResourceNameDefaultValueExpr.apply(arg)) .collect(Collectors.toList()); } 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/HttpBindings.java b/src/main/java/com/google/api/generator/gapic/model/HttpBindings.java index 9ca67cf4c7..171f6b1bf7 100644 --- a/src/main/java/com/google/api/generator/gapic/model/HttpBindings.java +++ b/src/main/java/com/google/api/generator/gapic/model/HttpBindings.java @@ -57,6 +57,8 @@ public int compareTo(HttpBinding o) { public abstract Set bodyParameters(); + public abstract boolean isAsteriskBody(); + public static HttpBindings.Builder builder() { return new AutoValue_HttpBindings.Builder() .setPathParameters(ImmutableSet.of()) @@ -93,6 +95,8 @@ public abstract static class Builder { public abstract HttpBindings.Builder setBodyParameters(Set bodyParameters); + public abstract HttpBindings.Builder setIsAsteriskBody(boolean asteriskBody); + public abstract HttpBindings autoBuild(); public HttpBindings build() { diff --git a/src/main/java/com/google/api/generator/gapic/model/Service.java b/src/main/java/com/google/api/generator/gapic/model/Service.java index ace91051bc..34d3f97b25 100644 --- a/src/main/java/com/google/api/generator/gapic/model/Service.java +++ b/src/main/java/com/google/api/generator/gapic/model/Service.java @@ -79,6 +79,24 @@ public TypeNode operationType() { return null; } + public boolean hasLroMethods() { + for (Method method : methods()) { + if (method.hasLro()) { + return true; + } + } + return false; + } + + public boolean hasStandardLroMethods() { + for (Method method : methods()) { + if (method.hasLro() && method.lro().operationServiceStubType() == null) { + return true; + } + } + return false; + } + public abstract Builder toBuilder(); public static Builder builder() { 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/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java b/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java index 26629949ef..36828206d3 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java +++ b/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java @@ -104,6 +104,7 @@ private static HttpBindings parseHttpRuleHelper( validateAndConstructHttpBindings(queryParamNames, message, messageTypes, false)) .setBodyParameters( validateAndConstructHttpBindings(bodyParamNames, message, messageTypes, false)) + .setIsAsteriskBody(body.equals(ASTERISK)) .build(); } 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", diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel index 159c97d9b1..28a4bfc8b4 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel @@ -5,8 +5,6 @@ package(default_visibility = ["//visibility:public"]) UPDATE_GOLDENS_TESTS = [ "BatchingDescriptorComposerTest", - "ServiceClientClassComposerTest", - "ServiceStubClassComposerTest", ] TESTS = UPDATE_GOLDENS_TESTS + [ diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java index 09b1bf5b1c..d3fa5aa2e9 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java @@ -27,6 +27,7 @@ import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.engine.writer.JavaWriterVisitor; +import com.google.api.generator.gapic.composer.grpc.GrpcContext; import com.google.api.generator.gapic.model.GapicBatchingSettings; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.GapicServiceConfig; @@ -329,7 +330,9 @@ public void lroBuilderExpr() { waitMethod, builderVarExpr, RETRY_CODES_DEFINITIONS_VAR_EXPR, - RETRY_PARAM_DEFINITIONS_VAR_EXPR); + RETRY_PARAM_DEFINITIONS_VAR_EXPR, + GrpcContext.instance().operationResponseTransformerType(), + GrpcContext.instance().operationMetadataTransformerType()); builderExpr.accept(writerVisitor); String expected = LineFormatter.lines( diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel index 14ac8deeba..825635a75e 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel @@ -8,8 +8,10 @@ TESTS = [ "GrpcServiceStubClassComposerTest", "MockServiceClassComposerTest", "MockServiceImplClassComposerTest", + "ServiceClientClassComposerTest", "ServiceClientTestClassComposerTest", "ServiceSettingsClassComposerTest", + "ServiceStubClassComposerTest", "ServiceStubSettingsClassComposerTest", ] diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposerTest.java similarity index 89% rename from src/test/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposerTest.java index b7767f41a6..331b94e484 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposerTest.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer.common; +package com.google.api.generator.gapic.composer.grpc; import static com.google.api.generator.test.framework.Assert.assertCodeEquals; @@ -28,7 +28,7 @@ public class ServiceClientClassComposerTest { @Test public void generateServiceClasses() { - GapicContext context = TestProtoLoader.instance().parseShowcaseEcho(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, echoProtoService); @@ -41,7 +41,7 @@ public void generateServiceClasses() { @Test public void generateServiceClasses_deprecated() { - GapicContext context = TestProtoLoader.instance().parseDeprecatedService(); + GapicContext context = GrpcTestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, protoService); @@ -55,7 +55,7 @@ public void generateServiceClasses_deprecated() { @Test public void generateServiceClasses_methodSignatureHasNestedFields() { - GapicContext context = TestProtoLoader.instance().parseShowcaseIdentity(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseIdentity(); Service protoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, protoService); @@ -68,7 +68,7 @@ public void generateServiceClasses_methodSignatureHasNestedFields() { @Test public void generateServiceClasses_bookshopNameConflicts() { - GapicContext context = TestProtoLoader.instance().parseBookshopService(); + GapicContext context = GrpcTestProtoLoader.instance().parseBookshopService(); Service protoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, protoService); diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposerTest.java similarity index 94% rename from src/test/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposerTest.java index b30ce3630c..bb411b9ad3 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposerTest.java @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer.common; +package com.google.api.generator.gapic.composer.grpc; import com.google.api.generator.engine.writer.JavaWriterVisitor; +import com.google.api.generator.gapic.composer.common.TestProtoLoader; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/BookshopClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/BookshopClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/BookshopClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/BookshopClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/IdentityClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/IdentityClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/IdentityClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/IdentityClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java index e3e5641f93..53392a549e 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java @@ -27,7 +27,7 @@ public class ServiceStubSettingsClassComposerTest { @Test public void generateServiceStubSettingsClasses_basic() { - GapicContext context = RestTestProtoLoader.instance().parseShowcaseEcho(); + GapicContext context = RestTestProtoLoader.instance().parseCompliance(); Service echoProtoService = context.services().get(0); GapicClass clazz = ServiceStubSettingsClassComposer.instance().generate(context, echoProtoService); diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden index 3535651104..a858c0123e 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden @@ -1,60 +1,33 @@ package com.google.showcase.v1beta1.stub; -import static com.google.showcase.v1beta1.EchoClient.PagedExpandPagedResponse; -import static com.google.showcase.v1beta1.EchoClient.SimplePagedExpandPagedResponse; - import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; import com.google.api.core.BetaApi; import com.google.api.gax.core.GaxProperties; import com.google.api.gax.core.GoogleCredentialsProvider; import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.grpc.ProtoOperationTransformers; 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.longrunning.OperationSnapshot; -import com.google.api.gax.longrunning.OperationTimedPollAlgorithm; import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiCallContext; import com.google.api.gax.rpc.ApiClientHeaderProvider; import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.PageContext; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.PagedListDescriptor; -import com.google.api.gax.rpc.PagedListResponseFactory; -import com.google.api.gax.rpc.ServerStreamingCallSettings; import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StreamingCallSettings; import com.google.api.gax.rpc.StubSettings; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; -import com.google.longrunning.Operation; -import com.google.showcase.v1beta1.BlockRequest; -import com.google.showcase.v1beta1.BlockResponse; -import com.google.showcase.v1beta1.EchoRequest; -import com.google.showcase.v1beta1.EchoResponse; -import com.google.showcase.v1beta1.ExpandRequest; -import com.google.showcase.v1beta1.Object; -import com.google.showcase.v1beta1.PagedExpandRequest; -import com.google.showcase.v1beta1.PagedExpandResponse; -import com.google.showcase.v1beta1.WaitMetadata; -import com.google.showcase.v1beta1.WaitRequest; -import com.google.showcase.v1beta1.WaitResponse; +import com.google.showcase.v1beta1.RepeatRequest; +import com.google.showcase.v1beta1.RepeatResponse; import java.io.IOException; import java.util.List; import javax.annotation.Generated; -import org.threeten.bp.Duration; // AUTO-GENERATED DOCUMENTATION AND CLASS. /** - * Settings class to configure an instance of {@link EchoStub}. + * Settings class to configure an instance of {@link ComplianceStub}. * *

The default instance has everything set to sensible defaults: * @@ -67,214 +40,73 @@ import org.threeten.bp.Duration; *

The builder of this class is recursive, so contained classes are themselves builders. When * build() is called, the tree of builders is called to create the complete settings object. * - *

For example, to set the total timeout of echo to 30 seconds: + *

For example, to set the total timeout of repeatDataBody to 30 seconds: * *

{@code
- * EchoStubSettings.Builder echoSettingsBuilder = EchoStubSettings.newBuilder();
- * echoSettingsBuilder
- *     .echoSettings()
+ * ComplianceStubSettings.Builder complianceSettingsBuilder = ComplianceStubSettings.newBuilder();
+ * complianceSettingsBuilder
+ *     .repeatDataBodySettings()
  *     .setRetrySettings(
- *         echoSettingsBuilder
- *             .echoSettings()
+ *         complianceSettingsBuilder
+ *             .repeatDataBodySettings()
  *             .getRetrySettings()
  *             .toBuilder()
  *             .setTotalTimeout(Duration.ofSeconds(30))
  *             .build());
- * EchoStubSettings echoSettings = echoSettingsBuilder.build();
+ * ComplianceStubSettings complianceSettings = complianceSettingsBuilder.build();
  * }
*/ @BetaApi @Generated("by gapic-generator-java") -public class EchoStubSettings extends StubSettings { +public class ComplianceStubSettings extends StubSettings { /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = - ImmutableList.builder().add("https://www.googleapis.com/auth/cloud-platform").build(); - - private final UnaryCallSettings echoSettings; - private final ServerStreamingCallSettings expandSettings; - private final StreamingCallSettings collectSettings; - private final StreamingCallSettings chatSettings; - private final StreamingCallSettings chatAgainSettings; - private final PagedCallSettings - pagedExpandSettings; - private final PagedCallSettings< - PagedExpandRequest, PagedExpandResponse, SimplePagedExpandPagedResponse> - simplePagedExpandSettings; - private final UnaryCallSettings waitSettings; - private final OperationCallSettings - waitOperationSettings; - private final UnaryCallSettings blockSettings; - private final UnaryCallSettings collideNameSettings; - - private static final PagedListDescriptor - PAGED_EXPAND_PAGE_STR_DESC = - new PagedListDescriptor() { - @Override - public String emptyToken() { - return ""; - } - - @Override - public PagedExpandRequest injectToken(PagedExpandRequest payload, String token) { - return PagedExpandRequest.newBuilder(payload).setPageToken(token).build(); - } - - @Override - public PagedExpandRequest injectPageSize(PagedExpandRequest payload, int pageSize) { - return PagedExpandRequest.newBuilder(payload).setPageSize(pageSize).build(); - } - - @Override - public Integer extractPageSize(PagedExpandRequest payload) { - return payload.getPageSize(); - } - - @Override - public String extractNextToken(PagedExpandResponse payload) { - return payload.getNextPageToken(); - } - - @Override - public Iterable extractResources(PagedExpandResponse payload) { - return payload.getResponsesList() == null - ? ImmutableList.of() - : payload.getResponsesList(); - } - }; - - private static final PagedListDescriptor - SIMPLE_PAGED_EXPAND_PAGE_STR_DESC = - new PagedListDescriptor() { - @Override - public String emptyToken() { - return ""; - } - - @Override - public PagedExpandRequest injectToken(PagedExpandRequest payload, String token) { - return PagedExpandRequest.newBuilder(payload).setPageToken(token).build(); - } - - @Override - public PagedExpandRequest injectPageSize(PagedExpandRequest payload, int pageSize) { - return PagedExpandRequest.newBuilder(payload).setPageSize(pageSize).build(); - } - - @Override - public Integer extractPageSize(PagedExpandRequest payload) { - return payload.getPageSize(); - } - - @Override - public String extractNextToken(PagedExpandResponse payload) { - return payload.getNextPageToken(); - } - - @Override - public Iterable extractResources(PagedExpandResponse payload) { - return payload.getResponsesList() == null - ? ImmutableList.of() - : payload.getResponsesList(); - } - }; - - private static final PagedListResponseFactory< - PagedExpandRequest, PagedExpandResponse, PagedExpandPagedResponse> - PAGED_EXPAND_PAGE_STR_FACT = - new PagedListResponseFactory< - PagedExpandRequest, PagedExpandResponse, PagedExpandPagedResponse>() { - @Override - public ApiFuture getFuturePagedResponse( - UnaryCallable callable, - PagedExpandRequest request, - ApiCallContext context, - ApiFuture futureResponse) { - PageContext pageContext = - PageContext.create(callable, PAGED_EXPAND_PAGE_STR_DESC, request, context); - return PagedExpandPagedResponse.createAsync(pageContext, futureResponse); - } - }; - - private static final PagedListResponseFactory< - PagedExpandRequest, PagedExpandResponse, SimplePagedExpandPagedResponse> - SIMPLE_PAGED_EXPAND_PAGE_STR_FACT = - new PagedListResponseFactory< - PagedExpandRequest, PagedExpandResponse, SimplePagedExpandPagedResponse>() { - @Override - public ApiFuture getFuturePagedResponse( - UnaryCallable callable, - PagedExpandRequest request, - ApiCallContext context, - ApiFuture futureResponse) { - PageContext pageContext = - PageContext.create(callable, SIMPLE_PAGED_EXPAND_PAGE_STR_DESC, request, context); - return SimplePagedExpandPagedResponse.createAsync(pageContext, futureResponse); - } - }; - - /** Returns the object with the settings used for calls to echo. */ - public UnaryCallSettings echoSettings() { - return echoSettings; - } - - /** Returns the object with the settings used for calls to expand. */ - public ServerStreamingCallSettings expandSettings() { - return expandSettings; - } - - /** Returns the object with the settings used for calls to collect. */ - public StreamingCallSettings collectSettings() { - return collectSettings; - } - - /** Returns the object with the settings used for calls to chat. */ - public StreamingCallSettings chatSettings() { - return chatSettings; + ImmutableList.builder().build(); + + private final UnaryCallSettings repeatDataBodySettings; + private final UnaryCallSettings repeatDataBodyInfoSettings; + private final UnaryCallSettings repeatDataQuerySettings; + private final UnaryCallSettings repeatDataSimplePathSettings; + private final UnaryCallSettings repeatDataPathResourceSettings; + private final UnaryCallSettings + repeatDataPathTrailingResourceSettings; + + /** Returns the object with the settings used for calls to repeatDataBody. */ + public UnaryCallSettings repeatDataBodySettings() { + return repeatDataBodySettings; } - /** Returns the object with the settings used for calls to chatAgain. */ - public StreamingCallSettings chatAgainSettings() { - return chatAgainSettings; + /** Returns the object with the settings used for calls to repeatDataBodyInfo. */ + public UnaryCallSettings repeatDataBodyInfoSettings() { + return repeatDataBodyInfoSettings; } - /** Returns the object with the settings used for calls to pagedExpand. */ - public PagedCallSettings - pagedExpandSettings() { - return pagedExpandSettings; + /** Returns the object with the settings used for calls to repeatDataQuery. */ + public UnaryCallSettings repeatDataQuerySettings() { + return repeatDataQuerySettings; } - /** Returns the object with the settings used for calls to simplePagedExpand. */ - public PagedCallSettings - simplePagedExpandSettings() { - return simplePagedExpandSettings; + /** Returns the object with the settings used for calls to repeatDataSimplePath. */ + public UnaryCallSettings repeatDataSimplePathSettings() { + return repeatDataSimplePathSettings; } - /** Returns the object with the settings used for calls to wait. */ - public UnaryCallSettings waitSettings() { - return waitSettings; + /** Returns the object with the settings used for calls to repeatDataPathResource. */ + public UnaryCallSettings repeatDataPathResourceSettings() { + return repeatDataPathResourceSettings; } - /** Returns the object with the settings used for calls to wait. */ - public OperationCallSettings waitOperationSettings() { - return waitOperationSettings; - } - - /** Returns the object with the settings used for calls to block. */ - public UnaryCallSettings blockSettings() { - return blockSettings; - } - - /** Returns the object with the settings used for calls to collideName. */ - public UnaryCallSettings collideNameSettings() { - return collideNameSettings; + /** Returns the object with the settings used for calls to repeatDataPathTrailingResource. */ + public UnaryCallSettings repeatDataPathTrailingResourceSettings() { + return repeatDataPathTrailingResourceSettings; } @BetaApi("A restructuring of stub classes is planned, so this may break in the future") - public EchoStub createStub() throws IOException { + public ComplianceStub createStub() throws IOException { if (getTransportChannelProvider() .getTransportName() .equals(HttpJsonTransportChannel.getHttpJsonTransportName())) { - return HttpJsonEchoStub.create(this); + return HttpJsonComplianceStub.create(this); } throw new UnsupportedOperationException( String.format( @@ -319,7 +151,8 @@ public class EchoStubSettings extends StubSettings { @BetaApi("The surface for customizing headers is not stable yet and may change in the future.") public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() { return ApiClientHeaderProvider.newBuilder() - .setGeneratedLibToken("gapic", GaxProperties.getLibraryVersion(EchoStubSettings.class)) + .setGeneratedLibToken( + "gapic", GaxProperties.getLibraryVersion(ComplianceStubSettings.class)) .setTransportToken( GaxHttpJsonProperties.getHttpJsonTokenName(), GaxHttpJsonProperties.getHttpJsonVersion()); @@ -340,54 +173,38 @@ public class EchoStubSettings extends StubSettings { return new Builder(this); } - protected EchoStubSettings(Builder settingsBuilder) throws IOException { + protected ComplianceStubSettings(Builder settingsBuilder) throws IOException { super(settingsBuilder); - echoSettings = settingsBuilder.echoSettings().build(); - expandSettings = settingsBuilder.expandSettings().build(); - collectSettings = settingsBuilder.collectSettings().build(); - chatSettings = settingsBuilder.chatSettings().build(); - chatAgainSettings = settingsBuilder.chatAgainSettings().build(); - pagedExpandSettings = settingsBuilder.pagedExpandSettings().build(); - simplePagedExpandSettings = settingsBuilder.simplePagedExpandSettings().build(); - waitSettings = settingsBuilder.waitSettings().build(); - waitOperationSettings = settingsBuilder.waitOperationSettings().build(); - blockSettings = settingsBuilder.blockSettings().build(); - collideNameSettings = settingsBuilder.collideNameSettings().build(); + repeatDataBodySettings = settingsBuilder.repeatDataBodySettings().build(); + repeatDataBodyInfoSettings = settingsBuilder.repeatDataBodyInfoSettings().build(); + repeatDataQuerySettings = settingsBuilder.repeatDataQuerySettings().build(); + repeatDataSimplePathSettings = settingsBuilder.repeatDataSimplePathSettings().build(); + repeatDataPathResourceSettings = settingsBuilder.repeatDataPathResourceSettings().build(); + repeatDataPathTrailingResourceSettings = + settingsBuilder.repeatDataPathTrailingResourceSettings().build(); } - /** Builder for EchoStubSettings. */ - public static class Builder extends StubSettings.Builder { + /** Builder for ComplianceStubSettings. */ + public static class Builder extends StubSettings.Builder { private final ImmutableList> unaryMethodSettingsBuilders; - private final UnaryCallSettings.Builder echoSettings; - private final ServerStreamingCallSettings.Builder expandSettings; - private final StreamingCallSettings.Builder collectSettings; - private final StreamingCallSettings.Builder chatSettings; - private final StreamingCallSettings.Builder chatAgainSettings; - private final PagedCallSettings.Builder< - PagedExpandRequest, PagedExpandResponse, PagedExpandPagedResponse> - pagedExpandSettings; - private final PagedCallSettings.Builder< - PagedExpandRequest, PagedExpandResponse, SimplePagedExpandPagedResponse> - simplePagedExpandSettings; - private final UnaryCallSettings.Builder waitSettings; - private final OperationCallSettings.Builder - waitOperationSettings; - private final UnaryCallSettings.Builder blockSettings; - private final UnaryCallSettings.Builder collideNameSettings; + private final UnaryCallSettings.Builder repeatDataBodySettings; + private final UnaryCallSettings.Builder + repeatDataBodyInfoSettings; + private final UnaryCallSettings.Builder repeatDataQuerySettings; + private final UnaryCallSettings.Builder + repeatDataSimplePathSettings; + private final UnaryCallSettings.Builder + repeatDataPathResourceSettings; + private final UnaryCallSettings.Builder + repeatDataPathTrailingResourceSettings; private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; static { ImmutableMap.Builder> definitions = ImmutableMap.builder(); - definitions.put( - "retry_policy_1_codes", - ImmutableSet.copyOf( - Lists.newArrayList( - StatusCode.Code.UNAVAILABLE, StatusCode.Code.UNKNOWN))); - definitions.put( - "no_retry_0_codes", ImmutableSet.copyOf(Lists.newArrayList())); + definitions.put("no_retry_codes", ImmutableSet.copyOf(Lists.newArrayList())); RETRYABLE_CODE_DEFINITIONS = definitions.build(); } @@ -396,25 +213,8 @@ public class EchoStubSettings extends StubSettings { static { ImmutableMap.Builder definitions = ImmutableMap.builder(); RetrySettings settings = null; - settings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(100L)) - .setRetryDelayMultiplier(2.0) - .setMaxRetryDelay(Duration.ofMillis(3000L)) - .setInitialRpcTimeout(Duration.ofMillis(10000L)) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(Duration.ofMillis(10000L)) - .setTotalTimeout(Duration.ofMillis(10000L)) - .build(); - definitions.put("retry_policy_1_params", settings); - settings = - RetrySettings.newBuilder() - .setInitialRpcTimeout(Duration.ofMillis(5000L)) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(Duration.ofMillis(5000L)) - .setTotalTimeout(Duration.ofMillis(5000L)) - .build(); - definitions.put("no_retry_0_params", settings); + settings = RetrySettings.newBuilder().setRpcTimeoutMultiplier(1.0).build(); + definitions.put("no_retry_params", settings); RETRY_PARAM_DEFINITIONS = definitions.build(); } @@ -425,52 +225,43 @@ public class EchoStubSettings extends StubSettings { protected Builder(ClientContext clientContext) { super(clientContext); - echoSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - expandSettings = ServerStreamingCallSettings.newBuilder(); - collectSettings = StreamingCallSettings.newBuilder(); - chatSettings = StreamingCallSettings.newBuilder(); - chatAgainSettings = StreamingCallSettings.newBuilder(); - pagedExpandSettings = PagedCallSettings.newBuilder(PAGED_EXPAND_PAGE_STR_FACT); - simplePagedExpandSettings = PagedCallSettings.newBuilder(SIMPLE_PAGED_EXPAND_PAGE_STR_FACT); - waitSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - waitOperationSettings = OperationCallSettings.newBuilder(); - blockSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - collideNameSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + repeatDataBodySettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + repeatDataBodyInfoSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + repeatDataQuerySettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + repeatDataSimplePathSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + repeatDataPathResourceSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + repeatDataPathTrailingResourceSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); unaryMethodSettingsBuilders = ImmutableList.>of( - echoSettings, - pagedExpandSettings, - simplePagedExpandSettings, - waitSettings, - blockSettings, - collideNameSettings); + repeatDataBodySettings, + repeatDataBodyInfoSettings, + repeatDataQuerySettings, + repeatDataSimplePathSettings, + repeatDataPathResourceSettings, + repeatDataPathTrailingResourceSettings); initDefaults(this); } - protected Builder(EchoStubSettings settings) { + protected Builder(ComplianceStubSettings settings) { super(settings); - echoSettings = settings.echoSettings.toBuilder(); - expandSettings = settings.expandSettings.toBuilder(); - collectSettings = settings.collectSettings.toBuilder(); - chatSettings = settings.chatSettings.toBuilder(); - chatAgainSettings = settings.chatAgainSettings.toBuilder(); - pagedExpandSettings = settings.pagedExpandSettings.toBuilder(); - simplePagedExpandSettings = settings.simplePagedExpandSettings.toBuilder(); - waitSettings = settings.waitSettings.toBuilder(); - waitOperationSettings = settings.waitOperationSettings.toBuilder(); - blockSettings = settings.blockSettings.toBuilder(); - collideNameSettings = settings.collideNameSettings.toBuilder(); + repeatDataBodySettings = settings.repeatDataBodySettings.toBuilder(); + repeatDataBodyInfoSettings = settings.repeatDataBodyInfoSettings.toBuilder(); + repeatDataQuerySettings = settings.repeatDataQuerySettings.toBuilder(); + repeatDataSimplePathSettings = settings.repeatDataSimplePathSettings.toBuilder(); + repeatDataPathResourceSettings = settings.repeatDataPathResourceSettings.toBuilder(); + repeatDataPathTrailingResourceSettings = + settings.repeatDataPathTrailingResourceSettings.toBuilder(); unaryMethodSettingsBuilders = ImmutableList.>of( - echoSettings, - pagedExpandSettings, - simplePagedExpandSettings, - waitSettings, - blockSettings, - collideNameSettings); + repeatDataBodySettings, + repeatDataBodyInfoSettings, + repeatDataQuerySettings, + repeatDataSimplePathSettings, + repeatDataPathResourceSettings, + repeatDataPathTrailingResourceSettings); } private static Builder createDefault() { @@ -488,62 +279,34 @@ public class EchoStubSettings extends StubSettings { private static Builder initDefaults(Builder builder) { builder - .echoSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_1_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_1_params")); - - builder - .expandSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_1_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_1_params")); + .repeatDataBodySettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); builder - .pagedExpandSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_1_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_1_params")); + .repeatDataBodyInfoSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); builder - .simplePagedExpandSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params")); + .repeatDataQuerySettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); builder - .waitSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params")); + .repeatDataSimplePathSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); builder - .blockSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params")); + .repeatDataPathResourceSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); builder - .collideNameSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params")); - - builder - .waitOperationSettings() - .setInitialCallSettings( - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params")) - .build()) - .setResponseTransformer( - ProtoOperationTransformers.ResponseTransformer.create(WaitResponse.class)) - .setMetadataTransformer( - ProtoOperationTransformers.MetadataTransformer.create(WaitMetadata.class)) - .setPollingAlgorithm( - OperationTimedPollAlgorithm.create( - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(5000L)) - .setRetryDelayMultiplier(1.5) - .setMaxRetryDelay(Duration.ofMillis(45000L)) - .setInitialRpcTimeout(Duration.ZERO) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(Duration.ZERO) - .setTotalTimeout(Duration.ofMillis(300000L)) - .build())); + .repeatDataPathTrailingResourceSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); return builder; } @@ -563,71 +326,41 @@ public class EchoStubSettings extends StubSettings { return unaryMethodSettingsBuilders; } - /** Returns the builder for the settings used for calls to echo. */ - public UnaryCallSettings.Builder echoSettings() { - return echoSettings; - } - - /** Returns the builder for the settings used for calls to expand. */ - public ServerStreamingCallSettings.Builder expandSettings() { - return expandSettings; - } - - /** Returns the builder for the settings used for calls to collect. */ - public StreamingCallSettings.Builder collectSettings() { - return collectSettings; - } - - /** Returns the builder for the settings used for calls to chat. */ - public StreamingCallSettings.Builder chatSettings() { - return chatSettings; - } - - /** Returns the builder for the settings used for calls to chatAgain. */ - public StreamingCallSettings.Builder chatAgainSettings() { - return chatAgainSettings; - } - - /** Returns the builder for the settings used for calls to pagedExpand. */ - public PagedCallSettings.Builder< - PagedExpandRequest, PagedExpandResponse, PagedExpandPagedResponse> - pagedExpandSettings() { - return pagedExpandSettings; + /** Returns the builder for the settings used for calls to repeatDataBody. */ + public UnaryCallSettings.Builder repeatDataBodySettings() { + return repeatDataBodySettings; } - /** Returns the builder for the settings used for calls to simplePagedExpand. */ - public PagedCallSettings.Builder< - PagedExpandRequest, PagedExpandResponse, SimplePagedExpandPagedResponse> - simplePagedExpandSettings() { - return simplePagedExpandSettings; + /** Returns the builder for the settings used for calls to repeatDataBodyInfo. */ + public UnaryCallSettings.Builder repeatDataBodyInfoSettings() { + return repeatDataBodyInfoSettings; } - /** Returns the builder for the settings used for calls to wait. */ - public UnaryCallSettings.Builder waitSettings() { - return waitSettings; + /** Returns the builder for the settings used for calls to repeatDataQuery. */ + public UnaryCallSettings.Builder repeatDataQuerySettings() { + return repeatDataQuerySettings; } - /** Returns the builder for the settings used for calls to wait. */ - @BetaApi( - "The surface for use by generated code is not stable yet and may change in the future.") - public OperationCallSettings.Builder - waitOperationSettings() { - return waitOperationSettings; + /** Returns the builder for the settings used for calls to repeatDataSimplePath. */ + public UnaryCallSettings.Builder repeatDataSimplePathSettings() { + return repeatDataSimplePathSettings; } - /** Returns the builder for the settings used for calls to block. */ - public UnaryCallSettings.Builder blockSettings() { - return blockSettings; + /** Returns the builder for the settings used for calls to repeatDataPathResource. */ + public UnaryCallSettings.Builder + repeatDataPathResourceSettings() { + return repeatDataPathResourceSettings; } - /** Returns the builder for the settings used for calls to collideName. */ - public UnaryCallSettings.Builder collideNameSettings() { - return collideNameSettings; + /** Returns the builder for the settings used for calls to repeatDataPathTrailingResource. */ + public UnaryCallSettings.Builder + repeatDataPathTrailingResourceSettings() { + return repeatDataPathTrailingResourceSettings; } @Override - public EchoStubSettings build() throws IOException { - return new EchoStubSettings(this); + public ComplianceStubSettings build() throws IOException { + return new ComplianceStubSettings(this); } } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden index 8db61290e0..ab84437e6e 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden @@ -4,7 +4,6 @@ import com.google.api.core.BetaApi; import com.google.api.gax.core.BackgroundResource; import com.google.api.gax.httpjson.HttpJsonCallSettings; import com.google.api.gax.httpjson.HttpJsonCallableFactory; -import com.google.api.gax.httpjson.HttpJsonOperationSnapshotCallable; import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; import com.google.api.gax.rpc.BatchingCallSettings; import com.google.api.gax.rpc.ClientContext; @@ -13,7 +12,6 @@ import com.google.api.gax.rpc.OperationCallable; import com.google.api.gax.rpc.PagedCallSettings; import com.google.api.gax.rpc.UnaryCallSettings; import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.Operation; import javax.annotation.Generated; // AUTO-GENERATED DOCUMENTATION AND CLASS. @@ -25,7 +23,7 @@ import javax.annotation.Generated; @BetaApi @Generated("by gapic-generator-java") public class HttpJsonComplianceCallableFactory - implements HttpJsonStubCallableFactory { + implements HttpJsonStubCallableFactory { @Override public UnaryCallable createUnaryCallable( @@ -60,18 +58,10 @@ public class HttpJsonComplianceCallableFactory @Override public OperationCallable createOperationCallable( - HttpJsonCallSettings httpJsonCallSettings, + HttpJsonCallSettings httpJsonCallSettings, OperationCallSettings callSettings, ClientContext clientContext, BackgroundResource operationsStub) { - UnaryCallable innerCallable = - HttpJsonCallableFactory.createBaseUnaryCallable( - httpJsonCallSettings, callSettings.getInitialCallSettings(), clientContext); - HttpJsonOperationSnapshotCallable initialCallable = - new HttpJsonOperationSnapshotCallable( - innerCallable, - httpJsonCallSettings.getMethodDescriptor().getOperationSnapshotFactory()); - return HttpJsonCallableFactory.createOperationCallable( - callSettings, clientContext, operationsStub.longRunningClient(), initialCallable); + return null; } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceStub.golden b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceStub.golden index 5324f21655..331e5bf961 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceStub.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceStub.golden @@ -57,8 +57,7 @@ public class HttpJsonComplianceStub extends ComplianceStub { }) .setRequestBodyExtractor( request -> - ProtoRestSerializer.create() - .toBody("serverVerify", request.getServerVerify())) + ProtoRestSerializer.create().toBody("*", request.toBuilder().build())) .build()) .setResponseParser( ProtoMessageResponseParser.newBuilder() diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClient.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClient.java index 7173f3bce5..f9039b41df 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClient.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClient.java @@ -329,6 +329,8 @@ public final OperationFuture deleteAsync( * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.rpc.ApiException if the remote call fails */ + @BetaApi( + "The surface for long-running operations is not stable yet and may change in the future.") public final OperationFuture deleteAsync(DeleteAddressRequest request) { return deleteOperationCallable().futureCall(request); } @@ -438,6 +440,8 @@ public final OperationFuture insertAsync( * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.rpc.ApiException if the remote call fails */ + @BetaApi( + "The surface for long-running operations is not stable yet and may change in the future.") public final OperationFuture insertAsync(InsertAddressRequest request) { return insertOperationCallable().futureCall(request); } diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClient.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClient.java index fb6a5e296d..09fb0b090a 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClient.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClient.java @@ -222,6 +222,112 @@ public final UnaryCallable getCallable() { return stub.getCallable(); } + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Waits for the specified Operation resource to return as `DONE` or for the request to approach + * the 2 minute deadline, and retrieves the specified Operation resource. This method differs from + * the `GET` method in that it waits for no more than the default deadline (2 minutes) and then + * returns the current state of the operation, which might be `DONE` or still in progress. + * + *

This method is called on a best-effort basis. Specifically: - In uncommon cases, when the + * server is overloaded, the request might return before the default deadline is reached, or might + * return after zero seconds. - If the default deadline is reached, there is no guarantee that the + * operation is actually done when the method returns. Be prepared to retry if the operation is + * not `DONE`. + * + *

Sample code: + * + *

{@code
+   * try (RegionOperationsClient regionOperationsClient = RegionOperationsClient.create()) {
+   *   String project = "project-309310695";
+   *   String region = "region-934795532";
+   *   String operation = "operation1662702951";
+   *   Operation response = regionOperationsClient.wait(project, region, operation);
+   * }
+   * }
+ * + * @param project Project ID for this request. + * @param region Name of the region for this request. + * @param operation Name of the Operations resource to return. + * @throws com.google.api.gax.rpc.ApiException if the remote call fails + */ + public final Operation wait(String project, String region, String operation) { + WaitRegionOperationRequest request = + WaitRegionOperationRequest.newBuilder() + .setProject(project) + .setRegion(region) + .setOperation(operation) + .build(); + return wait(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Waits for the specified Operation resource to return as `DONE` or for the request to approach + * the 2 minute deadline, and retrieves the specified Operation resource. This method differs from + * the `GET` method in that it waits for no more than the default deadline (2 minutes) and then + * returns the current state of the operation, which might be `DONE` or still in progress. + * + *

This method is called on a best-effort basis. Specifically: - In uncommon cases, when the + * server is overloaded, the request might return before the default deadline is reached, or might + * return after zero seconds. - If the default deadline is reached, there is no guarantee that the + * operation is actually done when the method returns. Be prepared to retry if the operation is + * not `DONE`. + * + *

Sample code: + * + *

{@code
+   * try (RegionOperationsClient regionOperationsClient = RegionOperationsClient.create()) {
+   *   WaitRegionOperationRequest request =
+   *       WaitRegionOperationRequest.newBuilder()
+   *           .setOperation("operation1662702951")
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .build();
+   *   Operation response = regionOperationsClient.wait(request);
+   * }
+   * }
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.rpc.ApiException if the remote call fails + */ + public final Operation wait(WaitRegionOperationRequest request) { + return waitCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Waits for the specified Operation resource to return as `DONE` or for the request to approach + * the 2 minute deadline, and retrieves the specified Operation resource. This method differs from + * the `GET` method in that it waits for no more than the default deadline (2 minutes) and then + * returns the current state of the operation, which might be `DONE` or still in progress. + * + *

This method is called on a best-effort basis. Specifically: - In uncommon cases, when the + * server is overloaded, the request might return before the default deadline is reached, or might + * return after zero seconds. - If the default deadline is reached, there is no guarantee that the + * operation is actually done when the method returns. Be prepared to retry if the operation is + * not `DONE`. + * + *

Sample code: + * + *

{@code
+   * try (RegionOperationsClient regionOperationsClient = RegionOperationsClient.create()) {
+   *   WaitRegionOperationRequest request =
+   *       WaitRegionOperationRequest.newBuilder()
+   *           .setOperation("operation1662702951")
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .build();
+   *   ApiFuture future = regionOperationsClient.waitCallable().futureCall(request);
+   *   // Do something.
+   *   Operation response = future.get();
+   * }
+   * }
+ */ + public final UnaryCallable waitCallable() { + return stub.waitCallable(); + } + @Override public final void close() { stub.close(); diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClientTest.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClientTest.java index d41b1f5191..684c1312ab 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClientTest.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClientTest.java @@ -140,4 +140,73 @@ public void getExceptionTest() throws Exception { // Expected exception. } } + + @Test + public void waitTest() throws Exception { + Operation expectedResponse = + Operation.newBuilder() + .setClientOperationId("clientOperationId-1230366697") + .setCreationTimestamp("creationTimestamp-370203401") + .setDescription("description-1724546052") + .setEndTime("endTime-1607243192") + .setError(Error.newBuilder().build()) + .setHttpErrorMessage("httpErrorMessage1577303431") + .setHttpErrorStatusCode(1386087020) + .setId(3355) + .setInsertTime("insertTime966165798") + .setKind("kind3292052") + .setName("name3373707") + .setOperationType("operationType91999553") + .setProgress(-1001078227) + .setRegion("region-934795532") + .setSelfLink("selfLink1191800166") + .setStartTime("startTime-2129294769") + .setStatusMessage("statusMessage-958704715") + .setTargetId(-815576439) + .setTargetLink("targetLink486368555") + .setUser("user3599307") + .addAllWarnings(new ArrayList()) + .setZone("zone3744684") + .build(); + mockService.addResponse(expectedResponse); + + String project = "project-309310695"; + String region = "region-934795532"; + String operation = "operation1662702951"; + + Operation actualResponse = client.wait(project, region, operation); + Assert.assertEquals(expectedResponse, actualResponse); + + List actualRequests = mockService.getRequestPaths(); + Assert.assertEquals(1, actualRequests.size()); + + String apiClientHeaderKey = + mockService + .getRequestHeaders() + .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) + .iterator() + .next(); + Assert.assertTrue( + GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() + .matcher(apiClientHeaderKey) + .matches()); + } + + @Test + public void waitExceptionTest() throws Exception { + ApiException exception = + ApiExceptionFactory.createException( + new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); + mockService.addException(exception); + + try { + String project = "project-309310695"; + String region = "region-934795532"; + String operation = "operation1662702951"; + client.wait(project, region, operation); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } } diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsSettings.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsSettings.java index 4e0ffca9d4..91cabed69d 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsSettings.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsSettings.java @@ -72,6 +72,11 @@ public UnaryCallSettings getSettings() { return ((RegionOperationsStubSettings) getStubSettings()).getSettings(); } + /** Returns the object with the settings used for calls to wait. */ + public UnaryCallSettings waitSettings() { + return ((RegionOperationsStubSettings) getStubSettings()).waitSettings(); + } + public static final RegionOperationsSettings create(RegionOperationsStubSettings stub) throws IOException { return new RegionOperationsSettings.Builder(stub.toBuilder()).build(); @@ -175,6 +180,11 @@ public UnaryCallSettings.Builder getSettin return getStubSettingsBuilder().getSettings(); } + /** Returns the builder for the settings used for calls to wait. */ + public UnaryCallSettings.Builder waitSettings() { + return getStubSettingsBuilder().waitSettings(); + } + @Override public RegionOperationsSettings build() throws IOException { return new RegionOperationsSettings(this); diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/gapic_metadata.json b/test/integration/goldens/compute/com/google/cloud/compute/v1/gapic_metadata.json index d2f2df6b3d..a56d0a2382 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/gapic_metadata.json +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/gapic_metadata.json @@ -33,6 +33,9 @@ "rpcs": { "Get": { "methods": ["get", "get", "getCallable"] + }, + "Wait": { + "methods": ["wait", "wait", "waitCallable"] } } } diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStub.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStub.java index 551b0ec0eb..9ae394b7ca 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStub.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStub.java @@ -40,10 +40,6 @@ @Generated("by gapic-generator-java") public abstract class AddressesStub implements BackgroundResource { - public RegionOperationsStub getOperationsStub() { - throw new UnsupportedOperationException("Not implemented: getOperationsStub()"); - } - public UnaryCallable aggregatedListPagedCallable() { throw new UnsupportedOperationException("Not implemented: aggregatedListPagedCallable()"); diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStubSettings.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStubSettings.java index 55866e3401..517743de7d 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStubSettings.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStubSettings.java @@ -25,10 +25,10 @@ import com.google.api.gax.core.GaxProperties; import com.google.api.gax.core.GoogleCredentialsProvider; import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.grpc.ProtoOperationTransformers; 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.httpjson.ProtoOperationTransformers; import com.google.api.gax.longrunning.OperationSnapshot; import com.google.api.gax.longrunning.OperationTimedPollAlgorithm; import com.google.api.gax.retrying.RetrySettings; diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java index 943580e59b..9e5e90fbe1 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java @@ -261,7 +261,7 @@ public class HttpJsonAddressesStub extends AddressesStub { private final UnaryCallable listPagedCallable; private final BackgroundResource backgroundResources; - private final HttpJsonRegionOperationsStub operationsStub; + private final HttpJsonRegionOperationsStub httpJsonOperationsStub; private final HttpJsonStubCallableFactory callableFactory; public static final HttpJsonAddressesStub create(AddressesStubSettings settings) @@ -300,7 +300,8 @@ protected HttpJsonAddressesStub( HttpJsonStubCallableFactory callableFactory) throws IOException { this.callableFactory = callableFactory; - this.operationsStub = HttpJsonRegionOperationsStub.create(clientContext, callableFactory); + this.httpJsonOperationsStub = + HttpJsonRegionOperationsStub.create(clientContext, callableFactory); HttpJsonCallSettings aggregatedListTransportSettings = @@ -334,7 +335,7 @@ protected HttpJsonAddressesStub( deleteTransportSettings, settings.deleteOperationSettings(), clientContext, - operationsStub); + httpJsonOperationsStub); this.insertCallable = callableFactory.createUnaryCallable( insertTransportSettings, settings.insertSettings(), clientContext); @@ -343,7 +344,7 @@ protected HttpJsonAddressesStub( insertTransportSettings, settings.insertOperationSettings(), clientContext, - operationsStub); + httpJsonOperationsStub); this.listCallable = callableFactory.createUnaryCallable( listTransportSettings, settings.listSettings(), clientContext); diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java index b775dbba59..24e9ad539a 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java @@ -20,7 +20,6 @@ import com.google.api.gax.core.BackgroundResource; import com.google.api.gax.httpjson.HttpJsonCallSettings; import com.google.api.gax.httpjson.HttpJsonCallableFactory; -import com.google.api.gax.httpjson.HttpJsonOperationSnapshotCallable; import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; import com.google.api.gax.rpc.BatchingCallSettings; import com.google.api.gax.rpc.ClientContext; @@ -29,7 +28,6 @@ import com.google.api.gax.rpc.PagedCallSettings; import com.google.api.gax.rpc.UnaryCallSettings; import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.Operation; import javax.annotation.Generated; // AUTO-GENERATED DOCUMENTATION AND CLASS. @@ -41,7 +39,7 @@ @Generated("by gapic-generator-java") @BetaApi public class HttpJsonRegionOperationsCallableFactory - implements HttpJsonStubCallableFactory { + implements HttpJsonStubCallableFactory { @Override public UnaryCallable createUnaryCallable( @@ -76,18 +74,10 @@ public UnaryCallable createBatchingCa @Override public OperationCallable createOperationCallable( - HttpJsonCallSettings httpJsonCallSettings, + HttpJsonCallSettings httpJsonCallSettings, OperationCallSettings callSettings, ClientContext clientContext, BackgroundResource operationsStub) { - UnaryCallable innerCallable = - HttpJsonCallableFactory.createBaseUnaryCallable( - httpJsonCallSettings, callSettings.getInitialCallSettings(), clientContext); - HttpJsonOperationSnapshotCallable initialCallable = - new HttpJsonOperationSnapshotCallable( - innerCallable, - httpJsonCallSettings.getMethodDescriptor().getOperationSnapshotFactory()); - return HttpJsonCallableFactory.createOperationCallable( - callSettings, clientContext, operationsStub.longRunningClient(), initialCallable); + return null; } } diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java index 1949dd2c60..c167489173 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java @@ -36,6 +36,7 @@ import com.google.cloud.compute.v1.GetRegionOperationRequest; import com.google.cloud.compute.v1.Operation; import com.google.cloud.compute.v1.Operation.Status; +import com.google.cloud.compute.v1.WaitRegionOperationRequest; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -107,7 +108,41 @@ public class HttpJsonRegionOperationsStub extends RegionOperationsStub { }) .build(); + private static final ApiMethodDescriptor + waitMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.cloud.compute.v1.RegionOperations/Wait") + .setHttpMethod(HttpMethods.POST) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/compute/v1/projects/projects/{project}/regions/{region}/operations/{operation}/wait", + request -> { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam(fields, "operation", request.getOperation()); + serializer.putPathParam(fields, "project", request.getProject()); + serializer.putPathParam(fields, "region", request.getRegion()); + return fields; + }) + .setQueryParamsExtractor( + request -> { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + }) + .setRequestBodyExtractor(request -> null) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(Operation.getDefaultInstance()) + .build()) + .build(); + private final UnaryCallable getCallable; + private final UnaryCallable waitCallable; private final BackgroundResource backgroundResources; private final LongRunningClient longRunningClient; @@ -156,10 +191,17 @@ protected HttpJsonRegionOperationsStub( HttpJsonCallSettings.newBuilder() .setMethodDescriptor(getMethodDescriptor) .build(); + HttpJsonCallSettings waitTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(waitMethodDescriptor) + .build(); this.getCallable = callableFactory.createUnaryCallable( getTransportSettings, settings.getSettings(), clientContext); + this.waitCallable = + callableFactory.createUnaryCallable( + waitTransportSettings, settings.waitSettings(), clientContext); this.longRunningClient = new HttpJsonLongRunningClient( @@ -174,6 +216,7 @@ protected HttpJsonRegionOperationsStub( public static List getMethodDescriptors() { List methodDescriptors = new ArrayList<>(); methodDescriptors.add(getMethodDescriptor); + methodDescriptors.add(waitMethodDescriptor); return methodDescriptors; } @@ -182,6 +225,11 @@ public UnaryCallable getCallable() { return getCallable; } + @Override + public UnaryCallable waitCallable() { + return waitCallable; + } + @Override public LongRunningClient longRunningClient() { return longRunningClient; diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStub.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStub.java index c3019038cb..2d40fa610a 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStub.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStub.java @@ -16,10 +16,13 @@ package com.google.cloud.compute.v1.stub; +import com.google.api.core.BetaApi; import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.rpc.LongRunningClient; import com.google.api.gax.rpc.UnaryCallable; import com.google.cloud.compute.v1.GetRegionOperationRequest; import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.WaitRegionOperationRequest; import javax.annotation.Generated; // AUTO-GENERATED DOCUMENTATION AND CLASS. @@ -31,10 +34,19 @@ @Generated("by gapic-generator-java") public abstract class RegionOperationsStub implements BackgroundResource { + @BetaApi + public LongRunningClient longRunningClient() { + throw new UnsupportedOperationException("Not implemented: longRunningClient()"); + } + public UnaryCallable getCallable() { throw new UnsupportedOperationException("Not implemented: getCallable()"); } + public UnaryCallable waitCallable() { + throw new UnsupportedOperationException("Not implemented: waitCallable()"); + } + @Override public abstract void close(); } diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStubSettings.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStubSettings.java index ebcf98e4f7..3c57601386 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStubSettings.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStubSettings.java @@ -33,6 +33,7 @@ import com.google.api.gax.rpc.UnaryCallSettings; import com.google.cloud.compute.v1.GetRegionOperationRequest; import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.WaitRegionOperationRequest; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -85,12 +86,18 @@ public class RegionOperationsStubSettings extends StubSettings getSettings; + private final UnaryCallSettings waitSettings; /** Returns the object with the settings used for calls to get. */ public UnaryCallSettings getSettings() { return getSettings; } + /** Returns the object with the settings used for calls to wait. */ + public UnaryCallSettings waitSettings() { + return waitSettings; + } + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") public RegionOperationsStub createStub() throws IOException { if (getTransportChannelProvider() @@ -167,12 +174,14 @@ protected RegionOperationsStubSettings(Builder settingsBuilder) throws IOExcepti super(settingsBuilder); getSettings = settingsBuilder.getSettings().build(); + waitSettings = settingsBuilder.waitSettings().build(); } /** Builder for RegionOperationsStubSettings. */ public static class Builder extends StubSettings.Builder { private final ImmutableList> unaryMethodSettingsBuilders; private final UnaryCallSettings.Builder getSettings; + private final UnaryCallSettings.Builder waitSettings; private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; @@ -184,6 +193,7 @@ public static class Builder extends StubSettings.BuildernewArrayList( StatusCode.Code.DEADLINE_EXCEEDED, StatusCode.Code.UNAVAILABLE))); + definitions.put("no_retry_codes", ImmutableSet.copyOf(Lists.newArrayList())); RETRYABLE_CODE_DEFINITIONS = definitions.build(); } @@ -203,6 +213,8 @@ public static class Builder extends StubSettings.Builder>of(getSettings); + unaryMethodSettingsBuilders = + ImmutableList.>of(getSettings, waitSettings); initDefaults(this); } @@ -223,8 +237,10 @@ protected Builder(RegionOperationsStubSettings settings) { super(settings); getSettings = settings.getSettings.toBuilder(); + waitSettings = settings.waitSettings.toBuilder(); - unaryMethodSettingsBuilders = ImmutableList.>of(getSettings); + unaryMethodSettingsBuilders = + ImmutableList.>of(getSettings, waitSettings); } private static Builder createDefault() { @@ -246,6 +262,11 @@ private static Builder initDefaults(Builder builder) { .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_0_codes")) .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_0_params")); + builder + .waitSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); + return builder; } @@ -269,6 +290,11 @@ public UnaryCallSettings.Builder getSettin return getSettings; } + /** Returns the builder for the settings used for calls to wait. */ + public UnaryCallSettings.Builder waitSettings() { + return waitSettings; + } + @Override public RegionOperationsStubSettings build() throws IOException { return new RegionOperationsStubSettings(this);