From fdcfe705b5fb42e11dfd511ccf7fdee40bcba131 Mon Sep 17 00:00:00 2001 From: Vadym Matsishevskyi <25311427+vam-google@users.noreply.github.com> Date: Thu, 26 Aug 2021 14:59:41 -0700 Subject: [PATCH] feat: REGAPIC initial implementation (#824) This includes: 1) Proper GRPC transcoding 2) Mimimal REST Operations (go make it compilable) 3) Rely on resource names for tests values generation (to not fail http url path validation) 4) Empty Server Streaming method implementation --- .../resources/gradle/assembly.gradle.tmpl | 4 +- .../resources/gradle/client_grpc.gradle.tmpl | 4 +- .../resources/gradle/client_rest.gradle.tmpl | 4 +- .../resources/gradle/grpc.gradle.tmpl | 4 +- .../resources/gradle/proto.gradle.tmpl | 4 +- .../generator/gapic/composer/Composer.java | 15 +- ...> AbstractServiceClientClassComposer.java} | 49 +- ...bstractServiceClientTestClassComposer.java | 7 +- .../AbstractServiceStubClassComposer.java | 983 +++-------------- ...tractServiceStubSettingsClassComposer.java | 10 +- ...ractTransportServiceStubClassComposer.java | 997 ++++++++++++++++++ .../common/RetrySettingsComposer.java | 14 +- .../common/ServiceStubClassComposer.java | 279 ----- .../composer/common/TransportContext.java | 23 +- .../defaultvalue/DefaultValueComposer.java | 26 +- .../gapic/composer/grpc/GrpcContext.java | 11 + .../grpc/GrpcServiceStubClassComposer.java | 17 +- .../grpc/ServiceClientClassComposer.java | 30 + .../grpc/ServiceClientTestClassComposer.java | 6 + .../grpc/ServiceStubClassComposer.java | 30 + ...onServiceCallableFactoryClassComposer.java | 6 +- .../HttpJsonServiceStubClassComposer.java | 253 +++-- .../gapic/composer/rest/RestContext.java | 15 +- .../rest/ServiceClientClassComposer.java | 30 + .../rest/ServiceClientTestClassComposer.java | 20 +- .../rest/ServiceStubClassComposer.java | 30 + .../ServiceClientSampleCodeComposer.java | 2 +- .../generator/gapic/model/HttpBindings.java | 4 + .../api/generator/gapic/model/Service.java | 9 + .../gapic/protoparser/HttpRuleParser.java | 1 + .../gapic/composer/common/BUILD.bazel | 2 - .../common/RetrySettingsComposerTest.java | 5 +- .../generator/gapic/composer/grpc/BUILD.bazel | 2 + .../ServiceClientClassComposerTest.java | 10 +- .../ServiceStubClassComposerTest.java | 3 +- .../goldens/BookshopClient.golden | 0 .../goldens/DeprecatedServiceClient.golden | 0 .../goldens/DeprecatedServiceStub.golden | 0 .../goldens/EchoClient.golden | 0 .../{common => grpc}/goldens/EchoStub.golden | 0 .../goldens/IdentityClient.golden | 0 .../ServiceStubSettingsClassComposerTest.java | 2 +- .../goldens/ComplianceStubSettings.golden | 531 +++------- .../goldens/HttpJsonComplianceStub.golden | 3 +- 44 files changed, 1767 insertions(+), 1678 deletions(-) rename src/main/java/com/google/api/generator/gapic/composer/common/{ServiceClientClassComposer.java => AbstractServiceClientClassComposer.java} (97%) create mode 100644 src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java delete mode 100644 src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/ServiceClientClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/rest/ServiceStubClassComposer.java rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/ServiceClientClassComposerTest.java (89%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/ServiceStubClassComposerTest.java (94%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/BookshopClient.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/DeprecatedServiceClient.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/DeprecatedServiceStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/EchoClient.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/EchoStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{common => grpc}/goldens/IdentityClient.golden (100%) diff --git a/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_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/composer/Composer.java b/src/main/java/com/google/api/generator/gapic/composer/Composer.java index 5c191b0a27..cee4b2bccc 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 @@ -17,14 +17,14 @@ 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.resourcename.ResourceNameHelperClassComposer; import com.google.api.generator.gapic.composer.rest.HttpJsonServiceCallableFactoryClassComposer; @@ -76,8 +76,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() @@ -86,6 +88,7 @@ public static List generateStubClasses(GapicContext context) { HttpJsonServiceCallableFactoryClassComposer.instance().generate(context, s)); clazzes.add(HttpJsonServiceStubClassComposer.instance().generate(context, s)); } else { + clazzes.add(ServiceStubClassComposer.instance().generate(context, s)); clazzes.add(ServiceStubSettingsClassComposer.instance().generate(context, s)); clazzes.add( GrpcServiceCallableFactoryClassComposer.instance().generate(context, s)); @@ -101,13 +104,17 @@ 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 { + clazzes.add(ServiceClientClassComposer.instance().generate(context, s)); clazzes.add(ServiceSettingsClassComposer.instance().generate(context, s)); } }); 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 97% 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 5a38db0562..18b9eeca81 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 @@ -96,8 +96,7 @@ 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 +114,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 @@ -198,7 +201,7 @@ private static List createClassHeaderComments( service, classMethodSampleCode, credentialsSampleCode, endpointSampleCode); } - private static List createClassMethods( + private List createClassMethods( Service service, Map messageTypes, TypeStore typeStore, @@ -225,14 +228,16 @@ private static boolean hasLroMethods(Service service) { 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")); + fieldNameToTypes.put( + getTransportContext().operationsClientName(), + getTransportContext().operationsClientType()); } return fieldNameToTypes.entrySet().stream() @@ -352,14 +357,14 @@ 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 operationsClientType = getTransportContext().operationsClientType(); TypeNode exceptionType = typeStore.get("IOException"); TypeNode settingsType = typeStore.get(settingsName); @@ -374,7 +379,10 @@ private static List createConstructorMethods( .build()); VariableExpr operationsClientVarExpr = VariableExpr.withVariable( - Variable.builder().setType(operationsClientType).setName("operationsClient").build()); + Variable.builder() + .setType(operationsClientType) + .setName(getTransportContext().operationsClientName()) + .build()); // Create the ServiceClient(ServiceSettings settings) ctor. List ctorAssignmentExprs = new ArrayList<>(); @@ -404,10 +412,15 @@ private static List createConstructorMethods( .build()) .build()); + String operationsStubGetterName = + String.format( + "get%s", + JavaStyle.toUpperCamelCase(getTransportContext().transportOperationsStubName())); + Expr clientArgExpr = MethodInvocationExpr.builder() .setExprReferenceExpr(stubVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setMethodName("getOperationsStub") + .setMethodName(operationsStubGetterName) .build(); AssignmentExpr operationsClientAssignExpr = AssignmentExpr.builder() @@ -476,15 +489,19 @@ private static List createConstructorMethods( return methods; } - private static List createGetterMethods( + 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"; + String getOperationsClientMethodName = + String.format( + "get%s", + JavaStyle.toUpperCamelCase(getTransportContext().operationsClientName())); if (hasLroClient) { - methodNameToTypes.put(getOperationsClientMethodName, typeStore.get("OperationsClient")); + methodNameToTypes.put( + getOperationsClientMethodName, getTransportContext().operationsClientType()); } AnnotationNode betaStubAnnotation = AnnotationNode.builder() @@ -1681,8 +1698,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..b677c66a24 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 @@ -470,7 +470,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 +735,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 +769,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/AbstractServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java index 034c94c949..1b26732cff 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,77 +16,43 @@ 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.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.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; 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.ImmutableMap; import com.google.longrunning.Operation; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashMap; +import java.util.Collections; 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; @@ -94,256 +60,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); + Map messageTypes = context.messages(); + TypeStore typeStore = createTypes(service, messageTypes); + String className = ClassNames.getServiceStubClassName(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 (getTransportContext().transportOperationsStubType() != null) { - classMemberVarExprs.put( - OPERATIONS_STUB_MEMBER_NAME, - VariableExpr.withVariable( - Variable.builder() - .setName(OPERATIONS_STUB_MEMBER_NAME) - .setType(getTransportContext().transportOperationsStubType()) - .build())); - } - classMemberVarExprs.put( - CALLABLE_FACTORY_MEMBER_NAME, - VariableExpr.withVariable( - Variable.builder() - .setName(CALLABLE_FACTORY_MEMBER_NAME) - .setType(getTransportContext().stubCallableFactoryType()) - .build())); - - List classStatements = - createClassStatements( - service, - protoMethodNameToDescriptorVarExprs, - callableClassMemberVarExprs, - classMemberVarExprs); - - StubCommentComposer commentComposer = - new StubCommentComposer(getTransportContext().transportName()); + 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); - - 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) { - List classStatements = new ArrayList<>(); - for (Statement statement : - createMethodDescriptorVariableDecls(service, protoMethodNameToDescriptorVarExprs)) { - 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) { - return service.methods().stream() - .map( - m -> - createMethodDescriptorVariableDecl( - service, m, protoMethodNameToDescriptorVarExprs.get(m.name()))) - .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()) { @@ -352,559 +100,155 @@ 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))); - 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(); - - 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()); + private List createClassMethods( + Service service, Map messageTypes, TypeStore typeStore) { + boolean hasLroClient = service.hasLroMethods(); + List methods = new ArrayList<>(); + if (hasLroClient) { + methods.add(createOperationsStubGetter(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); - if (getTransportContext().transportOperationsStubType() != null) { - secondCtorExprs.add( - AssignmentExpr.builder() - .setVariableExpr( - operationsStubClassVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType(getTransportContext().transportOperationsStubType()) - .setMethodName("create") - .setArguments(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) - .setReturnType(operationsStubClassVarExpr.type()) - .build()) - .build()); + 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)); } - 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); + return javaMethods; + } - // 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(); + private static MethodDefinition createOperationCallableGetter( + Method method, TypeStore typeStore) { + return createCallableGetterHelper(method, typeStore, true, false); + } - // Second constructor method. - MethodDefinition secondCtor = - ctorMakerFn.apply( - Arrays.asList(settingsVarExpr, clientContextVarExpr, callableFactoryVarExpr), - secondCtorStatements); + private static MethodDefinition createPagedCallableGetter(Method method, TypeStore typeStore) { + return createCallableGetterHelper(method, typeStore, false, true); + } - return Arrays.asList(firstCtor, secondCtor); + private static 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 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"); } - 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(); - } + List annotations = + method.isDeprecated() + ? Arrays.asList(AnnotationNode.withType(TypeNode.DEPRECATED)) + : Collections.emptyList(); - private static String getCallableCreatorMethodName(TypeNode callableVarExprType) { - final String typeName = callableVarExprType.reference().name(); - String streamName = "Unary"; + returnType = TypeNode.withReference(returnType.reference().copyAndSetGenerics(genericRefs)); - // 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); + return MethodDefinition.builder() + .setAnnotations(annotations) + .setScope(ScopeNode.PUBLIC) + .setReturnType(returnType) + .setName(methodName) + .setBody(createThrowUOEBody(methodName, typeStore)) + .build(); } - 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 MethodDefinition createOperationsStubGetter(TypeStore typeStore) { + String methodName = + String.format( + "get%s", + JavaStyle.toUpperCamelCase(getTransportContext().transportOperationsStubName())); + + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setReturnType(getTransportContext().operationsStubType()) + .setName(methodName) + .setBody(createThrowUOEBody(methodName, typeStore)) + .build(); } - private List createStubOverrideMethods( - VariableExpr backgroundResourcesVarExpr) { - 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<>(); - javaMethods.add( - methodMakerStarterFn - .apply("close") - .setIsFinal(true) + private static List createBackgroundResourceMethodOverrides() { + MethodDefinition closeMethod = + MethodDefinition.builder() + .setIsOverride(true) + .setScope(ScopeNode.PUBLIC) + .setIsAbstract(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; + .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(), @@ -913,52 +257,21 @@ 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; - } - - 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 - } + ClassNames.getServiceClientClassName(service)); - 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)))); + private static List createThrowUOEBody(String methodName, TypeStore typeStore) { + return Arrays.asList( + ExprStatement.withExpr( + ThrowExpr.builder() + .setType(typeStore.get("UnsupportedOperationException")) + .setMessageExpr(String.format("Not implemented: %s()", methodName)) + .build())); } - protected 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()); + 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..3df0394ddd 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 @@ -1136,7 +1136,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 +1236,7 @@ private static List createNestedClassStatements( return statements; } - private static List createNestedClassMethods( + private List createNestedClassMethods( Service service, GapicServiceConfig serviceConfig, TypeNode superType, @@ -1258,7 +1258,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 +1313,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); } 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..14fe5da0fa --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java @@ -0,0 +1,997 @@ +// 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.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.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.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.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)) { + classMemberVarExprs.put( + getTransportContext().transportOperationsStubName(), + VariableExpr.withVariable( + Variable.builder() + .setName(getTransportContext().transportOperationsStubName()) + .setType(getTransportContext().transportOperationsStubType()) + .build())); + } + classMemberVarExprs.put( + CALLABLE_FACTORY_MEMBER_NAME, + VariableExpr.withVariable( + Variable.builder() + .setName(CALLABLE_FACTORY_MEMBER_NAME) + .setType(getTransportContext().stubCallableFactoryType()) + .build())); + + List classStatements = + createClassStatements( + service, + protoMethodNameToDescriptorVarExprs, + callableClassMemberVarExprs, + classMemberVarExprs); + + 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); + + 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().transportOperationsStubName())); + + 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) { + List classStatements = new ArrayList<>(); + for (Statement statement : + createMethodDescriptorVariableDecls(service, protoMethodNameToDescriptorVarExprs)) { + 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) { + return service.methods().stream() + .map( + m -> + createMethodDescriptorVariableDecl( + service, m, protoMethodNameToDescriptorVarExprs.get(m.name()))) + .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)); + javaMethods.addAll( + createConstructorMethods( + service, + typeStore, + classMemberVarExprs, + callableClassMemberVarExprs, + protoMethodNameToDescriptorVarExprs)); + javaMethods.addAll( + createGetMethodDescriptorsMethod(service, typeStore, protoMethodNameToDescriptorVarExprs)); + javaMethods.addAll( + createOperationsStubGetterMethod( + service, classMemberVarExprs.get(getTransportContext().transportOperationsStubName()))); + javaMethods.addAll(createCallableGetterMethods(callableClassMemberVarExprs)); + javaMethods.addAll( + createStubOverrideMethods(classMemberVarExprs.get(BACKGROUND_RESOURCES_MEMBER_NAME))); + return javaMethods; + } + + 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(); + + 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().transportOperationsStubName()); + if (generateOperationsStubLogic(service)) { + secondCtorExprs.add( + AssignmentExpr.builder() + .setVariableExpr( + operationsStubClassVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType(getTransportContext().transportOperationsStubType()) + .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); + + // 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); + } + + 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) { + 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<>(); + 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 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()); + } +} 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 9d16f98f88..0000000000 --- a/src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java +++ /dev/null @@ -1,279 +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) { - methods.add(createOperationsStubGetter(typeStore)); - } - 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) { - String methodName = "getOperationsStub"; - return MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setReturnType(typeStore.get("OperationsStub")) - .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..9296c9b93c 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,7 +19,6 @@ import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Transport; import com.google.auto.value.AutoValue; -import javax.annotation.Nullable; @AutoValue public abstract class TransportContext { @@ -37,9 +36,10 @@ public abstract class TransportContext { public abstract Class methodDescriptorClass(); - @Nullable public abstract TypeNode transportOperationsStubType(); + public abstract String transportOperationsStubName(); + // For AbstractServiceSettingsClassComposer public abstract Class instantiatingChannelProviderClass(); @@ -59,6 +59,15 @@ public abstract class TransportContext { public abstract String transportCallSettingsName(); + // For RetrySettingsComposer + public abstract TypeNode operationResponseTransformerType(); + + public abstract TypeNode operationMetadataTransformerType(); + + public abstract TypeNode operationsClientType(); + + public abstract String operationsClientName(); + protected static TypeNode classToType(Class clazz) { return TypeNode.withReference(ConcreteReference.withClazz(clazz)); } @@ -100,8 +109,18 @@ public abstract Builder setDefaultTransportProviderBuilderName( public abstract Builder setTransportOperationsStubType(TypeNode transportOperationsStubType); + public abstract Builder setTransportOperationsStubName(String transportOperationsStubName); + public abstract Builder setOperationsStubType(TypeNode operationsStubType); + public abstract Builder setOperationResponseTransformerType(TypeNode operationResponseTransformerType); + + public abstract Builder setOperationMetadataTransformerType(TypeNode operationMetadataTransformerType); + + public abstract Builder setOperationsClientType(TypeNode operationsClientType); + + public abstract Builder setOperationsClientName(String operationsClientName); + 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..53a8d6f3ca 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,11 @@ 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.longrunning.OperationsClient; import com.google.longrunning.stub.GrpcOperationsStub; import com.google.longrunning.stub.OperationsStub; import io.grpc.MethodDescriptor; @@ -37,6 +39,7 @@ public abstract class GrpcContext extends TransportContext { .setStubCallableFactoryType(classToType(GrpcStubCallableFactory.class)) .setMethodDescriptorClass(MethodDescriptor.class) .setTransportOperationsStubType(classToType(GrpcOperationsStub.class)) + .setTransportOperationsStubName("operationsStub") // For grpc.ServiceSettingsClassComposer .setInstantiatingChannelProviderClass(InstantiatingGrpcChannelProvider.Builder.class) .setDefaultTransportProviderBuilderName("defaultGrpcTransportProviderBuilder") @@ -48,6 +51,14 @@ public abstract class GrpcContext extends TransportContext { .setTransportCallableFactoryType(classToType(GrpcCallableFactory.class)) .setOperationsStubType(classToType(OperationsStub.class)) .setTransportCallSettingsName("grpcCallSettings") + // For RetrySettingsComposer + .setOperationResponseTransformerType( + classToType(ProtoOperationTransformers.ResponseTransformer.class)) + .setOperationMetadataTransformerType( + classToType(ProtoOperationTransformers.MetadataTransformer.class)) + // For ServiceClientClassComposer + .setOperationsClientType(classToType(OperationsClient.class)) + .setOperationsClientName("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 f079aba780..22e986adb0 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.Method; @@ -52,7 +51,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 @@ -189,18 +188,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..636326d820 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 @@ -1055,6 +1055,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/rest/HttpJsonServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/rest/HttpJsonServiceCallableFactoryClassComposer.java index f9c4045cb9..75429dbdeb 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 @@ -14,7 +14,6 @@ package com.google.api.generator.gapic.composer.rest; -import com.google.api.gax.core.BackgroundResource; import com.google.api.gax.httpjson.ApiMessage; import com.google.api.generator.engine.ast.AnnotationNode; import com.google.api.generator.engine.ast.ConcreteReference; @@ -35,8 +34,6 @@ public class HttpJsonServiceCallableFactoryClassComposer private static final TypeNode MESSAGE_TYPE = TypeNode.withReference(ConcreteReference.withClazz(ApiMessage.class)); - private static final TypeNode BACKGROUND_RESOURCE_TYPE = - TypeNode.withReference(ConcreteReference.withClazz(BackgroundResource.class)); private HttpJsonServiceCallableFactoryClassComposer() { super(RestContext.instance()); @@ -69,7 +66,8 @@ protected List createClassImplements(TypeStore typeStore) { .reference() .copyAndSetGenerics( Arrays.asList( - MESSAGE_TYPE.reference(), BACKGROUND_RESOURCE_TYPE.reference())))); + MESSAGE_TYPE.reference(), + getTransportContext().operationsStubType().reference())))); } @Override 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 901dceacc6..ff927a3713 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 @@ -41,7 +41,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.Method; @@ -54,12 +54,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(); @@ -89,6 +90,11 @@ private static TypeStore createStaticTypes() { ProtoRestSerializer.class)); } + @Override + protected boolean generateOperationsStubLogic(Service service) { + return service.hasLroMethods(); + } + @Override protected Statement createMethodDescriptorVariableDecl( Service service, Method protoMethod, VariableExpr methodDescriptorVarExpr) { @@ -137,12 +143,6 @@ protected Statement createMethodDescriptorVariableDecl( .build()); } - @Override - protected List createOperationsStubGetterMethod( - VariableExpr operationsStubVarExpr) { - return Collections.emptyList(); - } - @Override protected Expr createTransportSettingsInitExpr( Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr) { @@ -311,16 +311,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); @@ -356,71 +360,148 @@ private List setResponseParserExpr(Method protoMethod) { return Collections.singletonList(expr); } - 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()) - .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); - bodyStatements.add(ExprStatement.withExpr(fieldsAssignExpr)); - returnExpr = fieldsVarExpr; - - TypeNode serializerVarType = - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(ProtoRestSerializer.class) - .setGenerics(method.inputType().reference()) - .build()); - - VariableExpr serializerVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("serializer").setType(serializerVarType).build()); - - Expr serializerAssignExpr = - AssignmentExpr.builder() - .setVariableExpr(serializerVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType( - FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) - .setMethodName("create") - .setReturnType(serializerVarType) - .build()) + 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(); + } - serializerExpr = serializerVarExpr; + private Expr createFieldsExtractorClassInstance( + Method method, + TypeNode extractorReturnType, + Set httpBindingFieldNames, + String serializerMethodName) { + List bodyStatements = new ArrayList<>(); - bodyStatements.add(ExprStatement.withExpr(serializerAssignExpr)); - } + 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(); + + bodyStatements.add(ExprStatement.withExpr(fieldsAssignExpr)); + + TypeNode serializerVarType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(ProtoRestSerializer.class) + .setGenerics(method.inputType().reference()) + .build()); + + VariableExpr serializerVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("serializer").setType(serializerVarType).build()); + + Expr serializerAssignExpr = + AssignmentExpr.builder() + .setVariableExpr(serializerVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType( + FIXED_REST_TYPESTORE.get(ProtoRestSerializer.class.getSimpleName())) + .setMethodName("create") + .setReturnType(serializerVarType) + .build()) + .build(); + + bodyStatements.add(ExprStatement.withExpr(serializerAssignExpr)); VariableExpr requestVarExpr = VariableExpr.withVariable( @@ -463,9 +544,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( @@ -474,24 +555,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)); } } @@ -500,7 +577,7 @@ private Expr createFieldsExtractorClassInstance( return LambdaExpr.builder() .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) .setBody(bodyStatements) - .setReturnExpr(returnExpr) + .setReturnExpr(fieldsVarExpr) .build(); } @@ -514,4 +591,26 @@ private List getHttpMethodTypeExpr(Method protoMethod) { .build(); return Collections.singletonList(expr); } + + 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")) { + 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..682e68f1da 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,6 +21,9 @@ 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; @@ -35,7 +38,8 @@ public abstract class RestContext extends TransportContext { .setCallSettingsClass(HttpJsonCallSettings.class) .setStubCallableFactoryType(classToType(HttpJsonStubCallableFactory.class)) .setMethodDescriptorClass(ApiMethodDescriptor.class) - .setTransportOperationsStubType(null) + .setTransportOperationsStubType(classToType(HttpJsonOperationsStub.class)) + .setTransportOperationsStubName("httpJsonOperationsStub") // For httpjson.ServiceSettingsClassComposer .setInstantiatingChannelProviderClass(InstantiatingHttpJsonChannelProvider.Builder.class) .setDefaultTransportProviderBuilderName("defaultHttpJsonTransportProviderBuilder") @@ -45,8 +49,17 @@ public abstract class RestContext extends TransportContext { // For httpjson.HttpJsonServiceCallableFactoryClassComposer .setTransportCallSettingsType(classToType(HttpJsonCallSettings.class)) .setTransportCallableFactoryType(classToType(HttpJsonCallableFactory.class)) + // TODO: set to com.google.api.gax.httpjson.longrunning.stub.OperationsStub.class .setOperationsStubType(classToType(BackgroundResource.class)) .setTransportCallSettingsName("httpJsonCallSettings") + // For RetrySettingsComposer + .setOperationResponseTransformerType( + classToType(ProtoOperationTransformers.ResponseTransformer.class)) + .setOperationMetadataTransformerType( + classToType(ProtoOperationTransformers.MetadataTransformer.class)) + // For ServiceClientClassComposer + .setOperationsClientType(classToType(OperationsClient.class)) + .setOperationsClientName("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..868955f379 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; @@ -420,7 +421,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 +525,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/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/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 f21125fb54..2ce5c09d2e 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 @@ -49,6 +49,15 @@ public boolean hasDescription() { return !Strings.isNullOrEmpty(description()); } + public boolean hasLroMethods() { + for (Method method : methods()) { + if (method.hasLro()) { + return true; + } + } + return false; + } + public abstract Builder toBuilder(); public static Builder builder() { 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/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/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()