This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit f5ce96c766db4885331e9a2b1940f158825ad626 Author: Claus Ibsen <[email protected]> AuthorDate: Tue Jun 1 10:13:44 2021 +0200 CAMEL-16664: camel-core - XML routes loader allow to load single route files also --- .../java/org/apache/camel/xml/in/ModelParser.java | 65 +++++++++++++++++++++- .../java/org/apache/camel/xml/in/BaseParser.java | 14 +++++ .../org/apache/camel/xml/in/ModelParserTest.java | 8 +-- .../nonamespace/singleRouteNoNamespace.xml | 22 ++------ .../packaging/ModelXmlParserGeneratorMojo.java | 35 +++++++++++- 5 files changed, 117 insertions(+), 27 deletions(-) diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java index 076fa12..c2421b8 100644 --- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java +++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java @@ -22,6 +22,8 @@ package org.apache.camel.xml.in; import java.io.IOException; import java.io.InputStream; import java.io.Reader; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import javax.annotation.Generated; import org.apache.camel.model.*; @@ -1078,7 +1080,26 @@ public class ModelParser extends BaseParser { } public Optional<RouteTemplatesDefinition> parseRouteTemplatesDefinition() throws IOException, XmlPullParserException { - return hasTag("routeTemplates") ? Optional.of(doParseRouteTemplatesDefinition()) : Optional.empty(); + String tag = getNextTag("routeTemplates", "routeTemplate"); + if (tag != null) { + switch (tag) { + case "routeTemplates" : return Optional.of(doParseRouteTemplatesDefinition()); + case "routeTemplate" : return parseSingleRouteTemplatesDefinition(); + } + } + return Optional.empty(); + } + private Optional<RouteTemplatesDefinition> parseSingleRouteTemplatesDefinition() + throws IOException, XmlPullParserException { + Optional<RouteTemplateDefinition> single = Optional.of(doParseRouteTemplateDefinition()); + if (single.isPresent()) { + List<RouteTemplateDefinition> list = new ArrayList<>(); + list.add(single.get()); + RouteTemplatesDefinition def = new RouteTemplatesDefinition(); + def.setRouteTemplates(list); + return Optional.of(def); + } + return Optional.empty(); } protected RouteTemplatesDefinition doParseRouteTemplatesDefinition() throws IOException, XmlPullParserException { return doParse(new RouteTemplatesDefinition(), @@ -1092,7 +1113,26 @@ public class ModelParser extends BaseParser { } public Optional<RoutesDefinition> parseRoutesDefinition() throws IOException, XmlPullParserException { - return hasTag("routes") ? Optional.of(doParseRoutesDefinition()) : Optional.empty(); + String tag = getNextTag("routes", "route"); + if (tag != null) { + switch (tag) { + case "routes" : return Optional.of(doParseRoutesDefinition()); + case "route" : return parseSingleRoutesDefinition(); + } + } + return Optional.empty(); + } + private Optional<RoutesDefinition> parseSingleRoutesDefinition() + throws IOException, XmlPullParserException { + Optional<RouteDefinition> single = Optional.of(doParseRouteDefinition()); + if (single.isPresent()) { + List<RouteDefinition> list = new ArrayList<>(); + list.add(single.get()); + RoutesDefinition def = new RoutesDefinition(); + def.setRoutes(list); + return Optional.of(def); + } + return Optional.empty(); } protected RoutesDefinition doParseRoutesDefinition() throws IOException, XmlPullParserException { return doParse(new RoutesDefinition(), @@ -2903,7 +2943,26 @@ public class ModelParser extends BaseParser { } public Optional<RestsDefinition> parseRestsDefinition() throws IOException, XmlPullParserException { - return hasTag("rests") ? Optional.of(doParseRestsDefinition()) : Optional.empty(); + String tag = getNextTag("rests", "rest"); + if (tag != null) { + switch (tag) { + case "rests" : return Optional.of(doParseRestsDefinition()); + case "rest" : return parseSingleRestsDefinition(); + } + } + return Optional.empty(); + } + private Optional<RestsDefinition> parseSingleRestsDefinition() + throws IOException, XmlPullParserException { + Optional<RestDefinition> single = Optional.of(doParseRestDefinition()); + if (single.isPresent()) { + List<RestDefinition> list = new ArrayList<>(); + list.add(single.get()); + RestsDefinition def = new RestsDefinition(); + def.setRests(list); + return Optional.of(def); + } + return Optional.empty(); } protected RestsDefinition doParseRestsDefinition() throws IOException, XmlPullParserException { return doParse(new RestsDefinition(), diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java index f89e633..639c13c 100644 --- a/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java +++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java @@ -218,6 +218,20 @@ public class BaseParser { return true; } + protected String getNextTag(String name, String name2) throws XmlPullParserException, IOException { + if (parser.nextTag() != XmlPullParser.START_TAG) { + throw new XmlPullParserException("Expected starting tag"); + } + + String pn = parser.getName(); + boolean match = Objects.equals(name, pn) || Objects.equals(name2, pn); + if (!match || !Objects.equals(namespace, parser.getNamespace())) { + return ""; // empty tag + } + + return pn; + } + @SuppressWarnings("unchecked") protected void handleOtherAttribute(Object definition, String name, String ns, String val) throws XmlPullParserException { // Ignore diff --git a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java index 4ff5185..fa80a30 100644 --- a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java +++ b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java @@ -32,7 +32,6 @@ import org.apache.camel.model.RoutesDefinition; import org.apache.camel.model.SetBodyDefinition; import org.apache.camel.model.language.XPathExpression; import org.apache.camel.model.rest.RestsDefinition; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -54,11 +53,10 @@ public class ModelParserTest { } @Test - @Disabled - public void testDefaultNamespace() throws Exception { + public void testSingleRouteNoNamespace() throws Exception { Path dir = getResourceFolder(); - Path path = new File(dir.toFile(), "nonamespace/routeNoNamespace.xml").toPath(); - ModelParser parser = new ModelParser(Files.newInputStream(path), NAMESPACE); + Path path = new File(dir.toFile(), "nonamespace/singleRouteNoNamespace.xml").toPath(); + ModelParser parser = new ModelParser(Files.newInputStream(path)); RoutesDefinition routes = parser.parseRoutesDefinition().orElse(null); assertNotNull(routes); } diff --git a/core/camel-xml-io/src/test/resources/nonamespace/singleRouteNoNamespace.xml b/core/camel-xml-io/src/test/resources/nonamespace/singleRouteNoNamespace.xml index 196cc24..0e331af 100644 --- a/core/camel-xml-io/src/test/resources/nonamespace/singleRouteNoNamespace.xml +++ b/core/camel-xml-io/src/test/resources/nonamespace/singleRouteNoNamespace.xml @@ -17,21 +17,7 @@ limitations under the License. --> -<routes id="camel"> - <route> - <from uri="seda:a"/> - <choice> - <when> - <simple>${header.foo} == 'bar'</simple> - <to uri="seda:b"/> - </when> - <when> - <ognl>header[foo] == 'cheese'</ognl> - <to uri="seda:c"/> - </when> - <otherwise> - <to uri="seda:d"/> - </otherwise> - </choice> - </route> -</routes> +<route id="route-b"> + <from uri="seda:b"/> + <to uri="mock:b"/> +</route> diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelXmlParserGeneratorMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelXmlParserGeneratorMojo.java index 16c4b05..bfc4cece 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelXmlParserGeneratorMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelXmlParserGeneratorMojo.java @@ -215,6 +215,8 @@ public class ModelXmlParserGeneratorMojo extends AbstractGeneratorMojo { parser.addImport(IOException.class); parser.addImport(XML_PULL_PARSER_EXCEPTION); parser.addImport(Array.class); + parser.addImport(List.class); + parser.addImport(ArrayList.class); parser.addAnnotation(SuppressWarnings.class).setLiteralValue("\"unused\""); parser.addAnnotation(Generated.class).setLiteralValue("\"" + getClass().getName() + "\""); parser.addMethod().setConstructor(true).setPublic().setName("ModelParser").addParameter(InputStream.class, "input").addThrows(IOException.class) @@ -475,14 +477,45 @@ public class ModelXmlParserGeneratorMojo extends AbstractGeneratorMojo { return " noValueHandler()"; }); if (clazz == routesDefinitionClass || clazz == routeTemplatesDefinitionClass || clazz == restsDefinitionClass) { + + // for routes/rests/routeTemplates we want to support single-mode as well, this means + // we check that the tag name is either plural or singular and parse accordingly + String element = clazz.getAnnotation(XmlRootElement.class).name(); + String capitalElement = Character.toUpperCase(element.charAt(0)) + element.substring(1); + String singleElement = element.endsWith("s") ? element.substring(0, element.length() - 1) : element; + String singleName = name.replace("sDefinition", "Definition"); + parser.addMethod().setPublic() .setReturnType(new GenericType(Optional.class, new GenericType(clazz))) .setName("parse" + name) .addThrows(IOException.class) .addThrows(XML_PULL_PARSER_EXCEPTION) - .setBodyF("return hasTag(\"%s\") ? Optional.of(doParse%s()) : Optional.empty();", element, name); + .setBody(String.format("String tag = getNextTag(\"%s\", \"%s\");", element, singleElement), + "if (tag != null) {", + " switch (tag) {", + String.format(" case \"%s\" : return Optional.of(doParse%s());", element, name), + String.format(" case \"%s\" : return parseSingle%s();", singleElement, name), + " }", + "}", + "return Optional.empty();"); + + parser.addMethod().setPrivate() + .setReturnType(new GenericType(Optional.class, new GenericType(clazz))) + .setName("parseSingle" + name) + .addThrows(IOException.class) + .addThrows(XML_PULL_PARSER_EXCEPTION) + .setBody(String.format("Optional<%s> single = Optional.of(doParse%s());", singleName, singleName), + "if (single.isPresent()) {", + String.format(" List<%s> list = new ArrayList<>();", singleName), + " list.add(single.get());", + String.format(" %s def = new %s();", name, name), + String.format(" def.set%s(list);", capitalElement), + " return Optional.of(def);", + "}", + "return Optional.empty();"); } + if (hasDerived) { if (!attributeMembers.isEmpty()) { parser.addMethod().setSignature("protected <T extends " + qname + "> AttributeHandler<T> " + lowercase(name) + "AttributeHandler()")
