diff --git a/rules_java_gapic/java_gapic.bzl b/rules_java_gapic/java_gapic.bzl index eb2cdee79a..f066c6a92d 100644 --- a/rules_java_gapic/java_gapic.bzl +++ b/rules_java_gapic/java_gapic.bzl @@ -22,6 +22,7 @@ def _java_gapic_postprocess_srcjar_impl(ctx): output_main = ctx.outputs.main output_test = ctx.outputs.test output_samples = ctx.outputs.samples + output_spring = ctx.outputs.spring output_resource_name = ctx.outputs.resource_name formatter = ctx.executable.formatter @@ -65,10 +66,21 @@ def _java_gapic_postprocess_srcjar_impl(ctx): cd $WORKING_DIR + unzip -q temp-codegen-spring.srcjar -d {output_dir_path}/spring + # This may fail if there are spaces and/or too many files (exceed max length of command length). + {formatter} --replace $(find {output_dir_path}/spring -type f -printf "%p ") + + # Spring source files. + cd {output_dir_path}/spring + zip -r $WORKING_DIR/{output_srcjar_name}-spring.srcjar ./ + + cd $WORKING_DIR + mv {output_srcjar_name}.srcjar {output_main} mv {output_srcjar_name}-resource-name.srcjar {output_resource_name} mv {output_srcjar_name}-tests.srcjar {output_test} mv {output_srcjar_name}-samples.srcjar {output_samples} + mv {output_srcjar_name}-spring.srcjar {output_spring} """.format( gapic_srcjar = gapic_srcjar.path, output_srcjar_name = output_srcjar_name, @@ -79,13 +91,14 @@ def _java_gapic_postprocess_srcjar_impl(ctx): output_resource_name = output_resource_name.path, output_test = output_test.path, output_samples = output_samples.path, + output_spring = output_spring.path, ) ctx.actions.run_shell( inputs = [gapic_srcjar], tools = [formatter], command = script, - outputs = [output_main, output_resource_name, output_test, output_samples], + outputs = [output_main, output_resource_name, output_test, output_samples, output_spring], ) _java_gapic_postprocess_srcjar = rule( @@ -102,6 +115,7 @@ _java_gapic_postprocess_srcjar = rule( "resource_name": "%{name}-resource-name.srcjar", "test": "%{name}-test.srcjar", "samples": "%{name}-samples.srcjar", + "spring": "%{name}-spring.srcjar", }, implementation = _java_gapic_postprocess_srcjar_impl, ) @@ -161,6 +175,62 @@ _java_gapic_samples_srcjar = rule( implementation = _java_gapic_samples_srcjar_impl, ) + +def _java_gapic_spring_srcjar_impl(ctx): + gapic_srcjar = ctx.file.gapic_srcjar + output_srcjar_name = ctx.label.name + output_spring = ctx.outputs.spring + formatter = ctx.executable.formatter + + output_dir_name = ctx.label.name + output_dir_path = "%s/%s" % (output_spring.dirname, output_dir_name) + + script = """ + unzip -q {gapic_srcjar} + # Sync'd to the output file name in Writer.java. + unzip -q temp-codegen-spring.srcjar -d {output_dir_path} + # This may fail if there are spaces and/or too many files (exceed max length of command length). + {formatter} --replace $(find {output_dir_path}/spring -type f -printf "%p ") + WORKING_DIR=`pwd` + + # Spring source files. + cd $WORKING_DIR/{output_dir_path} + zip -r $WORKING_DIR/{output_srcjar_name}-spring.srcjar ./ + + cd $WORKING_DIR + + mv {output_srcjar_name}-spring.srcjar {output_spring} + """.format( + gapic_srcjar = gapic_srcjar.path, + output_srcjar_name = output_srcjar_name, + formatter = formatter, + output_dir_name = output_dir_name, + output_dir_path = output_dir_path, + output_spring = output_spring.path, + ) + + ctx.actions.run_shell( + inputs = [gapic_srcjar], + tools = [formatter], + command = script, + outputs = [output_spring], + ) + +_java_gapic_spring_srcjar = rule( + attrs = { + "gapic_srcjar": attr.label(mandatory = True, allow_single_file = True), + "formatter": attr.label( + default = Label("//:google_java_format_binary"), + executable = True, + cfg = "host", + ), + }, + outputs = { + "spring": "%{name}-spring.srcjar", + }, + implementation = _java_gapic_spring_srcjar_impl, +) + def _extract_common_proto_dep(dep): return dep[dep.index("/"):] if "//google" in dep else dep @@ -190,6 +260,7 @@ def _java_gapic_srcjar( # possible values are: "grpc", "rest", "grpc+rest" transport, rest_numeric_enums, + spring_parent_coordinates, # Can be used to provide a java_library with a customized generator, # like the one which dumps descriptor to a file for future debugging. java_generator_name = "java_gapic", @@ -217,6 +288,9 @@ def _java_gapic_srcjar( if rest_numeric_enums: opt_args.append("rest-numeric-enums") + if spring_parent_coordinates: + opt_args.append("spring-parent-coordinates=%s" % spring_parent_coordinates) + # Produces the GAPIC metadata file if this flag is set. to any value. # Protoc invocation: --java_gapic_opt=metadata plugin_args = ["metadata"] @@ -245,6 +319,7 @@ def java_gapic_library( # possible values are: "grpc", "rest", "grpc+rest" transport = None, rest_numeric_enums = False, + spring_parent_coordinates = None, **kwargs): srcjar_name = name + "_srcjar" raw_srcjar_name = srcjar_name + "_raw" @@ -257,6 +332,7 @@ def java_gapic_library( service_yaml = service_yaml, transport = transport, rest_numeric_enums = rest_numeric_enums, + spring_parent_coordinates = spring_parent_coordinates, java_generator_name = "java_gapic", **kwargs ) @@ -273,6 +349,14 @@ def java_gapic_library( **kwargs ) + _java_gapic_spring_srcjar( + name = "%s_spring" % name, + gapic_srcjar = "%s.srcjar" % raw_srcjar_name, + **kwargs + ) + + print("postprocessing done.\n") + resource_name_name = "%s_resource_name" % name resource_name_deps = [resource_name_name] native.java_library( diff --git a/rules_java_gapic/java_gapic_pkg.bzl b/rules_java_gapic/java_gapic_pkg.bzl index 36a0d4314c..f89f420d59 100644 --- a/rules_java_gapic/java_gapic_pkg.bzl +++ b/rules_java_gapic/java_gapic_pkg.bzl @@ -68,6 +68,11 @@ def _gapic_pkg_tar_impl(ctx): for f in s.files.to_list(): samples.append(f) + spring =[] + for s in ctx.attr.spring: + for f in s.files.to_list(): + spring.append(f) + paths = _construct_package_dir_paths( ctx.attr.package_dir, ctx.outputs.pkg, @@ -80,6 +85,11 @@ def _gapic_pkg_tar_impl(ctx): unzip -q ./$s -d {package_dir_path}/{tar_cd_suffix}/{tar_prefix}/samples/snippets/generated/ done + for s in {spring}; do + mkdir -p {package_dir_path}/{tar_cd_suffix}/{tar_prefix}/spring/ + unzip -q ./$s -d {package_dir_path}/{tar_cd_suffix}/{tar_prefix}/spring/ + done + mkdir -p {package_dir_path} for dep in {deps}; do tar -xzpf $dep -C {package_dir_path} @@ -95,13 +105,14 @@ def _gapic_pkg_tar_impl(ctx): package_dir_path = paths.package_dir_path, package_dir = paths.package_dir, samples = " ".join(["'%s'" % s.path for s in samples]), + spring = " ".join(["'%s'" % s.path for s in spring]), pkg = ctx.outputs.pkg.path, tar_cd_suffix = paths.tar_cd_suffix, tar_prefix = paths.tar_prefix, ) ctx.actions.run_shell( - inputs = deps + samples, + inputs = deps + samples + spring, command = script, outputs = [ctx.outputs.pkg], ) @@ -114,6 +125,7 @@ gapic_pkg_tar = rule( attrs = { "deps": attr.label_list(mandatory = True), "samples": attr.label_list(mandatory = False), + "spring": attr.label_list(mandatory = False), "package_dir": attr.string(mandatory = False, default = ""), "extension": attr.string(mandatory = False, default = "tar.gz"), }, @@ -274,6 +286,10 @@ def _java_gapic_srcs_pkg_impl(ctx): if [ -d {package_dir_path}/src/main/java/samples ]; then mv {package_dir_path}/src/main/java/samples {package_dir_path} fi + + if [ -d {package_dir_path}/src/main/java/spring ]; then + mv {package_dir_path}/src/main/java/spring {package_dir_path} + fi done for proto_src in {proto_srcs}; do mkdir -p {package_dir_path}/src/main/proto @@ -319,6 +335,7 @@ def java_gapic_assembly_gradle_pkg( name, deps, include_samples = False, + include_spring = False, assembly_name = None, transport = None, **kwargs): @@ -339,6 +356,7 @@ def java_gapic_assembly_gradle_pkg( grpc_deps = [] proto_deps = [] samples = [] + spring = [] processed_deps = {} #there is no proper Set in Starlark for dep in deps: @@ -346,6 +364,8 @@ def java_gapic_assembly_gradle_pkg( if "_java_gapic" in dep: if include_samples: samples.append(dep + "_samples") + if include_spring: + spring.append(dep + "_spring") _put_dep_in_a_bucket(dep, client_deps, processed_deps) _put_dep_in_a_bucket("%s_test" % dep, client_test_deps, processed_deps) _put_dep_in_a_bucket("%s_resource_name" % dep, proto_deps, processed_deps) @@ -393,7 +413,8 @@ def java_gapic_assembly_gradle_pkg( name = name, assembly_name = package_dir, deps = proto_target_dep + grpc_target_dep + client_target_dep, - samples = samples, + samples = samples, # :vision_java_gapic_samples + spring = spring, # :vision_java_gapic_spring ) def _java_gapic_gradle_pkg( @@ -439,7 +460,7 @@ def _java_gapic_gradle_pkg( **kwargs ) -def _java_gapic_assembly_gradle_pkg(name, assembly_name, deps, samples = None, visibility = None): +def _java_gapic_assembly_gradle_pkg(name, assembly_name, deps, samples = None, spring = None, visibility = None): resource_target_name = "%s-resources" % assembly_name java_gapic_build_configs_pkg( name = resource_target_name, @@ -459,5 +480,6 @@ def _java_gapic_assembly_gradle_pkg(name, assembly_name, deps, samples = None, v ] + deps, samples = samples, package_dir = assembly_name, + spring = spring, visibility = visibility, ) diff --git a/src/main/java/com/google/api/generator/Main.java b/src/main/java/com/google/api/generator/Main.java index 2ad75c19ba..992c40a085 100644 --- a/src/main/java/com/google/api/generator/Main.java +++ b/src/main/java/com/google/api/generator/Main.java @@ -15,6 +15,7 @@ package com.google.api.generator; import com.google.api.generator.gapic.Generator; +import com.google.api.generator.spring.SpringGenerator; import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest; import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse; @@ -26,6 +27,8 @@ public static void main(String[] args) throws IOException { ProtoRegistry.registerAllExtensions(registry); CodeGeneratorRequest request = CodeGeneratorRequest.parseFrom(System.in, registry); CodeGeneratorResponse response = Generator.generateGapic(request); + CodeGeneratorResponse springResponse = SpringGenerator.generateSpring(request); response.writeTo(System.out); + springResponse.writeTo(System.out); } } diff --git a/src/main/java/com/google/api/generator/gapic/model/GapicContext.java b/src/main/java/com/google/api/generator/gapic/model/GapicContext.java index 8fdba8d3ee..6c2e840f81 100644 --- a/src/main/java/com/google/api/generator/gapic/model/GapicContext.java +++ b/src/main/java/com/google/api/generator/gapic/model/GapicContext.java @@ -49,6 +49,9 @@ public abstract class GapicContext { public abstract boolean restNumericEnumsEnabled(); + @Nullable + public abstract String springParentCoordinates(); + public GapicMetadata gapicMetadata() { return gapicMetadata; } @@ -113,6 +116,8 @@ public Builder setHelperResourceNames(Set helperResourceNames) { public abstract Builder setRestNumericEnumsEnabled(boolean restNumericEnumsEnabled); + public abstract Builder setSpringParentCoordinates(String springParentCoordinates); + public abstract Builder setTransport(Transport transport); abstract ImmutableMap resourceNames(); 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 35ba86dcc6..a9451d405d 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 @@ -118,6 +118,7 @@ public static GapicContext parse(CodeGeneratorRequest request) { Optional languageSettingsOpt = GapicLanguageSettingsParser.parse(gapicYamlConfigPathOpt); Optional transportOpt = PluginArgumentParser.parseTransport(request); + Optional springParent = PluginArgumentParser.parseSpringParentCoordinates(request); boolean willGenerateMetadata = PluginArgumentParser.hasMetadataFlag(request); boolean willGenerateNumericEnum = PluginArgumentParser.hasNumericEnumFlag(request); @@ -218,6 +219,7 @@ public static GapicContext parse(CodeGeneratorRequest request) { .setServiceYamlProto(serviceYamlProtoOpt.orElse(null)) .setTransport(transport) .setRestNumericEnumsEnabled(willGenerateNumericEnum) + .setSpringParentCoordinates(springParent.orElse(null)) .build(); } 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 f56e0621a9..18575db777 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 @@ -31,6 +31,7 @@ public class PluginArgumentParser { @VisibleForTesting static final String KEY_METADATA = "metadata"; @VisibleForTesting static final String KEY_NUMERIC_ENUM = "rest-numeric-enums"; @VisibleForTesting static final String KEY_SERVICE_YAML_CONFIG = "api-service-config"; + @VisibleForTesting static final String KEY_SPRING_PARENT = "spring-parent-coordinates"; @VisibleForTesting static final String KEY_TRANSPORT = "transport"; private static final String JSON_FILE_ENDING = "grpc_service_config.json"; @@ -61,6 +62,10 @@ static boolean hasNumericEnumFlag(CodeGeneratorRequest request) { return hasFlag(request.getParameter(), KEY_NUMERIC_ENUM); } + static Optional parseSpringParentCoordinates(CodeGeneratorRequest request) { + return parseConfigArgument(request.getParameter(), KEY_SPRING_PARENT); + } + /** Expects a comma-separated list of file paths. */ @VisibleForTesting static Optional parseJsonConfigPath(String pluginProtocArgument) { diff --git a/src/main/java/com/google/api/generator/spring/SpringGenerator.java b/src/main/java/com/google/api/generator/spring/SpringGenerator.java new file mode 100644 index 0000000000..b85f310d49 --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/SpringGenerator.java @@ -0,0 +1,34 @@ +// Copyright 2022 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.spring; + +import com.google.api.generator.gapic.model.GapicClass; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.GapicPackageInfo; +import com.google.api.generator.gapic.protoparser.Parser; +import com.google.api.generator.spring.composer.SpringComposer; +import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest; +import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse; +import java.util.List; + +public class SpringGenerator { + public static CodeGeneratorResponse generateSpring(CodeGeneratorRequest request) { + GapicContext context = Parser.parse(request); + List clazzes = SpringComposer.composeServiceAutoConfigClasses(context); + GapicPackageInfo packageInfo = SpringComposer.composePackageInfo(context); + String outputFilename = "temp-codegen-spring.srcjar"; + return SpringWriter.write(context, clazzes, packageInfo, outputFilename); + } +} diff --git a/src/main/java/com/google/api/generator/spring/SpringWriter.java b/src/main/java/com/google/api/generator/spring/SpringWriter.java new file mode 100644 index 0000000000..21669ae915 --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/SpringWriter.java @@ -0,0 +1,340 @@ +// Copyright 2022 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.spring; + +import com.google.api.generator.engine.ast.ClassDefinition; +import com.google.api.generator.engine.ast.PackageInfoDefinition; +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.GapicPackageInfo; +import com.google.api.generator.spring.utils.Utils; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.protobuf.ByteString; +import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.StringJoiner; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +public class SpringWriter { + static class GapicWriterException extends RuntimeException { + + public GapicWriterException(String errorMessage, Throwable cause) { + super(errorMessage, cause); + } + } + + public static CodeGeneratorResponse write( + GapicContext context, + List clazzes, + GapicPackageInfo gapicPackageInfo, + String outputFilePath) { + ByteString.Output output = ByteString.newOutput(); + JavaWriterVisitor codeWriter = new JavaWriterVisitor(); + JarOutputStream jos; + try { + jos = new JarOutputStream(output); + } catch (IOException e) { + throw new GapicWriterException(e.getMessage(), e); + } + + for (GapicClass gapicClazz : clazzes) { + writeClazz(gapicClazz, codeWriter, jos); + } + + // write spring.factories file + writeAutoConfigRegistration(context, jos); + writeSpringAdditionalMetadataJson(context, jos); + writePom(context, jos); + + // write package-info.java + writePackageInfo(gapicPackageInfo, codeWriter, jos); + + try { + jos.finish(); + jos.flush(); + } catch (IOException e) { + throw new GapicWriterException(e.getMessage(), e); + } + + CodeGeneratorResponse.Builder response = CodeGeneratorResponse.newBuilder(); + response + .setSupportedFeatures(CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL_VALUE) + .addFileBuilder() + .setName(outputFilePath) + .setContentBytes(output.toByteString()); + return response.build(); + } + + private static String writeClazz( + GapicClass gapicClazz, JavaWriterVisitor codeWriter, JarOutputStream jos) { + ClassDefinition clazz = gapicClazz.classDefinition(); + + clazz.accept(codeWriter); + String code = codeWriter.write(); + codeWriter.clear(); + + String path = getPath(clazz.packageString(), clazz.classIdentifier().name()); + String className = clazz.classIdentifier().name(); + JarEntry jarEntry = new JarEntry(String.format("%s/%s.java", path, className)); + try { + jos.putNextEntry(jarEntry); + jos.write(code.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new GapicWriterException( + String.format( + "Could not write code for class %s.%s: %s", + clazz.packageString(), clazz.classIdentifier().name(), e.getMessage()), + e); + } + return path; + } + + private static String writePackageInfo( + GapicPackageInfo gapicPackageInfo, JavaWriterVisitor codeWriter, JarOutputStream jos) { + PackageInfoDefinition packageInfo = gapicPackageInfo.packageInfo(); + packageInfo.accept(codeWriter); + String code = codeWriter.write(); + codeWriter.clear(); + + String packagePath = "src/main/java/" + packageInfo.pakkage().replaceAll("\\.", "/"); + JarEntry jarEntry = new JarEntry(String.format("%s/package-info.java", packagePath)); + try { + jos.putNextEntry(jarEntry); + jos.write(code.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new GapicWriterException("Could not write code for package-info.java", e); + } + return packagePath; + } + + @VisibleForTesting + static String buildAutoConfigRegistrationString(GapicContext context) { + StringJoiner sb = new StringJoiner("\n", "", ""); + context + .services() + .forEach( + service -> + sb.add( + String.format( + "%s.spring.%sSpringAutoConfig", service.pakkage(), service.name()))); + return sb.toString(); + } + + private static void writeAutoConfigRegistration(GapicContext context, JarOutputStream jos) { + String path = "src/main/resources/META-INF/spring"; + String fileName = + String.format("%s/org.springframework.boot.autoconfigure.AutoConfiguration.imports", path); + JarEntry jarEntry = new JarEntry(fileName); + try { + jos.putNextEntry(jarEntry); + String result = buildAutoConfigRegistrationString(context); + jos.write(result.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new GapicWriterException( + String.format("Could not write spring autoconfiguration registration to %s", fileName), + e); + } + } + + @VisibleForTesting + static String buildSpringAdditionalMetadataJsonString(GapicContext context) { + JsonObject jsonResult = new JsonObject(); + JsonArray objectArray = new JsonArray(); + context + .services() + .forEach( + service -> { + JsonObject innerObject = new JsonObject(); + innerObject.addProperty( + "name", + String.format( + "%s.enabled", + Utils.getSpringPropertyPrefix( + Utils.getPackageName(context), service.name()))); + innerObject.addProperty("type", "java.lang.Boolean"); + innerObject.addProperty( + "description", + String.format( + "Auto-configure Google Cloud %s components.", + Utils.getLibName(context) + "/" + service.name())); + innerObject.addProperty("defaultValue", true); + objectArray.add(innerObject); + }); + jsonResult.add("properties", objectArray); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + JsonElement prettyJson = JsonParser.parseString(jsonResult.toString()); + return gson.toJson(prettyJson); + } + + private static void writeSpringAdditionalMetadataJson(GapicContext context, JarOutputStream jos) { + String path = "src/main/resources/META-INF"; + JarEntry jarEntry = + new JarEntry(String.format("%s/additional-spring-configuration-metadata.json", path)); + try { + jos.putNextEntry(jarEntry); + String result = buildSpringAdditionalMetadataJsonString(context); + jos.write(result.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new GapicWriterException( + "Could not write additional-spring-configuration-metadata.json", e); + } + } + + @VisibleForTesting + static String buildPomString(GapicContext context) { + String pakkageName = Utils.getPackageName(context); + pakkageName = pakkageName.replace('.', '-'); + String clientLibraryShortName = Utils.getLibName(context); + String clientLibraryGroupId = "{{client-library-group-id}}"; + String clientLibraryName = "{{client-library-artifact-id}}"; + String clientLibraryVersion = "{{client-library-version}}"; + String springParentCoordinates = buildPomParent(context.springParentCoordinates()); + + String springStarterArtifactId = pakkageName + "-spring-starter"; + String springStarterVersion = "{{starter-version}}"; + String springStarterName = "Spring Boot Starter - " + clientLibraryShortName; + + StringJoiner sb = new StringJoiner(",\\\n"); + sb.add( + String.format( + "\n" + + "\n" + + " 4.0.0\n" + + "\n" + + "%s" + + " com.google.cloud\n" + + " %s\n" + + " %s\n" + + " %s\n" + + " Spring Boot Starter with AutoConfiguration for %s\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " %s\n" + + " %s\n" + + " %s\n" + + " \n" + + "\n" + + " \n" + + " org.springframework.boot\n" + + " spring-boot-starter\n" + + " 2.6.3\n" + + " \n" + + "\n" + + " \n" + + " com.google.cloud\n" + + " spring-cloud-gcp-core\n" + + " 3.2.1\n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " org.apache.maven.plugins\n" + + " maven-jar-plugin\n" + + " 3.2.2\n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + " \n" + + " org.apache.maven.plugins\n" + + " maven-jar-plugin\n" + + " \n" + + " \n" + + " \n" + + " true\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + "", + springParentCoordinates, + springStarterArtifactId, + springStarterVersion, + springStarterName, + clientLibraryShortName, + clientLibraryGroupId, + clientLibraryName, + clientLibraryVersion)); + + return sb.toString(); + } + + private static String buildPomParent(String springParentCoordinates) { + if (springParentCoordinates == null) { + return ""; + } + List splitCoords = Splitter.on(':').splitToList(springParentCoordinates); + Preconditions.checkArgument( + splitCoords.size() == 3, + "Expected parent coordinates to " + "be 3 elements separated by a colon (:)"); + String groupId = splitCoords.get(0); + String artifactId = splitCoords.get(1); + String version = splitCoords.get(2); + String template = + " \n" + + " %s\n" + + " %s\n" + + " %s\n" + + " \n"; + return String.format(template, groupId, artifactId, version); + } + + private static void writePom(GapicContext context, JarOutputStream jos) { + JarEntry jarEntry = new JarEntry("pom.xml"); + try { + jos.putNextEntry(jarEntry); + String result = buildPomString(context); + jos.write(result.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new GapicWriterException("Could not write pom.xml", e); + } + } + + private static String getPath(String pakkage, String className) { + String path = pakkage.replaceAll("\\.", "/"); + if (className.startsWith("Mock") || className.endsWith("Test")) { + path = "src/test/java/" + path; + } else { + path = "src/main/java/" + path; + } + + // Resource name helpers go into the protobuf package. Denote this with "proto/src/main/*". + if (className.endsWith("Name")) { + path = "proto/" + path; + } + return path; + } +} diff --git a/src/main/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposer.java b/src/main/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposer.java new file mode 100644 index 0000000000..952d79335e --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposer.java @@ -0,0 +1,1002 @@ +// Copyright 2022 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.spring.composer; + +import com.google.api.gax.core.ExecutorProvider; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.retrying.RetrySettings; +import com.google.api.gax.rpc.TransportChannelProvider; +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.ArithmeticOperationExpr; +import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.CastExpr; +import com.google.api.generator.engine.ast.ClassDefinition; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.ExprStatement; +import com.google.api.generator.engine.ast.IfStatement; +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.RelationalOperationExpr; +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.ThisObjectValue; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.engine.ast.VaporReference; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.common.ClassComposer; +import com.google.api.generator.gapic.composer.utils.ClassNames; +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.GapicServiceConfig; +import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.spring.composer.comment.SpringAutoconfigCommentComposer; +import com.google.api.generator.spring.utils.LoggerUtils; +import com.google.api.generator.spring.utils.Utils; +import com.google.common.base.CaseFormat; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class SpringAutoConfigClassComposer implements ClassComposer { + private static final String CLASS_NAME_PATTERN = "%sSpringAutoConfiguration"; + private static final String OPERATIONS_STUB_MEMBER_NAME = "operationsStub"; + private static final String BACKGROUND_RESOURCES_MEMBER_NAME = "backgroundResources"; + private static final String RETRY_PARAM_DEFINITIONS_VAR_NAME = "RETRY_PARAM_DEFINITIONS"; + + private static final SpringAutoConfigClassComposer INSTANCE = new SpringAutoConfigClassComposer(); + + private static final Map STATIC_TYPES = createStaticTypes(); + + private static final VariableExpr NESTED_RETRY_PARAM_DEFINITIONS_VAR_EXPR = + createNestedRetryParamDefinitionsVarExpr(); + + private SpringAutoConfigClassComposer() {} + + public static SpringAutoConfigClassComposer instance() { + return INSTANCE; + } + + @Override + public GapicClass generate(GapicContext context, Service service) { + String packageName = Utils.getSpringPackageName(service.pakkage()); + Map types = createDynamicTypes(service, packageName); + String serviceName = service.name(); + String serviceNameLowerCamel = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, serviceName); + String className = getThisClassName(serviceName); + String credentialsProviderName = serviceNameLowerCamel + "Credentials"; + String transportChannelProviderName = "default" + serviceName + "TransportChannelProvider"; + String clientName = serviceNameLowerCamel + "Client"; + GapicClass.Kind kind = Kind.MAIN; + + GapicServiceConfig gapicServiceConfig = context.serviceConfig(); + + types.get("CredentialsProvider").isSupertypeOrEquals(types.get("DefaultCredentialsProvider")); + + ClassDefinition classDef = + ClassDefinition.builder() + .setPackageString(packageName) + .setName(className) + .setScope(ScopeNode.PUBLIC) + .setHeaderCommentStatements( + SpringAutoconfigCommentComposer.createClassHeaderComments(className, serviceName)) + .setStatements(createMemberVariables(service, packageName, types, gapicServiceConfig)) + .setMethods( + Arrays.asList( + createConstructor(service.name(), className, types), + createCredentialsProviderBeanMethod( + service, className, credentialsProviderName, types), + createTransportChannelProviderBeanMethod( + service, transportChannelProviderName, types), + createClientBeanMethod( + service, + className, + credentialsProviderName, + transportChannelProviderName, + clientName, + types, + gapicServiceConfig))) + .setAnnotations(createClassAnnotations(service, types)) + .build(); + return GapicClass.create(kind, classDef); + } + + private static VariableExpr createNestedRetryParamDefinitionsVarExpr() { + TypeNode varType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(ImmutableMap.class) + .setGenerics( + Arrays.asList(TypeNode.STRING, STATIC_TYPES.get("RetrySettings")).stream() + .map(t -> t.reference()) + .collect(Collectors.toList())) + .build()); + + return VariableExpr.withVariable( + Variable.builder().setType(varType).setName(RETRY_PARAM_DEFINITIONS_VAR_NAME).build()); + } + + private static List createMemberVariables( + Service service, + String packageName, + Map types, + GapicServiceConfig serviceConfig) { + + String serviceName = service.name(); + + // private final LanguageProperties clientProperties; + Variable clientPropertiesVar = + Variable.builder() + .setName("clientProperties") + .setType(types.get(serviceName + "Properties")) + .build(); + VariableExpr clientPropertiesVarExpr = + VariableExpr.builder() + .setVariable(clientPropertiesVar) + .setScope(ScopeNode.PRIVATE) + .setIsFinal(true) + .setIsDecl(true) + .build(); + ExprStatement clientPropertiesStatement = ExprStatement.withExpr(clientPropertiesVarExpr); + + Statement loggerStatement = + LoggerUtils.getLoggerDeclarationExpr(serviceName + "AutoConfig", types); + return Arrays.asList(clientPropertiesStatement, loggerStatement); + } + + private static MethodDefinition createConstructor( + String serviceName, String className, Map types) { + /// constructor + // VariableExpr credentialsProviderBuilderVarExpr = + // VariableExpr.withVariable( + // Variable.builder() + // .setName("coreCredentialsProvider") + // .setType(types.get("CredentialsProvider")) + // .build()); + // + // VariableExpr coreProjectIdProviderVarExpr = + // VariableExpr.withVariable( + // Variable.builder() + // .setName("coreProjectIdProvider") + // .setType(types.get("GcpProjectIdProvider")) + // .build()); + + VariableExpr propertiesVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setName("clientProperties") + .setType(types.get(serviceName + "Properties")) + .build()); + // Variable projectIdProviderVar = + // Variable.builder() + // .setName("projectIdProvider") + // .setType(types.get("GcpProjectIdProvider")) + // .build(); + Variable clientPropertiesVar = + Variable.builder() + .setName("clientProperties") + .setType(types.get(serviceName + "Properties")) + .build(); + + Expr thisExpr = ValueExpr.withValue(ThisObjectValue.withType(types.get(className))); + + // this.clientProperties = clientProperties; + AssignmentExpr thisPropertiesAssignmentExpr = + AssignmentExpr.builder() + .setVariableExpr( + VariableExpr.withVariable(clientPropertiesVar) + .toBuilder() + .setExprReferenceExpr(thisExpr) + .build()) + .setValueExpr(propertiesVarExpr) + .build(); + ExprStatement thisPropertiesAssignmentStatement = + ExprStatement.withExpr(thisPropertiesAssignmentExpr); + + return MethodDefinition.constructorBuilder() + .setScope(ScopeNode.PROTECTED) + .setReturnType(types.get(className)) + .setArguments(Arrays.asList(propertiesVarExpr.toBuilder().setIsDecl(true).build())) + .setBody(Arrays.asList(thisPropertiesAssignmentStatement)) + .build(); + } + + private static List createClassAnnotations( + Service service, Map types) { + // @AutoConfiguration + // @ConditionalOnClass(LanguageServiceClient.class) + // @ConditionalOnProperty(value = + // "com.google.cloud.language.v1.spring.auto.language-service.enabled", matchIfMissing = true) + // @EnableConfigurationProperties(LanguageProperties.class) + + AssignmentExpr valueStringAssignmentExpr = + AssignmentExpr.builder() + .setVariableExpr( + VariableExpr.withVariable( + Variable.builder().setName("value").setType(TypeNode.STRING).build())) + .setValueExpr( + ValueExpr.withValue( + StringObjectValue.withValue( + Utils.getSpringPropertyPrefix(service.pakkage(), service.name()) + + ".enabled"))) + .build(); + AssignmentExpr matchIfMissingAssignmentExpr = + AssignmentExpr.builder() + .setVariableExpr( + VariableExpr.withVariable( + Variable.builder().setName("matchIfMissing").setType(TypeNode.BOOLEAN).build())) + .setValueExpr( + ValueExpr.withValue( + PrimitiveValue.builder().setValue("false").setType(TypeNode.BOOLEAN).build())) + .build(); + AnnotationNode conditionalOnPropertyNode = + AnnotationNode.builder() + .setType(types.get("ConditionalOnProperty")) + .addDescription(valueStringAssignmentExpr) + .addDescription(matchIfMissingAssignmentExpr) + .build(); + + AnnotationNode conditionalOnClassNode = + AnnotationNode.builder() + .setType(types.get("ConditionalOnClass")) + .setDescription( + VariableExpr.builder() + .setVariable( + Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) + .setStaticReferenceType(types.get("ServiceClient")) + .build()) + .build(); + + AssignmentExpr proxyBeanMethodsAssignmentExpr = + AssignmentExpr.builder() + .setVariableExpr( + VariableExpr.withVariable( + Variable.builder() + .setName("proxyBeanMethods") + .setType(TypeNode.BOOLEAN) + .build())) + .setValueExpr( + ValueExpr.withValue( + PrimitiveValue.builder().setValue("false").setType(TypeNode.BOOLEAN).build())) + .build(); + AnnotationNode configurationNode = + AnnotationNode.builder().setType(types.get("AutoConfiguration")).build(); + AnnotationNode enableConfigurationPropertiesNode = + AnnotationNode.builder() + .setType(types.get("EnableConfigurationProperties")) + .setDescription( + VariableExpr.builder() + .setVariable( + Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) + .setStaticReferenceType(types.get(service.name() + "Properties")) + .build()) + .build(); + + return Arrays.asList( + configurationNode, + conditionalOnClassNode, + conditionalOnPropertyNode, + enableConfigurationPropertiesNode); + } + + private static MethodDefinition createCredentialsProviderBeanMethod( + Service service, String className, String methodName, Map types) { + // @Bean + // @ConditionalOnMissingBean + // public CredentialsProvider languageServiceCredentials() throws IOException { + // return new DefaultCredentialsProvider(this.clientProperties); + // } + + Variable clientPropertiesVar = + Variable.builder() + .setName("clientProperties") + .setType(types.get(service.name() + "Properties")) + .build(); + + Expr thisExpr = ValueExpr.withValue(ThisObjectValue.withType(types.get(className))); + VariableExpr thisClientProperties = + VariableExpr.withVariable(clientPropertiesVar) + .toBuilder() + .setExprReferenceExpr(thisExpr) + .build(); + CastExpr castExpr = + CastExpr.builder() + .setExpr( + NewObjectExpr.builder() + .setType(types.get("DefaultCredentialsProvider")) + .setArguments(thisClientProperties) + .build()) + .setType(types.get("CredentialsProvider")) + .build(); + + return MethodDefinition.builder() + .setName(methodName) + .setHeaderCommentStatements( + SpringAutoconfigCommentComposer.createCredentialsProviderBeanComment()) + .setScope(ScopeNode.PUBLIC) + .setReturnType(types.get("CredentialsProvider")) + .setAnnotations( + Arrays.asList( + AnnotationNode.withType(types.get("Bean")), + AnnotationNode.withType(types.get("ConditionalOnMissingBean")))) + .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(IOException.class))) + .setReturnExpr(castExpr) + .build(); + } + + private static MethodDefinition createTransportChannelProviderBeanMethod( + Service service, String methodName, Map types) { + + // @Bean + // @ConditionalOnMissingBean + // public TransportChannelProvider defaultLanguageTransportChannelProvider() { + // return LanguageServiceSettings.defaultTransportChannelProvider(); + // } + // build expressions + MethodInvocationExpr returnExpr = + MethodInvocationExpr.builder() + .setMethodName("defaultTransportChannelProvider") + .setStaticReferenceType(types.get("ServiceSettings")) + .setReturnType(STATIC_TYPES.get("TransportChannelProvider")) + .build(); + + return MethodDefinition.builder() + .setHeaderCommentStatements( + SpringAutoconfigCommentComposer.createTransportChannelProviderComment()) + .setName(methodName) + .setScope(ScopeNode.PUBLIC) + .setReturnType(STATIC_TYPES.get("TransportChannelProvider")) + .setAnnotations( + Arrays.asList( + AnnotationNode.withType(types.get("Bean")), + AnnotationNode.withType(types.get("ConditionalOnMissingBean")))) + .setReturnExpr(returnExpr) + .build(); + } + + private static IfStatement createIfStatement( + Expr conditionExpr, List ifBody, List elseBody) { + IfStatement.Builder credentialIfStatement = + IfStatement.builder().setConditionExpr(conditionExpr).setBody(ifBody); + if (elseBody != null) { + credentialIfStatement.setElseBody(elseBody); + } + return credentialIfStatement.build(); + } + + private static Statement createRetrySettingBuilderForMethod( + String methodName, Variable settingBuilderVariable) { + // RetrySettings.Builder annotateTextRetrySettingsBuilder = + // clientSettingsBuilder.annotateTextSettings() + // .getRetrySettings() + // .toBuilder(); + Variable retrySettingBuilderVariable = + Variable.builder() + .setName(String.format("%sRetrySettingBuilder", methodName)) + .setType(STATIC_TYPES.get("Builder")) + .build(); + VariableExpr retrySettingsVarExpr = + VariableExpr.withVariable(retrySettingBuilderVariable).toBuilder().setIsDecl(true).build(); + MethodInvocationExpr clientSettingBuilderChain = + MethodInvocationExpr.builder() + .setExprReferenceExpr(VariableExpr.withVariable(settingBuilderVariable)) + .setMethodName(String.format("%sSettings", methodName)) + .build(); + clientSettingBuilderChain = + MethodInvocationExpr.builder() + .setExprReferenceExpr(clientSettingBuilderChain) + .setMethodName("getRetrySettings") + .build(); + clientSettingBuilderChain = + MethodInvocationExpr.builder() + .setExprReferenceExpr(clientSettingBuilderChain) + .setMethodName("toBuilder") + .setReturnType(STATIC_TYPES.get("Builder")) + .build(); + AssignmentExpr retrySettingCreateExpr = + AssignmentExpr.builder() + .setVariableExpr(retrySettingsVarExpr) + .setValueExpr(clientSettingBuilderChain) + .build(); + + return ExprStatement.withExpr(retrySettingCreateExpr); + } + + private static Statement setRetrySettingsForMethod( + String methodName, Variable settingBuilderVariable) { + // clientSettingsBuilder.annotateTextSettings() + // .setRetrySettings(annotateTextRetrySettingsBuilder.build()); + + MethodInvocationExpr clientSettingBuilderChain = + MethodInvocationExpr.builder() + .setExprReferenceExpr(VariableExpr.withVariable(settingBuilderVariable)) + .setMethodName(String.format("%sSettings", methodName)) + .build(); + + // annotateTextRetrySettingsBuilder.build() + Variable retrySettingBuilderVariable = + Variable.builder() + .setName(String.format("%sRetrySettingBuilder", methodName)) // extract method name + .setType(STATIC_TYPES.get("Builder")) + .build(); + MethodInvocationExpr retrySettingsBuilderChain = + MethodInvocationExpr.builder() + .setExprReferenceExpr(VariableExpr.withVariable(retrySettingBuilderVariable)) + .setMethodName("build") + .build(); + + clientSettingBuilderChain = + MethodInvocationExpr.builder() + .setExprReferenceExpr(clientSettingBuilderChain) + .setMethodName("setRetrySettings") + .setArguments(retrySettingsBuilderChain) + .build(); + + return ExprStatement.withExpr(clientSettingBuilderChain); + } + + private static MethodDefinition createClientBeanMethod( + Service service, + String className, + String credentialsProviderName, + String transportChannelProviderName, + String clientName, + Map types, + GapicServiceConfig gapicServiceConfig) { + // argument variables: + VariableExpr credentialsProviderVariableExpr = + VariableExpr.withVariable( + Variable.builder() + .setName("credentialsProvider") + .setType(types.get("CredentialsProvider")) + .build()); + VariableExpr transportChannelProviderVariableExpr = + VariableExpr.withVariable( + Variable.builder() + .setName("defaultTransportChannelProvider") + .setType(STATIC_TYPES.get("TransportChannelProvider")) + .build()); + + List bodyStatements = new ArrayList<>(); + // LanguageServiceSettings.Builder clientSettingsBuilder = + // LanguageServiceSettings.newBuilder() + // .setCredentialsProvider(credentialsProvider) + // .setTransportChannelProvider(defaultTransportChannelProvider) + // .setHeaderProvider( + // new UserAgentHeaderProvider(this.getClass())); + Variable settingBuilderVariable = + Variable.builder() + .setName("clientSettingsBuilder") + .setType(types.get("ServiceSettingsBuilder")) + .build(); + VariableExpr settingsVarExpr = + VariableExpr.withVariable(settingBuilderVariable).toBuilder().setIsDecl(true).build(); + Expr settingsBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(types.get("ServiceSettings")) + .setMethodName("newBuilder") + .build(); + + settingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(settingsBuilderExpr) + .setMethodName("setCredentialsProvider") + .setArguments(credentialsProviderVariableExpr) + .build(); + // .setTransportChannelProvider(defaultTransportChannelProvider) + settingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(settingsBuilderExpr) + .setMethodName("setTransportChannelProvider") + .setArguments(transportChannelProviderVariableExpr) + .build(); + // .setHeaderProvider( + // new UserAgentHeaderProvider(this.getClass())); + settingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(settingsBuilderExpr) + .setMethodName("setHeaderProvider") + // .setArguments() //TODO add augument here to create new obj. Caveat: decide where to + // UserAgentHeaderProvider class first. + .setReturnType(settingBuilderVariable.type()) + .build(); + AssignmentExpr settingCreateExpr = + AssignmentExpr.builder() + .setVariableExpr(settingsVarExpr) + .setValueExpr(settingsBuilderExpr) + .build(); + + bodyStatements.add(ExprStatement.withExpr(settingCreateExpr)); + + // if (this.clientProperties.getQuotaProjectId() != null) { + // clientSettingsBuilder.setQuotaProjectId(clientProperties.getQuotaProjectId()); + // LOGGER.info("Quota project id set to: " + clientProperties.getQuotaProjectId() + // + ", this overrides project id from credentials."); + // } + Expr thisExpr = ValueExpr.withValue(ThisObjectValue.withType(types.get(className))); + Variable clientPropertiesVar = + Variable.builder() + .setName("clientProperties") + .setType(types.get(service.name() + "Properties")) + .build(); + VariableExpr thisClientPropertiesVarExpr = + VariableExpr.withVariable(clientPropertiesVar) + .toBuilder() + .setExprReferenceExpr(thisExpr) + .build(); + + MethodInvocationExpr getQuotaProjectId = + MethodInvocationExpr.builder() + .setMethodName("getQuotaProjectId") + .setReturnType(TypeNode.STRING) + .setExprReferenceExpr(thisClientPropertiesVarExpr) + .build(); + RelationalOperationExpr projectIdIsNull = + RelationalOperationExpr.notEqualToWithExprs(getQuotaProjectId, ValueExpr.createNullExpr()); + + // clientSettingsBuilder.setQuotaProjectId(clientProperties.getQuotaProjectId()); + MethodInvocationExpr setQuotaProjectId = + MethodInvocationExpr.builder() + .setExprReferenceExpr(VariableExpr.withVariable(settingBuilderVariable)) + .setMethodName("setQuotaProjectId") + .setArguments(getQuotaProjectId) + .build(); + + ExprStatement projectIdLoggerStatement = + LoggerUtils.createLoggerStatement( + LoggerUtils.concatManyWithExprs( + ValueExpr.withValue(StringObjectValue.withValue("Quota project id set to ")), + getQuotaProjectId, + ValueExpr.withValue( + StringObjectValue.withValue(", this overrides project id from credentials."))), + types); + + IfStatement setQuotaProjectIdStatement = + createIfStatement( + projectIdIsNull, + Arrays.asList(ExprStatement.withExpr(setQuotaProjectId), projectIdLoggerStatement), + null); + + bodyStatements.add(setQuotaProjectIdStatement); + + // if (this.clientProperties.getExecutorThreadCount() != null) { + // ExecutorProvider executorProvider = + // LanguageServiceSettings.defaultExecutorProviderBuilder() + // .setExecutorThreadCount(clientProperties.getExecutorThreadCount()).build(); + // clientSettingsBuilder + // .setBackgroundExecutorProvider(executorProvider); + // } + + MethodInvocationExpr getExecutorThreadCount = + MethodInvocationExpr.builder() + .setMethodName("getExecutorThreadCount") + .setReturnType(TypeNode.INT_OBJECT) + .setExprReferenceExpr(thisClientPropertiesVarExpr) + .build(); + RelationalOperationExpr executorThreadCountIsNull = + RelationalOperationExpr.notEqualToWithExprs( + getExecutorThreadCount, ValueExpr.createNullExpr()); + + VariableExpr executorProviderVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType(STATIC_TYPES.get("ExecutorProvider")) + .setName("executorProvider") + .build()); + + MethodInvocationExpr chainedMethodToSetExecutorProvider = + MethodInvocationExpr.builder() + .setStaticReferenceType(types.get("ServiceSettings")) + .setMethodName("defaultExecutorProviderBuilder") + .build(); + chainedMethodToSetExecutorProvider = + MethodInvocationExpr.builder() + .setExprReferenceExpr(chainedMethodToSetExecutorProvider) + .setMethodName("setExecutorThreadCount") + .setArguments(getExecutorThreadCount) + .build(); + chainedMethodToSetExecutorProvider = + MethodInvocationExpr.builder() + .setExprReferenceExpr(chainedMethodToSetExecutorProvider) + .setMethodName("build") + .setReturnType(STATIC_TYPES.get("ExecutorProvider")) + .build(); + AssignmentExpr executorProviderAssignExpr = + AssignmentExpr.builder() + .setVariableExpr(executorProviderVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(chainedMethodToSetExecutorProvider) + .build(); + MethodInvocationExpr setBackgroundExecutorProvider = + MethodInvocationExpr.builder() + .setExprReferenceExpr(VariableExpr.withVariable(settingBuilderVariable)) + .setMethodName("setBackgroundExecutorProvider") + .setArguments(executorProviderVarExpr) + .build(); + + ExprStatement backgroundExecutorLoggerStatement = + LoggerUtils.createLoggerStatement( + ArithmeticOperationExpr.concatWithExprs( + ValueExpr.withValue( + StringObjectValue.withValue("Background executor thread count is ")), + getExecutorThreadCount), + types); + IfStatement setBackgroundExecutorProviderStatement = + createIfStatement( + executorThreadCountIsNull, + Arrays.asList( + ExprStatement.withExpr(executorProviderAssignExpr), + ExprStatement.withExpr(setBackgroundExecutorProvider), + backgroundExecutorLoggerStatement), + null); + + bodyStatements.add(setBackgroundExecutorProviderStatement); + + // if (clientProperties.getUseRest()) { + // clientSettingsBuilder.setTransportChannelProvider( + // LanguageServiceSettings.defaultHttpJsonTransportProviderBuilder().build()); + // } + + MethodInvocationExpr getUseRest = + MethodInvocationExpr.builder() + .setMethodName("getUseRest") + .setReturnType(TypeNode.BOOLEAN) + .setExprReferenceExpr(thisClientPropertiesVarExpr) + .build(); + + // LanguageServiceSettings.defaultHttpJsonTransportProviderBuilder().build() + Expr defaultTransportProviderBuider = + MethodInvocationExpr.builder() + .setStaticReferenceType(types.get("ServiceSettings")) + .setMethodName("defaultHttpJsonTransportProviderBuilder") + .build(); + defaultTransportProviderBuider = + MethodInvocationExpr.builder() + .setExprReferenceExpr(defaultTransportProviderBuider) + .setMethodName("build") + .setReturnType(STATIC_TYPES.get("InstantiatingHttpJsonChannelProvider")) + .build(); + + MethodInvocationExpr setTransportProvider = + MethodInvocationExpr.builder() + .setExprReferenceExpr(VariableExpr.withVariable(settingBuilderVariable)) + .setMethodName("setTransportChannelProvider") + .setArguments(defaultTransportProviderBuider) + .build(); + IfStatement setTransportChannelProviderStatement = + createIfStatement( + getUseRest, + Arrays.asList( + ExprStatement.withExpr(setTransportProvider), + LoggerUtils.createLoggerStatement( + ValueExpr.withValue( + StringObjectValue.withValue("Using HTTP transport channel")), + types)), + null); + + bodyStatements.add(setTransportChannelProviderStatement); + + // retry settings for each method + TypeNode thisClassType = types.get(service.name() + "AutoConfig"); + List retrySettings = + Utils.processRetrySettings( + service, + gapicServiceConfig, + thisClassType, + (String methodName) -> { + List statements = new ArrayList<>(); + statements.add( + createRetrySettingBuilderForMethod(methodName, settingBuilderVariable)); + return statements; + }, + (List methodAndPropertyName, Expr defaultVal) -> { + // return new ArrayList<>(); + List statements = new ArrayList<>(); + String methodName = methodAndPropertyName.get(0); + String settingName = methodAndPropertyName.get(1); // safe guard?? + String propertyName = + CaseFormat.LOWER_CAMEL.to( + CaseFormat.UPPER_CAMEL, Joiner.on("").join(methodAndPropertyName)); + + TypeNode propertyType = defaultVal.type(); + if (propertyType.equals(TypeNode.DOUBLE)) { + propertyType = TypeNode.DOUBLE_OBJECT; + } + MethodInvocationExpr currentRetrySettingProperty = + MethodInvocationExpr.builder() + .setMethodName(String.format("get%s", propertyName)) + .setReturnType(propertyType) + .setExprReferenceExpr(thisClientPropertiesVarExpr) + .build(); + RelationalOperationExpr currentRetrySettingPropertyIsNull = + RelationalOperationExpr.notEqualToWithExprs( + currentRetrySettingProperty, ValueExpr.createNullExpr()); + + // annotateTextRetrySettingsBuilder.setInitialRetryDelay(this.clientProperties.getAnnotateTextInitialRetryDelay()); + Variable retrySettingBuilderVariable = + Variable.builder() + .setName( + String.format("%sRetrySettingBuilder", methodName)) // extract method name + .setType(STATIC_TYPES.get("Builder")) + .build(); + MethodInvocationExpr retrySettingsBuilderChain = + MethodInvocationExpr.builder() + .setExprReferenceExpr(VariableExpr.withVariable(retrySettingBuilderVariable)) + .setMethodName(String.format("set%s", settingName)) + .setArguments(currentRetrySettingProperty) + .build(); + + IfStatement currentRetrySettingPropertyIfStatement = + createIfStatement( + currentRetrySettingPropertyIsNull, + Arrays.asList( + ExprStatement.withExpr(retrySettingsBuilderChain), + LoggerUtils.createLoggerStatement( + LoggerUtils.concatManyWithExprs( + ValueExpr.withValue( + StringObjectValue.withValue(propertyName + " set to ")), + currentRetrySettingProperty), + types)), + null); + statements.add(currentRetrySettingPropertyIfStatement); + return statements; + }, + (String methodName) -> { + List statements = new ArrayList<>(); + statements.add(setRetrySettingsForMethod(methodName, settingBuilderVariable)); + return statements; + }); + bodyStatements.addAll(retrySettings); + + // return expressions + MethodInvocationExpr serviceSettingsBuilt = + MethodInvocationExpr.builder() + .setMethodName("build") + .setExprReferenceExpr(settingsVarExpr.toBuilder().setIsDecl(false).build()) + .setReturnType(types.get("ServiceSettings")) + .build(); + MethodInvocationExpr returnExpr = + MethodInvocationExpr.builder() + // read more in client composer: + // src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java#L277-L292 + .setMethodName("create") + .setStaticReferenceType(types.get("ServiceClient")) + .setReturnType(types.get("ServiceClient")) + .setArguments(serviceSettingsBuilt) + .build(); + + String methodName = + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, service.name()) + "Client"; + String propertiesClassName = service.name() + "Properties"; + + return MethodDefinition.builder() + .setHeaderCommentStatements( + SpringAutoconfigCommentComposer.createClientBeanComment( + service.name(), propertiesClassName, transportChannelProviderName)) + .setName(methodName) + .setScope(ScopeNode.PUBLIC) + .setReturnType(types.get("ServiceClient")) + .setArguments( + Arrays.asList( + credentialsProviderVariableExpr + .toBuilder() + .setIsDecl(true) + .setAnnotations( + Arrays.asList( + AnnotationNode.builder() + .setType(types.get("Qualifier")) + .setDescription(credentialsProviderName) + .build())) + .build(), + transportChannelProviderVariableExpr + .toBuilder() + .setIsDecl(true) + .setAnnotations( + Arrays.asList( + AnnotationNode.builder() + .setType(types.get("Qualifier")) + .setDescription(transportChannelProviderName) + .build())) + .build())) + .setAnnotations( + Arrays.asList( + AnnotationNode.withType(types.get("Bean")), + AnnotationNode.withType(types.get("ConditionalOnMissingBean")))) + .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(IOException.class))) + .setReturnExpr(returnExpr) + .setBody(bodyStatements) + .build(); + } + + private static Map createStaticTypes() { + List concreteClazzes = + Arrays.asList( + RetrySettings.class, + RetrySettings.Builder + .class, // name will be just Builder. consider change of more than one builder here. + TransportChannelProvider.class, + // import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; + InstantiatingHttpJsonChannelProvider.class, + ExecutorProvider.class); + return concreteClazzes.stream() + .collect( + Collectors.toMap( + c -> c.getSimpleName(), + c -> TypeNode.withReference(ConcreteReference.withClazz(c)))); + } + + private static Map createDynamicTypes(Service service, String packageName) { + Map typeMap = + Arrays.asList(CLASS_NAME_PATTERN).stream() + .collect( + Collectors.toMap( + p -> String.format(p, service.name()), + p -> + TypeNode.withReference( + VaporReference.builder() + .setName(String.format(p, service.name())) + .setPakkage(packageName) + .build()))); + TypeNode credentialsProvider = + TypeNode.withReference( + VaporReference.builder() + .setName("CredentialsProvider") + .setPakkage("com.google.api.gax.core") + .build()); + TypeNode clientProperties = + TypeNode.withReference( + VaporReference.builder() + .setName(service.name() + "SpringProperties") + .setPakkage(packageName) + .build()); + + TypeNode clientAutoconfig = + TypeNode.withReference( + VaporReference.builder() + .setName(service.name() + "SpringAutoConfig") + .setPakkage(packageName) + .build()); + + TypeNode gcpProjectIdProvider = + TypeNode.withReference( + VaporReference.builder() + .setName("GcpProjectIdProvider") + .setPakkage("com.google.cloud.spring.core") + .build()); + + // import com.google.cloud.spring.core.Credentials; + TypeNode credentials = + TypeNode.withReference( + VaporReference.builder() + .setName("Credentials") + .setPakkage("com.google.cloud.spring.core") + .build()); + + // import com.google.cloud.spring.core.DefaultCredentialsProvider; + TypeNode defaultCredentialsProvider = + TypeNode.withReference( + VaporReference.builder() + .setName("DefaultCredentialsProvider") + .setPakkage("com.google.cloud.spring.core") + // TODO: this supre class info is not used, workaround by casting for now. look into + // VaporReference.isSupertypeOrEquals() + .setSupertypeReference( + VaporReference.builder() + .setName("CredentialsProvider") + .setPakkage("com.google.api.gax.core") + .build()) + .build()); + + TypeNode serviceClient = + TypeNode.withReference( + VaporReference.builder() + .setName(ClassNames.getServiceClientClassName(service)) + .setPakkage(service.pakkage()) + .build()); + TypeNode serviceSettings = + TypeNode.withReference( + VaporReference.builder() + .setName(ClassNames.getServiceSettingsClassName(service)) + .setPakkage(service.pakkage()) + .build()); + TypeNode serviceSettingsBuilder = + TypeNode.withReference( + VaporReference.builder() + .setPakkage(service.pakkage()) + .setName("Builder") + .setEnclosingClassNames(ClassNames.getServiceSettingsClassName(service)) + .build()); + + TypeNode bean = + TypeNode.withReference( + VaporReference.builder() + .setName("Bean") + .setPakkage("org.springframework.context.annotation") + .build()); + TypeNode autoConfiguration = + TypeNode.withReference( + VaporReference.builder() + .setName("AutoConfiguration") + .setPakkage("org.springframework.boot.autoconfigure") + .build()); + TypeNode enableConfigurationProperties = + TypeNode.withReference( + VaporReference.builder() + .setName("EnableConfigurationProperties") + .setPakkage("org.springframework.boot.context.properties") + .build()); + TypeNode conditionalOnMissingBean = + TypeNode.withReference( + VaporReference.builder() + .setName("ConditionalOnMissingBean") + .setPakkage("org.springframework.boot.autoconfigure.condition") + .build()); + + TypeNode conditionalOnProperty = + TypeNode.withReference( + VaporReference.builder() + .setName("ConditionalOnProperty") + .setPakkage("org.springframework.boot.autoconfigure.condition") + .build()); + TypeNode conditionalOnClass = + TypeNode.withReference( + VaporReference.builder() + .setName("ConditionalOnClass") + .setPakkage("org.springframework.boot.autoconfigure.condition") + .build()); + + TypeNode qualifier = + TypeNode.withReference( + VaporReference.builder() + .setName("Qualifier") + .setPakkage("org.springframework.beans.factory.annotation") + .build()); + + typeMap.put("CredentialsProvider", credentialsProvider); + typeMap.put(service.name() + "Properties", clientProperties); + typeMap.put(service.name() + "AutoConfig", clientAutoconfig); + typeMap.put("GcpProjectIdProvider", gcpProjectIdProvider); + typeMap.put("Credentials", credentials); + typeMap.put("DefaultCredentialsProvider", defaultCredentialsProvider); + typeMap.put("ServiceClient", serviceClient); + typeMap.put("ServiceSettings", serviceSettings); + typeMap.put("ServiceSettingsBuilder", serviceSettingsBuilder); + typeMap.put("Bean", bean); + typeMap.put("AutoConfiguration", autoConfiguration); + typeMap.put("EnableConfigurationProperties", enableConfigurationProperties); + typeMap.put("ConditionalOnMissingBean", conditionalOnMissingBean); + typeMap.put("ConditionalOnProperty", conditionalOnProperty); + typeMap.put("ConditionalOnClass", conditionalOnClass); + typeMap.put("Qualifier", qualifier); + typeMap.put("Log", LoggerUtils.getLoggerType()); + typeMap.put("LogFactory", LoggerUtils.getLoggerFactoryType()); + + return typeMap; + } + + private static String getThisClassName(String serviceName) { + return String.format(CLASS_NAME_PATTERN, serviceName); + } +} diff --git a/src/main/java/com/google/api/generator/spring/composer/SpringComposer.java b/src/main/java/com/google/api/generator/spring/composer/SpringComposer.java new file mode 100644 index 0000000000..b9f92c1f52 --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/composer/SpringComposer.java @@ -0,0 +1,125 @@ +// Copyright 2022 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.spring.composer; + +import com.google.api.core.BetaApi; +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.ClassDefinition; +import com.google.api.generator.gapic.composer.comment.CommentComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.model.GapicClass; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.GapicPackageInfo; +import com.google.api.generator.gapic.model.Transport; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Generated; + +public class SpringComposer { + + private static final TypeStore FIXED_TYPESTORE = createStaticTypes(); + + public static List composeServiceAutoConfigClasses(GapicContext context) { + List clazzes = new ArrayList<>(); + clazzes.addAll(generatePerServiceClasses(context)); + List clazzesWithHeader = addApacheLicense(clazzes); + return addExtraClassAnnotations(clazzesWithHeader); + } + + public static GapicPackageInfo composePackageInfo(GapicContext context) { + return addApacheLicense(SpringPackageInfoComposer.generatePackageInfo(context)); + } + + protected static List generatePerServiceClasses(GapicContext context) { + List clazzes = new ArrayList<>(); + context + .services() + .forEach( + s -> { + if (context.transport() == Transport.GRPC + || context.transport() == Transport.GRPC_REST) { + clazzes.add(SpringAutoConfigClassComposer.instance().generate(context, s)); + clazzes.add(SpringPropertiesClassComposer.instance().generate(context, s)); + } + }); + return clazzes; + } + + protected static List addApacheLicense(List gapicClassList) { + return gapicClassList.stream() + .map( + gapicClass -> { + ClassDefinition classWithHeader = + gapicClass + .classDefinition() + .toBuilder() + .setFileHeader(CommentComposer.APACHE_LICENSE_COMMENT) + .build(); + return GapicClass.create(gapicClass.kind(), classWithHeader); + }) + .collect(Collectors.toList()); + } + + protected static List addExtraClassAnnotations(List gapicClassList) { + AnnotationNode generatedAnnotation = + AnnotationNode.builder() + .setType(FIXED_TYPESTORE.get("Generated")) + .setDescription("by gapic-generator-java") + .build(); + AnnotationNode betaAnnotation = + AnnotationNode.builder() + .setType(FIXED_TYPESTORE.get("BetaApi")) + .setDescription("Autogenerated Spring autoconfiguration is not yet stable") + .build(); + return gapicClassList.stream() + .map( + gapicClass -> { + ImmutableList classAnnotations = + gapicClass.classDefinition().annotations(); + ImmutableList updatedAnnotations = + ImmutableList.builder() + .add(generatedAnnotation) + .add(betaAnnotation) + .addAll(classAnnotations) + .build(); + ClassDefinition classWithUpdatedAnnotations = + gapicClass + .classDefinition() + .toBuilder() + .setAnnotations(updatedAnnotations) + .build(); + + return GapicClass.create(gapicClass.kind(), classWithUpdatedAnnotations); + }) + .collect(Collectors.toList()); + } + + private static GapicPackageInfo addApacheLicense(GapicPackageInfo gapicPackageInfo) { + return GapicPackageInfo.with( + gapicPackageInfo + .packageInfo() + .toBuilder() + .setFileHeader(CommentComposer.APACHE_LICENSE_COMMENT) + .build()); + } + + private static TypeStore createStaticTypes() { + List> concreteClazzes = Arrays.asList(BetaApi.class, Generated.class); + return new TypeStore(concreteClazzes); + } +} diff --git a/src/main/java/com/google/api/generator/spring/composer/SpringPackageInfoComposer.java b/src/main/java/com/google/api/generator/spring/composer/SpringPackageInfoComposer.java new file mode 100644 index 0000000000..aa94bb3841 --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/composer/SpringPackageInfoComposer.java @@ -0,0 +1,55 @@ +// Copyright 2022 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.spring.composer; + +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.CommentStatement; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.JavaDocComment; +import com.google.api.generator.engine.ast.PackageInfoDefinition; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.GapicPackageInfo; +import com.google.api.generator.spring.utils.Utils; +import com.google.common.base.Preconditions; +import javax.annotation.Generated; + +public class SpringPackageInfoComposer { + private static final String PACKAGE_INFO_TITLE_PATTERN = + "Spring Boot auto-configurations for %s."; + + public static GapicPackageInfo generatePackageInfo(GapicContext context) { + Preconditions.checkState(!context.services().isEmpty(), "No services found to generate"); + PackageInfoDefinition packageInfo = + PackageInfoDefinition.builder() + .setPakkage(Utils.getSpringPackageName(Utils.getPackageName(context))) + .setHeaderCommentStatements(createPackageInfoJavadoc(context)) + .setAnnotations( + AnnotationNode.builder() + .setType(TypeNode.withReference(ConcreteReference.withClazz(Generated.class))) + .setDescription("by gapic-generator-java") + .build()) + .build(); + return GapicPackageInfo.with(packageInfo); + } + + private static CommentStatement createPackageInfoJavadoc(GapicContext context) { + JavaDocComment.Builder javaDocCommentBuilder = JavaDocComment.builder(); + javaDocCommentBuilder = + javaDocCommentBuilder.addComment( + String.format(PACKAGE_INFO_TITLE_PATTERN, Utils.getLibName(context))); + return CommentStatement.withComment(javaDocCommentBuilder.build()); + } +} diff --git a/src/main/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposer.java b/src/main/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposer.java new file mode 100644 index 0000000000..618f6f933b --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposer.java @@ -0,0 +1,385 @@ +// Copyright 2022 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.spring.composer; + +import static com.google.api.generator.engine.ast.NewObjectExpr.*; + +import com.google.api.gax.retrying.RetrySettings; +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.AstNode; +import com.google.api.generator.engine.ast.ClassDefinition; +import com.google.api.generator.engine.ast.ConcreteReference; +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.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.ThisObjectValue; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.engine.ast.VaporReference; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.common.ClassComposer; +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.GapicServiceConfig; +import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.spring.composer.comment.SpringPropertiesCommentComposer; +import com.google.api.generator.spring.utils.Utils; +import com.google.common.base.CaseFormat; +import com.google.common.base.Joiner; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class SpringPropertiesClassComposer implements ClassComposer { + private static final String CLASS_NAME_PATTERN = "%sSpringProperties"; + + private static final Map staticTypes = createStaticTypes(); + private static final String RETRY_PARAM_DEFINITIONS_VAR_NAME = "RETRY_PARAM_DEFINITIONS"; + + private static final SpringPropertiesClassComposer INSTANCE = new SpringPropertiesClassComposer(); + + public static SpringPropertiesClassComposer instance() { + return INSTANCE; + } + + @Override + public GapicClass generate(GapicContext context, Service service) { + String packageName = Utils.getSpringPackageName(service.pakkage()); + String className = String.format(CLASS_NAME_PATTERN, service.name()); + GapicServiceConfig gapicServiceConfig = context.serviceConfig(); + Map types = createDynamicTypes(service, packageName); + + // TODO: this is the prefix user will use to set properties, may need to change depending on + // branding. + AnnotationNode classAnnotationNode = + AnnotationNode.builder() + .setType(types.get("ConfigurationProperties")) + .setDescription(Utils.getSpringPropertyPrefix(service.pakkage(), service.name())) + .build(); + + ClassDefinition classDef = + ClassDefinition.builder() + .setHeaderCommentStatements( + SpringPropertiesCommentComposer.createClassHeaderComments( + className, service.name())) + .setPackageString(packageName) + .setName(className) + .setScope(ScopeNode.PUBLIC) + .setStatements(createMemberVariables(service, packageName, types, gapicServiceConfig)) + .setMethods(createGetterSetters(service, types, gapicServiceConfig)) + .setAnnotations(Arrays.asList(classAnnotationNode)) + .setImplementsTypes(Arrays.asList(types.get("CredentialsSupplier"))) + .build(); + return GapicClass.create(Kind.MAIN, classDef); + // return null; + } + + private static ExprStatement createMemberVarStatement( + String varName, + TypeNode varType, + boolean isFinal, + Expr defaultVal, + List annotationNodes) { + Variable memberVar = Variable.builder().setName(varName).setType(varType).build(); + VariableExpr memberVarExpr = + VariableExpr.builder() + .setVariable(memberVar) + .setScope(ScopeNode.PRIVATE) + .setAnnotations(annotationNodes == null ? Collections.emptyList() : annotationNodes) + .setIsDecl(true) + .setIsFinal(isFinal) + .build(); + + if (defaultVal == null) { + return ExprStatement.withExpr(memberVarExpr); + } + AssignmentExpr assignmentExpr = + AssignmentExpr.builder() + .setVariableExpr(memberVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(defaultVal) + .build(); + ExprStatement memberVarStatement = ExprStatement.withExpr(assignmentExpr); + + return memberVarStatement; + } + + private static List createMemberVariables( + Service service, + String packageName, + Map types, + GapicServiceConfig serviceConfig) { + + String serviceName = service.name(); + // @NestedConfigurationProperty + // private final Credentials credentials = new + // Credentials("https://www.googleapis.com/auth/cloud-language"); + NewObjectExpr defaultCredentialScopes = + builder() + .setType(types.get("Credentials")) + .setArguments( + service.oauthScopes().stream() + .map(x -> ValueExpr.withValue(StringObjectValue.withValue(x))) + .collect(Collectors.toList())) + .build(); + // Note that the annotations are set on the VariableExpr rather than the ExprStatement. + // The single annotation works fine here, + // but multiple annotations would be written to the same line + List credentialsAnnotations = + Arrays.asList(AnnotationNode.withType(types.get("NestedConfigurationProperty"))); + ExprStatement credentialsStatement = + createMemberVarStatement( + "credentials", + types.get("Credentials"), + true, + defaultCredentialScopes, + credentialsAnnotations); + + // private String quotaProjectId; + ExprStatement quotaProjectIdVarStatement = + createMemberVarStatement("quotaProjectId", TypeNode.STRING, false, null, null); + + // private Integer executorThreadCount; + ExprStatement executorThreadCountVarStatement = + createMemberVarStatement("executorThreadCount", TypeNode.INT_OBJECT, false, null, null); + + // private boolean useRest = false; + ExprStatement useRestVarStatement = + createMemberVarStatement("useRest", TypeNode.BOOLEAN, false, null, null); + + // + // private static final ImmutableMap RETRY_PARAM_DEFINITIONS; + + // declare each retry settings with its default value. use defaults from serviceConfig + TypeNode thisClassType = types.get(service.name() + "Properties"); + List retrySettings = + Utils.processRetrySettings( + service, + serviceConfig, + thisClassType, + (String propertyName) -> new ArrayList<>(), + (List methodAndPropertyName, Expr defaultVal) -> { + List getterAndSetter = new ArrayList<>(); + TypeNode propertyType = defaultVal.type(); + // TODO: safer cast? + if (propertyType.equals(TypeNode.DOUBLE)) { + propertyType = TypeNode.DOUBLE_OBJECT; + } + String propertyName = Joiner.on("").join(methodAndPropertyName); + ExprStatement retrySettingsStatement = + createMemberVarStatement(propertyName, propertyType, false, null, null); + getterAndSetter.add(retrySettingsStatement); + return getterAndSetter; + }, + (String propertyName) -> new ArrayList<>()); + + List statements = + retrySettings.stream().map(x -> (Statement) x).collect(Collectors.toList()); + + statements.add(0, useRestVarStatement); + statements.add(0, executorThreadCountVarStatement); + statements.add(0, quotaProjectIdVarStatement); + statements.add(0, credentialsStatement); + return statements; + } + + private static List createGetterSetters( + Service service, Map types, GapicServiceConfig gapicServiceConfig) { + + TypeNode thisClassType = types.get(service.name() + "Properties"); + List methodDefinitions = new ArrayList<>(); + + methodDefinitions.add( + createGetterMethod( + thisClassType, + "credentials", + types.get("Credentials"), + Arrays.asList(AnnotationNode.OVERRIDE))); + methodDefinitions.add( + createGetterMethod(thisClassType, "quotaProjectId", TypeNode.STRING, null)); + methodDefinitions.add(createSetterMethod(thisClassType, "quotaProjectId", TypeNode.STRING)); + methodDefinitions.add(createGetterMethod(thisClassType, "useRest", TypeNode.BOOLEAN, null)); + methodDefinitions.add( + createGetterMethod(thisClassType, "executorThreadCount", TypeNode.INT_OBJECT, null)); + methodDefinitions.add( + createSetterMethod(thisClassType, "executorThreadCount", TypeNode.INT_OBJECT)); + + List retrySettings = + Utils.processRetrySettings( + service, + gapicServiceConfig, + thisClassType, + (String propertyName) -> new ArrayList<>(), + (List methodAndPropertyName, Expr defaultVal) -> { + List getterAndSetter = new ArrayList<>(); + TypeNode propertyType = defaultVal.type(); + if (propertyType.equals(TypeNode.DOUBLE)) { + propertyType = TypeNode.DOUBLE_OBJECT; + } + String propertyName = Joiner.on("").join(methodAndPropertyName); + getterAndSetter.add( + createGetterMethod(thisClassType, propertyName, propertyType, null)); + getterAndSetter.add(createSetterMethod(thisClassType, propertyName, propertyType)); + return getterAndSetter; + }, + (String propertyName) -> new ArrayList<>()); + + methodDefinitions.addAll(retrySettings); + // TODO: This can be for future stages. for long running operations: + // for (Method method : service.methods()) { + // if (!method.hasLro()) { + // continue; + // } + // // + // com.google.api.generator.gapic.composer.common.RetrySettingsComposer.createLroSettingsBuilderExpr + // // %sOperationSettings + // } + + return methodDefinitions; + } + + private static MethodDefinition createGetterMethod( + TypeNode thisClassType, + String propertyName, + TypeNode returnType, + List annotationNodes) { + + Variable propertyVar = Variable.builder().setName(propertyName).setType(returnType).build(); + Expr thisExpr = ValueExpr.withValue(ThisObjectValue.withType(thisClassType)); + + VariableExpr propertyVariableExpr = + VariableExpr.withVariable(propertyVar).toBuilder().setExprReferenceExpr(thisExpr).build(); + + String methodName = "get" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, propertyName); + + return MethodDefinition.builder() + .setName(methodName) + .setScope(ScopeNode.PUBLIC) + .setReturnType(returnType) + .setAnnotations(annotationNodes == null ? Collections.emptyList() : annotationNodes) + .setReturnExpr(propertyVariableExpr) + .build(); + } + + private static MethodDefinition createSetterMethod( + TypeNode thisClassType, String propertyName, TypeNode returnType) { + Variable propertyVar = Variable.builder().setName(propertyName).setType(returnType).build(); + Expr thisExpr = ValueExpr.withValue(ThisObjectValue.withType(thisClassType)); + + AssignmentExpr propertyVarExpr = + AssignmentExpr.builder() + .setVariableExpr( + VariableExpr.withVariable(propertyVar) + .toBuilder() + .setExprReferenceExpr(thisExpr) + .build()) + .setValueExpr(VariableExpr.withVariable(propertyVar)) + .build(); + + String methodName = "set" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, propertyName); + + return MethodDefinition.builder() + .setName(methodName) + .setScope(ScopeNode.PUBLIC) + .setReturnType(TypeNode.VOID) + .setArguments(VariableExpr.builder().setVariable(propertyVar).setIsDecl(true).build()) + .setBody(Arrays.asList(ExprStatement.withExpr(propertyVarExpr))) + .build(); + } + + private static Map createDynamicTypes(Service service, String packageName) { + Map typeMap = + Arrays.asList(CLASS_NAME_PATTERN).stream() + .collect( + Collectors.toMap( + p -> String.format(p, service.name()), + p -> + TypeNode.withReference( + VaporReference.builder() + .setName(String.format(p, service.name())) + .setPakkage(packageName) + .build()))); + TypeNode clientProperties = + TypeNode.withReference( + VaporReference.builder() + .setName(service.name() + "SpringProperties") + .setPakkage(packageName) + .build()); + + // import com.google.cloud.spring.core.Credentials; + TypeNode credentials = + TypeNode.withReference( + VaporReference.builder() + .setName("Credentials") + .setPakkage("com.google.cloud.spring.core") + .build()); + + // import com.google.cloud.spring.core.CredentialsSupplier; + TypeNode credentialsSupplier = + TypeNode.withReference( + VaporReference.builder() + .setName("CredentialsSupplier") + .setPakkage("com.google.cloud.spring.core") + .build()); + // import org.springframework.boot.context.properties.ConfigurationProperties; + TypeNode configurationProperties = + TypeNode.withReference( + VaporReference.builder() + .setName("ConfigurationProperties") + .setPakkage("org.springframework.boot.context.properties") + .build()); + + // import org.springframework.boot.context.properties.NestedConfigurationProperty; + TypeNode nestedConfigurationProperty = + TypeNode.withReference( + VaporReference.builder() + .setName("NestedConfigurationProperty") + .setPakkage("org.springframework.boot.context.properties") + .build()); + + // import org.threeten.bp.Duration; + TypeNode duration = + TypeNode.withReference( + VaporReference.builder().setName("Duration").setPakkage("org.threeten.bp").build()); + + typeMap.put(service.name() + "Properties", clientProperties); + typeMap.put("Credentials", credentials); + typeMap.put("Duration", duration); + typeMap.put("CredentialsSupplier", credentialsSupplier); + typeMap.put("ConfigurationProperties", configurationProperties); + typeMap.put("NestedConfigurationProperty", nestedConfigurationProperty); + + return typeMap; + } + + private static Map createStaticTypes() { + List concreteClazzes = + Arrays.asList(RetrySettings.class, org.threeten.bp.Duration.class); + return concreteClazzes.stream() + .collect( + Collectors.toMap( + c -> c.getSimpleName(), + c -> TypeNode.withReference(ConcreteReference.withClazz(c)))); + } +} diff --git a/src/main/java/com/google/api/generator/spring/composer/comment/SpringAutoconfigCommentComposer.java b/src/main/java/com/google/api/generator/spring/composer/comment/SpringAutoconfigCommentComposer.java new file mode 100644 index 0000000000..171ae79909 --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/composer/comment/SpringAutoconfigCommentComposer.java @@ -0,0 +1,106 @@ +// Copyright 2022 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.spring.composer.comment; + +import com.google.api.generator.engine.ast.CommentStatement; +import com.google.api.generator.engine.ast.JavaDocComment; +import com.google.api.generator.gapic.composer.comment.CommentComposer; +import com.google.common.base.CaseFormat; +import java.util.Arrays; +import java.util.List; + +public class SpringAutoconfigCommentComposer { + + private static final String CLASS_HEADER_SUMMARY_PATTERN = + "Auto-configuration for {@link %sClient}."; + private static final String CLASS_HEADER_GENERAL_DESCRIPTION = + "Provides auto-configuration for Spring Boot"; + private static final String CLASS_HEADER_DEFAULTS_DESCRIPTION = + "The default instance has everything set to sensible defaults:"; + private static final String CLASS_HEADER_DEFAULTS_CREDENTIALS_DESCRIPTION = + "Credentials are acquired automatically through Application Default Credentials."; + private static final String CLASS_HEADER_DEFAULTS_TRANSPORT_DESCRIPTION = + "The default transport provider is used."; + private static final String CLASS_HEADER_DEFAULTS_RETRIES_DESCRIPTION = + "Retries are configured for idempotent methods but not for non-idempotent methods."; + + public static final String CREDENTIALS_PROVIDER_GENERAL_DESCRIPTION = + "Obtains the default credentials provider. The used key will be obtained from Spring Boot " + + "configuration data files."; + + public static final String TRANSPORT_CHANNEL_PROVIDER_GENERAL_DESCRIPTION = + "Returns the default channel provider. The default is gRPC and will default to it unless the " + + "useRest option is provided to use HTTP transport instead"; + public static final String CLIENT_BEAN_GENERAL_DESCRIPTION = + "Provides a %sClient bean configured to " + + "use the default credentials provider (obtained with %sCredentials()) and its default " + + "transport channel provider (%s()). It also configures the quota project ID if provided. It " + + "will configure an executor provider in case there is more than one thread configured " + + "in the client "; + + public static final String CLIENT_BEAN_RETRY_SETTINGS_DESCRIPTION = + "Individual retry settings " + + "are configured as well. It will use the relevant client library's default retry " + + "settings when they are not specified in %s."; + + public SpringAutoconfigCommentComposer() {} + + public static List createClassHeaderComments( + String configuredClassName, String serviceName) { + + JavaDocComment.Builder javaDocCommentBuilder = + JavaDocComment.builder() + .addUnescapedComment(String.format(CLASS_HEADER_SUMMARY_PATTERN, serviceName)) + .addParagraph(CLASS_HEADER_GENERAL_DESCRIPTION) + .addParagraph(CLASS_HEADER_DEFAULTS_DESCRIPTION) + .addUnorderedList( + Arrays.asList( + CLASS_HEADER_DEFAULTS_TRANSPORT_DESCRIPTION, + CLASS_HEADER_DEFAULTS_CREDENTIALS_DESCRIPTION, + CLASS_HEADER_DEFAULTS_RETRIES_DESCRIPTION)); + + return Arrays.asList( + CommentComposer.AUTO_GENERATED_CLASS_COMMENT, + CommentStatement.withComment(javaDocCommentBuilder.build())); + } + + public static CommentStatement createCredentialsProviderBeanComment() { + return CommentStatement.withComment( + JavaDocComment.builder().addParagraph(CREDENTIALS_PROVIDER_GENERAL_DESCRIPTION).build()); + } + + public static CommentStatement createTransportChannelProviderComment() { + return CommentStatement.withComment( + JavaDocComment.builder() + .addParagraph(TRANSPORT_CHANNEL_PROVIDER_GENERAL_DESCRIPTION) + .build()); + } + + public static CommentStatement createClientBeanComment( + String serviceName, String propertiesClazzName, String channelProviderName) { + String credentialsBaseName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, serviceName); + return CommentStatement.withComment( + JavaDocComment.builder() + .addParagraph( + String.format( + CLIENT_BEAN_GENERAL_DESCRIPTION, + serviceName, + credentialsBaseName, + channelProviderName)) + .addParagraph( + String.format(CLIENT_BEAN_RETRY_SETTINGS_DESCRIPTION, propertiesClazzName)) + .build()); + } +} diff --git a/src/main/java/com/google/api/generator/spring/composer/comment/SpringPropertiesCommentComposer.java b/src/main/java/com/google/api/generator/spring/composer/comment/SpringPropertiesCommentComposer.java new file mode 100644 index 0000000000..6d05240eea --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/composer/comment/SpringPropertiesCommentComposer.java @@ -0,0 +1,37 @@ +// Copyright 2022 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.spring.composer.comment; + +import com.google.api.generator.engine.ast.CommentStatement; +import com.google.api.generator.engine.ast.JavaDocComment; +import com.google.api.generator.gapic.composer.comment.CommentComposer; +import java.util.Arrays; +import java.util.List; + +public class SpringPropertiesCommentComposer { + private static final String CLASS_HEADER_GENERAL_DESCRIPTION = + "Provides default property values for %s client bean"; + + public static List createClassHeaderComments( + String configuredClassName, String serviceName) { + + JavaDocComment.Builder javaDocCommentBuilder = + JavaDocComment.builder() + .addParagraph(String.format(CLASS_HEADER_GENERAL_DESCRIPTION, serviceName)); + return Arrays.asList( + CommentComposer.AUTO_GENERATED_CLASS_COMMENT, + CommentStatement.withComment(javaDocCommentBuilder.build())); + } +} diff --git a/src/main/java/com/google/api/generator/spring/utils/LoggerUtils.java b/src/main/java/com/google/api/generator/spring/utils/LoggerUtils.java new file mode 100644 index 0000000000..31cce78ed2 --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/utils/LoggerUtils.java @@ -0,0 +1,109 @@ +// Copyright 2022 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.spring.utils; + +import com.google.api.generator.engine.ast.ArithmeticOperationExpr; +import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.ExprStatement; +import com.google.api.generator.engine.ast.MethodInvocationExpr; +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.VaporReference; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class LoggerUtils { + + public static Statement getLoggerDeclarationExpr(String className, Map types) { + + Variable loggerVar = Variable.builder().setName("LOGGER").setType(types.get("Log")).build(); + VariableExpr loggerExpr = + VariableExpr.builder() + .setVariable(loggerVar) + .setScope(ScopeNode.PRIVATE) + .setIsStatic(true) + .setIsFinal(true) + .setIsDecl(true) + .build(); + + MethodInvocationExpr loggerValueExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(types.get("LogFactory")) + .setMethodName("getLog") + .setArguments( + VariableExpr.builder() + .setVariable( + Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) + .setStaticReferenceType(types.get(className)) + .build()) + .setReturnType(types.get("Log")) + .build(); + + AssignmentExpr loggerAssignmentExpr = + AssignmentExpr.builder().setVariableExpr(loggerExpr).setValueExpr(loggerValueExpr).build(); + + return ExprStatement.withExpr(loggerAssignmentExpr); + } + + public static ExprStatement createLoggerStatement(Expr value, Map types) { + Variable loggerVariable = + Variable.builder().setName("LOGGER").setType(types.get("Log")).build(); + MethodInvocationExpr loggerCallExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(VariableExpr.withVariable(loggerVariable)) + .setMethodName("info") + .setArguments(value) + .build(); + return ExprStatement.withExpr(loggerCallExpr); + } + + public static TypeNode getLoggerType() { + return createType("Log", "org.apache.commons.logging"); + } + + public static TypeNode getLoggerFactoryType() { + return createType("LogFactory", "org.apache.commons.logging"); + } + + private static TypeNode createType(String className, String pakkage) { + TypeNode loggerType = + TypeNode.withReference( + VaporReference.builder().setName(className).setPakkage(pakkage).build()); + return loggerType; + } + + public static Expr concatManyWithExprs(Expr... exprs) { + List exprList = Arrays.asList(exprs); + return concatManyWithExprsHelper(Optional.empty(), exprList); + } + + private static Expr concatManyWithExprsHelper(Optional current, List exprs) { + if (!current.isPresent()) { + return concatManyWithExprsHelper(Optional.of(exprs.get(0)), exprs.subList(1, exprs.size())); + } + if (exprs.size() == 1) { + return ArithmeticOperationExpr.concatWithExprs(current.get(), exprs.get(0)); + } + return ArithmeticOperationExpr.concatWithExprs( + current.get(), + concatManyWithExprsHelper(Optional.of(exprs.get(0)), exprs.subList(1, exprs.size()))); + } +} diff --git a/src/main/java/com/google/api/generator/spring/utils/Utils.java b/src/main/java/com/google/api/generator/spring/utils/Utils.java new file mode 100644 index 0000000000..dea2b743f3 --- /dev/null +++ b/src/main/java/com/google/api/generator/spring/utils/Utils.java @@ -0,0 +1,208 @@ +// Copyright 2022 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.spring.utils; + +import com.google.api.generator.engine.ast.AstNode; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.MethodInvocationExpr; +import com.google.api.generator.engine.ast.PrimitiveValue; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.GapicRetrySettings; +import com.google.api.generator.gapic.model.GapicServiceConfig; +import com.google.api.generator.gapic.model.Method; +import com.google.api.generator.gapic.model.Service; +import com.google.common.base.CaseFormat; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.protobuf.Duration; +import com.google.protobuf.util.Durations; +import io.grpc.serviceconfig.MethodConfig.RetryPolicy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +public class Utils { + private static final TypeStore FIXED_TYPESTORE = createStaticTypes(); + + private static final String BRAND_NAME = "spring.cloud.gcp"; + + public static String getLibName(GapicContext context) { + // Returns parsed name of client library + // This should only be used in descriptive context, such as metadata and javadocs + + // Option 1: Use title from service yaml if available (e.g. Client Library Showcase API) + // However, service yaml is optionally parsed and not always available + // if (context.hasServiceYamlProto() + // && !Strings.isNullOrEmpty(context.serviceYamlProto().getTitle())) { + // return context.serviceYamlProto().getTitle(); + // } + + // Option 2: Parse ApiShortName from service proto's package name (e.g. + // com.google.cloud.vision.v1) + // This approach assumes pattern of xx.[...].xx.lib-name.v[version], which may have + // discrepancies + // eg. for vision proto: "com.google.cloud.vision.v1" + // https://github.com/googleapis/java-vision/blob/main/proto-google-cloud-vision-v1/src/main/proto/google/cloud/vision/v1/image_annotator.proto#L36 + List pakkagePhrases = Splitter.on(".").splitToList(getPackageName(context)); + return pakkagePhrases.get(pakkagePhrases.size() - 2); + + // Option 3: Parse ApiShortName from service proto's default host (e.g. vision.googleapis.com) + // TODO: Replace implementation above to reuse parsing logic from SampleGen: + // https://github.com/googleapis/gapic-generator-java/pull/1040 + } + + public static String getPackageName(GapicContext context) { + // Returns package name of client library + return context.services().get(0).pakkage(); + } + + public static String getSpringPackageName(String packageName) { + // Returns package name of generated spring autoconfiguration library + // e.g. for vision: com.google.cloud.vision.v1.spring + return packageName + ".spring"; + } + + public static String getSpringPropertyPrefix(String packageName, String serviceName) { + // Returns unique prefix for setting properties and enabling autoconfiguration + // Pattern: [package-name].spring.auto.[service-name] + // e.g. for vision's ImageAnnotator service: + // com.google.cloud.vision.v1.spring.auto.image-annotator + // Service name is converted to lower hyphen as required by ConfigurationPropertyName + // https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/context/properties/source/ConfigurationPropertyName.html + return packageName + + ".spring.auto." + + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, serviceName); + } + + public static List processRetrySettings( + Service service, + GapicServiceConfig gapicServiceConfig, + TypeNode thisClassType, + Function> perMethodFuncBeforeSettings, + BiFunction, Expr, List> processFunc, + Function> perMethodFuncAfterSettings) { + List resultList = new ArrayList<>(); + for (Method method : service.methods()) { + String methodName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, method.name()); + String retryParamName = gapicServiceConfig.getRetryParamsName(service, method); + resultList.addAll(perMethodFuncBeforeSettings.apply(methodName)); + // follow logic in: + // com.google.api.generator.gapic.composer.common.RetrySettingsComposer.createRetrySettingsExprs + // Build the settings object for each config. + + String settingsName = retryParamName; + GapicRetrySettings settings = + gapicServiceConfig.getAllGapicRetrySettings(service).get(retryParamName); + RetryPolicy retryPolicy = settings.retryPolicy(); + if (settings.kind().equals(GapicRetrySettings.Kind.FULL)) { + Preconditions.checkState( + retryPolicy.hasInitialBackoff(), + String.format("initialBackoff not found for setting %s", settingsName)); + + resultList.addAll( + processFunc.apply( + Arrays.asList(methodName, "InitialRetryDelay"), + createDurationOfMillisExpr(toValExpr(retryPolicy.getInitialBackoff())))); + + resultList.addAll( + processFunc.apply( + Arrays.asList(methodName, "RetryDelayMultiplier"), + toValExpr(retryPolicy.getBackoffMultiplier()))); + + Preconditions.checkState( + retryPolicy.hasMaxBackoff(), + String.format("maxBackoff not found for setting %s", settingsName)); + + resultList.addAll( + processFunc.apply( + Arrays.asList(methodName, "MaxRetryDelay"), + createDurationOfMillisExpr(toValExpr(retryPolicy.getMaxBackoff())))); + } + + if (!settings.kind().equals(GapicRetrySettings.Kind.NONE)) { + + resultList.addAll( + processFunc.apply( + Arrays.asList(methodName, "InitialRpcTimeout"), + createDurationOfMillisExpr(toValExpr(settings.timeout())))); + } + + // This will always be done, no matter the type of the retry settings object. + resultList.addAll( + processFunc.apply( + Arrays.asList(methodName, "RpcTimeoutMultiplier"), + ValueExpr.withValue( + // this value is hardcoded in, risk of gapic- changes in future? + // com.google.api.generator.gapic.composer.common.RetrySettingsComposer.createRetrySettingsExprs + PrimitiveValue.builder().setType(TypeNode.DOUBLE).setValue("1.0").build()))); + + if (!settings.kind().equals(GapicRetrySettings.Kind.NONE)) { + for (String setterMethodName : Arrays.asList("MaxRpcTimeout", "TotalTimeout")) { + + resultList.addAll( + processFunc.apply( + Arrays.asList(methodName, setterMethodName), + createDurationOfMillisExpr(toValExpr(settings.timeout())))); + } + } + + resultList.addAll(perMethodFuncAfterSettings.apply(methodName)); + } + return resultList; + } + + private static ValueExpr toValExpr(long longValue) { + return ValueExpr.withValue( + PrimitiveValue.builder() + .setType(TypeNode.LONG) + .setValue(String.format("%dL", longValue)) + .build()); + } + + private static ValueExpr toValExpr(float floatValue) { + return toValExpr((double) floatValue); + } + + private static ValueExpr toValExpr(double val) { + return ValueExpr.withValue( + PrimitiveValue.builder() + .setType(TypeNode.DOUBLE) + .setValue(String.format("%.1f", val)) + .build()); + } + + private static ValueExpr toValExpr(Duration duration) { + return toValExpr(Durations.toMillis(duration)); + } + + private static TypeStore createStaticTypes() { + List> concreteClazzes = Arrays.asList(org.threeten.bp.Duration.class); + return new TypeStore(concreteClazzes); + } + + private static MethodInvocationExpr createDurationOfMillisExpr(ValueExpr valExpr) { + return MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("Duration")) + .setMethodName("ofMillis") + .setArguments(valExpr) + .setReturnType(FIXED_TYPESTORE.get("Duration")) + .build(); + } +} diff --git a/src/test/java/com/google/api/generator/spring/SpringWriterTest.java b/src/test/java/com/google/api/generator/spring/SpringWriterTest.java new file mode 100644 index 0000000000..3e71bdba33 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/SpringWriterTest.java @@ -0,0 +1,66 @@ +// Copyright 2022 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.spring; + +import static org.junit.Assert.assertEquals; + +import com.google.api.generator.gapic.composer.common.TestProtoLoader; +import com.google.api.generator.gapic.model.GapicContext; +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.Before; +import org.junit.Test; + +public class SpringWriterTest { + private static final String PARENT_COORDS = "com.google.cloud:generated-parent:3.5.0-SNAPSHOT"; + private GapicContext context; + + @Before + public void setUp() { + this.context = + TestProtoLoader.instance() + .parseShowcaseEcho() + .toBuilder() + .setSpringParentCoordinates(PARENT_COORDS) + .build(); + } + + @Test + public void buildAutoConfigRegistrationStringTest() { + String result = SpringWriter.buildAutoConfigRegistrationString(context); + String expected = "com.google.showcase.v1beta1.spring.EchoSpringAutoConfig"; + assertEquals(expected, result); + } + + @Test + public void buildSpringAdditionalMetadataJsonStringTest() { + String result = SpringWriter.buildSpringAdditionalMetadataJsonString(context); + String fileName = "SpringAdditionalMetadataJson.golden"; + Utils.saveCodegenToFile(this.getClass(), fileName, result); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), fileName); + Assert.assertCodeEquals(goldenFilePath, result); + } + + @Test + public void buildPomStringTest() { + String result = SpringWriter.buildPomString(context); + String fileName = "SpringPackagePom.golden"; + Utils.saveCodegenToFile(this.getClass(), fileName, result); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), fileName); + Assert.assertCodeEquals(goldenFilePath, result); + } +} diff --git a/src/test/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposerTest.java b/src/test/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposerTest.java new file mode 100644 index 0000000000..64f93c5df2 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposerTest.java @@ -0,0 +1,42 @@ +// Copyright 2022 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.spring.composer; + +import com.google.api.generator.gapic.composer.common.TestProtoLoader; +import com.google.api.generator.gapic.model.GapicClass; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.test.framework.Assert; +import org.junit.Before; +import org.junit.Test; + +public class SpringAutoConfigClassComposerTest { + private GapicContext context; + private Service echoProtoService; + + @Before + public void setUp() { + this.context = TestProtoLoader.instance().parseShowcaseEcho(); + this.echoProtoService = this.context.services().get(0); + } + + @Test + public void generateAutoConfigClazzTest() { + GapicClass clazz = + SpringAutoConfigClassComposer.instance().generate(this.context, this.echoProtoService); + String fileName = clazz.classDefinition().classIdentifier() + ".golden"; + Assert.assertGoldenClass(this.getClass(), clazz, fileName); + } +} diff --git a/src/test/java/com/google/api/generator/spring/composer/SpringComposerTest.java b/src/test/java/com/google/api/generator/spring/composer/SpringComposerTest.java new file mode 100644 index 0000000000..6f9493f4c2 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/SpringComposerTest.java @@ -0,0 +1,58 @@ +// Copyright 2022 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.spring.composer; + +import com.google.api.generator.engine.writer.JavaWriterVisitor; +import com.google.api.generator.gapic.composer.common.TestProtoLoader; +import com.google.api.generator.gapic.model.GapicClass; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.GapicPackageInfo; +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 java.util.List; +import org.junit.Before; +import org.junit.Test; + +public class SpringComposerTest { + private GapicContext context; + + @Before + public void setUp() { + this.context = TestProtoLoader.instance().parseShowcaseEcho(); + } + + @Test + public void spring_composer_test() { + + List gapicClasses = SpringComposer.composeServiceAutoConfigClasses(context); + GapicPackageInfo packageInfo = SpringComposer.composePackageInfo(context); + + // write to verify result for now + for (GapicClass gapicClazz : gapicClasses) { + String fileName = gapicClazz.classDefinition().classIdentifier() + "Full.golden"; + Assert.assertGoldenClass(this.getClass(), gapicClazz, fileName); + } + + String packageInfoFileName = "SpringPackageInfoFull.golden"; + JavaWriterVisitor visitor = new JavaWriterVisitor(); + packageInfo.packageInfo().accept(visitor); + Utils.saveCodegenToFile(this.getClass(), packageInfoFileName, visitor.write()); + Path packageInfoGoldenFilePath = + Paths.get(Utils.getGoldenDir(this.getClass()), packageInfoFileName); + Assert.assertCodeEquals(packageInfoGoldenFilePath, visitor.write()); + } +} diff --git a/src/test/java/com/google/api/generator/spring/composer/SpringPackageInfoComposerTest.java b/src/test/java/com/google/api/generator/spring/composer/SpringPackageInfoComposerTest.java new file mode 100644 index 0000000000..9a044c0c15 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/SpringPackageInfoComposerTest.java @@ -0,0 +1,47 @@ +// Copyright 2022 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.spring.composer; + +import com.google.api.generator.engine.writer.JavaWriterVisitor; +import com.google.api.generator.gapic.composer.common.TestProtoLoader; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.GapicPackageInfo; +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.Before; +import org.junit.Test; + +public class SpringPackageInfoComposerTest { + private GapicContext context; + + @Before + public void setUp() { + this.context = TestProtoLoader.instance().parseShowcaseEcho(); + } + + @Test + public void generateSpringPackageInfoTest() { + GapicPackageInfo packageInfo = SpringPackageInfoComposer.generatePackageInfo(this.context); + JavaWriterVisitor visitor = new JavaWriterVisitor(); + packageInfo.packageInfo().accept(visitor); + String fileName = "SpringPackageInfo.golden"; + + Utils.saveCodegenToFile(this.getClass(), fileName, visitor.write()); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), fileName); + Assert.assertCodeEquals(goldenFilePath, visitor.write()); + } +} diff --git a/src/test/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposerTest.java b/src/test/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposerTest.java new file mode 100644 index 0000000000..f19298c067 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposerTest.java @@ -0,0 +1,42 @@ +// Copyright 2022 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.spring.composer; + +import com.google.api.generator.gapic.composer.common.TestProtoLoader; +import com.google.api.generator.gapic.model.GapicClass; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.test.framework.Assert; +import org.junit.Before; +import org.junit.Test; + +public class SpringPropertiesClassComposerTest { + private GapicContext context; + private Service echoProtoService; + + @Before + public void setUp() { + this.context = TestProtoLoader.instance().parseShowcaseEcho(); + this.echoProtoService = this.context.services().get(0); + } + + @Test + public void generateAutoConfigClazzTest() { + GapicClass clazz = + SpringPropertiesClassComposer.instance().generate(this.context, this.echoProtoService); + String fileName = clazz.classDefinition().classIdentifier() + ".golden"; + Assert.assertGoldenClass(this.getClass(), clazz, fileName); + } +} diff --git a/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringAutoConfiguration.golden b/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringAutoConfiguration.golden new file mode 100644 index 0000000000..e25e7ec599 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringAutoConfiguration.golden @@ -0,0 +1,436 @@ +package com.google.showcase.v1beta1.spring; + +import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.core.ExecutorProvider; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.retrying.RetrySettings; +import com.google.api.gax.rpc.TransportChannelProvider; +import com.google.cloud.spring.core.DefaultCredentialsProvider; +import com.google.showcase.v1beta1.EchoClient; +import com.google.showcase.v1beta1.EchoSettings; +import java.io.IOException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.threeten.bp.Duration; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Auto-configuration for {@link EchoClient}. + * + *

Provides auto-configuration for Spring Boot + * + *

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

    + *
  • The default transport provider is used. + *
  • Credentials are acquired automatically through Application Default Credentials. + *
  • Retries are configured for idempotent methods but not for non-idempotent methods. + *
+ */ +@AutoConfiguration +@ConditionalOnClass(EchoClient.class) +@ConditionalOnProperty( + value = "com.google.showcase.v1beta1.spring.auto.echo.enabled", + matchIfMissing = false) +@EnableConfigurationProperties(EchoSpringProperties.class) +public class EchoSpringAutoConfiguration { + private final EchoSpringProperties clientProperties; + private static final Log LOGGER = LogFactory.getLog(EchoSpringAutoConfig.class); + + protected EchoSpringAutoConfiguration(EchoSpringProperties clientProperties) { + this.clientProperties = clientProperties; + } + + /** + * Obtains the default credentials provider. The used key will be obtained from Spring Boot + * configuration data files. + */ + @Bean + @ConditionalOnMissingBean + public CredentialsProvider echoCredentials() throws IOException { + return ((CredentialsProvider) new DefaultCredentialsProvider(this.clientProperties)); + } + + /** + * Returns the default channel provider. The default is gRPC and will default to it unless the + * useRest option is provided to use HTTP transport instead + */ + @Bean + @ConditionalOnMissingBean + public TransportChannelProvider defaultEchoTransportChannelProvider() { + return EchoSettings.defaultTransportChannelProvider(); + } + + /** + * Provides a EchoClient bean configured to use the default credentials provider (obtained with + * echoCredentials()) and its default transport channel provider + * (defaultEchoTransportChannelProvider()). It also configures the quota project ID if provided. + * It will configure an executor provider in case there is more than one thread configured in the + * client + * + *

Individual retry settings are configured as well. It will use the relevant client library's + * default retry settings when they are not specified in EchoProperties. + */ + @Bean + @ConditionalOnMissingBean + public EchoClient echoClient( + @Qualifier("echoCredentials") CredentialsProvider credentialsProvider, + @Qualifier("defaultEchoTransportChannelProvider") + TransportChannelProvider defaultTransportChannelProvider) + throws IOException { + EchoSettings.Builder clientSettingsBuilder = + EchoSettings.newBuilder() + .setCredentialsProvider(credentialsProvider) + .setTransportChannelProvider(defaultTransportChannelProvider) + .setHeaderProvider(); + if (this.clientProperties.getQuotaProjectId() != null) { + clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); + LOGGER.info( + "Quota project id set to " + + this.clientProperties.getQuotaProjectId() + + ", this overrides project id from credentials."); + } + if (this.clientProperties.getExecutorThreadCount() != null) { + ExecutorProvider executorProvider = + EchoSettings.defaultExecutorProviderBuilder() + .setExecutorThreadCount(this.clientProperties.getExecutorThreadCount()) + .build(); + clientSettingsBuilder.setBackgroundExecutorProvider(executorProvider); + LOGGER.info( + "Background executor thread count is " + this.clientProperties.getExecutorThreadCount()); + } + if (this.clientProperties.getUseRest()) { + clientSettingsBuilder.setTransportChannelProvider( + EchoSettings.defaultHttpJsonTransportProviderBuilder().build()); + LOGGER.info("Using HTTP transport channel"); + } + RetrySettings.Builder echoRetrySettingBuilder = + clientSettingsBuilder.echoSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getEchoInitialRetryDelay() != null) { + echoRetrySettingBuilder.setInitialRetryDelay( + this.clientProperties.getEchoInitialRetryDelay()); + LOGGER.info( + "EchoInitialRetryDelay set to " + this.clientProperties.getEchoInitialRetryDelay()); + } + if (this.clientProperties.getEchoRetryDelayMultiplier() != null) { + echoRetrySettingBuilder.setRetryDelayMultiplier( + this.clientProperties.getEchoRetryDelayMultiplier()); + LOGGER.info( + "EchoRetryDelayMultiplier set to " + this.clientProperties.getEchoRetryDelayMultiplier()); + } + if (this.clientProperties.getEchoMaxRetryDelay() != null) { + echoRetrySettingBuilder.setMaxRetryDelay(this.clientProperties.getEchoMaxRetryDelay()); + LOGGER.info("EchoMaxRetryDelay set to " + this.clientProperties.getEchoMaxRetryDelay()); + } + if (this.clientProperties.getEchoInitialRpcTimeout() != null) { + echoRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getEchoInitialRpcTimeout()); + LOGGER.info( + "EchoInitialRpcTimeout set to " + this.clientProperties.getEchoInitialRpcTimeout()); + } + if (this.clientProperties.getEchoRpcTimeoutMultiplier() != null) { + echoRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getEchoRpcTimeoutMultiplier()); + LOGGER.info( + "EchoRpcTimeoutMultiplier set to " + this.clientProperties.getEchoRpcTimeoutMultiplier()); + } + if (this.clientProperties.getEchoMaxRpcTimeout() != null) { + echoRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getEchoMaxRpcTimeout()); + LOGGER.info("EchoMaxRpcTimeout set to " + this.clientProperties.getEchoMaxRpcTimeout()); + } + if (this.clientProperties.getEchoTotalTimeout() != null) { + echoRetrySettingBuilder.setTotalTimeout(this.clientProperties.getEchoTotalTimeout()); + LOGGER.info("EchoTotalTimeout set to " + this.clientProperties.getEchoTotalTimeout()); + } + clientSettingsBuilder.echoSettings().setRetrySettings(echoRetrySettingBuilder.build()); + RetrySettings.Builder expandRetrySettingBuilder = + clientSettingsBuilder.expandSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getExpandInitialRetryDelay() != null) { + expandRetrySettingBuilder.setInitialRetryDelay( + this.clientProperties.getExpandInitialRetryDelay()); + LOGGER.info( + "ExpandInitialRetryDelay set to " + this.clientProperties.getExpandInitialRetryDelay()); + } + if (this.clientProperties.getExpandRetryDelayMultiplier() != null) { + expandRetrySettingBuilder.setRetryDelayMultiplier( + this.clientProperties.getExpandRetryDelayMultiplier()); + LOGGER.info( + "ExpandRetryDelayMultiplier set to " + + this.clientProperties.getExpandRetryDelayMultiplier()); + } + if (this.clientProperties.getExpandMaxRetryDelay() != null) { + expandRetrySettingBuilder.setMaxRetryDelay(this.clientProperties.getExpandMaxRetryDelay()); + LOGGER.info("ExpandMaxRetryDelay set to " + this.clientProperties.getExpandMaxRetryDelay()); + } + if (this.clientProperties.getExpandInitialRpcTimeout() != null) { + expandRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getExpandInitialRpcTimeout()); + LOGGER.info( + "ExpandInitialRpcTimeout set to " + this.clientProperties.getExpandInitialRpcTimeout()); + } + if (this.clientProperties.getExpandRpcTimeoutMultiplier() != null) { + expandRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getExpandRpcTimeoutMultiplier()); + LOGGER.info( + "ExpandRpcTimeoutMultiplier set to " + + this.clientProperties.getExpandRpcTimeoutMultiplier()); + } + if (this.clientProperties.getExpandMaxRpcTimeout() != null) { + expandRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getExpandMaxRpcTimeout()); + LOGGER.info("ExpandMaxRpcTimeout set to " + this.clientProperties.getExpandMaxRpcTimeout()); + } + if (this.clientProperties.getExpandTotalTimeout() != null) { + expandRetrySettingBuilder.setTotalTimeout(this.clientProperties.getExpandTotalTimeout()); + LOGGER.info("ExpandTotalTimeout set to " + this.clientProperties.getExpandTotalTimeout()); + } + clientSettingsBuilder.expandSettings().setRetrySettings(expandRetrySettingBuilder.build()); + RetrySettings.Builder collectRetrySettingBuilder = + clientSettingsBuilder.collectSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getCollectInitialRpcTimeout() != null) { + collectRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getCollectInitialRpcTimeout()); + LOGGER.info( + "CollectInitialRpcTimeout set to " + this.clientProperties.getCollectInitialRpcTimeout()); + } + if (this.clientProperties.getCollectRpcTimeoutMultiplier() != null) { + collectRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getCollectRpcTimeoutMultiplier()); + LOGGER.info( + "CollectRpcTimeoutMultiplier set to " + + this.clientProperties.getCollectRpcTimeoutMultiplier()); + } + if (this.clientProperties.getCollectMaxRpcTimeout() != null) { + collectRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getCollectMaxRpcTimeout()); + LOGGER.info("CollectMaxRpcTimeout set to " + this.clientProperties.getCollectMaxRpcTimeout()); + } + if (this.clientProperties.getCollectTotalTimeout() != null) { + collectRetrySettingBuilder.setTotalTimeout(this.clientProperties.getCollectTotalTimeout()); + LOGGER.info("CollectTotalTimeout set to " + this.clientProperties.getCollectTotalTimeout()); + } + clientSettingsBuilder.collectSettings().setRetrySettings(collectRetrySettingBuilder.build()); + RetrySettings.Builder chatRetrySettingBuilder = + clientSettingsBuilder.chatSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getChatInitialRpcTimeout() != null) { + chatRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getChatInitialRpcTimeout()); + LOGGER.info( + "ChatInitialRpcTimeout set to " + this.clientProperties.getChatInitialRpcTimeout()); + } + if (this.clientProperties.getChatRpcTimeoutMultiplier() != null) { + chatRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getChatRpcTimeoutMultiplier()); + LOGGER.info( + "ChatRpcTimeoutMultiplier set to " + this.clientProperties.getChatRpcTimeoutMultiplier()); + } + if (this.clientProperties.getChatMaxRpcTimeout() != null) { + chatRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getChatMaxRpcTimeout()); + LOGGER.info("ChatMaxRpcTimeout set to " + this.clientProperties.getChatMaxRpcTimeout()); + } + if (this.clientProperties.getChatTotalTimeout() != null) { + chatRetrySettingBuilder.setTotalTimeout(this.clientProperties.getChatTotalTimeout()); + LOGGER.info("ChatTotalTimeout set to " + this.clientProperties.getChatTotalTimeout()); + } + clientSettingsBuilder.chatSettings().setRetrySettings(chatRetrySettingBuilder.build()); + RetrySettings.Builder chatAgainRetrySettingBuilder = + clientSettingsBuilder.chatAgainSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getChatAgainInitialRpcTimeout() != null) { + chatAgainRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getChatAgainInitialRpcTimeout()); + LOGGER.info( + "ChatAgainInitialRpcTimeout set to " + + this.clientProperties.getChatAgainInitialRpcTimeout()); + } + if (this.clientProperties.getChatAgainRpcTimeoutMultiplier() != null) { + chatAgainRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getChatAgainRpcTimeoutMultiplier()); + LOGGER.info( + "ChatAgainRpcTimeoutMultiplier set to " + + this.clientProperties.getChatAgainRpcTimeoutMultiplier()); + } + if (this.clientProperties.getChatAgainMaxRpcTimeout() != null) { + chatAgainRetrySettingBuilder.setMaxRpcTimeout( + this.clientProperties.getChatAgainMaxRpcTimeout()); + LOGGER.info( + "ChatAgainMaxRpcTimeout set to " + this.clientProperties.getChatAgainMaxRpcTimeout()); + } + if (this.clientProperties.getChatAgainTotalTimeout() != null) { + chatAgainRetrySettingBuilder.setTotalTimeout( + this.clientProperties.getChatAgainTotalTimeout()); + LOGGER.info( + "ChatAgainTotalTimeout set to " + this.clientProperties.getChatAgainTotalTimeout()); + } + clientSettingsBuilder + .chatAgainSettings() + .setRetrySettings(chatAgainRetrySettingBuilder.build()); + RetrySettings.Builder pagedExpandRetrySettingBuilder = + clientSettingsBuilder.pagedExpandSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getPagedExpandInitialRetryDelay() != null) { + pagedExpandRetrySettingBuilder.setInitialRetryDelay( + this.clientProperties.getPagedExpandInitialRetryDelay()); + LOGGER.info( + "PagedExpandInitialRetryDelay set to " + + this.clientProperties.getPagedExpandInitialRetryDelay()); + } + if (this.clientProperties.getPagedExpandRetryDelayMultiplier() != null) { + pagedExpandRetrySettingBuilder.setRetryDelayMultiplier( + this.clientProperties.getPagedExpandRetryDelayMultiplier()); + LOGGER.info( + "PagedExpandRetryDelayMultiplier set to " + + this.clientProperties.getPagedExpandRetryDelayMultiplier()); + } + if (this.clientProperties.getPagedExpandMaxRetryDelay() != null) { + pagedExpandRetrySettingBuilder.setMaxRetryDelay( + this.clientProperties.getPagedExpandMaxRetryDelay()); + LOGGER.info( + "PagedExpandMaxRetryDelay set to " + this.clientProperties.getPagedExpandMaxRetryDelay()); + } + if (this.clientProperties.getPagedExpandInitialRpcTimeout() != null) { + pagedExpandRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getPagedExpandInitialRpcTimeout()); + LOGGER.info( + "PagedExpandInitialRpcTimeout set to " + + this.clientProperties.getPagedExpandInitialRpcTimeout()); + } + if (this.clientProperties.getPagedExpandRpcTimeoutMultiplier() != null) { + pagedExpandRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getPagedExpandRpcTimeoutMultiplier()); + LOGGER.info( + "PagedExpandRpcTimeoutMultiplier set to " + + this.clientProperties.getPagedExpandRpcTimeoutMultiplier()); + } + if (this.clientProperties.getPagedExpandMaxRpcTimeout() != null) { + pagedExpandRetrySettingBuilder.setMaxRpcTimeout( + this.clientProperties.getPagedExpandMaxRpcTimeout()); + LOGGER.info( + "PagedExpandMaxRpcTimeout set to " + this.clientProperties.getPagedExpandMaxRpcTimeout()); + } + if (this.clientProperties.getPagedExpandTotalTimeout() != null) { + pagedExpandRetrySettingBuilder.setTotalTimeout( + this.clientProperties.getPagedExpandTotalTimeout()); + LOGGER.info( + "PagedExpandTotalTimeout set to " + this.clientProperties.getPagedExpandTotalTimeout()); + } + clientSettingsBuilder + .pagedExpandSettings() + .setRetrySettings(pagedExpandRetrySettingBuilder.build()); + RetrySettings.Builder simplePagedExpandRetrySettingBuilder = + clientSettingsBuilder.simplePagedExpandSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getSimplePagedExpandInitialRpcTimeout() != null) { + simplePagedExpandRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getSimplePagedExpandInitialRpcTimeout()); + LOGGER.info( + "SimplePagedExpandInitialRpcTimeout set to " + + this.clientProperties.getSimplePagedExpandInitialRpcTimeout()); + } + if (this.clientProperties.getSimplePagedExpandRpcTimeoutMultiplier() != null) { + simplePagedExpandRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getSimplePagedExpandRpcTimeoutMultiplier()); + LOGGER.info( + "SimplePagedExpandRpcTimeoutMultiplier set to " + + this.clientProperties.getSimplePagedExpandRpcTimeoutMultiplier()); + } + if (this.clientProperties.getSimplePagedExpandMaxRpcTimeout() != null) { + simplePagedExpandRetrySettingBuilder.setMaxRpcTimeout( + this.clientProperties.getSimplePagedExpandMaxRpcTimeout()); + LOGGER.info( + "SimplePagedExpandMaxRpcTimeout set to " + + this.clientProperties.getSimplePagedExpandMaxRpcTimeout()); + } + if (this.clientProperties.getSimplePagedExpandTotalTimeout() != null) { + simplePagedExpandRetrySettingBuilder.setTotalTimeout( + this.clientProperties.getSimplePagedExpandTotalTimeout()); + LOGGER.info( + "SimplePagedExpandTotalTimeout set to " + + this.clientProperties.getSimplePagedExpandTotalTimeout()); + } + clientSettingsBuilder + .simplePagedExpandSettings() + .setRetrySettings(simplePagedExpandRetrySettingBuilder.build()); + RetrySettings.Builder waitRetrySettingBuilder = + clientSettingsBuilder.waitSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getWaitInitialRpcTimeout() != null) { + waitRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getWaitInitialRpcTimeout()); + LOGGER.info( + "WaitInitialRpcTimeout set to " + this.clientProperties.getWaitInitialRpcTimeout()); + } + if (this.clientProperties.getWaitRpcTimeoutMultiplier() != null) { + waitRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getWaitRpcTimeoutMultiplier()); + LOGGER.info( + "WaitRpcTimeoutMultiplier set to " + this.clientProperties.getWaitRpcTimeoutMultiplier()); + } + if (this.clientProperties.getWaitMaxRpcTimeout() != null) { + waitRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getWaitMaxRpcTimeout()); + LOGGER.info("WaitMaxRpcTimeout set to " + this.clientProperties.getWaitMaxRpcTimeout()); + } + if (this.clientProperties.getWaitTotalTimeout() != null) { + waitRetrySettingBuilder.setTotalTimeout(this.clientProperties.getWaitTotalTimeout()); + LOGGER.info("WaitTotalTimeout set to " + this.clientProperties.getWaitTotalTimeout()); + } + clientSettingsBuilder.waitSettings().setRetrySettings(waitRetrySettingBuilder.build()); + RetrySettings.Builder blockRetrySettingBuilder = + clientSettingsBuilder.blockSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getBlockInitialRpcTimeout() != null) { + blockRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getBlockInitialRpcTimeout()); + LOGGER.info( + "BlockInitialRpcTimeout set to " + this.clientProperties.getBlockInitialRpcTimeout()); + } + if (this.clientProperties.getBlockRpcTimeoutMultiplier() != null) { + blockRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getBlockRpcTimeoutMultiplier()); + LOGGER.info( + "BlockRpcTimeoutMultiplier set to " + + this.clientProperties.getBlockRpcTimeoutMultiplier()); + } + if (this.clientProperties.getBlockMaxRpcTimeout() != null) { + blockRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getBlockMaxRpcTimeout()); + LOGGER.info("BlockMaxRpcTimeout set to " + this.clientProperties.getBlockMaxRpcTimeout()); + } + if (this.clientProperties.getBlockTotalTimeout() != null) { + blockRetrySettingBuilder.setTotalTimeout(this.clientProperties.getBlockTotalTimeout()); + LOGGER.info("BlockTotalTimeout set to " + this.clientProperties.getBlockTotalTimeout()); + } + clientSettingsBuilder.blockSettings().setRetrySettings(blockRetrySettingBuilder.build()); + RetrySettings.Builder collideNameRetrySettingBuilder = + clientSettingsBuilder.collideNameSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getCollideNameInitialRpcTimeout() != null) { + collideNameRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getCollideNameInitialRpcTimeout()); + LOGGER.info( + "CollideNameInitialRpcTimeout set to " + + this.clientProperties.getCollideNameInitialRpcTimeout()); + } + if (this.clientProperties.getCollideNameRpcTimeoutMultiplier() != null) { + collideNameRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getCollideNameRpcTimeoutMultiplier()); + LOGGER.info( + "CollideNameRpcTimeoutMultiplier set to " + + this.clientProperties.getCollideNameRpcTimeoutMultiplier()); + } + if (this.clientProperties.getCollideNameMaxRpcTimeout() != null) { + collideNameRetrySettingBuilder.setMaxRpcTimeout( + this.clientProperties.getCollideNameMaxRpcTimeout()); + LOGGER.info( + "CollideNameMaxRpcTimeout set to " + this.clientProperties.getCollideNameMaxRpcTimeout()); + } + if (this.clientProperties.getCollideNameTotalTimeout() != null) { + collideNameRetrySettingBuilder.setTotalTimeout( + this.clientProperties.getCollideNameTotalTimeout()); + LOGGER.info( + "CollideNameTotalTimeout set to " + this.clientProperties.getCollideNameTotalTimeout()); + } + clientSettingsBuilder + .collideNameSettings() + .setRetrySettings(collideNameRetrySettingBuilder.build()); + return EchoClient.create(clientSettingsBuilder.build()); + } +} diff --git a/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringAutoConfigurationFull.golden b/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringAutoConfigurationFull.golden new file mode 100644 index 0000000000..274d5ff95a --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringAutoConfigurationFull.golden @@ -0,0 +1,456 @@ +/* + * Copyright 2022 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.showcase.v1beta1.spring; + +import com.google.api.core.BetaApi; +import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.core.ExecutorProvider; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.retrying.RetrySettings; +import com.google.api.gax.rpc.TransportChannelProvider; +import com.google.cloud.spring.core.DefaultCredentialsProvider; +import com.google.showcase.v1beta1.EchoClient; +import com.google.showcase.v1beta1.EchoSettings; +import java.io.IOException; +import javax.annotation.Generated; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.threeten.bp.Duration; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** + * Auto-configuration for {@link EchoClient}. + * + *

Provides auto-configuration for Spring Boot + * + *

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

    + *
  • The default transport provider is used. + *
  • Credentials are acquired automatically through Application Default Credentials. + *
  • Retries are configured for idempotent methods but not for non-idempotent methods. + *
+ */ +@Generated("by gapic-generator-java") +@BetaApi("Autogenerated Spring autoconfiguration is not yet stable") +@AutoConfiguration +@ConditionalOnClass(EchoClient.class) +@ConditionalOnProperty( + value = "com.google.showcase.v1beta1.spring.auto.echo.enabled", + matchIfMissing = false) +@EnableConfigurationProperties(EchoSpringProperties.class) +public class EchoSpringAutoConfiguration { + private final EchoSpringProperties clientProperties; + private static final Log LOGGER = LogFactory.getLog(EchoSpringAutoConfig.class); + + protected EchoSpringAutoConfiguration(EchoSpringProperties clientProperties) { + this.clientProperties = clientProperties; + } + + /** + * Obtains the default credentials provider. The used key will be obtained from Spring Boot + * configuration data files. + */ + @Bean + @ConditionalOnMissingBean + public CredentialsProvider echoCredentials() throws IOException { + return ((CredentialsProvider) new DefaultCredentialsProvider(this.clientProperties)); + } + + /** + * Returns the default channel provider. The default is gRPC and will default to it unless the + * useRest option is provided to use HTTP transport instead + */ + @Bean + @ConditionalOnMissingBean + public TransportChannelProvider defaultEchoTransportChannelProvider() { + return EchoSettings.defaultTransportChannelProvider(); + } + + /** + * Provides a EchoClient bean configured to use the default credentials provider (obtained with + * echoCredentials()) and its default transport channel provider + * (defaultEchoTransportChannelProvider()). It also configures the quota project ID if provided. + * It will configure an executor provider in case there is more than one thread configured in the + * client + * + *

Individual retry settings are configured as well. It will use the relevant client library's + * default retry settings when they are not specified in EchoProperties. + */ + @Bean + @ConditionalOnMissingBean + public EchoClient echoClient( + @Qualifier("echoCredentials") CredentialsProvider credentialsProvider, + @Qualifier("defaultEchoTransportChannelProvider") + TransportChannelProvider defaultTransportChannelProvider) + throws IOException { + EchoSettings.Builder clientSettingsBuilder = + EchoSettings.newBuilder() + .setCredentialsProvider(credentialsProvider) + .setTransportChannelProvider(defaultTransportChannelProvider) + .setHeaderProvider(); + if (this.clientProperties.getQuotaProjectId() != null) { + clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); + LOGGER.info( + "Quota project id set to " + + this.clientProperties.getQuotaProjectId() + + ", this overrides project id from credentials."); + } + if (this.clientProperties.getExecutorThreadCount() != null) { + ExecutorProvider executorProvider = + EchoSettings.defaultExecutorProviderBuilder() + .setExecutorThreadCount(this.clientProperties.getExecutorThreadCount()) + .build(); + clientSettingsBuilder.setBackgroundExecutorProvider(executorProvider); + LOGGER.info( + "Background executor thread count is " + this.clientProperties.getExecutorThreadCount()); + } + if (this.clientProperties.getUseRest()) { + clientSettingsBuilder.setTransportChannelProvider( + EchoSettings.defaultHttpJsonTransportProviderBuilder().build()); + LOGGER.info("Using HTTP transport channel"); + } + RetrySettings.Builder echoRetrySettingBuilder = + clientSettingsBuilder.echoSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getEchoInitialRetryDelay() != null) { + echoRetrySettingBuilder.setInitialRetryDelay( + this.clientProperties.getEchoInitialRetryDelay()); + LOGGER.info( + "EchoInitialRetryDelay set to " + this.clientProperties.getEchoInitialRetryDelay()); + } + if (this.clientProperties.getEchoRetryDelayMultiplier() != null) { + echoRetrySettingBuilder.setRetryDelayMultiplier( + this.clientProperties.getEchoRetryDelayMultiplier()); + LOGGER.info( + "EchoRetryDelayMultiplier set to " + this.clientProperties.getEchoRetryDelayMultiplier()); + } + if (this.clientProperties.getEchoMaxRetryDelay() != null) { + echoRetrySettingBuilder.setMaxRetryDelay(this.clientProperties.getEchoMaxRetryDelay()); + LOGGER.info("EchoMaxRetryDelay set to " + this.clientProperties.getEchoMaxRetryDelay()); + } + if (this.clientProperties.getEchoInitialRpcTimeout() != null) { + echoRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getEchoInitialRpcTimeout()); + LOGGER.info( + "EchoInitialRpcTimeout set to " + this.clientProperties.getEchoInitialRpcTimeout()); + } + if (this.clientProperties.getEchoRpcTimeoutMultiplier() != null) { + echoRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getEchoRpcTimeoutMultiplier()); + LOGGER.info( + "EchoRpcTimeoutMultiplier set to " + this.clientProperties.getEchoRpcTimeoutMultiplier()); + } + if (this.clientProperties.getEchoMaxRpcTimeout() != null) { + echoRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getEchoMaxRpcTimeout()); + LOGGER.info("EchoMaxRpcTimeout set to " + this.clientProperties.getEchoMaxRpcTimeout()); + } + if (this.clientProperties.getEchoTotalTimeout() != null) { + echoRetrySettingBuilder.setTotalTimeout(this.clientProperties.getEchoTotalTimeout()); + LOGGER.info("EchoTotalTimeout set to " + this.clientProperties.getEchoTotalTimeout()); + } + clientSettingsBuilder.echoSettings().setRetrySettings(echoRetrySettingBuilder.build()); + RetrySettings.Builder expandRetrySettingBuilder = + clientSettingsBuilder.expandSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getExpandInitialRetryDelay() != null) { + expandRetrySettingBuilder.setInitialRetryDelay( + this.clientProperties.getExpandInitialRetryDelay()); + LOGGER.info( + "ExpandInitialRetryDelay set to " + this.clientProperties.getExpandInitialRetryDelay()); + } + if (this.clientProperties.getExpandRetryDelayMultiplier() != null) { + expandRetrySettingBuilder.setRetryDelayMultiplier( + this.clientProperties.getExpandRetryDelayMultiplier()); + LOGGER.info( + "ExpandRetryDelayMultiplier set to " + + this.clientProperties.getExpandRetryDelayMultiplier()); + } + if (this.clientProperties.getExpandMaxRetryDelay() != null) { + expandRetrySettingBuilder.setMaxRetryDelay(this.clientProperties.getExpandMaxRetryDelay()); + LOGGER.info("ExpandMaxRetryDelay set to " + this.clientProperties.getExpandMaxRetryDelay()); + } + if (this.clientProperties.getExpandInitialRpcTimeout() != null) { + expandRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getExpandInitialRpcTimeout()); + LOGGER.info( + "ExpandInitialRpcTimeout set to " + this.clientProperties.getExpandInitialRpcTimeout()); + } + if (this.clientProperties.getExpandRpcTimeoutMultiplier() != null) { + expandRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getExpandRpcTimeoutMultiplier()); + LOGGER.info( + "ExpandRpcTimeoutMultiplier set to " + + this.clientProperties.getExpandRpcTimeoutMultiplier()); + } + if (this.clientProperties.getExpandMaxRpcTimeout() != null) { + expandRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getExpandMaxRpcTimeout()); + LOGGER.info("ExpandMaxRpcTimeout set to " + this.clientProperties.getExpandMaxRpcTimeout()); + } + if (this.clientProperties.getExpandTotalTimeout() != null) { + expandRetrySettingBuilder.setTotalTimeout(this.clientProperties.getExpandTotalTimeout()); + LOGGER.info("ExpandTotalTimeout set to " + this.clientProperties.getExpandTotalTimeout()); + } + clientSettingsBuilder.expandSettings().setRetrySettings(expandRetrySettingBuilder.build()); + RetrySettings.Builder collectRetrySettingBuilder = + clientSettingsBuilder.collectSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getCollectInitialRpcTimeout() != null) { + collectRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getCollectInitialRpcTimeout()); + LOGGER.info( + "CollectInitialRpcTimeout set to " + this.clientProperties.getCollectInitialRpcTimeout()); + } + if (this.clientProperties.getCollectRpcTimeoutMultiplier() != null) { + collectRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getCollectRpcTimeoutMultiplier()); + LOGGER.info( + "CollectRpcTimeoutMultiplier set to " + + this.clientProperties.getCollectRpcTimeoutMultiplier()); + } + if (this.clientProperties.getCollectMaxRpcTimeout() != null) { + collectRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getCollectMaxRpcTimeout()); + LOGGER.info("CollectMaxRpcTimeout set to " + this.clientProperties.getCollectMaxRpcTimeout()); + } + if (this.clientProperties.getCollectTotalTimeout() != null) { + collectRetrySettingBuilder.setTotalTimeout(this.clientProperties.getCollectTotalTimeout()); + LOGGER.info("CollectTotalTimeout set to " + this.clientProperties.getCollectTotalTimeout()); + } + clientSettingsBuilder.collectSettings().setRetrySettings(collectRetrySettingBuilder.build()); + RetrySettings.Builder chatRetrySettingBuilder = + clientSettingsBuilder.chatSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getChatInitialRpcTimeout() != null) { + chatRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getChatInitialRpcTimeout()); + LOGGER.info( + "ChatInitialRpcTimeout set to " + this.clientProperties.getChatInitialRpcTimeout()); + } + if (this.clientProperties.getChatRpcTimeoutMultiplier() != null) { + chatRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getChatRpcTimeoutMultiplier()); + LOGGER.info( + "ChatRpcTimeoutMultiplier set to " + this.clientProperties.getChatRpcTimeoutMultiplier()); + } + if (this.clientProperties.getChatMaxRpcTimeout() != null) { + chatRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getChatMaxRpcTimeout()); + LOGGER.info("ChatMaxRpcTimeout set to " + this.clientProperties.getChatMaxRpcTimeout()); + } + if (this.clientProperties.getChatTotalTimeout() != null) { + chatRetrySettingBuilder.setTotalTimeout(this.clientProperties.getChatTotalTimeout()); + LOGGER.info("ChatTotalTimeout set to " + this.clientProperties.getChatTotalTimeout()); + } + clientSettingsBuilder.chatSettings().setRetrySettings(chatRetrySettingBuilder.build()); + RetrySettings.Builder chatAgainRetrySettingBuilder = + clientSettingsBuilder.chatAgainSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getChatAgainInitialRpcTimeout() != null) { + chatAgainRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getChatAgainInitialRpcTimeout()); + LOGGER.info( + "ChatAgainInitialRpcTimeout set to " + + this.clientProperties.getChatAgainInitialRpcTimeout()); + } + if (this.clientProperties.getChatAgainRpcTimeoutMultiplier() != null) { + chatAgainRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getChatAgainRpcTimeoutMultiplier()); + LOGGER.info( + "ChatAgainRpcTimeoutMultiplier set to " + + this.clientProperties.getChatAgainRpcTimeoutMultiplier()); + } + if (this.clientProperties.getChatAgainMaxRpcTimeout() != null) { + chatAgainRetrySettingBuilder.setMaxRpcTimeout( + this.clientProperties.getChatAgainMaxRpcTimeout()); + LOGGER.info( + "ChatAgainMaxRpcTimeout set to " + this.clientProperties.getChatAgainMaxRpcTimeout()); + } + if (this.clientProperties.getChatAgainTotalTimeout() != null) { + chatAgainRetrySettingBuilder.setTotalTimeout( + this.clientProperties.getChatAgainTotalTimeout()); + LOGGER.info( + "ChatAgainTotalTimeout set to " + this.clientProperties.getChatAgainTotalTimeout()); + } + clientSettingsBuilder + .chatAgainSettings() + .setRetrySettings(chatAgainRetrySettingBuilder.build()); + RetrySettings.Builder pagedExpandRetrySettingBuilder = + clientSettingsBuilder.pagedExpandSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getPagedExpandInitialRetryDelay() != null) { + pagedExpandRetrySettingBuilder.setInitialRetryDelay( + this.clientProperties.getPagedExpandInitialRetryDelay()); + LOGGER.info( + "PagedExpandInitialRetryDelay set to " + + this.clientProperties.getPagedExpandInitialRetryDelay()); + } + if (this.clientProperties.getPagedExpandRetryDelayMultiplier() != null) { + pagedExpandRetrySettingBuilder.setRetryDelayMultiplier( + this.clientProperties.getPagedExpandRetryDelayMultiplier()); + LOGGER.info( + "PagedExpandRetryDelayMultiplier set to " + + this.clientProperties.getPagedExpandRetryDelayMultiplier()); + } + if (this.clientProperties.getPagedExpandMaxRetryDelay() != null) { + pagedExpandRetrySettingBuilder.setMaxRetryDelay( + this.clientProperties.getPagedExpandMaxRetryDelay()); + LOGGER.info( + "PagedExpandMaxRetryDelay set to " + this.clientProperties.getPagedExpandMaxRetryDelay()); + } + if (this.clientProperties.getPagedExpandInitialRpcTimeout() != null) { + pagedExpandRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getPagedExpandInitialRpcTimeout()); + LOGGER.info( + "PagedExpandInitialRpcTimeout set to " + + this.clientProperties.getPagedExpandInitialRpcTimeout()); + } + if (this.clientProperties.getPagedExpandRpcTimeoutMultiplier() != null) { + pagedExpandRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getPagedExpandRpcTimeoutMultiplier()); + LOGGER.info( + "PagedExpandRpcTimeoutMultiplier set to " + + this.clientProperties.getPagedExpandRpcTimeoutMultiplier()); + } + if (this.clientProperties.getPagedExpandMaxRpcTimeout() != null) { + pagedExpandRetrySettingBuilder.setMaxRpcTimeout( + this.clientProperties.getPagedExpandMaxRpcTimeout()); + LOGGER.info( + "PagedExpandMaxRpcTimeout set to " + this.clientProperties.getPagedExpandMaxRpcTimeout()); + } + if (this.clientProperties.getPagedExpandTotalTimeout() != null) { + pagedExpandRetrySettingBuilder.setTotalTimeout( + this.clientProperties.getPagedExpandTotalTimeout()); + LOGGER.info( + "PagedExpandTotalTimeout set to " + this.clientProperties.getPagedExpandTotalTimeout()); + } + clientSettingsBuilder + .pagedExpandSettings() + .setRetrySettings(pagedExpandRetrySettingBuilder.build()); + RetrySettings.Builder simplePagedExpandRetrySettingBuilder = + clientSettingsBuilder.simplePagedExpandSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getSimplePagedExpandInitialRpcTimeout() != null) { + simplePagedExpandRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getSimplePagedExpandInitialRpcTimeout()); + LOGGER.info( + "SimplePagedExpandInitialRpcTimeout set to " + + this.clientProperties.getSimplePagedExpandInitialRpcTimeout()); + } + if (this.clientProperties.getSimplePagedExpandRpcTimeoutMultiplier() != null) { + simplePagedExpandRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getSimplePagedExpandRpcTimeoutMultiplier()); + LOGGER.info( + "SimplePagedExpandRpcTimeoutMultiplier set to " + + this.clientProperties.getSimplePagedExpandRpcTimeoutMultiplier()); + } + if (this.clientProperties.getSimplePagedExpandMaxRpcTimeout() != null) { + simplePagedExpandRetrySettingBuilder.setMaxRpcTimeout( + this.clientProperties.getSimplePagedExpandMaxRpcTimeout()); + LOGGER.info( + "SimplePagedExpandMaxRpcTimeout set to " + + this.clientProperties.getSimplePagedExpandMaxRpcTimeout()); + } + if (this.clientProperties.getSimplePagedExpandTotalTimeout() != null) { + simplePagedExpandRetrySettingBuilder.setTotalTimeout( + this.clientProperties.getSimplePagedExpandTotalTimeout()); + LOGGER.info( + "SimplePagedExpandTotalTimeout set to " + + this.clientProperties.getSimplePagedExpandTotalTimeout()); + } + clientSettingsBuilder + .simplePagedExpandSettings() + .setRetrySettings(simplePagedExpandRetrySettingBuilder.build()); + RetrySettings.Builder waitRetrySettingBuilder = + clientSettingsBuilder.waitSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getWaitInitialRpcTimeout() != null) { + waitRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getWaitInitialRpcTimeout()); + LOGGER.info( + "WaitInitialRpcTimeout set to " + this.clientProperties.getWaitInitialRpcTimeout()); + } + if (this.clientProperties.getWaitRpcTimeoutMultiplier() != null) { + waitRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getWaitRpcTimeoutMultiplier()); + LOGGER.info( + "WaitRpcTimeoutMultiplier set to " + this.clientProperties.getWaitRpcTimeoutMultiplier()); + } + if (this.clientProperties.getWaitMaxRpcTimeout() != null) { + waitRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getWaitMaxRpcTimeout()); + LOGGER.info("WaitMaxRpcTimeout set to " + this.clientProperties.getWaitMaxRpcTimeout()); + } + if (this.clientProperties.getWaitTotalTimeout() != null) { + waitRetrySettingBuilder.setTotalTimeout(this.clientProperties.getWaitTotalTimeout()); + LOGGER.info("WaitTotalTimeout set to " + this.clientProperties.getWaitTotalTimeout()); + } + clientSettingsBuilder.waitSettings().setRetrySettings(waitRetrySettingBuilder.build()); + RetrySettings.Builder blockRetrySettingBuilder = + clientSettingsBuilder.blockSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getBlockInitialRpcTimeout() != null) { + blockRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getBlockInitialRpcTimeout()); + LOGGER.info( + "BlockInitialRpcTimeout set to " + this.clientProperties.getBlockInitialRpcTimeout()); + } + if (this.clientProperties.getBlockRpcTimeoutMultiplier() != null) { + blockRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getBlockRpcTimeoutMultiplier()); + LOGGER.info( + "BlockRpcTimeoutMultiplier set to " + + this.clientProperties.getBlockRpcTimeoutMultiplier()); + } + if (this.clientProperties.getBlockMaxRpcTimeout() != null) { + blockRetrySettingBuilder.setMaxRpcTimeout(this.clientProperties.getBlockMaxRpcTimeout()); + LOGGER.info("BlockMaxRpcTimeout set to " + this.clientProperties.getBlockMaxRpcTimeout()); + } + if (this.clientProperties.getBlockTotalTimeout() != null) { + blockRetrySettingBuilder.setTotalTimeout(this.clientProperties.getBlockTotalTimeout()); + LOGGER.info("BlockTotalTimeout set to " + this.clientProperties.getBlockTotalTimeout()); + } + clientSettingsBuilder.blockSettings().setRetrySettings(blockRetrySettingBuilder.build()); + RetrySettings.Builder collideNameRetrySettingBuilder = + clientSettingsBuilder.collideNameSettings().getRetrySettings().toBuilder(); + if (this.clientProperties.getCollideNameInitialRpcTimeout() != null) { + collideNameRetrySettingBuilder.setInitialRpcTimeout( + this.clientProperties.getCollideNameInitialRpcTimeout()); + LOGGER.info( + "CollideNameInitialRpcTimeout set to " + + this.clientProperties.getCollideNameInitialRpcTimeout()); + } + if (this.clientProperties.getCollideNameRpcTimeoutMultiplier() != null) { + collideNameRetrySettingBuilder.setRpcTimeoutMultiplier( + this.clientProperties.getCollideNameRpcTimeoutMultiplier()); + LOGGER.info( + "CollideNameRpcTimeoutMultiplier set to " + + this.clientProperties.getCollideNameRpcTimeoutMultiplier()); + } + if (this.clientProperties.getCollideNameMaxRpcTimeout() != null) { + collideNameRetrySettingBuilder.setMaxRpcTimeout( + this.clientProperties.getCollideNameMaxRpcTimeout()); + LOGGER.info( + "CollideNameMaxRpcTimeout set to " + this.clientProperties.getCollideNameMaxRpcTimeout()); + } + if (this.clientProperties.getCollideNameTotalTimeout() != null) { + collideNameRetrySettingBuilder.setTotalTimeout( + this.clientProperties.getCollideNameTotalTimeout()); + LOGGER.info( + "CollideNameTotalTimeout set to " + this.clientProperties.getCollideNameTotalTimeout()); + } + clientSettingsBuilder + .collideNameSettings() + .setRetrySettings(collideNameRetrySettingBuilder.build()); + return EchoClient.create(clientSettingsBuilder.build()); + } +} diff --git a/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringProperties.golden b/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringProperties.golden new file mode 100644 index 0000000000..b7ca9ebe01 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringProperties.golden @@ -0,0 +1,487 @@ +package com.google.showcase.v1beta1.spring; + +import com.google.cloud.spring.core.Credentials; +import com.google.cloud.spring.core.CredentialsSupplier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.threeten.bp.Duration; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** Provides default property values for Echo client bean */ +@ConfigurationProperties("com.google.showcase.v1beta1.spring.auto.echo") +public class EchoSpringProperties implements CredentialsSupplier { + @NestedConfigurationProperty + private final Credentials credentials = + new Credentials("https://www.googleapis.com/auth/cloud-platform"); + + private String quotaProjectId; + private Integer executorThreadCount; + private boolean useRest; + private Duration echoInitialRetryDelay; + private Double echoRetryDelayMultiplier; + private Duration echoMaxRetryDelay; + private Duration echoInitialRpcTimeout; + private Double echoRpcTimeoutMultiplier; + private Duration echoMaxRpcTimeout; + private Duration echoTotalTimeout; + private Duration expandInitialRetryDelay; + private Double expandRetryDelayMultiplier; + private Duration expandMaxRetryDelay; + private Duration expandInitialRpcTimeout; + private Double expandRpcTimeoutMultiplier; + private Duration expandMaxRpcTimeout; + private Duration expandTotalTimeout; + private Duration collectInitialRpcTimeout; + private Double collectRpcTimeoutMultiplier; + private Duration collectMaxRpcTimeout; + private Duration collectTotalTimeout; + private Duration chatInitialRpcTimeout; + private Double chatRpcTimeoutMultiplier; + private Duration chatMaxRpcTimeout; + private Duration chatTotalTimeout; + private Duration chatAgainInitialRpcTimeout; + private Double chatAgainRpcTimeoutMultiplier; + private Duration chatAgainMaxRpcTimeout; + private Duration chatAgainTotalTimeout; + private Duration pagedExpandInitialRetryDelay; + private Double pagedExpandRetryDelayMultiplier; + private Duration pagedExpandMaxRetryDelay; + private Duration pagedExpandInitialRpcTimeout; + private Double pagedExpandRpcTimeoutMultiplier; + private Duration pagedExpandMaxRpcTimeout; + private Duration pagedExpandTotalTimeout; + private Duration simplePagedExpandInitialRpcTimeout; + private Double simplePagedExpandRpcTimeoutMultiplier; + private Duration simplePagedExpandMaxRpcTimeout; + private Duration simplePagedExpandTotalTimeout; + private Duration waitInitialRpcTimeout; + private Double waitRpcTimeoutMultiplier; + private Duration waitMaxRpcTimeout; + private Duration waitTotalTimeout; + private Duration blockInitialRpcTimeout; + private Double blockRpcTimeoutMultiplier; + private Duration blockMaxRpcTimeout; + private Duration blockTotalTimeout; + private Duration collideNameInitialRpcTimeout; + private Double collideNameRpcTimeoutMultiplier; + private Duration collideNameMaxRpcTimeout; + private Duration collideNameTotalTimeout; + + @Override + public Credentials getCredentials() { + return this.credentials; + } + + public String getQuotaProjectId() { + return this.quotaProjectId; + } + + public void setQuotaProjectId(String quotaProjectId) { + this.quotaProjectId = quotaProjectId; + } + + public boolean getUseRest() { + return this.useRest; + } + + public Integer getExecutorThreadCount() { + return this.executorThreadCount; + } + + public void setExecutorThreadCount(Integer executorThreadCount) { + this.executorThreadCount = executorThreadCount; + } + + public Duration getEchoInitialRetryDelay() { + return this.echoInitialRetryDelay; + } + + public void setEchoInitialRetryDelay(Duration echoInitialRetryDelay) { + this.echoInitialRetryDelay = echoInitialRetryDelay; + } + + public Double getEchoRetryDelayMultiplier() { + return this.echoRetryDelayMultiplier; + } + + public void setEchoRetryDelayMultiplier(Double echoRetryDelayMultiplier) { + this.echoRetryDelayMultiplier = echoRetryDelayMultiplier; + } + + public Duration getEchoMaxRetryDelay() { + return this.echoMaxRetryDelay; + } + + public void setEchoMaxRetryDelay(Duration echoMaxRetryDelay) { + this.echoMaxRetryDelay = echoMaxRetryDelay; + } + + public Duration getEchoInitialRpcTimeout() { + return this.echoInitialRpcTimeout; + } + + public void setEchoInitialRpcTimeout(Duration echoInitialRpcTimeout) { + this.echoInitialRpcTimeout = echoInitialRpcTimeout; + } + + public Double getEchoRpcTimeoutMultiplier() { + return this.echoRpcTimeoutMultiplier; + } + + public void setEchoRpcTimeoutMultiplier(Double echoRpcTimeoutMultiplier) { + this.echoRpcTimeoutMultiplier = echoRpcTimeoutMultiplier; + } + + public Duration getEchoMaxRpcTimeout() { + return this.echoMaxRpcTimeout; + } + + public void setEchoMaxRpcTimeout(Duration echoMaxRpcTimeout) { + this.echoMaxRpcTimeout = echoMaxRpcTimeout; + } + + public Duration getEchoTotalTimeout() { + return this.echoTotalTimeout; + } + + public void setEchoTotalTimeout(Duration echoTotalTimeout) { + this.echoTotalTimeout = echoTotalTimeout; + } + + public Duration getExpandInitialRetryDelay() { + return this.expandInitialRetryDelay; + } + + public void setExpandInitialRetryDelay(Duration expandInitialRetryDelay) { + this.expandInitialRetryDelay = expandInitialRetryDelay; + } + + public Double getExpandRetryDelayMultiplier() { + return this.expandRetryDelayMultiplier; + } + + public void setExpandRetryDelayMultiplier(Double expandRetryDelayMultiplier) { + this.expandRetryDelayMultiplier = expandRetryDelayMultiplier; + } + + public Duration getExpandMaxRetryDelay() { + return this.expandMaxRetryDelay; + } + + public void setExpandMaxRetryDelay(Duration expandMaxRetryDelay) { + this.expandMaxRetryDelay = expandMaxRetryDelay; + } + + public Duration getExpandInitialRpcTimeout() { + return this.expandInitialRpcTimeout; + } + + public void setExpandInitialRpcTimeout(Duration expandInitialRpcTimeout) { + this.expandInitialRpcTimeout = expandInitialRpcTimeout; + } + + public Double getExpandRpcTimeoutMultiplier() { + return this.expandRpcTimeoutMultiplier; + } + + public void setExpandRpcTimeoutMultiplier(Double expandRpcTimeoutMultiplier) { + this.expandRpcTimeoutMultiplier = expandRpcTimeoutMultiplier; + } + + public Duration getExpandMaxRpcTimeout() { + return this.expandMaxRpcTimeout; + } + + public void setExpandMaxRpcTimeout(Duration expandMaxRpcTimeout) { + this.expandMaxRpcTimeout = expandMaxRpcTimeout; + } + + public Duration getExpandTotalTimeout() { + return this.expandTotalTimeout; + } + + public void setExpandTotalTimeout(Duration expandTotalTimeout) { + this.expandTotalTimeout = expandTotalTimeout; + } + + public Duration getCollectInitialRpcTimeout() { + return this.collectInitialRpcTimeout; + } + + public void setCollectInitialRpcTimeout(Duration collectInitialRpcTimeout) { + this.collectInitialRpcTimeout = collectInitialRpcTimeout; + } + + public Double getCollectRpcTimeoutMultiplier() { + return this.collectRpcTimeoutMultiplier; + } + + public void setCollectRpcTimeoutMultiplier(Double collectRpcTimeoutMultiplier) { + this.collectRpcTimeoutMultiplier = collectRpcTimeoutMultiplier; + } + + public Duration getCollectMaxRpcTimeout() { + return this.collectMaxRpcTimeout; + } + + public void setCollectMaxRpcTimeout(Duration collectMaxRpcTimeout) { + this.collectMaxRpcTimeout = collectMaxRpcTimeout; + } + + public Duration getCollectTotalTimeout() { + return this.collectTotalTimeout; + } + + public void setCollectTotalTimeout(Duration collectTotalTimeout) { + this.collectTotalTimeout = collectTotalTimeout; + } + + public Duration getChatInitialRpcTimeout() { + return this.chatInitialRpcTimeout; + } + + public void setChatInitialRpcTimeout(Duration chatInitialRpcTimeout) { + this.chatInitialRpcTimeout = chatInitialRpcTimeout; + } + + public Double getChatRpcTimeoutMultiplier() { + return this.chatRpcTimeoutMultiplier; + } + + public void setChatRpcTimeoutMultiplier(Double chatRpcTimeoutMultiplier) { + this.chatRpcTimeoutMultiplier = chatRpcTimeoutMultiplier; + } + + public Duration getChatMaxRpcTimeout() { + return this.chatMaxRpcTimeout; + } + + public void setChatMaxRpcTimeout(Duration chatMaxRpcTimeout) { + this.chatMaxRpcTimeout = chatMaxRpcTimeout; + } + + public Duration getChatTotalTimeout() { + return this.chatTotalTimeout; + } + + public void setChatTotalTimeout(Duration chatTotalTimeout) { + this.chatTotalTimeout = chatTotalTimeout; + } + + public Duration getChatAgainInitialRpcTimeout() { + return this.chatAgainInitialRpcTimeout; + } + + public void setChatAgainInitialRpcTimeout(Duration chatAgainInitialRpcTimeout) { + this.chatAgainInitialRpcTimeout = chatAgainInitialRpcTimeout; + } + + public Double getChatAgainRpcTimeoutMultiplier() { + return this.chatAgainRpcTimeoutMultiplier; + } + + public void setChatAgainRpcTimeoutMultiplier(Double chatAgainRpcTimeoutMultiplier) { + this.chatAgainRpcTimeoutMultiplier = chatAgainRpcTimeoutMultiplier; + } + + public Duration getChatAgainMaxRpcTimeout() { + return this.chatAgainMaxRpcTimeout; + } + + public void setChatAgainMaxRpcTimeout(Duration chatAgainMaxRpcTimeout) { + this.chatAgainMaxRpcTimeout = chatAgainMaxRpcTimeout; + } + + public Duration getChatAgainTotalTimeout() { + return this.chatAgainTotalTimeout; + } + + public void setChatAgainTotalTimeout(Duration chatAgainTotalTimeout) { + this.chatAgainTotalTimeout = chatAgainTotalTimeout; + } + + public Duration getPagedExpandInitialRetryDelay() { + return this.pagedExpandInitialRetryDelay; + } + + public void setPagedExpandInitialRetryDelay(Duration pagedExpandInitialRetryDelay) { + this.pagedExpandInitialRetryDelay = pagedExpandInitialRetryDelay; + } + + public Double getPagedExpandRetryDelayMultiplier() { + return this.pagedExpandRetryDelayMultiplier; + } + + public void setPagedExpandRetryDelayMultiplier(Double pagedExpandRetryDelayMultiplier) { + this.pagedExpandRetryDelayMultiplier = pagedExpandRetryDelayMultiplier; + } + + public Duration getPagedExpandMaxRetryDelay() { + return this.pagedExpandMaxRetryDelay; + } + + public void setPagedExpandMaxRetryDelay(Duration pagedExpandMaxRetryDelay) { + this.pagedExpandMaxRetryDelay = pagedExpandMaxRetryDelay; + } + + public Duration getPagedExpandInitialRpcTimeout() { + return this.pagedExpandInitialRpcTimeout; + } + + public void setPagedExpandInitialRpcTimeout(Duration pagedExpandInitialRpcTimeout) { + this.pagedExpandInitialRpcTimeout = pagedExpandInitialRpcTimeout; + } + + public Double getPagedExpandRpcTimeoutMultiplier() { + return this.pagedExpandRpcTimeoutMultiplier; + } + + public void setPagedExpandRpcTimeoutMultiplier(Double pagedExpandRpcTimeoutMultiplier) { + this.pagedExpandRpcTimeoutMultiplier = pagedExpandRpcTimeoutMultiplier; + } + + public Duration getPagedExpandMaxRpcTimeout() { + return this.pagedExpandMaxRpcTimeout; + } + + public void setPagedExpandMaxRpcTimeout(Duration pagedExpandMaxRpcTimeout) { + this.pagedExpandMaxRpcTimeout = pagedExpandMaxRpcTimeout; + } + + public Duration getPagedExpandTotalTimeout() { + return this.pagedExpandTotalTimeout; + } + + public void setPagedExpandTotalTimeout(Duration pagedExpandTotalTimeout) { + this.pagedExpandTotalTimeout = pagedExpandTotalTimeout; + } + + public Duration getSimplePagedExpandInitialRpcTimeout() { + return this.simplePagedExpandInitialRpcTimeout; + } + + public void setSimplePagedExpandInitialRpcTimeout(Duration simplePagedExpandInitialRpcTimeout) { + this.simplePagedExpandInitialRpcTimeout = simplePagedExpandInitialRpcTimeout; + } + + public Double getSimplePagedExpandRpcTimeoutMultiplier() { + return this.simplePagedExpandRpcTimeoutMultiplier; + } + + public void setSimplePagedExpandRpcTimeoutMultiplier( + Double simplePagedExpandRpcTimeoutMultiplier) { + this.simplePagedExpandRpcTimeoutMultiplier = simplePagedExpandRpcTimeoutMultiplier; + } + + public Duration getSimplePagedExpandMaxRpcTimeout() { + return this.simplePagedExpandMaxRpcTimeout; + } + + public void setSimplePagedExpandMaxRpcTimeout(Duration simplePagedExpandMaxRpcTimeout) { + this.simplePagedExpandMaxRpcTimeout = simplePagedExpandMaxRpcTimeout; + } + + public Duration getSimplePagedExpandTotalTimeout() { + return this.simplePagedExpandTotalTimeout; + } + + public void setSimplePagedExpandTotalTimeout(Duration simplePagedExpandTotalTimeout) { + this.simplePagedExpandTotalTimeout = simplePagedExpandTotalTimeout; + } + + public Duration getWaitInitialRpcTimeout() { + return this.waitInitialRpcTimeout; + } + + public void setWaitInitialRpcTimeout(Duration waitInitialRpcTimeout) { + this.waitInitialRpcTimeout = waitInitialRpcTimeout; + } + + public Double getWaitRpcTimeoutMultiplier() { + return this.waitRpcTimeoutMultiplier; + } + + public void setWaitRpcTimeoutMultiplier(Double waitRpcTimeoutMultiplier) { + this.waitRpcTimeoutMultiplier = waitRpcTimeoutMultiplier; + } + + public Duration getWaitMaxRpcTimeout() { + return this.waitMaxRpcTimeout; + } + + public void setWaitMaxRpcTimeout(Duration waitMaxRpcTimeout) { + this.waitMaxRpcTimeout = waitMaxRpcTimeout; + } + + public Duration getWaitTotalTimeout() { + return this.waitTotalTimeout; + } + + public void setWaitTotalTimeout(Duration waitTotalTimeout) { + this.waitTotalTimeout = waitTotalTimeout; + } + + public Duration getBlockInitialRpcTimeout() { + return this.blockInitialRpcTimeout; + } + + public void setBlockInitialRpcTimeout(Duration blockInitialRpcTimeout) { + this.blockInitialRpcTimeout = blockInitialRpcTimeout; + } + + public Double getBlockRpcTimeoutMultiplier() { + return this.blockRpcTimeoutMultiplier; + } + + public void setBlockRpcTimeoutMultiplier(Double blockRpcTimeoutMultiplier) { + this.blockRpcTimeoutMultiplier = blockRpcTimeoutMultiplier; + } + + public Duration getBlockMaxRpcTimeout() { + return this.blockMaxRpcTimeout; + } + + public void setBlockMaxRpcTimeout(Duration blockMaxRpcTimeout) { + this.blockMaxRpcTimeout = blockMaxRpcTimeout; + } + + public Duration getBlockTotalTimeout() { + return this.blockTotalTimeout; + } + + public void setBlockTotalTimeout(Duration blockTotalTimeout) { + this.blockTotalTimeout = blockTotalTimeout; + } + + public Duration getCollideNameInitialRpcTimeout() { + return this.collideNameInitialRpcTimeout; + } + + public void setCollideNameInitialRpcTimeout(Duration collideNameInitialRpcTimeout) { + this.collideNameInitialRpcTimeout = collideNameInitialRpcTimeout; + } + + public Double getCollideNameRpcTimeoutMultiplier() { + return this.collideNameRpcTimeoutMultiplier; + } + + public void setCollideNameRpcTimeoutMultiplier(Double collideNameRpcTimeoutMultiplier) { + this.collideNameRpcTimeoutMultiplier = collideNameRpcTimeoutMultiplier; + } + + public Duration getCollideNameMaxRpcTimeout() { + return this.collideNameMaxRpcTimeout; + } + + public void setCollideNameMaxRpcTimeout(Duration collideNameMaxRpcTimeout) { + this.collideNameMaxRpcTimeout = collideNameMaxRpcTimeout; + } + + public Duration getCollideNameTotalTimeout() { + return this.collideNameTotalTimeout; + } + + public void setCollideNameTotalTimeout(Duration collideNameTotalTimeout) { + this.collideNameTotalTimeout = collideNameTotalTimeout; + } +} diff --git a/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringPropertiesFull.golden b/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringPropertiesFull.golden new file mode 100644 index 0000000000..d53b691bde --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/goldens/EchoSpringPropertiesFull.golden @@ -0,0 +1,507 @@ +/* + * Copyright 2022 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.showcase.v1beta1.spring; + +import com.google.api.core.BetaApi; +import com.google.cloud.spring.core.Credentials; +import com.google.cloud.spring.core.CredentialsSupplier; +import javax.annotation.Generated; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.threeten.bp.Duration; + +// AUTO-GENERATED DOCUMENTATION AND CLASS. +/** Provides default property values for Echo client bean */ +@Generated("by gapic-generator-java") +@BetaApi("Autogenerated Spring autoconfiguration is not yet stable") +@ConfigurationProperties("com.google.showcase.v1beta1.spring.auto.echo") +public class EchoSpringProperties implements CredentialsSupplier { + @NestedConfigurationProperty + private final Credentials credentials = + new Credentials("https://www.googleapis.com/auth/cloud-platform"); + + private String quotaProjectId; + private Integer executorThreadCount; + private boolean useRest; + private Duration echoInitialRetryDelay; + private Double echoRetryDelayMultiplier; + private Duration echoMaxRetryDelay; + private Duration echoInitialRpcTimeout; + private Double echoRpcTimeoutMultiplier; + private Duration echoMaxRpcTimeout; + private Duration echoTotalTimeout; + private Duration expandInitialRetryDelay; + private Double expandRetryDelayMultiplier; + private Duration expandMaxRetryDelay; + private Duration expandInitialRpcTimeout; + private Double expandRpcTimeoutMultiplier; + private Duration expandMaxRpcTimeout; + private Duration expandTotalTimeout; + private Duration collectInitialRpcTimeout; + private Double collectRpcTimeoutMultiplier; + private Duration collectMaxRpcTimeout; + private Duration collectTotalTimeout; + private Duration chatInitialRpcTimeout; + private Double chatRpcTimeoutMultiplier; + private Duration chatMaxRpcTimeout; + private Duration chatTotalTimeout; + private Duration chatAgainInitialRpcTimeout; + private Double chatAgainRpcTimeoutMultiplier; + private Duration chatAgainMaxRpcTimeout; + private Duration chatAgainTotalTimeout; + private Duration pagedExpandInitialRetryDelay; + private Double pagedExpandRetryDelayMultiplier; + private Duration pagedExpandMaxRetryDelay; + private Duration pagedExpandInitialRpcTimeout; + private Double pagedExpandRpcTimeoutMultiplier; + private Duration pagedExpandMaxRpcTimeout; + private Duration pagedExpandTotalTimeout; + private Duration simplePagedExpandInitialRpcTimeout; + private Double simplePagedExpandRpcTimeoutMultiplier; + private Duration simplePagedExpandMaxRpcTimeout; + private Duration simplePagedExpandTotalTimeout; + private Duration waitInitialRpcTimeout; + private Double waitRpcTimeoutMultiplier; + private Duration waitMaxRpcTimeout; + private Duration waitTotalTimeout; + private Duration blockInitialRpcTimeout; + private Double blockRpcTimeoutMultiplier; + private Duration blockMaxRpcTimeout; + private Duration blockTotalTimeout; + private Duration collideNameInitialRpcTimeout; + private Double collideNameRpcTimeoutMultiplier; + private Duration collideNameMaxRpcTimeout; + private Duration collideNameTotalTimeout; + + @Override + public Credentials getCredentials() { + return this.credentials; + } + + public String getQuotaProjectId() { + return this.quotaProjectId; + } + + public void setQuotaProjectId(String quotaProjectId) { + this.quotaProjectId = quotaProjectId; + } + + public boolean getUseRest() { + return this.useRest; + } + + public Integer getExecutorThreadCount() { + return this.executorThreadCount; + } + + public void setExecutorThreadCount(Integer executorThreadCount) { + this.executorThreadCount = executorThreadCount; + } + + public Duration getEchoInitialRetryDelay() { + return this.echoInitialRetryDelay; + } + + public void setEchoInitialRetryDelay(Duration echoInitialRetryDelay) { + this.echoInitialRetryDelay = echoInitialRetryDelay; + } + + public Double getEchoRetryDelayMultiplier() { + return this.echoRetryDelayMultiplier; + } + + public void setEchoRetryDelayMultiplier(Double echoRetryDelayMultiplier) { + this.echoRetryDelayMultiplier = echoRetryDelayMultiplier; + } + + public Duration getEchoMaxRetryDelay() { + return this.echoMaxRetryDelay; + } + + public void setEchoMaxRetryDelay(Duration echoMaxRetryDelay) { + this.echoMaxRetryDelay = echoMaxRetryDelay; + } + + public Duration getEchoInitialRpcTimeout() { + return this.echoInitialRpcTimeout; + } + + public void setEchoInitialRpcTimeout(Duration echoInitialRpcTimeout) { + this.echoInitialRpcTimeout = echoInitialRpcTimeout; + } + + public Double getEchoRpcTimeoutMultiplier() { + return this.echoRpcTimeoutMultiplier; + } + + public void setEchoRpcTimeoutMultiplier(Double echoRpcTimeoutMultiplier) { + this.echoRpcTimeoutMultiplier = echoRpcTimeoutMultiplier; + } + + public Duration getEchoMaxRpcTimeout() { + return this.echoMaxRpcTimeout; + } + + public void setEchoMaxRpcTimeout(Duration echoMaxRpcTimeout) { + this.echoMaxRpcTimeout = echoMaxRpcTimeout; + } + + public Duration getEchoTotalTimeout() { + return this.echoTotalTimeout; + } + + public void setEchoTotalTimeout(Duration echoTotalTimeout) { + this.echoTotalTimeout = echoTotalTimeout; + } + + public Duration getExpandInitialRetryDelay() { + return this.expandInitialRetryDelay; + } + + public void setExpandInitialRetryDelay(Duration expandInitialRetryDelay) { + this.expandInitialRetryDelay = expandInitialRetryDelay; + } + + public Double getExpandRetryDelayMultiplier() { + return this.expandRetryDelayMultiplier; + } + + public void setExpandRetryDelayMultiplier(Double expandRetryDelayMultiplier) { + this.expandRetryDelayMultiplier = expandRetryDelayMultiplier; + } + + public Duration getExpandMaxRetryDelay() { + return this.expandMaxRetryDelay; + } + + public void setExpandMaxRetryDelay(Duration expandMaxRetryDelay) { + this.expandMaxRetryDelay = expandMaxRetryDelay; + } + + public Duration getExpandInitialRpcTimeout() { + return this.expandInitialRpcTimeout; + } + + public void setExpandInitialRpcTimeout(Duration expandInitialRpcTimeout) { + this.expandInitialRpcTimeout = expandInitialRpcTimeout; + } + + public Double getExpandRpcTimeoutMultiplier() { + return this.expandRpcTimeoutMultiplier; + } + + public void setExpandRpcTimeoutMultiplier(Double expandRpcTimeoutMultiplier) { + this.expandRpcTimeoutMultiplier = expandRpcTimeoutMultiplier; + } + + public Duration getExpandMaxRpcTimeout() { + return this.expandMaxRpcTimeout; + } + + public void setExpandMaxRpcTimeout(Duration expandMaxRpcTimeout) { + this.expandMaxRpcTimeout = expandMaxRpcTimeout; + } + + public Duration getExpandTotalTimeout() { + return this.expandTotalTimeout; + } + + public void setExpandTotalTimeout(Duration expandTotalTimeout) { + this.expandTotalTimeout = expandTotalTimeout; + } + + public Duration getCollectInitialRpcTimeout() { + return this.collectInitialRpcTimeout; + } + + public void setCollectInitialRpcTimeout(Duration collectInitialRpcTimeout) { + this.collectInitialRpcTimeout = collectInitialRpcTimeout; + } + + public Double getCollectRpcTimeoutMultiplier() { + return this.collectRpcTimeoutMultiplier; + } + + public void setCollectRpcTimeoutMultiplier(Double collectRpcTimeoutMultiplier) { + this.collectRpcTimeoutMultiplier = collectRpcTimeoutMultiplier; + } + + public Duration getCollectMaxRpcTimeout() { + return this.collectMaxRpcTimeout; + } + + public void setCollectMaxRpcTimeout(Duration collectMaxRpcTimeout) { + this.collectMaxRpcTimeout = collectMaxRpcTimeout; + } + + public Duration getCollectTotalTimeout() { + return this.collectTotalTimeout; + } + + public void setCollectTotalTimeout(Duration collectTotalTimeout) { + this.collectTotalTimeout = collectTotalTimeout; + } + + public Duration getChatInitialRpcTimeout() { + return this.chatInitialRpcTimeout; + } + + public void setChatInitialRpcTimeout(Duration chatInitialRpcTimeout) { + this.chatInitialRpcTimeout = chatInitialRpcTimeout; + } + + public Double getChatRpcTimeoutMultiplier() { + return this.chatRpcTimeoutMultiplier; + } + + public void setChatRpcTimeoutMultiplier(Double chatRpcTimeoutMultiplier) { + this.chatRpcTimeoutMultiplier = chatRpcTimeoutMultiplier; + } + + public Duration getChatMaxRpcTimeout() { + return this.chatMaxRpcTimeout; + } + + public void setChatMaxRpcTimeout(Duration chatMaxRpcTimeout) { + this.chatMaxRpcTimeout = chatMaxRpcTimeout; + } + + public Duration getChatTotalTimeout() { + return this.chatTotalTimeout; + } + + public void setChatTotalTimeout(Duration chatTotalTimeout) { + this.chatTotalTimeout = chatTotalTimeout; + } + + public Duration getChatAgainInitialRpcTimeout() { + return this.chatAgainInitialRpcTimeout; + } + + public void setChatAgainInitialRpcTimeout(Duration chatAgainInitialRpcTimeout) { + this.chatAgainInitialRpcTimeout = chatAgainInitialRpcTimeout; + } + + public Double getChatAgainRpcTimeoutMultiplier() { + return this.chatAgainRpcTimeoutMultiplier; + } + + public void setChatAgainRpcTimeoutMultiplier(Double chatAgainRpcTimeoutMultiplier) { + this.chatAgainRpcTimeoutMultiplier = chatAgainRpcTimeoutMultiplier; + } + + public Duration getChatAgainMaxRpcTimeout() { + return this.chatAgainMaxRpcTimeout; + } + + public void setChatAgainMaxRpcTimeout(Duration chatAgainMaxRpcTimeout) { + this.chatAgainMaxRpcTimeout = chatAgainMaxRpcTimeout; + } + + public Duration getChatAgainTotalTimeout() { + return this.chatAgainTotalTimeout; + } + + public void setChatAgainTotalTimeout(Duration chatAgainTotalTimeout) { + this.chatAgainTotalTimeout = chatAgainTotalTimeout; + } + + public Duration getPagedExpandInitialRetryDelay() { + return this.pagedExpandInitialRetryDelay; + } + + public void setPagedExpandInitialRetryDelay(Duration pagedExpandInitialRetryDelay) { + this.pagedExpandInitialRetryDelay = pagedExpandInitialRetryDelay; + } + + public Double getPagedExpandRetryDelayMultiplier() { + return this.pagedExpandRetryDelayMultiplier; + } + + public void setPagedExpandRetryDelayMultiplier(Double pagedExpandRetryDelayMultiplier) { + this.pagedExpandRetryDelayMultiplier = pagedExpandRetryDelayMultiplier; + } + + public Duration getPagedExpandMaxRetryDelay() { + return this.pagedExpandMaxRetryDelay; + } + + public void setPagedExpandMaxRetryDelay(Duration pagedExpandMaxRetryDelay) { + this.pagedExpandMaxRetryDelay = pagedExpandMaxRetryDelay; + } + + public Duration getPagedExpandInitialRpcTimeout() { + return this.pagedExpandInitialRpcTimeout; + } + + public void setPagedExpandInitialRpcTimeout(Duration pagedExpandInitialRpcTimeout) { + this.pagedExpandInitialRpcTimeout = pagedExpandInitialRpcTimeout; + } + + public Double getPagedExpandRpcTimeoutMultiplier() { + return this.pagedExpandRpcTimeoutMultiplier; + } + + public void setPagedExpandRpcTimeoutMultiplier(Double pagedExpandRpcTimeoutMultiplier) { + this.pagedExpandRpcTimeoutMultiplier = pagedExpandRpcTimeoutMultiplier; + } + + public Duration getPagedExpandMaxRpcTimeout() { + return this.pagedExpandMaxRpcTimeout; + } + + public void setPagedExpandMaxRpcTimeout(Duration pagedExpandMaxRpcTimeout) { + this.pagedExpandMaxRpcTimeout = pagedExpandMaxRpcTimeout; + } + + public Duration getPagedExpandTotalTimeout() { + return this.pagedExpandTotalTimeout; + } + + public void setPagedExpandTotalTimeout(Duration pagedExpandTotalTimeout) { + this.pagedExpandTotalTimeout = pagedExpandTotalTimeout; + } + + public Duration getSimplePagedExpandInitialRpcTimeout() { + return this.simplePagedExpandInitialRpcTimeout; + } + + public void setSimplePagedExpandInitialRpcTimeout(Duration simplePagedExpandInitialRpcTimeout) { + this.simplePagedExpandInitialRpcTimeout = simplePagedExpandInitialRpcTimeout; + } + + public Double getSimplePagedExpandRpcTimeoutMultiplier() { + return this.simplePagedExpandRpcTimeoutMultiplier; + } + + public void setSimplePagedExpandRpcTimeoutMultiplier( + Double simplePagedExpandRpcTimeoutMultiplier) { + this.simplePagedExpandRpcTimeoutMultiplier = simplePagedExpandRpcTimeoutMultiplier; + } + + public Duration getSimplePagedExpandMaxRpcTimeout() { + return this.simplePagedExpandMaxRpcTimeout; + } + + public void setSimplePagedExpandMaxRpcTimeout(Duration simplePagedExpandMaxRpcTimeout) { + this.simplePagedExpandMaxRpcTimeout = simplePagedExpandMaxRpcTimeout; + } + + public Duration getSimplePagedExpandTotalTimeout() { + return this.simplePagedExpandTotalTimeout; + } + + public void setSimplePagedExpandTotalTimeout(Duration simplePagedExpandTotalTimeout) { + this.simplePagedExpandTotalTimeout = simplePagedExpandTotalTimeout; + } + + public Duration getWaitInitialRpcTimeout() { + return this.waitInitialRpcTimeout; + } + + public void setWaitInitialRpcTimeout(Duration waitInitialRpcTimeout) { + this.waitInitialRpcTimeout = waitInitialRpcTimeout; + } + + public Double getWaitRpcTimeoutMultiplier() { + return this.waitRpcTimeoutMultiplier; + } + + public void setWaitRpcTimeoutMultiplier(Double waitRpcTimeoutMultiplier) { + this.waitRpcTimeoutMultiplier = waitRpcTimeoutMultiplier; + } + + public Duration getWaitMaxRpcTimeout() { + return this.waitMaxRpcTimeout; + } + + public void setWaitMaxRpcTimeout(Duration waitMaxRpcTimeout) { + this.waitMaxRpcTimeout = waitMaxRpcTimeout; + } + + public Duration getWaitTotalTimeout() { + return this.waitTotalTimeout; + } + + public void setWaitTotalTimeout(Duration waitTotalTimeout) { + this.waitTotalTimeout = waitTotalTimeout; + } + + public Duration getBlockInitialRpcTimeout() { + return this.blockInitialRpcTimeout; + } + + public void setBlockInitialRpcTimeout(Duration blockInitialRpcTimeout) { + this.blockInitialRpcTimeout = blockInitialRpcTimeout; + } + + public Double getBlockRpcTimeoutMultiplier() { + return this.blockRpcTimeoutMultiplier; + } + + public void setBlockRpcTimeoutMultiplier(Double blockRpcTimeoutMultiplier) { + this.blockRpcTimeoutMultiplier = blockRpcTimeoutMultiplier; + } + + public Duration getBlockMaxRpcTimeout() { + return this.blockMaxRpcTimeout; + } + + public void setBlockMaxRpcTimeout(Duration blockMaxRpcTimeout) { + this.blockMaxRpcTimeout = blockMaxRpcTimeout; + } + + public Duration getBlockTotalTimeout() { + return this.blockTotalTimeout; + } + + public void setBlockTotalTimeout(Duration blockTotalTimeout) { + this.blockTotalTimeout = blockTotalTimeout; + } + + public Duration getCollideNameInitialRpcTimeout() { + return this.collideNameInitialRpcTimeout; + } + + public void setCollideNameInitialRpcTimeout(Duration collideNameInitialRpcTimeout) { + this.collideNameInitialRpcTimeout = collideNameInitialRpcTimeout; + } + + public Double getCollideNameRpcTimeoutMultiplier() { + return this.collideNameRpcTimeoutMultiplier; + } + + public void setCollideNameRpcTimeoutMultiplier(Double collideNameRpcTimeoutMultiplier) { + this.collideNameRpcTimeoutMultiplier = collideNameRpcTimeoutMultiplier; + } + + public Duration getCollideNameMaxRpcTimeout() { + return this.collideNameMaxRpcTimeout; + } + + public void setCollideNameMaxRpcTimeout(Duration collideNameMaxRpcTimeout) { + this.collideNameMaxRpcTimeout = collideNameMaxRpcTimeout; + } + + public Duration getCollideNameTotalTimeout() { + return this.collideNameTotalTimeout; + } + + public void setCollideNameTotalTimeout(Duration collideNameTotalTimeout) { + this.collideNameTotalTimeout = collideNameTotalTimeout; + } +} diff --git a/src/test/java/com/google/api/generator/spring/composer/goldens/SpringPackageInfo.golden b/src/test/java/com/google/api/generator/spring/composer/goldens/SpringPackageInfo.golden new file mode 100644 index 0000000000..d7ed65e461 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/goldens/SpringPackageInfo.golden @@ -0,0 +1,5 @@ +/** Spring Boot auto-configurations for showcase. */ +@Generated("by gapic-generator-java") +package com.google.showcase.v1beta1.spring; + +import javax.annotation.Generated; diff --git a/src/test/java/com/google/api/generator/spring/composer/goldens/SpringPackageInfoFull.golden b/src/test/java/com/google/api/generator/spring/composer/goldens/SpringPackageInfoFull.golden new file mode 100644 index 0000000000..4be7458a76 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/composer/goldens/SpringPackageInfoFull.golden @@ -0,0 +1,21 @@ +/* + * Copyright 2022 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. + */ + +/** Spring Boot auto-configurations for showcase. */ +@Generated("by gapic-generator-java") +package com.google.showcase.v1beta1.spring; + +import javax.annotation.Generated; diff --git a/src/test/java/com/google/api/generator/spring/goldens/SpringAdditionalMetadataJson.golden b/src/test/java/com/google/api/generator/spring/goldens/SpringAdditionalMetadataJson.golden new file mode 100644 index 0000000000..5da3bd87f0 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/goldens/SpringAdditionalMetadataJson.golden @@ -0,0 +1,10 @@ +{ + "properties": [ + { + "name": "com.google.showcase.v1beta1.spring.auto.echo.enabled", + "type": "java.lang.Boolean", + "description": "Auto-configure Google Cloud showcase/Echo components.", + "defaultValue": true + } + ] +} \ No newline at end of file diff --git a/src/test/java/com/google/api/generator/spring/goldens/SpringPackagePom.golden b/src/test/java/com/google/api/generator/spring/goldens/SpringPackagePom.golden new file mode 100644 index 0000000000..5ac64b8028 --- /dev/null +++ b/src/test/java/com/google/api/generator/spring/goldens/SpringPackagePom.golden @@ -0,0 +1,63 @@ + + + 4.0.0 + + + com.google.cloud + generated-parent + 3.5.0-SNAPSHOT + + com.google.cloud + com-google-showcase-v1beta1-spring-starter + {{starter-version}} + Spring Boot Starter - showcase + Spring Boot Starter with AutoConfiguration for showcase + + + + + {{client-library-group-id}} + {{client-library-artifact-id}} + {{client-library-version}} + + + + org.springframework.boot + spring-boot-starter + 2.6.3 + + + + com.google.cloud + spring-cloud-gcp-core + 3.2.1 + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.2 + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + + + + + + + + \ No newline at end of file