Author: davsclaus
Date: Tue May 10 11:35:30 2011
New Revision: 1101412

URL: http://svn.apache.org/viewvc?rev=1101412&view=rev
Log:
CAMEL-3958: advice with now supports selectors and addFirst/addLast to easily 
add some additional nodes to a given route. To be used with unit testing.

Added:
    
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksSelectTest.java
      - copied, changed from r1101352, 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksMatchTest.java
    
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveFirstLastTest.java
   (contents, props changed)
      - copied, changed from r1101352, 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksTest.java
Modified:
    
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
    
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TracingTestBase.java

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java?rev=1101412&r1=1101411&r2=1101412&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithBuilder.java
 Tue May 10 11:35:30 2011
@@ -18,6 +18,7 @@ package org.apache.camel.builder;
 
 import org.apache.camel.model.PipelineDefinition;
 import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.RouteDefinition;
 
 /**
  * A builder when using the <a 
href="http://camel.apache.org/advicewith.html";>advice with</a> feature.
@@ -28,6 +29,10 @@ public class AdviceWithBuilder<T extends
     private final String id;
     private final String toString;
     private final Class<T> type;
+    private boolean selectFirst;
+    private boolean selectLast;
+    private int selectFrom = -1;
+    private int selectTo = -1;
 
     public AdviceWithBuilder(AdviceWithRouteBuilder builder, String id, String 
toString, Class<T> type) {
         this.builder = builder;
@@ -41,18 +46,75 @@ public class AdviceWithBuilder<T extends
     }
 
     /**
+     * Will only apply the first node matched.
+     *
+     * @return the builder to build the nodes.
+     */
+    public AdviceWithBuilder<T> selectFirst() {
+        selectFirst = true;
+        selectLast = false;
+        return this;
+    }
+
+    /**
+     * Will only apply the last node matched.
+     *
+     * @return the builder to build the nodes.
+     */
+    public AdviceWithBuilder<T> selectLast() {
+        selectLast = true;
+        selectFirst = false;
+        return this;
+    }
+
+    /**
+     * Will only apply the n'th node matched.
+     *
+     * @param index index of node to match (is 0-based)
+     * @return the builder to build the nodes.
+     */
+    public AdviceWithBuilder<T> selectIndex(int index) {
+        if (index < 0) {
+            throw new IllegalArgumentException("Index must be a non negative 
number, was: " + index);
+        }
+        selectFrom = index;
+        selectTo = index;
+        return this;
+    }
+
+    /**
+     * Will only apply the node in the index range matched.
+     *
+     * @param from from index of node to start matching (inclusive)
+     * @param to to index of node to stop matching (inclusive)
+     * @return the builder to build the nodes.
+     */
+    public AdviceWithBuilder<T> selectRange(int from, int to) {
+        if (from < 0) {
+            throw new IllegalArgumentException("From must be a non negative 
number, was: " + from);
+        }
+        if (from > to) {
+            throw new IllegalArgumentException("From must be equal or lower 
than to. from: " + from + ", to: " + to);
+        }
+        selectFrom = from;
+        selectTo = to;
+        return this;
+    }
+
+    /**
      * Replaces the matched node(s) with the following nodes.
      *
      * @return the builder to build the nodes.
      */
     public ProcessorDefinition replace() {
+        RouteDefinition route = builder.getOriginalRoute();
         PipelineDefinition answer = new PipelineDefinition();
         if (id != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceById(builder.getOriginalRoute(),
 id, answer));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceById(route, id, answer, 
selectFirst, selectLast, selectFrom, selectTo));
         } else if (toString != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceByToString(builder.getOriginalRoute(),
 toString, answer));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceByToString(route, 
toString, answer, selectFirst, selectLast, selectFrom, selectTo));
         } else if (type != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceByType(builder.getOriginalRoute(),
 type, answer));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.replaceByType(route, type, 
answer, selectFirst, selectLast, selectFrom, selectTo));
         }
         return answer;
     }
@@ -61,12 +123,13 @@ public class AdviceWithBuilder<T extends
      * Removes the matched node(s)
      */
     public void remove() {
+        RouteDefinition route = builder.getOriginalRoute();
         if (id != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.removeById(builder.getOriginalRoute(),
 id));
+            builder.getAdviceWithTasks().add(AdviceWithTasks.removeById(route, 
id, selectFirst, selectLast, selectFrom, selectTo));
         } else if (toString != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.removeByToString(builder.getOriginalRoute(),
 toString));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.removeByToString(route, 
toString, selectLast, selectFirst, selectFrom, selectTo));
         } else if (type != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.removeByType(builder.getOriginalRoute(),
 type));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.removeByType(route, type, 
selectFirst, selectFirst, selectFrom, selectTo));
         }
     }
 
@@ -76,13 +139,14 @@ public class AdviceWithBuilder<T extends
      * @return the builder to build the nodes.
      */
     public ProcessorDefinition before() {
+        RouteDefinition route = builder.getOriginalRoute();
         PipelineDefinition answer = new PipelineDefinition();
         if (id != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.beforeById(builder.getOriginalRoute(),
 id, answer));
+            builder.getAdviceWithTasks().add(AdviceWithTasks.beforeById(route, 
id, answer, selectFirst, selectLast, selectFrom, selectTo));
         } else if (toString != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.beforeByToString(builder.getOriginalRoute(),
 toString, answer));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.beforeByToString(route, 
toString, answer, selectLast, selectFirst, selectFrom, selectTo));
         } else if (type != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.beforeByType(builder.getOriginalRoute(),
 type, answer));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.beforeByType(route, type, 
answer, selectFirst, selectLast, selectFrom, selectTo));
         }
         return answer;
     }
@@ -93,13 +157,14 @@ public class AdviceWithBuilder<T extends
      * @return the builder to build the nodes.
      */
     public ProcessorDefinition after() {
+        RouteDefinition route = builder.getOriginalRoute();
         PipelineDefinition answer = new PipelineDefinition();
         if (id != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.afterById(builder.getOriginalRoute(),
 id, answer));
+            builder.getAdviceWithTasks().add(AdviceWithTasks.afterById(route, 
id, answer, selectFirst, selectLast, selectFrom, selectTo));
         } else if (toString != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.afterByToString(builder.getOriginalRoute(),
 toString, answer));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.afterByToString(route, 
toString, answer, selectLast, selectFirst, selectFrom, selectTo));
         } else if (type != null) {
-            
builder.getAdviceWithTasks().add(AdviceWithTasks.afterByType(builder.getOriginalRoute(),
 type, answer));
+            
builder.getAdviceWithTasks().add(AdviceWithTasks.afterByType(route, type, 
answer, selectFirst, selectLast, selectFrom, selectTo));
         }
         return answer;
     }

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java?rev=1101412&r1=1101411&r2=1101412&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithRouteBuilder.java
 Tue May 10 11:35:30 2011
@@ -122,4 +122,24 @@ public abstract class AdviceWithRouteBui
         return new AdviceWithBuilder<T>(this, null, null, type);
     }
 
+    /**
+     * Weaves by adding the nodes to the start of the route.
+     *
+     * @return the builder
+     */
+    public <T extends ProcessorDefinition> ProcessorDefinition weaveAddFirst() 
{
+        ObjectHelper.notNull(originalRoute, "originalRoute", this);
+        return new AdviceWithBuilder<T>(this, "*", null, 
null).selectFirst().before();
+    }
+
+    /**
+     * Weaves by adding the nodes to the end of the route.
+     *
+     * @return the builder
+     */
+    public <T extends ProcessorDefinition> ProcessorDefinition weaveAddLast() {
+        ObjectHelper.notNull(originalRoute, "originalRoute", this);
+        return new AdviceWithBuilder<T>(this, "*", null, 
null).selectLast().after();
+    }
+
 }

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java?rev=1101412&r1=1101411&r2=1101412&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
 Tue May 10 11:35:30 2011
@@ -106,25 +106,33 @@ public final class AdviceWithTasks {
         }
     }
 
-
-    public static AdviceWithTask replaceByToString(final RouteDefinition 
route, final String toString, final ProcessorDefinition replace) {
-        return doReplace(route, new MatchByToString(toString), replace);
-    }
-
-    public static AdviceWithTask replaceById(final RouteDefinition route, 
final String id, final ProcessorDefinition replace) {
-        return doReplace(route, new MatchById(id), replace);
-    }
-
-    public static AdviceWithTask replaceByType(final RouteDefinition route, 
final Class type, final ProcessorDefinition replace) {
-        return doReplace(route, new MatchByType(type), replace);
+    public static AdviceWithTask replaceByToString(final RouteDefinition 
route, final String toString, final ProcessorDefinition replace,
+                                                   boolean selectFirst, 
boolean selectLast, int selectFrom, int selectTo) {
+        MatchBy matchBy = new MatchByToString(toString);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        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) {
+        MatchBy matchBy = new MatchById(id);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        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) {
+        MatchBy matchBy = new MatchByType(type);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        return doReplace(route, matchBy, replace, it);
     }
 
     @SuppressWarnings("unchecked")
-    private static AdviceWithTask doReplace(final RouteDefinition route, final 
MatchBy matchBy, final ProcessorDefinition replace) {
+    private static AdviceWithTask doReplace(final RouteDefinition route, final 
MatchBy matchBy, final ProcessorDefinition replace,
+                                            final 
Iterator<ProcessorDefinition> it) {
         return new AdviceWithTask() {
             public void task() throws Exception {
                 boolean match = false;
-                Iterator<ProcessorDefinition> it = 
ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), 
ProcessorDefinition.class);
                 while (it.hasNext()) {
                     ProcessorDefinition output = it.next();
                     if (matchBy.match(output)) {
@@ -148,23 +156,32 @@ public final class AdviceWithTasks {
         };
     }
 
-    public static AdviceWithTask removeByToString(final RouteDefinition route, 
final String toString) {
-        return doRemove(route, new MatchByToString(toString));
+    public static AdviceWithTask removeByToString(final RouteDefinition route, 
final String toString,
+                                                  boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+        MatchBy matchBy = new MatchByToString(toString);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        return doRemove(route, matchBy, it);
     }
 
-    public static AdviceWithTask removeById(final RouteDefinition route, final 
String id) {
-        return doRemove(route, new MatchById(id));
+    public static AdviceWithTask removeById(final RouteDefinition route, final 
String id,
+                                            boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+        MatchBy matchBy = new MatchById(id);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        return doRemove(route, matchBy, it);
     }
 
-    public static AdviceWithTask removeByType(final RouteDefinition route, 
final Class type) {
-        return doRemove(route, new MatchByType(type));
+    public static AdviceWithTask removeByType(final RouteDefinition route, 
final Class type,
+                                              boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+        MatchBy matchBy = new MatchByType(type);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        return doRemove(route, matchBy, it);
     }
 
-    private static AdviceWithTask doRemove(final RouteDefinition route, final 
MatchBy matchBy) {
+    private static AdviceWithTask doRemove(final RouteDefinition route, final 
MatchBy matchBy,
+                                           final Iterator<ProcessorDefinition> 
it) {
         return new AdviceWithTask() {
             public void task() throws Exception {
                 boolean match = false;
-                Iterator<ProcessorDefinition> it = 
ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), 
ProcessorDefinition.class);
                 while (it.hasNext()) {
                     ProcessorDefinition output = it.next();
                     if (matchBy.match(output)) {
@@ -187,24 +204,33 @@ public final class AdviceWithTasks {
         };
     }
 
-    public static AdviceWithTask beforeByToString(final RouteDefinition route, 
final String toString, final ProcessorDefinition before) {
-        return doBefore(route, new MatchByToString(toString), before);
-    }
-
-    public static AdviceWithTask beforeById(final RouteDefinition route, final 
String id, final ProcessorDefinition before) {
-        return doBefore(route, new MatchById(id), before);
-    }
-
-    public static AdviceWithTask beforeByType(final RouteDefinition route, 
final Class type, final ProcessorDefinition before) {
-        return doBefore(route, new MatchByType(type), before);
+    public static AdviceWithTask beforeByToString(final RouteDefinition route, 
final String toString, final ProcessorDefinition before,
+                                                  boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+        MatchBy matchBy = new MatchByToString(toString);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        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) {
+        MatchBy matchBy = new MatchById(id);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        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) {
+        MatchBy matchBy = new MatchByType(type);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        return doBefore(route, matchBy, before, it);
     }
 
     @SuppressWarnings("unchecked")
-    private static AdviceWithTask doBefore(final RouteDefinition route, final 
MatchBy matchBy, final ProcessorDefinition before) {
+    private static AdviceWithTask doBefore(final RouteDefinition route, final 
MatchBy matchBy, final ProcessorDefinition before,
+                                           final Iterator<ProcessorDefinition> 
it) {
         return new AdviceWithTask() {
             public void task() throws Exception {
                 boolean match = false;
-                Iterator<ProcessorDefinition> it = 
ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), 
ProcessorDefinition.class);
                 while (it.hasNext()) {
                     ProcessorDefinition output = it.next();
                     if (matchBy.match(output)) {
@@ -228,24 +254,33 @@ public final class AdviceWithTasks {
         };
     }
 
-    public static AdviceWithTask afterByToString(final RouteDefinition route, 
final String toString, final ProcessorDefinition after) {
-        return doAfter(route, new MatchByToString(toString), after);
-    }
-
-    public static AdviceWithTask afterById(final RouteDefinition route, final 
String id, final ProcessorDefinition after) {
-        return doAfter(route, new MatchById(id), after);
-    }
-
-    public static AdviceWithTask afterByType(final RouteDefinition route, 
final Class type, final ProcessorDefinition after) {
-        return doAfter(route, new MatchByType(type), after);
+    public static AdviceWithTask afterByToString(final RouteDefinition route, 
final String toString, final ProcessorDefinition after,
+                                                 boolean selectFirst, boolean 
selectLast, int selectFrom, int selectTo) {
+        MatchBy matchBy = new MatchByToString(toString);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        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) {
+        MatchBy matchBy = new MatchById(id);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        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) {
+        MatchBy matchBy = new MatchByType(type);
+        Iterator<ProcessorDefinition> it = 
AdviceWithTasks.createMatchByIterator(route, matchBy, selectFirst, selectLast, 
selectFrom, selectTo);
+        return doAfter(route, matchBy, after, it);
     }
 
     @SuppressWarnings("unchecked")
-    private static AdviceWithTask doAfter(final RouteDefinition route, final 
MatchBy matchBy, final ProcessorDefinition after) {
+    private static AdviceWithTask doAfter(final RouteDefinition route, final 
MatchBy matchBy, final ProcessorDefinition after,
+                                          final Iterator<ProcessorDefinition> 
it) {
         return new AdviceWithTask() {
             public void task() throws Exception {
                 boolean match = false;
-                Iterator<ProcessorDefinition> it = 
ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), 
ProcessorDefinition.class);
                 while (it.hasNext()) {
                     ProcessorDefinition output = it.next();
                     if (matchBy.match(output)) {
@@ -270,4 +305,142 @@ public final class AdviceWithTasks {
         };
     }
 
+    /**
+     * Create iterator which walks the route, and only returns nodes which 
matches the given set of criteria.
+     *
+     * @param route        the route
+     * @param matchBy      match by which must match
+     * @param selectFirst  optional to select only the first
+     * @param selectLast   optional to select only the last
+     * @param selectFrom   optional to select index/range
+     * @param selectTo     optional to select index/range
+     * 
+     * @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) {
+
+        // iterator to walk all nodes
+        final Iterator<ProcessorDefinition> itAll = 
ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), 
ProcessorDefinition.class);
+
+        // iterator to only walk nodes which matchBy matches
+        final Iterator<ProcessorDefinition> itMatchBy = new 
Iterator<ProcessorDefinition>() {
+            private ProcessorDefinition next;
+
+            @Override
+            public boolean hasNext() {
+                if (next == null) {
+                    // compute next
+                    next = next();
+                }
+                return next != null;
+            }
+
+            @Override
+            public ProcessorDefinition next() {
+                // grab the next if its ready
+                if (next != null) {
+                    ProcessorDefinition answer = next;
+                    next = null;
+                    return answer;
+                }
+
+                // find the next which matchBy matches
+                boolean found = false;
+                while (!found && itAll.hasNext()) {
+                    ProcessorDefinition def = itAll.next();
+                    if (matchBy.match(def)) {
+                        found = true;
+                        next = def;
+                    }
+                }
+
+                ProcessorDefinition answer = next;
+                next = null;
+                return answer;
+            }
+
+            @Override
+            public void remove() {
+            }
+        };
+
+        // iterator to only walk which selectXXX matches
+        return new Iterator<ProcessorDefinition>() {
+            private int current;
+            private ProcessorDefinition next;
+
+            @Override
+            public boolean hasNext() {
+                if (next == null) {
+                    // compute next
+                    next = next();
+                }
+                return next != null;
+            }
+
+            public ProcessorDefinition next() {
+                // grab the next if its ready
+                if (next != null) {
+                    ProcessorDefinition answer = next;
+                    next = null;
+                    return answer;
+                }
+
+                // a bit complicated logic to ensure 
selectFirst/selectLast,selectFrom/selectTo
+                // filter out unwanted nodes
+                // we use the matchBy iterator as the nodes mush at first 
match this iterator
+                // before we can do any selection
+
+                if (selectFrom >= 0 && current <= selectFrom) {
+                    // spool until we should start
+                    while (current <= selectFrom) {
+                        current++;
+                        if (itMatchBy.hasNext()) {
+                            next = itMatchBy.next();
+                        } else {
+                            next = null;
+                        }
+                    }
+                } else if (selectTo >= 0 && current <= selectTo) {
+                    // are we in range
+                    current++;
+                    if (itMatchBy.hasNext()) {
+                        next = itMatchBy.next();
+                    } else {
+                        next = null;
+                    }
+                } else if (selectLast) {
+                    // spool until the last matching
+                    while (itMatchBy.hasNext()) {
+                        current++;
+                        next = itMatchBy.next();
+                    }
+                } else if (selectFirst) {
+                    // only match the first
+                    current++;
+                    if (itMatchBy.hasNext() && current == 1) {
+                        next = itMatchBy.next();
+                    } else {
+                        next = null;
+                    }
+                } else if (!selectFirst && !selectLast && selectFrom < 0 && 
selectTo < 0) {
+                    // regular without any 
selectFirst,selectLast,selectFrom/selectTo stuff
+                    current++;
+                    if (itMatchBy.hasNext()) {
+                        next = itMatchBy.next();
+                    }
+                }
+
+                return next;
+            }
+
+            @Override
+            public void remove() {
+                // noop
+            }
+        };
+    }
+
 }

Copied: 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksSelectTest.java
 (from r1101352, 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksMatchTest.java)
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksSelectTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksSelectTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksMatchTest.java&r1=1101352&r2=1101412&rev=1101412&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksMatchTest.java
 (original)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksSelectTest.java
 Tue May 10 11:35:30 2011
@@ -23,19 +23,141 @@ import org.apache.camel.builder.RouteBui
 /**
  * Advice with match multiple ids test
  */
-public class AdviceWithTasksMatchTest extends ContextTestSupport {
+public class AdviceWithTasksSelectTest extends ContextTestSupport {
 
-    public void testReplaceMultipleIds() throws Exception {
+    public void testSelectFirst() throws Exception {
         context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
             @Override
             public void configure() throws Exception {
-                // replace all gold id's with the following route path
-                
weaveById("gold*").replace().multicast().to("mock:a").to("mock:b");
+                // should only match the first
+                
weaveById("gold*").selectFirst().replace().multicast().to("mock:a").to("mock:b");
+            }
+        });
+
+        getMockEndpoint("mock:foo").expectedMessageCount(0);
+        getMockEndpoint("mock:bar").expectedMessageCount(1);
+        getMockEndpoint("mock:baz").expectedMessageCount(1);
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:b").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testSelectLast() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // should only match the last
+                
weaveById("gold*").selectLast().replace().multicast().to("mock:a").to("mock:b");
+            }
+        });
+
+        getMockEndpoint("mock:foo").expectedMessageCount(1);
+        getMockEndpoint("mock:bar").expectedMessageCount(1);
+        getMockEndpoint("mock:baz").expectedMessageCount(0);
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:b").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+
+    public void testSelectIndexZero() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // should match the first index (0 based)
+                
weaveById("gold*").selectIndex(0).replace().multicast().to("mock:a").to("mock:b");
+            }
+        });
+
+        getMockEndpoint("mock:foo").expectedMessageCount(0);
+        getMockEndpoint("mock:bar").expectedMessageCount(1);
+        getMockEndpoint("mock:baz").expectedMessageCount(1);
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:b").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testSelectIndexOne() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // should match the second index (0 based)
+                
weaveById("gold*").selectIndex(1).replace().multicast().to("mock:a").to("mock:b");
+            }
+        });
+
+        getMockEndpoint("mock:foo").expectedMessageCount(1);
+        getMockEndpoint("mock:bar").expectedMessageCount(0);
+        getMockEndpoint("mock:baz").expectedMessageCount(1);
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:b").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testSelectIndexTwo() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // should match the third index (0 based)
+                
weaveById("gold*").selectIndex(2).replace().multicast().to("mock:a").to("mock:b");
+            }
+        });
+
+        getMockEndpoint("mock:foo").expectedMessageCount(1);
+        getMockEndpoint("mock:bar").expectedMessageCount(1);
+        getMockEndpoint("mock:baz").expectedMessageCount(0);
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:b").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testSelectIndexOutOfBounds() throws Exception {
+        try {
+            context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    // should be out of bounds
+                    
weaveById("gold*").selectIndex(4).replace().multicast().to("mock:a").to("mock:b");
+                }
+            });
+            fail("Should hve thrown exception");
+        } catch (IllegalArgumentException e) {
+            assertTrue(e.getMessage(), e.getMessage().startsWith("There are no 
outputs which matches: gold* in the route"));
+        }
+    }
+
+    public void testSelectRangeZeroOne() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // should match the first two (0-based)
+                weaveById("gold*").selectRange(0, 
1).replace().multicast().to("mock:a").to("mock:b");
             }
         });
 
         getMockEndpoint("mock:foo").expectedMessageCount(0);
         getMockEndpoint("mock:bar").expectedMessageCount(0);
+        getMockEndpoint("mock:baz").expectedMessageCount(1);
         getMockEndpoint("mock:a").expectedMessageCount(2);
         getMockEndpoint("mock:b").expectedMessageCount(2);
         getMockEndpoint("mock:result").expectedMessageCount(1);
@@ -45,6 +167,26 @@ public class AdviceWithTasksMatchTest ex
         assertMockEndpointsSatisfied();
     }
 
+    public void testSelectRangeOneTwo() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // should match the 2nd and 3rd (0-based)
+                weaveById("gold*").selectRange(1, 
2).replace().multicast().to("mock:a").to("mock:b");
+            }
+        });
+
+        getMockEndpoint("mock:foo").expectedMessageCount(1);
+        getMockEndpoint("mock:bar").expectedMessageCount(0);
+        getMockEndpoint("mock:baz").expectedMessageCount(0);
+        getMockEndpoint("mock:a").expectedMessageCount(2);
+        getMockEndpoint("mock:b").expectedMessageCount(2);
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
 
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
@@ -52,8 +194,10 @@ public class AdviceWithTasksMatchTest ex
             @Override
             public void configure() throws Exception {
                 from("direct:start")
+                    .log("Got ${body}").id("foo")
                     .to("mock:foo").id("gold-1")
                     .to("mock:bar").id("gold-2")
+                    .to("mock:baz").id("gold-3")
                     .to("mock:result").id("silver-1");
             }
         };

Copied: 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveFirstLastTest.java
 (from r1101352, 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksTest.java)
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveFirstLastTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveFirstLastTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksTest.java&r1=1101352&r2=1101412&rev=1101412&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTasksTest.java
 (original)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveFirstLastTest.java
 Tue May 10 11:35:30 2011
@@ -23,80 +23,21 @@ import org.apache.camel.builder.RouteBui
 /**
  * Advice with tests
  */
-public class AdviceWithTasksTest extends ContextTestSupport {
+public class AdviceWithWeaveFirstLastTest extends ContextTestSupport {
 
-    public void testUnknownId() throws Exception {
-        try {
-            context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
-                @Override
-                public void configure() throws Exception {
-                    weaveById("xxx").replace().to("mock:xxx");
-                }
-            });
-            fail("Should hve thrown exception");
-        } catch (IllegalArgumentException e) {
-            assertTrue(e.getMessage(), e.getMessage().startsWith("There are no 
outputs which matches: xxx in the route"));
-        }
-    }
-
-    public void testReplace() throws Exception {
+    public void testWeaveAddFirst() throws Exception {
         // START SNIPPET: e1
         context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
             @Override
             public void configure() throws Exception {
-                // weave the node in the route which has id = bar
-                // and replace it with the following route path
-                
weaveById("bar").replace().multicast().to("mock:a").to("mock:b");
+                // insert at first the given piece of route to the existing 
route
+                weaveAddFirst().to("mock:a").transform(constant("Bye World"));
             }
         });
         // END SNIPPET: e1
 
-        getMockEndpoint("mock:foo").expectedMessageCount(1);
-        getMockEndpoint("mock:bar").expectedMessageCount(0);
-        getMockEndpoint("mock:a").expectedMessageCount(1);
-        getMockEndpoint("mock:b").expectedMessageCount(1);
-        getMockEndpoint("mock:result").expectedMessageCount(1);
-
-        template.sendBody("direct:start", "Hello World");
-
-        assertMockEndpointsSatisfied();
-    }
-
-    public void testRemove() throws Exception {
-        // START SNIPPET: e2
-        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                // weave the node in the route which has id = bar and remove it
-                weaveById("bar").remove();
-            }
-        });
-        // END SNIPPET: e2
-
-        getMockEndpoint("mock:foo").expectedMessageCount(1);
-        getMockEndpoint("mock:result").expectedMessageCount(1);
-
-        template.sendBody("direct:start", "Hello World");
-
-        assertMockEndpointsSatisfied();
-
-        assertFalse("Should not have removed id", 
context.hasEndpoint("mock:bar") == null);
-    }
-
-    public void testBefore() throws Exception {
-        // START SNIPPET: e3
-        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                // weave the node in the route which has id = bar
-                // and insert the following route path before the adviced node
-                weaveById("bar").before().to("mock:a").transform(constant("Bye 
World"));
-            }
-        });
-        // END SNIPPET: e3
-
-        getMockEndpoint("mock:foo").expectedBodiesReceived("Hello World");
         getMockEndpoint("mock:a").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:foo").expectedBodiesReceived("Bye World");
         getMockEndpoint("mock:bar").expectedBodiesReceived("Bye World");
         getMockEndpoint("mock:result").expectedBodiesReceived("Bye World");
 
@@ -105,24 +46,24 @@ public class AdviceWithTasksTest extends
         assertMockEndpointsSatisfied();
     }
 
-    public void testAfter() throws Exception {
-        // START SNIPPET: e4
+    public void testWeaveAddLast() throws Exception {
+        // START SNIPPET: e2
         context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
             @Override
             public void configure() throws Exception {
-                // weave the node in the route which has id = bar
-                // and insert the following route path after the advice node
-                weaveById("bar").after().to("mock:a").transform(constant("Bye 
World"));
+                // insert at the end of the existing route, the given piece of 
route
+                weaveAddLast().to("mock:a").transform(constant("Bye World"));
             }
         });
-        // END SNIPPET: e4
+        // END SNIPPET: e2
 
-        getMockEndpoint("mock:foo").expectedBodiesReceived("Hello World");
         getMockEndpoint("mock:a").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:foo").expectedBodiesReceived("Hello World");
         getMockEndpoint("mock:bar").expectedBodiesReceived("Hello World");
-        getMockEndpoint("mock:result").expectedBodiesReceived("Bye World");
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
 
-        template.sendBody("direct:start", "Hello World");
+        Object out = template.requestBody("direct:start", "Hello World");
+        assertEquals("Bye World", out);
 
         assertMockEndpointsSatisfied();
     }

Propchange: 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveFirstLastTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithWeaveFirstLastTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TracingTestBase.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TracingTestBase.java?rev=1101412&r1=1101411&r2=1101412&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TracingTestBase.java
 (original)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TracingTestBase.java
 Tue May 10 11:35:30 2011
@@ -22,7 +22,7 @@ import org.apache.camel.ContextTestSuppo
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 
-public class TracingTestBase extends ContextTestSupport {
+public abstract class TracingTestBase extends ContextTestSupport {
     protected List<StringBuilder> tracedMessages;
     private TraceTestProcessor processor = new TraceTestProcessor();
 


Reply via email to