Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add parsing of autopopulated fields from serviceyaml #2312

Merged
merged 15 commits into from Dec 28, 2023
Expand Up @@ -14,6 +14,7 @@

package com.google.api.generator.gapic.model;

import com.google.api.FieldInfo.Format;
import com.google.api.generator.engine.ast.TypeNode;
import com.google.auto.value.AutoValue;
import java.util.Objects;
Expand All @@ -32,6 +33,16 @@ public abstract class Field {

public abstract TypeNode type();

// If the field contains a google.api.field_info.format value of UUID4 and is not marked as
// REQUIRED, then it is eligible to be auto-populated if the customer does not set it.
// The field needs to be cross-referenced against Method.autoPopulatedFields() to make the final
// determination if it *should* be auto-populated.
// See go/client-populate-request-id-design for more details.
public abstract boolean isEligibleToBeAutoPopulated();

@Nullable
public abstract Format fieldInfoFormat();

public abstract boolean isMessage();

public abstract boolean isEnum();
Expand Down Expand Up @@ -72,6 +83,7 @@ public boolean equals(Object o) {
return name().equals(other.name())
&& originalName().equals(other.originalName())
&& type().equals(other.type())
&& isEligibleToBeAutoPopulated() == other.isEligibleToBeAutoPopulated()
&& isMessage() == other.isMessage()
&& isEnum() == other.isEnum()
&& isRepeated() == other.isRepeated()
Expand Down Expand Up @@ -101,6 +113,7 @@ public int hashCode() {

public static Builder builder() {
return new AutoValue_Field.Builder()
.setIsEligibleToBeAutoPopulated(false)
.setIsMessage(false)
.setIsEnum(false)
.setIsRepeated(false)
Expand All @@ -117,6 +130,10 @@ public abstract static class Builder {

public abstract Builder setType(TypeNode type);

public abstract Builder setIsEligibleToBeAutoPopulated(boolean isEligibleToBeAutoPopulated);

public abstract Builder setFieldInfoFormat(Format fieldInfoFormat);

public abstract Builder setIsMessage(boolean isMessage);

public abstract Builder setIsEnum(boolean isEnum);
Expand Down
Expand Up @@ -69,6 +69,19 @@ public boolean isPaged() {
// [["content", "error"], ["content", "error", "info"]].
public abstract ImmutableList<List<MethodArgument>> methodSignatures();

@Nullable
public abstract List<String> autoPopulatedFields();
alicejli marked this conversation as resolved.
Show resolved Hide resolved

/**
* If a service's service_config.yaml file contains method_settings.auto_populated_fields for this
* method, and the method is a Unary-type, then this is true
*/
public boolean hasAutoPopulatedFields() {
alicejli marked this conversation as resolved.
Show resolved Hide resolved
return autoPopulatedFields() != null
&& autoPopulatedFields().size() > 0
&& stream().equals(Stream.NONE);
}

public abstract boolean operationPollingMethod();

public boolean hasLro() {
Expand Down Expand Up @@ -170,6 +183,8 @@ public abstract static class Builder {

public abstract Builder setOperationPollingMethod(boolean operationPollingMethod);

public abstract Builder setAutoPopulatedFields(List<String> autoPopulatedFields);

public abstract Builder setRoutingHeaderRule(RoutingHeaderRule routingHeaderRule);

public abstract Method build();
Expand Down
Expand Up @@ -16,7 +16,11 @@

import com.google.api.ClientProto;
import com.google.api.DocumentationRule;
import com.google.api.FieldBehaviorProto;
import com.google.api.FieldInfo.Format;
import com.google.api.FieldInfoProto;
import com.google.api.HttpRule;
import com.google.api.MethodSettings;
import com.google.api.ResourceDescriptor;
import com.google.api.ResourceProto;
import com.google.api.generator.engine.ast.TypeNode;
Expand Down Expand Up @@ -47,6 +51,7 @@
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 com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.longrunning.OperationInfo;
Expand Down Expand Up @@ -493,6 +498,7 @@ public static List<Service> parseService(
messageTypes,
resourceNames,
serviceConfigOpt,
serviceYamlProtoOpt,
outputArgResourceNames,
transport))
.build();
Expand Down Expand Up @@ -683,9 +689,28 @@ static List<Method> parseMethods(
Map<String, Message> messageTypes,
Map<String, ResourceName> resourceNames,
Optional<GapicServiceConfig> serviceConfigOpt,
Optional<com.google.api.Service> serviceYamlProtoOpt,
Set<ResourceName> outputArgResourceNames,
Transport transport) {
List<Method> methods = new ArrayList<>();

// Parse the serviceYaml for autopopulated methods and fields once and put into a map
ImmutableMap.Builder<String, List<String>> autoPopulatedMethodsWithFieldsBuilder =
ImmutableMap.builder();
if (serviceYamlProtoOpt.isPresent()) {
alicejli marked this conversation as resolved.
Show resolved Hide resolved
if (serviceYamlProtoOpt.get().getPublishing().getMethodSettingsList().size() > 0) {
alicejli marked this conversation as resolved.
Show resolved Hide resolved
for (MethodSettings methodSettings :
serviceYamlProtoOpt.get().getPublishing().getMethodSettingsList()) {
if (methodSettings.getAutoPopulatedFieldsCount() > 0) {
autoPopulatedMethodsWithFieldsBuilder.put(
methodSettings.getSelector(), methodSettings.getAutoPopulatedFieldsList());
}
}
}
}
ImmutableMap<String, List<String>> autoPopulatedMethodsWithFields =
autoPopulatedMethodsWithFieldsBuilder.build();

for (MethodDescriptor protoMethod : serviceDescriptor.getMethods()) {
// Parse the method.
TypeNode inputType = TypeParser.parseType(protoMethod.getInputType());
Expand All @@ -699,6 +724,12 @@ static List<Method> parseMethods(
}
}

// Parse the serviceYaml for autopopulated fields
List<String> autoPopulatedFields = null;
if (autoPopulatedMethodsWithFields.containsKey(protoMethod.getFullName())) {
autoPopulatedFields = autoPopulatedMethodsWithFields.get(protoMethod.getFullName());
}

boolean isDeprecated = false;
if (protoMethod.getOptions().hasDeprecated()) {
isDeprecated = protoMethod.getOptions().getDeprecated();
Expand Down Expand Up @@ -743,6 +774,7 @@ static List<Method> parseMethods(
resourceNames,
outputArgResourceNames))
.setHttpBindings(httpBindings)
.setAutoPopulatedFields(autoPopulatedFields)
.setRoutingHeaderRule(routingHeaderRule)
.setIsBatching(isBatching)
.setPageSizeFieldName(parsePageSizeFieldName(protoMethod, messageTypes, transport))
Expand Down Expand Up @@ -970,6 +1002,8 @@ private static Field parseField(
FieldOptions fieldOptions = fieldDescriptor.getOptions();
MessageOptions messageOptions = messageDescriptor.getOptions();
ResourceReference resourceReference = null;
boolean isEligibleToBeAutoPopulated = false;
Format fieldInfoFormat = null;
if (fieldOptions.hasExtension(ResourceProto.resourceReference)) {
com.google.api.ResourceReference protoResourceReference =
fieldOptions.getExtension(ResourceProto.resourceReference);
Expand Down Expand Up @@ -1000,6 +1034,21 @@ private static Field parseField(
}
}

// If field is annotated with fieldInfo.format = UUID4 and fieldBehavior != REQUIRED, then
// autopopulate the field
// TODO: Autopopulation requires fieldInfo.formatValue = UUID4; when more types are supported,
// this logic will need to be updated
if (fieldOptions.hasExtension(FieldInfoProto.fieldInfo)) {
fieldInfoFormat = fieldOptions.getExtension(FieldInfoProto.fieldInfo).getFormat();
if (fieldOptions.getExtension(FieldInfoProto.fieldInfo).getFormatValue() == 1) {
alicejli marked this conversation as resolved.
Show resolved Hide resolved
isEligibleToBeAutoPopulated = true;
}
}
if (fieldOptions.getExtensionCount(FieldBehaviorProto.fieldBehavior) > 0) {
blakeli0 marked this conversation as resolved.
Show resolved Hide resolved
if (fieldOptions.getExtension(FieldBehaviorProto.fieldBehavior).contains(2)) ;
alicejli marked this conversation as resolved.
Show resolved Hide resolved
isEligibleToBeAutoPopulated = false;
alicejli marked this conversation as resolved.
Show resolved Hide resolved
}

Field.Builder fieldBuilder = Field.builder();
if (fieldDescriptor.getFile().toProto().hasSourceCodeInfo()) {
SourceCodeInfoLocation protoFieldLocation =
Expand Down Expand Up @@ -1030,6 +1079,8 @@ private static Field parseField(
fieldDescriptor.getContainingOneof() != null
&& fieldDescriptor.getContainingOneof().isSynthetic())
.setIsRepeated(fieldDescriptor.isRepeated())
.setIsEligibleToBeAutoPopulated(isEligibleToBeAutoPopulated)
.setFieldInfoFormat(fieldInfoFormat)
.setIsMap(fieldDescriptor.isMapField())
.setResourceReference(resourceReference)
.build();
Expand Down
Expand Up @@ -568,6 +568,7 @@ public void createSimpleMessage_containsMessagesEnumsAndResourceName() {
"EchoRequest.newBuilder().setName("
+ "FoobarName.ofProjectFoobarName(\"[PROJECT]\", \"[FOOBAR]\").toString())"
+ ".setParent(FoobarName.ofProjectFoobarName(\"[PROJECT]\", \"[FOOBAR]\").toString())"
+ ".setRequestId(\"requestId693933066\")"
+ ".setSeverity(Severity.forNumber(0))"
+ ".setFoobar(Foobar.newBuilder().build()).build()",
writerVisitor.write());
Expand Down
Expand Up @@ -516,6 +516,7 @@ public class EchoClient implements BackgroundResource {
* EchoRequest.newBuilder()
* .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setRequestId("requestId693933066")
* .setSeverity(Severity.forNumber(0))
* .setFoobar(Foobar.newBuilder().build())
* .build();
Expand Down Expand Up @@ -545,6 +546,7 @@ public class EchoClient implements BackgroundResource {
* EchoRequest.newBuilder()
* .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setRequestId("requestId693933066")
* .setSeverity(Severity.forNumber(0))
* .setFoobar(Foobar.newBuilder().build())
* .build();
Expand All @@ -570,7 +572,11 @@ public class EchoClient implements BackgroundResource {
* // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
* try (EchoClient echoClient = EchoClient.create()) {
* ExpandRequest request =
* ExpandRequest.newBuilder().setContent("content951530617").setInfo("info3237038").build();
* ExpandRequest.newBuilder()
* .setContent("content951530617")
* .setInfo("info3237038")
* .setRequestId("requestId693933066")
* .build();
* ServerStream<EchoResponse> stream = echoClient.expandCallable().call(request);
* for (EchoResponse response : stream) {
* // Do something when a response is received.
Expand Down Expand Up @@ -616,6 +622,7 @@ public class EchoClient implements BackgroundResource {
* EchoRequest.newBuilder()
* .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setRequestId("requestId693933066")
* .setSeverity(Severity.forNumber(0))
* .setFoobar(Foobar.newBuilder().build())
* .build();
Expand Down Expand Up @@ -643,6 +650,7 @@ public class EchoClient implements BackgroundResource {
* EchoRequest.newBuilder()
* .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setRequestId("requestId693933066")
* .setSeverity(Severity.forNumber(0))
* .setFoobar(Foobar.newBuilder().build())
* .build();
Expand Down Expand Up @@ -673,6 +681,7 @@ public class EchoClient implements BackgroundResource {
* EchoRequest.newBuilder()
* .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setRequestId("requestId693933066")
* .setSeverity(Severity.forNumber(0))
* .setFoobar(Foobar.newBuilder().build())
* .build();
Expand Down Expand Up @@ -1081,6 +1090,7 @@ public class EchoClient implements BackgroundResource {
* EchoRequest.newBuilder()
* .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setRequestId("requestId693933066")
* .setSeverity(Severity.forNumber(0))
* .setFoobar(Foobar.newBuilder().build())
* .build();
Expand Down Expand Up @@ -1110,6 +1120,7 @@ public class EchoClient implements BackgroundResource {
* EchoRequest.newBuilder()
* .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
* .setRequestId("requestId693933066")
* .setSeverity(Severity.forNumber(0))
* .setFoobar(Foobar.newBuilder().build())
* .build();
Expand Down
Expand Up @@ -108,6 +108,7 @@ public class EchoClientTest {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand Down Expand Up @@ -403,7 +404,11 @@ public class EchoClientTest {
.build();
mockEcho.addResponse(expectedResponse);
ExpandRequest request =
ExpandRequest.newBuilder().setContent("content951530617").setInfo("info3237038").build();
ExpandRequest.newBuilder()
.setContent("content951530617")
.setInfo("info3237038")
.setRequestId("requestId693933066")
.build();

MockStreamObserver<EchoResponse> responseObserver = new MockStreamObserver<>();

Expand All @@ -420,7 +425,11 @@ public class EchoClientTest {
StatusRuntimeException exception = new StatusRuntimeException(io.grpc.Status.INVALID_ARGUMENT);
mockEcho.addException(exception);
ExpandRequest request =
ExpandRequest.newBuilder().setContent("content951530617").setInfo("info3237038").build();
ExpandRequest.newBuilder()
.setContent("content951530617")
.setInfo("info3237038")
.setRequestId("requestId693933066")
.build();

MockStreamObserver<EchoResponse> responseObserver = new MockStreamObserver<>();

Expand Down Expand Up @@ -449,6 +458,7 @@ public class EchoClientTest {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand All @@ -474,6 +484,7 @@ public class EchoClientTest {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand Down Expand Up @@ -507,6 +518,7 @@ public class EchoClientTest {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand All @@ -532,6 +544,7 @@ public class EchoClientTest {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand Down Expand Up @@ -565,6 +578,7 @@ public class EchoClientTest {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand All @@ -590,6 +604,7 @@ public class EchoClientTest {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand Down Expand Up @@ -848,6 +863,7 @@ public class EchoClientTest {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand All @@ -861,6 +877,7 @@ public class EchoClientTest {

Assert.assertEquals(request.getName(), actualRequest.getName());
Assert.assertEquals(request.getParent(), actualRequest.getParent());
Assert.assertEquals(request.getRequestId(), actualRequest.getRequestId());
Assert.assertEquals(request.getContent(), actualRequest.getContent());
Assert.assertEquals(request.getError(), actualRequest.getError());
Assert.assertEquals(request.getSeverity(), actualRequest.getSeverity());
Expand All @@ -881,6 +898,7 @@ public class EchoClientTest {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand Down
Expand Up @@ -43,6 +43,7 @@ public class AsyncChat {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand Down
Expand Up @@ -43,6 +43,7 @@ public class AsyncChatAgain {
EchoRequest.newBuilder()
.setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
.setRequestId("requestId693933066")
.setSeverity(Severity.forNumber(0))
.setFoobar(Foobar.newBuilder().build())
.build();
Expand Down