From 8983e23736a443057ee98446f5bac13e2d04fa48 Mon Sep 17 00:00:00 2001 From: vam-google Date: Tue, 1 Jun 2021 23:16:40 -0700 Subject: [PATCH 1/4] feat: implement DIREGAPIC --- BUILD.bazel | 26 + WORKSPACE | 56 +- dependencies.properties | 5 +- repositories.bzl | 10 +- rules_java_gapic/java_gapic.bzl | 47 +- rules_java_gapic/java_gapic_pkg.bzl | 8 +- ...nt.gradle.tmpl => client_grpc.gradle.tmpl} | 0 .../resources/gradle/client_rest.gradle.tmpl | 60 ++ .../com/google/api/generator/MainDumper.java | 50 ++ .../google/api/generator/MainFromFile.java | 60 ++ .../api/generator/gapic/composer/BUILD.bazel | 1 + .../generator/gapic/composer/Composer.java | 48 +- ...bstractServiceClientTestClassComposer.java | 8 +- .../grpc/GrpcServiceStubClassComposer.java | 2 +- .../generator/gapic/composer/rest/BUILD.bazel | 52 ++ ...onServiceCallableFactoryClassComposer.java | 81 +++ .../HttpJsonServiceStubClassComposer.java | 507 +++++++++++++++ .../gapic/composer/rest/RestContext.java | 55 ++ .../rest/ServiceClientTestClassComposer.java | 535 ++++++++++++++++ .../rest/ServiceSettingsClassComposer.java | 30 + .../ServiceStubSettingsClassComposer.java | 172 +++++ .../gapic/composer/store/TypeStore.java | 8 + .../gapic/model/HttpRuleBindings.java | 74 +++ .../api/generator/gapic/model/Method.java | 7 +- .../gapic/protoparser/HttpRuleParser.java | 93 ++- .../generator/gapic/protoparser/Parser.java | 25 +- .../protoparser/PluginArgumentParser.java | 33 +- .../composer/common/TestProtoLoader.java | 4 + .../generator/gapic/composer/grpc/BUILD.bazel | 2 - .../generator/gapic/composer/rest/BUILD.bazel | 99 +++ ...rviceCallableFactoryClassComposerTest.java | 43 ++ .../HttpJsonServiceStubClassComposerTest.java | 42 ++ .../composer/rest/RestTestProtoLoader.java | 78 +++ .../ServiceClientTestClassComposerTest.java | 42 ++ .../ServiceSettingsClassComposerTest.java | 41 ++ .../ServiceStubSettingsClassComposerTest.java | 42 ++ .../gapic/composer/rest/goldens/BUILD.bazel | 6 + .../rest/goldens/ComplianceClientTest.golden | 368 +++++++++++ .../rest/goldens/ComplianceSettings.golden | 219 +++++++ .../goldens/ComplianceStubSettings.golden | 604 ++++++++++++++++++ .../HttpJsonComplianceCallableFactory.golden | 66 ++ .../goldens/HttpJsonComplianceStub.golden | 510 +++++++++++++++ .../gapic/protoparser/HttpRuleParserTest.java | 23 +- .../api/generator/gapic/testdata/BUILD.bazel | 1 + .../generator/gapic/testdata/compliance.proto | 193 ++++++ test/integration/BUILD.bazel | 2 + test/integration/goldens/compute/BUILD.bazel | 9 + .../cloud/compute/v1/AddressesClient.java | 502 +++++++++++++++ .../cloud/compute/v1/AddressesClientTest.java | 314 +++++++++ .../cloud/compute/v1/AddressesSettings.java | 214 +++++++ .../compute/v1/RegionOperationsClient.java | 254 ++++++++ .../v1/RegionOperationsClientTest.java | 143 +++++ .../compute/v1/RegionOperationsSettings.java | 184 ++++++ .../cloud/compute/v1/gapic_metadata.json | 42 ++ .../google/cloud/compute/v1/package-info.java | 53 ++ .../cloud/compute/v1/stub/AddressesStub.java | 58 ++ .../v1/stub/AddressesStubSettings.java | 327 ++++++++++ .../HttpJsonAddressesCallableFactory.java | 80 +++ .../v1/stub/HttpJsonAddressesStub.java | 389 +++++++++++ ...tpJsonRegionOperationsCallableFactory.java | 80 +++ .../v1/stub/HttpJsonRegionOperationsStub.java | 197 ++++++ .../compute/v1/stub/RegionOperationsStub.java | 40 ++ .../v1/stub/RegionOperationsStubSettings.java | 257 ++++++++ 63 files changed, 7458 insertions(+), 123 deletions(-) rename rules_java_gapic/resources/gradle/{client.gradle.tmpl => client_grpc.gradle.tmpl} (100%) create mode 100644 rules_java_gapic/resources/gradle/client_rest.gradle.tmpl create mode 100644 src/main/java/com/google/api/generator/MainDumper.java create mode 100644 src/main/java/com/google/api/generator/MainFromFile.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/BUILD.bazel create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/ServiceSettingsClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/model/HttpRuleBindings.java create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/BUILD.bazel create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposerTest.java create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposerTest.java create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/RestTestProtoLoader.java create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposerTest.java create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/ServiceSettingsClassComposerTest.java create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/goldens/BUILD.bazel create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceClientTest.golden create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceSettings.golden create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden create mode 100644 src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceStub.golden create mode 100644 src/test/java/com/google/api/generator/gapic/testdata/compliance.proto create mode 100644 test/integration/goldens/compute/BUILD.bazel create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClient.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClientTest.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesSettings.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClient.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClientTest.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsSettings.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/gapic_metadata.json create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/package-info.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStub.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStubSettings.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesCallableFactory.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStub.java create mode 100644 test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStubSettings.java diff --git a/BUILD.bazel b/BUILD.bazel index 8823250fca..fa2b80f062 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -45,6 +45,32 @@ java_binary( ], ) +java_binary( + name = "protoc-gen-java_dumper", + main_class = "com.google.api.generator.MainDumper", + runtime_deps = [ + "//src/main/java/com/google/api/generator", + "//src/main/java/com/google/api/generator/gapic", + "@com_google_googleapis//google/api:api_java_proto", + "@com_google_googleapis//google/longrunning:longrunning_java_proto", + "@com_google_guava_guava", + "@com_google_protobuf//:protobuf_java", + ], +) + +java_binary( + name = "protoc-gen-java_gapicfromfile", + main_class = "com.google.api.generator.MainFromFile", + runtime_deps = [ + "//src/main/java/com/google/api/generator", + "//src/main/java/com/google/api/generator/gapic", + "@com_google_googleapis//google/api:api_java_proto", + "@com_google_googleapis//google/longrunning:longrunning_java_proto", + "@com_google_guava_guava", + "@com_google_protobuf//:protobuf_java", + ], +) + # google-java-format java_binary( name = "google_java_format_binary", diff --git a/WORKSPACE b/WORKSPACE index 66982c622d..173a832f34 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,6 +1,7 @@ workspace(name = "gapic_generator_java") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("@bazel_tools//tools/build_defs/repo:jvm.bzl", "jvm_maven_import_external") # DO NOT REMOVE. # This is needed to clobber any transitively-pulled in versions of bazel_skylib so that packages @@ -14,6 +15,32 @@ http_archive( ], ) +jvm_maven_import_external( + name = "google_java_format_all_deps", + artifact = "com.google.googlejavaformat:google-java-format:jar:all-deps:1.7", + server_urls = ["https://repo.maven.apache.org/maven2/", "http://repo1.maven.org/maven2/"], + licenses = ["notice", "reciprocal"] +) + +_gax_java_version = "1.64.0" + +http_archive( + name = "com_google_api_gax_java", + strip_prefix = "gax-java-%s" % _gax_java_version, + urls = ["https://github.com/googleapis/gax-java/archive/v%s.zip" % _gax_java_version], +) + +load("@com_google_api_gax_java//:repository_rules.bzl", "com_google_api_gax_java_properties") + +com_google_api_gax_java_properties( + name = "com_google_api_gax_java_properties", + file = "@com_google_api_gax_java//:dependencies.properties", +) + +load("@com_google_api_gax_java//:repositories.bzl", "com_google_api_gax_java_repositories") + +com_google_api_gax_java_repositories() + load("//:repository_rules.bzl", "gapic_generator_java_properties") gapic_generator_java_properties( @@ -35,8 +62,8 @@ protobuf_deps() # Import the monolith so we can transitively use its gapic rules for googleapis. http_archive( name = "com_google_api_codegen", - strip_prefix = "gapic-generator-2.4.6", - urls = ["https://github.com/googleapis/gapic-generator/archive/v2.4.6.zip"], + strip_prefix = "gapic-generator-2.11.1", + urls = ["https://github.com/googleapis/gapic-generator/archive/v2.11.1.zip"], ) load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language") @@ -48,25 +75,12 @@ switched_rules_by_language( java = True, ) -_gax_java_version = PROPERTIES["version.com_google_gax_java"] - -http_archive( - name = "com_google_api_gax_java", - strip_prefix = "gax-java-%s" % _gax_java_version, - urls = ["https://github.com/googleapis/gax-java/archive/v%s.zip" % _gax_java_version], -) - -load("@com_google_api_gax_java//:repository_rules.bzl", "com_google_api_gax_java_properties") - -com_google_api_gax_java_properties( - name = "com_google_api_gax_java_properties", - file = "@com_google_api_gax_java//:dependencies.properties", -) - -load("@com_google_api_gax_java//:repositories.bzl", "com_google_api_gax_java_repositories") - -com_google_api_gax_java_repositories() - load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories") grpc_java_repositories() + +http_archive( + name = "com_google_disco_to_proto3_converter", + strip_prefix = "disco-to-proto3-converter-1839f6aca5e968e59b7acc03e7018b0fda8c480b", + urls = ["https://github.com/googleapis/disco-to-proto3-converter/archive/1839f6aca5e968e59b7acc03e7018b0fda8c480b.zip"], +) diff --git a/dependencies.properties b/dependencies.properties index 841111924b..fbdc353a59 100644 --- a/dependencies.properties +++ b/dependencies.properties @@ -7,11 +7,10 @@ # Target workspace name: com_google_api_codegen # Versions only, for dependencies which actual artifacts differ between Bazel and Gradle -version.com_google_protobuf=3.13.0 +version.com_google_protobuf=3.15.2 # Version of google-java-format is downgraded from 1.8 to 1.7, because 1.8 supports java 11 minimum, while our JRE is java 8. version.google_java_format=1.7 version.com_google_api_common_java=1.9.3 -version.com_google_gax_java=1.62.0 version.io_grpc_java=1.30.2 # Common deps. @@ -20,7 +19,7 @@ maven.com_google_code_findbugs_jsr305=com.google.code.findbugs:jsr305:3.0.0 maven.com_google_auto_value_auto_value=com.google.auto.value:auto-value:1.7.2 maven.com_google_auto_value_auto_value_annotations=com.google.auto.value:auto-value-annotations:1.7.2 maven.com_google_code_gson=com.google.code.gson:gson:2.8.6 -maven.com_google_protobuf_protobuf_java=com.google.protobuf:protobuf-java:3.12.2 +maven.com_google_protobuf_protobuf_java=com.google.protobuf:protobuf-java:3.15.8 maven.io_github_java_diff_utils=io.github.java-diff-utils:java-diff-utils:4.0 maven.javax_annotation_javax_annotation_api=javax.annotation:javax.annotation-api:1.3.2 maven.javax_validation_javax_validation_api=javax.validation:validation-api:2.0.1.Final diff --git a/repositories.bzl b/repositories.bzl index e246cef5cc..0b2b5d4372 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -59,12 +59,18 @@ def gapic_generator_java_repositories(): _maybe( http_archive, name = "com_google_googleapis", - strip_prefix = "googleapis-2bea43cdc7a4443876380732980d83cd8d560582", + strip_prefix = "googleapis-0b26f05c9f469dc710e13a94f10d46dae4fa0b3c", urls = [ - "https://github.com/googleapis/googleapis/archive/2bea43cdc7a4443876380732980d83cd8d560582.zip", + "https://github.com/googleapis/googleapis/archive/0b26f05c9f469dc710e13a94f10d46dae4fa0b3c.zip", ], ) + _maybe( + native.local_repository, + name = "com_google_googleapis_discovery", + path = "/usr/local/google/home/vam/_/projects/_/googleapis-discovery" + ) + _maybe( native.bind, name = "guava", diff --git a/rules_java_gapic/java_gapic.bzl b/rules_java_gapic/java_gapic.bzl index 9c2436174c..f74d85cacd 100644 --- a/rules_java_gapic/java_gapic.bzl +++ b/rules_java_gapic/java_gapic.bzl @@ -127,12 +127,14 @@ def java_gapic_library( service_yaml = None, deps = [], test_deps = [], + transport = None, + java_generator_name = "java_gapic", **kwargs): file_args_dict = {} if grpc_service_config: file_args_dict[grpc_service_config] = "grpc-service-config" - else: + elif transport != "rest": for keyword in NO_GRPC_CONFIG_ALLOWLIST: if keyword not in name: fail("Missing a gRPC service config file") @@ -157,21 +159,25 @@ def java_gapic_library( srcjar_name = name + "_srcjar" raw_srcjar_name = srcjar_name + "_raw" output_suffix = ".srcjar" + opt_args = [] + + if transport: + opt_args.append("transport=%s" % transport) # Produces the GAPIC metadata file if this flag is set. to any value. # Protoc invocation: --java_gapic_opt=metadata plugin_args = ["metadata"] - _java_generator_name = "java_gapic" proto_custom_library( name = raw_srcjar_name, deps = srcs, - plugin = Label("@gapic_generator_java//:protoc-gen-%s" % _java_generator_name), + plugin = Label("@gapic_generator_java//:protoc-gen-%s" % java_generator_name), plugin_args = plugin_args, plugin_file_args = {}, opt_file_args = file_args_dict, - output_type = _java_generator_name, + output_type = java_generator_name, output_suffix = output_suffix, + opt_args = opt_args, **kwargs ) @@ -201,10 +207,7 @@ def java_gapic_library( "@com_google_protobuf//:protobuf_java", "@com_google_api_api_common//jar", "@com_google_api_gax_java//gax:gax", - "@com_google_api_gax_java//gax-grpc:gax_grpc", "@com_google_guava_guava//jar", - "@io_grpc_grpc_java//core:core", - "@io_grpc_grpc_java//protobuf:protobuf", "@com_google_code_findbugs_jsr305//jar", "@org_threeten_threetenbp//jar", "@io_opencensus_opencensus_api//jar", @@ -214,6 +217,17 @@ def java_gapic_library( "@javax_annotation_javax_annotation_api//jar", ] + if transport == "rest": + actual_deps += [ + "@com_google_api_gax_java//gax-httpjson:gax_httpjson", + ] + else: + actual_deps += [ + "@com_google_api_gax_java//gax-grpc:gax_grpc", + "@io_grpc_grpc_java//core:core", + "@io_grpc_grpc_java//protobuf:protobuf", + ] + native.java_library( name = name, srcs = ["%s.srcjar" % srcjar_name], @@ -224,15 +238,24 @@ def java_gapic_library( # Test deps. actual_test_deps = [ "@com_google_googleapis//google/type:type_java_proto", # Commonly used. - "@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", "@com_google_api_gax_java//gax:gax_testlib", "@com_google_code_gson_gson//jar", - "@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", "@junit_junit//jar", ] + + if transport == "rest": + actual_test_deps += [ + "@com_google_api_gax_java//gax-httpjson:gax_httpjson_testlib", + ] + else: + 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", + ] + _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 f06c515f72..a6bca826d2 100644 --- a/rules_java_gapic/java_gapic_pkg.bzl +++ b/rules_java_gapic/java_gapic_pkg.bzl @@ -301,6 +301,7 @@ def java_gapic_assembly_gradle_pkg( name, deps, assembly_name = None, + transport = None, **kwargs): package_dir = name if assembly_name: @@ -350,9 +351,14 @@ 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: + template_label = Label("//rules_java_gapic:resources/gradle/client_grpc.gradle.tmpl") + _java_gapic_gradle_pkg( name = client_target, - template_label = Label("//rules_java_gapic:resources/gradle/client.gradle.tmpl"), + template_label = template_label, deps = proto_target_dep + client_deps, test_deps = grpc_target_dep + client_test_deps, **kwargs diff --git a/rules_java_gapic/resources/gradle/client.gradle.tmpl b/rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl similarity index 100% rename from rules_java_gapic/resources/gradle/client.gradle.tmpl rename to rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl diff --git a/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl b/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl new file mode 100644 index 0000000000..ef16323736 --- /dev/null +++ b/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl @@ -0,0 +1,60 @@ +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.7 +targetCompatibility = 1.7 + +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-httpjson:{{version.gax_httpjson}}' + testCompile 'com.google.api:gax-httpjson:{{version.gax_httpjson}}:testlib' + testCompile '{{maven.junit_junit}}' + {{extra_deps}} +} + +task smokeTest(type: Test) { + filter { + includeTestsMatching "*SmokeTest" + setFailOnNoMatchingTests false + } +} + +test { + exclude "**/*SmokeTest*" +} + +sourceSets { + main { + java { + srcDir 'src/main/java' + } + } +} + +clean { + delete 'all-jars' +} + +task allJars(type: Copy) { + dependsOn test, jar + into 'all-jars' + // Replace with `from configurations.testRuntime, jar` to include test dependencies + from configurations.runtime, jar +} diff --git a/src/main/java/com/google/api/generator/MainDumper.java b/src/main/java/com/google/api/generator/MainDumper.java new file mode 100644 index 0000000000..018106b883 --- /dev/null +++ b/src/main/java/com/google/api/generator/MainDumper.java @@ -0,0 +1,50 @@ +// 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; + +import com.google.api.AnnotationsProto; +import com.google.api.ClientProto; +import com.google.api.FieldBehaviorProto; +import com.google.api.ResourceProto; +import com.google.longrunning.OperationsProto; +import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest; +import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse; +import java.io.IOException; + +public class MainDumper { + public static void main(String[] args) throws IOException { + ExtensionRegistry registry = ExtensionRegistry.newInstance(); + registerAllExtensions(registry); + CodeGeneratorRequest request = CodeGeneratorRequest.parseFrom(System.in, registry); + + CodeGeneratorResponse.Builder response = CodeGeneratorResponse.newBuilder(); + response + .setSupportedFeatures(CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL_VALUE) + .addFileBuilder() + .setName("desc-dump.bin") + .setContentBytes(request.toByteString()); + response.build().writeTo(System.out); + } + + /** Register all extensions needed to process API protofiles. */ + private static void registerAllExtensions(ExtensionRegistry extensionRegistry) { + OperationsProto.registerAllExtensions(extensionRegistry); + AnnotationsProto.registerAllExtensions(extensionRegistry); + ClientProto.registerAllExtensions(extensionRegistry); + ResourceProto.registerAllExtensions(extensionRegistry); + FieldBehaviorProto.registerAllExtensions(extensionRegistry); + } +} diff --git a/src/main/java/com/google/api/generator/MainFromFile.java b/src/main/java/com/google/api/generator/MainFromFile.java new file mode 100644 index 0000000000..e93f2db6ca --- /dev/null +++ b/src/main/java/com/google/api/generator/MainFromFile.java @@ -0,0 +1,60 @@ +// 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; + +import com.google.api.AnnotationsProto; +import com.google.api.ClientProto; +import com.google.api.FieldBehaviorProto; +import com.google.api.ResourceProto; +import com.google.api.generator.gapic.Generator; +import com.google.longrunning.OperationsProto; +import com.google.protobuf.Descriptors.DescriptorValidationException; +import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest; +import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class MainFromFile { + public static void main(String[] args) + throws IOException, InterruptedException, DescriptorValidationException { + ExtensionRegistry registry = ExtensionRegistry.newInstance(); + registerAllExtensions(registry); + + String inputFile = args[0]; + String outputFile = args[1]; + + try (InputStream inputStream = new FileInputStream(inputFile); + OutputStream outputStream = new FileOutputStream(outputFile); ) { + CodeGeneratorRequest request = CodeGeneratorRequest.parseFrom(inputStream, registry); + CodeGeneratorResponse response = Generator.generateGapic(request); + response.writeTo(outputStream); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + /** Register all extensions needed to process API protofiles. */ + private static void registerAllExtensions(ExtensionRegistry extensionRegistry) { + OperationsProto.registerAllExtensions(extensionRegistry); + AnnotationsProto.registerAllExtensions(extensionRegistry); + ClientProto.registerAllExtensions(extensionRegistry); + ResourceProto.registerAllExtensions(extensionRegistry); + FieldBehaviorProto.registerAllExtensions(extensionRegistry); + } +} 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 ae08ecda8b..066424921e 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/rest", "//src/main/java/com/google/api/generator/gapic/composer/resourcename", "//src/main/java/com/google/api/generator/gapic/composer/samplecode", "//src/main/java/com/google/api/generator/gapic/composer/store", 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 8dd716eb2a..4c6a4d3eed 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 @@ -27,12 +27,15 @@ import com.google.api.generator.gapic.composer.grpc.ServiceSettingsClassComposer; import com.google.api.generator.gapic.composer.grpc.ServiceStubSettingsClassComposer; 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.ResourceName; import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.gapic.model.Transport; import com.google.common.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; @@ -80,9 +83,20 @@ public static List generateStubClasses(GapicContext context) { .forEach( s -> { 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)); + if (context.transport() == Transport.REST) { + clazzes.add( + com.google.api.generator.gapic.composer.rest.ServiceStubSettingsClassComposer + .instance() + .generate(context, s)); + clazzes.add( + HttpJsonServiceCallableFactoryClassComposer.instance().generate(context, s)); + clazzes.add(HttpJsonServiceStubClassComposer.instance().generate(context, s)); + } else { + clazzes.add(ServiceStubSettingsClassComposer.instance().generate(context, s)); + clazzes.add( + GrpcServiceCallableFactoryClassComposer.instance().generate(context, s)); + clazzes.add(GrpcServiceStubClassComposer.instance().generate(context, s)); + } }); return clazzes; } @@ -94,7 +108,14 @@ public static List generateClientSettingsClasses(GapicContext contex .forEach( s -> { clazzes.add(ServiceClientClassComposer.instance().generate(context, s)); - clazzes.add(ServiceSettingsClassComposer.instance().generate(context, s)); + if (context.transport() == Transport.REST) { + clazzes.add( + com.google.api.generator.gapic.composer.rest.ServiceSettingsClassComposer + .instance() + .generate(context, s)); + } else { + clazzes.add(ServiceSettingsClassComposer.instance().generate(context, s)); + } }); return clazzes; } @@ -103,15 +124,28 @@ public static List generateMockClasses(GapicContext context, List clazzes = new ArrayList<>(); services.forEach( s -> { - clazzes.add(MockServiceClassComposer.instance().generate(context, s)); - clazzes.add(MockServiceImplClassComposer.instance().generate(context, s)); + if (context.transport() == Transport.REST) { + // REST transport tests donot not use mock services. + } else { + clazzes.add(MockServiceClassComposer.instance().generate(context, s)); + clazzes.add(MockServiceImplClassComposer.instance().generate(context, s)); + } }); return clazzes; } public static List generateTestClasses(GapicContext context) { return context.services().stream() - .map(s -> ServiceClientTestClassComposer.instance().generate(context, s)) + .map( + 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); + } + }) .collect(Collectors.toList()); } 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 7f45e974b3..fddeb531a4 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 @@ -98,7 +98,7 @@ public abstract class AbstractServiceClientTestClassComposer implements ClassCom protected static final TypeStore FIXED_TYPESTORE = createStaticTypes(); protected static final AnnotationNode TEST_ANNOTATION = - AnnotationNode.withType(FIXED_TYPESTORE.get("Test")); + AnnotationNode.withType(FIXED_TYPESTORE.get("Test")); private final TransportContext transportContext; @@ -816,8 +816,10 @@ private void addDynamicTypes(GapicContext context, Service service, TypeStore ty Arrays.asList( ClassNames.getMockServiceClassName(service), ClassNames.getServiceClientClassName(service), - ClassNames.getServiceSettingsClassName(service), - getTransportContext().classNames().getTransportServiceStubClassName(service))); + ClassNames.getServiceSettingsClassName(service))); + String stubPakkage = String.format("%s.stub", service.pakkage()); + typeStore.put( + stubPakkage, getTransportContext().classNames().getTransportServiceStubClassName(service)); // Pagination types. typeStore.putAll( service.pakkage(), 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 e7b30ebcbe..0e50ab3be8 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 @@ -289,7 +289,7 @@ private AnonymousClassExpr createRequestParamsExtractorAnonClass(Method method) VariableExpr.withVariable( Variable.builder().setType(method.inputType()).setName("request").build()); - for (String httpBindingFieldName : method.httpBindings()) { + for (String httpBindingFieldName : method.httpBindings().pathParameters()) { // Handle foo.bar cases by descending into the subfields. MethodInvocationExpr.Builder requestFieldGetterExprBuilder = MethodInvocationExpr.builder().setExprReferenceExpr(requestVarExpr); diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/composer/rest/BUILD.bazel new file mode 100644 index 0000000000..39c0461c35 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/BUILD.bazel @@ -0,0 +1,52 @@ +load("@rules_java//java:defs.bzl", "java_library") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "rest_files", + srcs = glob(["*.java"]), +) + +java_library( + name = "rest", + srcs = [ + ":rest_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/common", + "//src/main/java/com/google/api/generator/gapic/composer/comment", + "//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/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:gax", + "@com_google_api_gax_java//gax:gax_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/rest/HttpJsonServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java new file mode 100644 index 0000000000..435f9e63b3 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java @@ -0,0 +1,81 @@ +// 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.rest; + +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.httpjson.ApiMessage; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.gapic.composer.common.AbstractServiceCallableFactoryClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class HttpJsonServiceCallableFactoryClassComposer + extends AbstractServiceCallableFactoryClassComposer { + private static final HttpJsonServiceCallableFactoryClassComposer INSTANCE = + new HttpJsonServiceCallableFactoryClassComposer(); + + private static final TypeNode MESSAGE_TYPE = + TypeNode.withReference(ConcreteReference.withClazz(ApiMessage.class)); + private static final TypeNode BACKGROUND_RESOURCE_TYPE = + TypeNode.withReference(ConcreteReference.withClazz(BackgroundResource.class)); + + private HttpJsonServiceCallableFactoryClassComposer() { + super(RestContext.instance()); + } + + public static HttpJsonServiceCallableFactoryClassComposer instance() { + return INSTANCE; + } + + @Override + protected List createClassImplements(TypeStore typeStore) { + return Arrays.asList( + TypeNode.withReference( + getTransportContext() + .stubCallableFactoryType() + .reference() + .copyAndSetGenerics( + Arrays.asList( + MESSAGE_TYPE.reference(), BACKGROUND_RESOURCE_TYPE.reference())))); + } + + @Override + protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { + String methodVariantName = "Operation"; + String requestTemplateName = "RequestT"; + String responseTemplateName = "ResponseT"; + List methodTemplateNames = + Arrays.asList(requestTemplateName, responseTemplateName, "MetadataT"); + MethodDefinition method = + createGenericCallableMethod( + typeStore, + /*methodTemplateNames=*/ methodTemplateNames, + /*returnCallableKindName=*/ methodVariantName, + /*returnCallableTemplateNames=*/ methodTemplateNames, + /*methodVariantName=*/ methodVariantName, + /*httpJsonCallSettingsTemplateObjects=*/ Arrays.asList( + requestTemplateName, MESSAGE_TYPE), + /*callSettingsVariantName=*/ methodVariantName, + /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList())); + return method.toBuilder().setReturnExpr(ValueExpr.createNullExpr()).build(); + } +} 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 new file mode 100644 index 0000000000..582530c563 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java @@ -0,0 +1,507 @@ +// 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.rest; + +import com.google.api.client.http.HttpMethods; +import com.google.api.core.InternalApi; +import com.google.api.gax.httpjson.ApiMethodDescriptor; +import com.google.api.gax.httpjson.FieldsExtractor; +import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; +import com.google.api.gax.httpjson.ProtoMessageRequestFormatter; +import com.google.api.gax.httpjson.ProtoMessageResponseParser; +import com.google.api.gax.httpjson.ProtoRestSerializer; +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.AnonymousClassExpr; +import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.EnumRefExpr; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.ExprStatement; +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.ScopeNode; +import com.google.api.generator.engine.ast.Statement; +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.common.AbstractServiceStubClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class HttpJsonServiceStubClassComposer extends AbstractServiceStubClassComposer { + private static final HttpJsonServiceStubClassComposer INSTANCE = + new HttpJsonServiceStubClassComposer(); + + protected static final TypeStore FIXED_REST_TYPESTORE = createStaticTypes(); + + protected HttpJsonServiceStubClassComposer() { + super(RestContext.instance()); + } + + public static HttpJsonServiceStubClassComposer instance() { + return INSTANCE; + } + + private static TypeStore createStaticTypes() { + return new TypeStore( + Arrays.asList( + ApiMethodDescriptor.class, + ArrayList.class, + FieldsExtractor.class, + InternalApi.class, + HashMap.class, + HttpJsonCallSettings.class, + HttpJsonStubCallableFactory.class, + Map.class, + ProtoMessageRequestFormatter.class, + ProtoMessageResponseParser.class, + ProtoRestSerializer.class)); + } + + @Override + protected Statement createMethodDescriptorVariableDecl( + Service service, Method protoMethod, VariableExpr methodDescriptorVarExpr) { + MethodInvocationExpr expr = + MethodInvocationExpr.builder() + .setMethodName("newBuilder") + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(ApiMethodDescriptor.class.getSimpleName())) + .setGenerics(methodDescriptorVarExpr.variable().type().reference().generics()) + .build(); + + BiFunction, Function> maker = + getMethodMaker(); + + String codeMethodNameArg = getProtoRpcFullMethodName(service, protoMethod); + expr = + maker + .apply( + "setFullMethodName", + Arrays.asList(ValueExpr.withValue(StringObjectValue.withValue(codeMethodNameArg)))) + .apply(expr); + + expr = maker.apply("setHttpMethod", getHttpMethodTypeExpr(protoMethod)).apply(expr); + expr = maker.apply("setRequestFormatter", getRequestFormatterExpr(protoMethod)).apply(expr); + + expr = maker.apply("setResponseParser", setResponseParserExpr(protoMethod)).apply(expr); + + expr = + MethodInvocationExpr.builder() + .setMethodName("build") + .setExprReferenceExpr(expr) + .setReturnType(methodDescriptorVarExpr.type()) + .build(); + + return ExprStatement.withExpr( + AssignmentExpr.builder() + .setVariableExpr( + methodDescriptorVarExpr.toBuilder() + .setIsDecl(true) + .setScope(ScopeNode.PRIVATE) + .setIsStatic(true) + .setIsFinal(true) + .build()) + .setValueExpr(expr) + .build()); + } + + @Override + protected List createOperationsStubGetterMethod( + VariableExpr operationsStubVarExpr) { + return Collections.emptyList(); + } + + @Override + protected Expr createTransportSettingsInitExpr( + Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr) { + MethodInvocationExpr callSettingsBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(HttpJsonCallSettings.class.getSimpleName())) + .setGenerics(transportSettingsVarExpr.type().reference().generics()) + .setMethodName("newBuilder") + .build(); + callSettingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(callSettingsBuilderExpr) + .setMethodName("setMethodDescriptor") + .setArguments(Arrays.asList(methodDescriptorVarExpr)) + .build(); + + callSettingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(callSettingsBuilderExpr) + .setMethodName("build") + .setReturnType(transportSettingsVarExpr.type()) + .build(); + return AssignmentExpr.builder() + .setVariableExpr(transportSettingsVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(callSettingsBuilderExpr) + .build(); + } + + @Override + protected List createClassAnnotations(Service service) { + List annotations = super.createClassAnnotations(service); + + annotations.add( + AnnotationNode.builder() + .setType(FIXED_TYPESTORE.get("BetaApi")) + .setDescription( + "A restructuring of stub classes is planned, so this may break in the future") + .build()); + return annotations; + } + + @Override + protected List createGetMethodDescriptorsMethod( + Service service, + TypeStore typeStore, + Map protoMethodNameToDescriptorVarExprs) { + + List bodyExprs = new ArrayList<>(); + + VariableExpr methodDescriptorsVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(List.class) + .setGenerics( + Arrays.asList( + FIXED_REST_TYPESTORE.get("ApiMethodDescriptor").reference())) + .build())) + .setName("methodDescriptors") + .build()); + + bodyExprs.add( + AssignmentExpr.builder() + .setVariableExpr(methodDescriptorsVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + NewObjectExpr.builder() + .setType(FIXED_REST_TYPESTORE.get("ArrayList")) + .setIsGeneric(true) + .build()) + .build()); + + for (VariableExpr methodDescriptorVarExpr : protoMethodNameToDescriptorVarExprs.values()) { + bodyExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(methodDescriptorsVarExpr) + .setMethodName("add") + .setArguments(methodDescriptorVarExpr) + .build()); + } + + return Arrays.asList( + MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(methodDescriptorsVarExpr.type()) + .setReturnExpr(methodDescriptorsVarExpr) + .setAnnotations( + Arrays.asList(AnnotationNode.withType(FIXED_REST_TYPESTORE.get("InternalApi")))) + .setName("getMethodDescriptors") + .setBody(bodyExprs.stream().map(ExprStatement::withExpr).collect(Collectors.toList())) + .build()); + } + + private BiFunction, Function> + getMethodMaker() { + return (mName, argExpr) -> + (m) -> + MethodInvocationExpr.builder() + .setMethodName(mName) + .setArguments(argExpr) + .setExprReferenceExpr(m) + .build(); + } + + private List getRequestFormatterExpr(Method protoMethod) { + BiFunction, Function> + methodMaker = getMethodMaker(); + + MethodInvocationExpr expr = + MethodInvocationExpr.builder() + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(ProtoMessageRequestFormatter.class.getSimpleName())) + .setMethodName("newBuilder") + .setGenerics(Collections.singletonList(protoMethod.inputType().reference())) + // .setArguments(Arrays.asList(m)) + .build(); + + TypeNode extractorVarType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(Map.class) + .setGenerics(TypeNode.STRING.reference(), TypeNode.STRING.reference()) + .build()); + + expr = + methodMaker + .apply( + "setPath", + Arrays.asList( + ValueExpr.withValue( + StringObjectValue.withValue(protoMethod.httpBindings().patternLowerCamel())), + createFieldsExtractorAnonClass( + protoMethod, + extractorVarType, + protoMethod.httpBindings().pathParameters(), + "putPathParam"))) + .apply(expr); + + TypeNode fieldsVarGenericType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(List.class) + .setGenerics(TypeNode.STRING.reference()) + .build()); + + extractorVarType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(Map.class) + .setGenerics(TypeNode.STRING.reference(), fieldsVarGenericType.reference()) + .build()); + + expr = + methodMaker + .apply( + "setQueryParamsExtractor", + Arrays.asList( + createFieldsExtractorAnonClass( + protoMethod, + extractorVarType, + protoMethod.httpBindings().queryParameters(), + "putQueryParam"))) + .apply(expr); + + extractorVarType = TypeNode.STRING; + expr = + methodMaker + .apply( + "setRequestBodyExtractor", + Arrays.asList( + createFieldsExtractorAnonClass( + protoMethod, + extractorVarType, + protoMethod.httpBindings().bodyParameters(), + "toBody"))) + .apply(expr); + expr = methodMaker.apply("build", Collections.emptyList()).apply(expr); + + return Collections.singletonList(expr); + } + + private List setResponseParserExpr(Method protoMethod) { + BiFunction, Function> + methodMaker = getMethodMaker(); + + MethodInvocationExpr expr = + MethodInvocationExpr.builder() + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(ProtoMessageResponseParser.class.getSimpleName())) + .setMethodName("newBuilder") + .setGenerics(Collections.singletonList(protoMethod.outputType().reference())) + // .setArguments(Arrays.asList(m)) + .build(); + + expr = + methodMaker + .apply( + "setDefaultInstance", + Arrays.asList( + MethodInvocationExpr.builder() + .setStaticReferenceType(protoMethod.outputType()) + .setMethodName("getDefaultInstance") + .setReturnType(protoMethod.outputType()) + .build())) + .apply(expr); + expr = methodMaker.apply("build", Collections.emptyList()).apply(expr); + + return Collections.singletonList(expr); + } + + private Expr createFieldsExtractorAnonClass( + Method method, + TypeNode extractorReturnType, + Set httpBindingFieldNames, + String serializerMethodName) { + List bodyExprs = new ArrayList<>(); + + Expr returnExpr = null; + VariableExpr fieldsVarExpr = null; + Expr serializerExpr = null; + if (!extractorReturnType.isProtoPrimitiveType()) { + 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(); + + bodyExprs.add(fieldsAssignExpr); + returnExpr = fieldsVarExpr; + + TypeNode serializerVarType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(ProtoRestSerializer.class) + .setGenerics(method.inputType().reference()) + .build()); + + VariableExpr serializerVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("serializer").setType(serializerVarType).build()); + + 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(); + + serializerExpr = serializerVarExpr; + + bodyExprs.add(serializerAssignExpr); + } else { + serializerExpr = + MethodInvocationExpr.builder() + .setMethodName("create") + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) + .build(); + if (httpBindingFieldNames.isEmpty()) { + returnExpr = ValueExpr.createNullExpr(); + } + } + + VariableExpr requestVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(method.inputType()).setName("request").build()); + + for (String httpBindingFieldName : httpBindingFieldNames) { + // Handle foo.bar cases by descending into the subfields. + MethodInvocationExpr.Builder requestFieldGetterExprBuilder = + MethodInvocationExpr.builder().setExprReferenceExpr(requestVarExpr); + String[] descendantFields = httpBindingFieldName.split("\\."); + for (int i = 0; i < descendantFields.length; i++) { + String currFieldName = descendantFields[i]; + String bindingFieldMethodName = + String.format("get%s", JavaStyle.toUpperCamelCase(currFieldName)); + requestFieldGetterExprBuilder = + requestFieldGetterExprBuilder.setMethodName(bindingFieldMethodName); + if (i < descendantFields.length - 1) { + requestFieldGetterExprBuilder = + MethodInvocationExpr.builder() + .setExprReferenceExpr(requestFieldGetterExprBuilder.build()); + } + } + + MethodInvocationExpr requestBuilderExpr = requestFieldGetterExprBuilder.build(); + + ImmutableList.Builder paramsPutArgs = ImmutableList.builder(); + if (fieldsVarExpr != null) { + paramsPutArgs.add(fieldsVarExpr); + } + paramsPutArgs.add( + ValueExpr.withValue( + StringObjectValue.withValue(JavaStyle.toLowerCamelCase(httpBindingFieldName)))); + paramsPutArgs.add(requestBuilderExpr); + + if (fieldsVarExpr == null) { + Expr paramsPutExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(serializerExpr) + .setMethodName(serializerMethodName) + .setArguments(paramsPutArgs.build()) + .setReturnType(extractorReturnType) + .build(); + + returnExpr = paramsPutExpr; + } else { + Expr paramsPutExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(serializerExpr) + .setMethodName(serializerMethodName) + .setArguments(paramsPutArgs.build()) + .build(); + bodyExprs.add(paramsPutExpr); + } + } + + MethodDefinition extractMethod = + MethodDefinition.builder() + .setIsOverride(true) + .setScope(ScopeNode.PUBLIC) + .setReturnType(extractorReturnType) + .setName("extract") + .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) + .setBody(bodyExprs.stream().map(ExprStatement::withExpr).collect(Collectors.toList())) + .setReturnExpr(returnExpr) + .build(); + + TypeNode anonClassType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(FieldsExtractor.class) + .setGenerics(method.inputType().reference(), extractorReturnType.reference()) + .build()); + + return AnonymousClassExpr.builder().setType(anonClassType).setMethods(extractMethod).build(); + } + + private List getHttpMethodTypeExpr(Method protoMethod) { + EnumRefExpr expr = + EnumRefExpr.builder() + .setName(protoMethod.httpBindings().httpVerb()) + .setType( + TypeNode.withReference( + ConcreteReference.builder().setClazz(HttpMethods.class).build())) + .build(); + return Collections.singletonList(expr); + } +} 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 new file mode 100644 index 0000000000..fc5b385427 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java @@ -0,0 +1,55 @@ +// 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.rest; + +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.httpjson.ApiMethodDescriptor; +import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonCallableFactory; +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.generator.gapic.composer.common.TransportContext; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Transport; + +public abstract class RestContext extends TransportContext { + private static final TransportContext INSTANCE = + RestContext.builder() + .setClassNames(new ClassNames("HttpJson")) + .setTransport(Transport.REST) + .setTransportName("REST") + // For httpjson.HttpJsonServiceStubClassComposer + .setCallSettingsClass(HttpJsonCallSettings.class) + .setStubCallableFactoryType(classToType(HttpJsonStubCallableFactory.class)) + .setMethodDescriptorClass(ApiMethodDescriptor.class) + .setTransportOperationsStubType(null) + // For httpjson.ServiceSettingsClassComposer + .setInstantiatingChannelProviderClass(InstantiatingHttpJsonChannelProvider.Builder.class) + .setDefaultTransportProviderBuilderName("defaultHttpJsonTransportProviderBuilder") + // For httpjson.ServiceStubSettingsClassComposer + .setTransportChannelType(classToType(HttpJsonTransportChannel.class)) + .setTransportGetterName("getHttpJsonTransportName") + // For httpjson.HttpJsonServiceCallableFactoryClassComposer + .setTransportCallSettingsType(classToType(HttpJsonCallSettings.class)) + .setTransportCallableFactoryType(classToType(HttpJsonCallableFactory.class)) + .setOperationsStubType(classToType(BackgroundResource.class)) + .setTransportCallSettingsName("httpJsonCallSettings") + .build(); + + public static TransportContext 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 new file mode 100644 index 0000000000..7a0a422ab4 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java @@ -0,0 +1,535 @@ +// 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.rest; + +import com.google.api.gax.httpjson.ApiMethodDescriptor; +import com.google.api.gax.httpjson.GaxHttpJsonProperties; +import com.google.api.gax.httpjson.testing.MockHttpService; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ApiException; +import com.google.api.gax.rpc.ApiExceptionFactory; +import com.google.api.gax.rpc.StatusCode.Code; +import com.google.api.gax.rpc.testing.FakeStatusCode; +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.EnumRefExpr; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.ExprStatement; +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.PrimitiveValue; +import com.google.api.generator.engine.ast.ScopeNode; +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.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.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.ClassNames; +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.MethodArgument; +import com.google.api.generator.gapic.model.ResourceName; +import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.gapic.utils.JavaStyle; +import com.google.common.collect.ImmutableList; +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.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class ServiceClientTestClassComposer extends AbstractServiceClientTestClassComposer { + private static final String MOCK_SERVICE_VAR_NAME = "mockService"; + private static final String METHOD_DESCRIPTOR_NAME_PATTERN = "%sMethodDescriptor"; + + private static final ServiceClientTestClassComposer INSTANCE = + new ServiceClientTestClassComposer(); + + protected static final TypeStore FIXED_REST_TYPESTORE = createStaticTypes(); + + protected ServiceClientTestClassComposer() { + super(RestContext.instance()); + } + + public static ServiceClientTestClassComposer instance() { + return INSTANCE; + } + + private static TypeStore createStaticTypes() { + return new TypeStore( + Arrays.asList( + ApiClientHeaderProvider.class, + ApiException.class, + ApiExceptionFactory.class, + ApiMethodDescriptor.class, + Code.class, + Exception.class, + FakeStatusCode.class, + GaxHttpJsonProperties.class, + ImmutableList.class, + MockHttpService.class, + String.class)); + } + + @Override + protected Map createClassMemberVarExprs( + Service service, GapicContext context, TypeStore typeStore) { + BiFunction varExprFn = + (name, type) -> + VariableExpr.withVariable(Variable.builder().setName(name).setType(type).build()); + Map fields = new LinkedHashMap<>(); + fields.put( + MOCK_SERVICE_VAR_NAME, FIXED_REST_TYPESTORE.get(MockHttpService.class.getSimpleName())); + fields.put(CLIENT_VAR_NAME, typeStore.get(ClassNames.getServiceClientClassName(service))); + return fields.entrySet().stream() + .collect(Collectors.toMap(e -> e.getKey(), e -> varExprFn.apply(e.getKey(), e.getValue()))); + } + + @Override + protected List createClassMemberFieldDecls( + Map classMemberVarExprs) { + return classMemberVarExprs.values().stream() + .map( + v -> + ExprStatement.withExpr( + v.toBuilder() + .setIsDecl(true) + .setScope(ScopeNode.PRIVATE) + .setIsStatic(true) + .build())) + .collect(Collectors.toList()); + } + + @Override + protected MethodDefinition createStartStaticServerMethod( + Service service, + GapicContext context, + Map classMemberVarExprs, + TypeStore typeStore) { + + VariableExpr mockServiceVarExpr = classMemberVarExprs.get(MOCK_SERVICE_VAR_NAME); + VariableExpr clientVarExpr = classMemberVarExprs.get(CLIENT_VAR_NAME); + TypeNode settingsType = typeStore.get(ClassNames.getServiceSettingsClassName(service)); + TypeNode transportStubType = + typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); + + Function> methodBuilderFn = + methodExpr -> + (mName, argExpr) -> + MethodInvocationExpr.builder() + .setExprReferenceExpr(methodExpr) + .setMethodName(mName) + .setArguments(Arrays.asList(argExpr)) + .build(); + + Expr initMockServiceExpr = + AssignmentExpr.builder() + .setVariableExpr(mockServiceVarExpr) + .setValueExpr( + NewObjectExpr.builder() + .setType(mockServiceVarExpr.type()) + .setArguments( + MethodInvocationExpr.builder() + .setStaticReferenceType(transportStubType) + .setMethodName("getMethodDescriptors") + .build(), + MethodInvocationExpr.builder() + .setStaticReferenceType(settingsType) + .setMethodName("getDefaultEndpoint") + .build()) + .build()) + .build(); + + VariableExpr localSettingsVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("settings").setType(settingsType).build()); + + Expr settingsBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(settingsType) + .setMethodName("newBuilder") + .build(); + + Expr transportChannelProviderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(settingsType) + .setMethodName("defaultHttpJsonTransportProviderBuilder") + .build(); + + transportChannelProviderExpr = + methodBuilderFn + .apply(transportChannelProviderExpr) + .apply("setHttpTransport", mockServiceVarExpr); + + transportChannelProviderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(transportChannelProviderExpr) + .setMethodName("build") + .setReturnType(localSettingsVarExpr.type()) + .build(); + + settingsBuilderExpr = + methodBuilderFn + .apply(settingsBuilderExpr) + .apply("setTransportChannelProvider", transportChannelProviderExpr); + + settingsBuilderExpr = + methodBuilderFn + .apply(settingsBuilderExpr) + .apply( + "setCredentialsProvider", + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("NoCredentialsProvider")) + .setMethodName("create") + .build()); + settingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(settingsBuilderExpr) + .setMethodName("build") + .setReturnType(localSettingsVarExpr.type()) + .build(); + + Expr initLocalSettingsExpr = + AssignmentExpr.builder() + .setVariableExpr(localSettingsVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(settingsBuilderExpr) + .build(); + + Expr initClientExpr = + AssignmentExpr.builder() + .setVariableExpr(clientVarExpr) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType( + typeStore.get(ClassNames.getServiceClientClassName(service))) + .setMethodName("create") + .setArguments(Arrays.asList(localSettingsVarExpr)) + .setReturnType(clientVarExpr.type()) + .build()) + .build(); + + return MethodDefinition.builder() + .setAnnotations( + Arrays.asList(AnnotationNode.withType(FIXED_TYPESTORE.get("BeforeClass")))) + .setScope(ScopeNode.PUBLIC) + .setReturnType(TypeNode.VOID) + .setName("startStaticServer") + .setThrowsExceptions(Arrays.asList(FIXED_TYPESTORE.get("IOException"))) + .setIsStatic(true) + .setBody( + Arrays.asList(initMockServiceExpr, initLocalSettingsExpr, initClientExpr).stream() + .map(e -> ExprStatement.withExpr(e)) + .collect(Collectors.toList())) + .build(); + } + + @Override + protected MethodDefinition createStopServerMethod( + Service service, Map classMemberVarExprs) { + return MethodDefinition.builder() + .setAnnotations( + Arrays.asList(AnnotationNode.withType(FIXED_TYPESTORE.get("AfterClass")))) + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(TypeNode.VOID) + .setName("stopServer") + .setBody( + Arrays.asList( + ExprStatement.withExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get(CLIENT_VAR_NAME)) + .setMethodName("close") + .build()))) + .build(); + } + + @Override + protected MethodDefinition createSetUpMethod( + Service service, Map classMemberVarExprs, TypeStore typeStore) { + + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(AnnotationNode.withType(FIXED_TYPESTORE.get("Before")))) + .setScope(ScopeNode.PUBLIC) + .setReturnType(TypeNode.VOID) + .setName("setUp") + .setBody(Arrays.asList()) + .build(); + } + + @Override + protected MethodDefinition createTearDownMethod( + Service service, Map classMemberVarExprs) { + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(AnnotationNode.withType(FIXED_TYPESTORE.get("After")))) + .setScope(ScopeNode.PUBLIC) + .setReturnType(TypeNode.VOID) + .setName("tearDown") + .setThrowsExceptions( + Arrays.asList(TypeNode.withReference(ConcreteReference.withClazz(Exception.class)))) + .setBody( + Arrays.asList( + ExprStatement.withExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get(MOCK_SERVICE_VAR_NAME)) + .setMethodName("reset") + .build()))) + .build(); + } + + @Override + protected List constructRpcTestCheckerLogic( + Method method, + Service service, + boolean isRequestArg, + Map classMemberVarExprs, + VariableExpr requestVarExpr, + Message requestMessage, + List argExprs) { + + List methodExprs = new ArrayList<>(); + List methodStatements = new ArrayList<>(); + + VariableExpr actualRequestsVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(List.class) + .setGenerics( + Arrays.asList(FIXED_REST_TYPESTORE.get("String").reference())) + .build())) + .setName("actualRequests") + .build()); + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(actualRequestsVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get(getMockServiceVarName(service))) + .setMethodName("getRequestPaths") + .setReturnType(actualRequestsVarExpr.type()) + .build()) + .build()); + + methodExprs.add( + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) + .setMethodName("assertEquals") + .setArguments( + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.INT).setValue("1").build()), + MethodInvocationExpr.builder() + .setExprReferenceExpr(actualRequestsVarExpr) + .setMethodName("size") + .build()) + .build()); + + methodStatements.addAll( + methodExprs.stream().map(ExprStatement::withExpr).collect(Collectors.toList())); + + methodExprs.clear(); + methodStatements.add(EMPTY_LINE_STATEMENT); + + VariableExpr apiClientHeaderKeyVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType(FIXED_REST_TYPESTORE.get("String")) + .setName("apiClientHeaderKey") + .build()); + + AssignmentExpr apiClientHeaderKeyAssignExpr = + AssignmentExpr.builder() + .setVariableExpr(apiClientHeaderKeyVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setMethodName("next") + .setReturnType(apiClientHeaderKeyVarExpr.type()) + .setExprReferenceExpr( + MethodInvocationExpr.builder() + .setMethodName("iterator") + .setExprReferenceExpr( + MethodInvocationExpr.builder() + .setMethodName("get") + .setArguments( + MethodInvocationExpr.builder() + .setMethodName("getDefaultApiClientHeaderKey") + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get("ApiClientHeaderProvider")) + .build()) + .setExprReferenceExpr( + MethodInvocationExpr.builder() + .setMethodName("getRequestHeaders") + .setExprReferenceExpr( + classMemberVarExprs.get( + getMockServiceVarName(service))) + .build()) + .build()) + .build()) + .build()) + .build(); + + methodExprs.add(apiClientHeaderKeyAssignExpr); + + methodExprs.add( + MethodInvocationExpr.builder() + .setMethodName("assertTrue") + .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) + .setArguments( + MethodInvocationExpr.builder() + .setMethodName("matches") + .setExprReferenceExpr( + MethodInvocationExpr.builder() + .setMethodName("matcher") + .setArguments(apiClientHeaderKeyVarExpr) + .setExprReferenceExpr( + MethodInvocationExpr.builder() + .setMethodName("getDefaultApiClientHeaderPattern") + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get("GaxHttpJsonProperties")) + .build()) + .build()) + .build()) + .build()); + + methodStatements.addAll( + methodExprs.stream().map(ExprStatement::withExpr).collect(Collectors.toList())); + methodExprs.clear(); + + return methodStatements; + } + + @Override + protected MethodDefinition createStreamingRpcTestMethod( + Service service, + Method method, + Map classMemberVarExprs, + Map resourceNames, + Map messageTypes) { + return null; + } + + + @Override + protected MethodDefinition createRpcExceptionTestMethod( + Method method, + Service service, + List methodSignature, + int variantIndex, + Map classMemberVarExprs, + Map resourceNames, + Map messageTypes) { + VariableExpr exceptionVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType(FIXED_REST_TYPESTORE.get("ApiException")) + .setName("exception") + .build()); + + // First two assignment lines. + + Expr exceptionAssignExpr = + AssignmentExpr.builder() + .setVariableExpr(exceptionVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setMethodName("createException") + .setStaticReferenceType(FIXED_REST_TYPESTORE.get("ApiExceptionFactory")) + .setArguments( + NewObjectExpr.withType(FIXED_REST_TYPESTORE.get("Exception")), + MethodInvocationExpr.builder() + .setMethodName("of") + .setStaticReferenceType(FIXED_REST_TYPESTORE.get("FakeStatusCode")) + .setArguments( + EnumRefExpr.builder() + .setName("INVALID_ARGUMENT") + .setType(FIXED_REST_TYPESTORE.get("Code")) + .build()) + .build(), + ValueExpr.withValue( + PrimitiveValue.builder() + .setType(TypeNode.BOOLEAN) + .setValue("false") + .build())) + .setReturnType(exceptionVarExpr.type()) + .build()) + .build(); + + Expr addExceptionExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get(getMockServiceVarName(service))) + .setMethodName("addException") + .setArguments(exceptionVarExpr) + .build(); + + // Try-catch block. Build the method call. + String exceptionTestMethodName = + String.format( + "%sExceptionTest%s", + JavaStyle.toLowerCamelCase(method.name()), variantIndex > 0 ? variantIndex + 1 : ""); + + boolean isStreaming = !method.stream().equals(Method.Stream.NONE); + List methodBody = new ArrayList<>(); + methodBody.add(ExprStatement.withExpr(exceptionAssignExpr)); + methodBody.add(ExprStatement.withExpr(addExceptionExpr)); + if (isStreaming) { + methodBody.addAll( + createStreamingRpcExceptionTestStatements( + method, classMemberVarExprs, resourceNames, messageTypes)); + } else { + methodBody.addAll( + createRpcExceptionTestStatements( + method, methodSignature, classMemberVarExprs, resourceNames, messageTypes)); + } + + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(TEST_ANNOTATION)) + .setScope(ScopeNode.PUBLIC) + .setReturnType(TypeNode.VOID) + .setName(exceptionTestMethodName) + .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(Exception.class))) + .setBody(methodBody) + .build(); + } + + @Override + protected List createStreamingRpcExceptionTestStatements( + Method method, + Map classMemberVarExprs, + Map resourceNames, + Map messageTypes) { + return Collections.emptyList(); + } + + @Override + protected List createRpcLroExceptionTestCatchBody( + VariableExpr exceptionExpr, boolean isStreaming) { + return Collections.emptyList(); + } + + @Override + protected String getMockServiceVarName(Service service) { + return String.format(MOCK_SERVICE_VAR_NAME); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceSettingsClassComposer.java new file mode 100644 index 0000000000..53e27d577d --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceSettingsClassComposer.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 +// +// 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.rest; + +import com.google.api.generator.gapic.composer.common.AbstractServiceSettingsClassComposer; + +public class ServiceSettingsClassComposer extends AbstractServiceSettingsClassComposer { + private static final ServiceSettingsClassComposer INSTANCE = + new ServiceSettingsClassComposer(); + + protected ServiceSettingsClassComposer() { + super(RestContext.instance()); + } + + public static ServiceSettingsClassComposer 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 new file mode 100644 index 0000000000..c0f535ca7e --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java @@ -0,0 +1,172 @@ +// 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.rest; + +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.common.AbstractServiceStubSettingsClassComposer; +import com.google.api.generator.gapic.composer.comment.SettingsCommentComposer; +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; + +public class ServiceStubSettingsClassComposer extends + AbstractServiceStubSettingsClassComposer { + private static final ServiceStubSettingsClassComposer INSTANCE = + new ServiceStubSettingsClassComposer(); + + protected static final TypeStore FIXED_REST_TYPESTORE = createStaticTypes(); + + public static ServiceStubSettingsClassComposer instance() { + return INSTANCE; + } + + protected ServiceStubSettingsClassComposer() { + super(RestContext.instance()); + } + + private static TypeStore createStaticTypes() { + return new TypeStore( + Arrays.asList( + GaxHttpJsonProperties.class, + HttpJsonTransportChannel.class, + InstantiatingHttpJsonChannelProvider.class)); + } + + @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( + 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(); + } + + @Override + public MethodDefinition createDefaultTransportChannelProviderMethod() { + TypeNode returnType = FIXED_TYPESTORE.get("TransportChannelProvider"); + MethodInvocationExpr transportProviderBuilderExpr = + MethodInvocationExpr.builder() + .setMethodName("defaultHttpJsonTransportProviderBuilder") + .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(); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/store/TypeStore.java b/src/main/java/com/google/api/generator/gapic/composer/store/TypeStore.java index 061c42a67c..1a6c2e1c13 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/store/TypeStore.java +++ b/src/main/java/com/google/api/generator/gapic/composer/store/TypeStore.java @@ -29,6 +29,10 @@ public class TypeStore { public TypeStore() {} public TypeStore(List concreteClasses) { + putConcreteClassses(concreteClasses); + } + + private void putConcreteClassses(List concreteClasses) { store.putAll( concreteClasses.stream() .collect( @@ -67,6 +71,10 @@ public void put( .build())); } + public void putAll(List concreteClasses) { + putConcreteClassses(concreteClasses); + } + public void putAll( String pakkage, List typeNames, diff --git a/src/main/java/com/google/api/generator/gapic/model/HttpRuleBindings.java b/src/main/java/com/google/api/generator/gapic/model/HttpRuleBindings.java new file mode 100644 index 0000000000..431027e444 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/model/HttpRuleBindings.java @@ -0,0 +1,74 @@ +// 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.model; + +import com.google.api.generator.gapic.utils.JavaStyle; +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableSet; +import java.util.Set; + +@AutoValue +public abstract class HttpRuleBindings { + // private static final Pattern PATH_PARAM_PATTERN = Pattern.compile("[]") + public abstract String httpVerb(); + + public abstract String pattern(); + + public abstract Set pathParameters(); + + public abstract Set queryParameters(); + + public abstract Set bodyParameters(); + + // Private. + public static HttpRuleBindings.Builder builder() { + return new AutoValue_HttpRuleBindings.Builder() + .setHttpVerb("") + .setPattern("") + .setPathParameters(ImmutableSet.of()) + .setQueryParameters(ImmutableSet.of()) + .setBodyParameters(ImmutableSet.of()); + } + + public boolean isEmpty() { + return pathParameters().isEmpty(); + } + + public String patternLowerCamel() { + String lowerCamelPattern = pattern(); + for (String pathParam : pathParameters()) { + lowerCamelPattern = + lowerCamelPattern.replaceAll( + "\\{" + pathParam, "{" + JavaStyle.toLowerCamelCase(pathParam)); + } + return lowerCamelPattern; + } + + // Private. + @AutoValue.Builder + public abstract static class Builder { + public abstract HttpRuleBindings.Builder setHttpVerb(String httpVerb); + + public abstract HttpRuleBindings.Builder setPattern(String pattern); + + public abstract HttpRuleBindings.Builder setPathParameters(Set pathParameters); + + public abstract HttpRuleBindings.Builder setQueryParameters(Set queryParameters); + + public abstract HttpRuleBindings.Builder setBodyParameters(Set bodyParameters); + + public abstract HttpRuleBindings build(); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/model/Method.java b/src/main/java/com/google/api/generator/gapic/model/Method.java index df5a9aa668..514ed94a04 100644 --- a/src/main/java/com/google/api/generator/gapic/model/Method.java +++ b/src/main/java/com/google/api/generator/gapic/model/Method.java @@ -53,9 +53,8 @@ public enum Stream { @Nullable public abstract String mixedInApiName(); - // TODO(miraleung): May need to change this to MethodArgument, Field, or some new struct // HttpBinding pending dotted reference support. - public abstract List httpBindings(); + public abstract HttpRuleBindings httpBindings(); // Example from Expand in echo.proto: Thet TypeNodes that map to // [["content", "error"], ["content", "error", "info"]]. @@ -83,7 +82,7 @@ public static Builder builder() { return new AutoValue_Method.Builder() .setStream(Stream.NONE) .setMethodSignatures(ImmutableList.of()) - .setHttpBindings(ImmutableList.of()) + .setHttpBindings(HttpRuleBindings.builder().build()) .setIsBatching(false) .setIsPaged(false) .setIsDeprecated(false); @@ -118,7 +117,7 @@ public abstract static class Builder { public abstract Builder setMixedInApiName(String mixedInApiName); - public abstract Builder setHttpBindings(List httpBindings); + public abstract Builder setHttpBindings(HttpRuleBindings httpBindings); public abstract Builder setMethodSignatures(List> methodSignature); 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 10c9b1b071..5969b7e75f 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 @@ -18,16 +18,17 @@ import com.google.api.HttpRule; import com.google.api.HttpRule.PatternCase; import com.google.api.generator.gapic.model.Field; +import com.google.api.generator.gapic.model.HttpRuleBindings; import com.google.api.generator.gapic.model.Message; import com.google.api.pathtemplate.PathTemplate; import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Sets; import com.google.protobuf.DescriptorProtos.MethodOptions; import com.google.protobuf.Descriptors.MethodDescriptor; -import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -36,11 +37,11 @@ public class HttpRuleParser { private static final String ASTERISK = "*"; - public static Optional> parseHttpBindings( + public static HttpRuleBindings parse( MethodDescriptor protoMethod, Message inputMessage, Map messageTypes) { MethodOptions methodOptions = protoMethod.getOptions(); if (!methodOptions.hasExtension(AnnotationsProto.http)) { - return Optional.empty(); + return HttpRuleBindings.builder().build(); } HttpRule httpRule = methodOptions.getExtension(AnnotationsProto.http); @@ -53,26 +54,23 @@ public static Optional> parseHttpBindings( return parseHttpRuleHelper(httpRule, Optional.of(inputMessage), messageTypes); } - public static Optional> parseHttpRule(HttpRule httpRule) { + public static HttpRuleBindings parseHttpRule(HttpRule httpRule) { return parseHttpRuleHelper(httpRule, Optional.empty(), Collections.emptyMap()); } - private static Optional> parseHttpRuleHelper( + private static HttpRuleBindings parseHttpRuleHelper( HttpRule httpRule, Optional inputMessageOpt, Map messageTypes) { // Get pattern. - Set uniqueBindings = getHttpVerbPattern(httpRule); - if (uniqueBindings.isEmpty()) { - return Optional.empty(); - } - + String pattern = getPattern(httpRule); + ImmutableSet.Builder bindingsBuilder = getPatternBindings(pattern); if (httpRule.getAdditionalBindingsCount() > 0) { for (HttpRule additionalRule : httpRule.getAdditionalBindingsList()) { - uniqueBindings.addAll(getHttpVerbPattern(additionalRule)); + // TODO: save additional bindings path in HttpRuleBindings + bindingsBuilder.addAll(getPatternBindings(getPattern(additionalRule)).build()); } } - List bindings = new ArrayList<>(uniqueBindings); - Collections.sort(bindings); + Set bindings = bindingsBuilder.build(); // Binding validation. for (String binding : bindings) { @@ -99,40 +97,67 @@ private static Optional> parseHttpRuleHelper( } } - return Optional.of(bindings); + // TODO: support nested message fields bindings + String body = httpRule.getBody(); + Set bodyParameters; + Set queryParameters; + if (!inputMessageOpt.isPresent()) { + // Must be a mixin, do not support full HttpRuleBindings for now + bodyParameters = ImmutableSet.of(); + queryParameters = ImmutableSet.of(); + } else if (Strings.isNullOrEmpty(body)) { + bodyParameters = ImmutableSet.of(); + queryParameters = Sets.difference(inputMessageOpt.get().fieldMap().keySet(), bindings); + } else if (body.equals(ASTERISK)) { + bodyParameters = Sets.difference(inputMessageOpt.get().fieldMap().keySet(), bindings); + queryParameters = ImmutableSet.of(); + } else { + bodyParameters = ImmutableSet.of(body); + Set bodyBinidngsUnion = Sets.union(bodyParameters, bindings); + queryParameters = + Sets.difference(inputMessageOpt.get().fieldMap().keySet(), bodyBinidngsUnion); + } + + HttpRuleBindings.Builder httpBindings = HttpRuleBindings.builder(); + httpBindings.setHttpVerb(httpRule.getPatternCase().toString()); + httpBindings.setPattern(pattern); + httpBindings.setPathParameters(ImmutableSortedSet.copyOf(bindings)); + httpBindings.setQueryParameters(ImmutableSortedSet.copyOf(queryParameters)); + httpBindings.setBodyParameters(ImmutableSortedSet.copyOf(bodyParameters)); + + return httpBindings.build(); } - private static Set getHttpVerbPattern(HttpRule httpRule) { - String pattern = null; - // Assign a temp variable to prevent the formatter from removing the import. + private static String getPattern(HttpRule httpRule) { PatternCase patternCase = httpRule.getPatternCase(); switch (patternCase) { case GET: - pattern = httpRule.getGet(); - break; + return httpRule.getGet(); case PUT: - pattern = httpRule.getPut(); - break; + return httpRule.getPut(); case POST: - pattern = httpRule.getPost(); - break; + return httpRule.getPost(); case DELETE: - pattern = httpRule.getDelete(); - break; + return httpRule.getDelete(); case PATCH: - pattern = httpRule.getPatch(); - break; + return httpRule.getPatch(); case CUSTOM: // Invalid pattern. // Fall through. default: - return Collections.emptySet(); + return ""; + } + } + + private static ImmutableSortedSet.Builder getPatternBindings(String pattern) { + ImmutableSortedSet.Builder bindings = ImmutableSortedSet.naturalOrder(); + if (pattern.isEmpty()) { + return bindings; } PathTemplate template = PathTemplate.create(pattern); - Set bindings = - new HashSet( - // Filter out any unbound variable like "$0, $1, etc. - template.vars().stream().filter(s -> !s.contains("$")).collect(Collectors.toList())); + // Filter out any unbound variable like "$0, $1, etc. + bindings.addAll( + template.vars().stream().filter(s -> !s.contains("$")).collect(Collectors.toSet())); return bindings; } diff --git a/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java b/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java index a088e8ae46..518cb0b6bc 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java +++ b/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java @@ -26,6 +26,7 @@ import com.google.api.generator.gapic.model.GapicLanguageSettings; import com.google.api.generator.gapic.model.GapicLroRetrySettings; import com.google.api.generator.gapic.model.GapicServiceConfig; +import com.google.api.generator.gapic.model.HttpRuleBindings; import com.google.api.generator.gapic.model.LongrunningOperation; import com.google.api.generator.gapic.model.Message; import com.google.api.generator.gapic.model.Method; @@ -106,6 +107,7 @@ public static GapicContext parse(CodeGeneratorRequest request) { GapicLroRetrySettingsParser.parse(gapicYamlConfigPathOpt); Optional languageSettingsOpt = GapicLanguageSettingsParser.parse(gapicYamlConfigPathOpt); + Optional transportOpt = PluginArgumentParser.parseTransport(request); boolean willGenerateMetadata = PluginArgumentParser.hasMetadataFlag(request); @@ -186,7 +188,7 @@ public static GapicContext parse(CodeGeneratorRequest request) { .setServiceConfig(serviceConfigOpt.isPresent() ? serviceConfigOpt.get() : null) .setGapicMetadataEnabled(willGenerateMetadata) .setServiceYamlProto(serviceYamlProtoOpt.isPresent() ? serviceYamlProtoOpt.get() : null) - .setTransport(Transport.GRPC) + .setTransport(Transport.parse(transportOpt.orElse(Transport.GRPC.toString()))) .build(); } @@ -247,18 +249,18 @@ public static List parseServices( // Key: proto_package.ServiceName.RpcName. // Value: HTTP rules, which clobber those in the proto. // Assumes that http.rules.selector always specifies RPC names in the above format. - Map> mixedInMethodsToHttpRules = new HashMap<>(); + Map mixedInMethodsToHttpRules = new HashMap<>(); Map mixedInMethodsToDocs = new HashMap<>(); // Parse HTTP rules and documentation, which will override the proto. if (serviceYamlProtoOpt.isPresent()) { for (HttpRule httpRule : serviceYamlProtoOpt.get().getHttp().getRulesList()) { - Optional> httpBindingsOpt = HttpRuleParser.parseHttpRule(httpRule); - if (!httpBindingsOpt.isPresent()) { + HttpRuleBindings httpBindings = HttpRuleParser.parseHttpRule(httpRule); + if (httpBindings.isEmpty()) { continue; } for (String rpcFullNameRaw : httpRule.getSelector().split(",")) { String rpcFullName = rpcFullNameRaw.trim(); - mixedInMethodsToHttpRules.put(rpcFullName, httpBindingsOpt.get()); + mixedInMethodsToHttpRules.put(rpcFullName, httpBindings); } } for (DocumentationRule docRule : @@ -304,7 +306,7 @@ public static List parseServices( // HTTP rules and RPC documentation in the service.yaml file take // precedence. String fullMethodName = methodToFullProtoNameFn.apply(m); - List httpBindings = + HttpRuleBindings httpBindings = mixedInMethodsToHttpRules.containsKey(fullMethodName) ? mixedInMethodsToHttpRules.get(fullMethodName) : m.httpBindings(); @@ -542,7 +544,7 @@ private static boolean isMapType(Descriptor messageDescriptor) { * Populates ResourceName objects in Message POJOs. * * @param messageTypes A map of the message type name (as in the protobuf) to Message POJOs. - * @param resourceNames A list of ResourceName POJOs. + * @param resources A list of ResourceName POJOs. * @return The updated messageTypes map. */ public static Map updateResourceNamesInMessages( @@ -614,10 +616,7 @@ static List parseMethods( Message inputMessage = messageTypes.get(inputType.reference().fullName()); Preconditions.checkNotNull( inputMessage, String.format("No message found for %s", inputType.reference().fullName())); - Optional> httpBindingsOpt = - HttpRuleParser.parseHttpBindings(protoMethod, inputMessage, messageTypes); - List httpBindings = - httpBindingsOpt.isPresent() ? httpBindingsOpt.get() : Collections.emptyList(); + HttpRuleBindings httpBindings = HttpRuleParser.parse(protoMethod, inputMessage, messageTypes); boolean isBatching = !serviceConfigOpt.isPresent() ? false @@ -848,7 +847,9 @@ private static Field parseField( .setType(TypeParser.parseType(fieldDescriptor)) .setIsMessage(fieldDescriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) .setIsEnum(fieldDescriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) - .setIsContainedInOneof(fieldDescriptor.getContainingOneof() != null) + .setIsContainedInOneof( + fieldDescriptor.getContainingOneof() != null + && !fieldDescriptor.getContainingOneof().isSynthetic()) .setIsRepeated(fieldDescriptor.isRepeated()) .setIsMap(fieldDescriptor.isMapField()) .setResourceReference(resourceReference) diff --git a/src/main/java/com/google/api/generator/gapic/protoparser/PluginArgumentParser.java b/src/main/java/com/google/api/generator/gapic/protoparser/PluginArgumentParser.java index 53cd0f32f3..d5a7de1f79 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/PluginArgumentParser.java +++ b/src/main/java/com/google/api/generator/gapic/protoparser/PluginArgumentParser.java @@ -30,6 +30,7 @@ public class PluginArgumentParser { @VisibleForTesting static final String KEY_GAPIC_CONFIG = "gapic-config"; @VisibleForTesting static final String KEY_METADATA = "metadata"; @VisibleForTesting static final String KEY_SERVICE_YAML_CONFIG = "api-service-config"; + @VisibleForTesting static final String KEY_TRANSPORT = "transport"; private static final String JSON_FILE_ENDING = "grpc_service_config.json"; private static final String GAPIC_YAML_FILE_ENDING = "gapic.yaml"; @@ -47,6 +48,10 @@ static Optional parseServiceYamlConfigPath(CodeGeneratorRequest request) return parseServiceYamlConfigPath(request.getParameter()); } + static Optional parseTransport(CodeGeneratorRequest request) { + return parseConfigArgument(request.getParameter(), KEY_TRANSPORT); + } + static boolean hasMetadataFlag(CodeGeneratorRequest request) { return hasMetadataFlag(request.getParameter()); } @@ -54,17 +59,33 @@ static boolean hasMetadataFlag(CodeGeneratorRequest request) { /** Expects a comma-separated list of file paths. */ @VisibleForTesting static Optional parseJsonConfigPath(String pluginProtocArgument) { - return parseArgument(pluginProtocArgument, KEY_GRPC_SERVICE_CONFIG, JSON_FILE_ENDING); + return parseFileArgument(pluginProtocArgument, KEY_GRPC_SERVICE_CONFIG, JSON_FILE_ENDING); } @VisibleForTesting static Optional parseGapicYamlConfigPath(String pluginProtocArgument) { - return parseArgument(pluginProtocArgument, KEY_GAPIC_CONFIG, GAPIC_YAML_FILE_ENDING); + return parseFileArgument(pluginProtocArgument, KEY_GAPIC_CONFIG, GAPIC_YAML_FILE_ENDING); } @VisibleForTesting static Optional parseServiceYamlConfigPath(String pluginProtocArgument) { - return parseArgument(pluginProtocArgument, KEY_SERVICE_YAML_CONFIG, SERVICE_YAML_FILE_ENDING); + return parseFileArgument( + pluginProtocArgument, KEY_SERVICE_YAML_CONFIG, SERVICE_YAML_FILE_ENDING); + } + + @VisibleForTesting + private static Optional parseConfigArgument(String pluginProtocArgument, String key) { + if (Strings.isNullOrEmpty(pluginProtocArgument)) { + return Optional.empty(); + } + + for (String argComponent : pluginProtocArgument.split(COMMA)) { + String[] args = argComponent.trim().split(EQUALS); + if (args.length == 2 && key.equals(args[0])) { + return Optional.of(args[1]); + } + } + return Optional.empty(); } @VisibleForTesting @@ -72,10 +93,10 @@ static boolean hasMetadataFlag(String pluginProtocArgument) { return Arrays.stream(pluginProtocArgument.split(COMMA)).anyMatch(s -> s.equals(KEY_METADATA)); } - private static Optional parseArgument( + private static Optional parseFileArgument( String pluginProtocArgument, String key, String fileEnding) { if (Strings.isNullOrEmpty(pluginProtocArgument)) { - return Optional.empty(); + return Optional.empty(); } for (String argComponent : pluginProtocArgument.split(COMMA)) { String[] args = argComponent.trim().split(EQUALS); @@ -93,6 +114,6 @@ private static Optional parseArgument( return Optional.of(valueVal); } } - return Optional.empty(); + return Optional.empty(); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/TestProtoLoader.java b/src/test/java/com/google/api/generator/gapic/composer/common/TestProtoLoader.java index 5cd4ade9da..c1be33ad25 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/TestProtoLoader.java +++ b/src/test/java/com/google/api/generator/gapic/composer/common/TestProtoLoader.java @@ -268,4 +268,8 @@ public GapicContext parseLogging() { public String getTestFilesDirectory() { return testFilesDirectory; } + + public Transport getTransport() { + return transport; + } } 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 8c0cabe5a1..dde9ad4053 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 @@ -33,9 +33,7 @@ TEST_DEPS = [ "//src/main/java/com/google/api/generator/gapic/model", "//src/main/java/com/google/api/generator/gapic/protoparser", "//src/main/java/com/google/api/generator/gapic/composer/defaultvalue", - "//src/test/java/com/google/api/generator/gapic/testdata:deprecated_service_java_proto", "//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto", - "//src/test/java/com/google/api/generator/gapic/testdata:testgapic_java_proto", "@com_google_api_api_common//jar", "@com_google_api_gax_java//gax", "@com_google_api_api_common", diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/rest/BUILD.bazel new file mode 100644 index 0000000000..da9ede10b2 --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/BUILD.bazel @@ -0,0 +1,99 @@ +load("@rules_java//java:defs.bzl", "java_proto_library", "java_test") +load("//:rules_bazel/java/java_diff_test.bzl", "golden_update") + +package(default_visibility = ["//visibility:public"]) + +TESTS = [ + "HttpJsonServiceCallableFactoryClassComposerTest", + "HttpJsonServiceStubClassComposerTest", + "ServiceClientTestClassComposerTest", + "ServiceSettingsClassComposerTest", + "ServiceStubSettingsClassComposerTest", +] + +COMMON_SRCS = [ + "RestTestProtoLoader.java", +] + +TEST_DEPS = [ + ":common_resources_java_proto", + "//: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/composer", + "//src/main/java/com/google/api/generator/gapic/composer/common", + "//src/main/java/com/google/api/generator/gapic/composer/rest", + "//src/test/java/com/google/api/generator/gapic/composer/common", + "//src/test/java/com/google/api/generator/test/framework:asserts", + "//src/test/java/com/google/api/generator/test/framework:utils", + "//src/main/java/com/google/api/generator/gapic/composer/samplecode", + "//src/test/java/com/google/api/generator/testutils", + "//src/main/java/com/google/api/generator/gapic/model", + "//src/main/java/com/google/api/generator/gapic/protoparser", + "//src/main/java/com/google/api/generator/gapic/composer/defaultvalue", + "//src/test/java/com/google/api/generator/gapic/testdata:deprecated_service_java_proto", + "//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto", + "//src/test/java/com/google/api/generator/gapic/testdata:testgapic_java_proto", + "@com_google_api_api_common//jar", + "@com_google_api_gax_java//gax", + "@com_google_api_api_common", + "@com_google_googleapis//google/logging/v2:logging_java_proto", + "@com_google_googleapis//google/pubsub/v1:pubsub_java_proto", + "@com_google_googleapis//google/rpc:rpc_java_proto", + "@com_google_guava_guava", + "@com_google_protobuf//:protobuf_java", + "@com_google_truth_truth//jar", + "@junit_junit//jar", +] + +filegroup( + name = "composer_files", + srcs = glob(["*.java"]), +) + +java_proto_library( + name = "pubsub_java_proto", + deps = [ + "@com_google_googleapis//google/pubsub/v1:pubsub_proto", + ], +) + +java_proto_library( + name = "common_resources_java_proto", + deps = [ + "@com_google_googleapis//google/cloud:common_resources_proto", + ], +) + +[java_test( + name = test_name, + size = "medium", + srcs = [ + "{0}.java".format(test_name), + ] + COMMON_SRCS, + data = [ + "//src/test/java/com/google/api/generator/gapic/composer/rest/goldens:goldens_files", + "//src/test/java/com/google/api/generator/gapic/testdata:gapic_config_files", + "//src/test/java/com/google/api/generator/gapic/testdata:service_config_files", + ], + test_class = "com.google.api.generator.gapic.composer.rest.{0}".format(test_name), + deps = TEST_DEPS, +) for test_name in TESTS] + +# Run `bazel run src/test/java/com/google/api/generator/gapic/composer/rest:testTargetName_update` +# to update goldens as expected generated code. +# `ServiceClient*` tests are not supported now since they are still in active development. + +[golden_update( + name = "{0}_update".format(test_name), + srcs = [ + "{0}.java".format(test_name), + ] + COMMON_SRCS, + data = [ + "//src/test/java/com/google/api/generator/gapic/composer/rest/goldens:goldens_files", + "//src/test/java/com/google/api/generator/gapic/testdata:gapic_config_files", + "//src/test/java/com/google/api/generator/gapic/testdata:service_config_files", + ], + test_class = "com.google.api.generator.gapic.composer.rest.{0}".format(test_name), + deps = TEST_DEPS, +) for test_name in TESTS] diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposerTest.java new file mode 100644 index 0000000000..2207e3d7d1 --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposerTest.java @@ -0,0 +1,43 @@ +// 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.rest; + +import com.google.api.generator.engine.writer.JavaWriterVisitor; +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 com.google.api.generator.test.framework.Assert; +import com.google.api.generator.test.framework.Utils; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.Test; + +public class HttpJsonServiceCallableFactoryClassComposerTest { + @Test + public void generateServiceClasses() { + GapicContext context = RestTestProtoLoader.instance().parseCompliance(); + Service echoProtoService = context.services().get(0); + GapicClass clazz = + HttpJsonServiceCallableFactoryClassComposer.instance().generate(context, echoProtoService); + + JavaWriterVisitor visitor = new JavaWriterVisitor(); + clazz.classDefinition().accept(visitor); + Utils.saveCodegenToFile( + this.getClass(), "HttpJsonComplianceCallableFactory.golden", visitor.write()); + Path goldenFilePath = + Paths.get(Utils.getGoldenDir(this.getClass()), "HttpJsonComplianceCallableFactory.golden"); + Assert.assertCodeEquals(goldenFilePath, visitor.write()); + } +} diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposerTest.java new file mode 100644 index 0000000000..1efb7fd67b --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposerTest.java @@ -0,0 +1,42 @@ +// 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.rest; + +import com.google.api.generator.engine.writer.JavaWriterVisitor; +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 com.google.api.generator.test.framework.Assert; +import com.google.api.generator.test.framework.Utils; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.Test; + +public class HttpJsonServiceStubClassComposerTest { + @Test + public void generateHttpJsonServiceStubClass_simple() { + GapicContext context = RestTestProtoLoader.instance().parseCompliance(); + Service echoProtoService = context.services().get(0); + GapicClass clazz = + HttpJsonServiceStubClassComposer.instance().generate(context, echoProtoService); + + JavaWriterVisitor visitor = new JavaWriterVisitor(); + clazz.classDefinition().accept(visitor); + Utils.saveCodegenToFile(this.getClass(), "HttpJsonComplianceStub.golden", visitor.write()); + Path goldenFilePath = + Paths.get(Utils.getGoldenDir(this.getClass()), "HttpJsonComplianceStub.golden"); + Assert.assertCodeEquals(goldenFilePath, visitor.write()); + } +} diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/RestTestProtoLoader.java b/src/test/java/com/google/api/generator/gapic/composer/rest/RestTestProtoLoader.java new file mode 100644 index 0000000000..b729cc17c0 --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/RestTestProtoLoader.java @@ -0,0 +1,78 @@ +// 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.rest; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +import com.google.api.generator.gapic.composer.common.TestProtoLoader; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.GapicServiceConfig; +import com.google.api.generator.gapic.model.Message; +import com.google.api.generator.gapic.model.ResourceName; +import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.gapic.model.Transport; +import com.google.api.generator.gapic.protoparser.Parser; +import com.google.api.generator.gapic.protoparser.ServiceConfigParser; +import com.google.protobuf.Descriptors.FileDescriptor; +import com.google.protobuf.Descriptors.ServiceDescriptor; +import com.google.showcase.v1beta1.ComplianceOuterClass; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +public class RestTestProtoLoader extends TestProtoLoader { + private static final RestTestProtoLoader INSTANCE = new RestTestProtoLoader(); + + protected RestTestProtoLoader() { + super(Transport.REST, "src/test/java/com/google/api/generator/gapic/testdata/"); + } + + public static RestTestProtoLoader instance() { + return INSTANCE; + } + + public GapicContext parseCompliance() { + FileDescriptor echoFileDescriptor = ComplianceOuterClass.getDescriptor(); + ServiceDescriptor echoServiceDescriptor = echoFileDescriptor.getServices().get(0); + assertEquals(echoServiceDescriptor.getName(), "Compliance"); + + Map messageTypes = Parser.parseMessages(echoFileDescriptor); + Map resourceNames = Parser.parseResourceNames(echoFileDescriptor); + Set outputResourceNames = new HashSet<>(); + List services = + Parser.parseService( + echoFileDescriptor, messageTypes, resourceNames, Optional.empty(), outputResourceNames); + + String jsonFilename = "showcase_grpc_service_config.json"; + Path jsonPath = Paths.get(getTestFilesDirectory(), jsonFilename); + Optional configOpt = ServiceConfigParser.parse(jsonPath.toString()); + assertTrue(configOpt.isPresent()); + GapicServiceConfig config = configOpt.get(); + + return GapicContext.builder() + .setMessages(messageTypes) + .setResourceNames(resourceNames) + .setServices(services) + .setServiceConfig(config) + .setHelperResourceNames(outputResourceNames) + .setTransport(getTransport()) + .build(); + } +} diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposerTest.java new file mode 100644 index 0000000000..786344fcc1 --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposerTest.java @@ -0,0 +1,42 @@ +// 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.rest; + +import static com.google.api.generator.test.framework.Assert.assertCodeEquals; + +import com.google.api.generator.engine.writer.JavaWriterVisitor; +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 com.google.api.generator.test.framework.Utils; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.Test; + +public class ServiceClientTestClassComposerTest { + @Test + public void generateClientTest_echoClient() { + GapicContext context = RestTestProtoLoader.instance().parseCompliance(); + Service echoProtoService = context.services().get(0); + GapicClass clazz = + ServiceClientTestClassComposer.instance().generate(context, echoProtoService); + + JavaWriterVisitor visitor = new JavaWriterVisitor(); + clazz.classDefinition().accept(visitor); + Utils.saveCodegenToFile(this.getClass(), "ComplianceClientTest.golden", visitor.write()); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "ComplianceClientTest.golden"); + assertCodeEquals(goldenFilePath, visitor.write()); + } +} diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceSettingsClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceSettingsClassComposerTest.java new file mode 100644 index 0000000000..5631b00607 --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceSettingsClassComposerTest.java @@ -0,0 +1,41 @@ +// 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.rest; + +import com.google.api.generator.engine.writer.JavaWriterVisitor; +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 com.google.api.generator.test.framework.Assert; +import com.google.api.generator.test.framework.Utils; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.Test; + +public class ServiceSettingsClassComposerTest { + @Test + public void generateServiceClasses() { + GapicContext context = RestTestProtoLoader.instance().parseCompliance(); + Service echoProtoService = context.services().get(0); + GapicClass clazz = ServiceSettingsClassComposer.instance().generate(context, echoProtoService); + + JavaWriterVisitor visitor = new JavaWriterVisitor(); + clazz.classDefinition().accept(visitor); + Utils.saveCodegenToFile(this.getClass(), "ComplianceSettings.golden", visitor.write()); + Path goldenFilePath = + Paths.get(Utils.getGoldenDir(this.getClass()), "ComplianceSettings.golden"); + Assert.assertCodeEquals(goldenFilePath, visitor.write()); + } +} 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 new file mode 100644 index 0000000000..e3e5641f93 --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java @@ -0,0 +1,42 @@ +// 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.rest; + +import com.google.api.generator.engine.writer.JavaWriterVisitor; +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 com.google.api.generator.test.framework.Assert; +import com.google.api.generator.test.framework.Utils; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.Test; + +public class ServiceStubSettingsClassComposerTest { + @Test + public void generateServiceStubSettingsClasses_basic() { + GapicContext context = RestTestProtoLoader.instance().parseShowcaseEcho(); + Service echoProtoService = context.services().get(0); + GapicClass clazz = + ServiceStubSettingsClassComposer.instance().generate(context, echoProtoService); + + JavaWriterVisitor visitor = new JavaWriterVisitor(); + clazz.classDefinition().accept(visitor); + Utils.saveCodegenToFile(this.getClass(), "ComplianceStubSettings.golden", visitor.write()); + Path goldenFilePath = + Paths.get(Utils.getGoldenDir(this.getClass()), "ComplianceStubSettings.golden"); + Assert.assertCodeEquals(goldenFilePath, visitor.write()); + } +} diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/BUILD.bazel new file mode 100644 index 0000000000..85ac1a519e --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/BUILD.bazel @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "goldens_files", + srcs = glob(["*.golden"]), +) diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceClientTest.golden b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceClientTest.golden new file mode 100644 index 0000000000..9bc2d799ce --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceClientTest.golden @@ -0,0 +1,368 @@ +package com.google.showcase.v1beta1; + +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.httpjson.GaxHttpJsonProperties; +import com.google.api.gax.httpjson.testing.MockHttpService; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ApiException; +import com.google.api.gax.rpc.ApiExceptionFactory; +import com.google.api.gax.rpc.InvalidArgumentException; +import com.google.api.gax.rpc.StatusCode; +import com.google.api.gax.rpc.testing.FakeStatusCode; +import com.google.showcase.v1beta1.stub.HttpJsonComplianceStub; +import java.io.IOException; +import java.util.List; +import javax.annotation.Generated; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +@Generated("by gapic-generator-java") +public class ComplianceClientTest { + private static MockHttpService mockService; + private static ComplianceClient client; + + @BeforeClass + public static void startStaticServer() throws IOException { + mockService = + new MockHttpService( + HttpJsonComplianceStub.getMethodDescriptors(), ComplianceSettings.getDefaultEndpoint()); + ComplianceSettings settings = + ComplianceSettings.newBuilder() + .setTransportChannelProvider( + ComplianceSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport(mockService) + .build()) + .setCredentialsProvider(NoCredentialsProvider.create()) + .build(); + client = ComplianceClient.create(settings); + } + + @AfterClass + public static void stopServer() { + client.close(); + } + + @Before + public void setUp() {} + + @After + public void tearDown() throws Exception { + mockService.reset(); + } + + @Test + public void repeatDataBodyTest() throws Exception { + RepeatResponse expectedResponse = + RepeatResponse.newBuilder().setInfo(ComplianceData.newBuilder().build()).build(); + mockService.addResponse(expectedResponse); + + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + + RepeatResponse actualResponse = client.repeatDataBody(request); + 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 repeatDataBodyExceptionTest() throws Exception { + ApiException exception = + ApiExceptionFactory.createException( + new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); + mockService.addException(exception); + + try { + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + client.repeatDataBody(request); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } + + @Test + public void repeatDataBodyInfoTest() throws Exception { + RepeatResponse expectedResponse = + RepeatResponse.newBuilder().setInfo(ComplianceData.newBuilder().build()).build(); + mockService.addResponse(expectedResponse); + + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + + RepeatResponse actualResponse = client.repeatDataBodyInfo(request); + 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 repeatDataBodyInfoExceptionTest() throws Exception { + ApiException exception = + ApiExceptionFactory.createException( + new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); + mockService.addException(exception); + + try { + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + client.repeatDataBodyInfo(request); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } + + @Test + public void repeatDataQueryTest() throws Exception { + RepeatResponse expectedResponse = + RepeatResponse.newBuilder().setInfo(ComplianceData.newBuilder().build()).build(); + mockService.addResponse(expectedResponse); + + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + + RepeatResponse actualResponse = client.repeatDataQuery(request); + 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 repeatDataQueryExceptionTest() throws Exception { + ApiException exception = + ApiExceptionFactory.createException( + new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); + mockService.addException(exception); + + try { + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + client.repeatDataQuery(request); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } + + @Test + public void repeatDataSimplePathTest() throws Exception { + RepeatResponse expectedResponse = + RepeatResponse.newBuilder().setInfo(ComplianceData.newBuilder().build()).build(); + mockService.addResponse(expectedResponse); + + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + + RepeatResponse actualResponse = client.repeatDataSimplePath(request); + 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 repeatDataSimplePathExceptionTest() throws Exception { + ApiException exception = + ApiExceptionFactory.createException( + new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); + mockService.addException(exception); + + try { + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + client.repeatDataSimplePath(request); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } + + @Test + public void repeatDataPathResourceTest() throws Exception { + RepeatResponse expectedResponse = + RepeatResponse.newBuilder().setInfo(ComplianceData.newBuilder().build()).build(); + mockService.addResponse(expectedResponse); + + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + + RepeatResponse actualResponse = client.repeatDataPathResource(request); + 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 repeatDataPathResourceExceptionTest() throws Exception { + ApiException exception = + ApiExceptionFactory.createException( + new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); + mockService.addException(exception); + + try { + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + client.repeatDataPathResource(request); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } + + @Test + public void repeatDataPathTrailingResourceTest() throws Exception { + RepeatResponse expectedResponse = + RepeatResponse.newBuilder().setInfo(ComplianceData.newBuilder().build()).build(); + mockService.addResponse(expectedResponse); + + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + + RepeatResponse actualResponse = client.repeatDataPathTrailingResource(request); + 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 repeatDataPathTrailingResourceExceptionTest() throws Exception { + ApiException exception = + ApiExceptionFactory.createException( + new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); + mockService.addException(exception); + + try { + RepeatRequest request = + RepeatRequest.newBuilder() + .setName("name3373707") + .setInfo(ComplianceData.newBuilder().build()) + .setServerVerify(true) + .build(); + client.repeatDataPathTrailingResource(request); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } +} diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceSettings.golden b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceSettings.golden new file mode 100644 index 0000000000..2db4024718 --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceSettings.golden @@ -0,0 +1,219 @@ +package com.google.showcase.v1beta1; + +import com.google.api.core.ApiFunction; +import com.google.api.core.BetaApi; +import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.InstantiatingExecutorProvider; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.ClientSettings; +import com.google.api.gax.rpc.StubSettings; +import com.google.api.gax.rpc.TransportChannelProvider; +import com.google.api.gax.rpc.UnaryCallSettings; +import com.google.showcase.v1beta1.stub.ComplianceStubSettings; +import java.io.IOException; +import java.util.List; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Settings class to configure an instance of {@link ComplianceClient}. + * + *

The default instance has everything set to sensible defaults: + * + *

    + *
  • The default service address (localhost) and default port (7469) are used. + *
  • Credentials are acquired automatically through Application Default Credentials. + *
  • Retries are configured for idempotent methods but not for non-idempotent methods. + *
+ * + *

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 repeatDataBody to 30 seconds: + * + *

{@code
+ * ComplianceSettings.Builder complianceSettingsBuilder = ComplianceSettings.newBuilder();
+ * complianceSettingsBuilder
+ *     .repeatDataBodySettings()
+ *     .setRetrySettings(
+ *         complianceSettingsBuilder
+ *             .repeatDataBodySettings()
+ *             .getRetrySettings()
+ *             .toBuilder()
+ *             .setTotalTimeout(Duration.ofSeconds(30))
+ *             .build());
+ * ComplianceSettings complianceSettings = complianceSettingsBuilder.build();
+ * }
+ */ +@BetaApi +@Generated("by gapic-generator-java") +public class ComplianceSettings extends ClientSettings { + + /** Returns the object with the settings used for calls to repeatDataBody. */ + public UnaryCallSettings repeatDataBodySettings() { + return ((ComplianceStubSettings) getStubSettings()).repeatDataBodySettings(); + } + + /** Returns the object with the settings used for calls to repeatDataBodyInfo. */ + public UnaryCallSettings repeatDataBodyInfoSettings() { + return ((ComplianceStubSettings) getStubSettings()).repeatDataBodyInfoSettings(); + } + + /** Returns the object with the settings used for calls to repeatDataQuery. */ + public UnaryCallSettings repeatDataQuerySettings() { + return ((ComplianceStubSettings) getStubSettings()).repeatDataQuerySettings(); + } + + /** Returns the object with the settings used for calls to repeatDataSimplePath. */ + public UnaryCallSettings repeatDataSimplePathSettings() { + return ((ComplianceStubSettings) getStubSettings()).repeatDataSimplePathSettings(); + } + + /** Returns the object with the settings used for calls to repeatDataPathResource. */ + public UnaryCallSettings repeatDataPathResourceSettings() { + return ((ComplianceStubSettings) getStubSettings()).repeatDataPathResourceSettings(); + } + + /** Returns the object with the settings used for calls to repeatDataPathTrailingResource. */ + public UnaryCallSettings repeatDataPathTrailingResourceSettings() { + return ((ComplianceStubSettings) getStubSettings()).repeatDataPathTrailingResourceSettings(); + } + + public static final ComplianceSettings create(ComplianceStubSettings stub) throws IOException { + return new ComplianceSettings.Builder(stub.toBuilder()).build(); + } + + /** Returns a builder for the default ExecutorProvider for this service. */ + public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { + return ComplianceStubSettings.defaultExecutorProviderBuilder(); + } + + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return ComplianceStubSettings.getDefaultEndpoint(); + } + + /** Returns the default service scopes. */ + public static List getDefaultServiceScopes() { + return ComplianceStubSettings.getDefaultServiceScopes(); + } + + /** Returns a builder for the default credentials for this service. */ + public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { + return ComplianceStubSettings.defaultCredentialsProviderBuilder(); + } + + /** Returns a builder for the default ChannelProvider for this service. */ + public static InstantiatingHttpJsonChannelProvider.Builder + defaultHttpJsonTransportProviderBuilder() { + return ComplianceStubSettings.defaultHttpJsonTransportProviderBuilder(); + } + + public static TransportChannelProvider defaultTransportChannelProvider() { + return ComplianceStubSettings.defaultTransportChannelProvider(); + } + + @BetaApi("The surface for customizing headers is not stable yet and may change in the future.") + public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() { + return ComplianceStubSettings.defaultApiClientHeaderProviderBuilder(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder() { + return Builder.createDefault(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder(ClientContext clientContext) { + return new Builder(clientContext); + } + + /** Returns a builder containing all the values of this settings class. */ + public Builder toBuilder() { + return new Builder(this); + } + + protected ComplianceSettings(Builder settingsBuilder) throws IOException { + super(settingsBuilder); + } + + /** Builder for ComplianceSettings. */ + public static class Builder extends ClientSettings.Builder { + + protected Builder() throws IOException { + this(((ClientContext) null)); + } + + protected Builder(ClientContext clientContext) { + super(ComplianceStubSettings.newBuilder(clientContext)); + } + + protected Builder(ComplianceSettings settings) { + super(settings.getStubSettings().toBuilder()); + } + + protected Builder(ComplianceStubSettings.Builder stubSettings) { + super(stubSettings); + } + + private static Builder createDefault() { + return new Builder(ComplianceStubSettings.newBuilder()); + } + + public ComplianceStubSettings.Builder getStubSettingsBuilder() { + return ((ComplianceStubSettings.Builder) getStubSettings()); + } + + // NEXT_MAJOR_VER: remove 'throws Exception'. + /** + * Applies the given settings updater function to all of the unary API methods in this service. + * + *

Note: This method does not support applying settings to streaming methods. + */ + public Builder applyToAllUnaryMethods( + ApiFunction, Void> settingsUpdater) throws Exception { + super.applyToAllUnaryMethods( + getStubSettingsBuilder().unaryMethodSettingsBuilders(), settingsUpdater); + return this; + } + + /** Returns the builder for the settings used for calls to repeatDataBody. */ + public UnaryCallSettings.Builder repeatDataBodySettings() { + return getStubSettingsBuilder().repeatDataBodySettings(); + } + + /** Returns the builder for the settings used for calls to repeatDataBodyInfo. */ + public UnaryCallSettings.Builder repeatDataBodyInfoSettings() { + return getStubSettingsBuilder().repeatDataBodyInfoSettings(); + } + + /** Returns the builder for the settings used for calls to repeatDataQuery. */ + public UnaryCallSettings.Builder repeatDataQuerySettings() { + return getStubSettingsBuilder().repeatDataQuerySettings(); + } + + /** Returns the builder for the settings used for calls to repeatDataSimplePath. */ + public UnaryCallSettings.Builder repeatDataSimplePathSettings() { + return getStubSettingsBuilder().repeatDataSimplePathSettings(); + } + + /** Returns the builder for the settings used for calls to repeatDataPathResource. */ + public UnaryCallSettings.Builder + repeatDataPathResourceSettings() { + return getStubSettingsBuilder().repeatDataPathResourceSettings(); + } + + /** Returns the builder for the settings used for calls to repeatDataPathTrailingResource. */ + public UnaryCallSettings.Builder + repeatDataPathTrailingResourceSettings() { + return getStubSettingsBuilder().repeatDataPathTrailingResourceSettings(); + } + + @Override + public ComplianceSettings build() throws IOException { + return new ComplianceSettings(this); + } + } +} 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 new file mode 100644 index 0000000000..f274021dda --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden @@ -0,0 +1,604 @@ +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.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 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}. + * + *

The default instance has everything set to sensible defaults: + * + *

    + *
  • The default service address (localhost) and default port (7469) are used. + *
  • Credentials are acquired automatically through Application Default Credentials. + *
  • Retries are configured for idempotent methods but not for non-idempotent methods. + *
+ * + *

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: + * + *

{@code
+ * EchoStubSettings.Builder echoSettingsBuilder = EchoStubSettings.newBuilder();
+ * echoSettingsBuilder
+ *     .echoSettings()
+ *     .setRetrySettings(
+ *         echoSettingsBuilder
+ *             .echoSettings()
+ *             .getRetrySettings()
+ *             .toBuilder()
+ *             .setTotalTimeout(Duration.ofSeconds(30))
+ *             .build());
+ * EchoStubSettings echoSettings = echoSettingsBuilder.build();
+ * }
+ */ +@BetaApi +@Generated("by gapic-generator-java") +public class EchoStubSettings 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 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; + } + + /** 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 pagedExpand. */ + public PagedCallSettings + pagedExpandSettings() { + return pagedExpandSettings; + } + + /** 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 wait. */ + public UnaryCallSettings waitSettings() { + return waitSettings; + } + + /** 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; + } + + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") + public EchoStub createStub() throws IOException { + if (getTransportChannelProvider() + .getTransportName() + .equals(HttpJsonTransportChannel.getHttpJsonTransportName())) { + return HttpJsonEchoStub.create(this); + } + throw new UnsupportedOperationException( + String.format( + "Transport not supported: %s", getTransportChannelProvider().getTransportName())); + } + + /** Returns a builder for the default ExecutorProvider for this service. */ + public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { + return InstantiatingExecutorProvider.newBuilder(); + } + + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "localhost:7469"; + } + + /** Returns the default service scopes. */ + public static List getDefaultServiceScopes() { + return DEFAULT_SERVICE_SCOPES; + } + + /** Returns a builder for the default credentials for this service. */ + public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { + return GoogleCredentialsProvider.newBuilder().setScopesToApply(DEFAULT_SERVICE_SCOPES); + } + + /** Returns a builder for the default ChannelProvider for this service. */ + public static InstantiatingHttpJsonChannelProvider.Builder + defaultHttpJsonTransportProviderBuilder() { + return InstantiatingHttpJsonChannelProvider.newBuilder(); + } + + public static TransportChannelProvider defaultTransportChannelProvider() { + return defaultHttpJsonTransportProviderBuilder().build(); + } + + @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)) + .setTransportToken( + GaxHttpJsonProperties.getHttpJsonTokenName(), + GaxHttpJsonProperties.getHttpJsonVersion()); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder() { + return Builder.createDefault(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder(ClientContext clientContext) { + return new Builder(clientContext); + } + + /** Returns a builder containing all the values of this settings class. */ + public Builder toBuilder() { + return new Builder(this); + } + + protected EchoStubSettings(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(); + } + + /** Builder for EchoStubSettings. */ + 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 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())); + RETRYABLE_CODE_DEFINITIONS = definitions.build(); + } + + private static final ImmutableMap RETRY_PARAM_DEFINITIONS; + + 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); + RETRY_PARAM_DEFINITIONS = definitions.build(); + } + + protected Builder() { + this(((ClientContext) null)); + } + + 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(); + + unaryMethodSettingsBuilders = + ImmutableList.>of( + echoSettings, + pagedExpandSettings, + simplePagedExpandSettings, + waitSettings, + blockSettings); + initDefaults(this); + } + + protected Builder(EchoStubSettings 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(); + + unaryMethodSettingsBuilders = + ImmutableList.>of( + echoSettings, + pagedExpandSettings, + simplePagedExpandSettings, + waitSettings, + blockSettings); + } + + private static Builder createDefault() { + Builder builder = new Builder(((ClientContext) null)); + + builder.setTransportChannelProvider(defaultTransportChannelProvider()); + builder.setCredentialsProvider(defaultCredentialsProviderBuilder().build()); + builder.setInternalHeaderProvider(defaultApiClientHeaderProviderBuilder().build()); + builder.setEndpoint(getDefaultEndpoint()); + + return initDefaults(builder); + } + + 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")); + + builder + .pagedExpandSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_1_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_1_params")); + + builder + .simplePagedExpandSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params")); + + builder + .waitSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params")); + + builder + .blockSettings() + .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())); + + return builder; + } + + // NEXT_MAJOR_VER: remove 'throws Exception'. + /** + * Applies the given settings updater function to all of the unary API methods in this service. + * + *

Note: This method does not support applying settings to streaming methods. + */ + public Builder applyToAllUnaryMethods( + ApiFunction, Void> settingsUpdater) throws Exception { + super.applyToAllUnaryMethods(unaryMethodSettingsBuilders, settingsUpdater); + return this; + } + + public ImmutableList> unaryMethodSettingsBuilders() { + 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 simplePagedExpand. */ + public PagedCallSettings.Builder< + PagedExpandRequest, PagedExpandResponse, SimplePagedExpandPagedResponse> + simplePagedExpandSettings() { + return simplePagedExpandSettings; + } + + /** 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 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 block. */ + public UnaryCallSettings.Builder blockSettings() { + return blockSettings; + } + + @Override + public EchoStubSettings build() throws IOException { + return new EchoStubSettings(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 new file mode 100644 index 0000000000..2ddcef8135 --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden @@ -0,0 +1,66 @@ +package com.google.showcase.v1beta1.stub; + +import com.google.api.core.BetaApi; +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.httpjson.ApiMessage; +import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonCallableFactory; +import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; +import com.google.api.gax.rpc.BatchingCallSettings; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.OperationCallSettings; +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 javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * REST callable factory implementation for the Compliance service API. + * + *

This class is for advanced usage. + */ +@BetaApi +@Generated("by gapic-generator-java") +public class HttpJsonComplianceCallableFactory + implements HttpJsonStubCallableFactory { + + @Override + public UnaryCallable createUnaryCallable( + HttpJsonCallSettings httpJsonCallSettings, + UnaryCallSettings callSettings, + ClientContext clientContext) { + return HttpJsonCallableFactory.createUnaryCallable( + httpJsonCallSettings, callSettings, clientContext); + } + + @Override + public + UnaryCallable createPagedCallable( + HttpJsonCallSettings httpJsonCallSettings, + PagedCallSettings callSettings, + ClientContext clientContext) { + return HttpJsonCallableFactory.createPagedCallable( + httpJsonCallSettings, callSettings, clientContext); + } + + @Override + public UnaryCallable createBatchingCallable( + HttpJsonCallSettings httpJsonCallSettings, + BatchingCallSettings callSettings, + ClientContext clientContext) { + return HttpJsonCallableFactory.createBatchingCallable( + httpJsonCallSettings, callSettings, clientContext); + } + + @Override + public + OperationCallable createOperationCallable( + HttpJsonCallSettings httpJsonCallSettings, + OperationCallSettings callSettings, + ClientContext clientContext, + BackgroundResource operationsStub) { + 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 new file mode 100644 index 0000000000..9cf0e50192 --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceStub.golden @@ -0,0 +1,510 @@ +package com.google.showcase.v1beta1.stub; + +import com.google.api.client.http.HttpMethods; +import com.google.api.core.BetaApi; +import com.google.api.core.InternalApi; +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.core.BackgroundResourceAggregation; +import com.google.api.gax.httpjson.ApiMethodDescriptor; +import com.google.api.gax.httpjson.FieldsExtractor; +import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; +import com.google.api.gax.httpjson.ProtoMessageRequestFormatter; +import com.google.api.gax.httpjson.ProtoMessageResponseParser; +import com.google.api.gax.httpjson.ProtoRestSerializer; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.showcase.v1beta1.RepeatRequest; +import com.google.showcase.v1beta1.RepeatResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * REST stub implementation for the Compliance service API. + * + *

This class is for advanced usage and reflects the underlying API directly. + */ +@BetaApi +@Generated("by gapic-generator-java") +@BetaApi("A restructuring of stub classes is planned, so this may break in the future") +public class HttpJsonComplianceStub extends ComplianceStub { + private static final ApiMethodDescriptor + repeatDataBodyMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.showcase.v1beta1.Compliance/RepeatDataBody") + .setHttpMethod(HttpMethods.POST) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1beta1/repeat:body", + new FieldsExtractor>() { + @Override + public Map extract(RepeatRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor>>() { + @Override + public Map> extract(RepeatRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(RepeatRequest request) { + return ProtoRestSerializer.create() + .toBody("serverVerify", request.getServerVerify()); + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(RepeatResponse.getDefaultInstance()) + .build()) + .build(); + + private static final ApiMethodDescriptor + repeatDataBodyInfoMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.showcase.v1beta1.Compliance/RepeatDataBodyInfo") + .setHttpMethod(HttpMethods.POST) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1beta1/repeat:bodyinfo", + new FieldsExtractor>() { + @Override + public Map extract(RepeatRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor>>() { + @Override + public Map> extract(RepeatRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "name", request.getName()); + serializer.putQueryParam( + fields, "serverVerify", request.getServerVerify()); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(RepeatRequest request) { + return ProtoRestSerializer.create().toBody("info", request.getInfo()); + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(RepeatResponse.getDefaultInstance()) + .build()) + .build(); + + private static final ApiMethodDescriptor + repeatDataQueryMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.showcase.v1beta1.Compliance/RepeatDataQuery") + .setHttpMethod(HttpMethods.GET) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1beta1/repeat:query", + new FieldsExtractor>() { + @Override + public Map extract(RepeatRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor>>() { + @Override + public Map> extract(RepeatRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "info", request.getInfo()); + serializer.putQueryParam(fields, "name", request.getName()); + serializer.putQueryParam( + fields, "serverVerify", request.getServerVerify()); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(RepeatRequest request) { + return null; + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(RepeatResponse.getDefaultInstance()) + .build()) + .build(); + + private static final ApiMethodDescriptor + repeatDataSimplePathMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.showcase.v1beta1.Compliance/RepeatDataSimplePath") + .setHttpMethod(HttpMethods.GET) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1beta1/repeat/{info.fString}/{info.fInt32}/{info.fDouble}/{info.fBool}/{info.fKingdom}:simplepath", + new FieldsExtractor>() { + @Override + public Map extract(RepeatRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam( + fields, "info.fBool", request.getInfo().getFBool()); + serializer.putPathParam( + fields, "info.fDouble", request.getInfo().getFDouble()); + serializer.putPathParam( + fields, "info.fInt32", request.getInfo().getFInt32()); + serializer.putPathParam( + fields, "info.fKingdom", request.getInfo().getFKingdom()); + serializer.putPathParam( + fields, "info.fString", request.getInfo().getFString()); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor>>() { + @Override + public Map> extract(RepeatRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "info", request.getInfo()); + serializer.putQueryParam(fields, "name", request.getName()); + serializer.putQueryParam( + fields, "serverVerify", request.getServerVerify()); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(RepeatRequest request) { + return null; + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(RepeatResponse.getDefaultInstance()) + .build()) + .build(); + + private static final ApiMethodDescriptor + repeatDataPathResourceMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.showcase.v1beta1.Compliance/RepeatDataPathResource") + .setHttpMethod(HttpMethods.GET) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1beta1/repeat/{info.fString=first/*}/{info.fChild.fString=second/*}/bool/{info.fBool}:pathresource", + new FieldsExtractor>() { + @Override + public Map extract(RepeatRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam( + fields, "info.fBool", request.getInfo().getFBool()); + serializer.putPathParam( + fields, + "info.fChild.fString", + request.getInfo().getFChild().getFString()); + serializer.putPathParam( + fields, "info.fString", request.getInfo().getFString()); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor>>() { + @Override + public Map> extract(RepeatRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "info", request.getInfo()); + serializer.putQueryParam(fields, "name", request.getName()); + serializer.putQueryParam( + fields, "serverVerify", request.getServerVerify()); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(RepeatRequest request) { + return null; + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(RepeatResponse.getDefaultInstance()) + .build()) + .build(); + + private static final ApiMethodDescriptor + repeatDataPathTrailingResourceMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName( + "google.showcase.v1beta1.Compliance/RepeatDataPathTrailingResource") + .setHttpMethod(HttpMethods.GET) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1beta1/repeat/{info.fString=first/*}/{info.fChild.fString=second/**}:pathtrailingresource", + new FieldsExtractor>() { + @Override + public Map extract(RepeatRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam( + fields, + "info.fChild.fString", + request.getInfo().getFChild().getFString()); + serializer.putPathParam( + fields, "info.fString", request.getInfo().getFString()); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor>>() { + @Override + public Map> extract(RepeatRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "info", request.getInfo()); + serializer.putQueryParam(fields, "name", request.getName()); + serializer.putQueryParam( + fields, "serverVerify", request.getServerVerify()); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(RepeatRequest request) { + return null; + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(RepeatResponse.getDefaultInstance()) + .build()) + .build(); + + private final UnaryCallable repeatDataBodyCallable; + private final UnaryCallable repeatDataBodyInfoCallable; + private final UnaryCallable repeatDataQueryCallable; + private final UnaryCallable repeatDataSimplePathCallable; + private final UnaryCallable repeatDataPathResourceCallable; + private final UnaryCallable repeatDataPathTrailingResourceCallable; + + private final BackgroundResource backgroundResources; + private final HttpJsonStubCallableFactory callableFactory; + + public static final HttpJsonComplianceStub create(ComplianceStubSettings settings) + throws IOException { + return new HttpJsonComplianceStub(settings, ClientContext.create(settings)); + } + + public static final HttpJsonComplianceStub create(ClientContext clientContext) + throws IOException { + return new HttpJsonComplianceStub(ComplianceStubSettings.newBuilder().build(), clientContext); + } + + public static final HttpJsonComplianceStub create( + ClientContext clientContext, HttpJsonStubCallableFactory callableFactory) throws IOException { + return new HttpJsonComplianceStub( + ComplianceStubSettings.newBuilder().build(), clientContext, callableFactory); + } + + /** + * Constructs an instance of HttpJsonComplianceStub, 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. + */ + protected HttpJsonComplianceStub(ComplianceStubSettings settings, ClientContext clientContext) + throws IOException { + this(settings, clientContext, new HttpJsonComplianceCallableFactory()); + } + + /** + * Constructs an instance of HttpJsonComplianceStub, 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. + */ + protected HttpJsonComplianceStub( + ComplianceStubSettings settings, + ClientContext clientContext, + HttpJsonStubCallableFactory callableFactory) + throws IOException { + this.callableFactory = callableFactory; + + HttpJsonCallSettings repeatDataBodyTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(repeatDataBodyMethodDescriptor) + .build(); + HttpJsonCallSettings repeatDataBodyInfoTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(repeatDataBodyInfoMethodDescriptor) + .build(); + HttpJsonCallSettings repeatDataQueryTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(repeatDataQueryMethodDescriptor) + .build(); + HttpJsonCallSettings repeatDataSimplePathTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(repeatDataSimplePathMethodDescriptor) + .build(); + HttpJsonCallSettings repeatDataPathResourceTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(repeatDataPathResourceMethodDescriptor) + .build(); + HttpJsonCallSettings + repeatDataPathTrailingResourceTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(repeatDataPathTrailingResourceMethodDescriptor) + .build(); + + this.repeatDataBodyCallable = + callableFactory.createUnaryCallable( + repeatDataBodyTransportSettings, settings.repeatDataBodySettings(), clientContext); + this.repeatDataBodyInfoCallable = + callableFactory.createUnaryCallable( + repeatDataBodyInfoTransportSettings, + settings.repeatDataBodyInfoSettings(), + clientContext); + this.repeatDataQueryCallable = + callableFactory.createUnaryCallable( + repeatDataQueryTransportSettings, settings.repeatDataQuerySettings(), clientContext); + this.repeatDataSimplePathCallable = + callableFactory.createUnaryCallable( + repeatDataSimplePathTransportSettings, + settings.repeatDataSimplePathSettings(), + clientContext); + this.repeatDataPathResourceCallable = + callableFactory.createUnaryCallable( + repeatDataPathResourceTransportSettings, + settings.repeatDataPathResourceSettings(), + clientContext); + this.repeatDataPathTrailingResourceCallable = + callableFactory.createUnaryCallable( + repeatDataPathTrailingResourceTransportSettings, + settings.repeatDataPathTrailingResourceSettings(), + clientContext); + + this.backgroundResources = + new BackgroundResourceAggregation(clientContext.getBackgroundResources()); + } + + @InternalApi + public static List getMethodDescriptors() { + List methodDescriptors = new ArrayList<>(); + methodDescriptors.add(repeatDataPathTrailingResourceMethodDescriptor); + methodDescriptors.add(repeatDataSimplePathMethodDescriptor); + methodDescriptors.add(repeatDataQueryMethodDescriptor); + methodDescriptors.add(repeatDataPathResourceMethodDescriptor); + methodDescriptors.add(repeatDataBodyMethodDescriptor); + methodDescriptors.add(repeatDataBodyInfoMethodDescriptor); + return methodDescriptors; + } + + @Override + public UnaryCallable repeatDataBodyCallable() { + return repeatDataBodyCallable; + } + + @Override + public UnaryCallable repeatDataBodyInfoCallable() { + return repeatDataBodyInfoCallable; + } + + @Override + public UnaryCallable repeatDataQueryCallable() { + return repeatDataQueryCallable; + } + + @Override + public UnaryCallable repeatDataSimplePathCallable() { + return repeatDataSimplePathCallable; + } + + @Override + public UnaryCallable repeatDataPathResourceCallable() { + return repeatDataPathResourceCallable; + } + + @Override + public UnaryCallable repeatDataPathTrailingResourceCallable() { + return repeatDataPathTrailingResourceCallable; + } + + @Override + public final void close() { + shutdown(); + } + + @Override + public void shutdown() { + backgroundResources.shutdown(); + } + + @Override + public boolean isShutdown() { + return backgroundResources.isShutdown(); + } + + @Override + public boolean isTerminated() { + return backgroundResources.isTerminated(); + } + + @Override + public void shutdownNow() { + backgroundResources.shutdownNow(); + } + + @Override + public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { + return backgroundResources.awaitTermination(duration, unit); + } +} diff --git a/src/test/java/com/google/api/generator/gapic/protoparser/HttpRuleParserTest.java b/src/test/java/com/google/api/generator/gapic/protoparser/HttpRuleParserTest.java index 59a0775b69..dd21d47238 100644 --- a/src/test/java/com/google/api/generator/gapic/protoparser/HttpRuleParserTest.java +++ b/src/test/java/com/google/api/generator/gapic/protoparser/HttpRuleParserTest.java @@ -16,18 +16,16 @@ import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertThrows; +import com.google.api.generator.gapic.model.HttpRuleBindings; import com.google.api.generator.gapic.model.Message; import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.MethodDescriptor; import com.google.protobuf.Descriptors.ServiceDescriptor; import com.google.showcase.v1beta1.TestingOuterClass; -import java.util.List; import java.util.Map; -import java.util.Optional; import org.junit.Test; public class HttpRuleParserTest { @@ -42,16 +40,14 @@ public void parseHttpAnnotation_basic() { // CreateSession method. MethodDescriptor rpcMethod = testingService.getMethods().get(0); Message inputMessage = messages.get("com.google.showcase.v1beta1.CreateSessionRequest"); - Optional> httpBindingsOpt = - HttpRuleParser.parseHttpBindings(rpcMethod, inputMessage, messages); - assertFalse(httpBindingsOpt.isPresent()); + HttpRuleBindings httpBindings = HttpRuleParser.parse(rpcMethod, inputMessage, messages); + assertTrue(httpBindings.pathParameters().isEmpty()); // GetSession method. rpcMethod = testingService.getMethods().get(1); inputMessage = messages.get("com.google.showcase.v1beta1.GetSessionRequest"); - httpBindingsOpt = HttpRuleParser.parseHttpBindings(rpcMethod, inputMessage, messages); - assertTrue(httpBindingsOpt.isPresent()); - assertThat(httpBindingsOpt.get()).containsExactly("name"); + httpBindings = HttpRuleParser.parse(rpcMethod, inputMessage, messages); + assertThat(httpBindings.pathParameters()).containsExactly("name"); } @Test @@ -66,10 +62,8 @@ public void parseHttpAnnotation_multipleBindings() { MethodDescriptor rpcMethod = testingService.getMethods().get(testingService.getMethods().size() - 1); Message inputMessage = messages.get("com.google.showcase.v1beta1.VerifyTestRequest"); - Optional> httpBindingsOpt = - HttpRuleParser.parseHttpBindings(rpcMethod, inputMessage, messages); - assertTrue(httpBindingsOpt.isPresent()); - assertThat(httpBindingsOpt.get()) + HttpRuleBindings httpBindings = HttpRuleParser.parse(rpcMethod, inputMessage, messages); + assertThat(httpBindings.pathParameters()) .containsExactly("answer", "foo", "name", "test_to_verify.name", "type"); } @@ -86,7 +80,6 @@ public void parseHttpAnnotation_missingFieldFromMessage() { testingService.getMethods().get(testingService.getMethods().size() - 1); Message inputMessage = messages.get("com.google.showcase.v1beta1.CreateSessionRequest"); assertThrows( - IllegalStateException.class, - () -> HttpRuleParser.parseHttpBindings(rpcMethod, inputMessage, messages)); + IllegalStateException.class, () -> HttpRuleParser.parse(rpcMethod, inputMessage, messages)); } } diff --git a/src/test/java/com/google/api/generator/gapic/testdata/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/testdata/BUILD.bazel index 3be657ef66..ba75a8f62b 100644 --- a/src/test/java/com/google/api/generator/gapic/testdata/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/testdata/BUILD.bazel @@ -39,6 +39,7 @@ proto_library( "echo.proto", "identity.proto", "testing.proto", + "compliance.proto", ], deps = [ "@com_google_googleapis//google/api:annotations_proto", diff --git a/src/test/java/com/google/api/generator/gapic/testdata/compliance.proto b/src/test/java/com/google/api/generator/gapic/testdata/compliance.proto new file mode 100644 index 0000000000..43b320644c --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/testdata/compliance.proto @@ -0,0 +1,193 @@ +// 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. + +syntax = "proto3"; + +import "google/api/annotations.proto"; +import "google/api/client.proto"; + +package google.showcase.v1beta1; + +option go_package = "github.com/googleapis/gapic-showcase/server/genproto"; +option java_package = "com.google.showcase.v1beta1"; +option java_multiple_files = true; + +// This service is used to test that GAPICs can transcode proto3 requests to +// REST format correctly for various types of HTTP annotations. +service Compliance { + // This service is meant to only run locally on the port 7469 (keypad digits + // for "show"). + option (google.api.default_host) = "localhost:7469"; + + // This method echoes the ComplianceData request. This method exercises + // sending the entire request object in the REST body. + rpc RepeatDataBody(RepeatRequest) returns (RepeatResponse) { + option (google.api.http) = { + post: "/v1beta1/repeat:body" + body: "*" + }; + } + + // This method echoes the ComplianceData request. This method exercises + // sending the a message-type field in the REST body. Per AIP-127, only + // top-level, non-repeated fields can be sent this way. + rpc RepeatDataBodyInfo(RepeatRequest) returns (RepeatResponse) { + option (google.api.http) = { + post: "/v1beta1/repeat:bodyinfo" + body: "info" + }; + } + + // This method echoes the ComplianceData request. This method exercises + // sending all request fields as query parameters. + rpc RepeatDataQuery(RepeatRequest) returns (RepeatResponse) { + option (google.api.http) = { + get: "/v1beta1/repeat:query" + }; + } + + // This method echoes the ComplianceData request. This method exercises + // sending some parameters as "simple" path variables (i.e., of the form + // "/bar/{foo}" rather than "/{foo=bar/*}"), and the rest as query parameters. + rpc RepeatDataSimplePath(RepeatRequest) returns (RepeatResponse) { + option (google.api.http) = { + get: "/v1beta1/repeat/{info.f_string}/{info.f_int32}/{info.f_double}/{info.f_bool}/{info.f_kingdom}:simplepath" + }; + } + + // Same as RepeatDataSimplePath, but with a path resource. + rpc RepeatDataPathResource(RepeatRequest) returns (RepeatResponse) { + option (google.api.http) = { + get: "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/*}/bool/{info.f_bool}:pathresource" + }; + } + + // Same as RepeatDataSimplePath, but with a trailing resource. + rpc RepeatDataPathTrailingResource(RepeatRequest) returns (RepeatResponse) { + option (google.api.http) = { + get: "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/**}:pathtrailingresource" + }; + } +} + +message RepeatRequest { + string name = 1; + ComplianceData info = 2; + + // If true, the server will verify that the received request matches + // the request with the same name in the compliance test suite. + bool server_verify = 3; +} + +message RepeatResponse { + ComplianceData info = 1; +} + +// ComplianceSuite contains a set of requests that microgenerators should issue +// over REST to the Compliance service to test their gRPC-to-REST transcoding +// implementation. +message ComplianceSuite { + repeated ComplianceGroup group = 1; +} + +// ComplianceGroups encapsulates a group of RPC requests to the Compliance +// server: one request for each combination of elements of `rpcs` and of +// `requests`. +message ComplianceGroup { + string name = 1; + repeated string rpcs = 2; + repeated RepeatRequest requests = 3; +} + +// ComplianceData is a message used for testing REST transcoding of +// different data types. +message ComplianceData { + enum LifeKingdom { + LIFE_KINGDOM_UNSPECIFIED = 0; + ARCHAEBACTERIA = 1; + EUBACTERIA = 2; + PROTISTA = 3; + FUNGI = 4; + PLANTAE = 5; + ANIMALIA = 6; +} + // scalar types + + string f_string = 1; + + int32 f_int32 = 2; + sint32 f_sint32 = 3; + sfixed32 f_sfixed32 = 4; + + uint32 f_uint32 = 5; + fixed32 f_fixed32 = 6; + + int64 f_int64 = 7; + sint64 f_sint64 = 8; + sfixed64 f_sfixed64 = 9; + + uint64 f_uint64 = 10; + fixed64 f_fixed64 = 11; + + double f_double = 12; + float f_float = 13; + + bool f_bool = 14; + + bytes f_bytes = 15; + + LifeKingdom f_kingdom = 22; + + ComplianceDataChild f_child = 16; + + // optional fields + + optional string p_string = 17; + optional int32 p_int32 = 18; + optional double p_double = 19; + optional bool p_bool = 20; + optional LifeKingdom p_kingdom = 23; + optional ComplianceDataChild p_child = 21; +} + +message ComplianceDataChild { + string f_string = 1; + float f_float = 2; + double f_double = 3; + bool f_bool = 4; + Continent f_continent = 11; + ComplianceDataGrandchild f_child = 5; + + optional string p_string = 6; + optional float p_float = 7; + optional double p_double = 8; + optional bool p_bool = 9; + Continent p_continent = 12; + optional ComplianceDataGrandchild p_child = 10; +} + +message ComplianceDataGrandchild { + string f_string = 1; + double f_double = 2; + bool f_bool = 3; +} + +enum Continent { + CONTINENT_UNSPECIFIED = 0; + AFRICA = 1; + AMERICA = 2; + ANTARTICA = 3; + AUSTRALIA = 4; + EUROPE = 5; +} \ No newline at end of file diff --git a/test/integration/BUILD.bazel b/test/integration/BUILD.bazel index 23360e672b..f09da3c703 100644 --- a/test/integration/BUILD.bazel +++ b/test/integration/BUILD.bazel @@ -29,6 +29,7 @@ INTEGRATION_TEST_LIBRARIES = [ "logging", # Java package remapping in gapic.yaml. "redis", # Has a gapic.yaml. "library", # No gRPC service config. + "compute", # REGAPIC test. ] # Keys must match the values in INTEGRATION_TEST_LIBRARIES above. @@ -41,6 +42,7 @@ API_GAPIC_TARGETS = { "logging": "@com_google_googleapis//google/logging/v2:logging_java_gapic", "redis": "@com_google_googleapis//google/cloud/redis/v1beta1:redis_java_gapic", "library": "@com_google_googleapis//google/example/library/v1:library_java_gapic", + "compute": "@com_google_googleapis_discovery//google/cloud/compute/v1:compute_small2_java_gapic", } [integration_test( diff --git a/test/integration/goldens/compute/BUILD.bazel b/test/integration/goldens/compute/BUILD.bazel new file mode 100644 index 0000000000..667772f01b --- /dev/null +++ b/test/integration/goldens/compute/BUILD.bazel @@ -0,0 +1,9 @@ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "goldens_files", + srcs = glob([ + "*.java", + "gapic_metadata.json", + ]), +) 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 new file mode 100644 index 0000000000..43d73a4f6f --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClient.java @@ -0,0 +1,502 @@ +/* + * 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.cloud.compute.v1; + +import com.google.api.core.BetaApi; +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.cloud.compute.v1.stub.AddressesStub; +import com.google.cloud.compute.v1.stub.AddressesStubSettings; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Service Description: Services + * + *

The Addresses API. + * + *

This class provides the ability to make remote calls to the backing service through method + * calls that map to API methods. Sample code to get started: + * + *

{@code
+ * try (AddressesClient addressesClient = AddressesClient.create()) {
+ *   String project = "project-309310695";
+ *   AddressAggregatedList response = addressesClient.aggregatedList(project);
+ * }
+ * }
+ * + *

Note: close() needs to be called on the AddressesClient object to clean up resources such as + * threads. In the example above, try-with-resources is used, which automatically calls close(). + * + *

The surface of this class includes several types of Java methods for each of the API's + * methods: + * + *

    + *
  1. A "flattened" method. With this type of method, the fields of the request type have been + * converted into function parameters. It may be the case that not all fields are available as + * parameters, and not every API method will have a flattened method entry point. + *
  2. A "request object" method. This type of method only takes one parameter, a request object, + * which must be constructed before the call. Not every API method will have a request object + * method. + *
  3. A "callable" method. This type of method takes no parameters and returns an immutable API + * callable object, which can be used to initiate calls to the service. + *
+ * + *

See the individual methods for example code. + * + *

Many parameters require resource names to be formatted in a particular way. To assist with + * these names, this class includes a format method for each type of name, and additionally a parse + * method to extract the individual identifiers contained within names that are returned. + * + *

This class can be customized by passing in a custom instance of AddressesSettings to create(). + * For example: + * + *

To customize credentials: + * + *

{@code
+ * AddressesSettings addressesSettings =
+ *     AddressesSettings.newBuilder()
+ *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
+ *         .build();
+ * AddressesClient addressesClient = AddressesClient.create(addressesSettings);
+ * }
+ * + *

To customize the endpoint: + * + *

{@code
+ * AddressesSettings addressesSettings =
+ *     AddressesSettings.newBuilder().setEndpoint(myEndpoint).build();
+ * AddressesClient addressesClient = AddressesClient.create(addressesSettings);
+ * }
+ * + *

Please refer to the GitHub repository's samples for more quickstart code snippets. + */ +@Generated("by gapic-generator-java") +public class AddressesClient implements BackgroundResource { + private final AddressesSettings settings; + private final AddressesStub stub; + + /** Constructs an instance of AddressesClient with default settings. */ + public static final AddressesClient create() throws IOException { + return create(AddressesSettings.newBuilder().build()); + } + + /** + * Constructs an instance of AddressesClient, using the given settings. The channels are created + * based on the settings passed in, or defaults for any settings that are not set. + */ + public static final AddressesClient create(AddressesSettings settings) throws IOException { + return new AddressesClient(settings); + } + + /** + * Constructs an instance of AddressesClient, using the given stub for making calls. This is for + * advanced usage - prefer using create(AddressesSettings). + */ + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") + public static final AddressesClient create(AddressesStub stub) { + return new AddressesClient(stub); + } + + /** + * Constructs an instance of AddressesClient, 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. + */ + protected AddressesClient(AddressesSettings settings) throws IOException { + this.settings = settings; + this.stub = ((AddressesStubSettings) settings.getStubSettings()).createStub(); + } + + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") + protected AddressesClient(AddressesStub stub) { + this.settings = null; + this.stub = stub; + } + + public final AddressesSettings getSettings() { + return settings; + } + + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") + public AddressesStub getStub() { + return stub; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Retrieves an aggregated list of addresses. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   String project = "project-309310695";
+   *   AddressAggregatedList response = addressesClient.aggregatedList(project);
+   * }
+   * }
+ * + * @param project Project ID for this request. + * @throws com.google.api.gax.rpc.ApiException if the remote call fails + */ + public final AddressAggregatedList aggregatedList(String project) { + AggregatedListAddressesRequest request = + AggregatedListAddressesRequest.newBuilder().setProject(project).build(); + return aggregatedList(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Retrieves an aggregated list of addresses. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   AggregatedListAddressesRequest request =
+   *       AggregatedListAddressesRequest.newBuilder()
+   *           .setFilter("filter-1274492040")
+   *           .setIncludeAllScopes(true)
+   *           .setMaxResults(1128457243)
+   *           .setOrderBy("orderBy-1207110587")
+   *           .setPageToken("pageToken873572522")
+   *           .setProject("project-309310695")
+   *           .build();
+   *   AddressAggregatedList response = addressesClient.aggregatedList(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 AddressAggregatedList aggregatedList(AggregatedListAddressesRequest request) { + return aggregatedListCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Retrieves an aggregated list of addresses. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   AggregatedListAddressesRequest request =
+   *       AggregatedListAddressesRequest.newBuilder()
+   *           .setFilter("filter-1274492040")
+   *           .setIncludeAllScopes(true)
+   *           .setMaxResults(1128457243)
+   *           .setOrderBy("orderBy-1207110587")
+   *           .setPageToken("pageToken873572522")
+   *           .setProject("project-309310695")
+   *           .build();
+   *   ApiFuture future =
+   *       addressesClient.aggregatedListCallable().futureCall(request);
+   *   // Do something.
+   *   AddressAggregatedList response = future.get();
+   * }
+   * }
+ */ + public final UnaryCallable + aggregatedListCallable() { + return stub.aggregatedListCallable(); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Deletes the specified address resource. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   String project = "project-309310695";
+   *   String region = "region-934795532";
+   *   String address = "address-1147692044";
+   *   Operation response = addressesClient.delete(project, region, address);
+   * }
+   * }
+ * + * @param project Project ID for this request. + * @param region Name of the region for this request. + * @param address Name of the address resource to delete. + * @throws com.google.api.gax.rpc.ApiException if the remote call fails + */ + public final Operation delete(String project, String region, String address) { + DeleteAddressRequest request = + DeleteAddressRequest.newBuilder() + .setProject(project) + .setRegion(region) + .setAddress(address) + .build(); + return delete(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Deletes the specified address resource. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   DeleteAddressRequest request =
+   *       DeleteAddressRequest.newBuilder()
+   *           .setAddress("address-1147692044")
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .setRequestId("requestId693933066")
+   *           .build();
+   *   Operation response = addressesClient.delete(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 delete(DeleteAddressRequest request) { + return deleteCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Deletes the specified address resource. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   DeleteAddressRequest request =
+   *       DeleteAddressRequest.newBuilder()
+   *           .setAddress("address-1147692044")
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .setRequestId("requestId693933066")
+   *           .build();
+   *   ApiFuture future = addressesClient.deleteCallable().futureCall(request);
+   *   // Do something.
+   *   Operation response = future.get();
+   * }
+   * }
+ */ + public final UnaryCallable deleteCallable() { + return stub.deleteCallable(); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Creates an address resource in the specified project by using the data included in the request. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   String project = "project-309310695";
+   *   String region = "region-934795532";
+   *   Address addressResource = Address.newBuilder().build();
+   *   Operation response = addressesClient.insert(project, region, addressResource);
+   * }
+   * }
+ * + * @param project Project ID for this request. + * @param region Name of the region for this request. + * @param addressResource The body resource for this request + * @throws com.google.api.gax.rpc.ApiException if the remote call fails + */ + public final Operation insert(String project, String region, Address addressResource) { + InsertAddressRequest request = + InsertAddressRequest.newBuilder() + .setProject(project) + .setRegion(region) + .setAddressResource(addressResource) + .build(); + return insert(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Creates an address resource in the specified project by using the data included in the request. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   InsertAddressRequest request =
+   *       InsertAddressRequest.newBuilder()
+   *           .setAddressResource(Address.newBuilder().build())
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .setRequestId("requestId693933066")
+   *           .build();
+   *   Operation response = addressesClient.insert(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 insert(InsertAddressRequest request) { + return insertCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Creates an address resource in the specified project by using the data included in the request. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   InsertAddressRequest request =
+   *       InsertAddressRequest.newBuilder()
+   *           .setAddressResource(Address.newBuilder().build())
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .setRequestId("requestId693933066")
+   *           .build();
+   *   ApiFuture future = addressesClient.insertCallable().futureCall(request);
+   *   // Do something.
+   *   Operation response = future.get();
+   * }
+   * }
+ */ + public final UnaryCallable insertCallable() { + return stub.insertCallable(); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Retrieves a list of addresses contained within the specified region. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   String project = "project-309310695";
+   *   String region = "region-934795532";
+   *   String orderBy = "orderBy-1207110587";
+   *   AddressList response = addressesClient.list(project, region, orderBy);
+   * }
+   * }
+ * + * @param project Project ID for this request. + * @param region Name of the region for this request. + * @param orderBy Sorts list results by a certain order. By default, results are returned in + * alphanumerical order based on the resource name. + *

You can also sort results in descending order based on the creation timestamp using + * orderBy="creationTimestamp desc". This sorts results based on the creationTimestamp field + * in reverse chronological order (newest result first). Use this to sort resources like + * operations so that the newest operation is returned first. + *

Currently, only sorting by name or creationTimestamp desc is supported. + * @throws com.google.api.gax.rpc.ApiException if the remote call fails + */ + public final AddressList list(String project, String region, String orderBy) { + ListAddressesRequest request = + ListAddressesRequest.newBuilder() + .setProject(project) + .setRegion(region) + .setOrderBy(orderBy) + .build(); + return list(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Retrieves a list of addresses contained within the specified region. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   ListAddressesRequest request =
+   *       ListAddressesRequest.newBuilder()
+   *           .setFilter("filter-1274492040")
+   *           .setMaxResults(1128457243)
+   *           .setOrderBy("orderBy-1207110587")
+   *           .setPageToken("pageToken873572522")
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .build();
+   *   AddressList response = addressesClient.list(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 AddressList list(ListAddressesRequest request) { + return listCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Retrieves a list of addresses contained within the specified region. + * + *

Sample code: + * + *

{@code
+   * try (AddressesClient addressesClient = AddressesClient.create()) {
+   *   ListAddressesRequest request =
+   *       ListAddressesRequest.newBuilder()
+   *           .setFilter("filter-1274492040")
+   *           .setMaxResults(1128457243)
+   *           .setOrderBy("orderBy-1207110587")
+   *           .setPageToken("pageToken873572522")
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .build();
+   *   ApiFuture future = addressesClient.listCallable().futureCall(request);
+   *   // Do something.
+   *   AddressList response = future.get();
+   * }
+   * }
+ */ + public final UnaryCallable listCallable() { + return stub.listCallable(); + } + + @Override + public final void close() { + stub.close(); + } + + @Override + public void shutdown() { + stub.shutdown(); + } + + @Override + public boolean isShutdown() { + return stub.isShutdown(); + } + + @Override + public boolean isTerminated() { + return stub.isTerminated(); + } + + @Override + public void shutdownNow() { + stub.shutdownNow(); + } + + @Override + public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { + return stub.awaitTermination(duration, unit); + } +} diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClientTest.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClientTest.java new file mode 100644 index 0000000000..2890c9040c --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesClientTest.java @@ -0,0 +1,314 @@ +/* + * 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.cloud.compute.v1; + +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.httpjson.GaxHttpJsonProperties; +import com.google.api.gax.httpjson.testing.MockHttpService; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ApiException; +import com.google.api.gax.rpc.ApiExceptionFactory; +import com.google.api.gax.rpc.InvalidArgumentException; +import com.google.api.gax.rpc.StatusCode; +import com.google.api.gax.rpc.testing.FakeStatusCode; +import com.google.cloud.compute.v1.stub.HttpJsonAddressesStub; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import javax.annotation.Generated; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +@Generated("by gapic-generator-java1") +public class AddressesClientTest { + private static MockHttpService mockService; + private static AddressesClient client; + + @BeforeClass + public static void startStaticServer() throws IOException { + mockService = + new MockHttpService( + HttpJsonAddressesStub.getMethodDescriptors(), AddressesSettings.getDefaultEndpoint()); + AddressesSettings settings = + AddressesSettings.newBuilder() + .setTransportChannelProvider( + AddressesSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport(mockService) + .build()) + .setCredentialsProvider(NoCredentialsProvider.create()) + .build(); + client = AddressesClient.create(settings); + } + + @AfterClass + public static void stopServer() { + client.close(); + } + + @Before + public void setUp() {} + + @After + public void tearDown() throws Exception { + mockService.reset(); + } + + @Test + public void aggregatedListTest() throws Exception { + AddressAggregatedList expectedResponse = + AddressAggregatedList.newBuilder() + .setId("id3355") + .putAllItems(new HashMap()) + .setKind("kind3292052") + .setNextPageToken("nextPageToken-1386094857") + .setSelfLink("selfLink1191800166") + .setWarning(Warning.newBuilder().build()) + .build(); + mockService.addResponse(expectedResponse); + + String project = "project-309310695"; + + AddressAggregatedList actualResponse = client.aggregatedList(project); + 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 aggregatedListExceptionTest() throws Exception { + ApiException exception = + ApiExceptionFactory.createException( + new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); + mockService.addException(exception); + + try { + String project = "project-309310695"; + client.aggregatedList(project); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } + + @Test + public void deleteTest() 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("id3355") + .setInsertTime("insertTime966165798") + .setKind("kind3292052") + .setName("name3373707") + .setOperationType("operationType91999553") + .setProgress(-1001078227) + .setRegion("region-934795532") + .setSelfLink("selfLink1191800166") + .setStartTime("startTime-2129294769") + .setStatusMessage("statusMessage-958704715") + .setTargetId("targetId-441951604") + .setTargetLink("targetLink486368555") + .setUser("user3599307") + .addAllWarnings(new ArrayList()) + .setZone("zone3744684") + .build(); + mockService.addResponse(expectedResponse); + + String project = "project-309310695"; + String region = "region-934795532"; + String address = "address-1147692044"; + + Operation actualResponse = client.delete(project, region, address); + 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 deleteExceptionTest() 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 address = "address-1147692044"; + client.delete(project, region, address); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } + + @Test + public void insertTest() 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("id3355") + .setInsertTime("insertTime966165798") + .setKind("kind3292052") + .setName("name3373707") + .setOperationType("operationType91999553") + .setProgress(-1001078227) + .setRegion("region-934795532") + .setSelfLink("selfLink1191800166") + .setStartTime("startTime-2129294769") + .setStatusMessage("statusMessage-958704715") + .setTargetId("targetId-441951604") + .setTargetLink("targetLink486368555") + .setUser("user3599307") + .addAllWarnings(new ArrayList()) + .setZone("zone3744684") + .build(); + mockService.addResponse(expectedResponse); + + String project = "project-309310695"; + String region = "region-934795532"; + Address addressResource = Address.newBuilder().build(); + + Operation actualResponse = client.insert(project, region, addressResource); + 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 insertExceptionTest() 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"; + Address addressResource = Address.newBuilder().build(); + client.insert(project, region, addressResource); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } + + @Test + public void listTest() throws Exception { + AddressList expectedResponse = + AddressList.newBuilder() + .setId("id3355") + .addAllItems(new ArrayList
()) + .setKind("kind3292052") + .setNextPageToken("nextPageToken-1386094857") + .setSelfLink("selfLink1191800166") + .setWarning(Warning.newBuilder().build()) + .build(); + mockService.addResponse(expectedResponse); + + String project = "project-309310695"; + String region = "region-934795532"; + String orderBy = "orderBy-1207110587"; + + AddressList actualResponse = client.list(project, region, orderBy); + 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 listExceptionTest() 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 orderBy = "orderBy-1207110587"; + client.list(project, region, orderBy); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } +} diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesSettings.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesSettings.java new file mode 100644 index 0000000000..c19450b838 --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/AddressesSettings.java @@ -0,0 +1,214 @@ +/* + * 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.cloud.compute.v1; + +import com.google.api.core.ApiFunction; +import com.google.api.core.BetaApi; +import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.InstantiatingExecutorProvider; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.ClientSettings; +import com.google.api.gax.rpc.StubSettings; +import com.google.api.gax.rpc.TransportChannelProvider; +import com.google.api.gax.rpc.UnaryCallSettings; +import com.google.cloud.compute.v1.stub.AddressesStubSettings; +import java.io.IOException; +import java.util.List; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Settings class to configure an instance of {@link AddressesClient}. + * + *

The default instance has everything set to sensible defaults: + * + *

    + *
  • The default service address (compute.googleapis.com) and default port (443) are used. + *
  • Credentials are acquired automatically through Application Default Credentials. + *
  • Retries are configured for idempotent methods but not for non-idempotent methods. + *
+ * + *

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 aggregatedList to 30 seconds: + * + *

{@code
+ * AddressesSettings.Builder addressesSettingsBuilder = AddressesSettings.newBuilder();
+ * addressesSettingsBuilder
+ *     .aggregatedListSettings()
+ *     .setRetrySettings(
+ *         addressesSettingsBuilder
+ *             .aggregatedListSettings()
+ *             .getRetrySettings()
+ *             .toBuilder()
+ *             .setTotalTimeout(Duration.ofSeconds(30))
+ *             .build());
+ * AddressesSettings addressesSettings = addressesSettingsBuilder.build();
+ * }
+ */ +@Generated("by gapic-generator-java") +public class AddressesSettings extends ClientSettings { + + /** Returns the object with the settings used for calls to aggregatedList. */ + public UnaryCallSettings + aggregatedListSettings() { + return ((AddressesStubSettings) getStubSettings()).aggregatedListSettings(); + } + + /** Returns the object with the settings used for calls to delete. */ + public UnaryCallSettings deleteSettings() { + return ((AddressesStubSettings) getStubSettings()).deleteSettings(); + } + + /** Returns the object with the settings used for calls to insert. */ + public UnaryCallSettings insertSettings() { + return ((AddressesStubSettings) getStubSettings()).insertSettings(); + } + + /** Returns the object with the settings used for calls to list. */ + public UnaryCallSettings listSettings() { + return ((AddressesStubSettings) getStubSettings()).listSettings(); + } + + public static final AddressesSettings create(AddressesStubSettings stub) throws IOException { + return new AddressesSettings.Builder(stub.toBuilder()).build(); + } + + /** Returns a builder for the default ExecutorProvider for this service. */ + public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { + return AddressesStubSettings.defaultExecutorProviderBuilder(); + } + + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return AddressesStubSettings.getDefaultEndpoint(); + } + + /** Returns the default service scopes. */ + public static List getDefaultServiceScopes() { + return AddressesStubSettings.getDefaultServiceScopes(); + } + + /** Returns a builder for the default credentials for this service. */ + public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { + return AddressesStubSettings.defaultCredentialsProviderBuilder(); + } + + /** Returns a builder for the default ChannelProvider for this service. */ + public static InstantiatingHttpJsonChannelProvider.Builder + defaultHttpJsonTransportProviderBuilder() { + return AddressesStubSettings.defaultHttpJsonTransportProviderBuilder(); + } + + public static TransportChannelProvider defaultTransportChannelProvider() { + return AddressesStubSettings.defaultTransportChannelProvider(); + } + + @BetaApi("The surface for customizing headers is not stable yet and may change in the future.") + public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() { + return AddressesStubSettings.defaultApiClientHeaderProviderBuilder(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder() { + return Builder.createDefault(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder(ClientContext clientContext) { + return new Builder(clientContext); + } + + /** Returns a builder containing all the values of this settings class. */ + public Builder toBuilder() { + return new Builder(this); + } + + protected AddressesSettings(Builder settingsBuilder) throws IOException { + super(settingsBuilder); + } + + /** Builder for AddressesSettings. */ + public static class Builder extends ClientSettings.Builder { + + protected Builder() throws IOException { + this(((ClientContext) null)); + } + + protected Builder(ClientContext clientContext) { + super(AddressesStubSettings.newBuilder(clientContext)); + } + + protected Builder(AddressesSettings settings) { + super(settings.getStubSettings().toBuilder()); + } + + protected Builder(AddressesStubSettings.Builder stubSettings) { + super(stubSettings); + } + + private static Builder createDefault() { + return new Builder(AddressesStubSettings.newBuilder()); + } + + public AddressesStubSettings.Builder getStubSettingsBuilder() { + return ((AddressesStubSettings.Builder) getStubSettings()); + } + + // NEXT_MAJOR_VER: remove 'throws Exception'. + /** + * Applies the given settings updater function to all of the unary API methods in this service. + * + *

Note: This method does not support applying settings to streaming methods. + */ + public Builder applyToAllUnaryMethods( + ApiFunction, Void> settingsUpdater) throws Exception { + super.applyToAllUnaryMethods( + getStubSettingsBuilder().unaryMethodSettingsBuilders(), settingsUpdater); + return this; + } + + /** Returns the builder for the settings used for calls to aggregatedList. */ + public UnaryCallSettings.Builder + aggregatedListSettings() { + return getStubSettingsBuilder().aggregatedListSettings(); + } + + /** Returns the builder for the settings used for calls to delete. */ + public UnaryCallSettings.Builder deleteSettings() { + return getStubSettingsBuilder().deleteSettings(); + } + + /** Returns the builder for the settings used for calls to insert. */ + public UnaryCallSettings.Builder insertSettings() { + return getStubSettingsBuilder().insertSettings(); + } + + /** Returns the builder for the settings used for calls to list. */ + public UnaryCallSettings.Builder listSettings() { + return getStubSettingsBuilder().listSettings(); + } + + @Override + public AddressesSettings build() throws IOException { + return new AddressesSettings(this); + } + } +} 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 new file mode 100644 index 0000000000..a6d7347d88 --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClient.java @@ -0,0 +1,254 @@ +/* + * 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.cloud.compute.v1; + +import com.google.api.core.BetaApi; +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.cloud.compute.v1.stub.RegionOperationsStub; +import com.google.cloud.compute.v1.stub.RegionOperationsStubSettings; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Service Description: The RegionOperations API. + * + *

This class provides the ability to make remote calls to the backing service through method + * calls that map to API methods. Sample code to get started: + * + *

{@code
+ * try (RegionOperationsClient regionOperationsClient = RegionOperationsClient.create()) {
+ *   String project = "project-309310695";
+ *   String region = "region-934795532";
+ *   String operation = "operation1662702951";
+ *   Operation response = regionOperationsClient.get(project, region, operation);
+ * }
+ * }
+ * + *

Note: close() needs to be called on the RegionOperationsClient object to clean up resources + * such as threads. In the example above, try-with-resources is used, which automatically calls + * close(). + * + *

The surface of this class includes several types of Java methods for each of the API's + * methods: + * + *

    + *
  1. A "flattened" method. With this type of method, the fields of the request type have been + * converted into function parameters. It may be the case that not all fields are available as + * parameters, and not every API method will have a flattened method entry point. + *
  2. A "request object" method. This type of method only takes one parameter, a request object, + * which must be constructed before the call. Not every API method will have a request object + * method. + *
  3. A "callable" method. This type of method takes no parameters and returns an immutable API + * callable object, which can be used to initiate calls to the service. + *
+ * + *

See the individual methods for example code. + * + *

Many parameters require resource names to be formatted in a particular way. To assist with + * these names, this class includes a format method for each type of name, and additionally a parse + * method to extract the individual identifiers contained within names that are returned. + * + *

This class can be customized by passing in a custom instance of RegionOperationsSettings to + * create(). For example: + * + *

To customize credentials: + * + *

{@code
+ * RegionOperationsSettings regionOperationsSettings =
+ *     RegionOperationsSettings.newBuilder()
+ *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
+ *         .build();
+ * RegionOperationsClient regionOperationsClient =
+ *     RegionOperationsClient.create(regionOperationsSettings);
+ * }
+ * + *

To customize the endpoint: + * + *

{@code
+ * RegionOperationsSettings regionOperationsSettings =
+ *     RegionOperationsSettings.newBuilder().setEndpoint(myEndpoint).build();
+ * RegionOperationsClient regionOperationsClient =
+ *     RegionOperationsClient.create(regionOperationsSettings);
+ * }
+ * + *

Please refer to the GitHub repository's samples for more quickstart code snippets. + */ +@Generated("by gapic-generator-java") +public class RegionOperationsClient implements BackgroundResource { + private final RegionOperationsSettings settings; + private final RegionOperationsStub stub; + + /** Constructs an instance of RegionOperationsClient with default settings. */ + public static final RegionOperationsClient create() throws IOException { + return create(RegionOperationsSettings.newBuilder().build()); + } + + /** + * Constructs an instance of RegionOperationsClient, using the given settings. The channels are + * created based on the settings passed in, or defaults for any settings that are not set. + */ + public static final RegionOperationsClient create(RegionOperationsSettings settings) + throws IOException { + return new RegionOperationsClient(settings); + } + + /** + * Constructs an instance of RegionOperationsClient, using the given stub for making calls. This + * is for advanced usage - prefer using create(RegionOperationsSettings). + */ + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") + public static final RegionOperationsClient create(RegionOperationsStub stub) { + return new RegionOperationsClient(stub); + } + + /** + * Constructs an instance of RegionOperationsClient, 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. + */ + protected RegionOperationsClient(RegionOperationsSettings settings) throws IOException { + this.settings = settings; + this.stub = ((RegionOperationsStubSettings) settings.getStubSettings()).createStub(); + } + + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") + protected RegionOperationsClient(RegionOperationsStub stub) { + this.settings = null; + this.stub = stub; + } + + public final RegionOperationsSettings getSettings() { + return settings; + } + + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") + public RegionOperationsStub getStub() { + return stub; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Retrieves the specified region-specific Operations resource. + * + *

Sample code: + * + *

{@code
+   * try (RegionOperationsClient regionOperationsClient = RegionOperationsClient.create()) {
+   *   String project = "project-309310695";
+   *   String region = "region-934795532";
+   *   String operation = "operation1662702951";
+   *   Operation response = regionOperationsClient.get(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 get(String project, String region, String operation) { + GetRegionOperationRequest request = + GetRegionOperationRequest.newBuilder() + .setProject(project) + .setRegion(region) + .setOperation(operation) + .build(); + return get(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Retrieves the specified region-specific Operations resource. + * + *

Sample code: + * + *

{@code
+   * try (RegionOperationsClient regionOperationsClient = RegionOperationsClient.create()) {
+   *   GetRegionOperationRequest request =
+   *       GetRegionOperationRequest.newBuilder()
+   *           .setOperation("operation1662702951")
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .build();
+   *   Operation response = regionOperationsClient.get(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 get(GetRegionOperationRequest request) { + return getCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Retrieves the specified region-specific Operations resource. + * + *

Sample code: + * + *

{@code
+   * try (RegionOperationsClient regionOperationsClient = RegionOperationsClient.create()) {
+   *   GetRegionOperationRequest request =
+   *       GetRegionOperationRequest.newBuilder()
+   *           .setOperation("operation1662702951")
+   *           .setProject("project-309310695")
+   *           .setRegion("region-934795532")
+   *           .build();
+   *   ApiFuture future = regionOperationsClient.getCallable().futureCall(request);
+   *   // Do something.
+   *   Operation response = future.get();
+   * }
+   * }
+ */ + public final UnaryCallable getCallable() { + return stub.getCallable(); + } + + @Override + public final void close() { + stub.close(); + } + + @Override + public void shutdown() { + stub.shutdown(); + } + + @Override + public boolean isShutdown() { + return stub.isShutdown(); + } + + @Override + public boolean isTerminated() { + return stub.isTerminated(); + } + + @Override + public void shutdownNow() { + stub.shutdownNow(); + } + + @Override + public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { + return stub.awaitTermination(duration, unit); + } +} 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 new file mode 100644 index 0000000000..7f6b78232a --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsClientTest.java @@ -0,0 +1,143 @@ +/* + * 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.cloud.compute.v1; + +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.httpjson.GaxHttpJsonProperties; +import com.google.api.gax.httpjson.testing.MockHttpService; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ApiException; +import com.google.api.gax.rpc.ApiExceptionFactory; +import com.google.api.gax.rpc.InvalidArgumentException; +import com.google.api.gax.rpc.StatusCode; +import com.google.api.gax.rpc.testing.FakeStatusCode; +import com.google.cloud.compute.v1.stub.HttpJsonRegionOperationsStub; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Generated; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +@Generated("by gapic-generator-java") +public class RegionOperationsClientTest { + private static MockHttpService mockService; + private static RegionOperationsClient client; + + @BeforeClass + public static void startStaticServer() throws IOException { + mockService = + new MockHttpService( + HttpJsonRegionOperationsStub.getMethodDescriptors(), + RegionOperationsSettings.getDefaultEndpoint()); + RegionOperationsSettings settings = + RegionOperationsSettings.newBuilder() + .setTransportChannelProvider( + RegionOperationsSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport(mockService) + .build()) + .setCredentialsProvider(NoCredentialsProvider.create()) + .build(); + client = RegionOperationsClient.create(settings); + } + + @AfterClass + public static void stopServer() { + client.close(); + } + + @Before + public void setUp() {} + + @After + public void tearDown() throws Exception { + mockService.reset(); + } + + @Test + public void getTest() 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("id3355") + .setInsertTime("insertTime966165798") + .setKind("kind3292052") + .setName("name3373707") + .setOperationType("operationType91999553") + .setProgress(-1001078227) + .setRegion("region-934795532") + .setSelfLink("selfLink1191800166") + .setStartTime("startTime-2129294769") + .setStatusMessage("statusMessage-958704715") + .setTargetId("targetId-441951604") + .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.get(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 getExceptionTest() 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.get(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 new file mode 100644 index 0000000000..8b463e3e5c --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/RegionOperationsSettings.java @@ -0,0 +1,184 @@ +/* + * 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.cloud.compute.v1; + +import com.google.api.core.ApiFunction; +import com.google.api.core.BetaApi; +import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.InstantiatingExecutorProvider; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.ClientSettings; +import com.google.api.gax.rpc.StubSettings; +import com.google.api.gax.rpc.TransportChannelProvider; +import com.google.api.gax.rpc.UnaryCallSettings; +import com.google.cloud.compute.v1.stub.RegionOperationsStubSettings; +import java.io.IOException; +import java.util.List; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Settings class to configure an instance of {@link RegionOperationsClient}. + * + *

The default instance has everything set to sensible defaults: + * + *

    + *
  • The default service address (compute.googleapis.com) and default port (443) are used. + *
  • Credentials are acquired automatically through Application Default Credentials. + *
  • Retries are configured for idempotent methods but not for non-idempotent methods. + *
+ * + *

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 get to 30 seconds: + * + *

{@code
+ * RegionOperationsSettings.Builder regionOperationsSettingsBuilder =
+ *     RegionOperationsSettings.newBuilder();
+ * regionOperationsSettingsBuilder
+ *     .getSettings()
+ *     .setRetrySettings(
+ *         regionOperationsSettingsBuilder
+ *             .getSettings()
+ *             .getRetrySettings()
+ *             .toBuilder()
+ *             .setTotalTimeout(Duration.ofSeconds(30))
+ *             .build());
+ * RegionOperationsSettings regionOperationsSettings = regionOperationsSettingsBuilder.build();
+ * }
+ */ +@Generated("by gapic-generator-java") +public class RegionOperationsSettings extends ClientSettings { + + /** Returns the object with the settings used for calls to get. */ + public UnaryCallSettings getSettings() { + return ((RegionOperationsStubSettings) getStubSettings()).getSettings(); + } + + public static final RegionOperationsSettings create(RegionOperationsStubSettings stub) + throws IOException { + return new RegionOperationsSettings.Builder(stub.toBuilder()).build(); + } + + /** Returns a builder for the default ExecutorProvider for this service. */ + public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { + return RegionOperationsStubSettings.defaultExecutorProviderBuilder(); + } + + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return RegionOperationsStubSettings.getDefaultEndpoint(); + } + + /** Returns the default service scopes. */ + public static List getDefaultServiceScopes() { + return RegionOperationsStubSettings.getDefaultServiceScopes(); + } + + /** Returns a builder for the default credentials for this service. */ + public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { + return RegionOperationsStubSettings.defaultCredentialsProviderBuilder(); + } + + /** Returns a builder for the default ChannelProvider for this service. */ + public static InstantiatingHttpJsonChannelProvider.Builder + defaultHttpJsonTransportProviderBuilder() { + return RegionOperationsStubSettings.defaultHttpJsonTransportProviderBuilder(); + } + + public static TransportChannelProvider defaultTransportChannelProvider() { + return RegionOperationsStubSettings.defaultTransportChannelProvider(); + } + + @BetaApi("The surface for customizing headers is not stable yet and may change in the future.") + public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() { + return RegionOperationsStubSettings.defaultApiClientHeaderProviderBuilder(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder() { + return Builder.createDefault(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder(ClientContext clientContext) { + return new Builder(clientContext); + } + + /** Returns a builder containing all the values of this settings class. */ + public Builder toBuilder() { + return new Builder(this); + } + + protected RegionOperationsSettings(Builder settingsBuilder) throws IOException { + super(settingsBuilder); + } + + /** Builder for RegionOperationsSettings. */ + public static class Builder extends ClientSettings.Builder { + + protected Builder() throws IOException { + this(((ClientContext) null)); + } + + protected Builder(ClientContext clientContext) { + super(RegionOperationsStubSettings.newBuilder(clientContext)); + } + + protected Builder(RegionOperationsSettings settings) { + super(settings.getStubSettings().toBuilder()); + } + + protected Builder(RegionOperationsStubSettings.Builder stubSettings) { + super(stubSettings); + } + + private static Builder createDefault() { + return new Builder(RegionOperationsStubSettings.newBuilder()); + } + + public RegionOperationsStubSettings.Builder getStubSettingsBuilder() { + return ((RegionOperationsStubSettings.Builder) getStubSettings()); + } + + // NEXT_MAJOR_VER: remove 'throws Exception'. + /** + * Applies the given settings updater function to all of the unary API methods in this service. + * + *

Note: This method does not support applying settings to streaming methods. + */ + public Builder applyToAllUnaryMethods( + ApiFunction, Void> settingsUpdater) throws Exception { + super.applyToAllUnaryMethods( + getStubSettingsBuilder().unaryMethodSettingsBuilders(), settingsUpdater); + return this; + } + + /** Returns the builder for the settings used for calls to get. */ + public UnaryCallSettings.Builder getSettings() { + return getStubSettingsBuilder().getSettings(); + } + + @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 new file mode 100644 index 0000000000..3d8eb8ed66 --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/gapic_metadata.json @@ -0,0 +1,42 @@ +{ + "schema": "1.0", + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "java", + "protoPackage": "google.cloud.compute.v1", + "libraryPackage": "com.google.cloud.compute.v1", + "services": { + "Addresses": { + "clients": { + "grpc": { + "libraryClient": "AddressesClient", + "rpcs": { + "AggregatedList": { + "methods": ["aggregatedList", "aggregatedList", "aggregatedListCallable"] + }, + "Delete": { + "methods": ["delete", "delete", "deleteCallable"] + }, + "Insert": { + "methods": ["insert", "insert", "insertCallable"] + }, + "List": { + "methods": ["list", "list", "listCallable"] + } + } + } + } + }, + "RegionOperations": { + "clients": { + "grpc": { + "libraryClient": "RegionOperationsClient", + "rpcs": { + "Get": { + "methods": ["get", "get", "getCallable"] + } + } + } + } + } + } +} \ No newline at end of file diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/package-info.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/package-info.java new file mode 100644 index 0000000000..fbc46c7bdc --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/package-info.java @@ -0,0 +1,53 @@ +/* + * 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. + */ + +/** + * The interfaces provided are listed below, along with usage samples. + * + *

======================= AddressesClient ======================= + * + *

Service Description: Services + * + *

The Addresses API. + * + *

Sample for AddressesClient: + * + *

{@code
+ * try (AddressesClient addressesClient = AddressesClient.create()) {
+ *   String project = "project-309310695";
+ *   AddressAggregatedList response = addressesClient.aggregatedList(project);
+ * }
+ * }
+ * + *

======================= RegionOperationsClient ======================= + * + *

Service Description: The RegionOperations API. + * + *

Sample for RegionOperationsClient: + * + *

{@code
+ * try (RegionOperationsClient regionOperationsClient = RegionOperationsClient.create()) {
+ *   String project = "project-309310695";
+ *   String region = "region-934795532";
+ *   String operation = "operation1662702951";
+ *   Operation response = regionOperationsClient.get(project, region, operation);
+ * }
+ * }
+ */ +@Generated("by gapic-generator-java") +package com.google.cloud.compute.v1; + +import javax.annotation.Generated; 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 new file mode 100644 index 0000000000..d192131a5b --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStub.java @@ -0,0 +1,58 @@ +/* + * 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.cloud.compute.v1.stub; + +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.cloud.compute.v1.AddressAggregatedList; +import com.google.cloud.compute.v1.AddressList; +import com.google.cloud.compute.v1.AggregatedListAddressesRequest; +import com.google.cloud.compute.v1.DeleteAddressRequest; +import com.google.cloud.compute.v1.InsertAddressRequest; +import com.google.cloud.compute.v1.ListAddressesRequest; +import com.google.cloud.compute.v1.Operation; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Base stub class for the Addresses service API. + * + *

This class is for advanced usage and reflects the underlying API directly. + */ +@Generated("by gapic-generator-java") +public abstract class AddressesStub implements BackgroundResource { + + public UnaryCallable + aggregatedListCallable() { + throw new UnsupportedOperationException("Not implemented: aggregatedListCallable()"); + } + + public UnaryCallable deleteCallable() { + throw new UnsupportedOperationException("Not implemented: deleteCallable()"); + } + + public UnaryCallable insertCallable() { + throw new UnsupportedOperationException("Not implemented: insertCallable()"); + } + + public UnaryCallable listCallable() { + throw new UnsupportedOperationException("Not implemented: listCallable()"); + } + + @Override + public abstract void close(); +} 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 new file mode 100644 index 0000000000..bfb14459ca --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/AddressesStubSettings.java @@ -0,0 +1,327 @@ +/* + * 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.cloud.compute.v1.stub; + +import com.google.api.core.ApiFunction; +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.httpjson.GaxHttpJsonProperties; +import com.google.api.gax.httpjson.HttpJsonTransportChannel; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.retrying.RetrySettings; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.StatusCode; +import com.google.api.gax.rpc.StubSettings; +import com.google.api.gax.rpc.TransportChannelProvider; +import com.google.api.gax.rpc.UnaryCallSettings; +import com.google.cloud.compute.v1.AddressAggregatedList; +import com.google.cloud.compute.v1.AddressList; +import com.google.cloud.compute.v1.AggregatedListAddressesRequest; +import com.google.cloud.compute.v1.DeleteAddressRequest; +import com.google.cloud.compute.v1.InsertAddressRequest; +import com.google.cloud.compute.v1.ListAddressesRequest; +import com.google.cloud.compute.v1.Operation; +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 java.io.IOException; +import java.util.List; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Settings class to configure an instance of {@link AddressesStub}. + * + *

The default instance has everything set to sensible defaults: + * + *

    + *
  • The default service address (compute.googleapis.com) and default port (443) are used. + *
  • Credentials are acquired automatically through Application Default Credentials. + *
  • Retries are configured for idempotent methods but not for non-idempotent methods. + *
+ * + *

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 aggregatedList to 30 seconds: + * + *

{@code
+ * AddressesStubSettings.Builder addressesSettingsBuilder = AddressesStubSettings.newBuilder();
+ * addressesSettingsBuilder
+ *     .aggregatedListSettings()
+ *     .setRetrySettings(
+ *         addressesSettingsBuilder
+ *             .aggregatedListSettings()
+ *             .getRetrySettings()
+ *             .toBuilder()
+ *             .setTotalTimeout(Duration.ofSeconds(30))
+ *             .build());
+ * AddressesStubSettings addressesSettings = addressesSettingsBuilder.build();
+ * }
+ */ +@Generated("by gapic-generator-java") +public class AddressesStubSettings extends StubSettings { + /** The default scopes of the service. */ + private static final ImmutableList DEFAULT_SERVICE_SCOPES = + ImmutableList.builder() + .add("https://www.googleapis.com/auth/compute") + .add("https://www.googleapis.com/auth/cloud-platform") + .build(); + + private final UnaryCallSettings + aggregatedListSettings; + private final UnaryCallSettings deleteSettings; + private final UnaryCallSettings insertSettings; + private final UnaryCallSettings listSettings; + + /** Returns the object with the settings used for calls to aggregatedList. */ + public UnaryCallSettings + aggregatedListSettings() { + return aggregatedListSettings; + } + + /** Returns the object with the settings used for calls to delete. */ + public UnaryCallSettings deleteSettings() { + return deleteSettings; + } + + /** Returns the object with the settings used for calls to insert. */ + public UnaryCallSettings insertSettings() { + return insertSettings; + } + + /** Returns the object with the settings used for calls to list. */ + public UnaryCallSettings listSettings() { + return listSettings; + } + + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") + public AddressesStub createStub() throws IOException { + if (getTransportChannelProvider() + .getTransportName() + .equals(HttpJsonTransportChannel.getHttpJsonTransportName())) { + return HttpJsonAddressesStub.create(this); + } + throw new UnsupportedOperationException( + String.format( + "Transport not supported: %s", getTransportChannelProvider().getTransportName())); + } + + /** Returns a builder for the default ExecutorProvider for this service. */ + public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { + return InstantiatingExecutorProvider.newBuilder(); + } + + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "compute.googleapis.com:443"; + } + + /** Returns the default service scopes. */ + public static List getDefaultServiceScopes() { + return DEFAULT_SERVICE_SCOPES; + } + + /** Returns a builder for the default credentials for this service. */ + public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { + return GoogleCredentialsProvider.newBuilder().setScopesToApply(DEFAULT_SERVICE_SCOPES); + } + + /** Returns a builder for the default ChannelProvider for this service. */ + public static InstantiatingHttpJsonChannelProvider.Builder + defaultHttpJsonTransportProviderBuilder() { + return InstantiatingHttpJsonChannelProvider.newBuilder(); + } + + public static TransportChannelProvider defaultTransportChannelProvider() { + return defaultHttpJsonTransportProviderBuilder().build(); + } + + @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(AddressesStubSettings.class)) + .setTransportToken( + GaxHttpJsonProperties.getHttpJsonTokenName(), + GaxHttpJsonProperties.getHttpJsonVersion()); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder() { + return Builder.createDefault(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder(ClientContext clientContext) { + return new Builder(clientContext); + } + + /** Returns a builder containing all the values of this settings class. */ + public Builder toBuilder() { + return new Builder(this); + } + + protected AddressesStubSettings(Builder settingsBuilder) throws IOException { + super(settingsBuilder); + + aggregatedListSettings = settingsBuilder.aggregatedListSettings().build(); + deleteSettings = settingsBuilder.deleteSettings().build(); + insertSettings = settingsBuilder.insertSettings().build(); + listSettings = settingsBuilder.listSettings().build(); + } + + /** Builder for AddressesStubSettings. */ + public static class Builder extends StubSettings.Builder { + private final ImmutableList> unaryMethodSettingsBuilders; + private final UnaryCallSettings.Builder + aggregatedListSettings; + private final UnaryCallSettings.Builder deleteSettings; + private final UnaryCallSettings.Builder insertSettings; + private final UnaryCallSettings.Builder listSettings; + private static final ImmutableMap> + RETRYABLE_CODE_DEFINITIONS; + + static { + ImmutableMap.Builder> definitions = + ImmutableMap.builder(); + definitions.put("no_retry_codes", ImmutableSet.copyOf(Lists.newArrayList())); + RETRYABLE_CODE_DEFINITIONS = definitions.build(); + } + + private static final ImmutableMap RETRY_PARAM_DEFINITIONS; + + static { + ImmutableMap.Builder definitions = ImmutableMap.builder(); + RetrySettings settings = null; + settings = RetrySettings.newBuilder().setRpcTimeoutMultiplier(1.0).build(); + definitions.put("no_retry_params", settings); + RETRY_PARAM_DEFINITIONS = definitions.build(); + } + + protected Builder() { + this(((ClientContext) null)); + } + + protected Builder(ClientContext clientContext) { + super(clientContext); + + aggregatedListSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + deleteSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + insertSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + listSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + + unaryMethodSettingsBuilders = + ImmutableList.>of( + aggregatedListSettings, deleteSettings, insertSettings, listSettings); + initDefaults(this); + } + + protected Builder(AddressesStubSettings settings) { + super(settings); + + aggregatedListSettings = settings.aggregatedListSettings.toBuilder(); + deleteSettings = settings.deleteSettings.toBuilder(); + insertSettings = settings.insertSettings.toBuilder(); + listSettings = settings.listSettings.toBuilder(); + + unaryMethodSettingsBuilders = + ImmutableList.>of( + aggregatedListSettings, deleteSettings, insertSettings, listSettings); + } + + private static Builder createDefault() { + Builder builder = new Builder(((ClientContext) null)); + + builder.setTransportChannelProvider(defaultTransportChannelProvider()); + builder.setCredentialsProvider(defaultCredentialsProviderBuilder().build()); + builder.setInternalHeaderProvider(defaultApiClientHeaderProviderBuilder().build()); + builder.setEndpoint(getDefaultEndpoint()); + + return initDefaults(builder); + } + + private static Builder initDefaults(Builder builder) { + builder + .aggregatedListSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); + + builder + .deleteSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); + + builder + .insertSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); + + builder + .listSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); + + return builder; + } + + // NEXT_MAJOR_VER: remove 'throws Exception'. + /** + * Applies the given settings updater function to all of the unary API methods in this service. + * + *

Note: This method does not support applying settings to streaming methods. + */ + public Builder applyToAllUnaryMethods( + ApiFunction, Void> settingsUpdater) throws Exception { + super.applyToAllUnaryMethods(unaryMethodSettingsBuilders, settingsUpdater); + return this; + } + + public ImmutableList> unaryMethodSettingsBuilders() { + return unaryMethodSettingsBuilders; + } + + /** Returns the builder for the settings used for calls to aggregatedList. */ + public UnaryCallSettings.Builder + aggregatedListSettings() { + return aggregatedListSettings; + } + + /** Returns the builder for the settings used for calls to delete. */ + public UnaryCallSettings.Builder deleteSettings() { + return deleteSettings; + } + + /** Returns the builder for the settings used for calls to insert. */ + public UnaryCallSettings.Builder insertSettings() { + return insertSettings; + } + + /** Returns the builder for the settings used for calls to list. */ + public UnaryCallSettings.Builder listSettings() { + return listSettings; + } + + @Override + public AddressesStubSettings build() throws IOException { + return new AddressesStubSettings(this); + } + } +} diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesCallableFactory.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesCallableFactory.java new file mode 100644 index 0000000000..98f81444ec --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesCallableFactory.java @@ -0,0 +1,80 @@ +/* + * 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.cloud.compute.v1.stub; + +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.httpjson.ApiMessage; +import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonCallableFactory; +import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; +import com.google.api.gax.rpc.BatchingCallSettings; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.OperationCallSettings; +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 javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * REST callable factory implementation for the Addresses service API. + * + *

This class is for advanced usage. + */ +@Generated("by gapic-generator-java") +public class HttpJsonAddressesCallableFactory + implements HttpJsonStubCallableFactory { + + @Override + public UnaryCallable createUnaryCallable( + HttpJsonCallSettings httpJsonCallSettings, + UnaryCallSettings callSettings, + ClientContext clientContext) { + return HttpJsonCallableFactory.createUnaryCallable( + httpJsonCallSettings, callSettings, clientContext); + } + + @Override + public + UnaryCallable createPagedCallable( + HttpJsonCallSettings httpJsonCallSettings, + PagedCallSettings callSettings, + ClientContext clientContext) { + return HttpJsonCallableFactory.createPagedCallable( + httpJsonCallSettings, callSettings, clientContext); + } + + @Override + public UnaryCallable createBatchingCallable( + HttpJsonCallSettings httpJsonCallSettings, + BatchingCallSettings callSettings, + ClientContext clientContext) { + return HttpJsonCallableFactory.createBatchingCallable( + httpJsonCallSettings, callSettings, clientContext); + } + + @Override + public + OperationCallable createOperationCallable( + HttpJsonCallSettings httpJsonCallSettings, + OperationCallSettings callSettings, + ClientContext clientContext, + BackgroundResource operationsStub) { + return null; + } +} 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 new file mode 100644 index 0000000000..513ca00747 --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java @@ -0,0 +1,389 @@ +/* + * 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.cloud.compute.v1.stub; + +import com.google.api.client.http.HttpMethods; +import com.google.api.core.BetaApi; +import com.google.api.core.InternalApi; +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.core.BackgroundResourceAggregation; +import com.google.api.gax.httpjson.ApiMethodDescriptor; +import com.google.api.gax.httpjson.FieldsExtractor; +import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; +import com.google.api.gax.httpjson.ProtoMessageRequestFormatter; +import com.google.api.gax.httpjson.ProtoMessageResponseParser; +import com.google.api.gax.httpjson.ProtoRestSerializer; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.cloud.compute.v1.AddressAggregatedList; +import com.google.cloud.compute.v1.AddressList; +import com.google.cloud.compute.v1.AggregatedListAddressesRequest; +import com.google.cloud.compute.v1.DeleteAddressRequest; +import com.google.cloud.compute.v1.InsertAddressRequest; +import com.google.cloud.compute.v1.ListAddressesRequest; +import com.google.cloud.compute.v1.Operation; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * REST stub implementation for the Addresses service API. + * + *

This class is for advanced usage and reflects the underlying API directly. + */ +@Generated("by gapic-generator-java") +@BetaApi("A restructuring of stub classes is planned, so this may break in the future") +public class HttpJsonAddressesStub extends AddressesStub { + private static final ApiMethodDescriptor + aggregatedListMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.cloud.compute.v1.Addresses/AggregatedList") + .setHttpMethod(HttpMethods.GET) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/compute/v1/projects/{project}/aggregated/addresses", + new FieldsExtractor< + AggregatedListAddressesRequest, Map>() { + @Override + public Map extract( + AggregatedListAddressesRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam(fields, "project", request.getProject()); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor< + AggregatedListAddressesRequest, Map>>() { + @Override + public Map> extract( + AggregatedListAddressesRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "filter", request.getFilter()); + serializer.putQueryParam( + fields, "includeAllScopes", request.getIncludeAllScopes()); + serializer.putQueryParam( + fields, "maxResults", request.getMaxResults()); + serializer.putQueryParam(fields, "orderBy", request.getOrderBy()); + serializer.putQueryParam(fields, "pageToken", request.getPageToken()); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(AggregatedListAddressesRequest request) { + return null; + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(AddressAggregatedList.getDefaultInstance()) + .build()) + .build(); + + private static final ApiMethodDescriptor deleteMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.cloud.compute.v1.Addresses/Delete") + .setHttpMethod(HttpMethods.DELETE) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/compute/v1/projects/{project}/regions/{region}/addresses/{address}", + new FieldsExtractor>() { + @Override + public Map extract(DeleteAddressRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam(fields, "address", request.getAddress()); + serializer.putPathParam(fields, "project", request.getProject()); + serializer.putPathParam(fields, "region", request.getRegion()); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor>>() { + @Override + public Map> extract(DeleteAddressRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "requestId", request.getRequestId()); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(DeleteAddressRequest request) { + return null; + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(Operation.getDefaultInstance()) + .build()) + .build(); + + private static final ApiMethodDescriptor insertMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.cloud.compute.v1.Addresses/Insert") + .setHttpMethod(HttpMethods.POST) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/compute/v1/projects/{project}/regions/{region}/addresses", + new FieldsExtractor>() { + @Override + public Map extract(InsertAddressRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam(fields, "project", request.getProject()); + serializer.putPathParam(fields, "region", request.getRegion()); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor>>() { + @Override + public Map> extract(InsertAddressRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "requestId", request.getRequestId()); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(InsertAddressRequest request) { + return ProtoRestSerializer.create() + .toBody("addressResource", request.getAddressResource()); + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(Operation.getDefaultInstance()) + .build()) + .build(); + + private static final ApiMethodDescriptor listMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.cloud.compute.v1.Addresses/List") + .setHttpMethod(HttpMethods.GET) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/compute/v1/projects/{project}/regions/{region}/addresses", + new FieldsExtractor>() { + @Override + public Map extract(ListAddressesRequest request) { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam(fields, "project", request.getProject()); + serializer.putPathParam(fields, "region", request.getRegion()); + return fields; + } + }) + .setQueryParamsExtractor( + new FieldsExtractor>>() { + @Override + public Map> extract(ListAddressesRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "filter", request.getFilter()); + serializer.putQueryParam(fields, "maxResults", request.getMaxResults()); + serializer.putQueryParam(fields, "orderBy", request.getOrderBy()); + serializer.putQueryParam(fields, "pageToken", request.getPageToken()); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(ListAddressesRequest request) { + return null; + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(AddressList.getDefaultInstance()) + .build()) + .build(); + + private final UnaryCallable + aggregatedListCallable; + private final UnaryCallable deleteCallable; + private final UnaryCallable insertCallable; + private final UnaryCallable listCallable; + + private final BackgroundResource backgroundResources; + private final HttpJsonStubCallableFactory callableFactory; + + public static final HttpJsonAddressesStub create(AddressesStubSettings settings) + throws IOException { + return new HttpJsonAddressesStub(settings, ClientContext.create(settings)); + } + + public static final HttpJsonAddressesStub create(ClientContext clientContext) throws IOException { + return new HttpJsonAddressesStub(AddressesStubSettings.newBuilder().build(), clientContext); + } + + public static final HttpJsonAddressesStub create( + ClientContext clientContext, HttpJsonStubCallableFactory callableFactory) throws IOException { + return new HttpJsonAddressesStub( + AddressesStubSettings.newBuilder().build(), clientContext, callableFactory); + } + + /** + * Constructs an instance of HttpJsonAddressesStub, 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. + */ + protected HttpJsonAddressesStub(AddressesStubSettings settings, ClientContext clientContext) + throws IOException { + this(settings, clientContext, new HttpJsonAddressesCallableFactory()); + } + + /** + * Constructs an instance of HttpJsonAddressesStub, 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. + */ + protected HttpJsonAddressesStub( + AddressesStubSettings settings, + ClientContext clientContext, + HttpJsonStubCallableFactory callableFactory) + throws IOException { + this.callableFactory = callableFactory; + + HttpJsonCallSettings + aggregatedListTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(aggregatedListMethodDescriptor) + .build(); + HttpJsonCallSettings deleteTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(deleteMethodDescriptor) + .build(); + HttpJsonCallSettings insertTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(insertMethodDescriptor) + .build(); + HttpJsonCallSettings listTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(listMethodDescriptor) + .build(); + + this.aggregatedListCallable = + callableFactory.createUnaryCallable( + aggregatedListTransportSettings, settings.aggregatedListSettings(), clientContext); + this.deleteCallable = + callableFactory.createUnaryCallable( + deleteTransportSettings, settings.deleteSettings(), clientContext); + this.insertCallable = + callableFactory.createUnaryCallable( + insertTransportSettings, settings.insertSettings(), clientContext); + this.listCallable = + callableFactory.createUnaryCallable( + listTransportSettings, settings.listSettings(), clientContext); + + this.backgroundResources = + new BackgroundResourceAggregation(clientContext.getBackgroundResources()); + } + + @InternalApi + public static List getMethodDescriptors() { + List methodDescriptors = new ArrayList<>(); + methodDescriptors.add(deleteMethodDescriptor); + methodDescriptors.add(listMethodDescriptor); + methodDescriptors.add(insertMethodDescriptor); + methodDescriptors.add(aggregatedListMethodDescriptor); + return methodDescriptors; + } + + @Override + public UnaryCallable + aggregatedListCallable() { + return aggregatedListCallable; + } + + @Override + public UnaryCallable deleteCallable() { + return deleteCallable; + } + + @Override + public UnaryCallable insertCallable() { + return insertCallable; + } + + @Override + public UnaryCallable listCallable() { + return listCallable; + } + + @Override + public final void close() { + shutdown(); + } + + @Override + public void shutdown() { + backgroundResources.shutdown(); + } + + @Override + public boolean isShutdown() { + return backgroundResources.isShutdown(); + } + + @Override + public boolean isTerminated() { + return backgroundResources.isTerminated(); + } + + @Override + public void shutdownNow() { + backgroundResources.shutdownNow(); + } + + @Override + public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { + return backgroundResources.awaitTermination(duration, unit); + } +} 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 new file mode 100644 index 0000000000..2694d1aa62 --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java @@ -0,0 +1,80 @@ +/* + * 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.cloud.compute.v1.stub; + +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.httpjson.ApiMessage; +import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonCallableFactory; +import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; +import com.google.api.gax.rpc.BatchingCallSettings; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.OperationCallSettings; +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 javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * REST callable factory implementation for the RegionOperations service API. + * + *

This class is for advanced usage. + */ +@Generated("by gapic-generator-java") +public class HttpJsonRegionOperationsCallableFactory + implements HttpJsonStubCallableFactory { + + @Override + public UnaryCallable createUnaryCallable( + HttpJsonCallSettings httpJsonCallSettings, + UnaryCallSettings callSettings, + ClientContext clientContext) { + return HttpJsonCallableFactory.createUnaryCallable( + httpJsonCallSettings, callSettings, clientContext); + } + + @Override + public + UnaryCallable createPagedCallable( + HttpJsonCallSettings httpJsonCallSettings, + PagedCallSettings callSettings, + ClientContext clientContext) { + return HttpJsonCallableFactory.createPagedCallable( + httpJsonCallSettings, callSettings, clientContext); + } + + @Override + public UnaryCallable createBatchingCallable( + HttpJsonCallSettings httpJsonCallSettings, + BatchingCallSettings callSettings, + ClientContext clientContext) { + return HttpJsonCallableFactory.createBatchingCallable( + httpJsonCallSettings, callSettings, clientContext); + } + + @Override + public + OperationCallable createOperationCallable( + HttpJsonCallSettings httpJsonCallSettings, + OperationCallSettings callSettings, + ClientContext clientContext, + BackgroundResource operationsStub) { + 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 new file mode 100644 index 0000000000..0be8cf4d03 --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java @@ -0,0 +1,197 @@ +/* + * 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.cloud.compute.v1.stub; + +import com.google.api.client.http.HttpMethods; +import com.google.api.core.BetaApi; +import com.google.api.core.InternalApi; +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.core.BackgroundResourceAggregation; +import com.google.api.gax.httpjson.ApiMethodDescriptor; +import com.google.api.gax.httpjson.FieldsExtractor; +import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; +import com.google.api.gax.httpjson.ProtoMessageRequestFormatter; +import com.google.api.gax.httpjson.ProtoMessageResponseParser; +import com.google.api.gax.httpjson.ProtoRestSerializer; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.cloud.compute.v1.GetRegionOperationRequest; +import com.google.cloud.compute.v1.Operation; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * REST stub implementation for the RegionOperations service API. + * + *

This class is for advanced usage and reflects the underlying API directly. + */ +@Generated("by gapic-generator-java") +@BetaApi("A restructuring of stub classes is planned, so this may break in the future") +public class HttpJsonRegionOperationsStub extends RegionOperationsStub { + private static final ApiMethodDescriptor + getMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.cloud.compute.v1.RegionOperations/Get") + .setHttpMethod(HttpMethods.GET) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/compute/v1/projects/{project}/regions/{region}/operations/{operation}", + new FieldsExtractor>() { + @Override + public Map extract(GetRegionOperationRequest 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( + new FieldsExtractor< + GetRegionOperationRequest, Map>>() { + @Override + public Map> extract( + GetRegionOperationRequest request) { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + } + }) + .setRequestBodyExtractor( + new FieldsExtractor() { + @Override + public String extract(GetRegionOperationRequest request) { + return null; + } + }) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(Operation.getDefaultInstance()) + .build()) + .build(); + + private final UnaryCallable getCallable; + + private final BackgroundResource backgroundResources; + private final HttpJsonStubCallableFactory callableFactory; + + public static final HttpJsonRegionOperationsStub create(RegionOperationsStubSettings settings) + throws IOException { + return new HttpJsonRegionOperationsStub(settings, ClientContext.create(settings)); + } + + public static final HttpJsonRegionOperationsStub create(ClientContext clientContext) + throws IOException { + return new HttpJsonRegionOperationsStub( + RegionOperationsStubSettings.newBuilder().build(), clientContext); + } + + public static final HttpJsonRegionOperationsStub create( + ClientContext clientContext, HttpJsonStubCallableFactory callableFactory) throws IOException { + return new HttpJsonRegionOperationsStub( + RegionOperationsStubSettings.newBuilder().build(), clientContext, callableFactory); + } + + /** + * Constructs an instance of HttpJsonRegionOperationsStub, 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. + */ + protected HttpJsonRegionOperationsStub( + RegionOperationsStubSettings settings, ClientContext clientContext) throws IOException { + this(settings, clientContext, new HttpJsonRegionOperationsCallableFactory()); + } + + /** + * Constructs an instance of HttpJsonRegionOperationsStub, 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. + */ + protected HttpJsonRegionOperationsStub( + RegionOperationsStubSettings settings, + ClientContext clientContext, + HttpJsonStubCallableFactory callableFactory) + throws IOException { + this.callableFactory = callableFactory; + + HttpJsonCallSettings getTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(getMethodDescriptor) + .build(); + + this.getCallable = + callableFactory.createUnaryCallable( + getTransportSettings, settings.getSettings(), clientContext); + + this.backgroundResources = + new BackgroundResourceAggregation(clientContext.getBackgroundResources()); + } + + @InternalApi + public static List getMethodDescriptors() { + List methodDescriptors = new ArrayList<>(); + methodDescriptors.add(getMethodDescriptor); + return methodDescriptors; + } + + @Override + public UnaryCallable getCallable() { + return getCallable; + } + + @Override + public final void close() { + shutdown(); + } + + @Override + public void shutdown() { + backgroundResources.shutdown(); + } + + @Override + public boolean isShutdown() { + return backgroundResources.isShutdown(); + } + + @Override + public boolean isTerminated() { + return backgroundResources.isTerminated(); + } + + @Override + public void shutdownNow() { + backgroundResources.shutdownNow(); + } + + @Override + public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { + return backgroundResources.awaitTermination(duration, unit); + } +} 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 new file mode 100644 index 0000000000..c3019038cb --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStub.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 + * + * 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.cloud.compute.v1.stub; + +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.cloud.compute.v1.GetRegionOperationRequest; +import com.google.cloud.compute.v1.Operation; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Base stub class for the RegionOperations service API. + * + *

This class is for advanced usage and reflects the underlying API directly. + */ +@Generated("by gapic-generator-java") +public abstract class RegionOperationsStub implements BackgroundResource { + + public UnaryCallable getCallable() { + throw new UnsupportedOperationException("Not implemented: getCallable()"); + } + + @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 new file mode 100644 index 0000000000..0d94d74c0a --- /dev/null +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/RegionOperationsStubSettings.java @@ -0,0 +1,257 @@ +/* + * 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.cloud.compute.v1.stub; + +import com.google.api.core.ApiFunction; +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.httpjson.GaxHttpJsonProperties; +import com.google.api.gax.httpjson.HttpJsonTransportChannel; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.retrying.RetrySettings; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.StatusCode; +import com.google.api.gax.rpc.StubSettings; +import com.google.api.gax.rpc.TransportChannelProvider; +import com.google.api.gax.rpc.UnaryCallSettings; +import com.google.cloud.compute.v1.GetRegionOperationRequest; +import com.google.cloud.compute.v1.Operation; +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 java.io.IOException; +import java.util.List; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Settings class to configure an instance of {@link RegionOperationsStub}. + * + *

The default instance has everything set to sensible defaults: + * + *

    + *
  • The default service address (compute.googleapis.com) and default port (443) are used. + *
  • Credentials are acquired automatically through Application Default Credentials. + *
  • Retries are configured for idempotent methods but not for non-idempotent methods. + *
+ * + *

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 get to 30 seconds: + * + *

{@code
+ * RegionOperationsStubSettings.Builder regionOperationsSettingsBuilder =
+ *     RegionOperationsStubSettings.newBuilder();
+ * regionOperationsSettingsBuilder
+ *     .getSettings()
+ *     .setRetrySettings(
+ *         regionOperationsSettingsBuilder
+ *             .getSettings()
+ *             .getRetrySettings()
+ *             .toBuilder()
+ *             .setTotalTimeout(Duration.ofSeconds(30))
+ *             .build());
+ * RegionOperationsStubSettings regionOperationsSettings = regionOperationsSettingsBuilder.build();
+ * }
+ */ +@Generated("by gapic-generator-java") +public class RegionOperationsStubSettings extends StubSettings { + /** The default scopes of the service. */ + private static final ImmutableList DEFAULT_SERVICE_SCOPES = + ImmutableList.builder() + .add("https://www.googleapis.com/auth/compute.readonly") + .add("https://www.googleapis.com/auth/compute") + .add("https://www.googleapis.com/auth/cloud-platform") + .build(); + + private final UnaryCallSettings getSettings; + + /** Returns the object with the settings used for calls to get. */ + public UnaryCallSettings getSettings() { + return getSettings; + } + + @BetaApi("A restructuring of stub classes is planned, so this may break in the future") + public RegionOperationsStub createStub() throws IOException { + if (getTransportChannelProvider() + .getTransportName() + .equals(HttpJsonTransportChannel.getHttpJsonTransportName())) { + return HttpJsonRegionOperationsStub.create(this); + } + throw new UnsupportedOperationException( + String.format( + "Transport not supported: %s", getTransportChannelProvider().getTransportName())); + } + + /** Returns a builder for the default ExecutorProvider for this service. */ + public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { + return InstantiatingExecutorProvider.newBuilder(); + } + + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "compute.googleapis.com:443"; + } + + /** Returns the default service scopes. */ + public static List getDefaultServiceScopes() { + return DEFAULT_SERVICE_SCOPES; + } + + /** Returns a builder for the default credentials for this service. */ + public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { + return GoogleCredentialsProvider.newBuilder().setScopesToApply(DEFAULT_SERVICE_SCOPES); + } + + /** Returns a builder for the default ChannelProvider for this service. */ + public static InstantiatingHttpJsonChannelProvider.Builder + defaultHttpJsonTransportProviderBuilder() { + return InstantiatingHttpJsonChannelProvider.newBuilder(); + } + + public static TransportChannelProvider defaultTransportChannelProvider() { + return defaultHttpJsonTransportProviderBuilder().build(); + } + + @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(RegionOperationsStubSettings.class)) + .setTransportToken( + GaxHttpJsonProperties.getHttpJsonTokenName(), + GaxHttpJsonProperties.getHttpJsonVersion()); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder() { + return Builder.createDefault(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder(ClientContext clientContext) { + return new Builder(clientContext); + } + + /** Returns a builder containing all the values of this settings class. */ + public Builder toBuilder() { + return new Builder(this); + } + + protected RegionOperationsStubSettings(Builder settingsBuilder) throws IOException { + super(settingsBuilder); + + getSettings = settingsBuilder.getSettings().build(); + } + + /** Builder for RegionOperationsStubSettings. */ + public static class Builder extends StubSettings.Builder { + private final ImmutableList> unaryMethodSettingsBuilders; + private final UnaryCallSettings.Builder getSettings; + private static final ImmutableMap> + RETRYABLE_CODE_DEFINITIONS; + + static { + ImmutableMap.Builder> definitions = + ImmutableMap.builder(); + definitions.put("no_retry_codes", ImmutableSet.copyOf(Lists.newArrayList())); + RETRYABLE_CODE_DEFINITIONS = definitions.build(); + } + + private static final ImmutableMap RETRY_PARAM_DEFINITIONS; + + static { + ImmutableMap.Builder definitions = ImmutableMap.builder(); + RetrySettings settings = null; + settings = RetrySettings.newBuilder().setRpcTimeoutMultiplier(1.0).build(); + definitions.put("no_retry_params", settings); + RETRY_PARAM_DEFINITIONS = definitions.build(); + } + + protected Builder() { + this(((ClientContext) null)); + } + + protected Builder(ClientContext clientContext) { + super(clientContext); + + getSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); + + unaryMethodSettingsBuilders = ImmutableList.>of(getSettings); + initDefaults(this); + } + + protected Builder(RegionOperationsStubSettings settings) { + super(settings); + + getSettings = settings.getSettings.toBuilder(); + + unaryMethodSettingsBuilders = ImmutableList.>of(getSettings); + } + + private static Builder createDefault() { + Builder builder = new Builder(((ClientContext) null)); + + builder.setTransportChannelProvider(defaultTransportChannelProvider()); + builder.setCredentialsProvider(defaultCredentialsProviderBuilder().build()); + builder.setInternalHeaderProvider(defaultApiClientHeaderProviderBuilder().build()); + builder.setEndpoint(getDefaultEndpoint()); + + return initDefaults(builder); + } + + private static Builder initDefaults(Builder builder) { + builder + .getSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) + .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); + + return builder; + } + + // NEXT_MAJOR_VER: remove 'throws Exception'. + /** + * Applies the given settings updater function to all of the unary API methods in this service. + * + *

Note: This method does not support applying settings to streaming methods. + */ + public Builder applyToAllUnaryMethods( + ApiFunction, Void> settingsUpdater) throws Exception { + super.applyToAllUnaryMethods(unaryMethodSettingsBuilders, settingsUpdater); + return this; + } + + public ImmutableList> unaryMethodSettingsBuilders() { + return unaryMethodSettingsBuilders; + } + + /** Returns the builder for the settings used for calls to get. */ + public UnaryCallSettings.Builder getSettings() { + return getSettings; + } + + @Override + public RegionOperationsStubSettings build() throws IOException { + return new RegionOperationsStubSettings(this); + } + } +} From 9070765b8c2e3dfd89c52867dae0dad957df3659 Mon Sep 17 00:00:00 2001 From: vam-google Date: Tue, 8 Jun 2021 01:58:16 -0700 Subject: [PATCH 2/4] chore: small fixes --- repositories.bzl | 3 ++- test/integration/goldens/compute/BUILD.bazel | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/repositories.bzl b/repositories.bzl index 221cfe9a71..8b14726692 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -65,7 +65,8 @@ def gapic_generator_java_repositories(): ], ) - #TODO: replace with the googleapis-discovery upstream repo before mergin + #TODO: replace with the googleapis-discovery upstream after + # https://github.com/googleapis/googleapis-discovery/pull/46 is merged _maybe( http_archive, name = "com_google_googleapis_discovery", diff --git a/test/integration/goldens/compute/BUILD.bazel b/test/integration/goldens/compute/BUILD.bazel index 9face45656..2822013159 100644 --- a/test/integration/goldens/compute/BUILD.bazel +++ b/test/integration/goldens/compute/BUILD.bazel @@ -9,4 +9,4 @@ filegroup( ".*.sw*", ], ), -) \ No newline at end of file +) From e3afeb033add49c7b66d0df8772559f1fe969932 Mon Sep 17 00:00:00 2001 From: vam-google Date: Tue, 8 Jun 2021 13:19:15 -0700 Subject: [PATCH 3/4] chore: replace googleapis-discovery with proper link --- repositories.bzl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/repositories.bzl b/repositories.bzl index 8b14726692..6d37762dfa 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -65,14 +65,12 @@ def gapic_generator_java_repositories(): ], ) - #TODO: replace with the googleapis-discovery upstream after - # https://github.com/googleapis/googleapis-discovery/pull/46 is merged _maybe( http_archive, name = "com_google_googleapis_discovery", - strip_prefix = "googleapis-discovery-e38f9bcb93237eed01f40d4fe1337d820f9f6b80", + strip_prefix = "googleapis-discovery-4f5d0604132e93e63330e65e2e6648c75012780c", urls = [ - "https://github.com/vam-google/googleapis-discovery/archive/e38f9bcb93237eed01f40d4fe1337d820f9f6b80.zip", + "https://github.com/googleapis/googleapis-discovery/archive/4f5d0604132e93e63330e65e2e6648c75012780c.zip", ], ) From e899db50caa20aff589446ff81b2253c345eed4e Mon Sep 17 00:00:00 2001 From: vam-google Date: Thu, 10 Jun 2021 00:08:45 -0700 Subject: [PATCH 4/4] regenerate integration tests --- .../cloud/compute/v1/stub/AddressesStubSettings.java | 7 +++++++ .../compute/v1/stub/RegionOperationsStubSettings.java | 7 +++++++ 2 files changed, 14 insertions(+) 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 38085ac627..d8268b878b 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 @@ -135,6 +135,11 @@ public static String getDefaultEndpoint() { return "compute.googleapis.com:443"; } + /** Returns the default mTLS service endpoint. */ + public static String getDefaultMtlsEndpoint() { + return "compute.mtls.googleapis.com:443"; + } + /** Returns the default service scopes. */ public static List getDefaultServiceScopes() { return DEFAULT_SERVICE_SCOPES; @@ -254,6 +259,8 @@ private static Builder createDefault() { builder.setCredentialsProvider(defaultCredentialsProviderBuilder().build()); builder.setInternalHeaderProvider(defaultApiClientHeaderProviderBuilder().build()); builder.setEndpoint(getDefaultEndpoint()); + builder.setMtlsEndpoint(getDefaultMtlsEndpoint()); + builder.setSwitchToMtlsEndpointAllowed(true); return initDefaults(builder); } 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 a73893e0d5..25be522d20 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 @@ -112,6 +112,11 @@ public static String getDefaultEndpoint() { return "compute.googleapis.com:443"; } + /** Returns the default mTLS service endpoint. */ + public static String getDefaultMtlsEndpoint() { + return "compute.mtls.googleapis.com:443"; + } + /** Returns the default service scopes. */ public static List getDefaultServiceScopes() { return DEFAULT_SERVICE_SCOPES; @@ -215,6 +220,8 @@ private static Builder createDefault() { builder.setCredentialsProvider(defaultCredentialsProviderBuilder().build()); builder.setInternalHeaderProvider(defaultApiClientHeaderProviderBuilder().build()); builder.setEndpoint(getDefaultEndpoint()); + builder.setMtlsEndpoint(getDefaultMtlsEndpoint()); + builder.setSwitchToMtlsEndpointAllowed(true); return initDefaults(builder); }