added option to read arguments from a JSON or YAML file.

This commit is contained in:
Hugo Mercado
2018-01-09 15:49:47 -05:00
parent 9dbc34de7a
commit 1506adc20a
6 changed files with 301 additions and 32 deletions

View File

@@ -1,5 +1,8 @@
package io.swagger.codegen;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import com.google.common.io.Resources;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.BooleanSchema;
@@ -11,14 +14,16 @@ import org.apache.commons.io.Charsets;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
class CLIHelper {
public class CLIHelper {
static String loadResourceOAS3File() {
URL url = Resources.getResource("oas3.yaml");
@@ -81,7 +86,7 @@ class CLIHelper {
return null;
}
static Map<String, Object> createOptionValueMap(Schema schema, Map<String, Object> inputArgs) {
public static Map<String, Object> createOptionValueMap(Schema schema, Map<String, Object> inputArgs) {
if(inputArgs == null || inputArgs.isEmpty()) {
return null;
}
@@ -138,6 +143,43 @@ class CLIHelper {
return optionValueMap;
}
public static Map<String, Object> createOptionValueMap(JsonNode node) {
final Map<String, Object> optionValueMap = new HashMap<>();
Iterator<String> fieldNames = node.fieldNames();
while (fieldNames.hasNext()) {
String argument = fieldNames.next();
JsonNode valueNode = node.findValue(argument);
if (valueNode.isBoolean()) {
optionValueMap.put(argument, valueNode.booleanValue());
}
else if (valueNode.isShort() || valueNode.isInt()) {
optionValueMap.put(argument, valueNode.intValue());
}
else if (valueNode.isLong()) {
optionValueMap.put(argument, valueNode.longValue());
}
else if (valueNode.isFloat()) {
optionValueMap.put(argument, valueNode.floatValue());
}
else if (valueNode.isDouble()) {
optionValueMap.put(argument, valueNode.doubleValue());
}
else if (valueNode.isArray()) {
String inputElements = valueNode.toString()
.replace("[", StringUtils.EMPTY)
.replace("]", StringUtils.EMPTY)
.replace("\"", StringUtils.EMPTY)
.replace(" ", StringUtils.EMPTY);
final List<String> values = new ArrayList<>(Arrays.asList(inputElements.split(",")));
optionValueMap.put(argument, values);
} else {
optionValueMap.put(argument, valueNode.toString()
.replace("\"", StringUtils.EMPTY));
}
}
return optionValueMap;
}
private static String fixOptionName(String option) {
option = option.substring(countDashes(option));
return option.replace("-", "_");
@@ -151,4 +193,42 @@ class CLIHelper {
}
return 0;
}
public static boolean isValidJson(String content) {
if (StringUtils.isBlank(content)) {
return false;
}
try {
new ObjectMapper().readTree(content);
return true;
} catch (IOException ex) {
return false;
}
}
public static boolean isValidYaml(String content) {
if (StringUtils.isBlank(content)) {
return false;
}
try {
new YAMLMapper().readTree(content);
return true;
} catch (IOException ex) {
return false;
}
}
public static boolean isValidURL(String urlStr) {
if (StringUtils.isBlank(urlStr)) {
return false;
}
try {
URI uri = new URI(urlStr);
return uri.getScheme().toLowerCase().startsWith("http");
}
catch (Exception e) {
return false;
}
}
}

View File

@@ -1,14 +1,29 @@
package io.swagger.codegen.cmd;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.codegen.CLIHelper;
import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.config.CodegenConfigurator;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.core.util.Yaml;
import io.swagger.v3.parser.util.RemoteUrl;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static io.swagger.codegen.CLIHelper.isValidJson;
import static io.swagger.codegen.CLIHelper.isValidURL;
import static io.swagger.codegen.CLIHelper.isValidYaml;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyAdditionalPropertiesKvpList;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyImportMappingsKvpList;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyInstantiationTypesKvpList;
@@ -26,36 +41,37 @@ public class Generate implements Runnable {
public static final Logger LOG = LoggerFactory.getLogger(Generate.class);
private Boolean verbose;
private String lang;
private String output = "";
private String spec;
private String templateDir;
private String auth;
private List<String> systemProperties = new ArrayList<>();
private String configFile;
private Boolean skipOverwrite;
private String apiPackage;
private String modelPackage;
private String modelNamePrefix;
private String modelNameSuffix;
private List<String> instantiationTypes = new ArrayList<>();
private List<String> typeMappings = new ArrayList<>();
private List<String> additionalProperties = new ArrayList<>();
private List<String> languageSpecificPrimitives = new ArrayList<>();
private List<String> importMappings = new ArrayList<>();
private String invokerPackage;
private String groupId;
private String artifactId;
private String artifactVersion;
private String library;
private String gitUserId;
private String gitRepoId;
private String releaseNote;
private String httpUserAgent;
private List<String> reservedWordsMappings = new ArrayList<>();
private String ignoreFileOverride;
private Boolean removeOperationIdPrefix;
protected Boolean verbose;
protected String lang;
protected String output = "";
protected String spec;
protected String templateDir;
protected String auth;
protected List<String> systemProperties = new ArrayList<>();
protected String configFile;
protected Boolean skipOverwrite;
protected String apiPackage;
protected String modelPackage;
protected String modelNamePrefix;
protected String modelNameSuffix;
protected List<String> instantiationTypes = new ArrayList<>();
protected List<String> typeMappings = new ArrayList<>();
protected List<String> additionalProperties = new ArrayList<>();
protected List<String> languageSpecificPrimitives = new ArrayList<>();
protected List<String> importMappings = new ArrayList<>();
protected String invokerPackage;
protected String groupId;
protected String artifactId;
protected String artifactVersion;
protected String library;
protected String gitUserId;
protected String gitRepoId;
protected String releaseNote;
protected String httpUserAgent;
protected List<String> reservedWordsMappings = new ArrayList<>();
protected String ignoreFileOverride;
protected Boolean removeOperationIdPrefix;
private String url;
public void setVerbose(Boolean verbose) {
this.verbose = verbose;
@@ -177,9 +193,15 @@ public class Generate implements Runnable {
this.removeOperationIdPrefix = removeOperationIdPrefix;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public void run() {
loadArguments();
// attempt to read from config file
CodegenConfigurator configurator = CodegenConfigurator.fromFile(configFile);
@@ -289,4 +311,62 @@ public class Generate implements Runnable {
new DefaultGenerator().opts(clientOptInput).generate();
}
private void loadArguments() {
if (StringUtils.isBlank(this.url)) {
return;
}
final String content;
File file = new File(this.url);
if (file.exists() && file.isFile()) {
try {
content = FileUtils.readFileToString(file);
} catch (IOException e) {
LOG.error("Unable to read file: " + this.url, e);
return;
}
} else if (isValidURL(this.url)) {
try {
content = RemoteUrl.urlToString(this.url, null);
} catch (Exception e) {
LOG.error("Unable to read url: " + this.url, e);
return;
}
} else {
return;
}
if (StringUtils.isBlank(content)) {
return;
}
JsonNode node = null;
if (isValidJson(content)) {
try {
node = Json.mapper().readTree(content.getBytes());
} catch (IOException e) {
LOG.error("Unable to deserialize json from: " + this.url, e);
node = null;
}
} else if (isValidYaml(content)) {
try {
node = Yaml.mapper().readTree(content.getBytes());
} catch (IOException e) {
LOG.error("Unable to deserialize yaml from: " + this.url, e);
node = null;
}
}
if (node == null) {
return;
}
final Map<String, Object> optionValueMap = CLIHelper.createOptionValueMap(node);
try {
BeanUtils.populate(this, optionValueMap);
} catch (Exception e) {
LOG.error("Error setting values to object.", e);
}
}
}

View File

@@ -173,6 +173,12 @@ components:
title: "remove prefix of the operationId"
description: "Remove prefix of operationId, e.g. config_getId => getId"
x-option: "--remove-operation-id-prefix"
url:
type: "string"
title: "URL for arguments"
description: "load arguments from a local file or remote URL. Arguments found will replace any one placed on command."
x-option: "--url"
x-short-version: "-u"
ConfigHelp:
x-command: "config-help"
x-command-description: "Config help for chosen lang"

View File

@@ -1,17 +1,27 @@
package io.swagger.codegen.cmd;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.codegen.CLIHelper;
import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.SwaggerCodegen;
import io.swagger.codegen.config.CodegenConfigurator;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.core.util.Yaml;
import mockit.Expectations;
import mockit.FullVerifications;
import mockit.Injectable;
import mockit.Mocked;
import mockit.Verifications;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@SuppressWarnings("unused")
public class GenerateTest {
@@ -552,6 +562,85 @@ public class GenerateTest {
};
}
@Test
public void testExternalArguments() throws Exception {
String content = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("args.json"));
JsonNode node = Json.mapper().readTree(content.getBytes());
Map<String, Object> valueMap = CLIHelper.createOptionValueMap(node);
Assert.assertNotNull(valueMap);
Assert.assertTrue(valueMap.containsKey("lang"));
Assert.assertTrue(valueMap.containsKey("library"));
Assert.assertTrue(valueMap.containsKey("additionalProperties"));
Assert.assertTrue(valueMap.containsKey("spec"));
Assert.assertTrue(valueMap.containsKey("output"));
Assert.assertEquals(valueMap.get("lang"), "java");
Assert.assertEquals(valueMap.get("library"), "jersey2");
Assert.assertNotNull(valueMap.get("additionalProperties"));
Assert.assertTrue(valueMap.get("additionalProperties") instanceof ArrayList);
List<String> properties = (List<String>) valueMap.get("additionalProperties");
Assert.assertEquals(properties.size(), 2);
Assert.assertEquals(properties.get(0), "serializableModel=true");
Assert.assertEquals(properties.get(1), "withXml=true");
content = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("args.yaml"));
node = Yaml.mapper().readTree(content.getBytes());
valueMap = CLIHelper.createOptionValueMap(node);
Assert.assertNotNull(valueMap);
Assert.assertTrue(valueMap.containsKey("lang"));
Assert.assertTrue(valueMap.containsKey("library"));
Assert.assertTrue(valueMap.containsKey("additionalProperties"));
Assert.assertTrue(valueMap.containsKey("spec"));
Assert.assertTrue(valueMap.containsKey("output"));
Assert.assertEquals(valueMap.get("lang"), "java");
Assert.assertEquals(valueMap.get("library"), "jersey2");
Assert.assertNotNull(valueMap.get("additionalProperties"));
Assert.assertTrue(valueMap.get("additionalProperties") instanceof ArrayList);
properties = (List<String>) valueMap.get("additionalProperties");
Assert.assertEquals(properties.size(), 2);
Assert.assertEquals(properties.get(0), "serializableModel=true");
Assert.assertEquals(properties.get(1), "withXml=true");
}
@Test
public void testExternalArgumentsFromFile() throws Exception {
String location = "src/test/resources/args.json";
Generate generate = new Generate();
generate.setUrl(location);
generate.run();
Assert.assertEquals(generate.lang, "java");
Assert.assertEquals(generate.library, "jersey2");
Assert.assertEquals(generate.additionalProperties.size(), 2);
Assert.assertEquals(generate.additionalProperties.get(0), "serializableModel=true");
Assert.assertEquals(generate.additionalProperties.get(1), "withXml=true");
location = "src/test/resources/args.yaml";
generate = new Generate();
generate.setUrl(location);
generate.run();
Assert.assertEquals(generate.lang, "java");
Assert.assertEquals(generate.library, "jersey2");
Assert.assertEquals(generate.additionalProperties.size(), 2);
Assert.assertEquals(generate.additionalProperties.get(0), "serializableModel=true");
Assert.assertEquals(generate.additionalProperties.get(1), "withXml=true");
}
private void setupAndRunGenericTest(String... additionalParameters) {
setupAndRunTest("-i", "swagger.yaml", "-l", "java", "-o", "src/main/java", false, null,
additionalParameters);

View File

@@ -0,0 +1,7 @@
{
"lang":"java",
"library":"jersey2",
"additionalProperties":["serializableModel=true,withXml=true"],
"spec":"/some/place/locally",
"output":"/some/place/locally"
}

View File

@@ -0,0 +1,7 @@
lang: java
library: jersey2
additionalProperties:
- "serializableModel=true"
- "withXml=true"
spec: "/some/place/locally"
output: "/some/place/locally"