This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch rest-dsl-parser in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/rest-dsl-parser by this push: new 926d86c CAMEL-12824: camel-route-parser - Add parser for rest-dsl 926d86c is described below commit 926d86c20e628c9f85fd7448452f76d1881dd7db Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Sun Sep 23 11:55:17 2018 +0200 CAMEL-12824: camel-route-parser - Add parser for rest-dsl --- .../org/apache/camel/parser/XmlRestDslParser.java | 28 ++++- .../parser/helper/CamelXmlRestDslParserHelper.java | 136 +++++++++++++++++++++ .../apache/camel/parser/xml/XmlRestDslTest.java | 42 +++++++ .../org/apache/camel/parser/xml/myrest.xml | 13 ++ 4 files changed, 217 insertions(+), 2 deletions(-) diff --git a/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/XmlRestDslParser.java b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/XmlRestDslParser.java index db7a835..e28a295 100644 --- a/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/XmlRestDslParser.java +++ b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/XmlRestDslParser.java @@ -25,6 +25,7 @@ import org.w3c.dom.Document; import org.apache.camel.parser.helper.CamelXmlRestDslParserHelper; import org.apache.camel.parser.helper.XmlLineNumberParser; import org.apache.camel.parser.model.RestConfigurationDetails; +import org.apache.camel.parser.model.RestServiceDetails; /** * A Camel XML parser that parses Camel XML Rest DSL source code. @@ -33,8 +34,6 @@ import org.apache.camel.parser.model.RestConfigurationDetails; */ public final class XmlRestDslParser { - // TODO: xml rest services - private XmlRestDslParser() { } @@ -62,4 +61,29 @@ public final class XmlRestDslParser { return Collections.EMPTY_LIST; } + /** + * Parses the java source class and build a rest service model of the discovered rest services in the java source class. + * + * @param xml the xml file as input stream + * @param baseDir the base of the source code + * @param fullyQualifiedFileName the fully qualified source code file name + * @return a list of rest services + */ + public static List<RestServiceDetails> parseRestService(InputStream xml, String baseDir, String fullyQualifiedFileName) { + + // try parse it as dom + Document dom = null; + try { + dom = XmlLineNumberParser.parseXml(xml); + } catch (Exception e) { + // ignore as the xml file may not be valid at this point + } + if (dom != null) { + CamelXmlRestDslParserHelper parser = new CamelXmlRestDslParserHelper(); + return parser.parseRestService(dom, baseDir, fullyQualifiedFileName); + } + + return Collections.EMPTY_LIST; + } + } diff --git a/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/helper/CamelXmlRestDslParserHelper.java b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/helper/CamelXmlRestDslParserHelper.java index 0e83c1f..bb04cab 100644 --- a/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/helper/CamelXmlRestDslParserHelper.java +++ b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/helper/CamelXmlRestDslParserHelper.java @@ -24,6 +24,8 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.apache.camel.parser.model.RestConfigurationDetails; +import org.apache.camel.parser.model.RestServiceDetails; +import org.apache.camel.parser.model.RestVerbDetails; public final class CamelXmlRestDslParserHelper { @@ -39,6 +41,18 @@ public final class CamelXmlRestDslParserHelper { return answer; } + public List<RestServiceDetails> parseRestService(Node xmlNode, String baseDir, String fullyQualifiedFileName) { + + List<RestServiceDetails> answer = new ArrayList<>(); + + RestServiceDetails detail = new RestServiceDetails(); + detail.setFileName(fullyQualifiedFileName); + walkXmlTree(xmlNode, detail); + answer.add(detail); + + return answer; + } + private void walkXmlTree(Node xmlNode, RestConfigurationDetails detail) { if ("restConfiguration".equals(xmlNode.getNodeName())) { String lineNumber = (String) xmlNode.getUserData(XmlLineNumberParser.LINE_NUMBER); @@ -130,6 +144,128 @@ public final class CamelXmlRestDslParserHelper { } } + private void walkXmlTree(Node xmlNode, RestServiceDetails detail) { + if ("rest".equals(xmlNode.getNodeName())) { + String lineNumber = (String) xmlNode.getUserData(XmlLineNumberParser.LINE_NUMBER); + String lineNumberEnd = (String) xmlNode.getUserData(XmlLineNumberParser.LINE_NUMBER_END); + detail.setLineNumber(lineNumber); + detail.setLineNumberEnd(lineNumberEnd); + extractAttributes(xmlNode, detail); + } + + if (isParentRest(xmlNode)) { + if ("delete".equals(xmlNode.getNodeName())) { + RestVerbDetails verb = new RestVerbDetails(); + verb.setMethod("delete"); + detail.addVerb(verb); + extractAttributes(xmlNode, verb); + } else if ("get".equals(xmlNode.getNodeName())) { + RestVerbDetails verb = new RestVerbDetails(); + verb.setMethod("get"); + detail.addVerb(verb); + extractAttributes(xmlNode, verb); + } else if ("head".equals(xmlNode.getNodeName())) { + RestVerbDetails verb = new RestVerbDetails(); + verb.setMethod("head"); + detail.addVerb(verb); + extractAttributes(xmlNode, verb); + } else if ("patch".equals(xmlNode.getNodeName())) { + RestVerbDetails verb = new RestVerbDetails(); + verb.setMethod("patch"); + detail.addVerb(verb); + extractAttributes(xmlNode, verb); + } else if ("post".equals(xmlNode.getNodeName())) { + RestVerbDetails verb = new RestVerbDetails(); + verb.setMethod("post"); + detail.addVerb(verb); + extractAttributes(xmlNode, verb); + } else if ("put".equals(xmlNode.getNodeName())) { + RestVerbDetails verb = new RestVerbDetails(); + verb.setMethod("put"); + detail.addVerb(verb); + extractAttributes(xmlNode, verb); + } + + if ("description".equals(xmlNode.getNodeName())) { + String value = xmlNode.getTextContent(); + RestVerbDetails verb = getLastVerb(detail); + if (verb != null) { + verb.setDescription(value); + } else { + detail.setDescription(value); + } + } else if ("to".equals(xmlNode.getNodeName())) { + NamedNodeMap map = xmlNode.getAttributes(); + String uri = extractAttribute(map, "uri"); + RestVerbDetails verb = getLastVerb(detail); + if (verb != null) { + verb.setTo(uri); + } + } else if ("toD".equals(xmlNode.getNodeName())) { + NamedNodeMap map = xmlNode.getAttributes(); + String uri = extractAttribute(map, "uri"); + RestVerbDetails verb = getLastVerb(detail); + if (verb != null) { + verb.setToD(uri); + } + } + } + + // walk the rest of the children + NodeList children = xmlNode.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + walkXmlTree(child, detail); + } + } + } + + private static void extractAttributes(Node xmlNode, RestServiceDetails detail) { + NamedNodeMap map = xmlNode.getAttributes(); + detail.setConsumes(extractAttribute(map, "consumes")); + detail.setProduces(extractAttribute(map, "produces")); + detail.setApiDocs(extractAttribute(map, "apiDocs")); + detail.setBindingMode(extractAttribute(map, "bindingMode")); + detail.setClientRequestValidation(extractAttribute(map, "clientRequestValidation")); + detail.setEnableCORS(extractAttribute(map, "enableCORS")); + detail.setPath(extractAttribute(map, "path")); + detail.setSkipBindingOnErrorCode(extractAttribute(map, "skipBindingOnErrorCode")); + detail.setTag(extractAttribute(map, "tag")); + } + + private static void extractAttributes(Node xmlNode, RestVerbDetails detail) { + NamedNodeMap map = xmlNode.getAttributes(); + detail.setUri(extractAttribute(map, "uri")); + detail.setConsumes(extractAttribute(map, "consumes")); + detail.setProduces(extractAttribute(map, "produces")); + detail.setApiDocs(extractAttribute(map, "apiDocs")); + detail.setBindingMode(extractAttribute(map, "bindingMode")); + detail.setClientRequestValidation(extractAttribute(map, "clientRequestValidation")); + detail.setSkipBindingOnErrorCode(extractAttribute(map, "skipBindingOnErrorCode")); + detail.setType(extractAttribute(map, "type")); + detail.setOutType(extractAttribute(map, "outType")); + } + + private static RestVerbDetails getLastVerb(RestServiceDetails detail) { + if (detail.getVerbs() == null) { + return null; + } + return detail.getVerbs().get(detail.getVerbs().size() - 1); + } + + private static boolean isParentRest(Node node) { + if (node == null) { + return false; + } + String name = node.getNodeName(); + if ("rest".equals(name)) { + return true; + } else { + return isParentRest(node.getParentNode()); + } + } + private static String extractAttribute(NamedNodeMap map, String name) { if (map != null) { Node attr = map.getNamedItem(name); diff --git a/tooling/camel-route-parser/src/test/java/org/apache/camel/parser/xml/XmlRestDslTest.java b/tooling/camel-route-parser/src/test/java/org/apache/camel/parser/xml/XmlRestDslTest.java index 6acc2c6..78e1156 100644 --- a/tooling/camel-route-parser/src/test/java/org/apache/camel/parser/xml/XmlRestDslTest.java +++ b/tooling/camel-route-parser/src/test/java/org/apache/camel/parser/xml/XmlRestDslTest.java @@ -16,12 +16,17 @@ */ package org.apache.camel.parser.xml; +import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.List; +import org.apache.camel.parser.RestDslParser; import org.apache.camel.parser.XmlRestDslParser; import org.apache.camel.parser.model.RestConfigurationDetails; +import org.apache.camel.parser.model.RestServiceDetails; +import org.jboss.forge.roaster.Roaster; +import org.jboss.forge.roaster.model.source.JavaClassSource; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -66,4 +71,41 @@ public class XmlRestDslTest { assertEquals("value2", details.getCorsHeaders().get("key2")); } + @Test + public void parseRestService() throws Exception { + InputStream is = new FileInputStream("src/test/resources/org/apache/camel/parser/xml/myrest.xml"); + String fqn = "src/test/resources/org/apache/camel/camel/parser/xml/myrest.xml"; + String baseDir = "src/test/resources"; + List<RestServiceDetails> list = XmlRestDslParser.parseRestService(is, baseDir, fqn); + + assertEquals(1, list.size()); + RestServiceDetails details = list.get(0); + assertEquals("src/test/resources/org/apache/camel/camel/parser/xml/myrest.xml", details.getFileName()); + assertNull(details.getMethodName()); + assertNull(details.getClassName()); + + assertEquals("37", details.getLineNumber()); + assertEquals("47", details.getLineNumberEnd()); + assertEquals("src/test/resources/org/apache/camel/camel/parser/xml/myrest.xml", details.getFileName()); + assertNull(details.getMethodName()); + assertNull(details.getClassName()); + + assertEquals("/foo", details.getPath()); + assertEquals("my foo service", details.getDescription()); + assertEquals("json", details.getProduces()); + assertEquals("json", details.getProduces()); + assertEquals(2, details.getVerbs().size()); + assertEquals("get", details.getVerbs().get(0).getMethod()); + assertEquals("{id}", details.getVerbs().get(0).getUri()); + assertEquals("get by id", details.getVerbs().get(0).getDescription()); + assertEquals("log:id", details.getVerbs().get(0).getTo()); + assertEquals("false", details.getVerbs().get(0).getApiDocs()); + assertEquals("post", details.getVerbs().get(1).getMethod()); + assertEquals("post something", details.getVerbs().get(1).getDescription()); + assertEquals("xml", details.getVerbs().get(1).getBindingMode()); + assertEquals("log:post", details.getVerbs().get(1).getToD()); + assertNull(details.getVerbs().get(1).getUri()); + } + + } diff --git a/tooling/camel-route-parser/src/test/resources/org/apache/camel/parser/xml/myrest.xml b/tooling/camel-route-parser/src/test/resources/org/apache/camel/parser/xml/myrest.xml index 370be9e..82f493a 100644 --- a/tooling/camel-route-parser/src/test/resources/org/apache/camel/parser/xml/myrest.xml +++ b/tooling/camel-route-parser/src/test/resources/org/apache/camel/parser/xml/myrest.xml @@ -33,6 +33,19 @@ <corsHeaders key="key1" value="value1"/> <corsHeaders key="key2" value="value2"/> </restConfiguration> + + <rest path="/foo" consumes="xml" produces="json"> + <description>my foo service</description> + <get uri="{id}" apiDocs="false"> + <description>get by id</description> + <to uri="log:id"/> + </get> + <post bindingMode="xml"> + <description>post something</description> + <toD uri="log:post"/> + </post> + </rest> + </camelContext> </beans>