This commit is contained in:
Tony Tam
2015-08-23 11:09:47 -07:00
80 changed files with 4628 additions and 854 deletions

View File

@@ -60,6 +60,27 @@ public abstract class AbstractGenerator {
throw new RuntimeException("can't load template " + name);
}
/**
* Get the template file path with template dir prepended, and use the
* library template if exists.
*/
public String getFullTemplateFile(CodegenConfig config, String templateFile) {
String library = config.getLibrary();
if (library != null && !"".equals(library)) {
String libTemplateFile = config.templateDir() + File.separator +
"libraries" + File.separator + library + File.separator +
templateFile;
if (templateExists(libTemplateFile)) {
return libTemplateFile;
}
}
return config.templateDir() + File.separator + templateFile;
}
public boolean templateExists(String name) {
return this.getClass().getClassLoader().getResource(getCPResourcePath(name)) != null;
}
public String getCPResourcePath(String name) {
if (!"/".equals(File.separator)) {
return name.replaceAll(Pattern.quote(File.separator), "/");

View File

@@ -108,4 +108,13 @@ public interface CodegenConfig {
boolean isSkipOverwrite();
void setSkipOverwrite(boolean skipOverwrite);
Map<String, String> supportedLibraries();
void setLibrary(String library);
/**
* Library template (sub-template).
*/
String getLibrary();
}

View File

@@ -55,6 +55,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -81,6 +82,8 @@ public class DefaultCodegen {
protected List<CliOption> cliOptions = new ArrayList<CliOption>();
protected boolean skipOverwrite;
protected boolean supportsInheritance = false;
protected Map<String, String> supportedLibraries = new LinkedHashMap<String, String>();
protected String library = null;
public List<CliOption> cliOptions() {
return cliOptions;
@@ -1289,7 +1292,7 @@ public class DefaultCodegen {
m.emptyVars = true;
}
}
/**
* Remove characters not suitable for variable or method name from the input and camelize it
@@ -1310,7 +1313,7 @@ public class DefaultCodegen {
name = name.substring(0, 1).toLowerCase() + name.substring(1);
}
return name;
}
}
public static String camelize(String word) {
return camelize(word, false);
@@ -1389,4 +1392,33 @@ public class DefaultCodegen {
public void setSkipOverwrite(boolean skipOverwrite) {
this.skipOverwrite = skipOverwrite;
}
/**
* All library templates supported.
* (key: library name, value: library description)
*/
public Map<String, String> supportedLibraries() {
return supportedLibraries;
}
public void setLibrary(String library) {
if (library != null && !supportedLibraries.containsKey(library))
throw new RuntimeException("unknown library: " + library);
this.library = library;
}
/**
* Library template (sub-template).
*/
public String getLibrary() {
return library;
}
protected CliOption buildLibraryCliOption(Map<String, String> supportedLibraries) {
StringBuilder sb = new StringBuilder("library template (sub-template) to use:");
for (String lib : supportedLibraries.keySet()) {
sb.append("\n").append(lib).append(" - ").append(supportedLibraries.get(lib));
}
return new CliOption("library", sb.toString());
}
}

View File

@@ -145,7 +145,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
if (!config.shouldOverwrite(filename)) {
continue;
}
String template = readTemplate(config.templateDir() + File.separator + templateName);
String templateFile = getFullTemplateFile(config, templateName);
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
public Reader getTemplate(String name) {
@@ -197,7 +198,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
continue;
}
String template = readTemplate(config.templateDir() + File.separator + templateName);
String templateFile = getFullTemplateFile(config, templateName);
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
public Reader getTemplate(String name) {
@@ -268,8 +270,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
continue;
}
if (support.templateFile.endsWith("mustache")) {
String template = readTemplate(config.templateDir() + File.separator + support.templateFile);
String templateFile = getFullTemplateFile(config, support.templateFile);
if (templateFile.endsWith("mustache")) {
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
public Reader getTemplate(String name) {
@@ -285,12 +289,12 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
InputStream in = null;
try {
in = new FileInputStream(config.templateDir() + File.separator + support.templateFile);
in = new FileInputStream(templateFile);
} catch (Exception e) {
// continue
}
if (in == null) {
in = this.getClass().getClassLoader().getResourceAsStream(getCPResourcePath(config.templateDir() + File.separator + support.templateFile));
in = this.getClass().getClassLoader().getResourceAsStream(getCPResourcePath(templateFile));
}
File outputFile = new File(outputFilename);
OutputStream out = new FileOutputStream(outputFile, false);
@@ -299,7 +303,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
IOUtils.copy(in, out);
} else {
if (in == null) {
System.out.println("can't open " + config.templateDir() + File.separator + support.templateFile + " for input");
System.out.println("can't open " + templateFile + " for input");
}
if (out == null) {
System.out.println("can't open " + outputFile + " for output");

View File

@@ -77,7 +77,12 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code"));
cliOptions.add(new CliOption("localVariablePrefix", "prefix for generated code members and local variables"));
cliOptions.add(new CliOption("serializableModel", "boolean - toggle \"implements Serializable\" for generated models"));
supportedLibraries.put("<default>", "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2");
supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.6");
cliOptions.add(buildLibraryCliOption(supportedLibraries));
}
public CodegenType getTag() {
@@ -146,9 +151,10 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java"));
supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java"));
supportingFiles.add(new SupportingFile("JsonUtil.mustache", invokerFolder, "JsonUtil.java"));
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
supportingFiles.add(new SupportingFile("TypeRef.mustache", invokerFolder, "TypeRef.java"));
final String authFolder = (sourceFolder + File.separator + invokerPackage + ".auth").replace(".", File.separator);
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));
@@ -301,41 +307,41 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) {
final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent));
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel);
codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel);
}
return codegenModel;
}
private CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
// This generator uses inline classes to define enums, which breaks when
// This generator uses inline classes to define enums, which breaks when
// dealing with models that have subTypes. To clean this up, we will analyze
// the parent and child models, look for enums that match, and remove
// the parent and child models, look for enums that match, and remove
// them from the child models and leave them in the parent.
// Because the child models extend the parents, the enums will be available via the parent.
// Only bother with reconciliation if the parent model has enums.
if (parentCodegenModel.hasEnums) {
// Get the properties for the parent and child models
final List<CodegenProperty> parentModelCodegenProperties = parentCodegenModel.vars;
List<CodegenProperty> codegenProperties = codegenModel.vars;
// Iterate over all of the parent model properties
for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) {
// Look for enums
// Look for enums
if (parentModelCodegenPropery.isEnum) {
// Now that we have found an enum in the parent class,
// Now that we have found an enum in the parent class,
// and search the child class for the same enum.
Iterator<CodegenProperty> iterator = codegenProperties.iterator();
while (iterator.hasNext()) {
CodegenProperty codegenProperty = iterator.next();
if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) {
// We found an enum in the child class that is
// We found an enum in the child class that is
// a duplicate of the one in the parent, so remove it.
iterator.remove();
}
@@ -345,10 +351,10 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
codegenModel.vars = codegenProperties;
}
return codegenModel;
}
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}