Skip to content

Commit 4901b71

Browse files
authored
Merge pull request #8618 from swagger-api/mustache_engine
allow capability to generate templates with mustache engine.
2 parents d78362d + 49c33fd commit 4901b71

File tree

5 files changed

+181
-22
lines changed

5 files changed

+181
-22
lines changed

modules/swagger-codegen/src/main/java/io/swagger/codegen/v3/CodegenConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import java.util.Set;
66

77
import com.github.jknack.handlebars.Handlebars;
8+
import com.samskivert.mustache.Mustache;
9+
import io.swagger.codegen.v3.templates.TemplateEngine;
810
import io.swagger.v3.oas.models.OpenAPI;
911
import io.swagger.v3.oas.models.Operation;
1012
import io.swagger.v3.oas.models.media.Schema;
@@ -125,6 +127,10 @@ public interface CodegenConfig {
125127

126128
void processOpenAPI(OpenAPI openAPI);
127129

130+
Mustache.Compiler processCompiler(Mustache.Compiler compiler);
131+
132+
// TemplateEngine getTemplateEngine();
133+
128134
String sanitizeTag(String tag);
129135

130136
String toApiFilename(String name);

modules/swagger-codegen/src/main/java/io/swagger/codegen/v3/DefaultGenerator.java

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import com.github.jknack.handlebars.io.FileTemplateLoader;
66
import com.github.jknack.handlebars.io.TemplateLoader;
77
import io.swagger.codegen.v3.ignore.CodegenIgnoreProcessor;
8+
import io.swagger.codegen.v3.templates.HandlebarTemplateEngine;
9+
import io.swagger.codegen.v3.templates.TemplateEngine;
810
import io.swagger.codegen.v3.utils.ImplementationVersion;
911
import io.swagger.codegen.v3.utils.URLPathUtil;
1012
import io.swagger.v3.core.util.Json;
@@ -57,6 +59,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
5759
protected ClientOptInput opts;
5860
protected OpenAPI openAPI;
5961
protected CodegenIgnoreProcessor ignoreProcessor;
62+
protected TemplateEngine templateEngine;
6063
private Boolean generateApis = null;
6164
private Boolean generateModels = null;
6265
private Boolean generateSupportingFiles = null;
@@ -92,6 +95,9 @@ public Generator opts(ClientOptInput opts) {
9295
this.ignoreProcessor = new CodegenIgnoreProcessor(this.config.getOutputDir());
9396
}
9497

98+
// this.templateEngine = config.getTemplateEngine();
99+
this.templateEngine = new HandlebarTemplateEngine(config);
100+
95101
return this;
96102
}
97103

@@ -573,8 +579,7 @@ private void generateSupportingFiles(List<File> files, Map<String, Object> bundl
573579

574580
if(ignoreProcessor.allowsFile(new File(outputFilename))) {
575581
if (templateFile.endsWith("mustache")) {
576-
final com.github.jknack.handlebars.Template hTemplate = getHandlebars(templateFile);
577-
String rendered = hTemplate.apply(bundle);
582+
String rendered = templateEngine.getRendered(templateFile, bundle);
578583
writeToFile(outputFilename, rendered);
579584
files.add(new File(outputFilename));
580585
} else {
@@ -734,8 +739,7 @@ private File processTemplateToFile(Map<String, Object> templateData, String temp
734739
String adjustedOutputFilename = outputFilename.replaceAll("//", "/").replace('/', File.separatorChar);
735740
if(ignoreProcessor.allowsFile(new File(adjustedOutputFilename))) {
736741
String templateFile = getFullTemplateFile(config, templateName);
737-
final com.github.jknack.handlebars.Template hTemplate = getHandlebars(templateFile);
738-
String rendered = hTemplate.apply(templateData);
742+
String rendered = templateEngine.getRendered(templateFile, templateData);
739743
writeToFile(adjustedOutputFilename, rendered);
740744
return new File(adjustedOutputFilename);
741745
}
@@ -1002,24 +1006,6 @@ private Map<String, SecurityScheme> getAuthMethods(List<SecurityRequirement> sec
10021006
return authMethods;
10031007
}
10041008

1005-
private com.github.jknack.handlebars.Template getHandlebars(String templateFile) throws IOException {
1006-
templateFile = templateFile.replace(".mustache", StringUtils.EMPTY).replace("\\", "/");
1007-
String templateDir = config.templateDir().replace(".mustache", StringUtils.EMPTY).replace("\\", "/");
1008-
if (templateFile.startsWith(templateDir)) {
1009-
templateFile = StringUtils.replaceOnce(templateFile, templateDir, StringUtils.EMPTY);
1010-
}
1011-
TemplateLoader templateLoader = null;
1012-
if (config.additionalProperties().get(CodegenConstants.TEMPLATE_DIR) != null) {
1013-
templateLoader = new FileTemplateLoader(templateDir, ".mustache");
1014-
} else {
1015-
templateLoader = new ClassPathTemplateLoader("/" + templateDir, ".mustache");
1016-
}
1017-
final Handlebars handlebars = new Handlebars(templateLoader);
1018-
handlebars.prettyPrint(true);
1019-
config.addHandlebarHelpers(handlebars);
1020-
return handlebars.compile(templateFile);
1021-
}
1022-
10231009
private boolean isJavaCodegen(String name) {
10241010
return name.equalsIgnoreCase("java")
10251011
|| name.equalsIgnoreCase("inflector");
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package io.swagger.codegen.v3.templates;
2+
3+
import com.github.jknack.handlebars.Handlebars;
4+
import com.github.jknack.handlebars.io.ClassPathTemplateLoader;
5+
import com.github.jknack.handlebars.io.FileTemplateLoader;
6+
import com.github.jknack.handlebars.io.TemplateLoader;
7+
import io.swagger.codegen.v3.CodegenConfig;
8+
import io.swagger.codegen.v3.CodegenConstants;
9+
import org.apache.commons.lang3.StringUtils;
10+
11+
import java.io.IOException;
12+
import java.util.Map;
13+
14+
public class HandlebarTemplateEngine implements TemplateEngine {
15+
16+
private CodegenConfig config;
17+
18+
public HandlebarTemplateEngine(CodegenConfig config) {
19+
this.config = config;
20+
}
21+
22+
@Override
23+
public String getRendered(String templateFile, Map<String, Object> templateData) throws IOException {
24+
final com.github.jknack.handlebars.Template hTemplate = getHandlebars(templateFile);
25+
return hTemplate.apply(templateData);
26+
}
27+
28+
private com.github.jknack.handlebars.Template getHandlebars(String templateFile) throws IOException {
29+
templateFile = templateFile.replace(".mustache", StringUtils.EMPTY).replace("\\", "/");
30+
String templateDir = config.templateDir().replace(".mustache", StringUtils.EMPTY).replace("\\", "/");
31+
if (templateFile.startsWith(templateDir)) {
32+
templateFile = StringUtils.replaceOnce(templateFile, templateDir, StringUtils.EMPTY);
33+
}
34+
TemplateLoader templateLoader = null;
35+
if (config.additionalProperties().get(CodegenConstants.TEMPLATE_DIR) != null) {
36+
templateLoader = new FileTemplateLoader(templateDir, ".mustache");
37+
} else {
38+
templateLoader = new ClassPathTemplateLoader("/" + templateDir, ".mustache");
39+
}
40+
final Handlebars handlebars = new Handlebars(templateLoader);
41+
handlebars.prettyPrint(true);
42+
config.addHandlebarHelpers(handlebars);
43+
return handlebars.compile(templateFile);
44+
}
45+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package io.swagger.codegen.v3.templates;
2+
3+
import com.samskivert.mustache.Mustache;
4+
import com.samskivert.mustache.Template;
5+
import io.swagger.codegen.v3.CodegenConfig;
6+
import org.apache.commons.lang3.StringUtils;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
10+
import java.io.File;
11+
import java.io.FileInputStream;
12+
import java.io.IOException;
13+
import java.io.InputStream;
14+
import java.io.InputStreamReader;
15+
import java.io.Reader;
16+
import java.util.Map;
17+
import java.util.Scanner;
18+
import java.util.regex.Pattern;
19+
20+
public class MustacheTemplateEngine implements TemplateEngine {
21+
22+
private static final Logger LOGGER = LoggerFactory.getLogger(MustacheTemplateEngine.class);
23+
24+
private CodegenConfig config;
25+
26+
public MustacheTemplateEngine(CodegenConfig config) {
27+
this.config = config;
28+
}
29+
30+
@Override
31+
public String getRendered(String templateFile, Map<String, Object> templateData) throws IOException {
32+
String template = readTemplate(templateFile);
33+
34+
Mustache.Compiler compiler = Mustache.compiler();
35+
compiler = config.processCompiler(compiler);
36+
Template tmpl = compiler
37+
.withLoader((name) -> {
38+
final String fullTemplateFile = getFullTemplateFile(config, name + ".mustache");
39+
return getTemplateReader(fullTemplateFile);
40+
})
41+
.defaultValue(StringUtils.EMPTY)
42+
.compile(template);
43+
44+
return tmpl.execute(templateData);
45+
}
46+
47+
public String readTemplate(String name) {
48+
Reader reader = getTemplateReader(name);
49+
try {
50+
if (reader == null) {
51+
throw new RuntimeException("no file found");
52+
}
53+
final Scanner scanner = new Scanner(reader).useDelimiter("\\A");
54+
return scanner.hasNext() ? scanner.next() : "";
55+
} catch (Exception e) {
56+
LOGGER.error(e.getMessage());
57+
} finally {
58+
if (reader != null) {
59+
try {
60+
reader.close();
61+
} catch (IOException e) {
62+
LOGGER.error(e.getMessage());
63+
}
64+
}
65+
}
66+
throw new RuntimeException("can't load template " + name);
67+
}
68+
69+
public Reader getTemplateReader(String name) {
70+
try {
71+
InputStream is = this.getClass().getClassLoader().getResourceAsStream(getClassResourcePath(name));
72+
if (is == null) {
73+
is = new FileInputStream(new File(name));
74+
}
75+
return new InputStreamReader(is, "UTF-8");
76+
} catch (Exception e) {
77+
LOGGER.error(e.getMessage());
78+
}
79+
throw new RuntimeException("can't load template " + name);
80+
}
81+
82+
public String getFullTemplateFile(CodegenConfig config, String templateFile) {
83+
final String library = config.getLibrary();
84+
final String libTemplateFile = new StringBuilder(config.templateDir())
85+
.append(File.separator)
86+
.append("libraries")
87+
.append(File.separator)
88+
.append(templateFile)
89+
.toString();
90+
if (StringUtils.isNotEmpty(library)) {
91+
if (new File(libTemplateFile).exists()) {
92+
return libTemplateFile;
93+
}
94+
}
95+
final String template = config.templateDir() + File.separator + templateFile;
96+
if (new File(template).exists()) {
97+
return template;
98+
}
99+
if (StringUtils.isNotEmpty(library)) {
100+
if (this.getClass().getClassLoader().getResource(getClassResourcePath(libTemplateFile)) != null) {
101+
return libTemplateFile;
102+
}
103+
}
104+
return config.embeddedTemplateDir() + File.separator + templateFile;
105+
}
106+
107+
public String getClassResourcePath(String name) {
108+
if (!"/".equals(File.separator)) {
109+
return name.replaceAll(Pattern.quote(File.separator), "/");
110+
}
111+
return name;
112+
}
113+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.swagger.codegen.v3.templates;
2+
3+
import java.io.IOException;
4+
import java.util.Map;
5+
6+
public interface TemplateEngine {
7+
8+
String getRendered(String templateFile, Map<String, Object> templateData) throws IOException;
9+
}

0 commit comments

Comments
 (0)