Search in sources :

Example 6 with Field

use of com.google.api.generator.gapic.model.Field in project gapic-generator-java by googleapis.

the class MethodSignatureParser method parseTypeFromArgumentName.

private static Map<TypeNode, Field> parseTypeFromArgumentName(String argumentName, String servicePackage, Message inputMessage, Map<String, Message> messageTypes, Map<String, ResourceName> resourceNames, Map<String, ResourceName> patternsToResourceNames, List<Field> argumentFieldPathAcc, Set<ResourceName> outputArgResourceNames) {
    Map<TypeNode, Field> typeToField = new HashMap<>();
    int dotIndex = argumentName.indexOf(DOT);
    if (dotIndex < 1) {
        Field field = inputMessage.fieldMap().get(argumentName);
        Preconditions.checkNotNull(field, String.format("Field %s not found from input message %s values %s", argumentName, inputMessage.name(), inputMessage.fieldMap().keySet()));
        if (!field.hasResourceReference()) {
            typeToField.put(field.type(), field);
            return typeToField;
        }
        // Parse the resource name tyeps.
        List<ResourceName> resourceNameArgs = ResourceReferenceParser.parseResourceNames(field.resourceReference(), servicePackage, field.description(), resourceNames, patternsToResourceNames);
        outputArgResourceNames.addAll(resourceNameArgs);
        typeToField.put(TypeNode.STRING, field);
        typeToField.putAll(resourceNameArgs.stream().collect(Collectors.toMap(r -> r.type(), r -> field.toBuilder().setResourceReference(ResourceReference.withType(r.resourceTypeString())).build())));
        // Only resource name helpers should have more than one entry.
        if (typeToField.size() > 1) {
            typeToField.entrySet().stream().forEach(e -> {
                // Skip string-only variants or ResourceName generics.
                if (e.getKey().equals(TypeNode.STRING) || e.getKey().reference().name().equals("ResourceName")) {
                    return;
                }
                String resourceJavaTypeName = e.getKey().reference().name();
                String resourceTypeName = e.getValue().resourceReference().resourceTypeString();
                int indexOfSlash = resourceTypeName.indexOf("/");
                // We assume that the corresponding Java resource name helper type (i.e. the key)
                // ends in *Name. Check that it matches the expeced resource name type.
                Preconditions.checkState(resourceJavaTypeName.substring(0, resourceJavaTypeName.length() - 4).equals(resourceTypeName.substring(indexOfSlash + 1)), String.format("Resource Java type %s does not correspond to proto type %s", resourceJavaTypeName, resourceTypeName));
            });
        }
        return typeToField;
    }
    Preconditions.checkState(dotIndex < argumentName.length() - 1, String.format("Invalid argument name found: dot cannot be at the end of name %s", argumentName));
    String firstFieldName = argumentName.substring(0, dotIndex);
    String remainingArgumentName = argumentName.substring(dotIndex + 1);
    // Must be a sub-message for a type's subfield to be valid.
    Field firstField = inputMessage.fieldMap().get(firstFieldName);
    // Validate the field into which we're descending.
    Preconditions.checkState(!firstField.isRepeated(), String.format("Cannot descend into repeated field %s", firstField.name()));
    TypeNode firstFieldType = firstField.type();
    Preconditions.checkState(TypeNode.isReferenceType(firstFieldType) && !firstFieldType.equals(TypeNode.STRING), String.format("Field reference on %s cannot be a primitive type", firstFieldName));
    String firstFieldTypeName = firstFieldType.reference().fullName();
    Message firstFieldMessage = messageTypes.get(firstFieldTypeName);
    Preconditions.checkNotNull(firstFieldMessage, String.format("Message type %s for field reference %s invalid", firstFieldTypeName, firstFieldName));
    argumentFieldPathAcc.add(firstField);
    return parseTypeFromArgumentName(remainingArgumentName, servicePackage, firstFieldMessage, messageTypes, resourceNames, patternsToResourceNames, argumentFieldPathAcc, outputArgResourceNames);
}
Also used : Field(com.google.api.generator.gapic.model.Field) Message(com.google.api.generator.gapic.model.Message) HashMap(java.util.HashMap) ResourceName(com.google.api.generator.gapic.model.ResourceName) TypeNode(com.google.api.generator.engine.ast.TypeNode)

Example 7 with Field

use of com.google.api.generator.gapic.model.Field in project gapic-generator-java by googleapis.

the class Parser method parseFields.

private static List<Field> parseFields(Descriptor messageDescriptor, Set<ResourceReference> outputResourceReferencesSeen) {
    List<FieldDescriptor> fields = new ArrayList<>(messageDescriptor.getFields());
    // Sort by ascending field index order. This is important for paged responses, where the first
    // repeated type is taken.
    fields.sort((f1, f2) -> f1.getIndex() - f2.getIndex());
    // Mirror protoc's name conflict resolution behavior for fields.
    // If a singular field's name equals that of a repeated field with "Count" or "List" suffixed,
    // append the protobuf's field number to both fields' names.
    // See:
    // https://github.com/protocolbuffers/protobuf/blob/9df42757f97da9f748a464deeda96427a8f7ade0/src/google/protobuf/compiler/java/java_context.cc#L60
    Map<String, Integer> repeatedFieldNamesToNumber = fields.stream().filter(f -> f.isRepeated()).collect(Collectors.toMap(f -> f.getName(), f -> f.getNumber()));
    Set<Integer> fieldNumbersWithConflicts = new HashSet<>();
    for (FieldDescriptor field : fields) {
        Set<String> conflictingRepeatedFieldNames = repeatedFieldNamesToNumber.keySet().stream().filter(n -> field.getName().equals(n + "_count") || field.getName().equals(n + "_list")).collect(Collectors.toSet());
        if (!conflictingRepeatedFieldNames.isEmpty()) {
            fieldNumbersWithConflicts.addAll(conflictingRepeatedFieldNames.stream().map(n -> repeatedFieldNamesToNumber.get(n)).collect(Collectors.toSet()));
            fieldNumbersWithConflicts.add(field.getNumber());
        }
    }
    return fields.stream().map(f -> parseField(f, messageDescriptor, fieldNumbersWithConflicts.contains(f.getNumber()), outputResourceReferencesSeen)).collect(Collectors.toList());
}
Also used : HttpBindings(com.google.api.generator.gapic.model.HttpBindings) CodeGeneratorRequest(com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest) Arrays(java.util.Arrays) RoutingHeaderRule(com.google.api.generator.gapic.model.RoutingHeaderRule) OperationInfo(com.google.longrunning.OperationInfo) GapicServiceConfig(com.google.api.generator.gapic.model.GapicServiceConfig) DescriptorValidationException(com.google.protobuf.Descriptors.DescriptorValidationException) Field(com.google.api.generator.gapic.model.Field) Method(com.google.api.generator.gapic.model.Method) HttpRule(com.google.api.HttpRule) LongrunningOperation(com.google.api.generator.gapic.model.LongrunningOperation) Map(java.util.Map) ResourceProto(com.google.api.ResourceProto) FieldOptions(com.google.protobuf.DescriptorProtos.FieldOptions) FileDescriptor(com.google.protobuf.Descriptors.FileDescriptor) BiMap(com.google.common.collect.BiMap) ResourceDescriptor(com.google.api.ResourceDescriptor) ImmutableSet(com.google.common.collect.ImmutableSet) ResourceReference(com.google.api.generator.gapic.model.ResourceReference) Collection(java.util.Collection) Set(java.util.Set) FieldDescriptor(com.google.protobuf.Descriptors.FieldDescriptor) OperationsProto(com.google.longrunning.OperationsProto) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) ResourceNameConstants(com.google.api.generator.gapic.utils.ResourceNameConstants) List(java.util.List) FileDescriptorProto(com.google.protobuf.DescriptorProtos.FileDescriptorProto) EnumDescriptor(com.google.protobuf.Descriptors.EnumDescriptor) DocumentationRule(com.google.api.DocumentationRule) Optional(java.util.Optional) Transport(com.google.api.generator.gapic.model.Transport) GapicContext(com.google.api.generator.gapic.model.GapicContext) GapicLanguageSettings(com.google.api.generator.gapic.model.GapicLanguageSettings) IntStream(java.util.stream.IntStream) VaporReference(com.google.api.generator.engine.ast.VaporReference) TypeNode(com.google.api.generator.engine.ast.TypeNode) GapicLroRetrySettings(com.google.api.generator.gapic.model.GapicLroRetrySettings) Descriptor(com.google.protobuf.Descriptors.Descriptor) HashMap(java.util.HashMap) Function(java.util.function.Function) OperationResponseMapping(com.google.cloud.OperationResponseMapping) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Strings(com.google.common.base.Strings) MethodDescriptor(com.google.protobuf.Descriptors.MethodDescriptor) GapicBatchingSettings(com.google.api.generator.gapic.model.GapicBatchingSettings) Maps(com.google.common.collect.Maps) ResourceName(com.google.api.generator.gapic.model.ResourceName) Service(com.google.api.generator.gapic.model.Service) HashBiMap(com.google.common.collect.HashBiMap) ServiceOptions(com.google.protobuf.DescriptorProtos.ServiceOptions) ExtendedOperationsProto(com.google.cloud.ExtendedOperationsProto) EnumValueDescriptor(com.google.protobuf.Descriptors.EnumValueDescriptor) Preconditions(com.google.common.base.Preconditions) ServiceDescriptor(com.google.protobuf.Descriptors.ServiceDescriptor) OperationResponse(com.google.api.generator.gapic.model.OperationResponse) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Message(com.google.api.generator.gapic.model.Message) MethodOptions(com.google.protobuf.DescriptorProtos.MethodOptions) Collections(java.util.Collections) ClientProto(com.google.api.ClientProto) MessageOptions(com.google.protobuf.DescriptorProtos.MessageOptions) SourceCodeInfoLocation(com.google.api.generator.gapic.model.SourceCodeInfoLocation) ArrayList(java.util.ArrayList) FieldDescriptor(com.google.protobuf.Descriptors.FieldDescriptor) HashSet(java.util.HashSet)

Example 8 with Field

use of com.google.api.generator.gapic.model.Field in project gapic-generator-java by googleapis.

the class Parser method parseMethods.

@VisibleForTesting
static List<Method> parseMethods(ServiceDescriptor serviceDescriptor, String servicePackage, Map<String, Message> messageTypes, Map<String, ResourceName> resourceNames, Optional<GapicServiceConfig> serviceConfigOpt, Set<ResourceName> outputArgResourceNames, Transport transport) {
    List<Method> methods = new ArrayList<>();
    for (MethodDescriptor protoMethod : serviceDescriptor.getMethods()) {
        // Parse the method.
        TypeNode inputType = TypeParser.parseType(protoMethod.getInputType());
        Method.Builder methodBuilder = Method.builder();
        if (protoMethod.getFile().toProto().hasSourceCodeInfo()) {
            SourceCodeInfoLocation protoMethodLocation = SOURCE_CODE_INFO_PARSER.getLocation(protoMethod);
            if (!Objects.isNull(protoMethodLocation) && !Strings.isNullOrEmpty(protoMethodLocation.getLeadingComments())) {
                methodBuilder.setDescription(protoMethodLocation.getLeadingComments());
            }
        }
        boolean isDeprecated = false;
        if (protoMethod.getOptions().hasDeprecated()) {
            isDeprecated = protoMethod.getOptions().getDeprecated();
        }
        Message inputMessage = messageTypes.get(inputType.reference().fullName());
        Preconditions.checkNotNull(inputMessage, String.format("No message found for %s", inputType.reference().fullName()));
        HttpBindings httpBindings = HttpRuleParser.parse(protoMethod, inputMessage, messageTypes);
        boolean isBatching = !serviceConfigOpt.isPresent() ? false : serviceConfigOpt.get().hasBatchingSetting(/* protoPakkage */
        protoMethod.getFile().getPackage(), serviceDescriptor.getName(), protoMethod.getName());
        boolean operationPollingMethod = protoMethod.getOptions().hasExtension(ExtendedOperationsProto.operationPollingMethod) ? protoMethod.getOptions().getExtension(ExtendedOperationsProto.operationPollingMethod) : false;
        RoutingHeaderRule routingHeaderRule = RoutingRuleParser.parse(protoMethod, inputMessage, messageTypes);
        methods.add(methodBuilder.setName(protoMethod.getName()).setInputType(inputType).setOutputType(TypeParser.parseType(protoMethod.getOutputType())).setStream(Method.toStream(protoMethod.isClientStreaming(), protoMethod.isServerStreaming())).setLro(parseLro(servicePackage, protoMethod, messageTypes)).setMethodSignatures(MethodSignatureParser.parseMethodSignatures(protoMethod, servicePackage, inputType, messageTypes, resourceNames, outputArgResourceNames)).setHttpBindings(httpBindings).setRoutingHeaderRule(routingHeaderRule).setIsBatching(isBatching).setPageSizeFieldName(parsePageSizeFieldName(protoMethod, messageTypes, transport)).setIsDeprecated(isDeprecated).setOperationPollingMethod(operationPollingMethod).build());
        // Any input type that has a resource reference will need a resource name helper class.
        for (Field field : inputMessage.fields()) {
            if (field.hasResourceReference()) {
                String resourceTypeString = field.resourceReference().resourceTypeString();
                ResourceName resourceName = null;
                // versus example.com/FooBar.
                if (resourceTypeString.indexOf(SLASH) < 0) {
                    Optional<String> actualResourceTypeNameOpt = resourceNames.keySet().stream().filter(k -> k.substring(k.lastIndexOf(SLASH) + 1).equals(resourceTypeString)).findFirst();
                    if (actualResourceTypeNameOpt.isPresent()) {
                        resourceName = resourceNames.get(actualResourceTypeNameOpt.get());
                    }
                } else {
                    resourceName = resourceNames.get(resourceTypeString);
                }
                if (ResourceNameConstants.WILDCARD_PATTERN.equals(resourceTypeString)) {
                    resourceName = WILDCARD_RESOURCE_NAME;
                } else {
                    Preconditions.checkNotNull(resourceName, String.format("Resource name %s not found; parsing field %s in message %s in method %s", resourceTypeString, field.name(), inputMessage.name(), protoMethod.getName()));
                }
                outputArgResourceNames.add(resourceName);
            }
        }
    }
    return methods;
}
Also used : HttpBindings(com.google.api.generator.gapic.model.HttpBindings) CodeGeneratorRequest(com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest) Arrays(java.util.Arrays) RoutingHeaderRule(com.google.api.generator.gapic.model.RoutingHeaderRule) OperationInfo(com.google.longrunning.OperationInfo) GapicServiceConfig(com.google.api.generator.gapic.model.GapicServiceConfig) DescriptorValidationException(com.google.protobuf.Descriptors.DescriptorValidationException) Field(com.google.api.generator.gapic.model.Field) Method(com.google.api.generator.gapic.model.Method) HttpRule(com.google.api.HttpRule) LongrunningOperation(com.google.api.generator.gapic.model.LongrunningOperation) Map(java.util.Map) ResourceProto(com.google.api.ResourceProto) FieldOptions(com.google.protobuf.DescriptorProtos.FieldOptions) FileDescriptor(com.google.protobuf.Descriptors.FileDescriptor) BiMap(com.google.common.collect.BiMap) ResourceDescriptor(com.google.api.ResourceDescriptor) ImmutableSet(com.google.common.collect.ImmutableSet) ResourceReference(com.google.api.generator.gapic.model.ResourceReference) Collection(java.util.Collection) Set(java.util.Set) FieldDescriptor(com.google.protobuf.Descriptors.FieldDescriptor) OperationsProto(com.google.longrunning.OperationsProto) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) ResourceNameConstants(com.google.api.generator.gapic.utils.ResourceNameConstants) List(java.util.List) FileDescriptorProto(com.google.protobuf.DescriptorProtos.FileDescriptorProto) EnumDescriptor(com.google.protobuf.Descriptors.EnumDescriptor) DocumentationRule(com.google.api.DocumentationRule) Optional(java.util.Optional) Transport(com.google.api.generator.gapic.model.Transport) GapicContext(com.google.api.generator.gapic.model.GapicContext) GapicLanguageSettings(com.google.api.generator.gapic.model.GapicLanguageSettings) IntStream(java.util.stream.IntStream) VaporReference(com.google.api.generator.engine.ast.VaporReference) TypeNode(com.google.api.generator.engine.ast.TypeNode) GapicLroRetrySettings(com.google.api.generator.gapic.model.GapicLroRetrySettings) Descriptor(com.google.protobuf.Descriptors.Descriptor) HashMap(java.util.HashMap) Function(java.util.function.Function) OperationResponseMapping(com.google.cloud.OperationResponseMapping) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Strings(com.google.common.base.Strings) MethodDescriptor(com.google.protobuf.Descriptors.MethodDescriptor) GapicBatchingSettings(com.google.api.generator.gapic.model.GapicBatchingSettings) Maps(com.google.common.collect.Maps) ResourceName(com.google.api.generator.gapic.model.ResourceName) Service(com.google.api.generator.gapic.model.Service) HashBiMap(com.google.common.collect.HashBiMap) ServiceOptions(com.google.protobuf.DescriptorProtos.ServiceOptions) ExtendedOperationsProto(com.google.cloud.ExtendedOperationsProto) EnumValueDescriptor(com.google.protobuf.Descriptors.EnumValueDescriptor) Preconditions(com.google.common.base.Preconditions) ServiceDescriptor(com.google.protobuf.Descriptors.ServiceDescriptor) OperationResponse(com.google.api.generator.gapic.model.OperationResponse) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Message(com.google.api.generator.gapic.model.Message) MethodOptions(com.google.protobuf.DescriptorProtos.MethodOptions) Collections(java.util.Collections) ClientProto(com.google.api.ClientProto) MessageOptions(com.google.protobuf.DescriptorProtos.MessageOptions) SourceCodeInfoLocation(com.google.api.generator.gapic.model.SourceCodeInfoLocation) Message(com.google.api.generator.gapic.model.Message) HttpBindings(com.google.api.generator.gapic.model.HttpBindings) ResourceName(com.google.api.generator.gapic.model.ResourceName) ArrayList(java.util.ArrayList) Method(com.google.api.generator.gapic.model.Method) MethodDescriptor(com.google.protobuf.Descriptors.MethodDescriptor) Field(com.google.api.generator.gapic.model.Field) SourceCodeInfoLocation(com.google.api.generator.gapic.model.SourceCodeInfoLocation) RoutingHeaderRule(com.google.api.generator.gapic.model.RoutingHeaderRule) TypeNode(com.google.api.generator.engine.ast.TypeNode) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 9 with Field

use of com.google.api.generator.gapic.model.Field in project gapic-generator-java by googleapis.

the class ParserTest method parseMessages_fieldsHaveResourceReferences.

@Test
public void parseMessages_fieldsHaveResourceReferences() {
    FileDescriptor lockerServiceFileDescriptor = LockerProto.getDescriptor();
    Map<String, Message> messageTypes = Parser.parseMessages(lockerServiceFileDescriptor);
    // Child type.
    Message message = messageTypes.get("com.google.testgapic.v1beta1.CreateFolderRequest");
    Field field = message.fieldMap().get("parent");
    assertTrue(field.hasResourceReference());
    ResourceReference resourceReference = field.resourceReference();
    assertEquals("cloudresourcemanager.googleapis.com/Folder", resourceReference.resourceTypeString());
    assertTrue(resourceReference.isChildType());
    // Type.
    message = messageTypes.get("com.google.testgapic.v1beta1.GetFolderRequest");
    field = message.fieldMap().get("name");
    assertTrue(field.hasResourceReference());
    resourceReference = field.resourceReference();
    assertEquals("cloudresourcemanager.googleapis.com/Folder", resourceReference.resourceTypeString());
    assertFalse(resourceReference.isChildType());
    // Non-RPC-specific message.
    message = messageTypes.get("com.google.testgapic.v1beta1.Folder");
    field = message.fieldMap().get("name");
    assertTrue(field.hasResourceReference());
    resourceReference = field.resourceReference();
    assertEquals("cloudresourcemanager.googleapis.com/Folder", resourceReference.resourceTypeString());
    assertFalse(resourceReference.isChildType());
    // No explicit resource_reference annotation on the field, and the resource annotation is in the
    // message.
    message = messageTypes.get("com.google.testgapic.v1beta1.Document");
    field = message.fieldMap().get("name");
    assertTrue(field.hasResourceReference());
    resourceReference = field.resourceReference();
    assertEquals("testgapic.googleapis.com/Document", resourceReference.resourceTypeString());
    assertFalse(resourceReference.isChildType());
}
Also used : Field(com.google.api.generator.gapic.model.Field) Message(com.google.api.generator.gapic.model.Message) ResourceReference(com.google.api.generator.gapic.model.ResourceReference) FileDescriptor(com.google.protobuf.Descriptors.FileDescriptor) Test(org.junit.Test)

Example 10 with Field

use of com.google.api.generator.gapic.model.Field in project gapic-generator-java by googleapis.

the class ParserTest method parseFields_mapType.

@Test
public void parseFields_mapType() {
    FileDescriptor testingFileDescriptor = TestingOuterClass.getDescriptor();
    ServiceDescriptor testingService = testingFileDescriptor.getServices().get(0);
    assertEquals(testingService.getName(), "Testing");
    Map<String, Message> messageTypes = Parser.parseMessages(testingFileDescriptor);
    Message message = messageTypes.get("com.google.showcase.v1beta1.Session");
    Field field = message.fieldMap().get("session_ids_to_descriptor");
    assertEquals(TypeNode.withReference(ConcreteReference.builder().setClazz(Map.class).setGenerics(Arrays.asList(TypeNode.INT_OBJECT.reference(), TypeNode.STRING.reference())).build()), field.type());
}
Also used : Field(com.google.api.generator.gapic.model.Field) Message(com.google.api.generator.gapic.model.Message) ServiceDescriptor(com.google.protobuf.Descriptors.ServiceDescriptor) FileDescriptor(com.google.protobuf.Descriptors.FileDescriptor) Test(org.junit.Test)

Aggregations

Field (com.google.api.generator.gapic.model.Field)34 Message (com.google.api.generator.gapic.model.Message)23 TypeNode (com.google.api.generator.engine.ast.TypeNode)21 Expr (com.google.api.generator.engine.ast.Expr)17 Test (org.junit.Test)16 Method (com.google.api.generator.gapic.model.Method)14 ResourceName (com.google.api.generator.gapic.model.ResourceName)14 ArrayList (java.util.ArrayList)13 List (java.util.List)12 AssignmentExpr (com.google.api.generator.engine.ast.AssignmentExpr)9 MethodInvocationExpr (com.google.api.generator.engine.ast.MethodInvocationExpr)9 VariableExpr (com.google.api.generator.engine.ast.VariableExpr)9 ValueExpr (com.google.api.generator.engine.ast.ValueExpr)8 Preconditions (com.google.common.base.Preconditions)8 Map (java.util.Map)8 Collectors (java.util.stream.Collectors)8 ExprStatement (com.google.api.generator.engine.ast.ExprStatement)7 Statement (com.google.api.generator.engine.ast.Statement)7 MethodArgument (com.google.api.generator.gapic.model.MethodArgument)7 Strings (com.google.common.base.Strings)7