From d7b29e05d7cfda1eb1a3b09d7ad7d625cab4bde1 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Fri, 3 Sep 2021 19:36:29 -0400 Subject: [PATCH] Feat: Implement DIREGAPIC LRO annotations (#832) * fix ServiceStub Goldens * fix Stub golden * fix Stub golden * fix CallableFactory golden * fix java format * add annotation placement comments * only add machinery to methods that return operation * add grpc file that contained method that was edited on abstract class * update HttpJsonComplianceStub.golden * java format * add initial methods from annotations * add initial methods from annotations * Implement annotations * java format * fix package for Status * fix CallableFactory generics * java format * initialize new fields in message for parser test * set default value for operation_polling_method * add brackets to if statement * remove comments and invoke methods * add brackets to if statements and remove invoke methods * java formet --- WORKSPACE | 1 + ...ctServiceCallableFactoryClassComposer.java | 16 +- .../AbstractServiceStubClassComposer.java | 41 +- ...pcServiceCallableFactoryClassComposer.java | 9 +- ...onServiceCallableFactoryClassComposer.java | 56 ++- .../HttpJsonServiceStubClassComposer.java | 351 +++++++++++++----- .../api/generator/gapic/model/Message.java | 20 +- .../api/generator/gapic/model/Method.java | 21 +- .../gapic/model/OperationResponse.java | 56 +++ .../generator/gapic/protoparser/BUILD.bazel | 1 + .../generator/gapic/protoparser/Parser.java | 51 +++ .../HttpJsonComplianceCallableFactory.golden | 7 +- .../HttpJsonAddressesCallableFactory.java | 7 +- .../v1/stub/HttpJsonAddressesStub.java | 30 +- ...tpJsonRegionOperationsCallableFactory.java | 7 +- .../v1/stub/HttpJsonRegionOperationsStub.java | 21 +- 16 files changed, 532 insertions(+), 163 deletions(-) create mode 100644 src/main/java/com/google/api/generator/gapic/model/OperationResponse.java diff --git a/WORKSPACE b/WORKSPACE index 21e5f8ea67..cc406611a9 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -32,6 +32,7 @@ jvm_maven_import_external( # gapic-generator-java dependencies to match the order in googleapis repository, # which in its turn, prioritizes actual generated clients runtime dependencies # over the generator dependencies. + _gax_java_version = "2.3.0" http_archive( diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java index b3f4c7ee74..d643c9726b 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java @@ -41,6 +41,7 @@ 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 java.util.ArrayList; import java.util.Arrays; @@ -68,6 +69,13 @@ public GapicClass generate(GapicContext context, Service service) { GapicClass.Kind kind = Kind.STUB; String pakkage = String.format("%s.stub", service.pakkage()); + String operationService = ""; + for(Method method : service.methods()) { + if(method.operationService() != null) { + operationService = method.operationService(); + } + } + StubCommentComposer commentComposer = new StubCommentComposer(getTransportContext().transportName()); ClassDefinition classDef = @@ -79,7 +87,7 @@ public GapicClass generate(GapicContext context, Service service) { .setAnnotations(createClassAnnotations(service, typeStore)) .setImplementsTypes(createClassImplements(typeStore)) .setName(className) - .setMethods(createClassMethods(typeStore)) + .setMethods(createClassMethods(typeStore, operationService)) .setScope(ScopeNode.PUBLIC) .build(); return GapicClass.create(kind, classDef); @@ -112,12 +120,12 @@ protected List createClassAnnotations(Service service, TypeStore */ protected abstract List createClassImplements(TypeStore typeStore); - protected List createClassMethods(TypeStore typeStore) { + protected List createClassMethods(TypeStore typeStore, String operationService) { return Arrays.asList( createUnaryCallableMethod(typeStore), createPagedCallableMethod(typeStore), createBatchingCallableMethod(typeStore), - createOperationCallableMethod(typeStore)); + createOperationCallableMethod(typeStore, operationService)); } protected MethodDefinition createUnaryCallableMethod(TypeStore typeStore) { @@ -182,7 +190,7 @@ protected MethodDefinition createBatchingCallableMethod(TypeStore typeStore) { .collect(Collectors.toList())); } - protected abstract MethodDefinition createOperationCallableMethod(TypeStore typeStore); + protected abstract MethodDefinition createOperationCallableMethod(TypeStore typeStore, String operationService); protected MethodDefinition createGenericCallableMethod( TypeStore typeStore, 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 524f8f6361..3202684691 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 @@ -57,6 +57,7 @@ import com.google.api.generator.gapic.model.Service; import com.google.api.generator.gapic.utils.JavaStyle; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.longrunning.Operation; import java.io.IOException; @@ -152,6 +153,12 @@ public GapicClass generate(GapicContext context, Service service) { .setType(getTransportContext().transportOperationsStubType()) .build())); } + + boolean operationPollingMethod = checkOperationPollingMethod(service); + if(operationPollingMethod) { + declareLongRunningClient(classMemberVarExprs); + } + classMemberVarExprs.put( CALLABLE_FACTORY_MEMBER_NAME, VariableExpr.withVariable( @@ -383,7 +390,7 @@ protected List createClassMethods( createOperationsStubGetterMethod(classMemberVarExprs.get(OPERATIONS_STUB_MEMBER_NAME))); javaMethods.addAll(createCallableGetterMethods(callableClassMemberVarExprs)); javaMethods.addAll( - createStubOverrideMethods(classMemberVarExprs.get(BACKGROUND_RESOURCES_MEMBER_NAME))); + createStubOverrideMethods(classMemberVarExprs.get(BACKGROUND_RESOURCES_MEMBER_NAME), service)); return javaMethods; } @@ -625,12 +632,16 @@ protected List createConstructorMethods( secondCtorExprs.clear(); secondCtorStatements.add(EMPTY_LINE_STATEMENT); + + secondCtorStatements.addAll(createLongRunningClient(service, typeStore)); + // Instantiate backgroundResources. MethodInvocationExpr getBackgroundResourcesMethodExpr = MethodInvocationExpr.builder() .setExprReferenceExpr(clientContextVarExpr) .setMethodName("getBackgroundResources") .build(); + VariableExpr backgroundResourcesVarExpr = classMemberVarExprs.get("backgroundResources"); secondCtorExprs.add( AssignmentExpr.builder() @@ -655,6 +666,14 @@ protected List createConstructorMethods( return Arrays.asList(firstCtor, secondCtor); } + protected List createLongRunningClient(Service service, TypeStore typeStore) { + return ImmutableList.of(); + } + + protected void declareLongRunningClient(Map classMemberVarExprs) { + + } + private static Expr createCallableInitExpr( String callableVarName, VariableExpr callableVarExpr, @@ -762,7 +781,7 @@ private static List createCallableGetterMethods( } private List createStubOverrideMethods( - VariableExpr backgroundResourcesVarExpr) { + VariableExpr backgroundResourcesVarExpr, Service service) { Function methodMakerStarterFn = methodName -> MethodDefinition.builder() @@ -826,6 +845,11 @@ private List createStubOverrideMethods( .build()) .build(); List javaMethods = new ArrayList<>(); + //TODO: check for operation polling method + boolean operationPollingMethod = checkOperationPollingMethod(service); + if (operationPollingMethod) { + getterLongRunningClient(javaMethods); + } javaMethods.add( methodMakerStarterFn .apply("close") @@ -898,6 +922,19 @@ private List createStubOverrideMethods( return javaMethods; } + private boolean checkOperationPollingMethod(Service service) { + for(Method method : service.methods()) { + if(method.isOperationPollingMethod()) { + return true; + } + } + return false; + } + + protected void getterLongRunningClient(List javaMethods) { + + } + private TypeStore createDynamicTypes(Service service, String stubPakkage) { TypeStore typeStore = new TypeStore(); typeStore.putAll( diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposer.java index 5698f5a443..06bb6695b2 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposer.java @@ -45,8 +45,10 @@ protected List createClassImplements(TypeStore typeStore) { return Arrays.asList(getTransportContext().stubCallableFactoryType()); } - protected List createClassMethods(TypeStore typeStore) { - List classMethods = new ArrayList<>(super.createClassMethods(typeStore)); + protected List createClassMethods( + TypeStore typeStore, String operationService) { + List classMethods = + new ArrayList<>(super.createClassMethods(typeStore, operationService)); classMethods.addAll( Arrays.asList( createBidiStreamingCallableMethod(typeStore), @@ -98,7 +100,8 @@ protected MethodDefinition createPagedCallableMethod(TypeStore typeStore) { } @Override - protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { + protected MethodDefinition createOperationCallableMethod( + TypeStore typeStore, String operationService) { String methodVariantName = "Operation"; String requestTemplateName = "RequestT"; String responseTemplateName = "ResponseT"; 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 191c1d15fa..919e6c973c 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 @@ -15,7 +15,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.gax.httpjson.HttpJsonCallableFactory; import com.google.api.gax.httpjson.HttpJsonOperationSnapshotCallable; import com.google.api.gax.rpc.OperationCallable; @@ -47,7 +46,7 @@ public class HttpJsonServiceCallableFactoryClassComposer new HttpJsonServiceCallableFactoryClassComposer(); private static final TypeNode MESSAGE_TYPE = - TypeNode.withReference(ConcreteReference.withClazz(ApiMessage.class)); + TypeNode.withReference(ConcreteReference.withClazz(Operation.class)); private static final TypeNode BACKGROUND_RESOURCE_TYPE = TypeNode.withReference(ConcreteReference.withClazz(BackgroundResource.class)); @@ -86,7 +85,8 @@ protected List createClassImplements(TypeStore typeStore) { } @Override - protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { + protected MethodDefinition createOperationCallableMethod( + TypeStore typeStore, String operationService) { String methodVariantName = "Operation"; String requestTemplateName = "RequestT"; String responseTemplateName = "ResponseT"; @@ -104,6 +104,7 @@ protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { + " future."); // Generate generic method without the body + // TODO: change static usages to vapor references MethodDefinition method = createGenericCallableMethod( typeStore, @@ -119,13 +120,25 @@ protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { .collect(Collectors.toList()), Arrays.asList(betaAnnotation)); + // if (operationService.equals("")) { + // return method.toBuilder().setReturnExpr(ValueExpr.createNullExpr()).build(); + // } + List createOperationCallableBody = new ArrayList(2); - List arguments = method.arguments(); + List arguments = new ArrayList<>(method.arguments()); + // Variable stubVar = arguments.get(3).variable(); + // stubVar = Variable.builder() + // .setName(stubVar.identifier().name()) + // .setType(typeStore.get(operationService+"Stub")) + // .build(); + // arguments.set(3,VariableExpr.withVariable(stubVar)); + // method = method.toBuilder().setArguments(arguments).build(); + Variable httpJsonCallSettingsVar = arguments.get(0).variable(); - Variable callSettingsVar = arguments.get(1).variable(); + Variable operationCallSettingsVar = arguments.get(1).variable(); Variable clientContextVar = arguments.get(2).variable(); - Variable operationsStub = arguments.get(3).variable(); + Variable operationsStubVar = arguments.get(3).variable(); // Generate innerCallable VariableExpr innerCallableVarExpr = VariableExpr.builder() @@ -139,7 +152,7 @@ protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { .build(); MethodInvocationExpr getInitialCallSettingsExpr = MethodInvocationExpr.builder() - .setExprReferenceExpr(VariableExpr.withVariable(callSettingsVar)) + .setExprReferenceExpr(VariableExpr.withVariable(operationCallSettingsVar)) .setMethodName("getInitialCallSettings") .build(); MethodInvocationExpr createBaseUnaryCallableExpr = @@ -160,6 +173,20 @@ protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { .build(); createOperationCallableBody.add(ExprStatement.withExpr(innerCallableAssignExpr)); + // This is a temporary solution + VaporReference requestT = + VaporReference.builder() + .setName("RequestT") + .setPakkage("com.google.cloud.compute.v1.stub") + .build(); + + TypeNode initialCallableType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(HttpJsonOperationSnapshotCallable.class) + .setGenerics(requestT, ConcreteReference.withClazz(Operation.class)) + .build()); + // Generate initialCallable VariableExpr initialCallableVarExpr = VariableExpr.builder() @@ -167,9 +194,9 @@ protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { Variable.builder() .setName("initialCallable") .setType( - TypeNode.withReference(ConcreteReference.withClazz(UnaryCallable.class))) + initialCallableType) // TypeNode.withReference(ConcreteReference.withClazz(UnaryCallable.class))) .build()) - .setTemplateObjects(Arrays.asList(requestTemplateName, methodVariantName)) + // .setTemplateObjects(Arrays.asList(requestTemplateName, "OperationSnapshot")) .build(); MethodInvocationExpr getMethodDescriptorExpr = MethodInvocationExpr.builder() @@ -181,12 +208,7 @@ protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { .setExprReferenceExpr(getMethodDescriptorExpr) .setMethodName("getOperationSnapshotFactory") .build(); - // This is a temporary solution - VaporReference requestT = - VaporReference.builder() - .setName("RequestT") - .setPakkage("com.google.cloud.compute.v1.stub") - .build(); + TypeNode operationSnapshotCallableType = TypeNode.withReference( ConcreteReference.builder() @@ -209,7 +231,7 @@ protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { // Generate return statement MethodInvocationExpr longRunningClient = MethodInvocationExpr.builder() - .setExprReferenceExpr(VariableExpr.withVariable(operationsStub)) + .setExprReferenceExpr(VariableExpr.withVariable(operationsStubVar)) .setMethodName("longRunningClient") .build(); MethodInvocationExpr createOperationCallable = @@ -218,7 +240,7 @@ protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { TypeNode.withReference(ConcreteReference.withClazz(HttpJsonCallableFactory.class))) .setMethodName("createOperationCallable") .setArguments( - VariableExpr.withVariable(callSettingsVar), + VariableExpr.withVariable(operationCallSettingsVar), VariableExpr.withVariable(clientContextVar), longRunningClient, initialCallableVarExpr) 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 66fdfb2b4e..d00e23c5fc 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 @@ -19,12 +19,15 @@ import com.google.api.gax.httpjson.ApiMethodDescriptor; import com.google.api.gax.httpjson.FieldsExtractor; import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonLongRunningClient; import com.google.api.gax.httpjson.HttpJsonOperationSnapshot; import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; import com.google.api.gax.httpjson.ProtoMessageRequestFormatter; import com.google.api.gax.httpjson.ProtoMessageResponseParser; import com.google.api.gax.httpjson.ProtoRestSerializer; import com.google.api.gax.longrunning.OperationSnapshot; +import com.google.api.gax.rpc.LongRunningClient; +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.ConcreteReference; @@ -40,18 +43,22 @@ import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.Statement; import com.google.api.generator.engine.ast.StringObjectValue; +import com.google.api.generator.engine.ast.ThisObjectValue; import com.google.api.generator.engine.ast.TypeNode; import com.google.api.generator.engine.ast.ValueExpr; import com.google.api.generator.engine.ast.VaporReference; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; +import com.google.api.generator.gapic.composer.common.TransportContext; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.model.HttpBindings.HttpBinding; import com.google.api.generator.gapic.model.Message; import com.google.api.generator.gapic.model.Method; +import com.google.api.generator.gapic.model.OperationResponse; import com.google.api.generator.gapic.model.Service; import com.google.api.generator.gapic.utils.JavaStyle; +import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Arrays; @@ -124,14 +131,15 @@ protected Statement createMethodDescriptorVariableDecl( methodMaker.apply("setRequestFormatter", getRequestFormatterExpr(protoMethod)).apply(expr); expr = methodMaker.apply("setResponseParser", setResponseParserExpr(protoMethod)).apply(expr); - // System.out.println(protoMethod.outputType().reference().simpleName()); - if (protoMethod.outputType().reference().simpleName().equals("Operation")) { + if (protoMethod.isOperationPollingMethod() || protoMethod.operationService() != null) { expr = methodMaker .apply( "setOperationSnapshotFactory", setOperationSnapshotFactoryExpr(protoMethod, messageTypes)) .apply(expr); + } + if (protoMethod.isOperationPollingMethod()) { expr = methodMaker .apply( @@ -167,6 +175,10 @@ protected List createOperationsStubGetterMethod( return Collections.emptyList(); } + public HttpJsonServiceStubClassComposer(TransportContext transportContext) { + super(transportContext); + } + @Override protected Expr createTransportSettingsInitExpr( Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr) { @@ -380,9 +392,62 @@ private List setResponseParserExpr(Method protoMethod) { return Collections.singletonList(expr); } + // Generates get[camelCase(fieldName)] + private String getMethodFormat(String fieldName) { + return "get" + JavaStyle.toUpperCamelCase(fieldName); + } + + // Generates set[camelCase(fieldName)] + private String setMethodFormat(String fieldName) { + return "set" + JavaStyle.toUpperCamelCase(fieldName); + } + + // Generates: [nameVar].append(":").append([requestVar].get[FieldName]()); + private ExprStatement appendField( + VariableExpr nameVar, VariableExpr requestVar, String fieldName) { + BiFunction, Function> + methodMaker = getMethodMaker(); + ValueExpr colonValueExpr = + ValueExpr.builder().setValue(StringObjectValue.builder().setValue(":").build()).build(); + MethodInvocationExpr opNameAppendColonExpr = + MethodInvocationExpr.builder() + .setMethodName("append") + .setArguments(colonValueExpr) + .setExprReferenceExpr(nameVar) + .build(); + MethodInvocationExpr getField = + MethodInvocationExpr.builder() + .setExprReferenceExpr(requestVar) + .setMethodName(getMethodFormat(fieldName)) + .build(); + opNameAppendColonExpr = + methodMaker + .apply("append", Collections.singletonList(getField)) + .apply(opNameAppendColonExpr); + return ExprStatement.withExpr(opNameAppendColonExpr); + } + + // returns var.get(num); + private MethodInvocationExpr getExpr(VariableExpr var, String num) { + return MethodInvocationExpr.builder() + .setExprReferenceExpr(var) + .setMethodName("get") + .setArguments( + ValueExpr.builder() + .setValue(PrimitiveValue.builder().setValue(num).setType(TypeNode.INT).build()) + .build()) + .build(); + } + private List setOperationSnapshotFactoryExpr( Method protoMethod, Map messageTypes) { + Message inputOperationMessage = + messageTypes.get(protoMethod.inputType().reference().fullName()); + Message outputOperationMessage = + messageTypes.get(protoMethod.outputType().reference().fullName()); + OperationResponse operationResponse = outputOperationMessage.operationResponse(); + BiFunction, Function> methodMaker = getMethodMaker(); @@ -397,7 +462,6 @@ private List setOperationSnapshotFactoryExpr( List createBody = new ArrayList(4); // Generate opName - // This will be replaced and edited based on annotations TypeNode stringBuilderType = TypeNode.withReference(ConcreteReference.withClazz(StringBuilder.class)); VariableExpr opNameVarExpr = @@ -405,8 +469,8 @@ private List setOperationSnapshotFactoryExpr( Variable.builder().setType(stringBuilderType).setName("opName").build()); MethodInvocationExpr getId = MethodInvocationExpr.builder() - .setMethodName("getId") .setExprReferenceExpr(responseVarExpr) + .setMethodName(getMethodFormat(operationResponse.getNameFieldName())) .build(); Expr opNameObjectExpr = NewObjectExpr.builder().setType(stringBuilderType).setArguments(getId).build(); @@ -417,57 +481,34 @@ private List setOperationSnapshotFactoryExpr( .build(); createBody.add(ExprStatement.withExpr(opNameAssignExpr)); - // Generate changes opName - // This will be replaced and edited based on annotations - MethodInvocationExpr requestGetProjectExpr = - MethodInvocationExpr.builder() - .setMethodName("getProject") - .setExprReferenceExpr(requestVarExpr) - .build(); - ValueExpr colonValueExpr = - ValueExpr.builder().setValue(StringObjectValue.builder().setValue(":").build()).build(); - MethodInvocationExpr opNameAppendColonProjectExpr = - MethodInvocationExpr.builder() - .setMethodName("append") - .setArguments(colonValueExpr) - .setExprReferenceExpr(opNameVarExpr) - .build(); - opNameAppendColonProjectExpr = - methodMaker - .apply("append", Collections.singletonList(requestGetProjectExpr)) - .apply(opNameAppendColonProjectExpr); - createBody.add(ExprStatement.withExpr(opNameAppendColonProjectExpr)); - - // Generate changes to opName - MethodInvocationExpr requestGetRegionExpr = - MethodInvocationExpr.builder() - .setMethodName("getRegion") - .setExprReferenceExpr(requestVarExpr) - .build(); - MethodInvocationExpr opNameAppendColonRegionExpr = - MethodInvocationExpr.builder() - .setMethodName("append") - .setArguments(colonValueExpr) - .setExprReferenceExpr(opNameVarExpr) - .build(); - opNameAppendColonRegionExpr = - methodMaker - .apply("append", Collections.singletonList(requestGetRegionExpr)) - .apply(opNameAppendColonRegionExpr); - createBody.add(ExprStatement.withExpr(opNameAppendColonRegionExpr)); + // Generate compound operation name + if (!protoMethod.isOperationPollingMethod()) { + // TODO: Change to ordered map + Map requestFields = inputOperationMessage.operationRequestFields(); + List fieldAnnotationNames = new ArrayList(requestFields.keySet()); + Collections.sort(fieldAnnotationNames); + for (String fieldName : fieldAnnotationNames) { + createBody.add(appendField(opNameVarExpr, requestVarExpr, requestFields.get(fieldName))); + } + } - // Generate check status expression - // This will be replaced and edited based on annotations + // Generate check for status == done MethodInvocationExpr getStatusExpr = MethodInvocationExpr.builder() .setExprReferenceExpr(responseVarExpr) - .setMethodName("getStatus") + .setMethodName(getMethodFormat(operationResponse.getStatusFieldName())) .build(); + + String statusTypeName = operationResponse.getStatusFieldTypeName(); + String statusClassName = statusTypeName.substring(statusTypeName.lastIndexOf('.') + 1); + String statusPackage = protoMethod.servicePackage(); // "com" + + // statusTypeName.substring(0,statusTypeName.lastIndexOf('.')); + TypeNode statusType = TypeNode.withReference( VaporReference.builder() - .setName("Status") - .setPakkage("com.google.cloud.compute.v1") + .setName(statusClassName) + .setPakkage(statusPackage + "." + protoMethod.outputType().reference().simpleName()) .setIsStaticImport(false) .build()); VariableExpr statusDoneExpr = @@ -476,33 +517,38 @@ private List setOperationSnapshotFactoryExpr( .setStaticReferenceType(statusType) .build(); MethodInvocationExpr statusEqualsExpr = - methodMaker.apply("equals", Collections.singletonList(statusDoneExpr)).apply(getStatusExpr); + MethodInvocationExpr.builder() + .setExprReferenceExpr(statusDoneExpr) + .setMethodName("equals") + .setArguments(getStatusExpr) + .build(); // Generate return statement TypeNode httpJsonOperationSnapshotType = TypeNode.withReference(ConcreteReference.withClazz(HttpJsonOperationSnapshot.class)); - MethodInvocationExpr newBuilderExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(httpJsonOperationSnapshotType) - .setMethodName("newBuilder") - .build(); + + // Generate getter methods from annotations MethodInvocationExpr opNameToStringExpr = MethodInvocationExpr.builder() - .setMethodName("toString") .setExprReferenceExpr(opNameVarExpr) + .setMethodName("toString") .build(); - // This will be replaced and edited based on annotations MethodInvocationExpr getHttpErrorStatusCodeExpr = MethodInvocationExpr.builder() .setExprReferenceExpr(responseVarExpr) - .setMethodName("getHttpErrorStatusCode") + .setMethodName(getMethodFormat(operationResponse.getErrorCodeFieldName())) .build(); - // This will be replaced and edited based on annotations MethodInvocationExpr getHttpErrorMessageExpr = MethodInvocationExpr.builder() .setExprReferenceExpr(responseVarExpr) - .setMethodName("getHttpErrorMessage") + .setMethodName(getMethodFormat(operationResponse.getErrorMessageFieldName())) .build(); + MethodInvocationExpr newBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(httpJsonOperationSnapshotType) + .setMethodName("newBuilder") + .build(); + newBuilderExpr = methodMaker .apply("setName", Collections.singletonList(opNameToStringExpr)) @@ -546,10 +592,12 @@ private List setOperationSnapshotFactoryExpr( private List setPollingRequestFactoryExpr( Method protoMethod, Map messageTypes) { - BiFunction, Function> methodMaker = getMethodMaker(); + Message inputOperationMessage = + messageTypes.get(protoMethod.inputType().reference().fullName()); + List createBody = new ArrayList(1); // Generate input variables for create @@ -598,36 +646,49 @@ private List setPollingRequestFactoryExpr( createBody.add(ExprStatement.withExpr(idComponentsAssignExpr)); // Generate return statement - // This will be replaced and edited based on annotations - TypeNode getRegionOperationRequestType = - TypeNode.withReference( - VaporReference.builder() - .setName("GetRegionOperationRequest") - .setPakkage("com.google.cloud.compute.v1") - .setIsStaticImport(false) - .build()); + TypeNode getOperationRequestType = TypeNode.withReference(protoMethod.inputType().reference()); MethodInvocationExpr newBuilderExpr = MethodInvocationExpr.builder() - .setStaticReferenceType(getRegionOperationRequestType) + .setStaticReferenceType(getOperationRequestType) .setMethodName("newBuilder") .build(); - newBuilderExpr = - methodMaker - .apply("setOperation", Collections.singletonList(getExpr(idComponentsVarExpr, "0"))) - .apply(newBuilderExpr); - newBuilderExpr = - methodMaker - .apply("setProject", Collections.singletonList(getExpr(idComponentsVarExpr, "1"))) - .apply(newBuilderExpr); - newBuilderExpr = - methodMaker - .apply("setRegion", Collections.singletonList(getExpr(idComponentsVarExpr, "2"))) - .apply(newBuilderExpr); + BiMap responseFieldsMap = inputOperationMessage.operationResponseFields(); + List responseFieldAnnotationNames = new ArrayList(responseFieldsMap.keySet()); + Collections.sort(responseFieldAnnotationNames); + Set responseFieldsNames = responseFieldsMap.inverse().keySet(); + Set allFieldsNames = inputOperationMessage.fieldMap().keySet(); + ArrayList nonResponseFieldsNames = new ArrayList(); + for (String fieldName : allFieldsNames) { + if (!responseFieldsNames.contains(fieldName)) { + nonResponseFieldsNames.add(fieldName); + } + } + Collections.sort(nonResponseFieldsNames); + int index = 0; + for (String fieldAnnotationName : responseFieldAnnotationNames) { + newBuilderExpr = + methodMaker + .apply( + setMethodFormat(responseFieldsMap.get(fieldAnnotationName)), + Collections.singletonList(getExpr(idComponentsVarExpr, Integer.toString(index)))) + .apply(newBuilderExpr); + index++; + } + for (String fieldName : nonResponseFieldsNames) { + newBuilderExpr = + methodMaker + .apply( + setMethodFormat(fieldName), + Collections.singletonList(getExpr(idComponentsVarExpr, Integer.toString(index)))) + .apply(newBuilderExpr); + index++; + } + MethodInvocationExpr buildExpr = MethodInvocationExpr.builder() .setExprReferenceExpr(newBuilderExpr) .setMethodName("build") - .setReturnType(getRegionOperationRequestType) + .setReturnType(getOperationRequestType) .build(); // Return lambda anonymous class @@ -639,18 +700,6 @@ private List setPollingRequestFactoryExpr( .build()); } - // returns var.get(num); - private MethodInvocationExpr getExpr(VariableExpr var, String num) { - return MethodInvocationExpr.builder() - .setExprReferenceExpr(var) - .setMethodName("get") - .setArguments( - ValueExpr.builder() - .setValue(PrimitiveValue.builder().setValue(num).setType(TypeNode.INT).build()) - .build()) - .build(); - } - private Expr createFieldsExtractorClassInstance( Method method, TypeNode extractorReturnType, @@ -809,4 +858,120 @@ private List getHttpMethodTypeExpr(Method protoMethod) { .build(); return Collections.singletonList(expr); } + + @Override + protected List createLongRunningClient(Service service, TypeStore typeStore) { + boolean operation_polling_method = false; + Method protoMethod = null; + for (Method method : service.methods()) { + if (method.isOperationPollingMethod()) { + protoMethod = method; + operation_polling_method = true; + break; + } + } + if (operation_polling_method) { + Expr thisExpr = + ValueExpr.withValue( + ThisObjectValue.withType( + typeStore.get( + getTransportContext() + .classNames() + .getTransportServiceStubClassName(service)))); + + VariableExpr callable = + VariableExpr.withVariable( + Variable.builder() + .setName(protoMethod.name().toLowerCase() + "Callable") + .setType(TypeNode.withReference(ConcreteReference.withClazz(UnaryCallable.class))) + .build()); + VariableExpr methodDescriptor = + VariableExpr.withVariable( + Variable.builder() + .setName(protoMethod.name().toLowerCase() + "MethodDescriptor") + .setType( + TypeNode.withReference( + ConcreteReference.withClazz(ApiMethodDescriptor.class))) + .build()); + + TypeNode httpJsonLongRunningClientType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(HttpJsonLongRunningClient.class) + .setGenerics( + Arrays.asList( + protoMethod.inputType().reference(), + protoMethod.outputType().reference())) + .build()); + + NewObjectExpr HttpJsonLongRunningClient = + NewObjectExpr.builder() + .setType(httpJsonLongRunningClientType) + .setArguments( + Arrays.asList( + callable, + MethodInvocationExpr.builder() + .setExprReferenceExpr(methodDescriptor) + .setMethodName("getOperationSnapshotFactory") + .build(), + MethodInvocationExpr.builder() + .setExprReferenceExpr(methodDescriptor) + .setMethodName("getPollingRequestFactory") + .build())) + .build(); + + AssignmentExpr assignLongRunningClient = + AssignmentExpr.builder() + .setVariableExpr( + VariableExpr.builder() + .setExprReferenceExpr(thisExpr) + .setVariable( + Variable.builder() + .setName("longRunningClient") + .setType( + TypeNode.withReference( + ConcreteReference.withClazz(LongRunningClient.class))) + .build()) + .build()) + .setValueExpr(HttpJsonLongRunningClient) + .build(); + + return Arrays.asList(ExprStatement.withExpr(assignLongRunningClient)); + } else { + return Collections.emptyList(); + } + } + + @Override + protected void declareLongRunningClient(Map classMemberVarExprs) { + classMemberVarExprs.put( + "longRunningClient", + VariableExpr.withVariable( + Variable.builder() + .setName("longRunningClient") + .setType( + TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) + .build())); + } + + @Override + protected void getterLongRunningClient(List javaMethods) { + VariableExpr longRunningClient = + VariableExpr.withVariable( + Variable.builder() + .setName("longRunningClient") + .setType( + TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) + .build()); + + javaMethods.add( + MethodDefinition.builder() + .setName("longRunningClient") + .setScope(ScopeNode.PUBLIC) + .setIsOverride(true) + .setReturnType( + TypeNode.withReference(ConcreteReference.withClazz(LongRunningClient.class))) + .setReturnExpr(longRunningClient) + .build()); + } } diff --git a/src/main/java/com/google/api/generator/gapic/model/Message.java b/src/main/java/com/google/api/generator/gapic/model/Message.java index c58e62582e..51245444fe 100644 --- a/src/main/java/com/google/api/generator/gapic/model/Message.java +++ b/src/main/java/com/google/api/generator/gapic/model/Message.java @@ -18,6 +18,8 @@ import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.TypeNode; import com.google.auto.value.AutoValue; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.util.Arrays; @@ -51,6 +53,12 @@ public abstract class Message { public abstract ImmutableMap fieldMap(); + public abstract OperationResponse operationResponse(); + + public abstract Map operationRequestFields(); + + public abstract BiMap operationResponseFields(); + // The resource name annotation (and definition) in this message. Optional. // Expected dto be empty for messages that have no such definition. @Nullable @@ -103,7 +111,10 @@ public static Builder builder() { .setOuterNestedTypes(Collections.emptyList()) .setFields(Collections.emptyList()) .setFieldMap(Collections.emptyMap()) - .setEnumValues(Collections.emptyMap()); + .setEnumValues(Collections.emptyMap()) + .setOperationResponseFields(HashBiMap.create()) + .setOperationRequestFields(Collections.emptyMap()) + .setOperationResponse(OperationResponse.builder().build()); } @AutoValue.Builder @@ -129,6 +140,13 @@ public Builder setEnumValues(List names, List numbers) { public abstract Builder setOuterNestedTypes(List outerNestedTypes); + public abstract Builder setOperationResponse(OperationResponse operationResponse); + + public abstract Builder setOperationRequestFields(Map operationRequestFields); + + public abstract Builder setOperationResponseFields( + BiMap operationRequestFields); + abstract Builder setFieldMap(Map fieldMap); abstract ImmutableList fields(); diff --git a/src/main/java/com/google/api/generator/gapic/model/Method.java b/src/main/java/com/google/api/generator/gapic/model/Method.java index 56a1403098..aaf3f4a596 100644 --- a/src/main/java/com/google/api/generator/gapic/model/Method.java +++ b/src/main/java/com/google/api/generator/gapic/model/Method.java @@ -66,6 +66,14 @@ public boolean isPaged() { // [["content", "error"], ["content", "error", "info"]]. public abstract ImmutableList> methodSignatures(); + public abstract boolean operationPollingMethod(); + + @Nullable + public abstract String operationService(); + + @Nullable + public abstract String servicePackage(); + public boolean hasLro() { return lro() != null; } @@ -82,6 +90,10 @@ public boolean isMixin() { return mixedInApiName() != null; } + public boolean isOperationPollingMethod() { + return operationPollingMethod(); + } + public abstract Builder toBuilder(); public static Builder builder() { @@ -89,7 +101,8 @@ public static Builder builder() { .setStream(Stream.NONE) .setMethodSignatures(ImmutableList.of()) .setIsBatching(false) - .setIsDeprecated(false); + .setIsDeprecated(false) + .setOperationPollingMethod(false); } public static Stream toStream(boolean isClientStreaming, boolean isServerStreaming) { @@ -131,6 +144,12 @@ public abstract static class Builder { public abstract Builder setIsDeprecated(boolean isDeprecated); + public abstract Builder setOperationPollingMethod(boolean operationPollingMethod); + + public abstract Builder setOperationService(String operationService); + + public abstract Builder setServicePackage(String servicePackage); + public abstract Method build(); } } diff --git a/src/main/java/com/google/api/generator/gapic/model/OperationResponse.java b/src/main/java/com/google/api/generator/gapic/model/OperationResponse.java new file mode 100644 index 0000000000..1a141479ac --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/model/OperationResponse.java @@ -0,0 +1,56 @@ +/* + * 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.model; + +import com.google.auto.value.AutoValue; +import javax.annotation.Nullable; + +@AutoValue +public abstract class OperationResponse { + @Nullable + public abstract String getNameFieldName(); + + @Nullable + public abstract String getStatusFieldName(); + + @Nullable + public abstract String getErrorCodeFieldName(); + + @Nullable + public abstract String getErrorMessageFieldName(); + + @Nullable + public abstract String getStatusFieldTypeName(); + + public static Builder builder() { + return new AutoValue_OperationResponse.Builder(); + } + + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder setNameFieldName(String nameFieldName); + + public abstract Builder setStatusFieldName(String val); + + public abstract Builder setErrorCodeFieldName(String val); + + public abstract Builder setErrorMessageFieldName(String val); + + public abstract Builder setStatusFieldTypeName(String className); + + public abstract OperationResponse build(); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/protoparser/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/protoparser/BUILD.bazel index 6cccdd373a..904b7fbf2b 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/BUILD.bazel +++ b/src/main/java/com/google/api/generator/gapic/protoparser/BUILD.bazel @@ -30,6 +30,7 @@ java_library( "@com_google_code_findbugs_jsr305//jar", "@com_google_code_gson//jar", "@com_google_googleapis//google/api:api_java_proto", + "@com_google_googleapis//google/cloud:extended_operations_java_proto", "@com_google_googleapis//google/longrunning:longrunning_java_proto", "@com_google_guava_guava//jar", "@com_google_protobuf//:protobuf_java", diff --git a/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java b/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java index 42e2abaa2f..0fdbb86c2b 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java +++ b/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java @@ -30,15 +30,20 @@ import com.google.api.generator.gapic.model.LongrunningOperation; import com.google.api.generator.gapic.model.Message; import com.google.api.generator.gapic.model.Method; +import com.google.api.generator.gapic.model.OperationResponse; import com.google.api.generator.gapic.model.ResourceName; import com.google.api.generator.gapic.model.ResourceReference; import com.google.api.generator.gapic.model.Service; import com.google.api.generator.gapic.model.SourceCodeInfoLocation; import com.google.api.generator.gapic.model.Transport; import com.google.api.generator.gapic.utils.ResourceNameConstants; +import com.google.cloud.ExtendedOperationsProto; +import com.google.cloud.OperationResponseMapping; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.longrunning.OperationInfo; @@ -554,6 +559,35 @@ private static Map parseMessages( } } TypeNode messageType = TypeParser.parseType(messageDescriptor); + + List fields = messageDescriptor.getFields(); + HashMap operationRequestFields = new HashMap(); + BiMap operationResponseFields = HashBiMap.create(); + OperationResponse.Builder operationResponse = OperationResponse.builder(); + for (FieldDescriptor fd : fields) { + if (fd.getOptions().hasExtension(ExtendedOperationsProto.operationRequestField)) { + String orf = fd.getOptions().getExtension(ExtendedOperationsProto.operationRequestField); + operationRequestFields.put(orf, fd.getName()); + } + if (fd.getOptions().hasExtension(ExtendedOperationsProto.operationResponseField)) { + String orf = fd.getOptions().getExtension(ExtendedOperationsProto.operationResponseField); + operationResponseFields.put(orf, fd.getName()); + } + if (fd.getOptions().hasExtension(ExtendedOperationsProto.operationField)) { + OperationResponseMapping orm = + fd.getOptions().getExtension(ExtendedOperationsProto.operationField); + if (orm.equals(OperationResponseMapping.NAME)) { + operationResponse.setNameFieldName(fd.getName()); + } else if (orm.equals(OperationResponseMapping.STATUS)) { + operationResponse.setStatusFieldName(fd.getName()); + operationResponse.setStatusFieldTypeName(fd.toProto().getTypeName()); + } else if (orm.equals(OperationResponseMapping.ERROR_CODE)) { + operationResponse.setErrorCodeFieldName(fd.getName()); + } else if (orm.equals(OperationResponseMapping.ERROR_MESSAGE)) { + operationResponse.setErrorMessageFieldName(fd.getName()); + } + } + } messages.put( messageType.reference().fullName(), Message.builder() @@ -562,6 +596,9 @@ private static Map parseMessages( .setFullProtoName(messageDescriptor.getFullName()) .setFields(parseFields(messageDescriptor, outputResourceReferencesSeen)) .setOuterNestedTypes(outerNestedTypes) + .setOperationRequestFields(operationRequestFields) + .setOperationResponseFields(operationResponseFields) + .setOperationResponse(operationResponse.build()) .build()); return messages; } @@ -664,6 +701,17 @@ static List parseMethods( serviceDescriptor.getName(), protoMethod.getName()); + boolean operationPollingMethod = + protoMethod.getOptions().hasExtension(ExtendedOperationsProto.operationPollingMethod) + ? protoMethod + .getOptions() + .getExtension(ExtendedOperationsProto.operationPollingMethod) + : false; + String operationService = + protoMethod.getOptions().hasExtension(ExtendedOperationsProto.operationService) + ? protoMethod.getOptions().getExtension(ExtendedOperationsProto.operationService) + : null; + methods.add( methodBuilder .setName(protoMethod.getName()) @@ -684,6 +732,9 @@ static List parseMethods( .setIsBatching(isBatching) .setPageSizeFieldName(parsePageSizeFieldName(protoMethod, messageTypes, transport)) .setIsDeprecated(isDeprecated) + .setOperationPollingMethod(operationPollingMethod) + .setOperationService(operationService) + .setServicePackage(servicePackage) .build()); // Any input type that has a resource reference will need a resource name helper class. diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden index 0b58310417..f2b65c4025 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonComplianceCallableFactory.golden @@ -2,7 +2,6 @@ package com.google.showcase.v1beta1.stub; import com.google.api.core.BetaApi; import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.httpjson.ApiMessage; import com.google.api.gax.httpjson.HttpJsonCallSettings; import com.google.api.gax.httpjson.HttpJsonCallableFactory; import com.google.api.gax.httpjson.HttpJsonOperationSnapshotCallable; @@ -27,7 +26,7 @@ import javax.annotation.Generated; @BetaApi @Generated("by gapic-generator-java") public class HttpJsonComplianceCallableFactory - implements HttpJsonStubCallableFactory { + implements HttpJsonStubCallableFactory { @Override public UnaryCallable createUnaryCallable( @@ -62,14 +61,14 @@ public class HttpJsonComplianceCallableFactory @Override public OperationCallable createOperationCallable( - HttpJsonCallSettings httpJsonCallSettings, + HttpJsonCallSettings httpJsonCallSettings, OperationCallSettings callSettings, ClientContext clientContext, BackgroundResource operationsStub) { UnaryCallable innerCallable = HttpJsonCallableFactory.createBaseUnaryCallable( httpJsonCallSettings, callSettings.getInitialCallSettings(), clientContext); - UnaryCallable initialCallable = + HttpJsonOperationSnapshotCallable initialCallable = new HttpJsonOperationSnapshotCallable( innerCallable, httpJsonCallSettings.getMethodDescriptor().getOperationSnapshotFactory()); diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesCallableFactory.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesCallableFactory.java index 49347e5792..b9e0385e12 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesCallableFactory.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesCallableFactory.java @@ -18,7 +18,6 @@ import com.google.api.core.BetaApi; import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.httpjson.ApiMessage; import com.google.api.gax.httpjson.HttpJsonCallSettings; import com.google.api.gax.httpjson.HttpJsonCallableFactory; import com.google.api.gax.httpjson.HttpJsonOperationSnapshotCallable; @@ -42,7 +41,7 @@ @Generated("by gapic-generator-java") @BetaApi public class HttpJsonAddressesCallableFactory - implements HttpJsonStubCallableFactory { + implements HttpJsonStubCallableFactory { @Override public UnaryCallable createUnaryCallable( @@ -77,14 +76,14 @@ public UnaryCallable createBatchingCa @Override public OperationCallable createOperationCallable( - HttpJsonCallSettings httpJsonCallSettings, + HttpJsonCallSettings httpJsonCallSettings, OperationCallSettings callSettings, ClientContext clientContext, BackgroundResource operationsStub) { UnaryCallable innerCallable = HttpJsonCallableFactory.createBaseUnaryCallable( httpJsonCallSettings, callSettings.getInitialCallSettings(), clientContext); - UnaryCallable initialCallable = + HttpJsonOperationSnapshotCallable initialCallable = new HttpJsonOperationSnapshotCallable( innerCallable, httpJsonCallSettings.getMethodDescriptor().getOperationSnapshotFactory()); diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java index e2d4a26060..d79d2cc64a 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonAddressesStub.java @@ -38,14 +38,12 @@ import com.google.cloud.compute.v1.AddressList; import com.google.cloud.compute.v1.AggregatedListAddressesRequest; import com.google.cloud.compute.v1.DeleteAddressRequest; -import com.google.cloud.compute.v1.GetRegionOperationRequest; import com.google.cloud.compute.v1.InsertAddressRequest; import com.google.cloud.compute.v1.ListAddressesRequest; import com.google.cloud.compute.v1.Operation; -import com.google.cloud.compute.v1.Status; +import com.google.cloud.compute.v1.Operation.Status; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -144,26 +142,17 @@ public class HttpJsonAddressesStub extends AddressesStub { .build()) .setOperationSnapshotFactory( (DeleteAddressRequest request, Operation response) -> { - StringBuilder opName = new StringBuilder(response.getId()); + StringBuilder opName = new StringBuilder(response.getName()); opName.append(":").append(request.getProject()); opName.append(":").append(request.getRegion()); return HttpJsonOperationSnapshot.newBuilder() .setName(opName.toString()) .setMetadata(response) - .setDone(response.getStatus().equals(Status.DONE)) + .setDone(Status.DONE.equals(response.getStatus())) .setResponse(response) .setError(response.getHttpErrorStatusCode(), response.getHttpErrorMessage()) .build(); }) - .setPollingRequestFactory( - compoundOperationId -> { - List idComponents = Arrays.asList(compoundOperationId.split(":")); - return GetRegionOperationRequest.newBuilder() - .setOperation(idComponents.get(0)) - .setProject(idComponents.get(1)) - .setRegion(idComponents.get(2)) - .build(); - }) .build(); private static final ApiMethodDescriptor insertMethodDescriptor = @@ -203,26 +192,17 @@ public class HttpJsonAddressesStub extends AddressesStub { .build()) .setOperationSnapshotFactory( (InsertAddressRequest request, Operation response) -> { - StringBuilder opName = new StringBuilder(response.getId()); + StringBuilder opName = new StringBuilder(response.getName()); opName.append(":").append(request.getProject()); opName.append(":").append(request.getRegion()); return HttpJsonOperationSnapshot.newBuilder() .setName(opName.toString()) .setMetadata(response) - .setDone(response.getStatus().equals(Status.DONE)) + .setDone(Status.DONE.equals(response.getStatus())) .setResponse(response) .setError(response.getHttpErrorStatusCode(), response.getHttpErrorMessage()) .build(); }) - .setPollingRequestFactory( - compoundOperationId -> { - List idComponents = Arrays.asList(compoundOperationId.split(":")); - return GetRegionOperationRequest.newBuilder() - .setOperation(idComponents.get(0)) - .setProject(idComponents.get(1)) - .setRegion(idComponents.get(2)) - .build(); - }) .build(); private static final ApiMethodDescriptor listMethodDescriptor = diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java index 6113b5f496..b775dbba59 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsCallableFactory.java @@ -18,7 +18,6 @@ import com.google.api.core.BetaApi; import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.httpjson.ApiMessage; import com.google.api.gax.httpjson.HttpJsonCallSettings; import com.google.api.gax.httpjson.HttpJsonCallableFactory; import com.google.api.gax.httpjson.HttpJsonOperationSnapshotCallable; @@ -42,7 +41,7 @@ @Generated("by gapic-generator-java") @BetaApi public class HttpJsonRegionOperationsCallableFactory - implements HttpJsonStubCallableFactory { + implements HttpJsonStubCallableFactory { @Override public UnaryCallable createUnaryCallable( @@ -77,14 +76,14 @@ public UnaryCallable createBatchingCa @Override public OperationCallable createOperationCallable( - HttpJsonCallSettings httpJsonCallSettings, + HttpJsonCallSettings httpJsonCallSettings, OperationCallSettings callSettings, ClientContext clientContext, BackgroundResource operationsStub) { UnaryCallable innerCallable = HttpJsonCallableFactory.createBaseUnaryCallable( httpJsonCallSettings, callSettings.getInitialCallSettings(), clientContext); - UnaryCallable initialCallable = + HttpJsonOperationSnapshotCallable initialCallable = new HttpJsonOperationSnapshotCallable( innerCallable, httpJsonCallSettings.getMethodDescriptor().getOperationSnapshotFactory()); diff --git a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java index 47bc6a36a7..1949dd2c60 100644 --- a/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java +++ b/test/integration/goldens/compute/com/google/cloud/compute/v1/stub/HttpJsonRegionOperationsStub.java @@ -23,6 +23,7 @@ import com.google.api.gax.core.BackgroundResourceAggregation; import com.google.api.gax.httpjson.ApiMethodDescriptor; import com.google.api.gax.httpjson.HttpJsonCallSettings; +import com.google.api.gax.httpjson.HttpJsonLongRunningClient; import com.google.api.gax.httpjson.HttpJsonOperationSnapshot; import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; import com.google.api.gax.httpjson.ProtoMessageRequestFormatter; @@ -30,10 +31,11 @@ import com.google.api.gax.httpjson.ProtoRestSerializer; import com.google.api.gax.longrunning.OperationSnapshot; import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.LongRunningClient; import com.google.api.gax.rpc.UnaryCallable; import com.google.cloud.compute.v1.GetRegionOperationRequest; import com.google.cloud.compute.v1.Operation; -import com.google.cloud.compute.v1.Status; +import com.google.cloud.compute.v1.Operation.Status; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -85,13 +87,11 @@ public class HttpJsonRegionOperationsStub extends RegionOperationsStub { .build()) .setOperationSnapshotFactory( (GetRegionOperationRequest request, Operation response) -> { - StringBuilder opName = new StringBuilder(response.getId()); - opName.append(":").append(request.getProject()); - opName.append(":").append(request.getRegion()); + StringBuilder opName = new StringBuilder(response.getName()); return HttpJsonOperationSnapshot.newBuilder() .setName(opName.toString()) .setMetadata(response) - .setDone(response.getStatus().equals(Status.DONE)) + .setDone(Status.DONE.equals(response.getStatus())) .setResponse(response) .setError(response.getHttpErrorStatusCode(), response.getHttpErrorMessage()) .build(); @@ -110,6 +110,7 @@ public class HttpJsonRegionOperationsStub extends RegionOperationsStub { private final UnaryCallable getCallable; private final BackgroundResource backgroundResources; + private final LongRunningClient longRunningClient; private final HttpJsonStubCallableFactory callableFactory; public static final HttpJsonRegionOperationsStub create(RegionOperationsStubSettings settings) @@ -160,6 +161,11 @@ protected HttpJsonRegionOperationsStub( callableFactory.createUnaryCallable( getTransportSettings, settings.getSettings(), clientContext); + this.longRunningClient = + new HttpJsonLongRunningClient( + getCallable, + getMethodDescriptor.getOperationSnapshotFactory(), + getMethodDescriptor.getPollingRequestFactory()); this.backgroundResources = new BackgroundResourceAggregation(clientContext.getBackgroundResources()); } @@ -176,6 +182,11 @@ public UnaryCallable getCallable() { return getCallable; } + @Override + public LongRunningClient longRunningClient() { + return longRunningClient; + } + @Override public final void close() { try {