Freemarker templates

This commit is contained in:
Johan Maasing 2025-04-01 20:38:42 +02:00
parent 8057928548
commit d41212c7b2
5 changed files with 72 additions and 20 deletions

View file

@ -0,0 +1,6 @@
package se.senashdev.projekt.api
object Codecs:
<#list typeDefinitions as type>
given Codec[${type.name?cap_first}] = deriveCodec
</#list>

View file

@ -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}")
</#items>
.in(jsonBody[${endpoint.inputType?cap_first}])
.out(jsonBody[VersionedResponse])
</#list>
</#list>

View file

@ -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},
</#list>
)
</#list>

View file

@ -24,9 +24,9 @@
<version>4.7.6</version> <version>4.7.6</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>gg.jte</groupId> <groupId>org.freemarker</groupId>
<artifactId>jte</artifactId> <artifactId>freemarker</artifactId>
<version>3.2.0</version> <version>2.3.34</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>

View file

@ -1,14 +1,13 @@
package nu.zoom.dsl.jte; package nu.zoom.dsl.jte;
import gg.jte.CodeResolver; import freemarker.template.Configuration;
import gg.jte.ContentType; import freemarker.template.Template;
import gg.jte.TemplateEngine; import freemarker.template.TemplateException;
import gg.jte.TemplateOutput; import freemarker.template.TemplateExceptionHandler;
import gg.jte.output.FileOutput;
import gg.jte.resolve.DirectoryCodeResolver;
import nu.zoom.dsl.ast.DocumentNode; import nu.zoom.dsl.ast.DocumentNode;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
@ -19,27 +18,37 @@ public class Generator {
private final Path templatesDir ; private final Path templatesDir ;
private final DocumentNode data; private final DocumentNode data;
private final Path outputDir ; 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.templatesDir = Objects.requireNonNull(templatesDir);
this.data = Objects.requireNonNull(data); this.data = Objects.requireNonNull(data);
this.outputDir = Objects.requireNonNull(outputDir); this.outputDir = Objects.requireNonNull(outputDir);
this.templateEngine = TemplateEngine.create( this.cfg = new Configuration(Configuration.VERSION_2_3_34);
new DirectoryCodeResolver(templatesDir), cfg.setDirectoryForTemplateLoading(templatesDir.toFile());
ContentType.Plain cfg.setDefaultEncoding("UTF-8");
); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setLogTemplateExceptions(false);
cfg.setWrapUncheckedExceptions(true);
cfg.setFallbackOnNullLoopVariable(false);
} }
public List<Path> generate() throws IOException { public List<Path> generate() throws IOException, TemplateException {
List<Path> templates = Files.list(templatesDir).filter(p -> p.toString().endsWith(".jte")).toList() ; List<Path> templates = Files.list(templatesDir).filter(p -> p.toString().endsWith(".ftl")).toList() ;
ArrayList<Path> out = new ArrayList<>(); ArrayList<Path> out = new ArrayList<>();
for (Path template : templates) { for (Path template : templates) {
// TODO file ending // TODO file ending
Path outpath = outputDir.resolve(template.getFileName()); Path outpath = outputDir.resolve(outputFilenameFromTemplate(template.getFileName()));
this.templateEngine.render(template.getFileName().toString(), this.data, new FileOutput(outpath)); 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); out.add(outpath);
} }
}
return out ; return out ;
} }
private String outputFilenameFromTemplate(Path template) {
return template.getFileName().toString().replace(".ftl", ".scala");
}
} }