diff --git a/WORKSPACE b/WORKSPACE index cc406611a9..50cac18478 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -33,7 +33,7 @@ jvm_maven_import_external( # which in its turn, prioritizes actual generated clients runtime dependencies # over the generator dependencies. -_gax_java_version = "2.3.0" +_gax_java_version = "2.4.0" http_archive( name = "com_google_api_gax_java", diff --git a/repositories.bzl b/repositories.bzl index f2074f578d..6091b21171 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -70,9 +70,9 @@ def gapic_generator_java_repositories(): _maybe( http_archive, name = "com_google_googleapis_discovery", - strip_prefix = "googleapis-discovery-2872d382ff767518e63d59ececf5d6f9224b21b4", + strip_prefix = "googleapis-discovery-bb8a053b93ef8698297c41634aa9201f7e075277", urls = [ - "https://github.com/vam-google/googleapis-discovery/archive/2872d382ff767518e63d59ececf5d6f9224b21b4.zip", + "https://github.com/vam-google/googleapis-discovery/archive/bb8a053b93ef8698297c41634aa9201f7e075277.zip", ], ) diff --git a/rules_java_gapic/java_gapic.bzl b/rules_java_gapic/java_gapic.bzl index 65cb3617f7..91eb4ddb56 100644 --- a/rules_java_gapic/java_gapic.bzl +++ b/rules_java_gapic/java_gapic.bzl @@ -135,7 +135,7 @@ def _java_gapic_srcjar( if grpc_service_config: file_args_dict[grpc_service_config] = "grpc-service-config" - elif transport != "rest": + elif not transport or transport == "grpc": for keyword in NO_GRPC_CONFIG_ALLOWLIST: if keyword not in name: fail("Missing a gRPC service config file") @@ -230,16 +230,25 @@ def java_gapic_library( "@javax_annotation_javax_annotation_api//jar", ] - if transport == "rest": + if not transport or transport == "grpc": + actual_deps += [ + "@com_google_api_gax_java//gax-grpc:gax_grpc", + "@io_grpc_grpc_java//core:core", + "@io_grpc_grpc_java//protobuf:protobuf", + ] + elif transport == "rest": actual_deps += [ "@com_google_api_gax_java//gax-httpjson:gax_httpjson", ] - else: + elif transport == "grpc+rest": actual_deps += [ "@com_google_api_gax_java//gax-grpc:gax_grpc", "@io_grpc_grpc_java//core:core", "@io_grpc_grpc_java//protobuf:protobuf", + "@com_google_api_gax_java//gax-httpjson:gax_httpjson", ] + else: + fail("Unknown transport: %s" % transport) native.java_library( name = name, @@ -256,18 +265,29 @@ def java_gapic_library( "@junit_junit//jar", ] - if transport == "rest": + if not transport or transport == "grpc": + actual_test_deps += [ + "@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", + "@io_grpc_grpc_java//auth:auth", + "@io_grpc_grpc_netty_shaded//jar", + "@io_grpc_grpc_java//stub:stub", + "@io_opencensus_opencensus_contrib_grpc_metrics//jar", + ] + elif transport == "rest": actual_test_deps += [ "@com_google_api_gax_java//gax-httpjson:gax_httpjson_testlib", ] - else: + elif transport == "grpc+rest": actual_test_deps += [ "@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", "@io_grpc_grpc_java//auth:auth", "@io_grpc_grpc_netty_shaded//jar", "@io_grpc_grpc_java//stub:stub", "@io_opencensus_opencensus_contrib_grpc_metrics//jar", + "@com_google_api_gax_java//gax-httpjson:gax_httpjson_testlib", ] + else: + fail("Unknown transport: %s" % transport) _append_dep_without_duplicates(actual_test_deps, test_deps) _append_dep_without_duplicates(actual_test_deps, actual_deps) diff --git a/rules_java_gapic/java_gapic_pkg.bzl b/rules_java_gapic/java_gapic_pkg.bzl index a6bca826d2..eb109db524 100644 --- a/rules_java_gapic/java_gapic_pkg.bzl +++ b/rules_java_gapic/java_gapic_pkg.bzl @@ -351,10 +351,12 @@ def java_gapic_assembly_gradle_pkg( grpc_target_dep = ["%s" % grpc_target] if client_deps: - if transport == "rest": - template_label = Label("//rules_java_gapic:resources/gradle/client_rest.gradle.tmpl") - else: + if not transport or transport == "grpc": template_label = Label("//rules_java_gapic:resources/gradle/client_grpc.gradle.tmpl") + elif transport == "rest": + template_label = Label("//rules_java_gapic:resources/gradle/client_rest.gradle.tmpl") + elif transport == "grpc+rest": + template_label = Label("//rules_java_gapic:resources/gradle/client_grpcrest.gradle.tmpl") _java_gapic_gradle_pkg( name = client_target, diff --git a/rules_java_gapic/resources/gradle/assembly.gradle.tmpl b/rules_java_gapic/resources/gradle/assembly.gradle.tmpl index 3c0e59ee69..336a7a5c05 100644 --- a/rules_java_gapic/resources/gradle/assembly.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/assembly.gradle.tmpl @@ -12,8 +12,8 @@ subprojects { apply plugin: 'java' apply plugin: 'maven' - sourceCompatibility = 1.7 - targetCompatibility = 1.7 + sourceCompatibility = 1.8 + targetCompatibility = 1.8 test { testLogging { diff --git a/rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl b/rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl index 137f38d6f2..5ed53f6401 100644 --- a/rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/client_grpc.gradle.tmpl @@ -9,8 +9,8 @@ apply plugin: 'java' description = 'GAPIC library for {{name}}' group = 'com.google.cloud' version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/rules_java_gapic/resources/gradle/client_grpcrest.gradle.tmpl b/rules_java_gapic/resources/gradle/client_grpcrest.gradle.tmpl new file mode 100644 index 0000000000..fe5aa44622 --- /dev/null +++ b/rules_java_gapic/resources/gradle/client_grpcrest.gradle.tmpl @@ -0,0 +1,63 @@ +buildscript { + repositories { + mavenCentral() + } +} + +apply plugin: 'java' + +description = 'GAPIC library for {{name}}' +group = 'com.google.cloud' +version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +repositories { + mavenCentral() + mavenLocal() +} + +compileJava.options.encoding = 'UTF-8' +javadoc.options.encoding = 'UTF-8' + +dependencies { + compile 'com.google.api:gax:{{version.gax}}' + testCompile 'com.google.api:gax:{{version.gax}}:testlib' + compile 'com.google.api:gax-grpc:{{version.gax_grpc}}' + testCompile 'com.google.api:gax-grpc:{{version.gax_grpc}}:testlib' + compile 'com.google.api:gax-httpjson:{{version.gax_httpjson}}' + testCompile 'com.google.api:gax-httpjson:{{version.gax_httpjson}}:testlib' + testCompile 'io.grpc:grpc-netty-shaded:{{version.io_grpc}}' + testCompile '{{maven.junit_junit}}' + {{extra_deps}} +} + +task smokeTest(type: Test) { + filter { + includeTestsMatching "*SmokeTest" + setFailOnNoMatchingTests false + } +} + +test { + exclude "**/*SmokeTest*" +} + +sourceSets { + main { + java { + srcDir 'src/main/java' + } + } +} + +clean { + delete 'all-jars' +} + +task allJars(type: Copy) { + dependsOn test, jar + into 'all-jars' + // Replace with `from configurations.testRuntime, jar` to include test dependencies + from configurations.runtime, jar +} diff --git a/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl b/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl index ef16323736..20fab62963 100644 --- a/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/client_rest.gradle.tmpl @@ -9,8 +9,8 @@ apply plugin: 'java' description = 'GAPIC library for {{name}}' group = 'com.google.cloud' version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/rules_java_gapic/resources/gradle/grpc.gradle.tmpl b/rules_java_gapic/resources/gradle/grpc.gradle.tmpl index d5dfa3f3de..fbae0add76 100644 --- a/rules_java_gapic/resources/gradle/grpc.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/grpc.gradle.tmpl @@ -9,8 +9,8 @@ apply plugin: 'java' description = 'GRPC library for {{name}}' group = 'com.google.api.grpc' version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/rules_java_gapic/resources/gradle/proto.gradle.tmpl b/rules_java_gapic/resources/gradle/proto.gradle.tmpl index ad5e20fc33..27f0bf8448 100644 --- a/rules_java_gapic/resources/gradle/proto.gradle.tmpl +++ b/rules_java_gapic/resources/gradle/proto.gradle.tmpl @@ -9,8 +9,8 @@ apply plugin: 'java' description = 'PROTO library for {{name}}' group = 'com.google.api.grpc' version = (findProperty('version') == 'unspecified') ? '0.0.0-SNAPSHOT' : version -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/src/main/java/com/google/api/generator/gapic/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/BUILD.bazel index 9f6eb8954e..60cbc46d03 100644 --- a/src/main/java/com/google/api/generator/gapic/BUILD.bazel +++ b/src/main/java/com/google/api/generator/gapic/BUILD.bazel @@ -9,6 +9,7 @@ filegroup( "//src/main/java/com/google/api/generator/gapic/composer/comment:comment_files", "//src/main/java/com/google/api/generator/gapic/composer/defaultvalue:defaultvalue_files", "//src/main/java/com/google/api/generator/gapic/composer/grpc:grpc_files", + "//src/main/java/com/google/api/generator/gapic/composer/grpcrest:grpcrest_files", "//src/main/java/com/google/api/generator/gapic/composer/resourcename:resourcename_files", "//src/main/java/com/google/api/generator/gapic/composer/rest:rest_files", "//src/main/java/com/google/api/generator/gapic/composer/samplecode:samplecode_files", diff --git a/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel index 3cfcae2c62..0f09405d04 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel +++ b/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel @@ -21,6 +21,7 @@ java_library( "//src/main/java/com/google/api/generator/gapic/composer/common", "//src/main/java/com/google/api/generator/gapic/composer/defaultvalue", "//src/main/java/com/google/api/generator/gapic/composer/grpc", + "//src/main/java/com/google/api/generator/gapic/composer/grpcrest", "//src/main/java/com/google/api/generator/gapic/composer/resourcename", "//src/main/java/com/google/api/generator/gapic/composer/rest", "//src/main/java/com/google/api/generator/gapic/composer/samplecode", diff --git a/src/main/java/com/google/api/generator/gapic/composer/Composer.java b/src/main/java/com/google/api/generator/gapic/composer/Composer.java index 5c191b0a27..4eefc2845a 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/Composer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/Composer.java @@ -15,22 +15,21 @@ package com.google.api.generator.gapic.composer; import com.google.api.generator.engine.ast.ClassDefinition; -import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.gapic.composer.comment.CommentComposer; -import com.google.api.generator.gapic.composer.common.ServiceClientClassComposer; -import com.google.api.generator.gapic.composer.common.ServiceStubClassComposer; import com.google.api.generator.gapic.composer.grpc.GrpcServiceCallableFactoryClassComposer; import com.google.api.generator.gapic.composer.grpc.GrpcServiceStubClassComposer; import com.google.api.generator.gapic.composer.grpc.MockServiceClassComposer; import com.google.api.generator.gapic.composer.grpc.MockServiceImplClassComposer; +import com.google.api.generator.gapic.composer.grpc.ServiceClientClassComposer; import com.google.api.generator.gapic.composer.grpc.ServiceClientTestClassComposer; import com.google.api.generator.gapic.composer.grpc.ServiceSettingsClassComposer; +import com.google.api.generator.gapic.composer.grpc.ServiceStubClassComposer; import com.google.api.generator.gapic.composer.grpc.ServiceStubSettingsClassComposer; +import com.google.api.generator.gapic.composer.grpcrest.HttpJsonServiceClientTestClassComposer; import com.google.api.generator.gapic.composer.resourcename.ResourceNameHelperClassComposer; import com.google.api.generator.gapic.composer.rest.HttpJsonServiceCallableFactoryClassComposer; import com.google.api.generator.gapic.composer.rest.HttpJsonServiceStubClassComposer; import com.google.api.generator.gapic.model.GapicClass; -import com.google.api.generator.gapic.model.GapicClass.Kind; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.GapicPackageInfo; import com.google.api.generator.gapic.model.Service; @@ -76,8 +75,10 @@ public static List generateStubClasses(GapicContext context) { .services() .forEach( s -> { - clazzes.add(ServiceStubClassComposer.instance().generate(context, s)); if (context.transport() == Transport.REST) { + clazzes.add( + com.google.api.generator.gapic.composer.rest.ServiceStubClassComposer.instance() + .generate(context, s)); clazzes.add( com.google.api.generator.gapic.composer.rest.ServiceStubSettingsClassComposer .instance() @@ -85,11 +86,30 @@ public static List generateStubClasses(GapicContext context) { clazzes.add( HttpJsonServiceCallableFactoryClassComposer.instance().generate(context, s)); clazzes.add(HttpJsonServiceStubClassComposer.instance().generate(context, s)); - } else { + } else if (context.transport() == Transport.GRPC) { + clazzes.add(ServiceStubClassComposer.instance().generate(context, s)); clazzes.add(ServiceStubSettingsClassComposer.instance().generate(context, s)); clazzes.add( GrpcServiceCallableFactoryClassComposer.instance().generate(context, s)); clazzes.add(GrpcServiceStubClassComposer.instance().generate(context, s)); + } else if (context.transport() == Transport.GRPC_REST) { + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest.ServiceStubClassComposer + .instance() + .generate(context, s)); + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest + .ServiceStubSettingsClassComposer.instance() + .generate(context, s)); + clazzes.add( + GrpcServiceCallableFactoryClassComposer.instance().generate(context, s)); + clazzes.add(GrpcServiceStubClassComposer.instance().generate(context, s)); + clazzes.add( + HttpJsonServiceCallableFactoryClassComposer.instance().generate(context, s)); + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest + .HttpJsonServiceStubClassComposer.instance() + .generate(context, s)); } }); return clazzes; @@ -101,14 +121,27 @@ public static List generateClientSettingsClasses(GapicContext contex .services() .forEach( s -> { - clazzes.add(ServiceClientClassComposer.instance().generate(context, s)); if (context.transport() == Transport.REST) { + clazzes.add( + com.google.api.generator.gapic.composer.rest.ServiceClientClassComposer + .instance() + .generate(context, s)); clazzes.add( com.google.api.generator.gapic.composer.rest.ServiceSettingsClassComposer .instance() .generate(context, s)); - } else { + } else if (context.transport() == Transport.GRPC) { + clazzes.add(ServiceClientClassComposer.instance().generate(context, s)); clazzes.add(ServiceSettingsClassComposer.instance().generate(context, s)); + } else if (context.transport() == Transport.GRPC_REST) { + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest.ServiceClientClassComposer + .instance() + .generate(context, s)); + clazzes.add( + com.google.api.generator.gapic.composer.grpcrest.ServiceSettingsClassComposer + .instance() + .generate(context, s)); } }); return clazzes; @@ -120,7 +153,10 @@ public static List generateMockClasses(GapicContext context, List { if (context.transport() == Transport.REST) { // REST transport tests donot not use mock services. - } else { + } else if (context.transport() == Transport.GRPC) { + clazzes.add(MockServiceClassComposer.instance().generate(context, s)); + clazzes.add(MockServiceImplClassComposer.instance().generate(context, s)); + } else if (context.transport() == Transport.GRPC_REST) { clazzes.add(MockServiceClassComposer.instance().generate(context, s)); clazzes.add(MockServiceImplClassComposer.instance().generate(context, s)); } @@ -129,35 +165,25 @@ public static List generateMockClasses(GapicContext context, List generateTestClasses(GapicContext context) { - return context.services().stream() - .map( + List clazzes = new ArrayList<>(); + context + .services() + .forEach( s -> { if (context.transport() == Transport.REST) { - return com.google.api.generator.gapic.composer.rest.ServiceClientTestClassComposer - .instance() - .generate(context, s); - } else { - return ServiceClientTestClassComposer.instance().generate(context, s); + clazzes.add( + com.google.api.generator.gapic.composer.rest.ServiceClientTestClassComposer + .instance() + .generate(context, s)); + } else if (context.transport() == Transport.GRPC) { + clazzes.add(ServiceClientTestClassComposer.instance().generate(context, s)); + } else if (context.transport() == Transport.GRPC_REST) { + clazzes.add(ServiceClientTestClassComposer.instance().generate(context, s)); + clazzes.add(HttpJsonServiceClientTestClassComposer.instance().generate(context, s)); } - }) - .collect(Collectors.toList()); - } - - /** ====================== HELPERS ==================== */ - // TODO(miraleung): Add method list. - private static GapicClass generateGenericClass(Kind kind, String name, Service service) { - String pakkage = service.pakkage(); - if (kind.equals(Kind.STUB)) { - pakkage += ".stub"; - } + }); - ClassDefinition classDef = - ClassDefinition.builder() - .setPackageString(pakkage) - .setName(name) - .setScope(ScopeNode.PUBLIC) - .build(); - return GapicClass.create(kind, classDef); + return clazzes; } @VisibleForTesting diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java index ea3898051c..f4e31a962e 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java @@ -299,7 +299,7 @@ protected MethodDefinition createGenericCallableMethod( protected TypeNode getOperationsStubType(Service service) { TypeNode opeationsStubType = service.operationServiceStubType(); if (opeationsStubType == null) { - opeationsStubType = getTransportContext().operationsStubType(); + opeationsStubType = getTransportContext().operationsStubTypes().get(0); } return opeationsStubType; } diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java similarity index 94% rename from src/main/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java index 4f804822f1..6a9ec1b17a 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java @@ -85,19 +85,21 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.Generated; -public class ServiceClientClassComposer implements ClassComposer { - private static final ServiceClientClassComposer INSTANCE = new ServiceClientClassComposer(); +public abstract class AbstractServiceClientClassComposer implements ClassComposer { private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; private static final String CALLABLE_NAME_PATTERN = "%sCallable"; private static final String PAGED_CALLABLE_NAME_PATTERN = "%sPagedCallable"; @@ -115,10 +117,14 @@ private enum CallableMethodKind { PAGED, } - private ServiceClientClassComposer() {} + private final TransportContext transportContext; - public static ServiceClientClassComposer instance() { - return INSTANCE; + protected AbstractServiceClientClassComposer(TransportContext transportContext) { + this.transportContext = transportContext; + } + + protected TransportContext getTransportContext() { + return transportContext; } @Override @@ -129,7 +135,7 @@ public GapicClass generate(GapicContext context, Service service) { String className = ClassNames.getServiceClientClassName(service); GapicClass.Kind kind = Kind.MAIN; String pakkage = service.pakkage(); - boolean hasLroClient = exposeOperationsClient(service); + boolean hasLroClient = service.hasStandardLroMethods(); Map> grpcRpcsToJavaMethodNames = new HashMap<>(); @@ -198,7 +204,7 @@ private static List createClassHeaderComments( service, classMethodSampleCode, credentialsSampleCode, endpointSampleCode); } - private static List createClassMethods( + private List createClassMethods( Service service, Map messageTypes, TypeStore typeStore, @@ -216,23 +222,19 @@ private static List createClassMethods( return methods; } - private static boolean exposeOperationsClient(Service service) { - for (Method method : service.methods()) { - if (method.hasLro() && method.lro().operationServiceStubType() == null) { - return true; - } - } - return false; - } - - private static List createFieldDeclarations( + private List createFieldDeclarations( Service service, TypeStore typeStore, boolean hasLroClient) { Map fieldNameToTypes = new HashMap<>(); fieldNameToTypes.put( "settings", typeStore.get(ClassNames.getServiceSettingsClassName(service))); fieldNameToTypes.put("stub", typeStore.get(ClassNames.getServiceStubClassName(service))); if (hasLroClient) { - fieldNameToTypes.put("operationsClient", typeStore.get("OperationsClient")); + Iterator opClientName = getTransportContext().operationsClientNames().iterator(); + Iterator opClientType = getTransportContext().operationsClientTypes().iterator(); + + while (opClientName.hasNext() && opClientType.hasNext()) { + fieldNameToTypes.put(opClientName.next(), opClientType.next()); + } } return fieldNameToTypes.entrySet().stream() @@ -352,14 +354,13 @@ private static List createStaticCreatorMethods( return methods; } - private static List createConstructorMethods( + private List createConstructorMethods( Service service, TypeStore typeStore, boolean hasLroClient) { List methods = new ArrayList<>(); String thisClientName = ClassNames.getServiceClientClassName(service); String settingsName = ClassNames.getServiceSettingsClassName(service); TypeNode thisClassType = typeStore.get(thisClientName); TypeNode stubSettingsType = typeStore.get(ClassNames.getServiceStubSettingsClassName(service)); - TypeNode operationsClientType = typeStore.get("OperationsClient"); TypeNode exceptionType = typeStore.get("IOException"); TypeNode settingsType = typeStore.get(settingsName); @@ -372,9 +373,6 @@ private static List createConstructorMethods( .setType(typeStore.get(ClassNames.getServiceStubClassName(service))) .setName("stub") .build()); - VariableExpr operationsClientVarExpr = - VariableExpr.withVariable( - Variable.builder().setType(operationsClientType).setName("operationsClient").build()); // Create the ServiceClient(ServiceSettings settings) ctor. List ctorAssignmentExprs = new ArrayList<>(); @@ -404,25 +402,10 @@ private static List createConstructorMethods( .build()) .build()); - Expr clientArgExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(stubVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setMethodName("getOperationsStub") - .build(); - AssignmentExpr operationsClientAssignExpr = - AssignmentExpr.builder() - .setVariableExpr( - operationsClientVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType(operationsClientType) - .setMethodName("create") - .setArguments(clientArgExpr) - .setReturnType(operationsClientVarExpr.type()) - .build()) - .build(); + List operationsClientAssignExprs = + createOperationsClientAssignExprs(thisExpr, stubVarExpr); if (hasLroClient) { - ctorAssignmentExprs.add(operationsClientAssignExpr); + ctorAssignmentExprs.addAll(operationsClientAssignExprs); } methods.add( @@ -453,7 +436,7 @@ private static List createConstructorMethods( .setValueExpr(stubVarExpr) .build()); if (hasLroClient) { - ctorAssignmentExprs.add(operationsClientAssignExpr); + ctorAssignmentExprs.addAll(operationsClientAssignExprs); } AnnotationNode betaAnnotation = AnnotationNode.builder() @@ -476,15 +459,70 @@ private static List createConstructorMethods( return methods; } - private static List createGetterMethods( + private List createOperationsClientAssignExprs( + Expr thisExpr, VariableExpr stubVarExpr) { + List operationsClientAssignExprs = new ArrayList<>(); + + Iterator opClientTypesIt = getTransportContext().operationsClientTypes().iterator(); + Iterator opClientNamesIt = getTransportContext().operationsClientNames().iterator(); + Iterator opStubNamesIt = + getTransportContext().transportOperationsStubNames().iterator(); + + while (opClientTypesIt.hasNext() && opClientNamesIt.hasNext() && opStubNamesIt.hasNext()) { + TypeNode operationsClientType = opClientTypesIt.next(); + String opClientName = opClientNamesIt.next(); + String opStubName = opStubNamesIt.next(); + + VariableExpr operationsClientVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(operationsClientType).setName(opClientName).build()); + + String operationsStubGetterName = + String.format("get%s", JavaStyle.toUpperCamelCase(opStubName)); + + Expr clientArgExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(stubVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setMethodName(operationsStubGetterName) + .build(); + + AssignmentExpr operationsClientAssignExpr = + AssignmentExpr.builder() + .setVariableExpr( + operationsClientVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType(operationsClientType) + .setMethodName("create") + .setArguments(clientArgExpr) + .setReturnType(operationsClientVarExpr.type()) + .build()) + .build(); + operationsClientAssignExprs.add(operationsClientAssignExpr); + } + + return operationsClientAssignExprs; + } + + private List createGetterMethods( Service service, TypeStore typeStore, boolean hasLroClient) { Map methodNameToTypes = new LinkedHashMap<>(); methodNameToTypes.put( "getSettings", typeStore.get(ClassNames.getServiceSettingsClassName(service))); methodNameToTypes.put("getStub", typeStore.get(ClassNames.getServiceStubClassName(service))); - String getOperationsClientMethodName = "getOperationsClient"; + + Set getOperationsClientMethodNames = new HashSet<>(); + if (hasLroClient) { - methodNameToTypes.put(getOperationsClientMethodName, typeStore.get("OperationsClient")); + Iterator opClientNamesIt = getTransportContext().operationsClientNames().iterator(); + Iterator opClientTypesIt = getTransportContext().operationsClientTypes().iterator(); + + while (opClientNamesIt.hasNext() && opClientTypesIt.hasNext()) { + String opClientMethodName = + String.format("get%s", JavaStyle.toUpperCamelCase(opClientNamesIt.next())); + getOperationsClientMethodNames.add(opClientMethodName); + methodNameToTypes.put(opClientMethodName, opClientTypesIt.next()); + } } AnnotationNode betaStubAnnotation = AnnotationNode.builder() @@ -500,7 +538,7 @@ private static List createGetterMethods( TypeNode methodReturnType = e.getValue(); String returnVariableName = JavaStyle.toLowerCamelCase(methodName.substring(3)); MethodDefinition.Builder methodBuilder = MethodDefinition.builder(); - if (methodName.equals(getOperationsClientMethodName)) { + if (getOperationsClientMethodNames.contains(methodName)) { methodBuilder = methodBuilder.setHeaderCommentStatements( ServiceClientCommentComposer.GET_OPERATIONS_CLIENT_METHOD_COMMENT); @@ -708,6 +746,7 @@ private static MethodDefinition createMethodDefaultMethod( method.isPaged() ? typeStore.get(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, method.name())) : method.outputType(); + List annotations = new ArrayList<>(); if (method.hasLro()) { LongrunningOperation lro = method.lro(); methodOutputType = @@ -718,6 +757,13 @@ private static MethodDefinition createMethodDefaultMethod( .copyAndSetGenerics( Arrays.asList( lro.responseType().reference(), lro.metadataType().reference()))); + if (method.hasLro() && method.lro().operationServiceStubType() != null) { + annotations.add( + AnnotationNode.withTypeAndDescription( + typeStore.get("BetaApi"), + "The surface for long-running operations is not stable yet and may change in the" + + " future.")); + } } // Construct the method that accepts a request proto. @@ -759,8 +805,7 @@ private static MethodDefinition createMethodDefaultMethod( .setArguments(Arrays.asList(requestArgVarExpr)); if (method.isDeprecated()) { - methodBuilder = - methodBuilder.setAnnotations(Arrays.asList(AnnotationNode.withType(TypeNode.DEPRECATED))); + annotations.add(AnnotationNode.withType(TypeNode.DEPRECATED)); } if (isProtoEmptyType(methodOutputType)) { @@ -772,6 +817,9 @@ private static MethodDefinition createMethodDefaultMethod( methodBuilder = methodBuilder.setReturnExpr(callableMethodExpr).setReturnType(methodOutputType); } + + methodBuilder.setAnnotations(annotations); + return methodBuilder.build(); } @@ -1681,8 +1729,6 @@ private static void createVaporTypes(Service service, TypeStore typeStore) { ClassNames.getServiceClientClassName(service)); } - // LRO Gapic-generated types. - typeStore.put("com.google.longrunning", "OperationsClient"); // Pagination types. typeStore.putAll( service.pakkage(), diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java index 7d01cfbca3..364dd183b3 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java @@ -109,12 +109,14 @@ public TransportContext getTransportContext() { @Override public GapicClass generate(GapicContext context, Service service) { + return generate(ClassNames.getServiceClientTestClassName(service), context, service); + } + + protected GapicClass generate(String className, GapicContext context, Service service) { Map resourceNames = context.helperResourceNames(); - Map messageTypes = context.messages(); String pakkage = service.pakkage(); TypeStore typeStore = new TypeStore(); addDynamicTypes(context, service, typeStore); - String className = ClassNames.getServiceClientTestClassName(service); GapicClass.Kind kind = Kind.MAIN; Map classMemberVarExprs = @@ -196,7 +198,8 @@ private List createTestAdminMethods( TypeStore typeStore) { List javaMethods = new ArrayList<>(); javaMethods.add( - createStartStaticServerMethod(service, context, classMemberVarExprs, typeStore)); + createStartStaticServerMethod( + service, context, classMemberVarExprs, typeStore, "newBuilder")); javaMethods.add(createStopServerMethod(service, classMemberVarExprs)); javaMethods.add(createSetUpMethod(service, classMemberVarExprs, typeStore)); javaMethods.add(createTearDownMethod(service, classMemberVarExprs)); @@ -207,7 +210,8 @@ protected abstract MethodDefinition createStartStaticServerMethod( Service service, GapicContext context, Map classMemberVarExprs, - TypeStore typeStore); + TypeStore typeStore, + String newBuilderMethod); protected abstract MethodDefinition createStopServerMethod( Service service, Map classMemberVarExprs); @@ -470,7 +474,7 @@ private MethodDefinition createRpcTestMethod( VariableExpr.withVariable( Variable.builder().setType(methodArg.type()).setName(methodArgName).build()); argExprs.add(varExpr); - Expr valExpr = DefaultValueComposer.createDefaultValue(methodArg, resourceNames); + Expr valExpr = createDefaultValue(methodArg, resourceNames); methodExprs.add( AssignmentExpr.builder() .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) @@ -735,6 +739,9 @@ protected abstract List createStreamingRpcExceptionTestStatements( Map resourceNames, Map messageTypes); + protected abstract Expr createDefaultValue( + MethodArgument methodArg, Map resourceNames); + protected List createRpcExceptionTestStatements( Method method, List methodSignature, @@ -766,7 +773,7 @@ protected List createRpcExceptionTestStatements( VariableExpr.withVariable( Variable.builder().setType(methodArg.type()).setName(methodArgName).build()); argVarExprs.add(varExpr); - Expr valExpr = DefaultValueComposer.createDefaultValue(methodArg, resourceNames); + Expr valExpr = createDefaultValue(methodArg, resourceNames); tryBodyExprs.add( AssignmentExpr.builder() .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java index e59e689bb2..cd4f89cbb9 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java @@ -62,11 +62,13 @@ import com.google.api.generator.gapic.model.Service; import com.google.api.generator.gapic.utils.JavaStyle; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.google.longrunning.Operation; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.function.BiFunction; @@ -172,6 +174,7 @@ private List createClassMethods(Service service, TypeStore typ javaMethods.addAll(createSettingsGetterMethods(service, typeStore)); javaMethods.add(createCreatorMethod(service, typeStore)); javaMethods.addAll(createDefaultGetterMethods(service, typeStore)); + javaMethods.addAll(createNewBuilderMethods(service, typeStore, "newBuilder", "createDefault")); javaMethods.addAll(createBuilderHelperMethods(service, typeStore)); javaMethods.add(createConstructorMethod(service, typeStore)); return javaMethods; @@ -351,12 +354,19 @@ private List createDefaultGetterMethods(Service service, TypeS "defaultCredentialsProviderBuilder", typeMakerFn.apply(GoogleCredentialsProvider.Builder.class)), SettingsCommentComposer.DEFAULT_CREDENTIALS_PROVIDER_BUILDER_METHOD_COMMENT)); - javaMethods.add( - methodMakerFn.apply( - methodStarterFn.apply( - getTransportContext().defaultTransportProviderBuilderName(), - typeMakerFn.apply(getTransportContext().instantiatingChannelProviderClass())), - SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT)); + + Iterator providerBuilderNamesIt = + getTransportContext().defaultTransportProviderBuilderNames().iterator(); + Iterator> channelProviderClassesIt = + getTransportContext().instantiatingChannelProviderBuilderClasses().iterator(); + while (providerBuilderNamesIt.hasNext() && channelProviderClassesIt.hasNext()) { + javaMethods.add( + methodMakerFn.apply( + methodStarterFn.apply( + providerBuilderNamesIt.next(), + typeMakerFn.apply(channelProviderClassesIt.next())), + SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT)); + } javaMethods.add( methodStarterFn @@ -383,23 +393,31 @@ private List createDefaultGetterMethods(Service service, TypeS return javaMethods; } - private static List createBuilderHelperMethods( - Service service, TypeStore typeStore) { + protected List createNewBuilderMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { TypeNode builderType = typeStore.get(BUILDER_CLASS_NAME); - MethodDefinition newBuilderMethodOne = + return ImmutableList.of( MethodDefinition.builder() .setHeaderCommentStatements(SettingsCommentComposer.NEW_BUILDER_METHOD_COMMENT) .setScope(ScopeNode.PUBLIC) .setIsStatic(true) .setReturnType(builderType) - .setName("newBuilder") + .setName(newBuilderMethodName) .setReturnExpr( MethodInvocationExpr.builder() .setStaticReferenceType(builderType) - .setMethodName("createDefault") + .setMethodName(createDefaultMethodName) .setReturnType(builderType) .build()) - .build(); + .build()); + } + + private static List createBuilderHelperMethods( + Service service, TypeStore typeStore) { + TypeNode builderType = typeStore.get(BUILDER_CLASS_NAME); VariableExpr clientContextVarExpr = VariableExpr.withVariable( @@ -439,10 +457,10 @@ private static List createBuilderHelperMethods( .build()) .build(); - return Arrays.asList(newBuilderMethodOne, newBuilderMethodTwo, toBuilderMethod); + return Arrays.asList(newBuilderMethodTwo, toBuilderMethod); } - private static ClassDefinition createNestedBuilderClass(Service service, TypeStore typeStore) { + private ClassDefinition createNestedBuilderClass(Service service, TypeStore typeStore) { return ClassDefinition.builder() .setHeaderCommentStatements( SettingsCommentComposer.createBuilderClassComment( @@ -466,11 +484,12 @@ private static ClassDefinition createNestedBuilderClass(Service service, TypeSto .build(); } - private static List createNestedBuilderClassMethods( + private List createNestedBuilderClassMethods( Service service, TypeStore typeStore) { List javaMethods = new ArrayList<>(); javaMethods.addAll(createNestedBuilderConstructorMethods(service, typeStore)); - javaMethods.add(createNestedBuilderCreatorMethod(service, typeStore)); + javaMethods.addAll( + createNestedBuilderCreatorMethods(service, typeStore, "newBuilder", "createDefault")); javaMethods.add(createNestedBuilderStubSettingsBuilderMethod(service, typeStore)); javaMethods.add(createNestedBuilderApplyToAllUnaryMethod(service, typeStore)); javaMethods.addAll(createNestedBuilderSettingsGetterMethods(service, typeStore)); @@ -557,23 +576,28 @@ private static List createNestedBuilderConstructorMethods( return Arrays.asList(noArgCtor, clientContextCtor, settingsCtor, stubSettingsCtor); } - private static MethodDefinition createNestedBuilderCreatorMethod( - Service service, TypeStore typeStore) { + protected List createNestedBuilderCreatorMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { MethodInvocationExpr ctorArg = MethodInvocationExpr.builder() .setStaticReferenceType( typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) - .setMethodName("newBuilder") + .setMethodName(newBuilderMethodName) .build(); TypeNode builderType = typeStore.get(BUILDER_CLASS_NAME); - return MethodDefinition.builder() - .setScope(ScopeNode.PRIVATE) - .setIsStatic(true) - .setReturnType(builderType) - .setName("createDefault") - .setReturnExpr(NewObjectExpr.builder().setType(builderType).setArguments(ctorArg).build()) - .build(); + return ImmutableList.of( + MethodDefinition.builder() + .setScope(ScopeNode.PRIVATE) + .setIsStatic(true) + .setReturnType(builderType) + .setName(createDefaultMethodName) + .setReturnExpr( + NewObjectExpr.builder().setType(builderType).setArguments(ctorArg).build()) + .build()); } private static MethodDefinition createNestedBuilderStubSettingsBuilderMethod( diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java index 8935e0b00c..c54ccbde39 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java @@ -16,39 +16,27 @@ import com.google.api.core.BetaApi; import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.core.BackgroundResourceAggregation; import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientContext; import com.google.api.gax.rpc.ClientStreamingCallable; +import com.google.api.gax.rpc.LongRunningClient; import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.RequestParamsExtractor; import com.google.api.gax.rpc.ServerStreamingCallable; import com.google.api.gax.rpc.UnaryCallable; import com.google.api.generator.engine.ast.AnnotationNode; -import com.google.api.generator.engine.ast.AssignmentExpr; import com.google.api.generator.engine.ast.ClassDefinition; -import com.google.api.generator.engine.ast.CommentStatement; import com.google.api.generator.engine.ast.ConcreteReference; -import com.google.api.generator.engine.ast.EmptyLineStatement; -import com.google.api.generator.engine.ast.Expr; import com.google.api.generator.engine.ast.ExprStatement; -import com.google.api.generator.engine.ast.JavaDocComment; import com.google.api.generator.engine.ast.MethodDefinition; -import com.google.api.generator.engine.ast.MethodInvocationExpr; -import com.google.api.generator.engine.ast.NewObjectExpr; -import com.google.api.generator.engine.ast.ReferenceConstructorExpr; +import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.Statement; -import com.google.api.generator.engine.ast.ThisObjectValue; import com.google.api.generator.engine.ast.ThrowExpr; -import com.google.api.generator.engine.ast.TryCatchStatement; import com.google.api.generator.engine.ast.TypeNode; -import com.google.api.generator.engine.ast.ValueExpr; -import com.google.api.generator.engine.ast.VaporReference; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.gapic.composer.comment.StubCommentComposer; import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.composer.utils.PackageChecker; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicClass.Kind; @@ -57,40 +45,20 @@ import com.google.api.generator.gapic.model.Method; import com.google.api.generator.gapic.model.Service; import com.google.api.generator.gapic.utils.JavaStyle; -import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.longrunning.Operation; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.function.BiFunction; -import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.Generated; public abstract class AbstractServiceStubClassComposer implements ClassComposer { - private static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create(); - - private static final String METHOD_DESCRIPTOR_NAME_PATTERN = "%sMethodDescriptor"; + private static final String DOT = "."; private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; - private static final String PAGED_CALLABLE_CLASS_MEMBER_PATTERN = "%sPagedCallable"; - - private static final String BACKGROUND_RESOURCES_MEMBER_NAME = "backgroundResources"; - private static final String CALLABLE_NAME = "Callable"; - private static final String CALLABLE_FACTORY_MEMBER_NAME = "callableFactory"; - private static final String CALLABLE_CLASS_MEMBER_PATTERN = "%sCallable"; - private static final String OPERATION_CALLABLE_CLASS_MEMBER_PATTERN = "%sOperationCallable"; - private static final String OPERATION_CALLABLE_NAME = "OperationCallable"; - private static final String OPERATIONS_STUB_MEMBER_NAME = "operationsStub"; - private static final String PAGED_CALLABLE_NAME = "PagedCallable"; - - protected static final TypeStore FIXED_TYPESTORE = createStaticTypes(); private final TransportContext transportContext; @@ -98,271 +66,38 @@ protected AbstractServiceStubClassComposer(TransportContext transportContext) { this.transportContext = transportContext; } - public TransportContext getTransportContext() { + protected TransportContext getTransportContext() { return transportContext; } - private static TypeStore createStaticTypes() { - List concreteClazzes = - Arrays.asList( - BackgroundResource.class, - BackgroundResourceAggregation.class, - BetaApi.class, - BidiStreamingCallable.class, - ClientContext.class, - ClientStreamingCallable.class, - Generated.class, - ImmutableMap.class, - InterruptedException.class, - IOException.class, - Operation.class, - OperationCallable.class, - RequestParamsExtractor.class, - ServerStreamingCallable.class, - TimeUnit.class, - UnaryCallable.class); - return new TypeStore(concreteClazzes); - } - @Override public GapicClass generate(GapicContext context, Service service) { - String pakkage = service.pakkage() + ".stub"; - TypeStore typeStore = createDynamicTypes(service, pakkage); - String className = getTransportContext().classNames().getTransportServiceStubClassName(service); - GapicClass.Kind kind = Kind.STUB; - - Map protoMethodNameToDescriptorVarExprs = - createProtoMethodNameToDescriptorClassMembers( - service, getTransportContext().methodDescriptorClass()); - - Map callableClassMemberVarExprs = - createCallableClassMembers(service, typeStore); - - Map classMemberVarExprs = new LinkedHashMap<>(); - classMemberVarExprs.put( - BACKGROUND_RESOURCES_MEMBER_NAME, - VariableExpr.withVariable( - Variable.builder() - .setName(BACKGROUND_RESOURCES_MEMBER_NAME) - .setType(FIXED_TYPESTORE.get("BackgroundResource")) - .build())); - - - TypeNode opeationsStubType = getTransportOperationsStubType(service); - if (opeationsStubType != null) { - classMemberVarExprs.put( - OPERATIONS_STUB_MEMBER_NAME, - VariableExpr.withVariable( - Variable.builder() - .setName(OPERATIONS_STUB_MEMBER_NAME) - .setType(opeationsStubType) - .build())); - } - - boolean operationPollingMethod = checkOperationPollingMethod(service); - if(operationPollingMethod) { - VariableExpr longRunningVarExpr = declareLongRunningClient(); - if (longRunningVarExpr != null) { - classMemberVarExprs.put("longRunningClient", longRunningVarExpr); - } - } - - classMemberVarExprs.put( - CALLABLE_FACTORY_MEMBER_NAME, - VariableExpr.withVariable( - Variable.builder() - .setName(CALLABLE_FACTORY_MEMBER_NAME) - .setType(getTransportContext().stubCallableFactoryType()) - .build())); - Map messageTypes = context.messages(); - List classStatements = - createClassStatements( - service, - protoMethodNameToDescriptorVarExprs, - callableClassMemberVarExprs, - classMemberVarExprs, - messageTypes); - - StubCommentComposer commentComposer = - new StubCommentComposer(getTransportContext().transportName()); + TypeStore typeStore = createTypes(service, messageTypes); + String className = ClassNames.getServiceStubClassName(service); + GapicClass.Kind kind = Kind.STUB; + String pakkage = String.format("%s.stub", service.pakkage()); ClassDefinition classDef = ClassDefinition.builder() .setPackageString(pakkage) .setHeaderCommentStatements( - commentComposer.createTransportServiceStubClassHeaderComments( + StubCommentComposer.createServiceStubClassHeaderComments( service.name(), service.isDeprecated())) - .setAnnotations(createClassAnnotations(service)) - .setScope(ScopeNode.PUBLIC) + .setAnnotations(createClassAnnotations(service, typeStore)) + .setIsAbstract(true) + .setImplementsTypes(createClassImplements(typeStore)) .setName(className) - .setExtendsType( - typeStore.get(getTransportContext().classNames().getServiceStubClassName(service))) - .setStatements(classStatements) - .setMethods( - createClassMethods( - service, - typeStore, - classMemberVarExprs, - callableClassMemberVarExprs, - protoMethodNameToDescriptorVarExprs)) + .setMethods(createClassMethods(service, messageTypes, typeStore)) + .setScope(ScopeNode.PUBLIC) .build(); return GapicClass.create(kind, classDef); } - protected abstract Statement createMethodDescriptorVariableDecl( - Service service, Method protoMethod, VariableExpr methodDescriptorVarExpr, Map messageTypes); - - protected abstract List createOperationsStubGetterMethod( - VariableExpr operationsStubVarExpr); - - protected abstract Expr createTransportSettingsInitExpr( - Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr); - - protected List createGetMethodDescriptorsMethod( - Service service, - TypeStore typeStore, - Map protoMethodNameToDescriptorVarExprs) { - return Arrays.asList(); - } - - protected List createClassStatements( - Service service, - Map protoMethodNameToDescriptorVarExprs, - Map callableClassMemberVarExprs, - Map classMemberVarExprs, - Map messageTypes) { - List classStatements = new ArrayList<>(); - for (Statement statement : - createMethodDescriptorVariableDecls(service, protoMethodNameToDescriptorVarExprs, messageTypes)) { - classStatements.add(statement); - classStatements.add(EMPTY_LINE_STATEMENT); - } - - classStatements.addAll(createClassMemberFieldDeclarations(callableClassMemberVarExprs)); - classStatements.add(EMPTY_LINE_STATEMENT); - - classStatements.addAll(createClassMemberFieldDeclarations(classMemberVarExprs)); - return classStatements; - } - - protected List createMethodDescriptorVariableDecls( - Service service, Map protoMethodNameToDescriptorVarExprs, Map messageTypes) { - return service.methods().stream() - .map( - m -> - createMethodDescriptorVariableDecl( - service, m, protoMethodNameToDescriptorVarExprs.get(m.name()), messageTypes)) - .collect(Collectors.toList()); - } - - private static List createClassMemberFieldDeclarations( - Map fieldNameToVarExprs) { - return fieldNameToVarExprs.values().stream() - .map( - v -> - ExprStatement.withExpr( - v.toBuilder() - .setIsDecl(true) - .setScope(ScopeNode.PRIVATE) - .setIsFinal(true) - .build())) - .collect(Collectors.toList()); - } - - protected Map createProtoMethodNameToDescriptorClassMembers( - Service service, Class descriptorClass) { - return service.methods().stream() - .collect( - Collectors.toMap( - Method::name, - m -> - VariableExpr.withVariable( - Variable.builder() - .setName( - String.format( - METHOD_DESCRIPTOR_NAME_PATTERN, - JavaStyle.toLowerCamelCase(m.name()))) - .setType( - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(descriptorClass) - .setGenerics( - Arrays.asList( - m.inputType().reference(), - m.outputType().reference())) - .build())) - .build()), - (u, v) -> { - throw new IllegalStateException(); - }, - LinkedHashMap::new)); - } - - private Map createCallableClassMembers( - Service service, TypeStore typeStore) { - Map callableClassMembers = new LinkedHashMap<>(); - // Using a for-loop because the output cardinality is not a 1:1 mapping to the input set. - for (Method protoMethod : service.methods()) { - String javaStyleProtoMethodName = JavaStyle.toLowerCamelCase(protoMethod.name()); - String callableName = String.format(CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); - callableClassMembers.put( - callableName, - VariableExpr.withVariable( - Variable.builder() - .setName(callableName) - .setType(getCallableType(protoMethod)) - .build())); - if (protoMethod.hasLro()) { - callableName = - String.format(OPERATION_CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); - callableClassMembers.put( - callableName, - VariableExpr.withVariable( - Variable.builder() - .setName(callableName) - .setType( - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(OperationCallable.class) - .setGenerics( - Arrays.asList( - protoMethod.inputType().reference(), - protoMethod.lro().responseType().reference(), - protoMethod.lro().metadataType().reference())) - .build())) - .build())); - } - if (protoMethod.isPaged()) { - callableName = String.format(PAGED_CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); - callableClassMembers.put( - callableName, - VariableExpr.withVariable( - Variable.builder() - .setName(callableName) - .setType( - TypeNode.withReference( - getCallableType(protoMethod) - .reference() - .copyAndSetGenerics( - Arrays.asList( - protoMethod.inputType().reference(), - typeStore - .get( - String.format( - PAGED_RESPONSE_TYPE_NAME_PATTERN, - protoMethod.name())) - .reference())))) - .build())); - } - } - return callableClassMembers; - } - - protected List createClassAnnotations(Service service) { + private static List createClassAnnotations(Service service, TypeStore typeStore) { List annotations = new ArrayList<>(); if (!PackageChecker.isGaApi(service.pakkage())) { - annotations.add(AnnotationNode.withType(FIXED_TYPESTORE.get("BetaApi"))); + annotations.add(AnnotationNode.withType(typeStore.get("BetaApi"))); } if (service.isDeprecated()) { @@ -371,589 +106,169 @@ protected List createClassAnnotations(Service service) { annotations.add( AnnotationNode.builder() - .setType(FIXED_TYPESTORE.get("Generated")) + .setType(typeStore.get("Generated")) .setDescription("by gapic-generator-java") .build()); return annotations; } - protected List createClassMethods( - Service service, - TypeStore typeStore, - Map classMemberVarExprs, - Map callableClassMemberVarExprs, - Map protoMethodNameToDescriptorVarExprs) { - List javaMethods = new ArrayList<>(); - javaMethods.addAll(createStaticCreatorMethods(service, typeStore)); - javaMethods.addAll( - createConstructorMethods( - service, - typeStore, - classMemberVarExprs, - callableClassMemberVarExprs, - protoMethodNameToDescriptorVarExprs)); - javaMethods.addAll( - createGetMethodDescriptorsMethod(service, typeStore, protoMethodNameToDescriptorVarExprs)); - javaMethods.addAll( - createOperationsStubGetterMethod(classMemberVarExprs.get(OPERATIONS_STUB_MEMBER_NAME))); - javaMethods.addAll(createCallableGetterMethods(callableClassMemberVarExprs)); - javaMethods.addAll( - createStubOverrideMethods(classMemberVarExprs.get(BACKGROUND_RESOURCES_MEMBER_NAME), service)); - return javaMethods; + private static List createClassImplements(TypeStore typeStore) { + return Arrays.asList(typeStore.get("BackgroundResource")); } - private List createStaticCreatorMethods(Service service, TypeStore typeStore) { - TypeNode creatorMethodReturnType = - typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); - Function, MethodDefinition.Builder> creatorMethodStarterFn = - argList -> - MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setIsFinal(true) - .setReturnType(creatorMethodReturnType) - .setName("create") - .setArguments( - argList.stream() - .map(v -> v.toBuilder().setIsDecl(true).build()) - .collect(Collectors.toList())) - .setThrowsExceptions( - Arrays.asList( - TypeNode.withReference(ConcreteReference.withClazz(IOException.class)))); - - Function, Expr> instantiatorExprFn = - argList -> - NewObjectExpr.builder().setType(creatorMethodReturnType).setArguments(argList).build(); - - TypeNode stubSettingsType = - typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); - VariableExpr settingsVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("settings").setType(stubSettingsType).build()); - - TypeNode clientContextType = FIXED_TYPESTORE.get("ClientContext"); - VariableExpr clientContextVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("clientContext").setType(clientContextType).build()); - - VariableExpr callableFactoryVarExpr = - VariableExpr.withVariable( - Variable.builder() - .setName("callableFactory") - .setType(getTransportContext().stubCallableFactoryType()) - .build()); - - MethodInvocationExpr clientContextCreateMethodExpr = - MethodInvocationExpr.builder() - .setMethodName("create") - .setStaticReferenceType(clientContextType) - .setArguments(Arrays.asList(settingsVarExpr)) - .build(); - MethodInvocationExpr settingsBuilderMethodExpr = - MethodInvocationExpr.builder() - .setMethodName("newBuilder") - .setStaticReferenceType(stubSettingsType) - .build(); - settingsBuilderMethodExpr = - MethodInvocationExpr.builder() - .setMethodName("build") - .setExprReferenceExpr(settingsBuilderMethodExpr) - .build(); + private List createClassMethods( + Service service, Map messageTypes, TypeStore typeStore) { + List methods = new ArrayList<>(); + if (service.hasStandardLroMethods()) { + TypeNode operationsStubType = service.operationServiceStubType(); + methods.addAll(createOperationsStubGetters(typeStore, operationsStubType)); + } - return Arrays.asList( - creatorMethodStarterFn - .apply(Arrays.asList(settingsVarExpr)) - .setReturnExpr( - instantiatorExprFn.apply( - Arrays.asList(settingsVarExpr, clientContextCreateMethodExpr))) - .build(), - creatorMethodStarterFn - .apply(Arrays.asList(clientContextVarExpr)) - .setReturnExpr( - instantiatorExprFn.apply( - Arrays.asList(settingsBuilderMethodExpr, clientContextVarExpr))) - .build(), - creatorMethodStarterFn - .apply(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) - .setReturnExpr( - instantiatorExprFn.apply( - Arrays.asList( - settingsBuilderMethodExpr, clientContextVarExpr, callableFactoryVarExpr))) - .build()); + if (service.operationPollingMethod() != null) { + methods.addAll(createLongRunningClientGetters(typeStore)); + } + methods.addAll(createCallableGetters(service, messageTypes, typeStore)); + methods.addAll(createBackgroundResourceMethodOverrides()); + return methods; } - protected List createConstructorMethods( - Service service, - TypeStore typeStore, - Map classMemberVarExprs, - Map callableClassMemberVarExprs, - Map protoMethodNameToDescriptorVarExprs) { - TypeNode stubSettingsType = - typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); - VariableExpr settingsVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("settings").setType(stubSettingsType).build()); - - TypeNode clientContextType = FIXED_TYPESTORE.get("ClientContext"); - VariableExpr clientContextVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("clientContext").setType(clientContextType).build()); - - VariableExpr callableFactoryVarExpr = - VariableExpr.withVariable( - Variable.builder() - .setName("callableFactory") - .setType(getTransportContext().stubCallableFactoryType()) - .build()); - - TypeNode thisClassType = - typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); - TypeNode ioExceptionType = - TypeNode.withReference(ConcreteReference.withClazz(IOException.class)); - - BiFunction, List, MethodDefinition> ctorMakerFn = - (args, body) -> - MethodDefinition.constructorBuilder() - .setScope(ScopeNode.PROTECTED) - .setReturnType(thisClassType) - .setHeaderCommentStatements(Arrays.asList(createProtectedCtorComment(service))) - .setArguments( - args.stream() - .map(v -> v.toBuilder().setIsDecl(true).build()) - .collect(Collectors.toList())) - .setThrowsExceptions(Arrays.asList(ioExceptionType)) - .setBody(body) - .build(); - - // First constructor method. - MethodDefinition firstCtor = - ctorMakerFn.apply( - Arrays.asList(settingsVarExpr, clientContextVarExpr), - Arrays.asList( - ExprStatement.withExpr( - ReferenceConstructorExpr.thisBuilder() - .setType(thisClassType) - .setArguments( - settingsVarExpr, - clientContextVarExpr, - NewObjectExpr.builder() - .setType( - typeStore.get( - getTransportContext() - .classNames() - .getTransportServiceCallableFactoryClassName(service))) - .build()) - .build()))); - - Expr thisExpr = - ValueExpr.withValue( - ThisObjectValue.withType( - typeStore.get( - getTransportContext().classNames().getTransportServiceStubClassName(service)))); - // Body of the second constructor method. - List secondCtorStatements = new ArrayList<>(); - List secondCtorExprs = new ArrayList<>(); - secondCtorExprs.add( - AssignmentExpr.builder() - .setVariableExpr( - classMemberVarExprs.get("callableFactory").toBuilder() - .setExprReferenceExpr(thisExpr) - .build()) - .setValueExpr(callableFactoryVarExpr) - .build()); - VariableExpr operationsStubClassVarExpr = classMemberVarExprs.get(OPERATIONS_STUB_MEMBER_NAME); - - TypeNode opeationsStubType = getTransportOperationsStubType(service); - if (opeationsStubType != null) { - secondCtorExprs.add( - AssignmentExpr.builder() - .setVariableExpr( - operationsStubClassVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType(opeationsStubType) - .setMethodName("create") - .setArguments(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) - .setReturnType(operationsStubClassVarExpr.type()) - .build()) - .build()); + private List createCallableGetters( + Service service, Map messageTypes, TypeStore typeStore) { + // Use a traditional for-loop since the output cardinality is not necessarily 1:1 with that of + // service.methods(). + List javaMethods = new ArrayList<>(); + for (Method method : service.methods()) { + if (method.hasLro()) { + javaMethods.add(createOperationCallableGetter(method, typeStore)); + } + if (method.isPaged()) { + javaMethods.add(createPagedCallableGetter(method, typeStore)); + } + javaMethods.add(createCallableGetter(method, typeStore)); } - secondCtorStatements.addAll( - secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - secondCtorExprs.clear(); - secondCtorStatements.add(EMPTY_LINE_STATEMENT); - - // Transport settings local variables. - Map javaStyleMethodNameToTransportSettingsVarExprs = - service.methods().stream() - .collect( - Collectors.toMap( - m -> JavaStyle.toLowerCamelCase(m.name()), - m -> - VariableExpr.withVariable( - Variable.builder() - .setName( - String.format( - "%sTransportSettings", - JavaStyle.toLowerCamelCase(m.name()))) - .setType( - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(getTransportContext().callSettingsClass()) - .setGenerics( - Arrays.asList( - m.inputType().reference(), - m.outputType().reference())) - .build())) - .build()))); - - secondCtorExprs.addAll( - service.methods().stream() - .map( - m -> - createTransportSettingsInitExpr( - m, - javaStyleMethodNameToTransportSettingsVarExprs.get( - JavaStyle.toLowerCamelCase(m.name())), - protoMethodNameToDescriptorVarExprs.get(m.name()))) - .collect(Collectors.toList())); - secondCtorStatements.addAll( - secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - secondCtorExprs.clear(); - secondCtorStatements.add(EMPTY_LINE_STATEMENT); - - // Initialize Callable variables. - secondCtorExprs.addAll( - callableClassMemberVarExprs.entrySet().stream() - .map( - e -> - createCallableInitExpr( - e.getKey(), - e.getValue(), - callableFactoryVarExpr, - settingsVarExpr, - clientContextVarExpr, - operationsStubClassVarExpr, - thisExpr, - javaStyleMethodNameToTransportSettingsVarExprs)) - .collect(Collectors.toList())); - secondCtorStatements.addAll( - secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - secondCtorExprs.clear(); - secondCtorStatements.add(EMPTY_LINE_STATEMENT); - - - secondCtorStatements.addAll(createLongRunningClient(service, typeStore)); - - // Instantiate backgroundResources. - MethodInvocationExpr getBackgroundResourcesMethodExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(clientContextVarExpr) - .setMethodName("getBackgroundResources") - .build(); - - VariableExpr backgroundResourcesVarExpr = classMemberVarExprs.get("backgroundResources"); - secondCtorExprs.add( - AssignmentExpr.builder() - .setVariableExpr( - backgroundResourcesVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - NewObjectExpr.builder() - .setType(FIXED_TYPESTORE.get("BackgroundResourceAggregation")) - .setArguments(Arrays.asList(getBackgroundResourcesMethodExpr)) - .build()) - .build()); - secondCtorStatements.addAll( - secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - secondCtorExprs.clear(); - - // Second constructor method. - MethodDefinition secondCtor = - ctorMakerFn.apply( - Arrays.asList(settingsVarExpr, clientContextVarExpr, callableFactoryVarExpr), - secondCtorStatements); + return javaMethods; + } - return Arrays.asList(firstCtor, secondCtor); + private MethodDefinition createOperationCallableGetter( + Method method, TypeStore typeStore) { + return createCallableGetterHelper(method, typeStore, true, false); } - protected List createLongRunningClient(Service service, TypeStore typeStore) { - return ImmutableList.of(); + private MethodDefinition createPagedCallableGetter(Method method, TypeStore typeStore) { + return createCallableGetterHelper(method, typeStore, false, true); } - protected VariableExpr declareLongRunningClient() { - return null; + private MethodDefinition createCallableGetter(Method method, TypeStore typeStore) { + return createCallableGetterHelper(method, typeStore, false, false); } - private static Expr createCallableInitExpr( - String callableVarName, - VariableExpr callableVarExpr, - VariableExpr callableFactoryVarExpr, - VariableExpr settingsVarExpr, - VariableExpr clientContextVarExpr, - VariableExpr operationsStubClassVarExpr, - Expr thisExpr, - Map javaStyleMethodNameToTransportSettingsVarExprs) { - boolean isOperation = callableVarName.endsWith(OPERATION_CALLABLE_NAME); - boolean isPaged = callableVarName.endsWith(PAGED_CALLABLE_NAME); - int sublength = 0; - if (isOperation) { - sublength = OPERATION_CALLABLE_NAME.length(); - } else if (isPaged) { - sublength = PAGED_CALLABLE_NAME.length(); - } else { - sublength = CALLABLE_NAME.length(); - } - String javaStyleMethodName = callableVarName.substring(0, callableVarName.length() - sublength); - List creatorMethodArgVarExprs = null; - Expr transportSettingsVarExpr = - javaStyleMethodNameToTransportSettingsVarExprs.get(javaStyleMethodName); - if (transportSettingsVarExpr == null && isOperation) { - // Try again, in case the name dtection above was inaccurate. - isOperation = false; - sublength = CALLABLE_NAME.length(); - javaStyleMethodName = callableVarName.substring(0, callableVarName.length() - sublength); - transportSettingsVarExpr = - javaStyleMethodNameToTransportSettingsVarExprs.get(javaStyleMethodName); + private MethodDefinition createCallableGetterHelper( + Method method, TypeStore typeStore, boolean isLroCallable, boolean isPaged) { + TypeNode returnType; + switch (method.stream()) { + case CLIENT: + returnType = typeStore.get("ClientStreamingCallable"); + break; + case SERVER: + returnType = typeStore.get("ServerStreamingCallable"); + break; + case BIDI: + returnType = typeStore.get("BidiStreamingCallable"); + break; + case NONE: + // Fall through. + default: + returnType = typeStore.get(isLroCallable ? "OperationCallable" : "UnaryCallable"); } - Preconditions.checkNotNull( - transportSettingsVarExpr, + + String methodName = String.format( - "No transport settings variable found for method name %s", javaStyleMethodName)); - if (isOperation) { - creatorMethodArgVarExprs = - Arrays.asList( - transportSettingsVarExpr, - MethodInvocationExpr.builder() - .setExprReferenceExpr(settingsVarExpr) - .setMethodName(String.format("%sOperationSettings", javaStyleMethodName)) - .build(), - clientContextVarExpr, - operationsStubClassVarExpr); + "%s%sCallable", + JavaStyle.toLowerCamelCase(method.name()), + (isLroCallable ? "Operation" : isPaged ? "Paged" : "")); + List genericRefs = new ArrayList<>(); + genericRefs.add(method.inputType().reference()); + if (method.hasLro() && isLroCallable) { + genericRefs.add(method.lro().responseType().reference()); + genericRefs.add(method.lro().metadataType().reference()); + } else if (isPaged) { + genericRefs.add( + typeStore + .get(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, method.name())) + .reference()); } else { - creatorMethodArgVarExprs = - Arrays.asList( - transportSettingsVarExpr, - MethodInvocationExpr.builder() - .setExprReferenceExpr(settingsVarExpr) - .setMethodName(String.format("%sSettings", javaStyleMethodName)) - .build(), - clientContextVarExpr); + genericRefs.add(method.outputType().reference()); } - String callableCreatorMethodName = getCallableCreatorMethodName(callableVarExpr.type()); - return AssignmentExpr.builder() - .setVariableExpr(callableVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(callableFactoryVarExpr) - .setMethodName(callableCreatorMethodName) - .setArguments(creatorMethodArgVarExprs) - .setReturnType(callableVarExpr.type()) - .build()) - .build(); - } - - private static String getCallableCreatorMethodName(TypeNode callableVarExprType) { - final String typeName = callableVarExprType.reference().name(); - String streamName = "Unary"; + List annotations = + method.isDeprecated() + ? Arrays.asList(AnnotationNode.withType(TypeNode.DEPRECATED)) + : Collections.emptyList(); - // Special handling for pagination methods. - if (callableVarExprType.reference().generics().size() == 2 - && callableVarExprType.reference().generics().get(1).name().endsWith("PagedResponse")) { - streamName = "Paged"; - } else { - if (typeName.startsWith("Client")) { - streamName = "ClientStreaming"; - } else if (typeName.startsWith("Server")) { - streamName = "ServerStreaming"; - } else if (typeName.startsWith("Bidi")) { - streamName = "BidiStreaming"; - } else if (typeName.startsWith("Operation")) { - streamName = "Operation"; - } - } - return String.format("create%sCallable", streamName); - } + returnType = TypeNode.withReference(returnType.reference().copyAndSetGenerics(genericRefs)); - private static List createCallableGetterMethods( - Map callableClassMemberVarExprs) { - return callableClassMemberVarExprs.entrySet().stream() - .map( - e -> - MethodDefinition.builder() - .setIsOverride(true) - .setScope(ScopeNode.PUBLIC) - .setReturnType(e.getValue().type()) - .setName(e.getKey()) - .setReturnExpr(e.getValue()) - .build()) - .collect(Collectors.toList()); + return createCallableGetterMethodDefinition(returnType, methodName, annotations, typeStore); } - private List createStubOverrideMethods( - VariableExpr backgroundResourcesVarExpr, Service service) { - Function methodMakerStarterFn = - methodName -> - MethodDefinition.builder() - .setIsOverride(true) - .setScope(ScopeNode.PUBLIC) - .setName(methodName); - - Function voidMethodMakerFn = - methodName -> - methodMakerStarterFn - .apply(methodName) - .setReturnType(TypeNode.VOID) - .setBody( - Arrays.asList( - ExprStatement.withExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(backgroundResourcesVarExpr) - .setMethodName(methodName) - .build()))) - .build(); + private List createOperationsStubGetters(TypeStore typeStore, TypeNode operationsStubType) { + List getters = new ArrayList<>(); - Function booleanMethodMakerFn = - methodName -> - methodMakerStarterFn - .apply(methodName) - .setReturnType(TypeNode.BOOLEAN) - .setReturnExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(backgroundResourcesVarExpr) - .setMethodName(methodName) - .setReturnType(TypeNode.BOOLEAN) - .build()) - .build(); + Iterator operationStubNameIt = + getTransportContext().transportOperationsStubNames().iterator(); + Iterator operationStubTypeIt = getTransportContext().operationsStubTypes().iterator(); - // Generate the close() method: - // @Override - // public final void close() { - // try { - // backgroundResources.close(); - // } catch (RuntimeException e) { - // throw e; - // } catch (Exception e) { - // throw new IllegalStateException("Failed to close resource", e); - // } - // } + while (operationStubNameIt.hasNext() && operationStubTypeIt.hasNext()) { + String methodName = + String.format("get%s", JavaStyle.toUpperCamelCase(operationStubNameIt.next())); + //TODO: refactor this + TypeNode actualOperationsStubType = operationStubTypeIt.next(); + if (operationsStubType != null) { + actualOperationsStubType = operationsStubType; + } - VariableExpr catchRuntimeExceptionVarExpr = - VariableExpr.builder() - .setVariable( - Variable.builder() - .setType(TypeNode.withExceptionClazz(RuntimeException.class)) - .setName("e") - .build()) - .build(); - VariableExpr catchExceptionVarExpr = - VariableExpr.builder() - .setVariable( - Variable.builder() - .setType(TypeNode.withExceptionClazz(Exception.class)) - .setName("e") - .build()) - .build(); - List javaMethods = new ArrayList<>(); - if (service.operationPollingMethod() != null) { - javaMethods.addAll(createLongRunningClientGetter()); + getters.add(createOperationsStubGetterMethodDefinition(actualOperationsStubType, methodName, typeStore)); } - javaMethods.add( - methodMakerStarterFn - .apply("close") - .setIsFinal(true) - .setReturnType(TypeNode.VOID) - .setBody( - Arrays.asList( - TryCatchStatement.builder() - .setTryBody( - Arrays.asList( - ExprStatement.withExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(backgroundResourcesVarExpr) - .setMethodName("close") - .build()))) - .addCatch( - catchRuntimeExceptionVarExpr.toBuilder().setIsDecl(true).build(), - Arrays.asList( - ExprStatement.withExpr( - ThrowExpr.builder() - .setThrowExpr(catchRuntimeExceptionVarExpr) - .build()))) - .addCatch( - catchExceptionVarExpr.toBuilder().setIsDecl(true).build(), - Arrays.asList( - ExprStatement.withExpr( - ThrowExpr.builder() - .setType( - TypeNode.withExceptionClazz( - IllegalStateException.class)) - .setMessageExpr(String.format("Failed to close resource")) - .setCauseExpr(catchExceptionVarExpr) - .build()))) - .build())) - .build()); - javaMethods.add(voidMethodMakerFn.apply("shutdown")); - javaMethods.add(booleanMethodMakerFn.apply("isShutdown")); - javaMethods.add(booleanMethodMakerFn.apply("isTerminated")); - javaMethods.add(voidMethodMakerFn.apply("shutdownNow")); - List awaitTerminationArgs = - Arrays.asList( - VariableExpr.withVariable( - Variable.builder().setName("duration").setType(TypeNode.LONG).build()), - VariableExpr.withVariable( - Variable.builder() - .setName("unit") - .setType(FIXED_TYPESTORE.get("TimeUnit")) - .build())); - javaMethods.add( - methodMakerStarterFn - .apply("awaitTermination") - .setReturnType(TypeNode.BOOLEAN) - .setArguments( - awaitTerminationArgs.stream() - .map(v -> v.toBuilder().setIsDecl(true).build()) - .collect(Collectors.toList())) - .setThrowsExceptions(Arrays.asList(FIXED_TYPESTORE.get("InterruptedException"))) - .setReturnExpr( - MethodInvocationExpr.builder() - .setExprReferenceExpr(backgroundResourcesVarExpr) - .setMethodName("awaitTermination") - .setArguments( - awaitTerminationArgs.stream() - .map(v -> (Expr) v) - .collect(Collectors.toList())) - .setReturnType(TypeNode.BOOLEAN) - .build()) - .build()); - return javaMethods; + return getters; } - private boolean checkOperationPollingMethod(Service service) { - for(Method method : service.methods()) { - if(method.isOperationPollingMethod()) { - return true; - } - } - return false; + private List createLongRunningClientGetters(TypeStore typeStore) { + return ImmutableList.of(createCallableGetterMethodDefinition( + TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class)), + "longRunningClient", + ImmutableList.of(AnnotationNode.withType(typeStore.get("BetaApi"))), + typeStore)); } - protected List createLongRunningClientGetter() { - return Collections.emptyList(); + private static List createBackgroundResourceMethodOverrides() { + MethodDefinition closeMethod = + MethodDefinition.builder() + .setIsOverride(true) + .setScope(ScopeNode.PUBLIC) + .setIsAbstract(true) + .setReturnType(TypeNode.VOID) + .setName("close") + .build(); + return Arrays.asList(closeMethod); } - private TypeStore createDynamicTypes(Service service, String stubPakkage) { - TypeStore typeStore = new TypeStore(); - typeStore.putAll( - stubPakkage, + private static TypeStore createTypes(Service service, Map messageTypes) { + List concreteClazzes = Arrays.asList( - getTransportContext().classNames().getTransportServiceStubClassName(service), - getTransportContext().classNames().getServiceStubSettingsClassName(service), - getTransportContext().classNames().getServiceStubClassName(service), - getTransportContext() - .classNames() - .getTransportServiceCallableFactoryClassName(service))); + BackgroundResource.class, + BetaApi.class, + BidiStreamingCallable.class, + ClientStreamingCallable.class, + Generated.class, + Operation.class, + OperationCallable.class, + ServerStreamingCallable.class, + UnaryCallable.class, + UnsupportedOperationException.class); + TypeStore typeStore = new TypeStore(concreteClazzes); + + typeStore.put("com.google.longrunning.stub", "OperationsStub"); + // Pagination types. typeStore.putAll( service.pakkage(), @@ -962,68 +277,45 @@ private TypeStore createDynamicTypes(Service service, String stubPakkage) { .map(m -> String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, m.name())) .collect(Collectors.toList()), true, - getTransportContext().classNames().getServiceClientClassName(service)); - return typeStore; - } + ClassNames.getServiceClientClassName(service)); - private static TypeNode getCallableType(Method protoMethod) { - TypeNode callableType = FIXED_TYPESTORE.get("UnaryCallable"); - switch (protoMethod.stream()) { - case CLIENT: - callableType = FIXED_TYPESTORE.get("ClientStreamingCallable"); - break; - case SERVER: - callableType = FIXED_TYPESTORE.get("ServerStreamingCallable"); - break; - case BIDI: - callableType = FIXED_TYPESTORE.get("BidiStreamingCallable"); - break; - case NONE: - // Fall through - default: - // Fall through - } - - return TypeNode.withReference( - callableType - .reference() - .copyAndSetGenerics( - Arrays.asList( - protoMethod.inputType().reference(), protoMethod.outputType().reference()))); + return typeStore; } - private CommentStatement createProtectedCtorComment(Service service) { - return CommentStatement.withComment( - JavaDocComment.withComment( - String.format( - "Constructs an instance of %s, using the given settings. This is protected so that" - + " it is easy to make a subclass, but otherwise, the static factory methods" - + " should be preferred.", - getTransportContext().classNames().getTransportServiceStubClassName(service)))); + protected MethodDefinition createCallableGetterMethodDefinition( + TypeNode returnType, String methodName, List annotations, TypeStore typeStore) { + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setAnnotations(annotations) + .setName(methodName) + .setReturnType(returnType) + .setBody( + Arrays.asList( + ExprStatement.withExpr( + ThrowExpr.builder() + .setType(typeStore.get("UnsupportedOperationException")) + .setMessageExpr(String.format("Not implemented: %s()", methodName)) + .build()))) + .build(); } - protected String getProtoRpcFullMethodName(Service protoService, Method protoMethod) { - if (protoMethod.isMixin()) { - return String.format("%s/%s", protoMethod.mixedInApiName(), protoMethod.name()); - } - - return String.format( - "%s.%s/%s", protoService.protoPakkage(), protoService.name(), protoMethod.name()); + protected MethodDefinition createOperationsStubGetterMethodDefinition( + TypeNode returnType, String methodName, TypeStore typeStore) { + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setReturnType(returnType) + .setName(methodName) + .setBody( + Arrays.asList( + ExprStatement.withExpr( + ThrowExpr.builder() + .setType(typeStore.get("UnsupportedOperationException")) + .setMessageExpr(String.format("Not implemented: %s()", methodName)) + .build()))) + .build(); } - protected TypeNode getTransportOperationsStubType(Service service) { - TypeNode transportOpeationsStubType = service.operationServiceStubType(); - if (transportOpeationsStubType == null) { - transportOpeationsStubType = getTransportContext().transportOperationsStubType(); - } - else { - transportOpeationsStubType = TypeNode.withReference( - VaporReference.builder() - .setName("HttpJson" + transportOpeationsStubType.reference().simpleName()) - .setPakkage(transportOpeationsStubType.reference().pakkage()) - .build()); - } - - return transportOpeationsStubType; + private static String getClientClassName(Service service) { + return String.format("%sClient", service.overriddenName()); } } diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java index c999fccb9d..d61456e1ad 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java @@ -105,6 +105,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -225,11 +226,125 @@ protected MethodDefinition createDefaultCredentialsProviderBuilderMethod() { .build(); } - protected abstract MethodDefinition createDefaultTransportTransportProviderBuilderMethod(); + protected List createDefaultTransportTransportProviderBuilderMethods() { + // Create the defaultGrpcTransportProviderBuilder method. + Iterator> providerClassIt = + getTransportContext().instantiatingChannelProviderClasses().iterator(); + Iterator> providerBuilderClassIt = + getTransportContext().instantiatingChannelProviderBuilderClasses().iterator(); + Iterator builderNamesIt = + getTransportContext().defaultTransportProviderBuilderNames().iterator(); + + List methods = new ArrayList<>(); + + while (providerClassIt.hasNext() + && providerBuilderClassIt.hasNext() + && builderNamesIt.hasNext()) { + TypeNode returnType = + TypeNode.withReference(ConcreteReference.withClazz(providerBuilderClassIt.next())); + TypeNode channelProviderType = + TypeNode.withReference(ConcreteReference.withClazz(providerClassIt.next())); + + MethodInvocationExpr transportChannelProviderBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(channelProviderType) + .setMethodName("newBuilder") + .setReturnType(returnType) + .build(); + Expr returnExpr = + initializeTransportProviderBuilder(transportChannelProviderBuilderExpr, returnType); - protected abstract MethodDefinition createDefaultApiClientHeaderProviderBuilderMethod( + MethodDefinition method = + MethodDefinition.builder() + .setHeaderCommentStatements( + SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT) + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName(builderNamesIt.next()) + .setReturnExpr(returnExpr) + .build(); + methods.add(method); + } + + return methods; + } + + protected Expr initializeTransportProviderBuilder( + MethodInvocationExpr transportChannelProviderBuilderExpr, TypeNode returnType) { + return transportChannelProviderBuilderExpr; + } + + protected abstract List createApiClientHeaderProviderBuilderMethods( Service service, TypeStore typeStore); + protected MethodDefinition createApiClientHeaderProviderBuilderMethod( + Service service, + TypeStore typeStore, + String methodName, + TypeNode gaxPropertiesType, + String getTokenMethodName, + String getVersionMethodName) { + TypeNode returnType = + TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); + MethodInvocationExpr returnExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("ApiClientHeaderProvider")) + .setMethodName("newBuilder") + .build(); + + MethodInvocationExpr versionArgExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("GaxProperties")) + .setMethodName("getLibraryVersion") + .setArguments( + VariableExpr.builder() + .setVariable( + Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) + .setStaticReferenceType( + typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) + .build()) + .build(); + + returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(returnExpr) + .setMethodName("setGeneratedLibToken") + .setArguments(ValueExpr.withValue(StringObjectValue.withValue("gapic")), versionArgExpr) + .build(); + returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(returnExpr) + .setMethodName("setTransportToken") + .setArguments( + MethodInvocationExpr.builder() + .setStaticReferenceType(gaxPropertiesType) + .setMethodName(getTokenMethodName) + .build(), + MethodInvocationExpr.builder() + .setStaticReferenceType(gaxPropertiesType) + .setMethodName(getVersionMethodName) + .build()) + .setReturnType(returnType) + .build(); + + AnnotationNode annotation = + AnnotationNode.builder() + .setType(FIXED_TYPESTORE.get("BetaApi")) + .setDescription( + "The surface for customizing headers is not stable yet and may change in the" + + " future.") + .build(); + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(annotation)) + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName(methodName) + .setReturnExpr(returnExpr) + .build(); + } + public abstract MethodDefinition createDefaultTransportChannelProviderMethod(); private List createClassAnnotations(Service service) { @@ -843,6 +958,7 @@ private List createClassMethods( createMethodSettingsGetterMethods(methodSettingsMemberVarExprs, deprecatedSettingVarNames)); javaMethods.add(createCreateStubMethod(service, typeStore)); javaMethods.addAll(createDefaultHelperAndGetterMethods(service, typeStore)); + javaMethods.addAll(createNewBuilderMethods(service, typeStore, "newBuilder", "createDefault")); javaMethods.addAll(createBuilderHelperMethods(service, typeStore)); javaMethods.add(createClassConstructor(service, methodSettingsMemberVarExprs, typeStore)); return javaMethods; @@ -875,11 +991,7 @@ private static List createMethodSettingsGetterMethods( private MethodDefinition createCreateStubMethod(Service service, TypeStore typeStore) { // Set up the if-statement. - Expr tRansportNameExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(getTransportContext().transportChannelType()) - .setMethodName(getTransportContext().transportGetterName()) - .build(); + List bodyStatements = new ArrayList<>(); Expr getTransportNameExpr = MethodInvocationExpr.builder().setMethodName("getTransportChannelProvider").build(); @@ -889,31 +1001,48 @@ private MethodDefinition createCreateStubMethod(Service service, TypeStore typeS .setMethodName("getTransportName") .build(); - Expr ifConditionExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(getTransportNameExpr) - .setMethodName("equals") - .setArguments(tRansportNameExpr) - .setReturnType(TypeNode.BOOLEAN) - .build(); + Iterator channelTypesIt = getTransportContext().transportChannelTypes().iterator(); + Iterator getterNameIt = getTransportContext().transportGetterNames().iterator(); + Iterator serivceStubClassNameIt = + getTransportContext().classNames().getTransportServiceStubClassNames(service).iterator(); - Expr createExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType( - typeStore.get( - getTransportContext().classNames().getTransportServiceStubClassName(service))) - .setMethodName("create") - .setArguments( - ValueExpr.withValue( - ThisObjectValue.withType( - typeStore.get(ClassNames.getServiceStubSettingsClassName(service))))) - .build(); + while (channelTypesIt.hasNext() && getterNameIt.hasNext()) { + TypeNode channelType = channelTypesIt.next(); + String getterName = getterNameIt.next(); + String serivceStubClassName = serivceStubClassNameIt.next(); - IfStatement ifStatement = - IfStatement.builder() - .setConditionExpr(ifConditionExpr) - .setBody(Arrays.asList(ExprStatement.withExpr(ReturnExpr.withExpr(createExpr)))) - .build(); + Expr tRansportNameExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(channelType) + .setMethodName(getterName) + .build(); + + Expr ifConditionExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(getTransportNameExpr) + .setMethodName("equals") + .setArguments(tRansportNameExpr) + .setReturnType(TypeNode.BOOLEAN) + .build(); + + Expr createExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(typeStore.get(serivceStubClassName)) + .setMethodName("create") + .setArguments( + ValueExpr.withValue( + ThisObjectValue.withType( + typeStore.get(ClassNames.getServiceStubSettingsClassName(service))))) + .build(); + + IfStatement ifStatement = + IfStatement.builder() + .setConditionExpr(ifConditionExpr) + .setBody(Arrays.asList(ExprStatement.withExpr(ReturnExpr.withExpr(createExpr)))) + .build(); + + bodyStatements.add(ifStatement); + } // Set up exception throwing. Expr errorMessageExpr = @@ -930,6 +1059,8 @@ private MethodDefinition createCreateStubMethod(Service service, TypeStore typeS ExprStatement.withExpr( ThrowExpr.builder().setType(exceptionType).setMessageExpr(errorMessageExpr).build()); + bodyStatements.add(throwStatement); + // Put the method together. TypeNode returnType = typeStore.get(ClassNames.getServiceStubClassName(service)); AnnotationNode annotation = @@ -945,7 +1076,7 @@ private MethodDefinition createCreateStubMethod(Service service, TypeStore typeS .setReturnType(returnType) .setName("createStub") .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(IOException.class))) - .setBody(Arrays.asList(ifStatement, throwStatement)) + .setBody(bodyStatements) .build(); } @@ -1021,33 +1152,40 @@ private List createDefaultHelperAndGetterMethods( .build()); javaMethods.add(createDefaultCredentialsProviderBuilderMethod()); - javaMethods.add(createDefaultTransportTransportProviderBuilderMethod()); + javaMethods.addAll(createDefaultTransportTransportProviderBuilderMethods()); javaMethods.add(createDefaultTransportChannelProviderMethod()); - javaMethods.add(createDefaultApiClientHeaderProviderBuilderMethod(service, typeStore)); + javaMethods.addAll(createApiClientHeaderProviderBuilderMethods(service, typeStore)); return javaMethods; } - private static List createBuilderHelperMethods( - Service service, TypeStore typeStore) { - List javaMethods = new ArrayList<>(); + protected List createNewBuilderMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { // Create the newBuilder() method. final TypeNode builderReturnType = typeStore.get(NESTED_BUILDER_CLASS_NAME); - javaMethods.add( + return ImmutableList.of( MethodDefinition.builder() .setHeaderCommentStatements(SettingsCommentComposer.NEW_BUILDER_METHOD_COMMENT) .setScope(ScopeNode.PUBLIC) .setIsStatic(true) .setReturnType(builderReturnType) - .setName("newBuilder") + .setName(newBuilderMethodName) .setReturnExpr( MethodInvocationExpr.builder() .setStaticReferenceType(builderReturnType) - .setMethodName("createDefault") + .setMethodName(createDefaultMethodName) .setReturnType(builderReturnType) .build()) .build()); + } + protected List createBuilderHelperMethods( + Service service, TypeStore typeStore) { + List javaMethods = new ArrayList<>(); + final TypeNode builderReturnType = typeStore.get(NESTED_BUILDER_CLASS_NAME); // Create the newBuilder(ClientContext) method. Function newBuilderFn = argExpr -> NewObjectExpr.builder().setType(builderReturnType).setArguments(argExpr).build(); @@ -1136,7 +1274,7 @@ private static MethodDefinition createClassConstructor( .build(); } - private static ClassDefinition createNestedBuilderClass( + private ClassDefinition createNestedBuilderClass( Service service, @Nullable GapicServiceConfig serviceConfig, TypeStore typeStore) { // TODO(miraleung): Robustify this against a null serviceConfig. String thisClassName = ClassNames.getServiceStubSettingsClassName(service); @@ -1236,7 +1374,7 @@ private static List createNestedClassStatements( return statements; } - private static List createNestedClassMethods( + private List createNestedClassMethods( Service service, GapicServiceConfig serviceConfig, TypeNode superType, @@ -1247,7 +1385,7 @@ private static List createNestedClassMethods( nestedClassMethods.addAll( createNestedClassConstructorMethods( service, serviceConfig, nestedMethodSettingsMemberVarExprs, typeStore)); - nestedClassMethods.add(createNestedClassCreateDefaultMethod(typeStore)); + nestedClassMethods.addAll(createNestedClassCreateDefaultMethods(typeStore)); nestedClassMethods.add(createNestedClassInitDefaultsMethod(service, serviceConfig, typeStore)); nestedClassMethods.add(createNestedClassApplyToAllUnaryMethodsMethod(superType, typeStore)); nestedClassMethods.add(createNestedClassUnaryMethodSettingsBuilderGetterMethod()); @@ -1258,7 +1396,7 @@ private static List createNestedClassMethods( return nestedClassMethods; } - private static MethodDefinition createNestedClassInitDefaultsMethod( + private MethodDefinition createNestedClassInitDefaultsMethod( Service service, @Nullable GapicServiceConfig serviceConfig, TypeStore typeStore) { // TODO(miraleung): Robustify this against a null serviceConfig. TypeNode builderType = typeStore.get(NESTED_BUILDER_CLASS_NAME); @@ -1313,7 +1451,9 @@ private static MethodDefinition createNestedClassInitDefaultsMethod( method, builderVarExpr, NESTED_RETRYABLE_CODE_DEFINITIONS_VAR_EXPR, - NESTED_RETRY_PARAM_DEFINITIONS_VAR_EXPR))); + NESTED_RETRY_PARAM_DEFINITIONS_VAR_EXPR, + getTransportContext().operationResponseTransformerType(), + getTransportContext().operationMetadataTransformerType()))); bodyStatements.add(EMPTY_LINE_STATEMENT); } @@ -1583,7 +1723,22 @@ private static List createNestedClassConstructorMethods( return ctorMethods; } - private static MethodDefinition createNestedClassCreateDefaultMethod(TypeStore typeStore) { + protected List createNestedClassCreateDefaultMethods(TypeStore typeStore) { + return Collections.singletonList( + createNestedClassCreateDefaultMethod( + typeStore, + "createDefault", + "defaultTransportChannelProvider", + null, + "defaultApiClientHeaderProviderBuilder")); + } + + protected MethodDefinition createNestedClassCreateDefaultMethod( + TypeStore typeStore, + String methodName, + String defaultTransportChannelProvider, + String defaultTransportChannelProviderBuilder, + String defaultApiClientHeaderProviderBuilder) { List bodyStatements = new ArrayList<>(); // Initialize the builder: Builder builder = new Builder((ClientContext) null); @@ -1608,15 +1763,32 @@ private static MethodDefinition createNestedClassCreateDefaultMethod(TypeStore t bodyStatements.add(EMPTY_LINE_STATEMENT); List bodyExprs = new ArrayList<>(); - bodyExprs.add( - MethodInvocationExpr.builder() - .setExprReferenceExpr(builderVarExpr) - .setMethodName("setTransportChannelProvider") - .setArguments( - MethodInvocationExpr.builder() - .setMethodName("defaultTransportChannelProvider") - .build()) - .build()); + + if (defaultTransportChannelProvider != null) { + bodyExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(builderVarExpr) + .setMethodName("setTransportChannelProvider") + .setArguments( + MethodInvocationExpr.builder() + .setMethodName(defaultTransportChannelProvider) + .build()) + .build()); + } else { + bodyExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(builderVarExpr) + .setMethodName("setTransportChannelProvider") + .setArguments( + MethodInvocationExpr.builder() + .setExprReferenceExpr( + MethodInvocationExpr.builder() + .setMethodName(defaultTransportChannelProviderBuilder) + .build()) + .setMethodName("build") + .build()) + .build()); + } bodyExprs.add( MethodInvocationExpr.builder() @@ -1640,7 +1812,7 @@ private static MethodDefinition createNestedClassCreateDefaultMethod(TypeStore t MethodInvocationExpr.builder() .setExprReferenceExpr( MethodInvocationExpr.builder() - .setMethodName("defaultApiClientHeaderProviderBuilder") + .setMethodName(defaultApiClientHeaderProviderBuilder) .build()) .setMethodName("build") .build()) @@ -1683,7 +1855,7 @@ private static MethodDefinition createNestedClassCreateDefaultMethod(TypeStore t .setScope(ScopeNode.PRIVATE) .setIsStatic(true) .setReturnType(builderType) - .setName("createDefault") + .setName(methodName) .setBody(bodyStatements) .setReturnExpr(returnExpr) .build(); @@ -1867,10 +2039,12 @@ private TypeStore createDynamicTypes(Service service, String pakkage) { pakkage, Arrays.asList( thisClassName, - getTransportContext().classNames().getTransportServiceStubClassName(service), ClassNames.getServiceStubSettingsClassName(service), ClassNames.getServiceStubClassName(service))); + typeStore.putAll( + pakkage, getTransportContext().classNames().getTransportServiceStubClassNames(service)); + // Nested builder class. typeStore.put(pakkage, NESTED_BUILDER_CLASS_NAME, true, thisClassName); diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java new file mode 100644 index 0000000000..3aa79a452f --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java @@ -0,0 +1,1077 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.common; + +import com.google.api.core.BetaApi; +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.core.BackgroundResourceAggregation; +import com.google.api.gax.rpc.BidiStreamingCallable; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.ClientStreamingCallable; +import com.google.api.gax.rpc.LongRunningClient; +import com.google.api.gax.rpc.OperationCallable; +import com.google.api.gax.rpc.RequestParamsExtractor; +import com.google.api.gax.rpc.ServerStreamingCallable; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.ClassDefinition; +import com.google.api.generator.engine.ast.CommentStatement; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.EmptyLineStatement; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.ExprStatement; +import com.google.api.generator.engine.ast.JavaDocComment; +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.MethodInvocationExpr; +import com.google.api.generator.engine.ast.NewObjectExpr; +import com.google.api.generator.engine.ast.ReferenceConstructorExpr; +import com.google.api.generator.engine.ast.ScopeNode; +import com.google.api.generator.engine.ast.Statement; +import com.google.api.generator.engine.ast.ThisObjectValue; +import com.google.api.generator.engine.ast.ThrowExpr; +import com.google.api.generator.engine.ast.TryCatchStatement; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.engine.ast.VaporReference; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.comment.StubCommentComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.PackageChecker; +import com.google.api.generator.gapic.model.GapicClass; +import com.google.api.generator.gapic.model.GapicClass.Kind; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.Message; +import com.google.api.generator.gapic.model.Method; +import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.gapic.utils.JavaStyle; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.annotation.Generated; + +public abstract class AbstractTransportServiceStubClassComposer implements ClassComposer { + private static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create(); + + private static final String METHOD_DESCRIPTOR_NAME_PATTERN = "%sMethodDescriptor"; + private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; + private static final String PAGED_CALLABLE_CLASS_MEMBER_PATTERN = "%sPagedCallable"; + + private static final String BACKGROUND_RESOURCES_MEMBER_NAME = "backgroundResources"; + private static final String CALLABLE_NAME = "Callable"; + private static final String CALLABLE_FACTORY_MEMBER_NAME = "callableFactory"; + private static final String CALLABLE_CLASS_MEMBER_PATTERN = "%sCallable"; + private static final String OPERATION_CALLABLE_CLASS_MEMBER_PATTERN = "%sOperationCallable"; + private static final String OPERATION_CALLABLE_NAME = "OperationCallable"; + // private static final String OPERATIONS_STUB_MEMBER_NAME = "operationsStub"; + private static final String PAGED_CALLABLE_NAME = "PagedCallable"; + + protected static final TypeStore FIXED_TYPESTORE = createStaticTypes(); + + private final TransportContext transportContext; + + protected AbstractTransportServiceStubClassComposer(TransportContext transportContext) { + this.transportContext = transportContext; + } + + public TransportContext getTransportContext() { + return transportContext; + } + + private static TypeStore createStaticTypes() { + List concreteClazzes = + Arrays.asList( + BackgroundResource.class, + BackgroundResourceAggregation.class, + BetaApi.class, + BidiStreamingCallable.class, + ClientContext.class, + ClientStreamingCallable.class, + Generated.class, + ImmutableMap.class, + InterruptedException.class, + IOException.class, + Operation.class, + OperationCallable.class, + RequestParamsExtractor.class, + ServerStreamingCallable.class, + TimeUnit.class, + UnaryCallable.class); + return new TypeStore(concreteClazzes); + } + + @Override + public GapicClass generate(GapicContext context, Service service) { + String pakkage = service.pakkage() + ".stub"; + TypeStore typeStore = createDynamicTypes(service, pakkage); + String className = getTransportContext().classNames().getTransportServiceStubClassName(service); + GapicClass.Kind kind = Kind.STUB; + + Map protoMethodNameToDescriptorVarExprs = + createProtoMethodNameToDescriptorClassMembers( + service, getTransportContext().methodDescriptorClass()); + + Map callableClassMemberVarExprs = + createCallableClassMembers(service, typeStore); + + Map classMemberVarExprs = new LinkedHashMap<>(); + classMemberVarExprs.put( + BACKGROUND_RESOURCES_MEMBER_NAME, + VariableExpr.withVariable( + Variable.builder() + .setName(BACKGROUND_RESOURCES_MEMBER_NAME) + .setType(FIXED_TYPESTORE.get("BackgroundResource")) + .build())); + if (generateOperationsStubLogic(service)) { + // Transport-specific service stub may have only one element of the following, thus get(0). + TypeNode opeationsStubType = getTransportOperationsStubType(service); + classMemberVarExprs.put( + getTransportContext().transportOperationsStubNames().get(0), + VariableExpr.withVariable( + Variable.builder() + .setName(getTransportContext().transportOperationsStubNames().get(0)) + .setType(opeationsStubType) + .build())); + } + + boolean operationPollingMethod = checkOperationPollingMethod(service); + if(operationPollingMethod) { + VariableExpr longRunningVarExpr = declareLongRunningClient(); + if (longRunningVarExpr != null) { + classMemberVarExprs.put("longRunningClient", longRunningVarExpr); + } + } + + classMemberVarExprs.put( + CALLABLE_FACTORY_MEMBER_NAME, + VariableExpr.withVariable( + Variable.builder() + .setName(CALLABLE_FACTORY_MEMBER_NAME) + .setType(getTransportContext().stubCallableFactoryType()) + .build())); + + Map messageTypes = context.messages(); + List classStatements = + createClassStatements( + service, + protoMethodNameToDescriptorVarExprs, + callableClassMemberVarExprs, + classMemberVarExprs, + messageTypes); + + StubCommentComposer commentComposer = + new StubCommentComposer(getTransportContext().transportName()); + + ClassDefinition classDef = + ClassDefinition.builder() + .setPackageString(pakkage) + .setHeaderCommentStatements( + commentComposer.createTransportServiceStubClassHeaderComments( + service.name(), service.isDeprecated())) + .setAnnotations(createClassAnnotations(service)) + .setScope(ScopeNode.PUBLIC) + .setName(className) + .setExtendsType( + typeStore.get(getTransportContext().classNames().getServiceStubClassName(service))) + .setStatements(classStatements) + .setMethods( + createClassMethods( + service, + typeStore, + classMemberVarExprs, + callableClassMemberVarExprs, + protoMethodNameToDescriptorVarExprs)) + .build(); + return GapicClass.create(kind, classDef); + } + + protected abstract Statement createMethodDescriptorVariableDecl( + Service service, Method protoMethod, VariableExpr methodDescriptorVarExpr, Map messageTypes); + + protected boolean generateOperationsStubLogic(Service service) { + return true; + } + + protected List createOperationsStubGetterMethod( + Service service, VariableExpr operationsStubVarExpr) { + if (!generateOperationsStubLogic(service)) { + return Collections.emptyList(); + } + + String methodName = + String.format( + "get%s", + JavaStyle.toUpperCamelCase(getTransportContext().transportOperationsStubNames().get(0))); + + return Arrays.asList( + MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setReturnType(operationsStubVarExpr.type()) + .setName(methodName) + .setReturnExpr(operationsStubVarExpr) + .build()); + } + + protected abstract Expr createTransportSettingsInitExpr( + Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr); + + protected List createGetMethodDescriptorsMethod( + Service service, + TypeStore typeStore, + Map protoMethodNameToDescriptorVarExprs) { + return Arrays.asList(); + } + + protected List createClassStatements( + Service service, + Map protoMethodNameToDescriptorVarExprs, + Map callableClassMemberVarExprs, + Map classMemberVarExprs, + Map messageTypes) { + List classStatements = new ArrayList<>(); + for (Statement statement : + createMethodDescriptorVariableDecls(service, protoMethodNameToDescriptorVarExprs, messageTypes)) { + classStatements.add(statement); + classStatements.add(EMPTY_LINE_STATEMENT); + } + + classStatements.addAll(createClassMemberFieldDeclarations(callableClassMemberVarExprs)); + classStatements.add(EMPTY_LINE_STATEMENT); + + classStatements.addAll(createClassMemberFieldDeclarations(classMemberVarExprs)); + return classStatements; + } + + protected List createMethodDescriptorVariableDecls( + Service service, Map protoMethodNameToDescriptorVarExprs, Map messageTypes) { + return service.methods().stream() + .map( + m -> + createMethodDescriptorVariableDecl( + service, m, protoMethodNameToDescriptorVarExprs.get(m.name()), messageTypes)) + .collect(Collectors.toList()); + } + + private static List createClassMemberFieldDeclarations( + Map fieldNameToVarExprs) { + return fieldNameToVarExprs.values().stream() + .map( + v -> + ExprStatement.withExpr( + v.toBuilder() + .setIsDecl(true) + .setScope(ScopeNode.PRIVATE) + .setIsFinal(true) + .build())) + .collect(Collectors.toList()); + } + + protected Map createProtoMethodNameToDescriptorClassMembers( + Service service, Class descriptorClass) { + return service.methods().stream() + .collect( + Collectors.toMap( + Method::name, + m -> + VariableExpr.withVariable( + Variable.builder() + .setName( + String.format( + METHOD_DESCRIPTOR_NAME_PATTERN, + JavaStyle.toLowerCamelCase(m.name()))) + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(descriptorClass) + .setGenerics( + Arrays.asList( + m.inputType().reference(), + m.outputType().reference())) + .build())) + .build()), + (u, v) -> { + throw new IllegalStateException(); + }, + LinkedHashMap::new)); + } + + private Map createCallableClassMembers( + Service service, TypeStore typeStore) { + Map callableClassMembers = new LinkedHashMap<>(); + // Using a for-loop because the output cardinality is not a 1:1 mapping to the input set. + for (Method protoMethod : service.methods()) { + String javaStyleProtoMethodName = JavaStyle.toLowerCamelCase(protoMethod.name()); + String callableName = String.format(CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); + callableClassMembers.put( + callableName, + VariableExpr.withVariable( + Variable.builder() + .setName(callableName) + .setType(getCallableType(protoMethod)) + .build())); + if (protoMethod.hasLro()) { + callableName = + String.format(OPERATION_CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); + callableClassMembers.put( + callableName, + VariableExpr.withVariable( + Variable.builder() + .setName(callableName) + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(OperationCallable.class) + .setGenerics( + Arrays.asList( + protoMethod.inputType().reference(), + protoMethod.lro().responseType().reference(), + protoMethod.lro().metadataType().reference())) + .build())) + .build())); + } + if (protoMethod.isPaged()) { + callableName = String.format(PAGED_CALLABLE_CLASS_MEMBER_PATTERN, javaStyleProtoMethodName); + callableClassMembers.put( + callableName, + VariableExpr.withVariable( + Variable.builder() + .setName(callableName) + .setType( + TypeNode.withReference( + getCallableType(protoMethod) + .reference() + .copyAndSetGenerics( + Arrays.asList( + protoMethod.inputType().reference(), + typeStore + .get( + String.format( + PAGED_RESPONSE_TYPE_NAME_PATTERN, + protoMethod.name())) + .reference())))) + .build())); + } + } + return callableClassMembers; + } + + protected List createClassAnnotations(Service service) { + List annotations = new ArrayList<>(); + if (!PackageChecker.isGaApi(service.pakkage())) { + annotations.add(AnnotationNode.withType(FIXED_TYPESTORE.get("BetaApi"))); + } + + if (service.isDeprecated()) { + annotations.add(AnnotationNode.withType(TypeNode.DEPRECATED)); + } + + annotations.add( + AnnotationNode.builder() + .setType(FIXED_TYPESTORE.get("Generated")) + .setDescription("by gapic-generator-java") + .build()); + return annotations; + } + + protected List createClassMethods( + Service service, + TypeStore typeStore, + Map classMemberVarExprs, + Map callableClassMemberVarExprs, + Map protoMethodNameToDescriptorVarExprs) { + List javaMethods = new ArrayList<>(); + javaMethods.addAll(createStaticCreatorMethods(service, typeStore, "newBuilder")); + javaMethods.addAll( + createConstructorMethods( + service, + typeStore, + classMemberVarExprs, + callableClassMemberVarExprs, + protoMethodNameToDescriptorVarExprs)); + javaMethods.addAll( + createGetMethodDescriptorsMethod(service, typeStore, protoMethodNameToDescriptorVarExprs)); + javaMethods.addAll( + createOperationsStubGetterMethod( + service, classMemberVarExprs.get(getTransportContext().transportOperationsStubNames().get(0)))); + javaMethods.addAll(createCallableGetterMethods(callableClassMemberVarExprs)); + javaMethods.addAll( + createStubOverrideMethods(classMemberVarExprs.get(BACKGROUND_RESOURCES_MEMBER_NAME), service)); + return javaMethods; + } + + protected List createStaticCreatorMethods(Service service, TypeStore typeStore, String newBuilderMethod) { + TypeNode creatorMethodReturnType = + typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); + Function, MethodDefinition.Builder> creatorMethodStarterFn = + argList -> + MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setIsFinal(true) + .setReturnType(creatorMethodReturnType) + .setName("create") + .setArguments( + argList.stream() + .map(v -> v.toBuilder().setIsDecl(true).build()) + .collect(Collectors.toList())) + .setThrowsExceptions( + Arrays.asList( + TypeNode.withReference(ConcreteReference.withClazz(IOException.class)))); + + Function, Expr> instantiatorExprFn = + argList -> + NewObjectExpr.builder().setType(creatorMethodReturnType).setArguments(argList).build(); + + TypeNode stubSettingsType = + typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); + VariableExpr settingsVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("settings").setType(stubSettingsType).build()); + + TypeNode clientContextType = FIXED_TYPESTORE.get("ClientContext"); + VariableExpr clientContextVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("clientContext").setType(clientContextType).build()); + + VariableExpr callableFactoryVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setName("callableFactory") + .setType(getTransportContext().stubCallableFactoryType()) + .build()); + + MethodInvocationExpr clientContextCreateMethodExpr = + MethodInvocationExpr.builder() + .setMethodName("create") + .setStaticReferenceType(clientContextType) + .setArguments(Arrays.asList(settingsVarExpr)) + .build(); + MethodInvocationExpr settingsBuilderMethodExpr = + MethodInvocationExpr.builder() + .setMethodName(newBuilderMethod) + .setStaticReferenceType(stubSettingsType) + .build(); + settingsBuilderMethodExpr = + MethodInvocationExpr.builder() + .setMethodName("build") + .setExprReferenceExpr(settingsBuilderMethodExpr) + .build(); + + return Arrays.asList( + creatorMethodStarterFn + .apply(Arrays.asList(settingsVarExpr)) + .setReturnExpr( + instantiatorExprFn.apply( + Arrays.asList(settingsVarExpr, clientContextCreateMethodExpr))) + .build(), + creatorMethodStarterFn + .apply(Arrays.asList(clientContextVarExpr)) + .setReturnExpr( + instantiatorExprFn.apply( + Arrays.asList(settingsBuilderMethodExpr, clientContextVarExpr))) + .build(), + creatorMethodStarterFn + .apply(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) + .setReturnExpr( + instantiatorExprFn.apply( + Arrays.asList( + settingsBuilderMethodExpr, clientContextVarExpr, callableFactoryVarExpr))) + .build()); + } + + protected List createConstructorMethods( + Service service, + TypeStore typeStore, + Map classMemberVarExprs, + Map callableClassMemberVarExprs, + Map protoMethodNameToDescriptorVarExprs) { + TypeNode stubSettingsType = + typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); + VariableExpr settingsVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("settings").setType(stubSettingsType).build()); + + TypeNode clientContextType = FIXED_TYPESTORE.get("ClientContext"); + VariableExpr clientContextVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("clientContext").setType(clientContextType).build()); + + VariableExpr callableFactoryVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setName("callableFactory") + .setType(getTransportContext().stubCallableFactoryType()) + .build()); + + TypeNode thisClassType = + typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); + TypeNode ioExceptionType = + TypeNode.withReference(ConcreteReference.withClazz(IOException.class)); + + BiFunction, List, MethodDefinition> ctorMakerFn = + (args, body) -> + MethodDefinition.constructorBuilder() + .setScope(ScopeNode.PROTECTED) + .setReturnType(thisClassType) + .setHeaderCommentStatements(Arrays.asList(createProtectedCtorComment(service))) + .setArguments( + args.stream() + .map(v -> v.toBuilder().setIsDecl(true).build()) + .collect(Collectors.toList())) + .setThrowsExceptions(Arrays.asList(ioExceptionType)) + .setBody(body) + .build(); + + // First constructor method. + MethodDefinition firstCtor = + ctorMakerFn.apply( + Arrays.asList(settingsVarExpr, clientContextVarExpr), + Arrays.asList( + ExprStatement.withExpr( + ReferenceConstructorExpr.thisBuilder() + .setType(thisClassType) + .setArguments( + settingsVarExpr, + clientContextVarExpr, + NewObjectExpr.builder() + .setType( + typeStore.get( + getTransportContext() + .classNames() + .getTransportServiceCallableFactoryClassName(service))) + .build()) + .build()))); + + Expr thisExpr = + ValueExpr.withValue( + ThisObjectValue.withType( + typeStore.get( + getTransportContext().classNames().getTransportServiceStubClassName(service)))); + // Body of the second constructor method. + List secondCtorStatements = new ArrayList<>(); + List secondCtorExprs = new ArrayList<>(); + secondCtorExprs.add( + AssignmentExpr.builder() + .setVariableExpr( + classMemberVarExprs.get("callableFactory").toBuilder() + .setExprReferenceExpr(thisExpr) + .build()) + .setValueExpr(callableFactoryVarExpr) + .build()); + VariableExpr operationsStubClassVarExpr = classMemberVarExprs.get(getTransportContext().transportOperationsStubNames().get(0)); + //TODO: refactor this + if (generateOperationsStubLogic(service)) { + TypeNode opeationsStubType = getTransportOperationsStubType(service); + secondCtorExprs.add( + AssignmentExpr.builder() + .setVariableExpr( + operationsStubClassVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType(opeationsStubType) + .setMethodName("create") + .setArguments(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) + .setReturnType(operationsStubClassVarExpr.type()) + .build()) + .build()); + } + secondCtorStatements.addAll( + secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + secondCtorExprs.clear(); + secondCtorStatements.add(EMPTY_LINE_STATEMENT); + + // Transport settings local variables. + Map javaStyleMethodNameToTransportSettingsVarExprs = + service.methods().stream() + .collect( + Collectors.toMap( + m -> JavaStyle.toLowerCamelCase(m.name()), + m -> + VariableExpr.withVariable( + Variable.builder() + .setName( + String.format( + "%sTransportSettings", + JavaStyle.toLowerCamelCase(m.name()))) + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(getTransportContext().callSettingsClass()) + .setGenerics( + Arrays.asList( + m.inputType().reference(), + m.outputType().reference())) + .build())) + .build()))); + + secondCtorExprs.addAll( + service.methods().stream() + .map( + m -> + createTransportSettingsInitExpr( + m, + javaStyleMethodNameToTransportSettingsVarExprs.get( + JavaStyle.toLowerCamelCase(m.name())), + protoMethodNameToDescriptorVarExprs.get(m.name()))) + .collect(Collectors.toList())); + secondCtorStatements.addAll( + secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + secondCtorExprs.clear(); + secondCtorStatements.add(EMPTY_LINE_STATEMENT); + + // Initialize Callable variables. + secondCtorExprs.addAll( + callableClassMemberVarExprs.entrySet().stream() + .map( + e -> + createCallableInitExpr( + e.getKey(), + e.getValue(), + callableFactoryVarExpr, + settingsVarExpr, + clientContextVarExpr, + operationsStubClassVarExpr, + thisExpr, + javaStyleMethodNameToTransportSettingsVarExprs)) + .collect(Collectors.toList())); + secondCtorStatements.addAll( + secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + secondCtorExprs.clear(); + secondCtorStatements.add(EMPTY_LINE_STATEMENT); + + + secondCtorStatements.addAll(createLongRunningClient(service, typeStore)); + + // Instantiate backgroundResources. + MethodInvocationExpr getBackgroundResourcesMethodExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(clientContextVarExpr) + .setMethodName("getBackgroundResources") + .build(); + + VariableExpr backgroundResourcesVarExpr = classMemberVarExprs.get("backgroundResources"); + secondCtorExprs.add( + AssignmentExpr.builder() + .setVariableExpr( + backgroundResourcesVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr( + NewObjectExpr.builder() + .setType(FIXED_TYPESTORE.get("BackgroundResourceAggregation")) + .setArguments(Arrays.asList(getBackgroundResourcesMethodExpr)) + .build()) + .build()); + secondCtorStatements.addAll( + secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + secondCtorExprs.clear(); + + // Second constructor method. + MethodDefinition secondCtor = + ctorMakerFn.apply( + Arrays.asList(settingsVarExpr, clientContextVarExpr, callableFactoryVarExpr), + secondCtorStatements); + + return Arrays.asList(firstCtor, secondCtor); + } + + protected List createLongRunningClient(Service service, TypeStore typeStore) { + return ImmutableList.of(); + } + + protected VariableExpr declareLongRunningClient() { + return null; + } + + private Expr createCallableInitExpr( + String callableVarName, + VariableExpr callableVarExpr, + VariableExpr callableFactoryVarExpr, + VariableExpr settingsVarExpr, + VariableExpr clientContextVarExpr, + VariableExpr operationsStubClassVarExpr, + Expr thisExpr, + Map javaStyleMethodNameToTransportSettingsVarExprs) { + boolean isOperation = callableVarName.endsWith(OPERATION_CALLABLE_NAME); + boolean isPaged = callableVarName.endsWith(PAGED_CALLABLE_NAME); + int sublength = 0; + if (isOperation) { + sublength = OPERATION_CALLABLE_NAME.length(); + } else if (isPaged) { + sublength = PAGED_CALLABLE_NAME.length(); + } else { + sublength = CALLABLE_NAME.length(); + } + String javaStyleMethodName = callableVarName.substring(0, callableVarName.length() - sublength); + List creatorMethodArgVarExprs = null; + Expr transportSettingsVarExpr = + javaStyleMethodNameToTransportSettingsVarExprs.get(javaStyleMethodName); + if (transportSettingsVarExpr == null && isOperation) { + // Try again, in case the name dtection above was inaccurate. + isOperation = false; + sublength = CALLABLE_NAME.length(); + javaStyleMethodName = callableVarName.substring(0, callableVarName.length() - sublength); + transportSettingsVarExpr = + javaStyleMethodNameToTransportSettingsVarExprs.get(javaStyleMethodName); + } + Preconditions.checkNotNull( + transportSettingsVarExpr, + String.format( + "No transport settings variable found for method name %s", javaStyleMethodName)); + if (isOperation) { + creatorMethodArgVarExprs = + Arrays.asList( + transportSettingsVarExpr, + MethodInvocationExpr.builder() + .setExprReferenceExpr(settingsVarExpr) + .setMethodName(String.format("%sOperationSettings", javaStyleMethodName)) + .build(), + clientContextVarExpr, + operationsStubClassVarExpr); + } else { + creatorMethodArgVarExprs = + Arrays.asList( + transportSettingsVarExpr, + MethodInvocationExpr.builder() + .setExprReferenceExpr(settingsVarExpr) + .setMethodName(String.format("%sSettings", javaStyleMethodName)) + .build(), + clientContextVarExpr); + } + + Optional callableCreatorMethodName = + getCallableCreatorMethodName(callableVarExpr.type()); + + Expr initExpr; + if (callableCreatorMethodName.isPresent()) { + initExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(callableFactoryVarExpr) + .setMethodName(callableCreatorMethodName.get()) + .setArguments(creatorMethodArgVarExprs) + .setReturnType(callableVarExpr.type()) + .build(); + } else { + initExpr = ValueExpr.createNullExpr(); + } + + return AssignmentExpr.builder() + .setVariableExpr(callableVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr(initExpr) + .build(); + } + + protected Optional getCallableCreatorMethodName(TypeNode callableVarExprType) { + final String typeName = callableVarExprType.reference().name(); + String streamName = "Unary"; + + // Special handling for pagination methods. + if (callableVarExprType.reference().generics().size() == 2 + && callableVarExprType.reference().generics().get(1).name().endsWith("PagedResponse")) { + streamName = "Paged"; + } else { + if (typeName.startsWith("Client")) { + streamName = "ClientStreaming"; + } else if (typeName.startsWith("Server")) { + streamName = "ServerStreaming"; + } else if (typeName.startsWith("Bidi")) { + streamName = "BidiStreaming"; + } else if (typeName.startsWith("Operation")) { + streamName = "Operation"; + } + } + return Optional.of(String.format("create%sCallable", streamName)); + } + + private static List createCallableGetterMethods( + Map callableClassMemberVarExprs) { + return callableClassMemberVarExprs.entrySet().stream() + .map( + e -> + MethodDefinition.builder() + .setIsOverride(true) + .setScope(ScopeNode.PUBLIC) + .setReturnType(e.getValue().type()) + .setName(e.getKey()) + .setReturnExpr(e.getValue()) + .build()) + .collect(Collectors.toList()); + } + + private List createStubOverrideMethods( + VariableExpr backgroundResourcesVarExpr, Service service) { + Function methodMakerStarterFn = + methodName -> + MethodDefinition.builder() + .setIsOverride(true) + .setScope(ScopeNode.PUBLIC) + .setName(methodName); + + Function voidMethodMakerFn = + methodName -> + methodMakerStarterFn + .apply(methodName) + .setReturnType(TypeNode.VOID) + .setBody( + Arrays.asList( + ExprStatement.withExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(backgroundResourcesVarExpr) + .setMethodName(methodName) + .build()))) + .build(); + + Function booleanMethodMakerFn = + methodName -> + methodMakerStarterFn + .apply(methodName) + .setReturnType(TypeNode.BOOLEAN) + .setReturnExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(backgroundResourcesVarExpr) + .setMethodName(methodName) + .setReturnType(TypeNode.BOOLEAN) + .build()) + .build(); + + // Generate the close() method: + // @Override + // public final void close() { + // try { + // backgroundResources.close(); + // } catch (RuntimeException e) { + // throw e; + // } catch (Exception e) { + // throw new IllegalStateException("Failed to close resource", e); + // } + // } + + VariableExpr catchRuntimeExceptionVarExpr = + VariableExpr.builder() + .setVariable( + Variable.builder() + .setType(TypeNode.withExceptionClazz(RuntimeException.class)) + .setName("e") + .build()) + .build(); + VariableExpr catchExceptionVarExpr = + VariableExpr.builder() + .setVariable( + Variable.builder() + .setType(TypeNode.withExceptionClazz(Exception.class)) + .setName("e") + .build()) + .build(); + List javaMethods = new ArrayList<>(); + if (service.operationPollingMethod() != null) { + javaMethods.addAll(createLongRunningClientGetters()); + } + javaMethods.add( + methodMakerStarterFn + .apply("close") + .setIsFinal(true) + .setReturnType(TypeNode.VOID) + .setBody( + Arrays.asList( + TryCatchStatement.builder() + .setTryBody( + Arrays.asList( + ExprStatement.withExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(backgroundResourcesVarExpr) + .setMethodName("close") + .build()))) + .addCatch( + catchRuntimeExceptionVarExpr.toBuilder().setIsDecl(true).build(), + Arrays.asList( + ExprStatement.withExpr( + ThrowExpr.builder() + .setThrowExpr(catchRuntimeExceptionVarExpr) + .build()))) + .addCatch( + catchExceptionVarExpr.toBuilder().setIsDecl(true).build(), + Arrays.asList( + ExprStatement.withExpr( + ThrowExpr.builder() + .setType( + TypeNode.withExceptionClazz( + IllegalStateException.class)) + .setMessageExpr(String.format("Failed to close resource")) + .setCauseExpr(catchExceptionVarExpr) + .build()))) + .build())) + .build()); + javaMethods.add(voidMethodMakerFn.apply("shutdown")); + javaMethods.add(booleanMethodMakerFn.apply("isShutdown")); + javaMethods.add(booleanMethodMakerFn.apply("isTerminated")); + javaMethods.add(voidMethodMakerFn.apply("shutdownNow")); + + List awaitTerminationArgs = + Arrays.asList( + VariableExpr.withVariable( + Variable.builder().setName("duration").setType(TypeNode.LONG).build()), + VariableExpr.withVariable( + Variable.builder() + .setName("unit") + .setType(FIXED_TYPESTORE.get("TimeUnit")) + .build())); + javaMethods.add( + methodMakerStarterFn + .apply("awaitTermination") + .setReturnType(TypeNode.BOOLEAN) + .setArguments( + awaitTerminationArgs.stream() + .map(v -> v.toBuilder().setIsDecl(true).build()) + .collect(Collectors.toList())) + .setThrowsExceptions(Arrays.asList(FIXED_TYPESTORE.get("InterruptedException"))) + .setReturnExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(backgroundResourcesVarExpr) + .setMethodName("awaitTermination") + .setArguments( + awaitTerminationArgs.stream() + .map(v -> (Expr) v) + .collect(Collectors.toList())) + .setReturnType(TypeNode.BOOLEAN) + .build()) + .build()); + return javaMethods; + } + + private boolean checkOperationPollingMethod(Service service) { + for(Method method : service.methods()) { + if(method.isOperationPollingMethod()) { + return true; + } + } + return false; + } + + protected List createLongRunningClientGetters() { + VariableExpr longRunningClient = + VariableExpr.withVariable( + Variable.builder() + .setName("longRunningClient") + .setType( + TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) + .build()); + + return ImmutableList.of( + MethodDefinition.builder() + .setName("longRunningClient") + .setScope(ScopeNode.PUBLIC) + .setIsOverride(true) + .setReturnType( + TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) + .setReturnExpr(longRunningClient) + .build()); + } + + private TypeStore createDynamicTypes(Service service, String stubPakkage) { + TypeStore typeStore = new TypeStore(); + typeStore.putAll( + stubPakkage, + Arrays.asList( + getTransportContext().classNames().getTransportServiceStubClassName(service), + getTransportContext().classNames().getServiceStubSettingsClassName(service), + getTransportContext().classNames().getServiceStubClassName(service), + getTransportContext() + .classNames() + .getTransportServiceCallableFactoryClassName(service))); + // Pagination types. + typeStore.putAll( + service.pakkage(), + service.methods().stream() + .filter(m -> m.isPaged()) + .map(m -> String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, m.name())) + .collect(Collectors.toList()), + true, + getTransportContext().classNames().getServiceClientClassName(service)); + return typeStore; + } + + private static TypeNode getCallableType(Method protoMethod) { + TypeNode callableType = FIXED_TYPESTORE.get("UnaryCallable"); + switch (protoMethod.stream()) { + case CLIENT: + callableType = FIXED_TYPESTORE.get("ClientStreamingCallable"); + break; + case SERVER: + callableType = FIXED_TYPESTORE.get("ServerStreamingCallable"); + break; + case BIDI: + callableType = FIXED_TYPESTORE.get("BidiStreamingCallable"); + break; + case NONE: + // Fall through + default: + // Fall through + } + + return TypeNode.withReference( + callableType + .reference() + .copyAndSetGenerics( + Arrays.asList( + protoMethod.inputType().reference(), protoMethod.outputType().reference()))); + } + + private CommentStatement createProtectedCtorComment(Service service) { + return CommentStatement.withComment( + JavaDocComment.withComment( + String.format( + "Constructs an instance of %s, using the given settings. This is protected so that" + + " it is easy to make a subclass, but otherwise, the static factory methods" + + " should be preferred.", + getTransportContext().classNames().getTransportServiceStubClassName(service)))); + } + + protected String getProtoRpcFullMethodName(Service protoService, Method protoMethod) { + if (protoMethod.isMixin()) { + return String.format("%s/%s", protoMethod.mixedInApiName(), protoMethod.name()); + } + + return String.format( + "%s.%s/%s", protoService.protoPakkage(), protoService.name(), protoMethod.name()); + } + + protected TypeNode getTransportOperationsStubType(Service service) { + TypeNode transportOpeationsStubType = service.operationServiceStubType(); + if (transportOpeationsStubType == null) { + transportOpeationsStubType = getTransportContext().transportOperationsStubTypes().get(0); + } + else { + transportOpeationsStubType = TypeNode.withReference( + VaporReference.builder() + .setName("HttpJson" + transportOpeationsStubType.reference().simpleName()) + .setPakkage(transportOpeationsStubType.reference().pakkage()) + .build()); + } + + return transportOpeationsStubType; + } +} \ No newline at end of file diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java index 4a20961399..4497495d67 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java @@ -248,7 +248,9 @@ public static Expr createLroSettingsBuilderExpr( Method method, VariableExpr builderVarExpr, VariableExpr retryableCodeDefsVarExpr, - VariableExpr retryParamDefsVarExpr) { + VariableExpr retryParamDefsVarExpr, + TypeNode operationResponseTransformer, + TypeNode operationMetadataTransformer) { Preconditions.checkState( method.hasLro(), String.format( @@ -325,10 +327,7 @@ public static Expr createLroSettingsBuilderExpr( .setMethodName("setResponseTransformer") .setArguments( MethodInvocationExpr.builder() - .setStaticReferenceType( - TypeNode.withReference( - ConcreteReference.withClazz( - ProtoOperationTransformers.ResponseTransformer.class))) + .setStaticReferenceType(operationResponseTransformer) .setMethodName("create") .setArguments(classFieldRefFn.apply(method.lro().responseType())) .build()) @@ -339,10 +338,7 @@ public static Expr createLroSettingsBuilderExpr( .setMethodName("setMetadataTransformer") .setArguments( MethodInvocationExpr.builder() - .setStaticReferenceType( - TypeNode.withReference( - ConcreteReference.withClazz( - ProtoOperationTransformers.MetadataTransformer.class))) + .setStaticReferenceType(operationMetadataTransformer) .setMethodName("create") .setArguments(classFieldRefFn.apply(method.lro().metadataType())) .build()) diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java deleted file mode 100644 index 1c8bed3ccb..0000000000 --- a/src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.api.generator.gapic.composer.common; - -import com.google.api.core.BetaApi; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.generator.engine.ast.AnnotationNode; -import com.google.api.generator.engine.ast.ClassDefinition; -import com.google.api.generator.engine.ast.ExprStatement; -import com.google.api.generator.engine.ast.MethodDefinition; -import com.google.api.generator.engine.ast.Reference; -import com.google.api.generator.engine.ast.ScopeNode; -import com.google.api.generator.engine.ast.Statement; -import com.google.api.generator.engine.ast.ThrowExpr; -import com.google.api.generator.engine.ast.TypeNode; -import com.google.api.generator.gapic.composer.comment.StubCommentComposer; -import com.google.api.generator.gapic.composer.store.TypeStore; -import com.google.api.generator.gapic.composer.utils.ClassNames; -import com.google.api.generator.gapic.composer.utils.PackageChecker; -import com.google.api.generator.gapic.model.GapicClass; -import com.google.api.generator.gapic.model.GapicClass.Kind; -import com.google.api.generator.gapic.model.GapicContext; -import com.google.api.generator.gapic.model.Message; -import com.google.api.generator.gapic.model.Method; -import com.google.api.generator.gapic.model.Service; -import com.google.api.generator.gapic.utils.JavaStyle; -import com.google.longrunning.Operation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import javax.annotation.Generated; - -public class ServiceStubClassComposer implements ClassComposer { - private static final ServiceStubClassComposer INSTANCE = new ServiceStubClassComposer(); - private static final String DOT = "."; - private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; - - private ServiceStubClassComposer() {} - - public static ServiceStubClassComposer instance() { - return INSTANCE; - } - - @Override - public GapicClass generate(GapicContext context, Service service) { - Map messageTypes = context.messages(); - TypeStore typeStore = createTypes(service, messageTypes); - String className = ClassNames.getServiceStubClassName(service); - GapicClass.Kind kind = Kind.STUB; - String pakkage = String.format("%s.stub", service.pakkage()); - - ClassDefinition classDef = - ClassDefinition.builder() - .setPackageString(pakkage) - .setHeaderCommentStatements( - StubCommentComposer.createServiceStubClassHeaderComments( - service.name(), service.isDeprecated())) - .setAnnotations(createClassAnnotations(service, typeStore)) - .setIsAbstract(true) - .setImplementsTypes(createClassImplements(typeStore)) - .setName(className) - .setMethods(createClassMethods(service, messageTypes, typeStore)) - .setScope(ScopeNode.PUBLIC) - .build(); - return GapicClass.create(kind, classDef); - } - - private static List createClassAnnotations(Service service, TypeStore typeStore) { - List annotations = new ArrayList<>(); - if (!PackageChecker.isGaApi(service.pakkage())) { - annotations.add(AnnotationNode.withType(typeStore.get("BetaApi"))); - } - - if (service.isDeprecated()) { - annotations.add(AnnotationNode.withType(TypeNode.DEPRECATED)); - } - - annotations.add( - AnnotationNode.builder() - .setType(typeStore.get("Generated")) - .setDescription("by gapic-generator-java") - .build()); - return annotations; - } - - private static List createClassImplements(TypeStore typeStore) { - return Arrays.asList(typeStore.get("BackgroundResource")); - } - - private static List createClassMethods( - Service service, Map messageTypes, TypeStore typeStore) { - boolean hasLroClient = hasLroMethods(service); - List methods = new ArrayList<>(); - if (hasLroClient) { - TypeNode operationsStubType = service.operationServiceStubType(); - if (operationsStubType == null) { - operationsStubType = typeStore.get("OperationsStub"); - } - methods.add(createOperationsStubGetter(typeStore, operationsStubType)); - } - methods.addAll(createCallableGetters(service, messageTypes, typeStore)); - methods.addAll(createBackgroundResourceMethodOverrides()); - return methods; - } - - private static List createCallableGetters( - Service service, Map messageTypes, TypeStore typeStore) { - // Use a traditional for-loop since the output cardinality is not necessarily 1:1 with that of - // service.methods(). - List javaMethods = new ArrayList<>(); - for (Method method : service.methods()) { - if (method.hasLro()) { - javaMethods.add(createOperationCallableGetter(method, typeStore)); - } - if (method.isPaged()) { - javaMethods.add(createPagedCallableGetter(method, typeStore)); - } - javaMethods.add(createCallableGetter(method, typeStore)); - } - return javaMethods; - } - - private static MethodDefinition createOperationCallableGetter( - Method method, TypeStore typeStore) { - return createCallableGetterHelper(method, typeStore, true, false); - } - - private static MethodDefinition createPagedCallableGetter(Method method, TypeStore typeStore) { - return createCallableGetterHelper(method, typeStore, false, true); - } - - private static MethodDefinition createCallableGetter(Method method, TypeStore typeStore) { - return createCallableGetterHelper(method, typeStore, false, false); - } - - private static MethodDefinition createCallableGetterHelper( - Method method, TypeStore typeStore, boolean isLroCallable, boolean isPaged) { - TypeNode returnType; - switch (method.stream()) { - case CLIENT: - returnType = typeStore.get("ClientStreamingCallable"); - break; - case SERVER: - returnType = typeStore.get("ServerStreamingCallable"); - break; - case BIDI: - returnType = typeStore.get("BidiStreamingCallable"); - break; - case NONE: - // Fall through. - default: - returnType = typeStore.get(isLroCallable ? "OperationCallable" : "UnaryCallable"); - } - - String methodName = - String.format( - "%s%sCallable", - JavaStyle.toLowerCamelCase(method.name()), - (isLroCallable ? "Operation" : isPaged ? "Paged" : "")); - List genericRefs = new ArrayList<>(); - genericRefs.add(method.inputType().reference()); - if (method.hasLro() && isLroCallable) { - genericRefs.add(method.lro().responseType().reference()); - genericRefs.add(method.lro().metadataType().reference()); - } else if (isPaged) { - genericRefs.add( - typeStore - .get(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, method.name())) - .reference()); - } else { - genericRefs.add(method.outputType().reference()); - } - - List annotations = - method.isDeprecated() - ? Arrays.asList(AnnotationNode.withType(TypeNode.DEPRECATED)) - : Collections.emptyList(); - - returnType = TypeNode.withReference(returnType.reference().copyAndSetGenerics(genericRefs)); - - return MethodDefinition.builder() - .setAnnotations(annotations) - .setScope(ScopeNode.PUBLIC) - .setReturnType(returnType) - .setName(methodName) - .setBody(createThrowUOEBody(methodName, typeStore)) - .build(); - } - - private static MethodDefinition createOperationsStubGetter(TypeStore typeStore, TypeNode operationsStubType) { - String methodName = "getOperationsStub"; - return MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setReturnType(operationsStubType) - .setName(methodName) - .setBody(createThrowUOEBody(methodName, typeStore)) - .build(); - } - - private static List createBackgroundResourceMethodOverrides() { - MethodDefinition closeMethod = - MethodDefinition.builder() - .setIsOverride(true) - .setScope(ScopeNode.PUBLIC) - .setIsAbstract(true) - .setReturnType(TypeNode.VOID) - .setName("close") - .build(); - return Arrays.asList(closeMethod); - } - - private static boolean hasLroMethods(Service service) { - for (Method method : service.methods()) { - if (method.hasLro()) { - return true; - } - } - return false; - } - - private static TypeStore createTypes(Service service, Map messageTypes) { - List concreteClazzes = - Arrays.asList( - BackgroundResource.class, - BetaApi.class, - BidiStreamingCallable.class, - ClientStreamingCallable.class, - Generated.class, - Operation.class, - OperationCallable.class, - ServerStreamingCallable.class, - UnaryCallable.class, - UnsupportedOperationException.class); - TypeStore typeStore = new TypeStore(concreteClazzes); - - typeStore.put("com.google.longrunning.stub", "OperationsStub"); - - // Pagination types. - typeStore.putAll( - service.pakkage(), - service.methods().stream() - .filter(m -> m.isPaged()) - .map(m -> String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, m.name())) - .collect(Collectors.toList()), - true, - ClassNames.getServiceClientClassName(service)); - - return typeStore; - } - - private static List createThrowUOEBody(String methodName, TypeStore typeStore) { - return Arrays.asList( - ExprStatement.withExpr( - ThrowExpr.builder() - .setType(typeStore.get("UnsupportedOperationException")) - .setMessageExpr(String.format("Not implemented: %s()", methodName)) - .build())); - } - - private static String getClientClassName(Service service) { - return String.format("%sClient", service.overriddenName()); - } -} diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java b/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java index 4058fbafbf..507ff662ca 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java @@ -19,6 +19,7 @@ import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Transport; import com.google.auto.value.AutoValue; +import java.util.List; import javax.annotation.Nullable; @AutoValue @@ -29,36 +30,57 @@ public abstract class TransportContext { // For AbstractServiceStubClassComposer public abstract Transport transport(); + @Nullable public abstract String transportName(); + @Nullable public abstract Class callSettingsClass(); + @Nullable public abstract TypeNode stubCallableFactoryType(); + @Nullable public abstract Class methodDescriptorClass(); - @Nullable - public abstract TypeNode transportOperationsStubType(); + public abstract List transportOperationsStubTypes(); + + public abstract List transportOperationsStubNames(); // For AbstractServiceSettingsClassComposer - public abstract Class instantiatingChannelProviderClass(); + public abstract List> instantiatingChannelProviderClasses(); - public abstract String defaultTransportProviderBuilderName(); + public abstract List> instantiatingChannelProviderBuilderClasses(); + + public abstract List defaultTransportProviderBuilderNames(); + + public abstract List transportApiClientHeaderProviderBuilderNames(); // For AbstractServiceStubSettingsClassComposer - public abstract TypeNode transportChannelType(); + public abstract List transportChannelTypes(); - public abstract String transportGetterName(); + public abstract List transportGetterNames(); // For AbstractServiceCallableFactoryClassComposer + @Nullable public abstract TypeNode transportCallSettingsType(); + @Nullable public abstract TypeNode transportCallableFactoryType(); - public abstract TypeNode operationsStubType(); + public abstract List operationsStubTypes(); + @Nullable public abstract String transportCallSettingsName(); + // For RetrySettingsComposer + public abstract TypeNode operationResponseTransformerType(); + + public abstract TypeNode operationMetadataTransformerType(); + + public abstract List operationsClientTypes(); + + public abstract List operationsClientNames(); + protected static TypeNode classToType(Class clazz) { return TypeNode.withReference(ConcreteReference.withClazz(clazz)); } @@ -82,15 +104,21 @@ public abstract static class Builder { public abstract Builder setMethodDescriptorClass(Class methodDescriptorClass); - public abstract Builder setInstantiatingChannelProviderClass( - Class instantiatingChannelProviderClass); + public abstract Builder setInstantiatingChannelProviderClasses( + List> instantiatingChannelProviderClasses); + + public abstract Builder setInstantiatingChannelProviderBuilderClasses( + List> instantiatingChannelProviderBuilderClasses); + + public abstract Builder setDefaultTransportProviderBuilderNames( + List defaultTransportProviderBuilderNames); - public abstract Builder setDefaultTransportProviderBuilderName( - String defaultTransportProviderBuilderName); + public abstract Builder setTransportApiClientHeaderProviderBuilderNames( + List transportApiClientHeaderProviderBuilderNames); - public abstract Builder setTransportChannelType(TypeNode transportChannelType); + public abstract Builder setTransportChannelTypes(List transportChannelTypes); - public abstract Builder setTransportGetterName(String transportGetterName); + public abstract Builder setTransportGetterNames(List transportGetterNames); public abstract Builder setTransportCallSettingsType(TypeNode transportCallSettingsType); @@ -98,9 +126,19 @@ public abstract Builder setDefaultTransportProviderBuilderName( public abstract Builder setTransportCallSettingsName(String transportCallSettingsName); - public abstract Builder setTransportOperationsStubType(TypeNode transportOperationsStubType); + public abstract Builder setTransportOperationsStubTypes(List transportOperationsStubTypes); + + public abstract Builder setTransportOperationsStubNames(List transportOperationsStubNames); + + public abstract Builder setOperationsStubTypes(List operationsStubType); + + public abstract Builder setOperationResponseTransformerType(TypeNode operationResponseTransformerType); + + public abstract Builder setOperationMetadataTransformerType(TypeNode operationMetadataTransformerType); + + public abstract Builder setOperationsClientTypes(List operationsClientTypes); - public abstract Builder setOperationsStubType(TypeNode operationsStubType); + public abstract Builder setOperationsClientNames(List operationsClientNames); public abstract TransportContext build(); } diff --git a/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java b/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java index 75562d680c..5af2722fd7 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java @@ -58,8 +58,11 @@ public class DefaultValueComposer { TypeNode.withReference(ConcreteReference.withClazz(ByteString.class)); public static Expr createDefaultValue( - MethodArgument methodArg, Map resourceNames) { - if (methodArg.isResourceNameHelper()) { + MethodArgument methodArg, + Map resourceNames, + boolean forceResourceNameInitializer) { + if (methodArg.isResourceNameHelper() + || (forceResourceNameInitializer && methodArg.field().hasResourceReference())) { Preconditions.checkState( methodArg.field().hasResourceReference(), String.format( @@ -72,10 +75,21 @@ public static Expr createDefaultValue( String.format( "No resource name found for reference %s", methodArg.field().resourceReference().resourceTypeString())); - return createDefaultValue( - resourceName, - resourceNames.values().stream().collect(Collectors.toList()), - methodArg.field().name()); + Expr defValue = + createDefaultValue( + resourceName, + resourceNames.values().stream().collect(Collectors.toList()), + methodArg.field().name()); + + if (!methodArg.isResourceNameHelper() && methodArg.field().hasResourceReference()) { + defValue = + MethodInvocationExpr.builder() + .setExprReferenceExpr(defValue) + .setMethodName("toString") + .setReturnType(TypeNode.STRING) + .build(); + } + return defValue; } if (methodArg.type().equals(methodArg.field().type())) { diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java index 9a291669e2..5f9b27963e 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java @@ -19,9 +19,12 @@ import com.google.api.gax.grpc.GrpcStubCallableFactory; import com.google.api.gax.grpc.GrpcTransportChannel; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.api.gax.grpc.ProtoOperationTransformers; import com.google.api.generator.gapic.composer.common.TransportContext; import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Transport; +import com.google.common.collect.ImmutableList; +import com.google.longrunning.OperationsClient; import com.google.longrunning.stub.GrpcOperationsStub; import com.google.longrunning.stub.OperationsStub; import io.grpc.MethodDescriptor; @@ -36,18 +39,33 @@ public abstract class GrpcContext extends TransportContext { .setCallSettingsClass(GrpcCallSettings.class) .setStubCallableFactoryType(classToType(GrpcStubCallableFactory.class)) .setMethodDescriptorClass(MethodDescriptor.class) - .setTransportOperationsStubType(classToType(GrpcOperationsStub.class)) + .setTransportOperationsStubTypes(ImmutableList.of(classToType(GrpcOperationsStub.class))) + .setTransportOperationsStubNames(ImmutableList.of("operationsStub")) // For grpc.ServiceSettingsClassComposer - .setInstantiatingChannelProviderClass(InstantiatingGrpcChannelProvider.Builder.class) - .setDefaultTransportProviderBuilderName("defaultGrpcTransportProviderBuilder") + .setInstantiatingChannelProviderClasses( + ImmutableList.of(InstantiatingGrpcChannelProvider.class)) + .setInstantiatingChannelProviderBuilderClasses( + ImmutableList.of(InstantiatingGrpcChannelProvider.Builder.class)) + .setDefaultTransportProviderBuilderNames( + ImmutableList.of("defaultGrpcTransportProviderBuilder")) + .setTransportApiClientHeaderProviderBuilderNames( + ImmutableList.of("defaultGrpcApiClientHeaderProviderBuilder")) // For grpc.ServiceStubSettingsClassComposer - .setTransportChannelType(classToType(GrpcTransportChannel.class)) - .setTransportGetterName("getGrpcTransportName") + .setTransportChannelTypes(ImmutableList.of(classToType(GrpcTransportChannel.class))) + .setTransportGetterNames(ImmutableList.of("getGrpcTransportName")) // For grpc.GrpcServiceCallableFactoryClassComposer .setTransportCallSettingsType(classToType(GrpcCallSettings.class)) .setTransportCallableFactoryType(classToType(GrpcCallableFactory.class)) - .setOperationsStubType(classToType(OperationsStub.class)) + .setOperationsStubTypes(ImmutableList.of(classToType(OperationsStub.class))) .setTransportCallSettingsName("grpcCallSettings") + // For RetrySettingsComposer + .setOperationResponseTransformerType( + classToType(ProtoOperationTransformers.ResponseTransformer.class)) + .setOperationMetadataTransformerType( + classToType(ProtoOperationTransformers.MetadataTransformer.class)) + // For ServiceClientClassComposer + .setOperationsClientTypes(ImmutableList.of(classToType(OperationsClient.class))) + .setOperationsClientNames(ImmutableList.of("operationsClient")) .build(); public static TransportContext instance() { diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java index 3fc25a95b2..f3ad194c51 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java @@ -22,7 +22,6 @@ import com.google.api.generator.engine.ast.Expr; import com.google.api.generator.engine.ast.ExprStatement; import com.google.api.generator.engine.ast.LambdaExpr; -import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.Statement; @@ -31,7 +30,7 @@ import com.google.api.generator.engine.ast.ValueExpr; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; -import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; +import com.google.api.generator.gapic.composer.common.AbstractTransportServiceStubClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.model.HttpBindings.HttpBinding; import com.google.api.generator.gapic.model.Message; @@ -53,7 +52,7 @@ import java.util.function.Function; import java.util.stream.Collectors; -public class GrpcServiceStubClassComposer extends AbstractServiceStubClassComposer { +public class GrpcServiceStubClassComposer extends AbstractTransportServiceStubClassComposer { private static final GrpcServiceStubClassComposer INSTANCE = new GrpcServiceStubClassComposer(); // Legacy support for the original reroute_to_grpc_interface option in gapic.yaml. These two APIs @@ -193,18 +192,6 @@ protected EnumRefExpr getMethodDescriptorMethodTypeExpr(Method protoMethod) { .build(); } - @Override - protected List createOperationsStubGetterMethod( - VariableExpr operationsStubVarExpr) { - return Arrays.asList( - MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setReturnType(operationsStubVarExpr.type()) - .setName("getOperationsStub") - .setReturnExpr(operationsStubVarExpr) - .build()); - } - @Override protected Expr createTransportSettingsInitExpr( Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr) { diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposer.java new file mode 100644 index 0000000000..9b95e9c280 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.generator.gapic.composer.grpc; + +import com.google.api.generator.gapic.composer.common.AbstractServiceClientClassComposer; + +public class ServiceClientClassComposer extends AbstractServiceClientClassComposer { + private static final ServiceClientClassComposer INSTANCE = new ServiceClientClassComposer(); + + protected ServiceClientClassComposer() { + super(GrpcContext.instance()); + } + + public static ServiceClientClassComposer instance() { + return INSTANCE; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java index 15b05ee765..75bd4c0133 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java @@ -143,7 +143,8 @@ protected MethodDefinition createStartStaticServerMethod( Service service, GapicContext context, Map classMemberVarExprs, - TypeStore typeStore) { + TypeStore typeStore, + String newBuilderMethod) { VariableExpr serviceHelperVarExpr = classMemberVarExprs.get(SERVICE_HELPER_VAR_NAME); Function serviceToVarExprFn = s -> classMemberVarExprs.get(getMockServiceVarName(s)); @@ -1055,6 +1056,12 @@ protected List createStreamingRpcExceptionTestStatements( return statements; } + @Override + protected Expr createDefaultValue( + MethodArgument methodArg, Map resourceNames) { + return DefaultValueComposer.createDefaultValue(methodArg, resourceNames, false); + } + @Override protected List createRpcLroExceptionTestCatchBody( VariableExpr exceptionExpr, boolean isStreaming) { diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposer.java new file mode 100644 index 0000000000..1e11c5087d --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.generator.gapic.composer.grpc; + +import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; + +public class ServiceStubClassComposer extends AbstractServiceStubClassComposer { + private static final ServiceStubClassComposer INSTANCE = new ServiceStubClassComposer(); + + protected ServiceStubClassComposer() { + super(GrpcContext.instance()); + } + + public static ServiceStubClassComposer instance() { + return INSTANCE; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java index 6d0b8e221d..a80feffcd5 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java @@ -18,14 +18,12 @@ import com.google.api.gax.grpc.GaxGrpcProperties; import com.google.api.gax.grpc.GrpcTransportChannel; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.generator.engine.ast.AnnotationNode; import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.Expr; import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.PrimitiveValue; import com.google.api.generator.engine.ast.ScopeNode; -import com.google.api.generator.engine.ast.StringObjectValue; import com.google.api.generator.engine.ast.TypeNode; import com.google.api.generator.engine.ast.ValueExpr; import com.google.api.generator.engine.ast.Variable; @@ -33,9 +31,9 @@ import com.google.api.generator.gapic.composer.comment.SettingsCommentComposer; import com.google.api.generator.gapic.composer.common.AbstractServiceStubSettingsClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; -import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Service; import java.util.Arrays; +import java.util.Collections; import java.util.List; public class ServiceStubSettingsClassComposer extends AbstractServiceStubSettingsClassComposer { @@ -62,37 +60,17 @@ private static TypeStore createStaticTypes() { } @Override - protected MethodDefinition createDefaultTransportTransportProviderBuilderMethod() { - // Create the defaultGrpcTransportProviderBuilder method. - TypeNode returnType = - TypeNode.withReference( - ConcreteReference.withClazz(InstantiatingGrpcChannelProvider.Builder.class)); - MethodInvocationExpr transportChannelProviderBuilderExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_GRPC_TYPESTORE.get(InstantiatingGrpcChannelProvider.class.getSimpleName())) - .setMethodName("newBuilder") - .build(); - transportChannelProviderBuilderExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(transportChannelProviderBuilderExpr) - .setMethodName("setMaxInboundMessageSize") - .setArguments( - VariableExpr.builder() - .setVariable( - Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build()) - .setStaticReferenceType(TypeNode.INT_OBJECT) - .build()) - .setReturnType(returnType) - .build(); - return MethodDefinition.builder() - .setHeaderCommentStatements( - SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) + protected Expr initializeTransportProviderBuilder( + MethodInvocationExpr transportChannelProviderBuilderExpr, TypeNode returnType) { + return MethodInvocationExpr.builder() + .setExprReferenceExpr(transportChannelProviderBuilderExpr) + .setMethodName("setMaxInboundMessageSize") + .setArguments( + VariableExpr.builder() + .setVariable(Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build()) + .setStaticReferenceType(TypeNode.INT_OBJECT) + .build()) .setReturnType(returnType) - .setName("defaultGrpcTransportProviderBuilder") - .setReturnExpr(transportChannelProviderBuilderExpr) .build(); } @@ -138,69 +116,16 @@ protected MethodDefinition createDefaultCredentialsProviderBuilderMethod() { } @Override - protected MethodDefinition createDefaultApiClientHeaderProviderBuilderMethod( + protected List createApiClientHeaderProviderBuilderMethods( Service service, TypeStore typeStore) { - // Create the defaultApiClientHeaderProviderBuilder method. - TypeNode returnType = - TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); - MethodInvocationExpr returnExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("ApiClientHeaderProvider")) - .setMethodName("newBuilder") - .build(); - - MethodInvocationExpr versionArgExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GaxProperties")) - .setMethodName("getLibraryVersion") - .setArguments( - VariableExpr.builder() - .setVariable( - Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) - .setStaticReferenceType( - typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) - .build()) - .build(); - - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setGeneratedLibToken") - .setArguments(ValueExpr.withValue(StringObjectValue.withValue("gapic")), versionArgExpr) - .build(); - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setTransportToken") - .setArguments( - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_GRPC_TYPESTORE.get(GaxGrpcProperties.class.getSimpleName())) - .setMethodName("getGrpcTokenName") - .build(), - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_GRPC_TYPESTORE.get(GaxGrpcProperties.class.getSimpleName())) - .setMethodName("getGrpcVersion") - .build()) - .setReturnType(returnType) - .build(); - - AnnotationNode annotation = - AnnotationNode.builder() - .setType(FIXED_TYPESTORE.get("BetaApi")) - .setDescription( - "The surface for customizing headers is not stable yet and may change in the" - + " future.") - .build(); - return MethodDefinition.builder() - .setAnnotations(Arrays.asList(annotation)) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setReturnType(returnType) - .setName("defaultApiClientHeaderProviderBuilder") - .setReturnExpr(returnExpr) - .build(); + return Collections.singletonList( + createApiClientHeaderProviderBuilderMethod( + service, + typeStore, + "defaultApiClientHeaderProviderBuilder", + FIXED_GRPC_TYPESTORE.get(GaxGrpcProperties.class.getSimpleName()), + "getGrpcTokenName", + "getGrpcVersion")); } @Override diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/BUILD.bazel new file mode 100644 index 0000000000..ea77aab100 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/BUILD.bazel @@ -0,0 +1,55 @@ +load("@rules_java//java:defs.bzl", "java_library") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "grpcrest_files", + srcs = glob(["*.java"]), +) + +java_library( + name = "grpcrest", + srcs = [ + ":grpcrest_files", + ], + deps = [ + "//:service_config_java_proto", + "//src/main/java/com/google/api/generator/engine/ast", + "//src/main/java/com/google/api/generator/engine/writer", + "//src/main/java/com/google/api/generator/gapic:status_java_proto", + "//src/main/java/com/google/api/generator/gapic/composer/comment", + "//src/main/java/com/google/api/generator/gapic/composer/common", + "//src/main/java/com/google/api/generator/gapic/composer/defaultvalue", + "//src/main/java/com/google/api/generator/gapic/composer/resourcename", + "//src/main/java/com/google/api/generator/gapic/composer/rest", + "//src/main/java/com/google/api/generator/gapic/composer/samplecode", + "//src/main/java/com/google/api/generator/gapic/composer/store", + "//src/main/java/com/google/api/generator/gapic/composer/utils", + "//src/main/java/com/google/api/generator/gapic/model", + "//src/main/java/com/google/api/generator/gapic/utils", + "//src/main/java/com/google/api/generator/util", + "@com_google_api_api_common//jar", + "@com_google_api_gax_java//gax", + "@com_google_api_gax_java//gax:gax_testlib", + "@com_google_api_gax_java//gax-grpc:gax_grpc", + "@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", + "@com_google_api_gax_java//gax-httpjson:gax_httpjson", + "@com_google_api_gax_java//gax-httpjson:gax_httpjson_testlib", + "@com_google_code_findbugs_jsr305//jar", + "@com_google_googleapis//gapic/metadata:metadata_java_proto", + "@com_google_googleapis//google/api:api_java_proto", + "@com_google_googleapis//google/longrunning:longrunning_java_proto", + "@com_google_googleapis//google/rpc:rpc_java_proto", + "@com_google_guava_guava//jar", + "@com_google_http_client_google_http_client//jar", + "@com_google_protobuf//:protobuf_java", + "@com_google_protobuf//:protobuf_java_util", + "@com_google_protobuf//java/core", + "@io_grpc_grpc_java//api", + "@io_grpc_grpc_java//protobuf", + "@io_grpc_grpc_java//stub", + "@javax_annotation_javax_annotation_api//jar", + "@junit_junit//jar", + "@org_threeten_threetenbp//jar", + ], +) diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/GrpcRestContext.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/GrpcRestContext.java new file mode 100644 index 0000000000..3f84bf3c97 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/GrpcRestContext.java @@ -0,0 +1,95 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.grpc.GrpcTransportChannel; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.api.gax.grpc.ProtoOperationTransformers; +import com.google.api.gax.httpjson.HttpJsonTransportChannel; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.httpjson.longrunning.stub.HttpJsonOperationsStub; +import com.google.api.generator.gapic.composer.common.TransportContext; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Transport; +import com.google.common.collect.ImmutableList; +import com.google.longrunning.OperationsClient; +import com.google.longrunning.stub.GrpcOperationsStub; +import com.google.longrunning.stub.OperationsStub; + +public abstract class GrpcRestContext extends TransportContext { + private static final TransportContext INSTANCE = + GrpcRestContext.builder() + .setClassNames(new ClassNames("Grpc", "HttpJson")) + .setTransport(Transport.GRPC_REST) + .setTransportName(null) + // For grpcrest.GrpcServiceStubClassComposer + .setCallSettingsClass(null) + .setStubCallableFactoryType(null) + .setMethodDescriptorClass(null) + .setTransportOperationsStubTypes( + ImmutableList.of( + classToType(GrpcOperationsStub.class), classToType(HttpJsonOperationsStub.class))) + .setTransportOperationsStubNames( + ImmutableList.of("operationsStub", "httpJsonOperationsStub")) + // For grpcrest.ServiceSettingsClassComposer + .setInstantiatingChannelProviderClasses( + ImmutableList.of( + InstantiatingGrpcChannelProvider.class, + InstantiatingHttpJsonChannelProvider.class)) + .setInstantiatingChannelProviderBuilderClasses( + ImmutableList.of( + InstantiatingGrpcChannelProvider.Builder.class, + InstantiatingHttpJsonChannelProvider.Builder.class)) + .setDefaultTransportProviderBuilderNames( + ImmutableList.of( + "defaultGrpcTransportProviderBuilder", "defaultHttpJsonTransportProviderBuilder")) + .setTransportApiClientHeaderProviderBuilderNames( + ImmutableList.of( + "defaultGrpcApiClientHeaderProviderBuilder", + "defaultHttpJsonApiClientHeaderProviderBuilder")) + // For grpcrest.ServiceStubSettingsClassComposer + .setTransportChannelTypes( + ImmutableList.of( + classToType(GrpcTransportChannel.class), + classToType(HttpJsonTransportChannel.class))) + .setTransportGetterNames( + ImmutableList.of("getGrpcTransportName", "getHttpJsonTransportName")) + // For grpcrest.GrpcServiceCallableFactoryClassComposer + .setTransportCallSettingsType(null) + .setTransportCallableFactoryType(null) + .setOperationsStubTypes( + ImmutableList.of( + classToType(OperationsStub.class), classToType(BackgroundResource.class))) + .setTransportCallSettingsName(null) + // For RetrySettingsComposer + // TODO: fix when LRO for REST RE FIXED + .setOperationResponseTransformerType( + classToType(ProtoOperationTransformers.ResponseTransformer.class)) + .setOperationMetadataTransformerType( + classToType(ProtoOperationTransformers.MetadataTransformer.class)) + // For ServiceClientClassComposer + .setOperationsClientTypes( + ImmutableList.of( + classToType(OperationsClient.class), + classToType(com.google.api.gax.httpjson.longrunning.OperationsClient.class))) + .setOperationsClientNames( + ImmutableList.of("operationsClient", "httpJsonOperationsClient")) + .build(); + + public static TransportContext instance() { + return INSTANCE; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceClientTestClassComposer.java new file mode 100644 index 0000000000..9f9bbafc05 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceClientTestClassComposer.java @@ -0,0 +1,57 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.common.AbstractServiceClientTestClassComposer; +import com.google.api.generator.gapic.composer.rest.ServiceClientTestClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.model.GapicClass; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.Service; +import java.util.Map; + +public class HttpJsonServiceClientTestClassComposer extends ServiceClientTestClassComposer { + private static final HttpJsonServiceClientTestClassComposer INSTANCE = + new HttpJsonServiceClientTestClassComposer(); + + protected HttpJsonServiceClientTestClassComposer() { + super(); + } + + public static AbstractServiceClientTestClassComposer instance() { + return INSTANCE; + } + + @Override + protected GapicClass generate(String className, GapicContext context, Service service) { + return super.generate( + getTransportContext().classNames().getServiceClientTestClassNames(service).get(0), + context, + service); + } + + @Override + protected MethodDefinition createStartStaticServerMethod( + Service service, + GapicContext context, + Map classMemberVarExprs, + TypeStore typeStore, + String newBuilderMethod) { + return super.createStartStaticServerMethod( + service, context, classMemberVarExprs, typeStore, "newHttpJsonBuilder"); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceStubClassComposer.java new file mode 100644 index 0000000000..7f99c81287 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/HttpJsonServiceStubClassComposer.java @@ -0,0 +1,40 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.model.Service; +import java.util.List; + +public class HttpJsonServiceStubClassComposer + extends com.google.api.generator.gapic.composer.rest.HttpJsonServiceStubClassComposer { + private static final HttpJsonServiceStubClassComposer INSTANCE = + new HttpJsonServiceStubClassComposer(); + + protected HttpJsonServiceStubClassComposer() { + super(); + } + + public static HttpJsonServiceStubClassComposer instance() { + return INSTANCE; + } + + @Override + protected List createStaticCreatorMethods( + Service service, TypeStore typeStore, String newBuilderMethod) { + return super.createStaticCreatorMethods(service, typeStore, "newHttpJsonBuilder"); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceClientClassComposer.java new file mode 100644 index 0000000000..7529b002cf --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceClientClassComposer.java @@ -0,0 +1,29 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.gapic.composer.common.AbstractServiceClientClassComposer; + +public class ServiceClientClassComposer extends AbstractServiceClientClassComposer { + private static final ServiceClientClassComposer INSTANCE = new ServiceClientClassComposer(); + + protected ServiceClientClassComposer() { + super(GrpcRestContext.instance()); + } + + public static ServiceClientClassComposer instance() { + return INSTANCE; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceSettingsClassComposer.java new file mode 100644 index 0000000000..03ff5dc54a --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceSettingsClassComposer.java @@ -0,0 +1,68 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.gapic.composer.common.AbstractServiceSettingsClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.model.Service; +import java.util.ArrayList; +import java.util.List; + +public class ServiceSettingsClassComposer extends AbstractServiceSettingsClassComposer { + private static final ServiceSettingsClassComposer INSTANCE = new ServiceSettingsClassComposer(); + + protected ServiceSettingsClassComposer() { + super(GrpcRestContext.instance()); + } + + public static ServiceSettingsClassComposer instance() { + return INSTANCE; + } + + @Override + protected List createNestedBuilderCreatorMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { + List methods = new ArrayList<>(); + + methods.addAll( + super.createNestedBuilderCreatorMethods(service, typeStore, "newBuilder", "createDefault")); + methods.addAll( + super.createNestedBuilderCreatorMethods( + service, typeStore, "newHttpJsonBuilder", "createHttpJsonDefault")); + + return methods; + } + + @Override + protected List createNewBuilderMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { + List methods = new ArrayList<>(); + + methods.addAll( + super.createNewBuilderMethods(service, typeStore, "newBuilder", "createDefault")); + methods.addAll( + super.createNewBuilderMethods( + service, typeStore, "newHttpJsonBuilder", "createHttpJsonDefault")); + + return methods; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubClassComposer.java new file mode 100644 index 0000000000..6be0ef7ac2 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubClassComposer.java @@ -0,0 +1,47 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.ReturnExpr; +import com.google.api.generator.engine.ast.ScopeNode; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; + +public class ServiceStubClassComposer extends AbstractServiceStubClassComposer { + private static final ServiceStubClassComposer INSTANCE = new ServiceStubClassComposer(); + + protected ServiceStubClassComposer() { + super(GrpcRestContext.instance()); + } + + public static ServiceStubClassComposer instance() { + return INSTANCE; + } + + @Override + protected MethodDefinition createOperationsStubGetterMethodDefinition( + TypeNode returnType, String methodName, TypeStore typeStore) { + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setReturnType(returnType) + .setName(methodName) + .setReturnExpr(ReturnExpr.withExpr(ValueExpr.createNullExpr())) + .build(); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubSettingsClassComposer.java new file mode 100644 index 0000000000..6f65ced39c --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceStubSettingsClassComposer.java @@ -0,0 +1,200 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpcrest; + +import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.grpc.GaxGrpcProperties; +import com.google.api.gax.httpjson.GaxHttpJsonProperties; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.MethodInvocationExpr; +import com.google.api.generator.engine.ast.PrimitiveValue; +import com.google.api.generator.engine.ast.ScopeNode; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.comment.SettingsCommentComposer; +import com.google.api.generator.gapic.composer.common.AbstractServiceStubSettingsClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Service; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; + +public class ServiceStubSettingsClassComposer extends AbstractServiceStubSettingsClassComposer { + private static final ServiceStubSettingsClassComposer INSTANCE = + new ServiceStubSettingsClassComposer(); + + public static ServiceStubSettingsClassComposer instance() { + return INSTANCE; + } + + protected ServiceStubSettingsClassComposer() { + super(GrpcRestContext.instance()); + } + + @Override + protected Expr initializeTransportProviderBuilder( + MethodInvocationExpr transportChannelProviderBuilderExpr, TypeNode returnType) { + if (!returnType.reference().isFromPackage("com.google.api.gax.grpc")) { + return transportChannelProviderBuilderExpr; + } + + return MethodInvocationExpr.builder() + .setExprReferenceExpr(transportChannelProviderBuilderExpr) + .setMethodName("setMaxInboundMessageSize") + .setArguments( + VariableExpr.builder() + .setVariable(Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build()) + .setStaticReferenceType(TypeNode.INT_OBJECT) + .build()) + .setReturnType(returnType) + .build(); + } + + @Override + protected MethodDefinition createDefaultCredentialsProviderBuilderMethod() { + TypeNode returnType = + TypeNode.withReference( + ConcreteReference.withClazz(GoogleCredentialsProvider.Builder.class)); + MethodInvocationExpr credsProviderBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("GoogleCredentialsProvider")) + .setMethodName("newBuilder") + .build(); + credsProviderBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(credsProviderBuilderExpr) + .setMethodName("setScopesToApply") + .setArguments(DEFAULT_SERVICE_SCOPES_VAR_EXPR) + .setReturnType(returnType) + .build(); + + // This section is specific to GAPIC clients. It sets UseJwtAccessWithScope value to true to + // enable self signed JWT feature. + credsProviderBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(credsProviderBuilderExpr) + .setMethodName("setUseJwtAccessWithScope") + .setArguments( + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.BOOLEAN).setValue("true").build())) + .setReturnType(returnType) + .build(); + + return MethodDefinition.builder() + .setHeaderCommentStatements( + SettingsCommentComposer.DEFAULT_CREDENTIALS_PROVIDER_BUILDER_METHOD_COMMENT) + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName("defaultCredentialsProviderBuilder") + .setReturnExpr(credsProviderBuilderExpr) + .build(); + } + + @Override + protected List createApiClientHeaderProviderBuilderMethods( + Service service, TypeStore typeStore) { + + TypeNode returnType = + TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); + + return ImmutableList.of( + createApiClientHeaderProviderBuilderMethod( + service, + typeStore, + "defaultGrpcApiClientHeaderProviderBuilder", + TypeNode.withReference(ConcreteReference.withClazz(GaxGrpcProperties.class)), + "getGrpcTokenName", + "getGrpcVersion"), + createApiClientHeaderProviderBuilderMethod( + service, + typeStore, + "defaultHttpJsonApiClientHeaderProviderBuilder", + TypeNode.withReference(ConcreteReference.withClazz(GaxHttpJsonProperties.class)), + "getHttpJsonTokenName", + "getHttpJsonVersion"), + MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName("defaultApiClientHeaderProviderBuilder") + .setReturnExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType( + typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) + .setMethodName("defaultGrpcApiClientHeaderProviderBuilder") + .setReturnType(returnType) + .build()) + .build()); + } + + @Override + public MethodDefinition createDefaultTransportChannelProviderMethod() { + TypeNode returnType = FIXED_TYPESTORE.get("TransportChannelProvider"); + MethodInvocationExpr transportProviderBuilderExpr = + MethodInvocationExpr.builder().setMethodName("defaultGrpcTransportProviderBuilder").build(); + transportProviderBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(transportProviderBuilderExpr) + .setMethodName("build") + .setReturnType(returnType) + .build(); + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName("defaultTransportChannelProvider") + .setReturnExpr(transportProviderBuilderExpr) + .build(); + } + + @Override + protected List createNestedClassCreateDefaultMethods(TypeStore typeStore) { + return ImmutableList.of( + createNestedClassCreateDefaultMethod( + typeStore, + "createDefault", + "defaultTransportChannelProvider", + null, + "defaultApiClientHeaderProviderBuilder"), + createNestedClassCreateDefaultMethod( + typeStore, + "createHttpJsonDefault", + null, + "defaultHttpJsonTransportProviderBuilder", + "defaultHttpJsonApiClientHeaderProviderBuilder")); + } + + @Override + protected List createNewBuilderMethods( + Service service, + TypeStore typeStore, + String newBuilderMethodName, + String createDefaultMethodName) { + List methods = new ArrayList<>(); + methods.addAll( + super.createNewBuilderMethods(service, typeStore, "newBuilder", "createDefault")); + methods.addAll( + super.createNewBuilderMethods( + service, typeStore, "newHttpJsonBuilder", "createHttpJsonDefault")); + return methods; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java index 7f8a966859..a7b525239e 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java @@ -27,13 +27,14 @@ import com.google.api.generator.engine.ast.NewObjectExpr; import com.google.api.generator.engine.ast.Statement; import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; import com.google.api.generator.engine.ast.VaporReference; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.gapic.composer.common.AbstractServiceCallableFactoryClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.model.Service; -import com.google.longrunning.Operation; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -45,7 +46,7 @@ public class HttpJsonServiceCallableFactoryClassComposer new HttpJsonServiceCallableFactoryClassComposer(); private static final TypeNode DEFAULT_OPERATION_TYPE = - TypeNode.withReference(ConcreteReference.withClazz(Operation.class)); + TypeNode.withReference(ConcreteReference.withClazz(Object.class)); private HttpJsonServiceCallableFactoryClassComposer() { super(RestContext.instance()); @@ -127,7 +128,16 @@ protected MethodDefinition createOperationCallableMethod(Service service, TypeSt .collect(Collectors.toList()), Arrays.asList(betaAnnotation)); - List createOperationCallableBody = new ArrayList(2); + List createOperationCallableBody = new ArrayList<>(); + if (service.operationServiceStubType() == null) { + // It is an Operation polling service, it cannot contain LRO methods + return method + .toBuilder() + .setBody(ImmutableList.of()) + .setReturnExpr(ValueExpr.createNullExpr()) + .build(); + } + List arguments = new ArrayList<>(method.arguments()); Variable httpJsonCallSettingsVar = arguments.get(0).variable(); diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java index 39974fe44a..fb45703936 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceStubClassComposer.java @@ -49,8 +49,7 @@ import com.google.api.generator.engine.ast.VaporReference; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; -import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; -import com.google.api.generator.gapic.composer.common.TransportContext; +import com.google.api.generator.gapic.composer.common.AbstractTransportServiceStubClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.model.HttpBindings.HttpBinding; import com.google.api.generator.gapic.model.Message; @@ -66,12 +65,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; -public class HttpJsonServiceStubClassComposer extends AbstractServiceStubClassComposer { +public class HttpJsonServiceStubClassComposer extends AbstractTransportServiceStubClassComposer { private static final HttpJsonServiceStubClassComposer INSTANCE = new HttpJsonServiceStubClassComposer(); @@ -101,6 +101,11 @@ private static TypeStore createStaticTypes() { ProtoRestSerializer.class)); } + @Override + protected boolean generateOperationsStubLogic(Service service) { + return service.hasLroMethods(); + } + @Override protected Statement createMethodDescriptorVariableDecl( Service service, @@ -172,12 +177,11 @@ protected Statement createMethodDescriptorVariableDecl( @Override protected List createOperationsStubGetterMethod( - VariableExpr operationsStubVarExpr) { - return Collections.emptyList(); - } - - public HttpJsonServiceStubClassComposer(TransportContext transportContext) { - super(transportContext); + Service service, VariableExpr operationsStubVarExpr) { + if (!service.hasStandardLroMethods()) { + return Collections.emptyList(); + } + return super.createOperationsStubGetterMethod(service, operationsStubVarExpr); } @Override @@ -348,16 +352,20 @@ private List getRequestFormatterExpr(Method protoMethod) { .apply(expr); extractorVarType = TypeNode.STRING; + boolean asteriskBody = protoMethod.httpBindings().isAsteriskBody(); expr = methodMaker .apply( "setRequestBodyExtractor", Arrays.asList( - createFieldsExtractorClassInstance( + createBodyFieldsExtractorClassInstance( protoMethod, extractorVarType, - protoMethod.httpBindings().bodyParameters(), - "toBody"))) + asteriskBody + ? protoMethod.httpBindings().pathParameters() + : protoMethod.httpBindings().bodyParameters(), + "toBody", + asteriskBody))) .apply(expr); expr = methodMaker.apply("build", Collections.emptyList()).apply(expr); @@ -699,71 +707,148 @@ private List setPollingRequestFactoryExpr( .build()); } - private Expr createFieldsExtractorClassInstance( + private Expr createBodyFieldsExtractorClassInstance( Method method, TypeNode extractorReturnType, Set httpBindingFieldNames, - String serializerMethodName) { + String serializerMethodName, + boolean asteriskBody) { List bodyStatements = new ArrayList<>(); Expr returnExpr = null; - VariableExpr fieldsVarExpr = null; - Expr serializerExpr = null; - if (extractorReturnType.isProtoPrimitiveType()) { - serializerExpr = + Expr serializerExpr = + MethodInvocationExpr.builder() + .setMethodName("create") + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) + .build(); + + VariableExpr requestVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(method.inputType()).setName("request").build()); + Expr bodyRequestExpr = requestVarExpr; + String requestMethodPrefix = "get"; + String bodyParamName = null; + + if (asteriskBody) { + bodyRequestExpr = MethodInvocationExpr.builder() - .setMethodName("create") - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) + .setExprReferenceExpr(requestVarExpr) + .setMethodName("toBuilder") .build(); - if (httpBindingFieldNames.isEmpty()) { - returnExpr = ValueExpr.createNullExpr(); + // In case of `body: "*"` case we send the whole request message as a body, minus the fields + // in the path, therefore the "clear" prefix here. + requestMethodPrefix = "clear"; + } + + Expr prevExpr = bodyRequestExpr; + for (HttpBinding httpBindingFieldName : httpBindingFieldNames) { + // Handle foo.bar cases by descending into the subfields. + MethodInvocationExpr.Builder requestFieldMethodExprBuilder = + MethodInvocationExpr.builder().setExprReferenceExpr(prevExpr); + bodyParamName = JavaStyle.toLowerCamelCase(httpBindingFieldName.name()); + String[] descendantFields = httpBindingFieldName.name().split("\\."); + if (asteriskBody && descendantFields.length > 1) { + // This is the `body: "*"` case, do not clean nested body fields as it a very rare, not + // well-defined case, and it is generally safer to send more than less in such case. + continue; } + for (int i = 0; i < descendantFields.length; i++) { + String currFieldName = descendantFields[i]; + String bindingFieldMethodName = + String.format("%s%s", requestMethodPrefix, JavaStyle.toUpperCamelCase(currFieldName)); + requestFieldMethodExprBuilder = + requestFieldMethodExprBuilder.setMethodName(bindingFieldMethodName); + + if (i < descendantFields.length - 1) { + requestFieldMethodExprBuilder = + MethodInvocationExpr.builder() + .setExprReferenceExpr(requestFieldMethodExprBuilder.build()); + } + } + prevExpr = requestFieldMethodExprBuilder.build(); + } + + if (httpBindingFieldNames.isEmpty() && !asteriskBody) { + returnExpr = ValueExpr.createNullExpr(); } else { - fieldsVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("fields").setType(extractorReturnType).build()); - Expr fieldsAssignExpr = - AssignmentExpr.builder() - .setVariableExpr(fieldsVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr( - NewObjectExpr.builder() - .setType(FIXED_REST_TYPESTORE.get(HashMap.class.getSimpleName())) - .setIsGeneric(true) - .build()) + ImmutableList.Builder paramsPutArgs = ImmutableList.builder(); + if (asteriskBody) { + prevExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(prevExpr) + .setMethodName("build") + .build(); + bodyParamName = "*"; + } + paramsPutArgs.add(ValueExpr.withValue(StringObjectValue.withValue(bodyParamName))); + paramsPutArgs.add(prevExpr); + + returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(serializerExpr) + .setMethodName(serializerMethodName) + .setArguments(paramsPutArgs.build()) + .setReturnType(extractorReturnType) .build(); + } + + // Overrides FieldsExtractor + // (https://github.com/googleapis/gax-java/blob/12b18ee255d3fabe13bb3969df40753b29f830d5/gax-httpjson/src/main/java/com/google/api/gax/httpjson/FieldsExtractor.java). + return LambdaExpr.builder() + .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) + .setBody(bodyStatements) + .setReturnExpr(returnExpr) + .build(); + } - bodyStatements.add(ExprStatement.withExpr(fieldsAssignExpr)); - returnExpr = fieldsVarExpr; + private Expr createFieldsExtractorClassInstance( + Method method, + TypeNode extractorReturnType, + Set httpBindingFieldNames, + String serializerMethodName) { + List bodyStatements = new ArrayList<>(); - TypeNode serializerVarType = - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(ProtoRestSerializer.class) - .setGenerics(method.inputType().reference()) - .build()); + VariableExpr fieldsVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("fields").setType(extractorReturnType).build()); + Expr fieldsAssignExpr = + AssignmentExpr.builder() + .setVariableExpr(fieldsVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + NewObjectExpr.builder() + .setType(FIXED_REST_TYPESTORE.get(HashMap.class.getSimpleName())) + .setIsGeneric(true) + .build()) + .build(); - VariableExpr serializerVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("serializer").setType(serializerVarType).build()); + bodyStatements.add(ExprStatement.withExpr(fieldsAssignExpr)); - Expr serializerAssignExpr = - AssignmentExpr.builder() - .setVariableExpr(serializerVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) - .setMethodName("create") - .setReturnType(serializerVarType) - .build()) - .build(); + TypeNode serializerVarType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(ProtoRestSerializer.class) + .setGenerics(method.inputType().reference()) + .build()); - serializerExpr = serializerVarExpr; + VariableExpr serializerVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("serializer").setType(serializerVarType).build()); - bodyStatements.add(ExprStatement.withExpr(serializerAssignExpr)); - } + Expr serializerAssignExpr = + AssignmentExpr.builder() + .setVariableExpr(serializerVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) + .setMethodName("create") + .setReturnType(serializerVarType) + .build()) + .build(); + + bodyStatements.add(ExprStatement.withExpr(serializerAssignExpr)); VariableExpr requestVarExpr = VariableExpr.withVariable( @@ -806,9 +891,9 @@ private Expr createFieldsExtractorClassInstance( MethodInvocationExpr requestHasExpr = requestFieldHasExprBuilder.build(); ImmutableList.Builder paramsPutArgs = ImmutableList.builder(); - if (fieldsVarExpr != null) { - paramsPutArgs.add(fieldsVarExpr); - } + + paramsPutArgs.add(fieldsVarExpr); + paramsPutArgs.add( ValueExpr.withValue( StringObjectValue.withValue( @@ -817,24 +902,20 @@ private Expr createFieldsExtractorClassInstance( Expr paramsPutExpr = MethodInvocationExpr.builder() - .setExprReferenceExpr(serializerExpr) + .setExprReferenceExpr(serializerVarExpr) .setMethodName(serializerMethodName) .setArguments(paramsPutArgs.build()) .setReturnType(extractorReturnType) .build(); - if (fieldsVarExpr == null) { - returnExpr = paramsPutExpr; + if (httpBindingFieldName.isOptional()) { + bodyStatements.add( + IfStatement.builder() + .setConditionExpr(requestHasExpr) + .setBody(Arrays.asList(ExprStatement.withExpr(paramsPutExpr))) + .build()); } else { - if (httpBindingFieldName.isOptional()) { - bodyStatements.add( - IfStatement.builder() - .setConditionExpr(requestHasExpr) - .setBody(Arrays.asList(ExprStatement.withExpr(paramsPutExpr))) - .build()); - } else { - bodyStatements.add(ExprStatement.withExpr(paramsPutExpr)); - } + bodyStatements.add(ExprStatement.withExpr(paramsPutExpr)); } } @@ -843,7 +924,7 @@ private Expr createFieldsExtractorClassInstance( return LambdaExpr.builder() .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) .setBody(bodyStatements) - .setReturnExpr(returnExpr) + .setReturnExpr(fieldsVarExpr) .build(); } @@ -942,24 +1023,25 @@ protected VariableExpr declareLongRunningClient() { .build()); } - @Override - protected List createLongRunningClientGetter() { - VariableExpr longRunningClient = - VariableExpr.withVariable( - Variable.builder() - .setName("longRunningClient") - .setType( - TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) - .build()); + protected Optional getCallableCreatorMethodName(TypeNode callableVarExprType) { + final String typeName = callableVarExprType.reference().name(); + String streamName = "Unary"; - return ImmutableList.of( - MethodDefinition.builder() - .setName("longRunningClient") - .setScope(ScopeNode.PUBLIC) - .setIsOverride(true) - .setReturnType( - TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) - .setReturnExpr(longRunningClient) - .build()); + // Special handling for pagination methods. + if (callableVarExprType.reference().generics().size() == 2 + && callableVarExprType.reference().generics().get(1).name().endsWith("PagedResponse")) { + streamName = "Paged"; + } else { + if (typeName.startsWith("Client")) { + return Optional.empty(); // not supported in REST transport + } else if (typeName.startsWith("Server")) { + return Optional.empty(); // not supported in REST transport (for now) + } else if (typeName.startsWith("Bidi")) { + return Optional.empty(); // not supported in REST transport + } else if (typeName.startsWith("Operation")) { + streamName = "Operation"; + } + } + return Optional.of(String.format("create%sCallable", streamName)); } } diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java b/src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java index fc5b385427..eab59215bf 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/RestContext.java @@ -21,9 +21,13 @@ import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; import com.google.api.gax.httpjson.HttpJsonTransportChannel; import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.api.gax.httpjson.ProtoOperationTransformers; +import com.google.api.gax.httpjson.longrunning.OperationsClient; +import com.google.api.gax.httpjson.longrunning.stub.HttpJsonOperationsStub; import com.google.api.generator.gapic.composer.common.TransportContext; import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Transport; +import com.google.common.collect.ImmutableList; public abstract class RestContext extends TransportContext { private static final TransportContext INSTANCE = @@ -35,18 +39,35 @@ public abstract class RestContext extends TransportContext { .setCallSettingsClass(HttpJsonCallSettings.class) .setStubCallableFactoryType(classToType(HttpJsonStubCallableFactory.class)) .setMethodDescriptorClass(ApiMethodDescriptor.class) - .setTransportOperationsStubType(null) + .setTransportOperationsStubTypes( + ImmutableList.of(classToType(HttpJsonOperationsStub.class))) + .setTransportOperationsStubNames(ImmutableList.of("httpJsonOperationsStub")) // For httpjson.ServiceSettingsClassComposer - .setInstantiatingChannelProviderClass(InstantiatingHttpJsonChannelProvider.Builder.class) - .setDefaultTransportProviderBuilderName("defaultHttpJsonTransportProviderBuilder") + .setInstantiatingChannelProviderClasses( + ImmutableList.of(InstantiatingHttpJsonChannelProvider.class)) + .setInstantiatingChannelProviderBuilderClasses( + ImmutableList.of(InstantiatingHttpJsonChannelProvider.Builder.class)) + .setDefaultTransportProviderBuilderNames( + ImmutableList.of("defaultHttpJsonTransportProviderBuilder")) + .setTransportApiClientHeaderProviderBuilderNames( + ImmutableList.of("defaultHttpJsonApiClientHeaderProviderBuilder")) // For httpjson.ServiceStubSettingsClassComposer - .setTransportChannelType(classToType(HttpJsonTransportChannel.class)) - .setTransportGetterName("getHttpJsonTransportName") + .setTransportChannelTypes(ImmutableList.of(classToType(HttpJsonTransportChannel.class))) + .setTransportGetterNames(ImmutableList.of("getHttpJsonTransportName")) // For httpjson.HttpJsonServiceCallableFactoryClassComposer .setTransportCallSettingsType(classToType(HttpJsonCallSettings.class)) .setTransportCallableFactoryType(classToType(HttpJsonCallableFactory.class)) - .setOperationsStubType(classToType(BackgroundResource.class)) + // TODO: set to com.google.api.gax.httpjson.longrunning.stub.OperationsStub.class + .setOperationsStubTypes(ImmutableList.of(classToType(BackgroundResource.class))) .setTransportCallSettingsName("httpJsonCallSettings") + // For RetrySettingsComposer + .setOperationResponseTransformerType( + classToType(ProtoOperationTransformers.ResponseTransformer.class)) + .setOperationMetadataTransformerType( + classToType(ProtoOperationTransformers.MetadataTransformer.class)) + // For ServiceClientClassComposer + .setOperationsClientTypes(ImmutableList.of(classToType(OperationsClient.class))) + .setOperationsClientNames(ImmutableList.of("httpJsonOperationsClient")) .build(); public static TransportContext instance() { diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientClassComposer.java new file mode 100644 index 0000000000..9b5f996db7 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientClassComposer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.generator.gapic.composer.rest; + +import com.google.api.generator.gapic.composer.common.AbstractServiceClientClassComposer; + +public class ServiceClientClassComposer extends AbstractServiceClientClassComposer { + private static final ServiceClientClassComposer INSTANCE = new ServiceClientClassComposer(); + + protected ServiceClientClassComposer() { + super(RestContext.instance()); + } + + public static ServiceClientClassComposer instance() { + return INSTANCE; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java index 5eed17f8f2..893777e057 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientTestClassComposer.java @@ -39,6 +39,7 @@ import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.gapic.composer.common.AbstractServiceClientTestClassComposer; +import com.google.api.generator.gapic.composer.defaultvalue.DefaultValueComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.GapicContext; @@ -72,7 +73,7 @@ protected ServiceClientTestClassComposer() { super(RestContext.instance()); } - public static ServiceClientTestClassComposer instance() { + public static AbstractServiceClientTestClassComposer instance() { return INSTANCE; } @@ -125,7 +126,8 @@ protected MethodDefinition createStartStaticServerMethod( Service service, GapicContext context, Map classMemberVarExprs, - TypeStore typeStore) { + TypeStore typeStore, + String newBuilderMethod) { VariableExpr mockServiceVarExpr = classMemberVarExprs.get(MOCK_SERVICE_VAR_NAME); VariableExpr clientVarExpr = classMemberVarExprs.get(CLIENT_VAR_NAME); @@ -167,7 +169,7 @@ protected MethodDefinition createStartStaticServerMethod( Expr settingsBuilderExpr = MethodInvocationExpr.builder() .setStaticReferenceType(settingsType) - .setMethodName("newBuilder") + .setMethodName(newBuilderMethod) .build(); Expr transportChannelProviderExpr = @@ -420,7 +422,18 @@ protected MethodDefinition createStreamingRpcTestMethod( Map classMemberVarExprs, Map resourceNames, Map messageTypes) { - return null; + // Add some actual statements once implemented + List methodStatements = new ArrayList<>(); + + String testMethodName = String.format("%sTest", JavaStyle.toLowerCamelCase(method.name())); + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(TEST_ANNOTATION)) + .setScope(ScopeNode.PUBLIC) + .setReturnType(TypeNode.VOID) + .setName(testMethodName) + .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(Exception.class))) + .setBody(methodStatements) + .build(); } @Override @@ -513,6 +526,12 @@ protected List createStreamingRpcExceptionTestStatements( return Collections.emptyList(); } + @Override + protected Expr createDefaultValue( + MethodArgument methodArg, Map resourceNames) { + return DefaultValueComposer.createDefaultValue(methodArg, resourceNames, true); + } + @Override protected List createRpcLroExceptionTestCatchBody( VariableExpr exceptionExpr, boolean isStreaming) { diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubClassComposer.java new file mode 100644 index 0000000000..704fac96b6 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubClassComposer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.generator.gapic.composer.rest; + +import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; + +public class ServiceStubClassComposer extends AbstractServiceStubClassComposer { + private static final ServiceStubClassComposer INSTANCE = new ServiceStubClassComposer(); + + protected ServiceStubClassComposer() { + super(RestContext.instance()); + } + + public static ServiceStubClassComposer instance() { + return INSTANCE; + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java index 9375399546..b12528ec3f 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposer.java @@ -17,23 +17,16 @@ import com.google.api.gax.httpjson.GaxHttpJsonProperties; import com.google.api.gax.httpjson.HttpJsonTransportChannel; import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.generator.engine.ast.AnnotationNode; -import com.google.api.generator.engine.ast.ConcreteReference; import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.ScopeNode; -import com.google.api.generator.engine.ast.StringObjectValue; import com.google.api.generator.engine.ast.TypeNode; -import com.google.api.generator.engine.ast.ValueExpr; -import com.google.api.generator.engine.ast.Variable; -import com.google.api.generator.engine.ast.VariableExpr; -import com.google.api.generator.gapic.composer.comment.SettingsCommentComposer; import com.google.api.generator.gapic.composer.common.AbstractServiceStubSettingsClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; -import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Service; import java.util.Arrays; +import java.util.Collections; +import java.util.List; public class ServiceStubSettingsClassComposer extends AbstractServiceStubSettingsClassComposer { private static final ServiceStubSettingsClassComposer INSTANCE = @@ -58,94 +51,16 @@ private static TypeStore createStaticTypes() { } @Override - protected MethodDefinition createDefaultTransportTransportProviderBuilderMethod() { - // Create the defaultHttpJsonTransportProviderBuilder method. - TypeNode returnType = - TypeNode.withReference( - ConcreteReference.withClazz(InstantiatingHttpJsonChannelProvider.Builder.class)); - MethodInvocationExpr transportChannelProviderBuilderExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get( - InstantiatingHttpJsonChannelProvider.class.getSimpleName())) - .setMethodName("newBuilder") - .setReturnType(returnType) - .build(); - return MethodDefinition.builder() - .setHeaderCommentStatements( - SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setReturnType(returnType) - .setName("defaultHttpJsonTransportProviderBuilder") - .setReturnExpr(transportChannelProviderBuilderExpr) - .build(); - } - - @Override - protected MethodDefinition createDefaultApiClientHeaderProviderBuilderMethod( + protected List createApiClientHeaderProviderBuilderMethods( Service service, TypeStore typeStore) { - // Create the defaultApiClientHeaderProviderBuilder method. - TypeNode returnType = - TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); - MethodInvocationExpr returnExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("ApiClientHeaderProvider")) - .setMethodName("newBuilder") - .build(); - - MethodInvocationExpr versionArgExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GaxProperties")) - .setMethodName("getLibraryVersion") - .setArguments( - VariableExpr.builder() - .setVariable( - Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) - .setStaticReferenceType( - typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) - .build()) - .build(); - - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setGeneratedLibToken") - .setArguments(ValueExpr.withValue(StringObjectValue.withValue("gapic")), versionArgExpr) - .build(); - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setTransportToken") - .setArguments( - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get(GaxHttpJsonProperties.class.getSimpleName())) - .setMethodName("getHttpJsonTokenName") - .build(), - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get(GaxHttpJsonProperties.class.getSimpleName())) - .setMethodName("getHttpJsonVersion") - .build()) - .setReturnType(returnType) - .build(); - - AnnotationNode annotation = - AnnotationNode.builder() - .setType(FIXED_TYPESTORE.get("BetaApi")) - .setDescription( - "The surface for customizing headers is not stable yet and may change in the" - + " future.") - .build(); - return MethodDefinition.builder() - .setAnnotations(Arrays.asList(annotation)) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setReturnType(returnType) - .setName("defaultApiClientHeaderProviderBuilder") - .setReturnExpr(returnExpr) - .build(); + return Collections.singletonList( + createApiClientHeaderProviderBuilderMethod( + service, + typeStore, + "defaultApiClientHeaderProviderBuilder", + FIXED_REST_TYPESTORE.get(GaxHttpJsonProperties.class.getSimpleName()), + "getHttpJsonTokenName", + "getHttpJsonVersion")); } @Override diff --git a/src/main/java/com/google/api/generator/gapic/composer/samplecode/ServiceClientSampleCodeComposer.java b/src/main/java/com/google/api/generator/gapic/composer/samplecode/ServiceClientSampleCodeComposer.java index ac8d805b59..5572bde8e3 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/samplecode/ServiceClientSampleCodeComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/samplecode/ServiceClientSampleCodeComposer.java @@ -1310,7 +1310,7 @@ private static List createRpcMethodArgumentDefaultValueExprs( .map( arg -> !isStringTypedResourceName(arg, resourceNames) - ? DefaultValueComposer.createDefaultValue(arg, resourceNames) + ? DefaultValueComposer.createDefaultValue(arg, resourceNames, false) : stringResourceNameDefaultValueExpr.apply(arg)) .collect(Collectors.toList()); } diff --git a/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java b/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java index f1abb45a4c..c0b717fc0a 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java +++ b/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java @@ -15,6 +15,9 @@ package com.google.api.generator.gapic.composer.utils; import com.google.api.generator.gapic.model.Service; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; /** Provides Gapic class names. */ public class ClassNames { @@ -23,6 +26,7 @@ public class ClassNames { private static final String MOCK_SERVICE_IMPL_CLASS_NAME_PATTERN = "Mock%sImpl"; private static final String SERVICE_CLIENT_CLASS_NAME_PATTERN = "%sClient"; private static final String SERVICE_CLIENT_TEST_CLASS_NAME_PATTERN = "%sClientTest"; + private static final String SERVICE_CLIENT_TRANSPORT_TEST_CLASS_NAME_PATTERN = "%sClient%sTest"; private static final String SERVICE_SETTINGS_CLASS_NAME_PATTERN = "%sSettings"; private static final String SERVICE_STUB_SETTINGS_CLASS_NAME_PATTERN = "%sStubSettings"; private static final String SERVICE_STUB_CLASS_NAME_PATTERN = "%sStub"; @@ -30,10 +34,10 @@ public class ClassNames { private static final String TRANSPORT_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN = "%s%sCallableFactory"; - private final String transportPrefix; + private final List transportPrefixes; - public ClassNames(String transportPrefix) { - this.transportPrefix = transportPrefix; + public ClassNames(String... transportPrefixes) { + this.transportPrefixes = Arrays.asList(transportPrefixes); } public static String getServiceClientClassName(Service service) { @@ -59,23 +63,50 @@ public static String getServiceStubClassName(Service service) { } public String getTransportServiceCallableFactoryClassName(Service service) { - return String.format( - TRANSPORT_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN, - transportPrefix, - monolithBackwardsCompatibleName(service.name())); + return getTransportServiceCallableFactoryClassNames(service).get(0); + } + + public List getTransportServiceCallableFactoryClassNames(Service service) { + return transportPrefixes.stream() + .map( + prefix -> + String.format( + TRANSPORT_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN, + prefix, + monolithBackwardsCompatibleName(service.name()))) + .collect(Collectors.toList()); } public String getTransportServiceStubClassName(Service service) { - return String.format( - TRANSPORT_SERVICE_STUB_CLASS_NAME_PATTERN, - transportPrefix, - monolithBackwardsCompatibleName(service.name())); + return getTransportServiceStubClassNames(service).get(0); + } + + public List getTransportServiceStubClassNames(Service service) { + return transportPrefixes.stream() + .map( + prefix -> + String.format( + TRANSPORT_SERVICE_STUB_CLASS_NAME_PATTERN, + prefix, + monolithBackwardsCompatibleName(service.name()))) + .collect(Collectors.toList()); } public static String getServiceClientTestClassName(Service service) { return String.format(SERVICE_CLIENT_TEST_CLASS_NAME_PATTERN, service.overriddenName()); } + public List getServiceClientTestClassNames(Service service) { + return transportPrefixes.stream() + .map( + prefix -> + String.format( + SERVICE_CLIENT_TRANSPORT_TEST_CLASS_NAME_PATTERN, + service.overriddenName(), + prefix)) + .collect(Collectors.toList()); + } + public static String getMockServiceClassName(Service service) { return String.format(MOCK_SERVICE_CLASS_NAME_PATTERN, service.name()); } diff --git a/src/main/java/com/google/api/generator/gapic/model/HttpBindings.java b/src/main/java/com/google/api/generator/gapic/model/HttpBindings.java index 9ca67cf4c7..171f6b1bf7 100644 --- a/src/main/java/com/google/api/generator/gapic/model/HttpBindings.java +++ b/src/main/java/com/google/api/generator/gapic/model/HttpBindings.java @@ -57,6 +57,8 @@ public int compareTo(HttpBinding o) { public abstract Set bodyParameters(); + public abstract boolean isAsteriskBody(); + public static HttpBindings.Builder builder() { return new AutoValue_HttpBindings.Builder() .setPathParameters(ImmutableSet.of()) @@ -93,6 +95,8 @@ public abstract static class Builder { public abstract HttpBindings.Builder setBodyParameters(Set bodyParameters); + public abstract HttpBindings.Builder setIsAsteriskBody(boolean asteriskBody); + public abstract HttpBindings autoBuild(); public HttpBindings build() { diff --git a/src/main/java/com/google/api/generator/gapic/model/Service.java b/src/main/java/com/google/api/generator/gapic/model/Service.java index ace91051bc..34d3f97b25 100644 --- a/src/main/java/com/google/api/generator/gapic/model/Service.java +++ b/src/main/java/com/google/api/generator/gapic/model/Service.java @@ -79,6 +79,24 @@ public TypeNode operationType() { return null; } + public boolean hasLroMethods() { + for (Method method : methods()) { + if (method.hasLro()) { + return true; + } + } + return false; + } + + public boolean hasStandardLroMethods() { + for (Method method : methods()) { + if (method.hasLro() && method.lro().operationServiceStubType() == null) { + return true; + } + } + return false; + } + public abstract Builder toBuilder(); public static Builder builder() { diff --git a/src/main/java/com/google/api/generator/gapic/model/Transport.java b/src/main/java/com/google/api/generator/gapic/model/Transport.java index aeb7b9361c..ae7820c8ed 100644 --- a/src/main/java/com/google/api/generator/gapic/model/Transport.java +++ b/src/main/java/com/google/api/generator/gapic/model/Transport.java @@ -17,8 +17,6 @@ public enum Transport { REST, GRPC, - // Never used in the context as is, must be split into two contexts (REST and GRPC respectively) - // instead. GRPC_REST; /** diff --git a/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java b/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java index 26629949ef..36828206d3 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java +++ b/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java @@ -104,6 +104,7 @@ private static HttpBindings parseHttpRuleHelper( validateAndConstructHttpBindings(queryParamNames, message, messageTypes, false)) .setBodyParameters( validateAndConstructHttpBindings(bodyParamNames, message, messageTypes, false)) + .setIsAsteriskBody(body.equals(ASTERISK)) .build(); } diff --git a/src/test/java/com/google/api/generator/gapic/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/BUILD.bazel index 40de9b259f..5c5f8983ad 100644 --- a/src/test/java/com/google/api/generator/gapic/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/BUILD.bazel @@ -6,6 +6,7 @@ filegroup( "//src/test/java/com/google/api/generator/gapic/composer:composer_files", "//src/test/java/com/google/api/generator/gapic/composer/defaultvalue:defaultvalue_files", "//src/test/java/com/google/api/generator/gapic/composer/grpc:grpc_files", + # "//src/test/java/com/google/api/generator/gapic/composer/grpcrest:grpcrest_files", "//src/test/java/com/google/api/generator/gapic/composer/resourcename:resourcename_files", "//src/test/java/com/google/api/generator/gapic/composer/rest:rest_files", "//src/test/java/com/google/api/generator/gapic/composer/samplecode:samplecode_files", diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel index 159c97d9b1..28a4bfc8b4 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel @@ -5,8 +5,6 @@ package(default_visibility = ["//visibility:public"]) UPDATE_GOLDENS_TESTS = [ "BatchingDescriptorComposerTest", - "ServiceClientClassComposerTest", - "ServiceStubClassComposerTest", ] TESTS = UPDATE_GOLDENS_TESTS + [ diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java index 09b1bf5b1c..d3fa5aa2e9 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java @@ -27,6 +27,7 @@ import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.engine.writer.JavaWriterVisitor; +import com.google.api.generator.gapic.composer.grpc.GrpcContext; import com.google.api.generator.gapic.model.GapicBatchingSettings; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.GapicServiceConfig; @@ -329,7 +330,9 @@ public void lroBuilderExpr() { waitMethod, builderVarExpr, RETRY_CODES_DEFINITIONS_VAR_EXPR, - RETRY_PARAM_DEFINITIONS_VAR_EXPR); + RETRY_PARAM_DEFINITIONS_VAR_EXPR, + GrpcContext.instance().operationResponseTransformerType(), + GrpcContext.instance().operationMetadataTransformerType()); builderExpr.accept(writerVisitor); String expected = LineFormatter.lines( diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel index 14ac8deeba..825635a75e 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel @@ -8,8 +8,10 @@ TESTS = [ "GrpcServiceStubClassComposerTest", "MockServiceClassComposerTest", "MockServiceImplClassComposerTest", + "ServiceClientClassComposerTest", "ServiceClientTestClassComposerTest", "ServiceSettingsClassComposerTest", + "ServiceStubClassComposerTest", "ServiceStubSettingsClassComposerTest", ] diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposerTest.java similarity index 89% rename from src/test/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposerTest.java index b7767f41a6..331b94e484 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposerTest.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer.common; +package com.google.api.generator.gapic.composer.grpc; import static com.google.api.generator.test.framework.Assert.assertCodeEquals; @@ -28,7 +28,7 @@ public class ServiceClientClassComposerTest { @Test public void generateServiceClasses() { - GapicContext context = TestProtoLoader.instance().parseShowcaseEcho(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, echoProtoService); @@ -41,7 +41,7 @@ public void generateServiceClasses() { @Test public void generateServiceClasses_deprecated() { - GapicContext context = TestProtoLoader.instance().parseDeprecatedService(); + GapicContext context = GrpcTestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, protoService); @@ -55,7 +55,7 @@ public void generateServiceClasses_deprecated() { @Test public void generateServiceClasses_methodSignatureHasNestedFields() { - GapicContext context = TestProtoLoader.instance().parseShowcaseIdentity(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseIdentity(); Service protoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, protoService); @@ -68,7 +68,7 @@ public void generateServiceClasses_methodSignatureHasNestedFields() { @Test public void generateServiceClasses_bookshopNameConflicts() { - GapicContext context = TestProtoLoader.instance().parseBookshopService(); + GapicContext context = GrpcTestProtoLoader.instance().parseBookshopService(); Service protoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, protoService); diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposerTest.java similarity index 94% rename from src/test/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposerTest.java index b30ce3630c..bb411b9ad3 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposerTest.java @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer.common; +package com.google.api.generator.gapic.composer.grpc; import com.google.api.generator.engine.writer.JavaWriterVisitor; +import com.google.api.generator.gapic.composer.common.TestProtoLoader; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/BookshopClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/BookshopClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/BookshopClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/BookshopClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/IdentityClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/IdentityClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/common/goldens/IdentityClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/IdentityClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java index e3e5641f93..53392a549e 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/ServiceStubSettingsClassComposerTest.java @@ -27,7 +27,7 @@ public class ServiceStubSettingsClassComposerTest { @Test public void generateServiceStubSettingsClasses_basic() { - GapicContext context = RestTestProtoLoader.instance().parseShowcaseEcho(); + GapicContext context = RestTestProtoLoader.instance().parseCompliance(); Service echoProtoService = context.services().get(0); GapicClass clazz = ServiceStubSettingsClassComposer.instance().generate(context, echoProtoService); diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden index 3535651104..a858c0123e 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceStubSettings.golden @@ -1,60 +1,33 @@ package com.google.showcase.v1beta1.stub; -import static com.google.showcase.v1beta1.EchoClient.PagedExpandPagedResponse; -import static com.google.showcase.v1beta1.EchoClient.SimplePagedExpandPagedResponse; - import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; import com.google.api.core.BetaApi; import com.google.api.gax.core.GaxProperties; import com.google.api.gax.core.GoogleCredentialsProvider; import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.grpc.ProtoOperationTransformers; import com.google.api.gax.httpjson.GaxHttpJsonProperties; import com.google.api.gax.httpjson.HttpJsonTransportChannel; import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.longrunning.OperationTimedPollAlgorithm; import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiCallContext; import com.google.api.gax.rpc.ApiClientHeaderProvider; import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.PageContext; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.PagedListDescriptor; -import com.google.api.gax.rpc.PagedListResponseFactory; -import com.google.api.gax.rpc.ServerStreamingCallSettings; import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StreamingCallSettings; import com.google.api.gax.rpc.StubSettings; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; -import com.google.longrunning.Operation; -import com.google.showcase.v1beta1.BlockRequest; -import com.google.showcase.v1beta1.BlockResponse; -import com.google.showcase.v1beta1.EchoRequest; -import com.google.showcase.v1beta1.EchoResponse; -import com.google.showcase.v1beta1.ExpandRequest; -import com.google.showcase.v1beta1.Object; -import com.google.showcase.v1beta1.PagedExpandRequest; -import com.google.showcase.v1beta1.PagedExpandResponse; -import com.google.showcase.v1beta1.WaitMetadata; -import com.google.showcase.v1beta1.WaitRequest; -import com.google.showcase.v1beta1.WaitResponse; +import com.google.showcase.v1beta1.RepeatRequest; +import com.google.showcase.v1beta1.RepeatResponse; import java.io.IOException; import java.util.List; import javax.annotation.Generated; -import org.threeten.bp.Duration; // AUTO-GENERATED DOCUMENTATION AND CLASS. /** - * Settings class to configure an instance of {@link EchoStub}. + * Settings class to configure an instance of {@link ComplianceStub}. * *

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

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

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

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

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

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

Sample code: + * + *

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

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

Sample code: + * + *

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

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

Sample code: + * + *

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