diff --git a/sdk-platform-java/api-common-java/src/main/java/com/google/api/pathtemplate/PathTemplate.java b/sdk-platform-java/api-common-java/src/main/java/com/google/api/pathtemplate/PathTemplate.java index cc9f4c110e74..1fd7df80c463 100644 --- a/sdk-platform-java/api-common-java/src/main/java/com/google/api/pathtemplate/PathTemplate.java +++ b/sdk-platform-java/api-common-java/src/main/java/com/google/api/pathtemplate/PathTemplate.java @@ -296,6 +296,124 @@ public Set vars() { return bindings.keySet(); } + /** Returns the set of resource literals. A resource literal is a literal followed by a binding */ + // For example, projects/{project} is a literal/binding pair and projects is a resource literal. + public Set getResourceLiterals() { + Set canonicalSegments = new java.util.LinkedHashSet<>(); + boolean inBinding = false; + for (int i = 0; i < segments.size(); i++) { + Segment seg = segments.get(i); + if (seg.kind() == SegmentKind.BINDING) { + inBinding = true; + } else if (seg.kind() == SegmentKind.END_BINDING) { + inBinding = false; + } else if (seg.kind() == SegmentKind.LITERAL) { + String value = seg.value(); + if (value.matches("^v\\d+[a-zA-Z0-9]*$")) { // just in case + continue; + } + if (inBinding) { + // This is for extracting "projects" and "locations" from named binding + // {name=projects/*/locations/*} + canonicalSegments.add(value); + } else if (i + 1 < segments.size() && segments.get(i + 1).kind() == SegmentKind.BINDING) { + // This is for regular cases projects/{project}/locations/{location} + canonicalSegments.add(value); + } + } + } + return canonicalSegments; + } + + /** + * Returns the canonical resource name string. A canonical resource name is extracted from the + * template by finding the version literal, then finding the last binding that is a + * literal/binding pair or named binding, and then extracting the segments between the version + * literal and the last binding. + */ + // For example, projects/{project} is a literal/binding pair. {bar=projects/*/locations/*/bars/*} + // is a named binding. + // If a template is /compute/v1/projects/{project}/locations/{location}, known resources are + // "projects" and "locations", the canonical resource name is + // projects/{project}/locations/{location}. See unit tests for all cases. + public String getCanonicalResourceName(Set knownResources) { + if (knownResources == null) { + return ""; + } + + int startIndex = 0; + for (int i = 0; i < segments.size(); i++) { + Segment seg = segments.get(i); + if (seg.kind() == SegmentKind.LITERAL) { + String value = seg.value(); + if (value.matches("^v\\d+[a-zA-Z0-9]*$")) { + startIndex = i + 1; + break; + } + } + } + + int lastValidEndBindingIndex = -1; + // Iterate from the end of the segments to find the last valid resource binding. + // Searching backwards allows us to stop immediately once the last valid pair is found. + for (int i = segments.size() - 1; i >= 0; i--) { + Segment seg = segments.get(i); + + // We are looking for the end of a binding (e.g., "}" in "{project}" or "{name=projects/*}") + if (seg.kind() == SegmentKind.END_BINDING) { + int bindingStartIndex = -1; + int literalCountInBinding = 0; + boolean isValidPair = false; + + // Traverse backwards to find the start of this specific binding + // and count the literals captured inside it. + for (int j = i - 1; j >= 0; j--) { + Segment innerSeg = segments.get(j); + if (innerSeg.kind() == SegmentKind.BINDING) { + bindingStartIndex = j; + break; + } else if (innerSeg.kind() == SegmentKind.LITERAL) { + literalCountInBinding++; + } + } + + if (bindingStartIndex != -1) { + // 1. If the binding contains any literals, it is considered a valid named resource + // binding. + if (literalCountInBinding > 0) { + isValidPair = true; + } else if (bindingStartIndex > 0) { + // 2. For simple bindings like "{project}", the binding itself has no inner literal + // resources. + // Instead, we check if the literal segment immediately preceding it (e.g., "projects/") + // is a known resource. + Segment prevSeg = segments.get(bindingStartIndex - 1); + if (prevSeg.kind() == SegmentKind.LITERAL && knownResources.contains(prevSeg.value())) { + isValidPair = true; + } + } + + if (isValidPair) { + // We successfully found the last valid binding! Record its end index and terminate the + // search. + lastValidEndBindingIndex = i; + break; + } + // The current binding wasn't a valid resource pair. + // Skip over all inner segments of this invalid binding so we don't evaluate them again. + i = bindingStartIndex; + } + } + } + + if (lastValidEndBindingIndex == -1 || lastValidEndBindingIndex < startIndex) { + return ""; + } + + List canonicalSegments = segments.subList(startIndex, lastValidEndBindingIndex + 1); + return toSyntax(canonicalSegments, true).replace("=*}", "}"); + } + /** * Returns a template for the parent of this template. * diff --git a/sdk-platform-java/api-common-java/src/test/java/com/google/api/pathtemplate/PathTemplateTest.java b/sdk-platform-java/api-common-java/src/test/java/com/google/api/pathtemplate/PathTemplateTest.java index 6ac45cdf203e..4c09639e5f44 100644 --- a/sdk-platform-java/api-common-java/src/test/java/com/google/api/pathtemplate/PathTemplateTest.java +++ b/sdk-platform-java/api-common-java/src/test/java/com/google/api/pathtemplate/PathTemplateTest.java @@ -31,6 +31,7 @@ package com.google.api.pathtemplate; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.truth.Truth; import java.util.Map; import java.util.Set; @@ -894,6 +895,164 @@ void testTemplateWithMultipleSimpleBindings() { Truth.assertThat(url).isEqualTo("v1/shelves/s1/books/b1"); } + @Test + void testGetResourceLiterals_simplePath() { + PathTemplate template = + PathTemplate.create("/compute/v1/projects/{project}/locations/{location}/widgets/{widget}"); + Truth.assertThat(template.getResourceLiterals()) + .containsExactly("projects", "locations", "widgets"); + } + + @Test + void testGetResourceLiterals_multipleLiterals() { + PathTemplate template = + PathTemplate.create( + "/compute/v1/projects/{project}/global/locations/{location}/widgets/{widget}"); + Truth.assertThat(template.getResourceLiterals()) + .containsExactly("projects", "locations", "widgets"); + } + + @Test + void testGetResourceLiterals_regexPath() { + PathTemplate template = + PathTemplate.create("v1/projects/{project=projects/*}/instances/{instance_id=instances/*}"); + Truth.assertThat(template.getResourceLiterals()).containsExactly("projects", "instances"); + } + + @Test + void testGetResourceLiterals_onlyNonResourceLiterals() { + PathTemplate template = PathTemplate.create("compute/v1/projects"); + Truth.assertThat(template.getResourceLiterals()).isEmpty(); + } + + @Test + void testGetResourceLiterals_nameBinding() { + PathTemplate template = PathTemplate.create("v1/{name=projects/*/instances/*}"); + Truth.assertThat(template.getResourceLiterals()).containsExactly("projects", "instances"); + } + + @Test + void testGetResourceLiterals_complexResourceId() { + PathTemplate template = PathTemplate.create("projects/{project}/zones/{zone_a}~{zone_b}"); + Truth.assertThat(template.getResourceLiterals()).containsExactly("projects", "zones"); + } + + @Test + void testGetResourceLiterals_customVerb() { + PathTemplate template = PathTemplate.create("projects/{project}/instances/{instance}:execute"); + Truth.assertThat(template.getResourceLiterals()).containsExactly("projects", "instances"); + } + + @Test + void testGetCanonicalResourceName_namedBindingsSimple() { + Set moreKnownResources = ImmutableSet.of("projects", "locations", "bars"); + PathTemplate template = PathTemplate.create("/v1/{bar=projects/*/locations/*/bars/*}"); + Truth.assertThat(template.getCanonicalResourceName(moreKnownResources)) + .isEqualTo("{bar=projects/*/locations/*/bars/*}"); + } + + @Test + void testGetCanonicalResourceName_namedBindingsWithUnknownResource() { + Set knownResources = ImmutableSet.of(); + PathTemplate template = PathTemplate.create("/v1/{bar=projects/*/locations/*/unknown/*}"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("{bar=projects/*/locations/*/unknown/*}"); + } + + @Test + void testGetCanonicalResourceName_simplePath() { + Set knownResources = ImmutableSet.of("projects", "locations", "instances", "widgets"); + PathTemplate template = + PathTemplate.create("/compute/v1/projects/{project}/locations/{location}/widgets/{widget}"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("projects/{project}/locations/{location}/widgets/{widget}"); + } + + @Test + void testGetCanonicalResourceName_v1beta1WithSimplePath() { + Set knownResources = ImmutableSet.of("projects", "locations", "instances", "widgets"); + PathTemplate template = + PathTemplate.create( + "/compute/v1beta1/projects/{project}/locations/{location}/widgets/{widget}"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("projects/{project}/locations/{location}/widgets/{widget}"); + } + + @Test + void testGetCanonicalResourceName_regexVariables() { + Set knownResources = ImmutableSet.of("projects", "locations", "instances", "widgets"); + PathTemplate template = + PathTemplate.create("v1/projects/{project=projects/*}/instances/{instance_id=instances/*}"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("projects/{project=projects/*}/instances/{instance_id=instances/*}"); + } + + @Test + void testGetCanonicalResourceName_noVariables() { + Set knownResources = ImmutableSet.of("projects", "locations", "instances", "widgets"); + PathTemplate template = PathTemplate.create("v1/projects/locations"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)).isEmpty(); + } + + @Test + void testGetCanonicalResourceName_unknownResource() { + Set knownResources = ImmutableSet.of("projects", "locations", "instances", "widgets"); + PathTemplate template = + PathTemplate.create("v1/projects/{project}/unknownResource/{unknownResource}"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("projects/{project}"); + } + + @Test + void testGetCanonicalResourceName_customVerb() { + Set knownResources = ImmutableSet.of("projects", "locations", "instances", "widgets"); + PathTemplate template = PathTemplate.create("projects/{project}/instances/{instance}:execute"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("projects/{project}/instances/{instance}"); + } + + @Test + void testGetCanonicalResourceName_nameBindingMixedWithSimpleBinding() { + Set knownResources = ImmutableSet.of("projects", "locations", "instances", "widgets"); + PathTemplate template = + PathTemplate.create("v1/{field=projects/*/instances/*}/actions/{action}"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("{field=projects/*/instances/*}"); + } + + @Test + void testGetCanonicalResourceName_multipleLiteralsWithSimpleBinding() { + Set knownResources = ImmutableSet.of("actions"); + PathTemplate template = PathTemplate.create("v1/locations/global/actions/{action}"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("locations/global/actions/{action}"); + } + + @Test + void testGetCanonicalResourceName_multipleLiteralsWithMultipleBindings() { + Set knownResources = ImmutableSet.of("instances", "actions"); + PathTemplate template = + PathTemplate.create("v1/locations/global/instances/{instance}/actions/{action}"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("locations/global/instances/{instance}/actions/{action}"); + } + + @Test + void testGetCanonicalResourceName_multipleLiteralsBetweenMultipleBindings() { + Set knownResources = ImmutableSet.of("instances", "actions"); + PathTemplate template = + PathTemplate.create("v1/instances/{instance}/locations/global/actions/{action}"); + Truth.assertThat(template.getCanonicalResourceName(knownResources)) + .isEqualTo("instances/{instance}/locations/global/actions/{action}"); + } + + @Test + void testGetCanonicalResourceName_nullKnownResources() { + PathTemplate template = + PathTemplate.create("v1/projects/{project}/locations/{location}/widgets/{widget}"); + Truth.assertThat(template.getCanonicalResourceName(null)).isEmpty(); + } + private static void assertPositionalMatch(Map match, String... expected) { Truth.assertThat(match).isNotNull(); int i = 0; diff --git a/sdk-platform-java/gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java b/sdk-platform-java/gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java index 98d8a121f758..922dda48dcc9 100644 --- a/sdk-platform-java/gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java +++ b/sdk-platform-java/gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/common/AbstractTransportServiceStubClassComposer.java @@ -85,20 +85,26 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; +import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.annotation.Generated; import javax.annotation.Nullable; public abstract class AbstractTransportServiceStubClassComposer implements ClassComposer { + private static final List AIP_STANDARDS_METHODS = + ImmutableList.of( + "Get", "List", "Create", "Delete", "Update", "Patch", "Insert", "AggregatedList"); private static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create(); private static final String METHOD_DESCRIPTOR_NAME_PATTERN = "%sMethodDescriptor"; @@ -109,6 +115,9 @@ public abstract class AbstractTransportServiceStubClassComposer implements Class protected static final String CALLABLE_CLASS_MEMBER_PATTERN = "%sCallable"; private static final String OPERATION_CALLABLE_CLASS_MEMBER_PATTERN = "%sOperationCallable"; + private static final ImmutableList HEURISTIC_ENABLED_PACKAGES = + ImmutableList.of("google.cloud.compute", "google.cloud.sql", "google.cloud.bigquery"); + protected static final TypeStore FIXED_TYPESTORE = createStaticTypes(); private final TransportContext transportContext; @@ -147,6 +156,15 @@ private static TypeStore createStaticTypes() { return new TypeStore(concreteClazzes); } + private static boolean isHeuristicEnabled(String protoPackage) { + for (String prefix : HEURISTIC_ENABLED_PACKAGES) { + if (protoPackage.startsWith(prefix)) { + return true; + } + } + return false; + } + @Override public GapicClass generate(GapicContext context, Service service) { if (!service.hasAnyEnabledMethodsForTransport(getTransportContext().transport())) { @@ -277,11 +295,13 @@ protected List createOperationsStubGetterMethod( } protected Expr createTransportSettingsInitExpr( + Service service, Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr, List classStatements, - ImmutableMap messageTypes) { + ImmutableMap messageTypes, + Set knownResources) { MethodInvocationExpr callSettingsBuilderExpr = MethodInvocationExpr.builder() .setStaticReferenceType(getTransportContext().transportCallSettingsType()) @@ -331,7 +351,9 @@ protected Expr createTransportSettingsInitExpr( .build(); } - LambdaExpr extractor = createResourceNameExtractorClassInstance(method, messageTypes); + LambdaExpr extractor = + createResourceNameExtractorClassInstance( + service, method, messageTypes, knownResources, classStatements); if (extractor != null) { callSettingsBuilderExpr = MethodInvocationExpr.builder() @@ -774,18 +796,21 @@ protected List createConstructorMethods( .build())) .build()))); + Set knownResources = getKnownResources(service); secondCtorExprs.addAll( service.methods().stream() .filter(x -> x.isSupportedByTransport(getTransportContext().transport())) .map( m -> createTransportSettingsInitExpr( + service, m, javaStyleMethodNameToTransportSettingsVarExprs.get( JavaStyle.toLowerCamelCase(m.name())), protoMethodNameToDescriptorVarExprs.get(m.name()), classStatements, - context.messages())) + context.messages(), + knownResources)) .collect(Collectors.toList())); secondCtorStatements.addAll( secondCtorExprs.stream().map(ExprStatement::withExpr).collect(Collectors.toList())); @@ -1510,29 +1535,143 @@ private static Predicate shouldAutoPopulate(Message methodRequestMessage * resource reference (see {@link Field#hasResourceReference()}) */ @Nullable - protected static LambdaExpr createResourceNameExtractorClassInstance( - Method method, ImmutableMap messageTypes) { + protected LambdaExpr createResourceNameExtractorClassInstance( + Service service, + Method method, + ImmutableMap messageTypes, + Set knownResources, + List classStatements) { Field resourceNameField = getDestinationResourceIdField(method, messageTypes); - if (resourceNameField == null) { + if (resourceNameField != null) { + // Expected expression: request -> request.getField() + VariableExpr requestVarExpr = createRequestVarExpr(method); + List bodyStatements = new ArrayList<>(); + Expr returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(requestVarExpr) + .setMethodName( + String.format("get%s", JavaStyle.toUpperCamelCase(resourceNameField.name()))) + .setReturnType(TypeNode.STRING) + .build(); + + return LambdaExpr.builder() + .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) + .setBody(bodyStatements) + .setReturnExpr(returnExpr) + .build(); + } + + if (!isHeuristicEnabled(service.protoPakkage())) { + return null; + } + + if (!method.hasHttpBindings()) { return null; } - // Expected expression: request -> request.getField() + String canonicalPath = + extractCanonicalResourceName(method.httpBindings().pattern(), knownResources); + if (!canonicalPath.contains("{")) { + return null; + } + + // Expected expression: private static final PathTemplate GET_HEURISTIC_RESOURCE_NAME_TEMPLATE = + // PathTemplate.create("projects/{project}/locations/{location}/heuristics/{heuristic}"); + TypeNode pathTemplateType = + TypeNode.withReference(ConcreteReference.withClazz(PathTemplate.class)); + String templateName = + String.format("%s_RESOURCE_NAME_TEMPLATE", JavaStyle.toUpperSnakeCase(method.name())); + Variable pathTemplateVar = + Variable.builder().setType(pathTemplateType).setName(templateName).build(); + Statement pathTemplateClassStatement = + createPathTemplateClassStatement(canonicalPath, pathTemplateType, pathTemplateVar); + + classStatements.add(pathTemplateClassStatement); + VariableExpr requestVarExpr = createRequestVarExpr(method); List bodyStatements = new ArrayList<>(); - Expr returnExpr = + + TypeNode mapType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(Map.class) + .setGenerics(TypeNode.STRING.reference(), TypeNode.STRING.reference()) + .build()); + TypeNode hashMapType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(java.util.HashMap.class) + .setGenerics(TypeNode.STRING.reference(), TypeNode.STRING.reference()) + .build()); + + // Expected expression: Map resourceNameSegments = new HashMap(); + VariableExpr resourceNameSegmentsVarExpr = + VariableExpr.builder() + .setVariable( + Variable.builder().setName("resourceNameSegments").setType(mapType).build()) + .setIsDecl(true) + .build(); + + bodyStatements.add( + ExprStatement.withExpr( + AssignmentExpr.builder() + .setVariableExpr(resourceNameSegmentsVarExpr) + .setValueExpr( + NewObjectExpr.builder().setType(hashMapType).setIsGeneric(true).build()) + .build())); + + VariableExpr resourceNameSegmentsExpr = + VariableExpr.builder() + .setVariable( + Variable.builder().setName("resourceNameSegments").setType(mapType).build()) + .build(); + + Set httpBindings = method.httpBindings().pathParameters(); + + // For each httpBinding, + // generates resourceNameSegments.put("field",String.valueOf(request.getField())); + for (HttpBindings.HttpBinding httpBinding : httpBindings) { + if (!Pattern.compile("\\{" + httpBinding.name() + "(?:=.*?)?\\}") + .matcher(canonicalPath) + .find()) { + continue; + } + MethodInvocationExpr getFieldExpr = + createRequestFieldGetterExpr( + requestVarExpr, + httpBinding.name(), + httpBinding.field() != null && httpBinding.field().isEnum()); + + MethodInvocationExpr putExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(resourceNameSegmentsExpr) + .setMethodName("put") + .setArguments( + ValueExpr.withValue(StringObjectValue.withValue(httpBinding.name())), + MethodInvocationExpr.builder() + .setStaticReferenceType(TypeNode.STRING) + .setMethodName("valueOf") + .setArguments(getFieldExpr) + .setReturnType(TypeNode.STRING) + .build()) + .build(); + bodyStatements.add(ExprStatement.withExpr(putExpr)); + } + + MethodInvocationExpr instantiateExpr = MethodInvocationExpr.builder() - .setExprReferenceExpr(requestVarExpr) - .setMethodName( - String.format("get%s", JavaStyle.toUpperCamelCase(resourceNameField.name()))) + .setExprReferenceExpr(VariableExpr.builder().setVariable(pathTemplateVar).build()) + .setMethodName("instantiate") + .setArguments(resourceNameSegmentsExpr) .setReturnType(TypeNode.STRING) .build(); return LambdaExpr.builder() .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) .setBody(bodyStatements) - .setReturnExpr(returnExpr) + .setReturnExpr(instantiateExpr) .build(); } @@ -1698,7 +1837,8 @@ private void createRequestParamsExtractorBodyForRoutingHeaders( Variable.builder().setType(pathTemplateType).setName(pathTemplateName).build(); Expr routingHeaderPatternExpr = VariableExpr.withVariable(pathTemplateVar); Statement pathTemplateClassVar = - createPathTemplateClassStatement(routingHeaderParam, pathTemplateType, pathTemplateVar); + createPathTemplateClassStatement( + routingHeaderParam.pattern(), pathTemplateType, pathTemplateVar); classStatements.add(pathTemplateClassVar); MethodInvocationExpr addParamMethodExpr = MethodInvocationExpr.builder() @@ -1728,9 +1868,7 @@ private void createRequestParamsExtractorBodyForRoutingHeaders( } private Statement createPathTemplateClassStatement( - RoutingHeaderRule.RoutingHeaderParam routingHeaderParam, - TypeNode pathTemplateType, - Variable pathTemplateVar) { + String pattern, TypeNode pathTemplateType, Variable pathTemplateVar) { VariableExpr pathTemplateVarExpr = VariableExpr.builder() .setVariable(pathTemplateVar) @@ -1739,8 +1877,7 @@ private Statement createPathTemplateClassStatement( .setIsFinal(true) .setScope(ScopeNode.PRIVATE) .build(); - ValueExpr valueExpr = - ValueExpr.withValue(StringObjectValue.withValue(routingHeaderParam.pattern())); + ValueExpr valueExpr = ValueExpr.withValue(StringObjectValue.withValue(pattern)); Expr pathTemplateExpr = AssignmentExpr.builder() .setVariableExpr(pathTemplateVarExpr) @@ -1825,4 +1962,52 @@ private static VariableExpr createRequestVarExpr(Method method) { return VariableExpr.withVariable( Variable.builder().setType(method.inputType()).setName("request").build()); } + + private static Set getKnownResources(Service service) { + + Set knownResources = new HashSet<>(); + for (Method method : service.methods()) { + if (!method.hasHttpBindings()) { + continue; + } + if (isAipStandardMethod(AIP_STANDARDS_METHODS, method.name())) { + for (String pattern : method.httpBindings().additionalPatterns()) { + knownResources.addAll(extractLiteralSegments(pattern)); + } + knownResources.addAll(extractLiteralSegments(method.httpBindings().pattern())); + } + } + return knownResources; + } + + private static boolean isAipStandardMethod(List standards, String methodName) { + return standards.stream().anyMatch(standard -> standard.equalsIgnoreCase(methodName)); + } + + private static Set extractLiteralSegments(String pattern) { + if (pattern == null || pattern.isEmpty()) { + return new HashSet<>(); + } + try { + PathTemplate template = PathTemplate.create(pattern); + return template.getResourceLiterals(); + } catch (Exception e) { + return new HashSet<>(); + } + } + + private static String extractCanonicalResourceName(String pattern, Set knownResources) { + if (pattern == null + || pattern.isEmpty() + || knownResources == null + || knownResources.isEmpty()) { + return ""; + } + try { + PathTemplate template = PathTemplate.create(pattern); + return template.getCanonicalResourceName(knownResources); + } catch (Exception e) { + return ""; + } + } } diff --git a/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcResourceNameExtractorStub.golden b/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcResourceNameExtractorStub.golden index 371e29f39464..4657fbe7da7d 100644 --- a/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcResourceNameExtractorStub.golden +++ b/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcResourceNameExtractorStub.golden @@ -1,4 +1,4 @@ -package com.google.extractor.testing.stub; +package com.google.cloud.bigquery.testing.stub; import com.google.api.gax.core.BackgroundResource; import com.google.api.gax.core.BackgroundResourceAggregation; @@ -7,16 +7,25 @@ import com.google.api.gax.grpc.GrpcStubCallableFactory; import com.google.api.gax.rpc.ClientContext; import com.google.api.gax.rpc.RequestParamsBuilder; import com.google.api.gax.rpc.UnaryCallable; -import com.google.extractor.testing.Bar; -import com.google.extractor.testing.Foo; -import com.google.extractor.testing.GetBarRequest; -import com.google.extractor.testing.GetFooRequest; -import com.google.extractor.testing.ListFoosRequest; -import com.google.extractor.testing.ListFoosResponse; +import com.google.api.pathtemplate.PathTemplate; +import com.google.cloud.bigquery.testing.Bar; +import com.google.cloud.bigquery.testing.Foo; +import com.google.cloud.bigquery.testing.GetBarRequest; +import com.google.cloud.bigquery.testing.GetFooRequest; +import com.google.cloud.bigquery.testing.GetHeuristicRequest; +import com.google.cloud.bigquery.testing.GetHeuristicWithNamedBindingRequest; +import com.google.cloud.bigquery.testing.GetHeuristicWithNestedFieldsRequest; +import com.google.cloud.bigquery.testing.GetHeuristicWithResourceReferenceRequest; +import com.google.cloud.bigquery.testing.Heuristic; +import com.google.cloud.bigquery.testing.ListFoosRequest; +import com.google.cloud.bigquery.testing.ListFoosResponse; +import com.google.cloud.bigquery.testing.ListHeuristicsRequest; +import com.google.cloud.bigquery.testing.ListHeuristicsResponse; import com.google.longrunning.stub.GrpcOperationsStub; import io.grpc.MethodDescriptor; import io.grpc.protobuf.ProtoUtils; import java.io.IOException; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.annotation.Generated; @@ -32,7 +41,7 @@ public class GrpcResourceNameExtractorTestingStub extends ResourceNameExtractorT private static final MethodDescriptor getFooMethodDescriptor = MethodDescriptor.newBuilder() .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName("google.extractor.testing.ResourceNameExtractorTesting/GetFoo") + .setFullMethodName("google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetFoo") .setRequestMarshaller(ProtoUtils.marshaller(GetFooRequest.getDefaultInstance())) .setResponseMarshaller(ProtoUtils.marshaller(Foo.getDefaultInstance())) .setSampledToLocalTracing(true) @@ -41,30 +50,126 @@ public class GrpcResourceNameExtractorTestingStub extends ResourceNameExtractorT private static final MethodDescriptor getBarMethodDescriptor = MethodDescriptor.newBuilder() .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName("google.extractor.testing.ResourceNameExtractorTesting/GetBar") + .setFullMethodName("google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetBar") .setRequestMarshaller(ProtoUtils.marshaller(GetBarRequest.getDefaultInstance())) .setResponseMarshaller(ProtoUtils.marshaller(Bar.getDefaultInstance())) .setSampledToLocalTracing(true) .build(); + private static final MethodDescriptor + getHeuristicMethodDescriptor = + MethodDescriptor.newBuilder() + .setType(MethodDescriptor.MethodType.UNARY) + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetHeuristic") + .setRequestMarshaller(ProtoUtils.marshaller(GetHeuristicRequest.getDefaultInstance())) + .setResponseMarshaller(ProtoUtils.marshaller(Heuristic.getDefaultInstance())) + .setSampledToLocalTracing(true) + .build(); + private static final MethodDescriptor listFoosMethodDescriptor = MethodDescriptor.newBuilder() .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName("google.extractor.testing.ResourceNameExtractorTesting/ListFoos") + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/ListFoos") .setRequestMarshaller(ProtoUtils.marshaller(ListFoosRequest.getDefaultInstance())) .setResponseMarshaller(ProtoUtils.marshaller(ListFoosResponse.getDefaultInstance())) .setSampledToLocalTracing(true) .build(); + private static final MethodDescriptor + getMethodDescriptor = + MethodDescriptor.newBuilder() + .setType(MethodDescriptor.MethodType.UNARY) + .setFullMethodName("google.cloud.bigquery.testing.ResourceNameExtractorTesting/Get") + .setRequestMarshaller( + ProtoUtils.marshaller(GetHeuristicWithNamedBindingRequest.getDefaultInstance())) + .setResponseMarshaller(ProtoUtils.marshaller(Heuristic.getDefaultInstance())) + .setSampledToLocalTracing(true) + .build(); + + private static final MethodDescriptor + listMethodDescriptor = + MethodDescriptor.newBuilder() + .setType(MethodDescriptor.MethodType.UNARY) + .setFullMethodName("google.cloud.bigquery.testing.ResourceNameExtractorTesting/List") + .setRequestMarshaller( + ProtoUtils.marshaller(ListHeuristicsRequest.getDefaultInstance())) + .setResponseMarshaller( + ProtoUtils.marshaller(ListHeuristicsResponse.getDefaultInstance())) + .setSampledToLocalTracing(true) + .build(); + + private static final MethodDescriptor + getHeuristicWithResourceReferenceMethodDescriptor = + MethodDescriptor.newBuilder() + .setType(MethodDescriptor.MethodType.UNARY) + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetHeuristicWithResourceReference") + .setRequestMarshaller( + ProtoUtils.marshaller( + GetHeuristicWithResourceReferenceRequest.getDefaultInstance())) + .setResponseMarshaller(ProtoUtils.marshaller(Heuristic.getDefaultInstance())) + .setSampledToLocalTracing(true) + .build(); + + private static final MethodDescriptor + getHeuristicWithNestedFieldsMethodDescriptor = + MethodDescriptor.newBuilder() + .setType(MethodDescriptor.MethodType.UNARY) + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetHeuristicWithNestedFields") + .setRequestMarshaller( + ProtoUtils.marshaller(GetHeuristicWithNestedFieldsRequest.getDefaultInstance())) + .setResponseMarshaller(ProtoUtils.marshaller(Heuristic.getDefaultInstance())) + .setSampledToLocalTracing(true) + .build(); + + private static final MethodDescriptor + getHeuristicWithNamedBindingMethodDescriptor = + MethodDescriptor.newBuilder() + .setType(MethodDescriptor.MethodType.UNARY) + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetHeuristicWithNamedBinding") + .setRequestMarshaller( + ProtoUtils.marshaller(GetHeuristicWithNamedBindingRequest.getDefaultInstance())) + .setResponseMarshaller(ProtoUtils.marshaller(Heuristic.getDefaultInstance())) + .setSampledToLocalTracing(true) + .build(); + private final UnaryCallable getFooCallable; private final UnaryCallable getBarCallable; + private final UnaryCallable getHeuristicCallable; private final UnaryCallable listFoosCallable; + private final UnaryCallable getCallable; + private final UnaryCallable listCallable; + private final UnaryCallable + getHeuristicWithResourceReferenceCallable; + private final UnaryCallable + getHeuristicWithNestedFieldsCallable; + private final UnaryCallable + getHeuristicWithNamedBindingCallable; private final BackgroundResource backgroundResources; private final GrpcOperationsStub operationsStub; private final GrpcStubCallableFactory callableFactory; + private static final PathTemplate GET_BAR_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("{bar=projects/*/locations/*/bars/*}"); + private static final PathTemplate GET_HEURISTIC_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/locations/{location}/heuristics/{heuristic}"); + private static final PathTemplate GET_RESOURCE_NAME_TEMPLATE = + PathTemplate.create( + "projects/{project}/locations/{location}/{parent_name=reservations/*/reservationBlocks/*/reservationSubBlocks/*}/heuristics/{heuristic}"); + private static final PathTemplate LIST_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/locations/{location}"); + private static final PathTemplate GET_HEURISTIC_WITH_NESTED_FIELDS_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/locations/{location}/heuristics/{heuristic.name}"); + private static final PathTemplate GET_HEURISTIC_WITH_NAMED_BINDING_RESOURCE_NAME_TEMPLATE = + PathTemplate.create( + "projects/{project}/locations/{location}/{parent_name=reservations/*/reservationBlocks/*/reservationSubBlocks/*}/heuristics/{heuristic}"); + public static final GrpcResourceNameExtractorTestingStub create( ResourceNameExtractorTestingStubSettings settings) throws IOException { return new GrpcResourceNameExtractorTestingStub(settings, ClientContext.create(settings)); @@ -128,6 +233,32 @@ public class GrpcResourceNameExtractorTestingStub extends ResourceNameExtractorT builder.add("bar", String.valueOf(request.getBar())); return builder.build(); }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("bar", String.valueOf(request.getBar())); + return GET_BAR_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) + .build(); + GrpcCallSettings getHeuristicTransportSettings = + GrpcCallSettings.newBuilder() + .setMethodDescriptor(getHeuristicMethodDescriptor) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("heuristic", String.valueOf(request.getHeuristic())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("heuristic", String.valueOf(request.getHeuristic())); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return GET_HEURISTIC_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) .build(); GrpcCallSettings listFoosTransportSettings = GrpcCallSettings.newBuilder() @@ -140,6 +271,109 @@ public class GrpcResourceNameExtractorTestingStub extends ResourceNameExtractorT }) .setResourceNameExtractor(request -> request.getParent()) .build(); + GrpcCallSettings getTransportSettings = + GrpcCallSettings.newBuilder() + .setMethodDescriptor(getMethodDescriptor) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("heuristic", String.valueOf(request.getHeuristic())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("parent_name", String.valueOf(request.getParentName())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("heuristic", String.valueOf(request.getHeuristic())); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put("parent_name", String.valueOf(request.getParentName())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return GET_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) + .build(); + GrpcCallSettings listTransportSettings = + GrpcCallSettings.newBuilder() + .setMethodDescriptor(listMethodDescriptor) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return LIST_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) + .build(); + GrpcCallSettings + getHeuristicWithResourceReferenceTransportSettings = + GrpcCallSettings.newBuilder() + .setMethodDescriptor(getHeuristicWithResourceReferenceMethodDescriptor) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("heuristic", String.valueOf(request.getHeuristic())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor(request -> request.getFoo()) + .build(); + GrpcCallSettings + getHeuristicWithNestedFieldsTransportSettings = + GrpcCallSettings.newBuilder() + .setMethodDescriptor(getHeuristicWithNestedFieldsMethodDescriptor) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add( + "heuristic.name", String.valueOf(request.getHeuristic().getName())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put( + "heuristic.name", String.valueOf(request.getHeuristic().getName())); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return GET_HEURISTIC_WITH_NESTED_FIELDS_RESOURCE_NAME_TEMPLATE.instantiate( + resourceNameSegments); + }) + .build(); + GrpcCallSettings + getHeuristicWithNamedBindingTransportSettings = + GrpcCallSettings.newBuilder() + .setMethodDescriptor(getHeuristicWithNamedBindingMethodDescriptor) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("heuristic", String.valueOf(request.getHeuristic())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("parent_name", String.valueOf(request.getParentName())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("heuristic", String.valueOf(request.getHeuristic())); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put( + "parent_name", String.valueOf(request.getParentName())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return GET_HEURISTIC_WITH_NAMED_BINDING_RESOURCE_NAME_TEMPLATE.instantiate( + resourceNameSegments); + }) + .build(); this.getFooCallable = callableFactory.createUnaryCallable( @@ -147,9 +381,33 @@ public class GrpcResourceNameExtractorTestingStub extends ResourceNameExtractorT this.getBarCallable = callableFactory.createUnaryCallable( getBarTransportSettings, settings.getBarSettings(), clientContext); + this.getHeuristicCallable = + callableFactory.createUnaryCallable( + getHeuristicTransportSettings, settings.getHeuristicSettings(), clientContext); this.listFoosCallable = callableFactory.createUnaryCallable( listFoosTransportSettings, settings.listFoosSettings(), clientContext); + this.getCallable = + callableFactory.createUnaryCallable( + getTransportSettings, settings.getSettings(), clientContext); + this.listCallable = + callableFactory.createUnaryCallable( + listTransportSettings, settings.listSettings(), clientContext); + this.getHeuristicWithResourceReferenceCallable = + callableFactory.createUnaryCallable( + getHeuristicWithResourceReferenceTransportSettings, + settings.getHeuristicWithResourceReferenceSettings(), + clientContext); + this.getHeuristicWithNestedFieldsCallable = + callableFactory.createUnaryCallable( + getHeuristicWithNestedFieldsTransportSettings, + settings.getHeuristicWithNestedFieldsSettings(), + clientContext); + this.getHeuristicWithNamedBindingCallable = + callableFactory.createUnaryCallable( + getHeuristicWithNamedBindingTransportSettings, + settings.getHeuristicWithNamedBindingSettings(), + clientContext); this.backgroundResources = new BackgroundResourceAggregation(clientContext.getBackgroundResources()); @@ -169,11 +427,44 @@ public class GrpcResourceNameExtractorTestingStub extends ResourceNameExtractorT return getBarCallable; } + @Override + public UnaryCallable getHeuristicCallable() { + return getHeuristicCallable; + } + @Override public UnaryCallable listFoosCallable() { return listFoosCallable; } + @Override + public UnaryCallable getCallable() { + return getCallable; + } + + @Override + public UnaryCallable listCallable() { + return listCallable; + } + + @Override + public UnaryCallable + getHeuristicWithResourceReferenceCallable() { + return getHeuristicWithResourceReferenceCallable; + } + + @Override + public UnaryCallable + getHeuristicWithNestedFieldsCallable() { + return getHeuristicWithNestedFieldsCallable; + } + + @Override + public UnaryCallable + getHeuristicWithNamedBindingCallable() { + return getHeuristicWithNamedBindingCallable; + } + @Override public final void close() { try { diff --git a/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonResourceNameExtractorStub.golden b/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonResourceNameExtractorStub.golden index c3296eb84117..ee8722706bd8 100644 --- a/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonResourceNameExtractorStub.golden +++ b/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/HttpJsonResourceNameExtractorStub.golden @@ -1,4 +1,4 @@ -package com.google.extractor.testing.stub; +package com.google.cloud.bigquery.testing.stub; import com.google.api.core.InternalApi; import com.google.api.gax.core.BackgroundResource; @@ -12,12 +12,20 @@ import com.google.api.gax.httpjson.ProtoRestSerializer; import com.google.api.gax.rpc.ClientContext; import com.google.api.gax.rpc.RequestParamsBuilder; import com.google.api.gax.rpc.UnaryCallable; -import com.google.extractor.testing.Bar; -import com.google.extractor.testing.Foo; -import com.google.extractor.testing.GetBarRequest; -import com.google.extractor.testing.GetFooRequest; -import com.google.extractor.testing.ListFoosRequest; -import com.google.extractor.testing.ListFoosResponse; +import com.google.api.pathtemplate.PathTemplate; +import com.google.cloud.bigquery.testing.Bar; +import com.google.cloud.bigquery.testing.Foo; +import com.google.cloud.bigquery.testing.GetBarRequest; +import com.google.cloud.bigquery.testing.GetFooRequest; +import com.google.cloud.bigquery.testing.GetHeuristicRequest; +import com.google.cloud.bigquery.testing.GetHeuristicWithNamedBindingRequest; +import com.google.cloud.bigquery.testing.GetHeuristicWithNestedFieldsRequest; +import com.google.cloud.bigquery.testing.GetHeuristicWithResourceReferenceRequest; +import com.google.cloud.bigquery.testing.Heuristic; +import com.google.cloud.bigquery.testing.ListFoosRequest; +import com.google.cloud.bigquery.testing.ListFoosResponse; +import com.google.cloud.bigquery.testing.ListHeuristicsRequest; +import com.google.cloud.bigquery.testing.ListHeuristicsResponse; import com.google.protobuf.TypeRegistry; import java.io.IOException; import java.util.ArrayList; @@ -39,7 +47,7 @@ public class HttpJsonResourceNameExtractorTestingStub extends ResourceNameExtrac private static final ApiMethodDescriptor getFooMethodDescriptor = ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.extractor.testing.ResourceNameExtractorTesting/GetFoo") + .setFullMethodName("google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetFoo") .setHttpMethod("GET") .setType(ApiMethodDescriptor.MethodType.UNARY) .setRequestFormatter( @@ -71,7 +79,7 @@ public class HttpJsonResourceNameExtractorTestingStub extends ResourceNameExtrac private static final ApiMethodDescriptor getBarMethodDescriptor = ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.extractor.testing.ResourceNameExtractorTesting/GetBar") + .setFullMethodName("google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetBar") .setHttpMethod("GET") .setType(ApiMethodDescriptor.MethodType.UNARY) .setRequestFormatter( @@ -101,10 +109,47 @@ public class HttpJsonResourceNameExtractorTestingStub extends ResourceNameExtrac .build()) .build(); + private static final ApiMethodDescriptor + getHeuristicMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetHeuristic") + .setHttpMethod("GET") + .setType(ApiMethodDescriptor.MethodType.UNARY) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1/projects/{project}/locations/{location}/heuristics/{heuristic}", + request -> { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam(fields, "heuristic", request.getHeuristic()); + serializer.putPathParam(fields, "location", request.getLocation()); + serializer.putPathParam(fields, "project", request.getProject()); + return fields; + }) + .setQueryParamsExtractor( + request -> { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + }) + .setRequestBodyExtractor(request -> null) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(Heuristic.getDefaultInstance()) + .setDefaultTypeRegistry(typeRegistry) + .build()) + .build(); + private static final ApiMethodDescriptor listFoosMethodDescriptor = ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.extractor.testing.ResourceNameExtractorTesting/ListFoos") + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/ListFoos") .setHttpMethod("GET") .setType(ApiMethodDescriptor.MethodType.UNARY) .setRequestFormatter( @@ -134,13 +179,220 @@ public class HttpJsonResourceNameExtractorTestingStub extends ResourceNameExtrac .build()) .build(); + private static final ApiMethodDescriptor + getMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.cloud.bigquery.testing.ResourceNameExtractorTesting/Get") + .setHttpMethod("GET") + .setType(ApiMethodDescriptor.MethodType.UNARY) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1/projects/{project}/locations/{location}/{parentName=reservations/*/reservationBlocks/*/reservationSubBlocks/*}/heuristics/{heuristic}", + request -> { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam(fields, "heuristic", request.getHeuristic()); + serializer.putPathParam(fields, "location", request.getLocation()); + serializer.putPathParam(fields, "parentName", request.getParentName()); + serializer.putPathParam(fields, "project", request.getProject()); + return fields; + }) + .setQueryParamsExtractor( + request -> { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + }) + .setRequestBodyExtractor(request -> null) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(Heuristic.getDefaultInstance()) + .setDefaultTypeRegistry(typeRegistry) + .build()) + .build(); + + private static final ApiMethodDescriptor + listMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName("google.cloud.bigquery.testing.ResourceNameExtractorTesting/List") + .setHttpMethod("GET") + .setType(ApiMethodDescriptor.MethodType.UNARY) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1/projects/{project}/locations/{location}/heuristics", + request -> { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam(fields, "location", request.getLocation()); + serializer.putPathParam(fields, "project", request.getProject()); + return fields; + }) + .setQueryParamsExtractor( + request -> { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + }) + .setRequestBodyExtractor(request -> null) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(ListHeuristicsResponse.getDefaultInstance()) + .setDefaultTypeRegistry(typeRegistry) + .build()) + .build(); + + private static final ApiMethodDescriptor + getHeuristicWithResourceReferenceMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetHeuristicWithResourceReference") + .setHttpMethod("GET") + .setType(ApiMethodDescriptor.MethodType.UNARY) + .setRequestFormatter( + ProtoMessageRequestFormatter + .newBuilder() + .setPath( + "/v1/projects/{project}/locations/{location}/heuristics/{heuristic}", + request -> { + Map fields = new HashMap<>(); + ProtoRestSerializer + serializer = ProtoRestSerializer.create(); + serializer.putPathParam(fields, "heuristic", request.getHeuristic()); + serializer.putPathParam(fields, "location", request.getLocation()); + serializer.putPathParam(fields, "project", request.getProject()); + return fields; + }) + .setQueryParamsExtractor( + request -> { + Map> fields = new HashMap<>(); + ProtoRestSerializer + serializer = ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "foo", request.getFoo()); + return fields; + }) + .setRequestBodyExtractor(request -> null) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(Heuristic.getDefaultInstance()) + .setDefaultTypeRegistry(typeRegistry) + .build()) + .build(); + + private static final ApiMethodDescriptor + getHeuristicWithNestedFieldsMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetHeuristicWithNestedFields") + .setHttpMethod("GET") + .setType(ApiMethodDescriptor.MethodType.UNARY) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1/projects/{project}/locations/{location}/heuristics/{heuristic.name}", + request -> { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam( + fields, "heuristic.name", request.getHeuristic().getName()); + serializer.putPathParam(fields, "location", request.getLocation()); + serializer.putPathParam(fields, "project", request.getProject()); + return fields; + }) + .setQueryParamsExtractor( + request -> { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putQueryParam(fields, "heuristic", request.getHeuristic()); + return fields; + }) + .setRequestBodyExtractor(request -> null) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(Heuristic.getDefaultInstance()) + .setDefaultTypeRegistry(typeRegistry) + .build()) + .build(); + + private static final ApiMethodDescriptor + getHeuristicWithNamedBindingMethodDescriptor = + ApiMethodDescriptor.newBuilder() + .setFullMethodName( + "google.cloud.bigquery.testing.ResourceNameExtractorTesting/GetHeuristicWithNamedBinding") + .setHttpMethod("GET") + .setType(ApiMethodDescriptor.MethodType.UNARY) + .setRequestFormatter( + ProtoMessageRequestFormatter.newBuilder() + .setPath( + "/v1/projects/{project}/locations/{location}/{parentName=reservations/*/reservationBlocks/*/reservationSubBlocks/*}/heuristics/{heuristic}", + request -> { + Map fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + serializer.putPathParam(fields, "heuristic", request.getHeuristic()); + serializer.putPathParam(fields, "location", request.getLocation()); + serializer.putPathParam(fields, "parentName", request.getParentName()); + serializer.putPathParam(fields, "project", request.getProject()); + return fields; + }) + .setQueryParamsExtractor( + request -> { + Map> fields = new HashMap<>(); + ProtoRestSerializer serializer = + ProtoRestSerializer.create(); + return fields; + }) + .setRequestBodyExtractor(request -> null) + .build()) + .setResponseParser( + ProtoMessageResponseParser.newBuilder() + .setDefaultInstance(Heuristic.getDefaultInstance()) + .setDefaultTypeRegistry(typeRegistry) + .build()) + .build(); + private final UnaryCallable getFooCallable; private final UnaryCallable getBarCallable; + private final UnaryCallable getHeuristicCallable; private final UnaryCallable listFoosCallable; + private final UnaryCallable getCallable; + private final UnaryCallable listCallable; + private final UnaryCallable + getHeuristicWithResourceReferenceCallable; + private final UnaryCallable + getHeuristicWithNestedFieldsCallable; + private final UnaryCallable + getHeuristicWithNamedBindingCallable; private final BackgroundResource backgroundResources; private final HttpJsonStubCallableFactory callableFactory; + private static final PathTemplate GET_BAR_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("{bar=projects/*/locations/*/bars/*}"); + private static final PathTemplate GET_HEURISTIC_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/locations/{location}/heuristics/{heuristic}"); + private static final PathTemplate GET_RESOURCE_NAME_TEMPLATE = + PathTemplate.create( + "projects/{project}/locations/{location}/{parent_name=reservations/*/reservationBlocks/*/reservationSubBlocks/*}/heuristics/{heuristic}"); + private static final PathTemplate LIST_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/locations/{location}"); + private static final PathTemplate GET_HEURISTIC_WITH_NESTED_FIELDS_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/locations/{location}/heuristics/{heuristic.name}"); + private static final PathTemplate GET_HEURISTIC_WITH_NAMED_BINDING_RESOURCE_NAME_TEMPLATE = + PathTemplate.create( + "projects/{project}/locations/{location}/{parent_name=reservations/*/reservationBlocks/*/reservationSubBlocks/*}/heuristics/{heuristic}"); + public static final HttpJsonResourceNameExtractorTestingStub create( ResourceNameExtractorTestingStubSettings settings) throws IOException { return new HttpJsonResourceNameExtractorTestingStub(settings, ClientContext.create(settings)); @@ -205,6 +457,33 @@ public class HttpJsonResourceNameExtractorTestingStub extends ResourceNameExtrac builder.add("bar", String.valueOf(request.getBar())); return builder.build(); }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("bar", String.valueOf(request.getBar())); + return GET_BAR_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) + .build(); + HttpJsonCallSettings getHeuristicTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(getHeuristicMethodDescriptor) + .setTypeRegistry(typeRegistry) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("heuristic", String.valueOf(request.getHeuristic())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("heuristic", String.valueOf(request.getHeuristic())); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return GET_HEURISTIC_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) .build(); HttpJsonCallSettings listFoosTransportSettings = HttpJsonCallSettings.newBuilder() @@ -218,6 +497,114 @@ public class HttpJsonResourceNameExtractorTestingStub extends ResourceNameExtrac }) .setResourceNameExtractor(request -> request.getParent()) .build(); + HttpJsonCallSettings getTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(getMethodDescriptor) + .setTypeRegistry(typeRegistry) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("heuristic", String.valueOf(request.getHeuristic())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("parent_name", String.valueOf(request.getParentName())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("heuristic", String.valueOf(request.getHeuristic())); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put("parent_name", String.valueOf(request.getParentName())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return GET_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) + .build(); + HttpJsonCallSettings listTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(listMethodDescriptor) + .setTypeRegistry(typeRegistry) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return LIST_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) + .build(); + HttpJsonCallSettings + getHeuristicWithResourceReferenceTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(getHeuristicWithResourceReferenceMethodDescriptor) + .setTypeRegistry(typeRegistry) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("heuristic", String.valueOf(request.getHeuristic())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor(request -> request.getFoo()) + .build(); + HttpJsonCallSettings + getHeuristicWithNestedFieldsTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(getHeuristicWithNestedFieldsMethodDescriptor) + .setTypeRegistry(typeRegistry) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add( + "heuristic.name", String.valueOf(request.getHeuristic().getName())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put( + "heuristic.name", String.valueOf(request.getHeuristic().getName())); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return GET_HEURISTIC_WITH_NESTED_FIELDS_RESOURCE_NAME_TEMPLATE.instantiate( + resourceNameSegments); + }) + .build(); + HttpJsonCallSettings + getHeuristicWithNamedBindingTransportSettings = + HttpJsonCallSettings.newBuilder() + .setMethodDescriptor(getHeuristicWithNamedBindingMethodDescriptor) + .setTypeRegistry(typeRegistry) + .setParamsExtractor( + request -> { + RequestParamsBuilder builder = RequestParamsBuilder.create(); + builder.add("heuristic", String.valueOf(request.getHeuristic())); + builder.add("location", String.valueOf(request.getLocation())); + builder.add("parent_name", String.valueOf(request.getParentName())); + builder.add("project", String.valueOf(request.getProject())); + return builder.build(); + }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("heuristic", String.valueOf(request.getHeuristic())); + resourceNameSegments.put("location", String.valueOf(request.getLocation())); + resourceNameSegments.put( + "parent_name", String.valueOf(request.getParentName())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return GET_HEURISTIC_WITH_NAMED_BINDING_RESOURCE_NAME_TEMPLATE.instantiate( + resourceNameSegments); + }) + .build(); this.getFooCallable = callableFactory.createUnaryCallable( @@ -225,9 +612,33 @@ public class HttpJsonResourceNameExtractorTestingStub extends ResourceNameExtrac this.getBarCallable = callableFactory.createUnaryCallable( getBarTransportSettings, settings.getBarSettings(), clientContext); + this.getHeuristicCallable = + callableFactory.createUnaryCallable( + getHeuristicTransportSettings, settings.getHeuristicSettings(), clientContext); this.listFoosCallable = callableFactory.createUnaryCallable( listFoosTransportSettings, settings.listFoosSettings(), clientContext); + this.getCallable = + callableFactory.createUnaryCallable( + getTransportSettings, settings.getSettings(), clientContext); + this.listCallable = + callableFactory.createUnaryCallable( + listTransportSettings, settings.listSettings(), clientContext); + this.getHeuristicWithResourceReferenceCallable = + callableFactory.createUnaryCallable( + getHeuristicWithResourceReferenceTransportSettings, + settings.getHeuristicWithResourceReferenceSettings(), + clientContext); + this.getHeuristicWithNestedFieldsCallable = + callableFactory.createUnaryCallable( + getHeuristicWithNestedFieldsTransportSettings, + settings.getHeuristicWithNestedFieldsSettings(), + clientContext); + this.getHeuristicWithNamedBindingCallable = + callableFactory.createUnaryCallable( + getHeuristicWithNamedBindingTransportSettings, + settings.getHeuristicWithNamedBindingSettings(), + clientContext); this.backgroundResources = new BackgroundResourceAggregation(clientContext.getBackgroundResources()); @@ -238,7 +649,13 @@ public class HttpJsonResourceNameExtractorTestingStub extends ResourceNameExtrac List methodDescriptors = new ArrayList<>(); methodDescriptors.add(getFooMethodDescriptor); methodDescriptors.add(getBarMethodDescriptor); + methodDescriptors.add(getHeuristicMethodDescriptor); methodDescriptors.add(listFoosMethodDescriptor); + methodDescriptors.add(getMethodDescriptor); + methodDescriptors.add(listMethodDescriptor); + methodDescriptors.add(getHeuristicWithResourceReferenceMethodDescriptor); + methodDescriptors.add(getHeuristicWithNestedFieldsMethodDescriptor); + methodDescriptors.add(getHeuristicWithNamedBindingMethodDescriptor); return methodDescriptors; } @@ -252,11 +669,44 @@ public class HttpJsonResourceNameExtractorTestingStub extends ResourceNameExtrac return getBarCallable; } + @Override + public UnaryCallable getHeuristicCallable() { + return getHeuristicCallable; + } + @Override public UnaryCallable listFoosCallable() { return listFoosCallable; } + @Override + public UnaryCallable getCallable() { + return getCallable; + } + + @Override + public UnaryCallable listCallable() { + return listCallable; + } + + @Override + public UnaryCallable + getHeuristicWithResourceReferenceCallable() { + return getHeuristicWithResourceReferenceCallable; + } + + @Override + public UnaryCallable + getHeuristicWithNestedFieldsCallable() { + return getHeuristicWithNestedFieldsCallable; + } + + @Override + public UnaryCallable + getHeuristicWithNamedBindingCallable() { + return getHeuristicWithNamedBindingCallable; + } + @Override public final void close() { try { diff --git a/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/test/protoloader/TestProtoLoader.java b/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/test/protoloader/TestProtoLoader.java index a4c4a3afb5c3..b14d36e82810 100644 --- a/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/test/protoloader/TestProtoLoader.java +++ b/sdk-platform-java/gapic-generator-java/src/test/java/com/google/api/generator/test/protoloader/TestProtoLoader.java @@ -31,9 +31,9 @@ import com.google.api.version.test.ApiVersionTestingOuterClass; import com.google.auto.populate.field.AutoPopulateFieldTestingOuterClass; import com.google.bookshop.v1beta1.BookshopProto; +import com.google.cloud.bigquery.testing.ResourceNameExtractorTestingOuterClass; import com.google.cloud.bigquery.v2.JobProto; import com.google.explicit.dynamic.routing.header.ExplicitDynamicRoutingHeaderTestingOuterClass; -import com.google.extractor.testing.ResourceNameExtractorTestingOuterClass; import com.google.logging.v2.LogEntryProto; import com.google.logging.v2.LoggingConfigProto; import com.google.logging.v2.LoggingMetricsProto; diff --git a/sdk-platform-java/gapic-generator-java/src/test/proto/resource_name_extractor_testing.proto b/sdk-platform-java/gapic-generator-java/src/test/proto/resource_name_extractor_testing.proto index f339db4b93ee..1dd59b24cf99 100644 --- a/sdk-platform-java/gapic-generator-java/src/test/proto/resource_name_extractor_testing.proto +++ b/sdk-platform-java/gapic-generator-java/src/test/proto/resource_name_extractor_testing.proto @@ -1,10 +1,10 @@ syntax = "proto3"; -package google.extractor.testing; +package google.cloud.bigquery.testing; option java_multiple_files = true; option java_outer_classname = "ResourceNameExtractorTestingOuterClass"; -option java_package = "com.google.extractor.testing"; +option java_package = "com.google.cloud.bigquery.testing"; import "google/api/annotations.proto"; import "google/api/client.proto"; @@ -27,14 +27,73 @@ service ResourceNameExtractorTesting { option (google.api.method_signature) = "bar"; } + rpc GetHeuristic(GetHeuristicRequest) returns (Heuristic) { + option (google.api.http) = { + get: "/v1/projects/{project}/locations/{location}/heuristics/{heuristic}" + }; + } + rpc ListFoos(ListFoosRequest) returns (ListFoosResponse) { option (google.api.http) = { get: "/v1/{parent=projects/*/locations/*}/foos" }; option (google.api.method_signature) = "parent"; } + + // Exact AIP Method for populating known resources + rpc Get(GetHeuristicWithNamedBindingRequest) returns (Heuristic) { + option (google.api.http) = { + get: "/v1/projects/{project}/locations/{location}/{parent_name=reservations/*/reservationBlocks/*/reservationSubBlocks/*}/heuristics/{heuristic}" + }; + } + + rpc List(ListHeuristicsRequest) returns (ListHeuristicsResponse) { + option (google.api.http) = { + get: "/v1/projects/{project}/locations/{location}/heuristics" + }; + } + + // Should NOT generate a heuristic, because it has a resource_reference field + rpc GetHeuristicWithResourceReference(GetHeuristicWithResourceReferenceRequest) returns (Heuristic) { + option (google.api.http) = { + get: "/v1/projects/{project}/locations/{location}/heuristics/{heuristic}" + }; + } + + + rpc GetHeuristicWithNestedFields(GetHeuristicWithNestedFieldsRequest) returns (Heuristic) { + option (google.api.http) = { + get: "/v1/projects/{project}/locations/{location}/heuristics/{heuristic.name}" + }; + } + + rpc GetHeuristicWithNamedBinding(GetHeuristicWithNamedBindingRequest) returns (Heuristic) { + option (google.api.http) = { + get: "/v1/projects/{project}/locations/{location}/{parent_name=reservations/*/reservationBlocks/*/reservationSubBlocks/*}/heuristics/{heuristic}" + }; + } +} + +message ListHeuristicsRequest { + string project = 1; + string location = 2; +} +message ListHeuristicsResponse { + repeated Heuristic heuristics = 1; +} + +message GetHeuristicWithResourceReferenceRequest { + string project = 1; + string location = 2; + string heuristic = 3; + string foo = 4 [ + (google.api.resource_reference) = { + type: "extractor.googleapis.com/Foo" + } + ]; } + message Foo { option (google.api.resource) = { type: "extractor.googleapis.com/Foo" @@ -47,6 +106,29 @@ message Bar { string name = 1; } +message GetHeuristicRequest { + string project = 1; + string location = 2; + string heuristic = 3; +} + +message GetHeuristicWithNestedFieldsRequest { + string project = 1; + string location = 2; + Heuristic heuristic = 3; +} + +message GetHeuristicWithNamedBindingRequest { + string project = 1; + string location = 2; + string parent_name = 3; + string heuristic = 4; +} + +message Heuristic { + string name = 1; +} + message GetFooRequest { string name = 1 [ (google.api.resource_reference) = { diff --git a/sdk-platform-java/test/integration/goldens/compute/src/com/google/cloud/compute/v1small/stub/HttpJsonAddressesStub.java b/sdk-platform-java/test/integration/goldens/compute/src/com/google/cloud/compute/v1small/stub/HttpJsonAddressesStub.java index 9bb9f6c18179..545ecf7a36a2 100644 --- a/sdk-platform-java/test/integration/goldens/compute/src/com/google/cloud/compute/v1small/stub/HttpJsonAddressesStub.java +++ b/sdk-platform-java/test/integration/goldens/compute/src/com/google/cloud/compute/v1small/stub/HttpJsonAddressesStub.java @@ -34,6 +34,7 @@ import com.google.api.gax.rpc.OperationCallable; import com.google.api.gax.rpc.RequestParamsBuilder; import com.google.api.gax.rpc.UnaryCallable; +import com.google.api.pathtemplate.PathTemplate; import com.google.cloud.compute.v1small.AddressAggregatedList; import com.google.cloud.compute.v1small.AddressList; import com.google.cloud.compute.v1small.AggregatedListAddressesRequest; @@ -274,6 +275,15 @@ public class HttpJsonAddressesStub extends AddressesStub { private final HttpJsonRegionOperationsStub httpJsonOperationsStub; private final HttpJsonStubCallableFactory callableFactory; + private static final PathTemplate AGGREGATED_LIST_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}"); + private static final PathTemplate DELETE_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/regions/{region}/addresses/{address}"); + private static final PathTemplate INSERT_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/regions/{region}"); + private static final PathTemplate LIST_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/regions/{region}"); + public static final HttpJsonAddressesStub create(AddressesStubSettings settings) throws IOException { return new HttpJsonAddressesStub(settings, ClientContext.create(settings)); @@ -324,6 +334,13 @@ protected HttpJsonAddressesStub( builder.add("project", String.valueOf(request.getProject())); return builder.build(); }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + return AGGREGATED_LIST_RESOURCE_NAME_TEMPLATE.instantiate( + resourceNameSegments); + }) .build(); HttpJsonCallSettings deleteTransportSettings = HttpJsonCallSettings.newBuilder() @@ -337,6 +354,14 @@ protected HttpJsonAddressesStub( builder.add("region", String.valueOf(request.getRegion())); return builder.build(); }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("address", String.valueOf(request.getAddress())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + resourceNameSegments.put("region", String.valueOf(request.getRegion())); + return DELETE_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) .build(); HttpJsonCallSettings insertTransportSettings = HttpJsonCallSettings.newBuilder() @@ -349,6 +374,13 @@ protected HttpJsonAddressesStub( builder.add("region", String.valueOf(request.getRegion())); return builder.build(); }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + resourceNameSegments.put("region", String.valueOf(request.getRegion())); + return INSERT_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) .build(); HttpJsonCallSettings listTransportSettings = HttpJsonCallSettings.newBuilder() @@ -361,6 +393,13 @@ protected HttpJsonAddressesStub( builder.add("region", String.valueOf(request.getRegion())); return builder.build(); }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + resourceNameSegments.put("region", String.valueOf(request.getRegion())); + return LIST_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) .build(); this.aggregatedListCallable = diff --git a/sdk-platform-java/test/integration/goldens/compute/src/com/google/cloud/compute/v1small/stub/HttpJsonRegionOperationsStub.java b/sdk-platform-java/test/integration/goldens/compute/src/com/google/cloud/compute/v1small/stub/HttpJsonRegionOperationsStub.java index e9e339169f9b..d0ef4b45db7c 100644 --- a/sdk-platform-java/test/integration/goldens/compute/src/com/google/cloud/compute/v1small/stub/HttpJsonRegionOperationsStub.java +++ b/sdk-platform-java/test/integration/goldens/compute/src/com/google/cloud/compute/v1small/stub/HttpJsonRegionOperationsStub.java @@ -32,6 +32,7 @@ import com.google.api.gax.rpc.LongRunningClient; import com.google.api.gax.rpc.RequestParamsBuilder; import com.google.api.gax.rpc.UnaryCallable; +import com.google.api.pathtemplate.PathTemplate; import com.google.cloud.compute.v1small.GetRegionOperationRequest; import com.google.cloud.compute.v1small.Operation; import com.google.cloud.compute.v1small.Operation.Status; @@ -153,6 +154,11 @@ public class HttpJsonRegionOperationsStub extends RegionOperationsStub { private final LongRunningClient longRunningClient; private final HttpJsonStubCallableFactory callableFactory; + private static final PathTemplate GET_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/{project}/regions/{region}/operations/{operation}"); + private static final PathTemplate WAIT_RESOURCE_NAME_TEMPLATE = + PathTemplate.create("projects/projects/{project}/regions/{region}/operations/{operation}"); + public static final HttpJsonRegionOperationsStub create(RegionOperationsStubSettings settings) throws IOException { return new HttpJsonRegionOperationsStub(settings, ClientContext.create(settings)); @@ -204,6 +210,14 @@ protected HttpJsonRegionOperationsStub( builder.add("region", String.valueOf(request.getRegion())); return builder.build(); }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("operation", String.valueOf(request.getOperation())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + resourceNameSegments.put("region", String.valueOf(request.getRegion())); + return GET_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) .build(); HttpJsonCallSettings waitTransportSettings = HttpJsonCallSettings.newBuilder() @@ -217,6 +231,14 @@ protected HttpJsonRegionOperationsStub( builder.add("region", String.valueOf(request.getRegion())); return builder.build(); }) + .setResourceNameExtractor( + request -> { + Map resourceNameSegments = new HashMap(); + resourceNameSegments.put("operation", String.valueOf(request.getOperation())); + resourceNameSegments.put("project", String.valueOf(request.getProject())); + resourceNameSegments.put("region", String.valueOf(request.getRegion())); + return WAIT_RESOURCE_NAME_TEMPLATE.instantiate(resourceNameSegments); + }) .build(); this.getCallable =