Skip to content
This repository has been archived by the owner on Jun 28, 2022. It is now read-only.

Commit

Permalink
Bootstrapping disco-gapic (#1257)
Browse files Browse the repository at this point in the history
  • Loading branch information
garrettjonesgoogle authored May 26, 2017
1 parent 8d418bc commit a5014a4
Show file tree
Hide file tree
Showing 17 changed files with 876 additions and 37 deletions.
10 changes: 10 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,16 @@ task runDiscoBatch(type: JavaExec) {
}
}

// Task to run DiscoGapicGeneratorTool
// =============================
task runDiscoGapicGen(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'com.google.api.codegen.DiscoGapicGeneratorTool'
if (project.hasProperty('clargs')) {
args = clargs.split(',').toList()
}
}

task verifyLicense << {
def licenseText = new File(rootProject.rootDir, 'license-header-javadoc.txt').text
def srcFiles = []
Expand Down
185 changes: 185 additions & 0 deletions src/main/java/com/google/api/codegen/DiscoGapicGeneratorApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/* Copyright 2017 Google Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.api.codegen;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.api.codegen.config.GapicProductConfig;
import com.google.api.codegen.config.PackageMetadataConfig;
import com.google.api.codegen.discogapic.DiscoGapicProvider;
import com.google.api.codegen.discogapic.DiscoGapicProviderFactory;
import com.google.api.codegen.discovery.DiscoveryNode;
import com.google.api.codegen.discovery.Document;
import com.google.api.codegen.gapic.GapicGeneratorConfig;
import com.google.api.codegen.util.ClassInstantiator;
import com.google.api.tools.framework.model.DiagCollector;
import com.google.api.tools.framework.model.SimpleDiagCollector;
import com.google.api.tools.framework.snippet.Doc;
import com.google.api.tools.framework.tools.ToolOptions;
import com.google.api.tools.framework.tools.ToolOptions.Option;
import com.google.api.tools.framework.tools.ToolUtil;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.inject.TypeLiteral;
import com.google.protobuf.Message;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class DiscoGapicGeneratorApi {
public static final Option<String> DISCOVERY_DOC =
ToolOptions.createOption(
String.class,
"discovery_doc",
"The Discovery doc representing the service description.",
"");

public static final Option<String> OUTPUT_FILE =
ToolOptions.createOption(
String.class,
"output_file",
"The name of the output file or folder to put generated code.",
"");

public static final Option<List<String>> GENERATOR_CONFIG_FILES =
ToolOptions.createOption(
new TypeLiteral<List<String>>() {},
"config_files",
"The list of YAML configuration files for the code generator.",
ImmutableList.<String>of());

public static final Option<String> PACKAGE_CONFIG_FILE =
ToolOptions.createOption(
String.class, "package_config", "The package metadata configuration.", "");

public static final Option<List<String>> ENABLED_ARTIFACTS =
ToolOptions.createOption(
new TypeLiteral<List<String>>() {},
"enabled_artifacts",
"The artifacts to be generated by the code generator.",
ImmutableList.<String>of());

private final ToolOptions options;

/** Constructs a code generator api based on given options. */
public DiscoGapicGeneratorApi(ToolOptions options) {
this.options = options;
}

public void run() throws Exception {

String discoveryDocPath = options.get(DISCOVERY_DOC);
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);

Document document = Document.from(new DiscoveryNode(root));

// Read the YAML config and convert it to proto.
List<String> configFileNames = options.get(GENERATOR_CONFIG_FILES);
if (configFileNames.size() == 0) {
System.err.println(String.format("--%s must be provided", GENERATOR_CONFIG_FILES.name()));
return;
}

ConfigProto configProto = loadConfigFromFiles(configFileNames);
if (configProto == null) {
return;
}

PackageMetadataConfig packageConfig = null;
if (!Strings.isNullOrEmpty(options.get(PACKAGE_CONFIG_FILE))) {
String contents =
new String(
Files.readAllBytes(Paths.get(options.get(PACKAGE_CONFIG_FILE))),
StandardCharsets.UTF_8);
packageConfig = PackageMetadataConfig.createFromString(contents);
}
GeneratorProto generator = configProto.getGenerator();
GapicProductConfig productConfig = GapicProductConfig.create(document, configProto);

String factory = generator.getFactory();
String id = generator.getId();

DiscoGapicProviderFactory providerFactory = createProviderFactory(factory);
GapicGeneratorConfig generatorConfig =
GapicGeneratorConfig.newBuilder()
.id(id)
.enabledArtifacts(options.get(ENABLED_ARTIFACTS))
.build();

List<DiscoGapicProvider> providers =
providerFactory.create(document, productConfig, generatorConfig, packageConfig);
String outputFile = options.get(OUTPUT_FILE);
Map<String, Doc> outputFiles = Maps.newHashMap();
for (DiscoGapicProvider provider : providers) {
outputFiles.putAll(provider.generate());
}
ToolUtil.writeFiles(outputFiles, outputFile);
}

private static DiscoGapicProviderFactory createProviderFactory(String factory) {
@SuppressWarnings("unchecked")
DiscoGapicProviderFactory provider =
ClassInstantiator.createClass(
factory,
DiscoGapicProviderFactory.class,
new Class<?>[] {},
new Object[] {},
"generator",
new ClassInstantiator.ErrorReporter() {
@Override
public void error(String message, Object... args) {
System.err.printf(message, args);
}
});
return provider;
}

private List<File> pathsToFiles(List<String> configFileNames) {
List<File> files = new ArrayList<>();

for (String configFileName : configFileNames) {
files.add(new File(configFileName));
}

return files;
}

private ConfigProto loadConfigFromFiles(List<String> configFileNames) {
List<File> configFiles = pathsToFiles(configFileNames);
DiagCollector diagCollector = new SimpleDiagCollector();
ImmutableMap<String, Message> supportedConfigTypes =
ImmutableMap.<String, Message>of(
ConfigProto.getDescriptor().getFullName(), ConfigProto.getDefaultInstance());
ConfigProto configProto =
(ConfigProto) MultiYamlReader.read(diagCollector, configFiles, supportedConfigTypes);
return configProto;
}
}
120 changes: 120 additions & 0 deletions src/main/java/com/google/api/codegen/DiscoGapicGeneratorTool.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/* Copyright 2017 Google Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.api.codegen;

import com.google.api.tools.framework.tools.ToolOptions;
import com.google.common.collect.Lists;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;

public class DiscoGapicGeneratorTool {
public static void main(String[] args) throws Exception {
Options options = new Options();
options.addOption("h", "help", false, "show usage");
options.addOption(
Option.builder()
.longOpt("discovery_doc")
.desc("The Discovery doc representing the service description.")
.hasArg()
.argName("DISCOVERY-DOC")
.required(true)
.build());
// TODO add this option back
// options.addOption(
// Option.builder()
// .longOpt("service_yaml")
// .desc("The service YAML configuration file or files.")
// .hasArg()
// .argName("SERVICE-YAML")
// .required(true)
// .build());
options.addOption(
Option.builder()
.longOpt("gapic_yaml")
.desc("The GAPIC YAML configuration file or files.")
.hasArg()
.argName("GAPIC-YAML")
.required(true)
.build());
options.addOption(
Option.builder()
.longOpt("package_yaml")
.desc("The package metadata YAML configuration file.")
.hasArg()
.argName("PACKAGE-YAML")
.build());
options.addOption(
Option.builder("o")
.longOpt("output")
.desc("The directory in which to output the generated client library.")
.hasArg()
.argName("OUTPUT-DIRECTORY")
.build());
options.addOption(
Option.builder()
.longOpt("enabled_artifacts")
.desc(
"Optional. Artifacts enabled for the generator. "
+ "Currently supports 'surface' and 'test'.")
.hasArg()
.argName("ENABLED_ARTIFACTS")
.required(false)
.build());

CommandLine cl = (new DefaultParser()).parse(options, args);
if (cl.hasOption("help")) {
HelpFormatter formater = new HelpFormatter();
formater.printHelp("CodeGeneratorTool", options);
}

try {
generate(
cl.getOptionValue("discovery_doc"),
// cl.getOptionValues("service_yaml"),
cl.getOptionValues("gapic_yaml"),
cl.getOptionValue("package_yaml"),
cl.getOptionValue("output", ""),
cl.getOptionValues("enabled_artifacts"));
} catch (Exception e) {
e.printStackTrace(System.err);
System.exit(1);
}
}

private static void generate(
String discoveryDoc,
// String[] configs,
String[] generatorConfigs,
String packageConfig,
String outputDirectory,
String[] enabledArtifacts)
throws Exception {
ToolOptions options = ToolOptions.create();
// options.set(ToolOptions.CONFIG_FILES, Lists.newArrayList(configs));
options.set(DiscoGapicGeneratorApi.DISCOVERY_DOC, discoveryDoc);
options.set(CodeGeneratorApi.OUTPUT_FILE, outputDirectory);
options.set(CodeGeneratorApi.GENERATOR_CONFIG_FILES, Lists.newArrayList(generatorConfigs));
options.set(CodeGeneratorApi.PACKAGE_CONFIG_FILE, packageConfig);

if (enabledArtifacts != null) {
options.set(CodeGeneratorApi.ENABLED_ARTIFACTS, Lists.newArrayList(enabledArtifacts));
}
DiscoGapicGeneratorApi codeGen = new DiscoGapicGeneratorApi(options);
codeGen.run();
}
}
Loading

0 comments on commit a5014a4

Please sign in to comment.