CAMEL-8369: weaveAddLast should add last to the route, which is after the first 
level nodes only. Added maxDeep option to the weaver to limit how far down the 
rabbit hole we look. Thanks to Chris Pimlott for the unit test.


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

Branch: refs/heads/camel-2.14.x
Commit: b63525df0ee7048f94fe797e07ce9861001cdd19
Parents: 66be276
Author: Claus Ibsen <davscl...@apache.org>
Authored: Wed Feb 18 08:50:14 2015 +0100
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Wed Feb 18 09:39:09 2015 +0100

----------------------------------------------------------------------
 .../apache/camel/builder/AdviceWithBuilder.java | 44 ++++++++++-----
 .../camel/builder/AdviceWithRouteBuilder.java   |  2 +-
 .../apache/camel/builder/AdviceWithTasks.java   | 55 +++++++++----------
 .../camel/model/ProcessorDefinitionHelper.java  | 56 ++++++++++++++++----
 .../AdviceWithWeaveAfterLastSplitTest.java      | 56 ++++++++++++++++++++
 5 files changed, 162 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/b63525df/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java 
b/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java
index e86f411..b89ffa5 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java
@@ -33,6 +33,7 @@ public class AdviceWithBuilder<T extends 
ProcessorDefinition<?>> {
     private boolean selectLast;
     private int selectFrom = -1;
     private int selectTo = -1;
+    private int maxDeep = -1;
 
     public AdviceWithBuilder(AdviceWithRouteBuilder builder, String id, String 
toString, Class<T> type) {
         this.builder = builder;
@@ -102,6 +103,25 @@ public class AdviceWithBuilder<T extends 
ProcessorDefinition<?>> {
     }
 
     /**
+     * Will only apply for nodes maximum levels deep.
+     * <p/>
+     * The first level is <tt>1</tt>, and level <tt>2</tt> is the children of 
the the first level nodes, and so on.
+     * <p/>
+     * Use zero or negative value for unbounded level.
+     *
+     * @param maxDeep the maximum levels to traverse deep in the Camel route 
tree.
+     * @return the builder to build the nodes.
+     */
+    public AdviceWithBuilder<T> maxDeep(int maxDeep) {
+        if (maxDeep == 0) {
+            // disable it
+            this.maxDeep = -1;
+        }
+        this.maxDeep = maxDeep;
+        return this;
+    }
+
+    /**
      * Replaces the matched node(s) with the following nodes.
      *
      * @return the builder to build the nodes.
@@ -110,11 +130,11 @@ public class AdviceWithBuilder<T extends 
ProcessorDefinition<?>> {
         RouteDefinition route = builder.getOriginalRoute();
         PipelineDefinition answer = new PipelineDefinition();
         if (id != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceById(route, id, answer, 
selectFirst, selectLast, selectFrom, selectTo));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceById(route, id, answer, 
selectFirst, selectLast, selectFrom, selectTo, maxDeep));
         } else if (toString != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceByToString(route, 
toString, answer, selectFirst, selectLast, selectFrom, selectTo));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceByToString(route, 
toString, answer, selectFirst, selectLast, selectFrom, selectTo, maxDeep));
         } else if (type != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceByType(route, type, 
answer, selectFirst, selectLast, selectFrom, selectTo));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceByType(route, type, 
answer, selectFirst, selectLast, selectFrom, selectTo, maxDeep));
         }
         return answer;
     }
@@ -125,11 +145,11 @@ public class AdviceWithBuilder<T extends 
ProcessorDefinition<?>> {
     public void remove() {
         RouteDefinition route = builder.getOriginalRoute();
         if (id != null) {
-            builder.getAdviceWithTasks().add(AdviceWithTasks.removeById(route, 
id, selectFirst, selectLast, selectFrom, selectTo));
+            builder.getAdviceWithTasks().add(AdviceWithTasks.removeById(route, 
id, selectFirst, selectLast, selectFrom, selectTo, maxDeep));
         } else if (toString != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.removeByToString(route, 
toString, selectLast, selectFirst, selectFrom, selectTo));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.removeByToString(route, 
toString, selectLast, selectFirst, selectFrom, selectTo, maxDeep));
         } else if (type != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.removeByType(route, type, 
selectFirst, selectFirst, selectFrom, selectTo));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.removeByType(route, type, 
selectFirst, selectFirst, selectFrom, selectTo, maxDeep));
         }
     }
 
@@ -142,11 +162,11 @@ public class AdviceWithBuilder<T extends 
ProcessorDefinition<?>> {
         RouteDefinition route = builder.getOriginalRoute();
         PipelineDefinition answer = new PipelineDefinition();
         if (id != null) {
-            builder.getAdviceWithTasks().add(AdviceWithTasks.beforeById(route, 
id, answer, selectFirst, selectLast, selectFrom, selectTo));
+            builder.getAdviceWithTasks().add(AdviceWithTasks.beforeById(route, 
id, answer, selectFirst, selectLast, selectFrom, selectTo, maxDeep));
         } else if (toString != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.beforeByToString(route, 
toString, answer, selectLast, selectFirst, selectFrom, selectTo));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.beforeByToString(route, 
toString, answer, selectLast, selectFirst, selectFrom, selectTo, maxDeep));
         } else if (type != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.beforeByType(route, type, 
answer, selectFirst, selectLast, selectFrom, selectTo));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.beforeByType(route, type, 
answer, selectFirst, selectLast, selectFrom, selectTo, maxDeep));
         }
         return answer;
     }
@@ -160,11 +180,11 @@ public class AdviceWithBuilder<T extends 
ProcessorDefinition<?>> {
         RouteDefinition route = builder.getOriginalRoute();
         PipelineDefinition answer = new PipelineDefinition();
         if (id != null) {
-            builder.getAdviceWithTasks().add(AdviceWithTasks.afterById(route, 
id, answer, selectFirst, selectLast, selectFrom, selectTo));
+            builder.getAdviceWithTasks().add(AdviceWithTasks.afterById(route, 
id, answer, selectFirst, selectLast, selectFrom, selectTo, maxDeep));
         } else if (toString != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.afterByToString(route, 
toString, answer, selectLast, selectFirst, selectFrom, selectTo));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.afterByToString(route, 
toString, answer, selectLast, selectFirst, selectFrom, selectTo, maxDeep));
         } else if (type != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.afterByType(route, type, 
answer, selectFirst, selectLast, selectFrom, selectTo));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.afterByType(route, type, 
answer, selectFirst, selectLast, selectFrom, selectTo, maxDeep));
         }
         return answer;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/b63525df/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java 
b/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java
index 205ff44..df80247 100644
--- 
a/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java
+++ 
b/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java
@@ -179,7 +179,7 @@ public abstract class AdviceWithRouteBuilder extends 
RouteBuilder {
      */
     public <T extends ProcessorDefinition<?>> ProcessorDefinition<?> 
weaveAddLast() {
         ObjectHelper.notNull(originalRoute, "originalRoute", this);
-        return new AdviceWithBuilder<T>(this, "*", null, 
null).selectLast().after();
+        return new AdviceWithBuilder<T>(this, "*", null, 
null).maxDeep(1).selectLast().after();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/b63525df/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java 
b/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
index 311f9b2..23690a1 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
@@ -115,23 +115,23 @@ public final class AdviceWithTasks {
     }
 
     public static AdviceWithTask replaceByToString(final RouteDefinition 
route, final String toString, final ProcessorDefinition<?> replace,
-                                                   boolean selectFirst, 
boolean selectLast, int selectFrom, int selectTo) {
+                                                   boolean selectFirst, 
boolean selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchByToString(toString);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doReplace(route, new MatchByToString(toString), replace, it);
     }
 
     public static AdviceWithTask replaceById(final RouteDefinition route, 
final String id, final ProcessorDefinition<?> replace,
-                                             boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                             boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchById(id);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doReplace(route, matchBy, replace, it);
     }
 
     public static AdviceWithTask replaceByType(final RouteDefinition route, 
final Class<?> type, final ProcessorDefinition<?> replace,
-                                               boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                               boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchByType(type);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doReplace(route, matchBy, replace, it);
     }
 
@@ -164,23 +164,23 @@ public final class AdviceWithTasks {
     }
 
     public static AdviceWithTask removeByToString(final RouteDefinition route, 
final String toString,
-                                                  boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                                  boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchByToString(toString);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doRemove(route, matchBy, it);
     }
 
     public static AdviceWithTask removeById(final RouteDefinition route, final 
String id,
-                                            boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                            boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchById(id);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doRemove(route, matchBy, it);
     }
 
     public static AdviceWithTask removeByType(final RouteDefinition route, 
final Class<?> type,
-                                              boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                              boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchByType(type);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doRemove(route, matchBy, it);
     }
 
@@ -212,23 +212,23 @@ public final class AdviceWithTasks {
     }
 
     public static AdviceWithTask beforeByToString(final RouteDefinition route, 
final String toString, final ProcessorDefinition<?> before,
-                                                  boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                                  boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchByToString(toString);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doBefore(route, matchBy, before, it);
     }
 
     public static AdviceWithTask beforeById(final RouteDefinition route, final 
String id, final ProcessorDefinition<?> before,
-                                            boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                            boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchById(id);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doBefore(route, matchBy, before, it);
     }
 
     public static AdviceWithTask beforeByType(final RouteDefinition route, 
final Class<?> type, final ProcessorDefinition<?> before,
-                                              boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                              boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchByType(type);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doBefore(route, matchBy, before, it);
     }
 
@@ -261,23 +261,23 @@ public final class AdviceWithTasks {
     }
 
     public static AdviceWithTask afterByToString(final RouteDefinition route, 
final String toString, final ProcessorDefinition<?> after,
-                                                 boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                                 boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchByToString(toString);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doAfter(route, matchBy, after, it);
     }
 
     public static AdviceWithTask afterById(final RouteDefinition route, final 
String id, final ProcessorDefinition<?> after,
-                                           boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                           boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchById(id);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doAfter(route, matchBy, after, it);
     }
 
     public static AdviceWithTask afterByType(final RouteDefinition route, 
final Class<?> type, final ProcessorDefinition<?> after,
-                                             boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+                                             boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo, int maxDeep) {
         MatchBy matchBy = new MatchByType(type);
-        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        Iterator<ProcessorDefinition<?>> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo, maxDeep);
         return doAfter(route, matchBy, after, it);
     }
 
@@ -362,18 +362,19 @@ public final class AdviceWithTasks {
      * @param selectLast   optional to select only the last
      * @param selectFrom   optional to select index/range
      * @param selectTo     optional to select index/range
-     * 
+     * @param maxDeep      maximum levels deep (is unbounded by default)
+     *
      * @return the iterator
      */
     private static Iterator<ProcessorDefinition<?>> 
createMatchByIterator(final RouteDefinition route, final MatchBy matchBy,
                                                                final boolean 
selectFirst, final boolean selectLast,
-                                                               final int 
selectFrom, final int selectTo) {
+                                                               final int 
selectFrom, final int selectTo, int maxDeep) {
 
         // first iterator and apply match by
         List<ProcessorDefinition<?>> matched = new 
ArrayList<ProcessorDefinition<?>>();
 
         @SuppressWarnings("rawtypes")
-        Iterator<ProcessorDefinition> itAll = 
ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), 
ProcessorDefinition.class);
+        Iterator<ProcessorDefinition> itAll = 
ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), 
ProcessorDefinition.class, maxDeep);
         while (itAll.hasNext()) {
             ProcessorDefinition<?> next = itAll.next();
             if (matchBy.match(next)) {

http://git-wip-us.apache.org/repos/asf/camel/blob/b63525df/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
 
b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
index 71ecbbe..acb618a 100644
--- 
a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
+++ 
b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
@@ -55,8 +55,20 @@ public final class ProcessorDefinitionHelper {
      * @return         the found definitions, or <tt>null</tt> if not found
      */
     public static <T> Iterator<T> 
filterTypeInOutputs(List<ProcessorDefinition<?>> outputs, Class<T> type) {
+        return filterTypeInOutputs(outputs, type, -1);
+    }
+
+    /**
+     * Looks for the given type in the list of outputs and recurring all the 
children as well.
+     *
+     * @param outputs  list of outputs, can be null or empty.
+     * @param type     the type to look for
+     * @param maxDeep  maximum levels deep to traverse
+     * @return         the found definitions, or <tt>null</tt> if not found
+     */
+    public static <T> Iterator<T> 
filterTypeInOutputs(List<ProcessorDefinition<?>> outputs, Class<T> type, int 
maxDeep) {
         List<T> found = new ArrayList<T>();
-        doFindType(outputs, type, found);
+        doFindType(outputs, type, found, maxDeep);
         return found.iterator();
     }
 
@@ -70,7 +82,7 @@ public final class ProcessorDefinitionHelper {
      */
     public static <T> T findFirstTypeInOutputs(List<ProcessorDefinition<?>> 
outputs, Class<T> type) {
         List<T> found = new ArrayList<T>();
-        doFindType(outputs, type, found);
+        doFindType(outputs, type, found, -1);
         if (found.isEmpty()) {
             return null;
         }
@@ -202,19 +214,41 @@ public final class ProcessorDefinitionHelper {
         return set;
     }
 
+    private static <T> void doFindType(List<ProcessorDefinition<?>> outputs, 
Class<T> type, List<T> found, int maxDeep) {
+
+        // do we have any top level abstracts, then we should max deep one 
more level down
+        // as that is really what we want to traverse as well
+        if (maxDeep > 0) {
+            for (ProcessorDefinition<?> out : outputs) {
+                if (out.isAbstract() && out.isTopLevelOnly()) {
+                    maxDeep = maxDeep + 1;
+                    break;
+                }
+            }
+        }
+
+        // start from level 1
+        doFindType(outputs, type, found, 1, maxDeep);
+    }
+
     @SuppressWarnings({"unchecked", "rawtypes"})
-    private static <T> void doFindType(List<ProcessorDefinition<?>> outputs, 
Class<T> type, List<T> found) {
+    private static <T> void doFindType(List<ProcessorDefinition<?>> outputs, 
Class<T> type, List<T> found, int current, int maxDeep) {
         if (outputs == null || outputs.isEmpty()) {
             return;
         }
 
+        // break out
+        if (maxDeep > 0 && current > maxDeep) {
+            return;
+        }
+
         for (ProcessorDefinition out : outputs) {
 
             // send is much common
             if (out instanceof SendDefinition) {
                 SendDefinition send = (SendDefinition) out;
                 List<ProcessorDefinition<?>> children = send.getOutputs();
-                doFindType(children, type, found);
+                doFindType(children, type, found, ++current, maxDeep);
             }
 
             // special for choice
@@ -231,13 +265,13 @@ public final class ProcessorDefinitionHelper {
                         found.add((T)when);   
                     }
                     List<ProcessorDefinition<?>> children = when.getOutputs();
-                    doFindType(children, type, found);
+                    doFindType(children, type, found, ++current, maxDeep);
                 }
 
                 // otherwise is optional
                 if (choice.getOtherwise() != null) {
                     List<ProcessorDefinition<?>> children = 
choice.getOtherwise().getOutputs();
-                    doFindType(children, type, found);
+                    doFindType(children, type, found, ++current, maxDeep);
                 }
 
                 // do not check children as we already did that
@@ -254,15 +288,15 @@ public final class ProcessorDefinitionHelper {
                 }
 
                 List<ProcessorDefinition<?>> doTryOut = 
doTry.getOutputsWithoutCatches();
-                doFindType(doTryOut, type, found);
+                doFindType(doTryOut, type, found, ++current, maxDeep);
 
                 List<CatchDefinition> doTryCatch = doTry.getCatchClauses();
                 for (CatchDefinition doCatch : doTryCatch) {
-                    doFindType(doCatch.getOutputs(), type, found);
+                    doFindType(doCatch.getOutputs(), type, found, ++current, 
maxDeep);
                 }
 
                 if (doTry.getFinallyClause() != null) {
-                    doFindType(doTry.getFinallyClause().getOutputs(), type, 
found);
+                    doFindType(doTry.getFinallyClause().getOutputs(), type, 
found, ++current, maxDeep);
                 }
 
                 // do not check children as we already did that
@@ -279,7 +313,7 @@ public final class ProcessorDefinitionHelper {
                 }
 
                 List<ProcessorDefinition<?>> outDefOut = outDef.getOutputs();
-                doFindType(outDefOut, type, found);
+                doFindType(outDefOut, type, found, ++current, maxDeep);
 
                 // do not check children as we already did that
                 continue;
@@ -291,7 +325,7 @@ public final class ProcessorDefinitionHelper {
 
             // try children as well
             List<ProcessorDefinition<?>> children = out.getOutputs();
-            doFindType(children, type, found);
+            doFindType(children, type, found, ++current, maxDeep);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/b63525df/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveAfterLastSplitTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveAfterLastSplitTest.java
 
b/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveAfterLastSplitTest.java
new file mode 100644
index 0000000..f94b13d
--- /dev/null
+++ 
b/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveAfterLastSplitTest.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.camel.processor.interceptor;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+
+/**
+ * Advice with tests
+ */
+public class AdviceWithWeaveAfterLastSplitTest extends ContextTestSupport {
+
+    public void testAfterLastSplit() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                weaveAddLast().log("weaveAddLast: ${body}").to("mock:result");
+            }
+        });
+        context.start();
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:input", "1,2");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:input").split(body(String.class).tokenize(",")).log("within split: 
${body}").end();
+            }
+        };
+    }
+
+}
\ No newline at end of file

Reply via email to