diff --git a/endpoints.tapir b/endpoints.tapir new file mode 100644 index 0000000..e69de29 diff --git a/parser/src/main/java/nu/zoom/state/EndpointNode.java b/parser/src/main/java/nu/zoom/state/EndpointNode.java new file mode 100644 index 0000000..1ca4a1c --- /dev/null +++ b/parser/src/main/java/nu/zoom/state/EndpointNode.java @@ -0,0 +1,4 @@ +package nu.zoom.state; + +public record EndpointNode(PathsNode paths, HandlerNode handler) { +} diff --git a/parser/src/main/java/nu/zoom/state/FieldNode.java b/parser/src/main/java/nu/zoom/state/FieldNode.java new file mode 100644 index 0000000..0cd12f1 --- /dev/null +++ b/parser/src/main/java/nu/zoom/state/FieldNode.java @@ -0,0 +1,4 @@ +package nu.zoom.state; + +public record FieldNode(String name, String type) { +} diff --git a/parser/src/main/java/nu/zoom/state/HandlerNode.java b/parser/src/main/java/nu/zoom/state/HandlerNode.java new file mode 100644 index 0000000..fe221ce --- /dev/null +++ b/parser/src/main/java/nu/zoom/state/HandlerNode.java @@ -0,0 +1,6 @@ +package nu.zoom.state; + +import java.util.List; + +public record HandlerNode(String name, List fields) { +} diff --git a/parser/src/main/java/nu/zoom/state/NodeTransformer.java b/parser/src/main/java/nu/zoom/state/NodeTransformer.java new file mode 100644 index 0000000..1704a2f --- /dev/null +++ b/parser/src/main/java/nu/zoom/state/NodeTransformer.java @@ -0,0 +1,127 @@ +package nu.zoom.state; + +import nu.zoom.tapir.parser.Node; +import nu.zoom.tapir.parser.ParseException; +import nu.zoom.tapir.parser.SimpleNode; +import nu.zoom.tapir.parser.TapirParserTreeConstants; + +import java.util.ArrayList; +import java.util.List; + +public class NodeTransformer { + + public static List transform(SimpleNode rootNode) throws ParseException { + ArrayList endpoints = new ArrayList<>(); + for (int i = 0; i < rootNode.jjtGetNumChildren(); i++) { + SimpleNode endpoint = assertSimpleNode(rootNode.jjtGetChild(i)); + endpoints.add(handleEndpoint(endpoint)); + } + return endpoints ; + } + + private static EndpointNode handleEndpoint(SimpleNode node) throws ParseException { + int numChildren = node.jjtGetNumChildren(); + if (numChildren != 2) { + throw new ParseException("Endpoint node should have two children but had: " + numChildren); + } + SimpleNode pathsParseNode = + assertSimpleNodeType( + node.jjtGetChild(0), + TapirParserTreeConstants.JJTPATHS + ); + PathsNode pathsNode = handlePaths(pathsParseNode); + SimpleNode handlerParseNode = + assertSimpleNodeType( + node.jjtGetChild(1), + TapirParserTreeConstants.JJTHANDLERSPEC + ); + HandlerNode handlerNode = handleHandler(handlerParseNode); + return new EndpointNode(pathsNode, handlerNode); + } + + private static HandlerNode handleHandler(SimpleNode handlerSpec) throws ParseException { + int numChildren = handlerSpec.jjtGetNumChildren(); + if (numChildren != 2) { + throw new ParseException("HandlerSpec-node should have two children but had: " + numChildren); + } + String handlerName = getStringValue( + assertSimpleNodeType( + handlerSpec.jjtGetChild(0), + TapirParserTreeConstants.JJTHANDLERNAME + ) + ); + SimpleNode payloadFieldsParseNode = + assertSimpleNodeType( + handlerSpec.jjtGetChild(1), + TapirParserTreeConstants.JJTPAYLOADFIELDS + ); + List fields = handleFields(payloadFieldsParseNode); + return new HandlerNode(handlerName, fields); + } + + private static List handleFields(SimpleNode payloadFieldsParseNode) throws ParseException { + ArrayList fields = new ArrayList<>(); + for (int i = 0; i < payloadFieldsParseNode.jjtGetNumChildren(); i++) { + SimpleNode payloadFieldParseNode = + assertSimpleNodeType( + payloadFieldsParseNode.jjtGetChild(i), + TapirParserTreeConstants.JJTPAYLOADFIELD + ); + int numFieldNodes = payloadFieldParseNode.jjtGetNumChildren(); + if (numFieldNodes != 2) { + throw new ParseException("Field-node should have two children but had: " + numFieldNodes); + } + String fieldName = getStringValue( + assertSimpleNodeType( + payloadFieldParseNode.jjtGetChild(0), + TapirParserTreeConstants.JJTPAYLOADFIELDNAME + ) + ); + String fieldType = getStringValue( + assertSimpleNodeType( + payloadFieldParseNode.jjtGetChild(1), + TapirParserTreeConstants.JJTPAYLOADFIELDTYPE + ) + ); + fields.add(new FieldNode(fieldName, fieldType)); + } + return fields; + } + + private static PathsNode handlePaths(SimpleNode pathsParseNode) throws ParseException { + int numPathSegments = pathsParseNode.jjtGetNumChildren(); + ArrayList segments = new ArrayList<>(); + for (int i = 0; i < numPathSegments; i++) { + SimpleNode segmentParseNode = assertSimpleNodeType(pathsParseNode.jjtGetChild(i), TapirParserTreeConstants.JJTPATH); + segments.add(getStringValue(segmentParseNode)); + } + return new PathsNode(segments); + } + + private static SimpleNode assertSimpleNodeType(Node node, int nodeType) throws ParseException { + SimpleNode result = assertSimpleNode(node); + if (result.getId() != nodeType) { + throw new ParseException( + "Expected Node of type " + + TapirParserTreeConstants.jjtNodeName[nodeType] + + " but was " + TapirParserTreeConstants.jjtNodeName[result.getId()] + ); + } + return result; + } + + private static SimpleNode assertSimpleNode(Node node) throws ParseException { + if (node instanceof SimpleNode) { + return (SimpleNode) node; + } + throw new ParseException("Expected Node to be a " + SimpleNode.class + " but found " + node.getClass()); + } + + private static String getStringValue(SimpleNode node) throws ParseException { + Object value = node.jjtGetValue(); + if (value instanceof String) { + return (String) value; + } + throw new ParseException("Expected Node " + node + " to have a String value but was " + value.getClass()); + } +} diff --git a/parser/src/main/java/nu/zoom/state/PathsNode.java b/parser/src/main/java/nu/zoom/state/PathsNode.java new file mode 100644 index 0000000..d29e048 --- /dev/null +++ b/parser/src/main/java/nu/zoom/state/PathsNode.java @@ -0,0 +1,6 @@ +package nu.zoom.state; + +import java.util.List; + +public record PathsNode(List paths) { +} diff --git a/parser/src/main/java/nu/zoom/state/TargetGenerator.java b/parser/src/main/java/nu/zoom/state/TargetGenerator.java new file mode 100644 index 0000000..05adbc1 --- /dev/null +++ b/parser/src/main/java/nu/zoom/state/TargetGenerator.java @@ -0,0 +1,38 @@ +package nu.zoom.state; + +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; + +public class TargetGenerator { + private final Path outputPath; + private final Path templatePath; + + public static class TargetGeneratorException extends Exception { + public TargetGeneratorException(String message) { + super(message); + } + public TargetGeneratorException(Exception cause) { + super(cause); + } + } + + public TargetGenerator( + Path outputPath, + Path templatePath, + List endpoints + ) { + this.outputPath = Objects.requireNonNull( + outputPath, + "Output path is required" + ); + this.templatePath = Objects.requireNonNull( + templatePath, + "Template path is required" + ); + } + + public void generate() throws TargetGeneratorException { + + } +} diff --git a/tapir-templates/endpoints.ftl b/tapir-templates/endpoints.ftl new file mode 100644 index 0000000..e69de29