From d41212c7b246e15569c81dc4ea3dadd91dc93247 Mon Sep 17 00:00:00 2001 From: Johan Maasing Date: Tue, 1 Apr 2025 20:38:42 +0200 Subject: [PATCH] Freemarker templates --- endpoints-templates/Codecs.ftl | 6 +++ endpoints-templates/Endpoints.ftl | 27 ++++++++++++ endpoints-templates/Protocol.ftl | 10 +++++ parser/pom.xml | 6 +-- .../main/java/nu/zoom/dsl/jte/Generator.java | 43 +++++++++++-------- 5 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 endpoints-templates/Codecs.ftl create mode 100644 endpoints-templates/Endpoints.ftl create mode 100644 endpoints-templates/Protocol.ftl diff --git a/endpoints-templates/Codecs.ftl b/endpoints-templates/Codecs.ftl new file mode 100644 index 0000000..91a06d3 --- /dev/null +++ b/endpoints-templates/Codecs.ftl @@ -0,0 +1,6 @@ +package se.senashdev.projekt.api + +object Codecs: +<#list typeDefinitions as type> + given Codec[${type.name?cap_first}] = deriveCodec + diff --git a/endpoints-templates/Endpoints.ftl b/endpoints-templates/Endpoints.ftl new file mode 100644 index 0000000..fc1749a --- /dev/null +++ b/endpoints-templates/Endpoints.ftl @@ -0,0 +1,27 @@ +package se.senashdev.projekt.api + +import se.rutdev.projekt.api.HttpProtocol.VersionedResponse +import se.rutdev.framework.json.circe.RutUtilsCodec +import se.rutdev.framework +import se.rutdev.framework.service.api.{OAuthUtils, RequestMeta, RutTapir} +import se.rutdev.pd.ProblemDetailProtocol.ProblemDetail +import sttp.tapir.Schema +import se.senashdev.projekt.api.Protocol.* +import se.senashdev.projekt.api.Codecs._ + +class Endpoints(override val config: OAuthUtils.OAuthConfig) extends framework.service.api.Endpoints with RutTapir with RutUtilsCodec: + type ApiEndpoint[I, O] = OAuthEndpoint[RequestMeta.OAuthRequestMeta, I, ProblemDetail, O] + +<#list endpoints as endpoint> + val ${endpoint.inputType}Endpoint = ApiEndpoint[${endpoint.inputType?cap_first}, VersionedResponse] = + <#list endpoint.paths.paths> + apiV1Endpoint + .post + <#items as segment> + .in("${segment}") + + .in(jsonBody[${endpoint.inputType?cap_first}]) + .out(jsonBody[VersionedResponse]) + + + \ No newline at end of file diff --git a/endpoints-templates/Protocol.ftl b/endpoints-templates/Protocol.ftl new file mode 100644 index 0000000..96423b7 --- /dev/null +++ b/endpoints-templates/Protocol.ftl @@ -0,0 +1,10 @@ +package se.senashdev.projekt.api + +object Protocol: +<#list typeDefinitions as type> + case class ${type.name?cap_first}( + <#list type.fields as field> + ${field.name} : ${field.type}, + + ) + diff --git a/parser/pom.xml b/parser/pom.xml index 40af316..1f7e1d8 100644 --- a/parser/pom.xml +++ b/parser/pom.xml @@ -24,9 +24,9 @@ 4.7.6 - gg.jte - jte - 3.2.0 + org.freemarker + freemarker + 2.3.34 diff --git a/parser/src/main/java/nu/zoom/dsl/jte/Generator.java b/parser/src/main/java/nu/zoom/dsl/jte/Generator.java index 4382e3c..bb46534 100644 --- a/parser/src/main/java/nu/zoom/dsl/jte/Generator.java +++ b/parser/src/main/java/nu/zoom/dsl/jte/Generator.java @@ -1,14 +1,13 @@ package nu.zoom.dsl.jte; -import gg.jte.CodeResolver; -import gg.jte.ContentType; -import gg.jte.TemplateEngine; -import gg.jte.TemplateOutput; -import gg.jte.output.FileOutput; -import gg.jte.resolve.DirectoryCodeResolver; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; import nu.zoom.dsl.ast.DocumentNode; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -19,27 +18,37 @@ public class Generator { private final Path templatesDir ; private final DocumentNode data; private final Path outputDir ; - private final TemplateEngine templateEngine; + private final Configuration cfg; - public Generator(Path templatesDir, DocumentNode data, Path outputDir) { + public Generator(Path templatesDir, DocumentNode data, Path outputDir) throws IOException { this.templatesDir = Objects.requireNonNull(templatesDir); this.data = Objects.requireNonNull(data); this.outputDir = Objects.requireNonNull(outputDir); - this.templateEngine = TemplateEngine.create( - new DirectoryCodeResolver(templatesDir), - ContentType.Plain - ); + this.cfg = new Configuration(Configuration.VERSION_2_3_34); + cfg.setDirectoryForTemplateLoading(templatesDir.toFile()); + cfg.setDefaultEncoding("UTF-8"); + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + cfg.setLogTemplateExceptions(false); + cfg.setWrapUncheckedExceptions(true); + cfg.setFallbackOnNullLoopVariable(false); } - public List generate() throws IOException { - List templates = Files.list(templatesDir).filter(p -> p.toString().endsWith(".jte")).toList() ; + public List generate() throws IOException, TemplateException { + List templates = Files.list(templatesDir).filter(p -> p.toString().endsWith(".ftl")).toList() ; ArrayList out = new ArrayList<>(); for (Path template : templates) { // TODO file ending - Path outpath = outputDir.resolve(template.getFileName()); - this.templateEngine.render(template.getFileName().toString(), this.data, new FileOutput(outpath)); - out.add(outpath); + Path outpath = outputDir.resolve(outputFilenameFromTemplate(template.getFileName())); + Template ftl = this.cfg.getTemplate(template.getFileName().toString()) ; + try (var outw = Files.newBufferedWriter(outpath, StandardCharsets.UTF_8)) { + ftl.process(this.data, outw); + out.add(outpath); + } } return out ; } + + private String outputFilenameFromTemplate(Path template) { + return template.getFileName().toString().replace(".ftl", ".scala"); + } }