use of com.google.api.codegen.util.ProtoParser in project toolkit by googleapis.
the class GapicProductConfig method create.
/**
* Creates an instance of GapicProductConfig based on ConfigProto, linking up API interface
* configurations with specified interfaces in interfaceConfigMap. On errors, null will be
* returned, and diagnostics are reported to the model.
*
* @param model The protobuf model for which we are creating a config.
* @param configProto The parsed set of library config files from input
* @param sampleConfigProto The parsed set of sample config files from the input
* @param protoPackage The source proto package, as opposed to imported protos, that we will
* generate clients for.
* @param clientPackage The desired package name for the generated client.
* @param language The language that this config will be used to generate a client in.
* @param grpcServiceConfig Method retries configuration.
* @param transportProtocol Transport protocol to support.
*/
@Nullable
public static GapicProductConfig create(Model model, @Nullable ConfigProto configProto, @Nullable SampleConfigProto sampleConfigProto, @Nullable String protoPackage, @Nullable String clientPackage, TargetLanguage language, @Nullable ServiceConfig grpcServiceConfig, TransportProtocol transportProtocol) {
final String defaultPackage;
SymbolTable symbolTable = model.getSymbolTable();
if (protoPackage != null) {
// Default to using --package option for value of default package and first API protoFile.
defaultPackage = protoPackage;
} else if (configProto != null && configProto.getInterfacesCount() > 0) {
// Otherwise use configProto to get the proto file containing the first interface listed in
// the config proto, and use it as the assigned file for generated resource names, and to get
// the default message namespace.
ProtoFile file = symbolTable.lookupInterface(configProto.getInterfaces(0).getName()).getFile();
defaultPackage = file.getProto().getPackage();
} else {
throw new NullPointerException("configProto and protoPackage cannot both be null. " + "If using artman, please add the proto_package field to artman config, " + "or switch to bazel.");
}
// Consider all proto files in the defaultPackage as well as its sub-packages
// as source files.
List<ProtoFile> sourceProtos = model.getFiles().stream().filter(f -> f.getProto().getPackage().startsWith(defaultPackage)).collect(Collectors.toList());
if (protoPackage != null && configProto == null) {
if (sourceProtos.isEmpty()) {
model.getDiagReporter().getDiagCollector().addDiag(Diag.error(SimpleLocation.TOPLEVEL, "There are no source proto files with package %s", defaultPackage));
}
sourceProtos.forEach(model::addRoot);
}
// Toggle on/off proto annotations parsing.
ProtoParser protoParser;
ConfigVersionValidator versionValidator = new ConfigVersionValidator();
if (versionValidator.isV2Config(configProto)) {
versionValidator.validateV2Config(configProto);
protoParser = new ProtoParser(true);
if (configProto == null) {
configProto = ConfigProto.getDefaultInstance();
}
} else {
protoParser = new ProtoParser(false);
}
DiagCollector diagCollector = model.getDiagReporter().getDiagCollector();
ProtoFile packageProtoFile = sourceProtos.isEmpty() ? null : sourceProtos.get(0);
ImmutableMap<String, ResourceNameConfig> resourceNameConfigs;
ResourceNameMessageConfigs messageConfigs;
if (protoParser.isProtoAnnotationsEnabled()) {
Map<String, ResourceDescriptorConfig> descriptorConfigMap = protoParser.getResourceDescriptorConfigMap(model.getFiles(), diagCollector);
List<ResourceReference> fieldsWithResourceRefs = sourceProtos.stream().flatMap(protoFile -> protoFile.getMessages().stream()).flatMap(messageType -> messageType.getFields().stream()).filter(protoParser::hasResourceReference).map(protoParser::getResourceReference).collect(Collectors.toList());
Set<String> configsWithChildTypeReferences = fieldsWithResourceRefs.stream().map(ResourceReference::getChildType).filter(t -> !Strings.isNullOrEmpty(t)).collect(Collectors.toSet());
Set<String> configsWithTypeReferences = fieldsWithResourceRefs.stream().map(ResourceReference::getType).filter(t -> !Strings.isNullOrEmpty(t)).collect(Collectors.toSet());
Map<String, DeprecatedCollectionConfigProto> deprecatedPatternResourceMap = configProto.getInterfacesList().stream().flatMap(i -> i.getDeprecatedCollectionsList().stream()).distinct().collect(ImmutableMap.toImmutableMap(DeprecatedCollectionConfigProto::getNamePattern, c -> c));
// Create a pattern-to-resource map to make looking up parent resources easier.
Map<String, List<ResourceDescriptorConfig>> patternResourceDescriptorMap = ResourceDescriptorConfig.getPatternResourceMap(descriptorConfigMap.values());
// Create a child-to-parent map to make resolving child_type easier.
Map<String, List<ResourceDescriptorConfig>> childParentResourceMap = ResourceDescriptorConfig.getChildParentResourceMap(descriptorConfigMap, patternResourceDescriptorMap);
resourceNameConfigs = createResourceNameConfigsFromAnnotationsAndGapicConfig(model, diagCollector, configProto, packageProtoFile, language, descriptorConfigMap, configsWithTypeReferences, configsWithChildTypeReferences, deprecatedPatternResourceMap, patternResourceDescriptorMap, childParentResourceMap, defaultPackage);
messageConfigs = ResourceNameMessageConfigs.createFromAnnotations(diagCollector, model.getFiles(), resourceNameConfigs, protoParser, descriptorConfigMap, childParentResourceMap);
} else {
resourceNameConfigs = createResourceNameConfigsFromGapicConfigOnly(model, diagCollector, configProto, packageProtoFile, language);
messageConfigs = ResourceNameMessageConfigs.createFromGapicConfigOnly(sourceProtos, configProto, defaultPackage);
}
if (resourceNameConfigs == null) {
return null;
}
String clientPackageName;
LanguageSettingsProto settings = configProto.getLanguageSettingsMap().get(language.toString().toLowerCase());
if (settings == null) {
settings = LanguageSettingsProto.getDefaultInstance();
if (!Strings.isNullOrEmpty(clientPackage)) {
clientPackageName = clientPackage;
} else {
String basePackageName = Optional.ofNullable(protoPackage).orElse(getPackageName(model));
clientPackageName = LanguageSettingsMerger.getFormattedPackageName(language, basePackageName);
}
} else {
clientPackageName = settings.getPackageName();
}
ImmutableMap<String, Interface> protoInterfaces = getInterfacesFromProtoFile(diagCollector, sourceProtos, symbolTable);
ImmutableList<GapicInterfaceInput> interfaceInputs;
if (protoParser.isProtoAnnotationsEnabled()) {
interfaceInputs = createInterfaceInputsWithAnnotationsAndGapicConfig(diagCollector, configProto.getInterfacesList(), protoInterfaces, language);
} else {
interfaceInputs = createInterfaceInputsWithGapicConfigOnly(diagCollector, configProto.getInterfacesList(), protoInterfaces, symbolTable, language);
}
if (interfaceInputs == null) {
return null;
}
GrpcGapicRetryMapping grpcGapicRetryMapping = null;
if (grpcServiceConfig != null) {
grpcGapicRetryMapping = GrpcGapicRetryMapping.create(grpcServiceConfig, protoInterfaces);
}
ImmutableMap<String, InterfaceConfig> interfaceConfigMap = createInterfaceConfigMap(diagCollector, interfaceInputs, defaultPackage, settings, messageConfigs, resourceNameConfigs, language, transportProtocol, protoParser, grpcGapicRetryMapping);
ImmutableList<String> copyrightLines;
ImmutableList<String> licenseLines;
String configSchemaVersion = null;
LicenseHeaderUtil licenseHeaderUtil = new LicenseHeaderUtil();
try {
copyrightLines = licenseHeaderUtil.loadCopyrightLines();
licenseLines = licenseHeaderUtil.loadLicenseLines();
} catch (Exception e) {
model.getDiagReporter().getDiagCollector().addDiag(Diag.error(SimpleLocation.TOPLEVEL, "Exception: %s", e.getMessage()));
e.printStackTrace(System.err);
throw new RuntimeException(e);
}
if (!configProto.equals(ConfigProto.getDefaultInstance())) {
configSchemaVersion = configProto.getConfigSchemaVersion();
if (Strings.isNullOrEmpty(configSchemaVersion)) {
model.getDiagReporter().getDiagCollector().addDiag(Diag.error(SimpleLocation.TOPLEVEL, "config_schema_version field is required in GAPIC yaml."));
}
}
Boolean enableStringFormatFunctionsOverride = null;
if (configProto.hasEnableStringFormatFunctionsOverride()) {
enableStringFormatFunctionsOverride = configProto.getEnableStringFormatFunctionsOverride().getValue();
}
if (interfaceConfigMap == null || copyrightLines == null || licenseLines == null) {
return null;
}
return new AutoValue_GapicProductConfig(interfaceConfigMap, clientPackageName, settings.getDomainLayerLocation(), settings.getReleaseLevel(), messageConfigs, copyrightLines, licenseLines, resourceNameConfigs, protoParser, transportProtocol, createResponseFieldConfigMap(messageConfigs, resourceNameConfigs), configSchemaVersion, enableStringFormatFunctionsOverride, SampleConfig.createSampleConfigTable(sampleConfigProto, interfaceConfigMap), new Date());
}
use of com.google.api.codegen.util.ProtoParser in project toolkit by googleapis.
the class ResourceNameMessageConfigsTest method testCreateFlattenings.
@Test
public void testCreateFlattenings() {
ProtoMethodModel methodModel = new ProtoMethodModel(createShelvesMethod);
Field bookField = Mockito.mock(Field.class);
Mockito.when(bookField.getType()).thenReturn(TypeRef.of(bookType));
Mockito.when(bookField.getParent()).thenReturn(createShelvesRequest);
Mockito.when(bookField.getSimpleName()).thenReturn("book");
Mockito.when(bookType.getFields()).thenReturn(ImmutableList.of());
Field nameField = Mockito.mock(Field.class);
Mockito.when(nameField.getParent()).thenReturn(createShelvesRequest);
Mockito.when(createShelvesRequest.getFullName()).thenReturn("library.CreateShelvesRequest");
Mockito.when(nameField.getType()).thenReturn(TypeRef.fromPrimitiveName("string"));
Mockito.when(nameField.getSimpleName()).thenReturn("name");
Mockito.doReturn(ResourceReference.newBuilder().setType("library.googleapis.com/Shelf").build()).when(protoParser).getResourceReference(nameField);
Mockito.doReturn(true).when(protoParser).hasResourceReference(nameField);
Mockito.when(createShelvesRequest.lookupField("book")).thenReturn(bookField);
Mockito.when(createShelvesRequest.lookupField("name")).thenReturn(nameField);
Mockito.when(createShelvesRequest.getFields()).thenReturn(ImmutableList.of(bookField, nameField));
Mockito.doReturn(ResourceReference.newBuilder().setType("library.googleapis.com/Shelf").build()).when(protoParser).getResourceReference(shelfName);
Mockito.doReturn(true).when(protoParser).hasResourceReference(shelfName);
Mockito.doReturn(ResourceReference.newBuilder().setType("library.googleapis.com/Book").build()).when(protoParser).getResourceReference(bookField);
Mockito.doReturn(true).when(protoParser).hasResourceReference(bookField);
Mockito.doReturn(ResourceReference.newBuilder().setType("library.googleapis.com/Shelf").build()).when(protoParser).getResourceReference(nameField);
Mockito.doReturn(true).when(protoParser).hasResourceReference(nameField);
// ProtoFile contributes flattenings {["name", "book"], ["name"]}.
Mockito.doReturn(Arrays.asList(Arrays.asList("name", "book"), Arrays.asList("name"))).when(protoParser).getMethodSignatures(createShelvesMethod);
Mockito.when(protoFile.getMessages()).thenReturn(ImmutableList.of(bookMessage, shelfMessage, createShelvesRequest));
// Gapic config contributes flattenings {["book"]}.
MethodConfigProto methodConfigProto = MethodConfigProto.newBuilder().setName(CREATE_SHELF_METHOD_NAME).setFlattening(FlatteningConfigProto.newBuilder().addGroups(FlatteningGroupProto.newBuilder().addAllParameters(Arrays.asList("book")))).setResourceNameTreatment(ResourceNameTreatment.STATIC_TYPES).build();
DiagCollector diagCollector = new BoundedDiagCollector();
assertThat(diagCollector.getErrorCount()).isEqualTo(0);
ImmutableMap<String, ResourceNameConfig> resourceNameConfigs = GapicProductConfig.createResourceNameConfigsFromAnnotationsAndGapicConfig(null, diagCollector, ConfigProto.getDefaultInstance(), protoFile, TargetLanguage.CSHARP, resourceDescriptorConfigMap, resourceDescriptorConfigMap.keySet(), Collections.emptySet(), Collections.emptyMap(), patternResourceDescriptorMap, Collections.emptyMap(), "library");
assertThat(diagCollector.getErrorCount()).isEqualTo(0);
ResourceNameMessageConfigs messageConfigs = ResourceNameMessageConfigs.createFromAnnotations(diagCollector, sourceProtoFiles, resourceNameConfigs, protoParser, resourceDescriptorConfigMap, Collections.emptyMap());
List<FlatteningConfig> flatteningConfigs = new ArrayList<>(FlatteningConfig.createFlatteningConfigs(diagCollector, messageConfigs, resourceNameConfigs, methodConfigProto, methodModel, protoParser));
assertThat(diagCollector.getErrorCount()).isEqualTo(0);
List<Diag> warningDiags = diagCollector.getDiags().stream().filter(d -> d.getKind().equals(Kind.WARNING)).collect(Collectors.toList());
assertThat(flatteningConfigs).isNotNull();
assertThat(flatteningConfigs.size()).isEqualTo(6);
// Check the flattening from the Gapic config.
List<FlatteningConfig> flatteningConfigFromGapicConfigs = flatteningConfigs.stream().filter(f -> f.getFlattenedFieldConfigs().size() == 1 && f.getFlattenedFieldConfigs().containsKey("book")).collect(ImmutableList.toImmutableList());
assertThat(flatteningConfigFromGapicConfigs.size()).isEqualTo(2);
for (FlatteningConfig configFromGapicConfig : flatteningConfigFromGapicConfigs) {
Map<String, FieldConfig> paramsFromGapicConfigFlattening = configFromGapicConfig.getFlattenedFieldConfigs();
assertThat(paramsFromGapicConfigFlattening.get("book").getField().getSimpleName()).isEqualTo("book");
assertThat(((ProtoField) paramsFromGapicConfigFlattening.get("book").getField()).getType().getProtoType().getMessageType()).isEqualTo(bookType);
}
flatteningConfigs.removeAll(flatteningConfigFromGapicConfigs);
// Check the flattenings from the protofile annotations.
flatteningConfigs.sort(Comparator.comparingInt(c -> Iterables.size(c.getFlattenedFields())));
FlatteningConfig shelfFlattening = flatteningConfigs.get(0);
assertThat(Iterables.size(shelfFlattening.getFlattenedFields())).isEqualTo(1);
FieldConfig nameConfig = shelfFlattening.getFlattenedFieldConfigs().get("name");
assertThat(nameConfig.getResourceNameTreatment()).isEqualTo(ResourceNameTreatment.STATIC_TYPES);
assertThat(((SingleResourceNameConfig) nameConfig.getResourceNameConfig()).getNamePattern()).isEqualTo(PROTO_SHELF_PATH);
FlatteningConfig shelfAndBookFlattening = flatteningConfigs.get(2);
assertThat(Iterables.size(shelfAndBookFlattening.getFlattenedFields())).isEqualTo(2);
FieldConfig nameConfig2 = shelfAndBookFlattening.getFlattenedFieldConfigs().get("name");
assertThat(nameConfig2.getResourceNameTreatment()).isEqualTo(ResourceNameTreatment.STATIC_TYPES);
// Use PROTO_SHELF_PATH over GAPIC_SHELF_PATH.
assertThat(((SingleResourceNameConfig) nameConfig2.getResourceNameConfig()).getNamePattern()).isEqualTo(PROTO_SHELF_PATH);
FieldConfig bookConfig = shelfAndBookFlattening.getFlattenedFieldConfigs().get("book");
assertThat(bookConfig.getResourceNameTreatment()).isEqualTo(ResourceNameTreatment.STATIC_TYPES);
// Use the resource name path from proto file.
assertThat(((SingleResourceNameConfig) bookConfig.getResourceNameConfig()).getNamePattern()).isEqualTo(PROTO_BOOK_PATH);
assertThat(((ProtoTypeRef) bookConfig.getField().getType()).getProtoType().getMessageType()).isEqualTo(bookType);
// Restore protoFile.getMessages()
Mockito.when(protoFile.getMessages()).thenReturn(ImmutableList.of(bookMessage, shelfMessage));
}
use of com.google.api.codegen.util.ProtoParser in project toolkit by googleapis.
the class GapicProductConfig method create.
public static GapicProductConfig create(DiscoApiModel model, ConfigProto configProto, TargetLanguage language) {
String defaultPackage = configProto.getLanguageSettingsMap().get(language.toString().toLowerCase()).getPackageName();
ResourceNameMessageConfigs messageConfigs = ResourceNameMessageConfigs.createMessageResourceTypesConfig(model, configProto, defaultPackage);
ImmutableMap<String, ResourceNameConfig> resourceNameConfigs = createResourceNameConfigs(model.getDiagCollector(), configProto, language);
TransportProtocol transportProtocol = TransportProtocol.HTTP;
LanguageSettingsProto settings = configProto.getLanguageSettingsMap().get(language.toString().toLowerCase());
if (settings == null) {
settings = LanguageSettingsProto.getDefaultInstance();
}
ImmutableMap<String, InterfaceConfig> interfaceConfigMap = createDiscoGapicInterfaceConfigMap(model, configProto, settings, messageConfigs, resourceNameConfigs, language);
LicenseHeaderUtil licenseHeaderUtil = new LicenseHeaderUtil();
ImmutableList<String> copyrightLines;
ImmutableList<String> licenseLines;
try {
copyrightLines = licenseHeaderUtil.loadCopyrightLines();
licenseLines = licenseHeaderUtil.loadLicenseLines();
} catch (Exception e) {
model.getDiagCollector().addDiag(Diag.error(SimpleLocation.TOPLEVEL, "Exception: %s", e.getMessage()));
e.printStackTrace(System.err);
throw new RuntimeException(e);
}
String configSchemaVersion = configProto.getConfigSchemaVersion();
if (Strings.isNullOrEmpty(configSchemaVersion)) {
model.getDiagCollector().addDiag(Diag.error(SimpleLocation.TOPLEVEL, "config_schema_version field is required in GAPIC yaml."));
}
Boolean enableStringFormatFunctionsOverride = null;
if (configProto.getEnableStringFormatFunctionsOverride().isInitialized()) {
enableStringFormatFunctionsOverride = configProto.getEnableStringFormatFunctionsOverride().getValue();
}
return new AutoValue_GapicProductConfig(interfaceConfigMap, settings.getPackageName(), settings.getDomainLayerLocation(), settings.getReleaseLevel(), messageConfigs, copyrightLines, licenseLines, resourceNameConfigs, new ProtoParser(false), transportProtocol, createResponseFieldConfigMap(messageConfigs, resourceNameConfigs), configSchemaVersion, enableStringFormatFunctionsOverride, ImmutableTable.of(), new Date());
}
Aggregations