diff --git a/endgen-dist/pom.xml b/endgen-dist/pom.xml
index dda6922..8a2fedb 100644
--- a/endgen-dist/pom.xml
+++ b/endgen-dist/pom.xml
@@ -5,7 +5,7 @@
nu.zoom.dsl
endgen
- 1.2-SNAPSHOT
+ 1.3-SNAPSHOT
endgen-dist
diff --git a/endgen-maven-plugin/README.md b/endgen-maven-plugin/README.md
new file mode 100644
index 0000000..3df592d
--- /dev/null
+++ b/endgen-maven-plugin/README.md
@@ -0,0 +1,35 @@
+# Configure
+
+Add the following to your `pom.xml`
+
+```xml
+
+
+
+ nu.zoom.dsl
+ endgen-maven-plugin
+ 1.2-SNAPSHOT
+
+
+
+ endgen
+
+
+ ${project.basedir}/src/main/endpoint-templates
+ ${project.basedir}/src/main/endgen/test01.endpoints
+
+
+
+
+
+
+```
+
+Replace the `` with the latest published version of the endgen plugin.
+
+* `templates` should point to the template directory to use.
+* `dsl` should be the file to generate code from.
+* `output` can be used to specify the directory where the generated files are written. Default is `${project.build.directory}/generated-sources/endgen`.
+* `parser` can be used to force the use of either the `Endpoints` or the `States` parser. Default is to determined by looking at the file ending of the dsl-file.
+
+If you have several DSL-files that you wish to generate from you can repeat the `` block with other configurations.
\ No newline at end of file
diff --git a/endgen-maven-plugin/pom.xml b/endgen-maven-plugin/pom.xml
new file mode 100644
index 0000000..9974c25
--- /dev/null
+++ b/endgen-maven-plugin/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+
+ nu.zoom.dsl
+ endgen
+ 1.3-SNAPSHOT
+
+ endgen-maven-plugin
+ maven-plugin
+
+
+ 3.15.1
+
+
+
+ org.apache.maven
+ maven-plugin-api
+ 3.9.9
+ provided
+
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ ${maven-plugin-tools.version}
+ provided
+
+
+ nu.zoom.dsl
+ parser
+ ${project.parent.version}
+
+
+
\ No newline at end of file
diff --git a/endgen-maven-plugin/src/main/java/nu/zoom/dsl/maven/EndgenMojo.java b/endgen-maven-plugin/src/main/java/nu/zoom/dsl/maven/EndgenMojo.java
new file mode 100644
index 0000000..757eee5
--- /dev/null
+++ b/endgen-maven-plugin/src/main/java/nu/zoom/dsl/maven/EndgenMojo.java
@@ -0,0 +1,68 @@
+package nu.zoom.dsl.maven;
+
+import nu.zoom.dsl.run.Runner;
+import nu.zoom.dsl.run.ValidationException;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+
+import java.io.File;
+import java.util.Optional;
+
+@Mojo(
+ name = "endgen",
+ defaultPhase = LifecyclePhase.GENERATE_SOURCES
+)
+public class EndgenMojo extends AbstractMojo {
+ @Parameter(
+ name = "templates",
+ defaultValue = "${project.build.sourceDirectory}/main/endgen-templates"
+ )
+ File templates;
+
+ @Parameter(
+ name = "output",
+ defaultValue = "${project.build.directory}/generated-sources/endgen"
+ )
+ File output;
+
+ @Parameter(name = "dsl", required = true)
+ File dsl;
+
+ @Parameter(name = "parser")
+ String parser;
+
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ try {
+ Runner.run(
+ optional(dsl).map(File::toPath).orElseThrow(),
+ optional(templates).map(File::toPath),
+ optional(output).map(File::toPath),
+ getParserType(parser),
+ new MavenLogger(getLog())
+ );
+ } catch (Exception e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+ }
+
+ private Optional getParserType(final String type) throws ValidationException {
+ if (type == null) {
+ return Optional.empty();
+ }
+ try {
+ return Optional.of(Runner.ParserType.valueOf(type));
+ } catch (IllegalArgumentException e) {
+ throw new ValidationException(e);
+ }
+ }
+
+ private Optional optional(T arg) {
+ return arg == null ? Optional.empty() : Optional.of(arg);
+ }
+}
diff --git a/endgen-maven-plugin/src/main/java/nu/zoom/dsl/maven/MavenLogger.java b/endgen-maven-plugin/src/main/java/nu/zoom/dsl/maven/MavenLogger.java
new file mode 100644
index 0000000..03b98be
--- /dev/null
+++ b/endgen-maven-plugin/src/main/java/nu/zoom/dsl/maven/MavenLogger.java
@@ -0,0 +1,17 @@
+package nu.zoom.dsl.maven;
+
+import nu.zoom.dsl.run.Logger;
+import org.apache.maven.plugin.logging.Log;
+
+public class MavenLogger implements Logger {
+ private final Log delegate;
+
+ public MavenLogger(Log delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void println(String message) {
+ this.delegate.debug(message);
+ }
+}
diff --git a/endgen-maven-plugin/src/main/java/nu/zoom/dsl/maven/Run.java b/endgen-maven-plugin/src/main/java/nu/zoom/dsl/maven/Run.java
new file mode 100644
index 0000000..c8a0779
--- /dev/null
+++ b/endgen-maven-plugin/src/main/java/nu/zoom/dsl/maven/Run.java
@@ -0,0 +1,52 @@
+package nu.zoom.dsl.maven;
+
+import java.io.File;
+
+public class Run {
+ private File templates;
+ private File output;
+ private File dsl;
+ private String parser;
+
+ public File getTemplates() {
+ return templates;
+ }
+
+ public void setTemplates(File templates) {
+ this.templates = templates;
+ }
+
+ public File getOutput() {
+ return output;
+ }
+
+ public void setOutput(File output) {
+ this.output = output;
+ }
+
+ public File getDsl() {
+ return dsl;
+ }
+
+ public void setDsl(File dsl) {
+ this.dsl = dsl;
+ }
+
+ public String getParser() {
+ return parser;
+ }
+
+ public void setParser(String parser) {
+ this.parser = parser;
+ }
+
+ @Override
+ public String toString() {
+ return "Run{" +
+ "templates=" + templates +
+ ", output=" + output +
+ ", dsl=" + dsl +
+ ", parser='" + parser + '\'' +
+ '}';
+ }
+}
diff --git a/parser/pom.xml b/parser/pom.xml
index ba9d182..67c6925 100644
--- a/parser/pom.xml
+++ b/parser/pom.xml
@@ -20,7 +20,7 @@
nu.zoom.dsl
endgen
- 1.2-SNAPSHOT
+ 1.3-SNAPSHOT
parser
diff --git a/parser/src/main/java/nu/zoom/dsl/cli/EndpointsCLI.java b/parser/src/main/java/nu/zoom/dsl/cli/EndpointsCLI.java
index e3d5794..8d79757 100644
--- a/parser/src/main/java/nu/zoom/dsl/cli/EndpointsCLI.java
+++ b/parser/src/main/java/nu/zoom/dsl/cli/EndpointsCLI.java
@@ -14,7 +14,7 @@
package nu.zoom.dsl.cli;
import nu.zoom.dsl.ast.DocumentNode;
-import nu.zoom.dsl.ast.ParserWrapper;
+import nu.zoom.dsl.run.*;
import nu.zoom.dsl.freemarker.Generator;
import picocli.CommandLine;
import picocli.CommandLine.Command;
@@ -24,8 +24,8 @@ import picocli.CommandLine.Parameters;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.Callable;
@Command(
@@ -34,20 +34,16 @@ import java.util.concurrent.Callable;
description = "Generate source code from an endpoints specification file."
)
public class EndpointsCLI implements Callable {
- public enum ParserType {
- Endpoints,
- States
- }
@SuppressWarnings("unused")
@Parameters(index = "0", description = "The source endpoints DSL file.")
private Path file;
@SuppressWarnings("CanBeFinal")
- @Option(names = {"-t", "--template"}, defaultValue = "endpoints-template", description = "The template directory. Default is ${DEFAULT-VALUE}")
+ @Option(names = {"-t", "--template"}, defaultValue = Runner.DEFAULT_TEMPLATE_DIRECTORY_NAME, description = "The template directory. Default is ${DEFAULT-VALUE}")
private Path templateDir ;
@SuppressWarnings("CanBeFinal")
- @Option(names = {"-o", "--output"}, defaultValue = "endpoints-output", description = "The directory to write the generated code to. Default is ${DEFAULT-VALUE}")
+ @Option(names = {"-o", "--output"}, defaultValue = Runner.DEFAULT_OUTPUT_DIRECTORY_NAME, description = "The directory to write the generated code to. Default is ${DEFAULT-VALUE}")
private Path outputDir ;
@SuppressWarnings("unused")
@@ -55,7 +51,7 @@ public class EndpointsCLI implements Callable {
private Boolean verbose = false;
@Option(names = {"-p", "--parser"}, description = "Force use of a specific parser instead of determining from filename. Valid values: ${COMPLETION-CANDIDATES}.")
- private ParserType parser = null;
+ private Runner.ParserType parser = null;
public static void main(String[] args) {
int exitCode = new CommandLine(new EndpointsCLI()).execute(args);
@@ -65,32 +61,14 @@ public class EndpointsCLI implements Callable {
@Override
public Integer call() {
try {
- validateTemplateDirectory();
- validateInputFile();
- validateOutputDirectory();
- verbose("Parsing: " + file.toAbsolutePath());
- if (parser == null) {
- if (file.getFileName().toString().endsWith(".states")) {
- parser = ParserType.States;
- }
- }
- final DocumentNode rootNode ;
- if (parser == ParserType.States) {
- verbose("using state grammar.") ;
- rootNode = ParserWrapper.parseStates(file);
- } else {
- verbose("using endpoints grammar.") ;
- rootNode = ParserWrapper.parseEndpoints(file);
- }
- verbose("AST: " + rootNode);
- verbose("Generating from templates in: " + templateDir.toAbsolutePath());
- Generator generator = new Generator(templateDir, rootNode, outputDir);
- List generatedPaths = generator.generate();
- if (generatedPaths.isEmpty()) {
- System.out.println("No generated paths found.");
- } else {
- generatedPaths.forEach(p -> verbose("Generated: " + p.toAbsolutePath()));
- }
+ final Logger logger = this.verbose ? new StdoutLogger() : new NullLogger() ;
+ Runner.run(
+ this.file,
+ Optional.of(this.templateDir),
+ Optional.of(this.outputDir),
+ parser == null ? Optional.empty() : Optional.of(parser),
+ logger
+ );
return 0;
} catch (Exception e) {
System.err.println(e.getMessage());
diff --git a/parser/src/main/java/nu/zoom/dsl/run/EndgenException.java b/parser/src/main/java/nu/zoom/dsl/run/EndgenException.java
new file mode 100644
index 0000000..7771e11
--- /dev/null
+++ b/parser/src/main/java/nu/zoom/dsl/run/EndgenException.java
@@ -0,0 +1,15 @@
+package nu.zoom.dsl.run;
+
+public abstract class EndgenException extends Exception {
+ public EndgenException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public EndgenException(Throwable cause) {
+ super(cause);
+ }
+
+ public EndgenException(String message) {
+ super(message);
+ }
+}
diff --git a/parser/src/main/java/nu/zoom/dsl/run/GeneratorException.java b/parser/src/main/java/nu/zoom/dsl/run/GeneratorException.java
new file mode 100644
index 0000000..5157d97
--- /dev/null
+++ b/parser/src/main/java/nu/zoom/dsl/run/GeneratorException.java
@@ -0,0 +1,15 @@
+package nu.zoom.dsl.run;
+
+public class GeneratorException extends EndgenException {
+ public GeneratorException(String message) {
+ super(message);
+ }
+
+ public GeneratorException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public GeneratorException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/parser/src/main/java/nu/zoom/dsl/run/Logger.java b/parser/src/main/java/nu/zoom/dsl/run/Logger.java
new file mode 100644
index 0000000..80826d3
--- /dev/null
+++ b/parser/src/main/java/nu/zoom/dsl/run/Logger.java
@@ -0,0 +1,5 @@
+package nu.zoom.dsl.run;
+
+public interface Logger {
+ void println(String message);
+}
diff --git a/parser/src/main/java/nu/zoom/dsl/run/NullLogger.java b/parser/src/main/java/nu/zoom/dsl/run/NullLogger.java
new file mode 100644
index 0000000..014f473
--- /dev/null
+++ b/parser/src/main/java/nu/zoom/dsl/run/NullLogger.java
@@ -0,0 +1,8 @@
+package nu.zoom.dsl.run;
+
+public class NullLogger implements Logger {
+ @Override
+ public void println(String message) {
+
+ }
+}
diff --git a/parser/src/main/java/nu/zoom/dsl/run/ParserException.java b/parser/src/main/java/nu/zoom/dsl/run/ParserException.java
new file mode 100644
index 0000000..b726384
--- /dev/null
+++ b/parser/src/main/java/nu/zoom/dsl/run/ParserException.java
@@ -0,0 +1,15 @@
+package nu.zoom.dsl.run;
+
+public class ParserException extends EndgenException {
+ public ParserException(String message) {
+ super(message);
+ }
+
+ public ParserException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ParserException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/parser/src/main/java/nu/zoom/dsl/ast/ParserWrapper.java b/parser/src/main/java/nu/zoom/dsl/run/ParserWrapper.java
similarity index 93%
rename from parser/src/main/java/nu/zoom/dsl/ast/ParserWrapper.java
rename to parser/src/main/java/nu/zoom/dsl/run/ParserWrapper.java
index 11a95fd..ce62d9c 100644
--- a/parser/src/main/java/nu/zoom/dsl/ast/ParserWrapper.java
+++ b/parser/src/main/java/nu/zoom/dsl/run/ParserWrapper.java
@@ -11,8 +11,11 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package nu.zoom.dsl.ast;
+package nu.zoom.dsl.run;
+import nu.zoom.dsl.ast.DocumentNode;
+import nu.zoom.dsl.ast.EndpointsVisitorTransformer;
+import nu.zoom.dsl.ast.StatesVisitorTransformer;
import nu.zoom.dsl.parser.*;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
diff --git a/parser/src/main/java/nu/zoom/dsl/run/Runner.java b/parser/src/main/java/nu/zoom/dsl/run/Runner.java
new file mode 100644
index 0000000..ebf162b
--- /dev/null
+++ b/parser/src/main/java/nu/zoom/dsl/run/Runner.java
@@ -0,0 +1,96 @@
+package nu.zoom.dsl.run;
+
+import freemarker.template.TemplateException;
+import nu.zoom.dsl.ast.DocumentNode;
+import nu.zoom.dsl.freemarker.Generator;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Optional;
+
+public final class Runner {
+ public static final String DEFAULT_TEMPLATE_DIRECTORY_NAME = "endpoints-template";
+ public static final String DEFAULT_OUTPUT_DIRECTORY_NAME = "endpoints-output";
+
+ public static void run(
+ Path dsl,
+ Optional templates,
+ Optional output,
+ Optional maybeParser,
+ Logger logger
+ ) throws ValidationException, IOException, GeneratorException {
+ Path templatesDir = templates.orElse(Paths.get(DEFAULT_TEMPLATE_DIRECTORY_NAME));
+ Path outputDir = output.orElse(Paths.get(DEFAULT_OUTPUT_DIRECTORY_NAME));
+
+ validateOutputDirectory(outputDir);
+ validateTemplateDirectory(templatesDir);
+ validateInputFile(dsl);
+ logger.println("Parsing: " + dsl.toAbsolutePath());
+
+ final ParserType parser =
+ maybeParser.orElseGet(
+ () -> {
+ if (dsl.getFileName().toString().endsWith(".states")) {
+ return ParserType.States;
+ } else {
+ return ParserType.Endpoints;
+ }
+ }
+ );
+
+ final DocumentNode rootNode;
+ if (parser == ParserType.States) {
+ logger.println("using state grammar.");
+ rootNode = ParserWrapper.parseStates(dsl);
+ } else {
+ logger.println("using endpoints grammar.");
+ rootNode = ParserWrapper.parseEndpoints(dsl);
+ }
+ logger.println("AST: " + rootNode);
+ logger.println("Generating from templates in: " + templatesDir.toAbsolutePath());
+ Generator generator = new Generator(templatesDir, rootNode, outputDir);
+ List generatedPaths = null;
+ try {
+ generatedPaths = generator.generate();
+ } catch (TemplateException e) {
+ throw new GeneratorException(e);
+ }
+ if (generatedPaths.isEmpty()) {
+ System.out.println("No generated paths found.");
+ } else {
+ generatedPaths.forEach(p -> logger.println("Generated: " + p.toAbsolutePath()));
+ }
+ }
+
+ private static void validateOutputDirectory(Path outputDir) throws IOException, ValidationException {
+ if (Files.notExists(outputDir)) {
+ Files.createDirectories(outputDir);
+ }
+ if (!Files.isDirectory(outputDir)) {
+ throw new ValidationException("Output directory: '" + outputDir + " 'is not a directory.");
+ }
+ }
+
+ private static void validateTemplateDirectory(Path templateDir) throws ValidationException {
+ if (!Files.isDirectory(templateDir)) {
+ throw new ValidationException("Template directory '" + templateDir + "' is not a directory.");
+ }
+ }
+
+ private static void validateInputFile(Path file) throws ValidationException {
+ if (Files.notExists(file)) {
+ throw new ValidationException("Input file '" + file + "' does not exist.");
+ }
+ if (!Files.isReadable(file) || !Files.isRegularFile(file)) {
+ throw new ValidationException("Input file '" + file + "' is not a readable file.");
+ }
+ }
+
+ public enum ParserType {
+ Endpoints,
+ States
+ }
+}
diff --git a/parser/src/main/java/nu/zoom/dsl/run/StdoutLogger.java b/parser/src/main/java/nu/zoom/dsl/run/StdoutLogger.java
new file mode 100644
index 0000000..7b0b7d4
--- /dev/null
+++ b/parser/src/main/java/nu/zoom/dsl/run/StdoutLogger.java
@@ -0,0 +1,9 @@
+package nu.zoom.dsl.run;
+
+public class StdoutLogger implements Logger {
+
+ @Override
+ public void println(String message) {
+ System.out.println(message);
+ }
+}
diff --git a/parser/src/main/java/nu/zoom/dsl/run/ValidationException.java b/parser/src/main/java/nu/zoom/dsl/run/ValidationException.java
new file mode 100644
index 0000000..1627d72
--- /dev/null
+++ b/parser/src/main/java/nu/zoom/dsl/run/ValidationException.java
@@ -0,0 +1,15 @@
+package nu.zoom.dsl.run;
+
+public class ValidationException extends EndgenException {
+ public ValidationException(String message) {
+ super(message);
+ }
+
+ public ValidationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ValidationException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/pom.xml b/pom.xml
index 86744cc..82a7a48 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
nu.zoom.dsl
endgen
- 1.2-SNAPSHOT
+ 1.3-SNAPSHOT
pom
@@ -65,6 +65,7 @@
parser
endgen-dist
+ endgen-maven-plugin
diff --git a/sample-maven/pom.xml b/sample-maven/pom.xml
new file mode 100644
index 0000000..99fdbab
--- /dev/null
+++ b/sample-maven/pom.xml
@@ -0,0 +1,70 @@
+
+
+
+ 4.0.0
+
+ nu.zoom.dsl
+ sample-maven
+ 1.0-SNAPSHOT
+ jar
+
+
+ 21
+ 21
+ UTF-8
+
+
+
+
+ ASF 2.0
+ https://www.apache.org/licenses/LICENSE-2.0
+
+
+
+
+
+ Johan Maasing
+ johan@zoom.nu
+
+ developer
+
+
+
+
+
+
+
+ nu.zoom.dsl
+ endgen-maven-plugin
+ 1.2-SNAPSHOT
+
+
+
+ endgen
+
+
+ ${project.basedir}/src/main/endpoint-templates
+ ${project.basedir}/src/main/endgen/test01.endpoints
+
+
+
+
+
+
+
+
diff --git a/sample-maven/src/main/endgen/test01.endpoints b/sample-maven/src/main/endgen/test01.endpoints
new file mode 100644
index 0000000..6f212ed
--- /dev/null
+++ b/sample-maven/src/main/endgen/test01.endpoints
@@ -0,0 +1,28 @@
+/*
+ Copyright 2025 "Johan Maasing"
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+{
+ some: configvalue,
+ someother: value,
+ package: se.rutdev.senash
+}
+
+/some/endpoint <- SomeType(foo:String)
+Embedded(foo:Bar)
+/some/other/endpoint <- (bar:Seq[Embedded])
+/yet/other/endpoint2 <- (bar2:Seq[AType]) -> NamedResponse(foo:Bar)
+AType(data: java.util.List)
+/yet/other/endpoint3 <- (bar2:Seq[AType]) -> (foo:Bar)
diff --git a/sample-maven/src/main/endgen/test01.states b/sample-maven/src/main/endgen/test01.states
new file mode 100644
index 0000000..3b9a67a
--- /dev/null
+++ b/sample-maven/src/main/endgen/test01.states
@@ -0,0 +1,21 @@
+/*
+ Copyright 2025 "Johan Maasing"
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+{ title: SomeNodes, package: nu.zoom.dsl.states }
+
+start(s:S) -> message(foo:foo) -> middle(foo:foo) ,
+middle -> selfmessage(bar:bar) -> middle(bar:bar),
+middle -> message(bar:baz) -> end
diff --git a/sample-maven/src/main/endpoint-templates/nu/zoom/dsl/sample/Endpoints.java.ftl b/sample-maven/src/main/endpoint-templates/nu/zoom/dsl/sample/Endpoints.java.ftl
new file mode 100644
index 0000000..624c722
--- /dev/null
+++ b/sample-maven/src/main/endpoint-templates/nu/zoom/dsl/sample/Endpoints.java.ftl
@@ -0,0 +1,22 @@
+// Copyright 2025 "Johan Maasing"
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+<#list meta.templateDirectories>package<#items as dir>${dir}<#sep>.#items>;#list>
+
+class Endpoints() {
+<#list endpoints as endpoint>
+ /* <#list endpoint.paths.paths><#items as segment>/${segment}#items>#list> */
+ public void handle${endpoint.inputType?cap_first}
+
+#list>
+}
\ No newline at end of file