use of com.google.api.codegen.common.TargetLanguage in project toolkit by googleapis.
the class DiscoGapicGeneratorApp method getGenerators.
/**
* From config file paths, constructs the DiscoGapicGenerators to run.
*/
@VisibleForTesting
public static List<CodeGenerator<?>> getGenerators(String discoveryDocPath, List<String> configFileNames, String packageConfig2File, String dependencyConfigFile, String languageStr, List<String> enabledArtifacts, ArtifactType artifactType) throws IOException {
if (!new File(discoveryDocPath).exists()) {
throw new IOException("File not found: " + discoveryDocPath);
}
Reader reader = new InputStreamReader(new FileInputStream(new File(discoveryDocPath)));
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(reader);
// Read the YAML config and convert it to proto.
if (configFileNames.size() == 0) {
throw new IOException(String.format("--%s must be provided", GENERATOR_CONFIG_FILES.name()));
}
ConfigProto configProto = loadConfigFromFiles(configFileNames);
if (configProto == null) {
throw new IOException("Failed to load config proto.");
}
PackageMetadataConfig packageConfig = null;
if (!Strings.isNullOrEmpty(packageConfig2File)) {
ApiDefaultsConfig apiDefaultsConfig = ApiDefaultsConfig.load();
DependenciesConfig dependenciesConfig;
if (dependencyConfigFile != null) {
dependenciesConfig = DependenciesConfig.loadFromURL(new File(dependencyConfigFile).toURI().toURL());
} else {
dependenciesConfig = DependenciesConfig.load();
}
PackagingConfig packagingConfig = PackagingConfig.load(packageConfig2File);
packageConfig = PackageMetadataConfig.createFromPackaging(apiDefaultsConfig, dependenciesConfig, packagingConfig);
}
TargetLanguage language;
if (!Strings.isNullOrEmpty(languageStr)) {
language = TargetLanguage.fromString(languageStr.toUpperCase());
} else {
throw new IllegalArgumentException("Language not set by --language option.");
}
String defaultPackageName = configProto.getLanguageSettingsMap().get(languageStr).getPackageName();
DiscoApiModel model = new DiscoApiModel(Document.from(new DiscoveryNode(root)), defaultPackageName);
GapicProductConfig productConfig = GapicProductConfig.create(model, configProto, language);
ArtifactFlags artifactFlags = new ArtifactFlags(enabledArtifacts, artifactType, false);
return DiscoGapicGeneratorFactory.create(language, model, productConfig, packageConfig, artifactFlags);
}
use of com.google.api.codegen.common.TargetLanguage in project toolkit by googleapis.
the class GapicGeneratorApp method process.
@Override
protected void process() throws Exception {
String protoPackage = Strings.emptyToNull(options.get(PROTO_PACKAGE));
// Read the GAPIC config, if it was given, and convert it to proto.
List<String> configFileNames = options.get(GENERATOR_CONFIG_FILES);
ConfigProto configProto = null;
if (configFileNames.size() > 0) {
// Read the YAML config and convert it to proto.
ConfigSource configSource = loadConfigFromFiles(configFileNames, ConfigProto.getDescriptor().getFullName(), ConfigProto.getDefaultInstance());
if (configSource == null) {
return;
}
configProto = (ConfigProto) configSource.getConfig();
if (configProto == null) {
return;
}
}
// Consume gRPC Service Config if it is given with gapic_v2.
String gRPCServiceConfigPath = options.get(GRPC_SERVICE_CONFIG);
ServiceConfig gRPCServiceConfig = null;
if (!Strings.isNullOrEmpty(gRPCServiceConfigPath) && configProto.getConfigSchemaVersion().equals("2.0.0")) {
ServiceConfig.Builder builder = ServiceConfig.newBuilder();
FileReader file = new FileReader(gRPCServiceConfigPath);
JsonFormat.parser().merge(file, builder);
gRPCServiceConfig = builder.build();
}
// Read the sample configs, if they are given, and convert them to protos.
SampleConfigProto sampleConfigProto = null;
List<String> sampleConfigFileNames = options.get(SAMPLE_CONFIG_FILES);
if (sampleConfigFileNames.size() > 0) {
ConfigSource configSource = loadConfigFromFiles(SampleConfigSanitizer.sanitize(sampleConfigFileNames), SampleConfigProto.getDescriptor().getFullName(), SampleConfigProto.getDefaultInstance());
// TODO(hzyi): Verify this works for repeated fields as well
// TODO(hzyi): Allow users to put arbitrary top-level directives not
// used by gapic-generator
sampleConfigProto = (SampleConfigProto) configSource.getConfig();
}
model.establishStage(Merged.KEY);
if (model.getDiagReporter().getDiagCollector().getErrorCount() > 0) {
for (Diag diag : model.getDiagReporter().getDiagCollector().getDiags()) {
System.err.println(diag.toString());
}
return;
}
ApiDefaultsConfig apiDefaultsConfig = ApiDefaultsConfig.load();
DependenciesConfig dependenciesConfig = DependenciesConfig.load();
TargetLanguage language;
if (!Strings.isNullOrEmpty(options.get(LANGUAGE))) {
language = TargetLanguage.fromString(options.get(LANGUAGE).toUpperCase());
} else {
throw new IllegalArgumentException("Language not set by --language option.");
}
String clientPackage = Strings.emptyToNull(options.get(CLIENT_PACKAGE));
String transport = options.get(TRANSPORT).toLowerCase();
TransportProtocol tp;
if (transport.equals("grpc")) {
tp = TransportProtocol.GRPC;
} else if (transport.equals("rest")) {
tp = TransportProtocol.HTTP;
} else {
throw new IllegalArgumentException("Unknown transport protocol: " + transport);
}
GapicProductConfig productConfig = GapicProductConfig.create(model, configProto, sampleConfigProto, protoPackage, clientPackage, language, gRPCServiceConfig, tp);
if (productConfig == null) {
ToolUtil.reportDiags(model.getDiagReporter().getDiagCollector(), true);
return;
}
PackagingConfig packagingConfig;
if (!Strings.isNullOrEmpty(options.get(PACKAGE_CONFIG2_FILE))) {
packagingConfig = PackagingConfig.load(options.get(PACKAGE_CONFIG2_FILE));
} else {
packagingConfig = PackagingConfig.loadFromProductConfig(productConfig.getInterfaceConfigMap());
}
PackageMetadataConfig packageConfig = PackageMetadataConfig.createFromPackaging(apiDefaultsConfig, dependenciesConfig, packagingConfig);
// TODO(hzyi-google): Once we switch to sample configs, require an
// additional check to generate samples:
// `sampleConfigProto != null`
ArtifactFlags artifactFlags = new ArtifactFlags(options.get(ENABLED_ARTIFACTS), artifactType, options.get(DEV_SAMPLES));
List<CodeGenerator<?>> generators = GapicGeneratorFactory.create(language, model, productConfig, packageConfig, artifactFlags);
ImmutableMap.Builder<String, GeneratedResult<?>> generatedResults = ImmutableMap.builder();
for (CodeGenerator<?> generator : generators) {
Map<String, ? extends GeneratedResult<?>> generatorResult = generator.generate();
for (Map.Entry<String, ? extends GeneratedResult<?>> entry : generatorResult.entrySet()) {
generatedResults.put(entry.getKey(), entry.getValue());
}
}
gapicWriter.writeCodeGenOutput(generatedResults.build(), model.getDiagReporter().getDiagCollector());
}
use of com.google.api.codegen.common.TargetLanguage in project toolkit by googleapis.
the class PackageGeneratorApp method generate.
protected Map<String, GeneratedResult<Doc>> generate(Model model) throws IOException {
TargetLanguage language = TargetLanguage.fromString(options.get(LANGUAGE));
PackageMetadataConfig config = null;
ApiDefaultsConfig apiDefaultsConfig = ApiDefaultsConfig.load();
DependenciesConfig dependenciesConfig;
if (dependenciesYamlUrl != null) {
dependenciesConfig = DependenciesConfig.loadFromURL(dependenciesYamlUrl);
} else {
dependenciesConfig = DependenciesConfig.load();
}
PackagingConfig packagingConfig = null;
if (!Strings.isNullOrEmpty(options.get(PACKAGE_CONFIG2_FILE))) {
packagingConfig = PackagingConfig.load(options.get(PACKAGE_CONFIG2_FILE));
} else {
// TODO(andrealin): Get PackageMetadataConfig from proto annotations.
}
config = PackageMetadataConfig.createFromPackaging(apiDefaultsConfig, dependenciesConfig, packagingConfig);
Preconditions.checkNotNull(config);
PackagingArtifactType artifactType = options.get(PackageGeneratorApp.ARTIFACT_TYPE);
if (artifactType == null) {
artifactType = config.artifactType();
}
CodeGenerator<Doc> generator = PackageGeneratorFactory.create(language, artifactType, options, model, config);
return generator.generate();
}
use of com.google.api.codegen.common.TargetLanguage 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.common.TargetLanguage in project toolkit by googleapis.
the class Configs method buildMapWithDefault.
/**
* Transforms entries of the input map into TargetLanguage, taking into account an optional
* default setting.
*/
static <V> Map<TargetLanguage, V> buildMapWithDefault(Map<String, V> inputMap) {
Map<TargetLanguage, V> outputMap = new HashMap<>();
if (inputMap == null) {
return outputMap;
}
Set<TargetLanguage> configuredLanguages = new HashSet<>();
V defaultValue = null;
for (Map.Entry<String, V> entry : inputMap.entrySet()) {
if (entry.getKey().equals(CONFIG_KEY_DEFAULT)) {
defaultValue = entry.getValue();
} else {
TargetLanguage targetLanguage = TargetLanguage.fromString(entry.getKey());
configuredLanguages.add(targetLanguage);
outputMap.put(targetLanguage, entry.getValue());
}
for (TargetLanguage language : TargetLanguage.values()) {
if (!configuredLanguages.contains(language)) {
outputMap.put(language, defaultValue);
}
}
}
return outputMap;
}
Aggregations