CAMEL-10344: RouteIdFactory for rest routes

Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/b0025751
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/b0025751
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/b0025751

Branch: refs/heads/master
Commit: b0025751386f59e7020ebd5cc19b9580eb477f46
Parents: 0da9713
Author: Tomasz Kopczynski <to...@kopczynski.net.pl>
Authored: Sun Nov 27 20:05:49 2016 +0100
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Thu Dec 1 12:23:22 2016 +0100

----------------------------------------------------------------------
 .../org/apache/camel/impl/RouteIdFactory.java   | 126 ++++++++++++++++---
 .../apache/camel/model/rest/RestDefinition.java |   8 +-
 .../apache/camel/model/rest/VerbDefinition.java |  10 +-
 .../apache/camel/impl/RouteIdFactoryTest.java   |  15 +++
 4 files changed, 143 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/b0025751/camel-core/src/main/java/org/apache/camel/impl/RouteIdFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/RouteIdFactory.java 
b/camel-core/src/main/java/org/apache/camel/impl/RouteIdFactory.java
index 5fdb51c..06044ea 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/RouteIdFactory.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/RouteIdFactory.java
@@ -22,20 +22,22 @@ import java.util.Optional;
 import org.apache.camel.NamedNode;
 import org.apache.camel.model.FromDefinition;
 import org.apache.camel.model.RouteDefinition;
-import org.apache.camel.model.rest.RestBindingDefinition;
+import org.apache.camel.model.rest.RestDefinition;
+import org.apache.camel.model.rest.VerbDefinition;
 import org.apache.camel.spi.NodeIdFactory;
 
 /**
  * Factory for generating route ids based on uris.
  * <p>
  * For direct/seda routes it returns route name (direct:start -> start).
- * For rest routes it returns its context path.
+ * For rest routes it returns its method and context path formatted as one 
string.
  * <p>
  * When id cannot be generated, falls back to other {@link NodeIdFactory} 
implementation.
  * If none is passed in the constructor, then {@link DefaultNodeIdFactory} is 
used.
  */
 public class RouteIdFactory implements NodeIdFactory {
 
+    private static final char SEPARATOR = '-';
     private NodeIdFactory defaultNodeIdFactory;
 
     public RouteIdFactory() {
@@ -62,6 +64,14 @@ public class RouteIdFactory implements NodeIdFactory {
             }
         }
 
+        if (definition instanceof VerbDefinition) {
+            Optional<String> id = extractIdFromVerb((VerbDefinition) 
definition);
+
+            if (id.isPresent()) {
+                return id.get();
+            }
+        }
+
         return defaultNodeIdFactory.createId(definition);
     }
 
@@ -69,6 +79,10 @@ public class RouteIdFactory implements NodeIdFactory {
      * Extract id from routes
      */
     private Optional<String> extractId(RouteDefinition routeDefinition) {
+        if (routeDefinition.getRestDefinition() != null) {
+            return Optional.empty();
+        }
+
         List<FromDefinition> inputs = routeDefinition.getInputs();
 
         if (inputs == null || inputs.isEmpty()) {
@@ -97,27 +111,111 @@ public class RouteIdFactory implements NodeIdFactory {
     }
 
     /**
-     * Extract id from rest route.
+     * Extract id from a rest route.
      */
     private Optional<String> extractIdFromRestDefinition(RouteDefinition 
route) {
-        if (route.getOutputs().get(0) instanceof RestBindingDefinition) {
-            if (route.getRestDefinition() == null) {
-                return Optional.empty();
-            }
+        if (route.getRestDefinition() != null) {
+            return extractIdFromInput(route);
+        }
 
-            String path = route.getRestDefinition().getPath();
+        return Optional.empty();
+    }
 
-            if (path == null) {
-                return Optional.empty();
-            }
+    /**
+     * Extract id from a rest verb definition.
+     */
+    private Optional<String> extractIdFromVerb(VerbDefinition verb) {
+        RestDefinition restDefinition = verb.getRest();
+
+        if (restDefinition != null) {
+            StringBuilder routeId = new StringBuilder();
+            routeId.append(verb.asVerb());
+            appendWithSeparator(routeId, prepareUri(restDefinition.getPath()));
 
-            if (path.indexOf('/') > 0) {
-                return Optional.of(path.substring(0, path.indexOf('/')));
+            if (verb.getUri() != null && verb.getUri().length() > 0) {
+                appendWithSeparator(routeId, prepareUri(verb.getUri()));
             }
 
-            return Optional.of(path);
+            verb.setUsedForGeneratingNodeId(true);
+
+            return Optional.of(routeId.toString());
         }
 
         return Optional.empty();
+
+    }
+
+    /**
+     * Extract id from rest input uri.
+     */
+    private Optional<String> extractIdFromInput(RouteDefinition route) {
+        List<FromDefinition> inputs = route.getInputs();
+
+        if (inputs == null || inputs.isEmpty()) {
+            return Optional.empty();
+        }
+
+        FromDefinition from = inputs.get(0);
+        String uri = from.getUri();
+
+        String[] uriSplitted = uri.split(":");
+
+        // needs to have at least 3 fields
+        if (uriSplitted.length < 3) {
+            return Optional.empty();
+        }
+
+        String verb = uriSplitted[1];
+        String contextPath = uriSplitted[2];
+        String additionalUri = "";
+
+        if (uriSplitted.length > 3 && uriSplitted[3].startsWith("/")) {
+            additionalUri = uriSplitted[3];
+        }
+
+        StringBuilder routeId = new StringBuilder(verb.length() + 
contextPath.length() + additionalUri.length());
+
+        routeId.append(verb);
+        appendWithSeparator(routeId, prepareUri(contextPath));
+
+        if (additionalUri.length() > 0) {
+            appendWithSeparator(routeId, prepareUri(additionalUri));
+        }
+
+        return Optional.of(routeId.toString());
+    }
+
+    /**
+     * Prepares uri to be part of the id.
+     */
+    private String prepareUri(String uri) {
+        if (uri == null) {
+            return "";
+        }
+
+        if (uri.contains("?")) {
+            uri = uri.substring(0, uri.indexOf('?'));
+        }
+
+        return uri.replaceAll("/", String.valueOf(SEPARATOR));
+    }
+
+    /**
+     * Appends new element to the builder.
+     */
+    private void appendWithSeparator(StringBuilder builder, String str) {
+        if (builder.charAt(builder.length() - 1) == SEPARATOR) {
+            if (str.startsWith(String.valueOf(SEPARATOR))) {
+                builder.append(str.replaceFirst(String.valueOf(SEPARATOR), 
""));
+            } else {
+                builder.append(str);
+            }
+        } else {
+            if (!str.startsWith(String.valueOf(SEPARATOR))) {
+                builder.append(SEPARATOR);
+            }
+
+            builder.append(str);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/b0025751/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java 
b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index c7ba4b8..68deb66 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -772,7 +772,13 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
                     route.setId(id);
                 }
             }
-            String routeId = route.idOrCreate(camelContext.getNodeIdFactory());
+
+            String routeId = verb.idOrCreate(camelContext.getNodeIdFactory());
+
+            if (!verb.getUsedForGeneratingNodeId()) {
+                routeId = route.idOrCreate(camelContext.getNodeIdFactory());
+            }
+
             verb.setRouteId(routeId);
             options.put("routeId", routeId);
             if (component != null && !component.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/camel/blob/b0025751/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java 
b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
index be27799..cc6731e 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
@@ -101,6 +101,9 @@ public class VerbDefinition extends 
OptionalIdentifiedDefinition<VerbDefinition>
     @XmlAttribute
     private Boolean apiDocs;
 
+    @XmlTransient
+    private Boolean usedForGeneratingNodeId = Boolean.FALSE;
+
     @Override
     public String getLabel() {
         if (method != null) {
@@ -406,6 +409,11 @@ public class VerbDefinition extends 
OptionalIdentifiedDefinition<VerbDefinition>
         }
     }
 
+    public Boolean getUsedForGeneratingNodeId() {
+        return usedForGeneratingNodeId;
+    }
 
-
+    public void setUsedForGeneratingNodeId(Boolean usedForGeneratingNodeId) {
+        this.usedForGeneratingNodeId = usedForGeneratingNodeId;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/b0025751/camel-core/src/test/java/org/apache/camel/impl/RouteIdFactoryTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/impl/RouteIdFactoryTest.java 
b/camel-core/src/test/java/org/apache/camel/impl/RouteIdFactoryTest.java
index d6ecb71..c74ea06 100644
--- a/camel-core/src/test/java/org/apache/camel/impl/RouteIdFactoryTest.java
+++ b/camel-core/src/test/java/org/apache/camel/impl/RouteIdFactoryTest.java
@@ -39,6 +39,9 @@ public class RouteIdFactoryTest extends ContextTestSupport {
                 context.setNodeIdFactory(new RouteIdFactory());
                 from("direct:start1?timeout=30000").to("mock:result");
                 from("direct:start2").to("mock:result");
+                rest("/say/hello").get("/bar").to("mock:result");
+                rest("/say/hello").get().to("mock:result");
+                rest().get("/hello").to("mock:result");
             }
         };
     }
@@ -51,4 +54,16 @@ public class RouteIdFactoryTest extends ContextTestSupport {
         assertEquals("start2", context.getRouteDefinitions().get(1).getId());
     }
 
+    public void testRestRouteIdWithVerbUri() {
+        assertEquals("get-say-hello-bar", 
context.getRouteDefinitions().get(2).getId());
+    }
+
+    public void testRestRouteIdWithoutVerbUri() {
+        assertEquals("get-say-hello", 
context.getRouteDefinitions().get(3).getId());
+    }
+
+    public void testRestRouteIdWithoutPathUri() {
+        assertEquals("get-hello", 
context.getRouteDefinitions().get(4).getId());
+    }
+
 }
\ No newline at end of file

Reply via email to