You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by np...@apache.org on 2018/06/12 09:18:44 UTC

[sling-org-apache-sling-pipes] branch master updated: SLING-7704 introduce SuperPipe

This is an automated email from the ASF dual-hosted git repository.

npeltier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-pipes.git


The following commit(s) were added to refs/heads/master by this push:
     new df21d88  SLING-7704 introduce SuperPipe
df21d88 is described below

commit df21d8817060f923883fb904ca216c3838b73a3d
Author: Nicolas Peltier <pe...@gmail.com>
AuthorDate: Tue Jun 12 11:18:22 2018 +0200

    SLING-7704 introduce SuperPipe
    
    - abstract class for any pipe which execution depends on sub pipes,
    - ReferencePipe and ContainerPipe are modified (and not public anymore) to be extending it,
    - Pipe & BasePipe are only knowing SuperPipe now
---
 src/main/java/org/apache/sling/pipes/BasePipe.java |  14 +--
 src/main/java/org/apache/sling/pipes/Pipe.java     |  19 +--
 .../java/org/apache/sling/pipes/SuperPipe.java     | 129 +++++++++++++++++++++
 .../sling/pipes/{ => internal}/ContainerPipe.java  | 104 ++++-------------
 .../org/apache/sling/pipes/internal/NotPipe.java   |   3 +-
 .../sling/pipes/internal/PipeBuilderImpl.java      |   2 -
 .../apache/sling/pipes/internal/PlumberImpl.java   |   2 -
 .../sling/pipes/internal/PlumberServlet.java       |   1 -
 .../sling/pipes/{ => internal}/ReferencePipe.java  |  72 ++++--------
 .../apache/sling/pipes/internal/TraversePipe.java  |   2 +-
 .../org/apache/sling/pipes/internal/WritePipe.java |   2 +-
 .../org/apache/sling/pipes/AbstractPipeTest.java   |   3 +-
 .../org/apache/sling/pipes/ContainerPipeTest.java  |  10 +-
 .../apache/sling/pipes/dummies/DummySearch.java    |   2 +-
 .../sling/pipes/internal/ReferencePipeTest.java    |   1 -
 .../apache/sling/pipes/internal/WritePipeTest.java |   4 +-
 .../org/apache/sling/pipes/it/PipeBuilderIT.java   |   2 +-
 .../apache/sling/pipes/models/PipeModelTest.java   |   2 +-
 18 files changed, 202 insertions(+), 172 deletions(-)

diff --git a/src/main/java/org/apache/sling/pipes/BasePipe.java b/src/main/java/org/apache/sling/pipes/BasePipe.java
index 97f2e59..7cb6248 100644
--- a/src/main/java/org/apache/sling/pipes/BasePipe.java
+++ b/src/main/java/org/apache/sling/pipes/BasePipe.java
@@ -49,10 +49,9 @@ public class BasePipe implements Pipe {
     protected ResourceResolver resolver;
     protected ValueMap properties;
     protected Resource resource;
-    protected ContainerPipe parent;
+    protected SuperPipe parent;
     protected String distributionAgent;
     protected PipeBindings bindings;
-    protected ReferencePipe referrer;
 
     // used by pipes using complex JCR configurations
     public static final List<String> IGNORED_PROPERTIES = Arrays.asList(new String[]{"jcr:lastModified", "jcr:primaryType", "jcr:created", "jcr:createdBy", "jcr:uuid"});
@@ -60,12 +59,12 @@ public class BasePipe implements Pipe {
     protected Boolean dryRunObject;
 
     @Override
-    public ContainerPipe getParent() {
+    public SuperPipe getParent() {
         return parent;
     }
 
     @Override
-    public void setParent(ContainerPipe parent) {
+    public void setParent(SuperPipe parent) {
         this.parent = parent;
     }
 
@@ -183,7 +182,7 @@ public class BasePipe implements Pipe {
      * @return pipe before this one or the referrer's can be null in case there is no parent
      */
     protected Pipe getPreviousPipe(){
-        return referrer == null ? (parent != null ? parent.getPreviousPipe(this) : null) : referrer.getPreviousPipe();
+        return parent != null ? parent.getPreviousPipe(this) : null;
     }
 
     /**
@@ -282,11 +281,6 @@ public class BasePipe implements Pipe {
         return distributionAgent;
     }
 
-    @Override
-    public void setReferrer(ReferencePipe pipe) {
-        referrer = pipe;
-    }
-
     /**
      * Empty resource iterator
      */
diff --git a/src/main/java/org/apache/sling/pipes/Pipe.java b/src/main/java/org/apache/sling/pipes/Pipe.java
index a4d8940..ea0858d 100644
--- a/src/main/java/org/apache/sling/pipes/Pipe.java
+++ b/src/main/java/org/apache/sling/pipes/Pipe.java
@@ -71,16 +71,15 @@ public interface Pipe {
     String getName();
 
     /**
-     * set the pipe parent
-     * @param parent container pipe
+     * sets the parent pipe this pipe is referred by
+     * @param pipe referrer that refers to this instance
      */
-    void setParent(ContainerPipe parent);
+    void setParent(SuperPipe pipe);
 
     /**
-     * Return parent's pipe (can be null)
-     * @return pipe's container parent
+     * @return pipe's parent (can be null)
      */
-    ContainerPipe getParent();
+    SuperPipe getParent();
 
     /**
      * Get pipe current's resource *before* next execution, meaning either the
@@ -119,10 +118,4 @@ public interface Pipe {
      * @return configured distribution agent
      */
     String getDistributionAgent();
-
-    /**
-     * sets the reference pipe this pipe is referred by
-     * @param pipe referrer that refers to this instance
-     */
-    void setReferrer(ReferencePipe pipe);
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/pipes/SuperPipe.java b/src/main/java/org/apache/sling/pipes/SuperPipe.java
new file mode 100644
index 0000000..d608cdd
--- /dev/null
+++ b/src/main/java/org/apache/sling/pipes/SuperPipe.java
@@ -0,0 +1,129 @@
+/*
+ * 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.sling.pipes;
+
+import org.apache.sling.api.resource.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Pipe that outputs some other pipes output, managing for them what is their outputs, and bindings
+ */
+public abstract class SuperPipe extends BasePipe {
+    private static final Logger LOG = LoggerFactory.getLogger(SuperPipe.class);
+
+    /**
+     * Sleep time, in ms, after each resource returned
+     */
+    public static final String PN_SLEEP = "sleep";
+
+    protected long sleep = 0L;
+
+    protected List<Pipe> subpipes = new ArrayList<>();
+
+    /**
+     * Pipe Constructor
+     *
+     * @param plumber       plumber
+     * @param resource      configuration resource
+     * @param upperBindings already set bindings, can be null
+     *
+     * @throws Exception in case configuration is not working
+     */
+    public SuperPipe(Plumber plumber, Resource resource, PipeBindings upperBindings) throws Exception {
+        super(plumber, resource, upperBindings);
+        sleep = properties.get(PN_SLEEP, 0L);
+    }
+
+    /**
+     * build the subpipes pipes list
+     */
+    public abstract void buildChildren() throws Exception;
+
+    /**
+     * @return output of this super pipe's subpipes
+     */
+    protected abstract Iterator<Resource> computeSubpipesOutput() throws Exception;
+
+    @Override
+    protected Iterator<Resource> computeOutput() throws Exception {
+        if (subpipes.isEmpty()){
+            buildChildren();
+        }
+        return computeSubpipesOutput();
+    }
+
+    /**
+     * Return the first pipe in the container
+     * @return first pipe of the container
+     */
+    protected Pipe getFirstPipe() {
+        return subpipes.size() > 0 ? subpipes.get(0) : null;
+    }
+
+    /**
+     * Return the last pipe in the container
+     * @return pipe in the last position of the container's pipes
+     */
+    protected Pipe getLastPipe() {
+        return subpipes.size() > 0 ? subpipes.get(subpipes.size() - 1) : null;
+    }
+
+    /**
+     * Return the previous pipe of the given child pipe
+     * @param pipe child pipe of this parent
+     * @return previous pipe if any
+     */
+    public Pipe getPreviousPipe(Pipe pipe){
+        Pipe previousPipe = null;
+        if (!subpipes.isEmpty()){
+            if (subpipes.get(0).equals(pipe) && parent != null){
+                //in the case this pipe has a parent, previous pipe is the one of the referrer
+                return parent.getPreviousPipe(this);
+            }
+            for (Pipe candidate : subpipes){
+                if (candidate.equals(pipe)){
+                    return previousPipe;
+                }
+                previousPipe = candidate;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean modifiesContent() {
+        try {
+            if (subpipes.isEmpty()) {
+                buildChildren();
+            }
+            for (Pipe pipe : subpipes){
+                if (pipe.modifiesContent()){
+                    return true;
+                }
+            }
+            return false;
+        } catch (Exception e){
+            LOG.error("something went wrong while building this pipe, we'll consider this pipe as modifying content", e);
+        }
+        return true;
+    }
+}
diff --git a/src/main/java/org/apache/sling/pipes/ContainerPipe.java b/src/main/java/org/apache/sling/pipes/internal/ContainerPipe.java
similarity index 70%
rename from src/main/java/org/apache/sling/pipes/ContainerPipe.java
rename to src/main/java/org/apache/sling/pipes/internal/ContainerPipe.java
index 0c5c72f..2224a0c 100644
--- a/src/main/java/org/apache/sling/pipes/ContainerPipe.java
+++ b/src/main/java/org/apache/sling/pipes/internal/ContainerPipe.java
@@ -14,38 +14,30 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.pipes;
+package org.apache.sling.pipes.internal;
 
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.pipes.SuperPipe;
+import org.apache.sling.pipes.Pipe;
+import org.apache.sling.pipes.PipeBindings;
+import org.apache.sling.pipes.Plumber;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 /**
  * This pipe executes the pipes it has in its configuration, chaining their result, and
  * modifying each contained pipe's expression with its context
  */
-public class ContainerPipe extends BasePipe {
+public class ContainerPipe extends SuperPipe {
     private static final Logger log = LoggerFactory.getLogger(ContainerPipe.class);
 
     public static final String RESOURCE_TYPE = "slingPipes/container";
 
     /**
-     * Sleep time, in ms, after each resource returned
-     */
-    public static final String PN_SLEEP = "sleep";
-
-    Map<String, Pipe> pipes = new HashMap<>();
-
-    List<Pipe> pipeList = new ArrayList<>();
-
-    long sleep = 0L;
-    /**
      * Constructor
      * @param plumber plumber
      * @param resource container's configuration resource
@@ -54,7 +46,10 @@ public class ContainerPipe extends BasePipe {
      */
     public ContainerPipe(Plumber plumber, Resource resource, PipeBindings upperBindings) throws Exception{
         super(plumber, resource, upperBindings);
-        sleep = properties.get(PN_SLEEP, 0L);
+    }
+
+    @Override
+    public void buildChildren() {
         for (Iterator<Resource> childPipeResources = getConfiguration().listChildren(); childPipeResources.hasNext();){
             Resource pipeResource = childPipeResources.next();
             Pipe pipe = plumber.getPipe(pipeResource, bindings);
@@ -62,77 +57,20 @@ public class ContainerPipe extends BasePipe {
                 log.error("configured pipe {} is either not registered, or not computable by the plumber", pipeResource.getPath());
             } else {
                 pipe.setParent(this);
-                pipes.put(pipe.getName(), pipe);
-                pipeList.add(pipe);
+                subpipes.add(pipe);
             }
         }
     }
 
     @Override
-    public boolean modifiesContent() {
-        for (Pipe pipe : pipes.values()){
-            if (pipe.modifiesContent()){
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public Iterator<Resource> getOutput()  {
-        if (pipeList.size() > 0) {
-            return new ContainerResourceIterator(this, sleep);
+    protected Iterator<Resource> computeSubpipesOutput() {
+        if (subpipes.size() > 0) {
+            return new ContainerResourceIterator(this);
         }
         return EMPTY_ITERATOR;
     }
 
     /**
-     * Returns the pipe immediately before the given pipe, null if it's the first
-     * @param pipe given pipe
-     * @return previous pipe of the param
-     */
-    public Pipe getPreviousPipe(Pipe pipe){
-        Pipe previousPipe = null;
-        if (!pipeList.isEmpty()){
-            if (pipeList.get(0).equals(pipe) && referrer != null){
-                //in case this pipe is referred, previous pipe is the one of the referrer
-                return referrer.getPreviousPipe();
-            }
-            for (Pipe candidate : pipeList){
-                if (candidate.equals(pipe)){
-                    return previousPipe;
-                }
-                previousPipe = candidate;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Return the first pipe in the container
-     * @return first pipe of the container
-     */
-    public Pipe getFirstPipe() {
-        return pipeList.iterator().next();
-    }
-
-    /**
-     * Return the last pipe in the container
-     * @return pipe in the last position of the container's pipes
-     */
-    public Pipe getLastPipe() {
-        return pipeList.get(pipeList.size() - 1);
-    }
-
-    /**
-     * output resource of the container pipe
-     * @return output resource of the last pipe of the container
-     */
-    public Resource getOutputResource() {
-        return bindings.getExecutedResource(getLastPipe().getName());
-    }
-
-    /**
      * Container Iterator, that iterates through the whole chain
      * of pipes, returning the result resources of the end of the chain
      */
@@ -158,12 +96,12 @@ public class ContainerPipe extends BasePipe {
          * Constructor
          * @param containerPipe corresponding container pipe
          */
-        ContainerResourceIterator(ContainerPipe containerPipe, long sleep) {
+        ContainerResourceIterator(ContainerPipe containerPipe) {
             container = containerPipe;
             bindings = container.bindings;
             iterators = new HashMap<>();
             Pipe firstPipe = container.getFirstPipe();
-            this.sleep = sleep;
+            this.sleep = container.sleep;
             //we initialize the first iterator the only one not to be updated
             iterators.put(firstPipe, firstPipe.getOutput());
         }
@@ -174,17 +112,17 @@ public class ContainerPipe extends BasePipe {
          * @return true if cursor has been updated
          */
         private boolean updateCursor(){
-            Pipe currentPipe = container.pipeList.get(cursor);
+            Pipe currentPipe = container.subpipes.get(cursor);
             Iterator<Resource> it = iterators.get(currentPipe);
             do {
                 // go up to at best reach the last pipe, updating iterators & bindings of the
                 // all intermediates, if an intermediate pipe is not outputing anything
                 // anymore, stop.
-                while (it.hasNext() && cursor < container.pipeList.size() - 1) {
+                while (it.hasNext() && cursor < container.subpipes.size() - 1) {
                     Resource resource = it.next();
                     bindings.updateBindings(currentPipe, resource);
                     //now we update the following pipe output with that new context
-                    Pipe nextPipe = container.pipeList.get(++cursor);
+                    Pipe nextPipe = container.subpipes.get(++cursor);
                     iterators.put(nextPipe, nextPipe.getOutput());
                     currentPipe = nextPipe;
                     log.debug("switching to {}", currentPipe);
@@ -192,11 +130,11 @@ public class ContainerPipe extends BasePipe {
                 }
                 //go down (or stay) to the first pipe having a next item
                 while (!it.hasNext() && cursor > 0) {
-                    currentPipe = container.pipeList.get(--cursor);
+                    currentPipe = container.subpipes.get(--cursor);
                     log.debug("switching to {}", currentPipe);
                     it = iterators.get(currentPipe);
                 }
-            } while (it.hasNext() && cursor < container.pipeList.size() - 1);
+            } while (it.hasNext() && cursor < container.subpipes.size() - 1);
             //2 choices here:
             // either cursor is at 0 with no resource left: end,
             // either cursor is on last pipe with a resource left: hasNext
diff --git a/src/main/java/org/apache/sling/pipes/internal/NotPipe.java b/src/main/java/org/apache/sling/pipes/internal/NotPipe.java
index 76e4e18..63fafdb 100644
--- a/src/main/java/org/apache/sling/pipes/internal/NotPipe.java
+++ b/src/main/java/org/apache/sling/pipes/internal/NotPipe.java
@@ -19,7 +19,6 @@ package org.apache.sling.pipes.internal;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.pipes.PipeBindings;
 import org.apache.sling.pipes.Plumber;
-import org.apache.sling.pipes.ReferencePipe;
 
 import java.util.Collections;
 import java.util.Iterator;
@@ -37,7 +36,7 @@ public class NotPipe extends ReferencePipe {
     }
 
     @Override
-    protected Iterator<Resource> computeReferenceOutput() throws Exception {
+    protected Iterator<Resource> computeSubpipesOutput() throws Exception {
         if (reference.getOutput().hasNext()){
             return EMPTY_ITERATOR;
         }
diff --git a/src/main/java/org/apache/sling/pipes/internal/PipeBuilderImpl.java b/src/main/java/org/apache/sling/pipes/internal/PipeBuilderImpl.java
index 0dda842..775e55c 100644
--- a/src/main/java/org/apache/sling/pipes/internal/PipeBuilderImpl.java
+++ b/src/main/java/org/apache/sling/pipes/internal/PipeBuilderImpl.java
@@ -23,13 +23,11 @@ import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.event.jobs.Job;
 import org.apache.sling.pipes.BasePipe;
-import org.apache.sling.pipes.ContainerPipe;
 import org.apache.sling.pipes.ExecutionResult;
 import org.apache.sling.pipes.OutputWriter;
 import org.apache.sling.pipes.Pipe;
 import org.apache.sling.pipes.PipeBuilder;
 import org.apache.sling.pipes.Plumber;
-import org.apache.sling.pipes.ReferencePipe;
 import org.apache.sling.pipes.internal.inputstream.CsvPipe;
 import org.apache.sling.pipes.internal.inputstream.JsonPipe;
 import org.apache.sling.pipes.internal.inputstream.RegexpPipe;
diff --git a/src/main/java/org/apache/sling/pipes/internal/PlumberImpl.java b/src/main/java/org/apache/sling/pipes/internal/PlumberImpl.java
index 075957c..5fd5751 100644
--- a/src/main/java/org/apache/sling/pipes/internal/PlumberImpl.java
+++ b/src/main/java/org/apache/sling/pipes/internal/PlumberImpl.java
@@ -34,7 +34,6 @@ import org.apache.sling.event.jobs.Job;
 import org.apache.sling.event.jobs.JobManager;
 import org.apache.sling.event.jobs.consumer.JobConsumer;
 import org.apache.sling.pipes.BasePipe;
-import org.apache.sling.pipes.ContainerPipe;
 import org.apache.sling.pipes.ExecutionResult;
 import org.apache.sling.pipes.OutputWriter;
 import org.apache.sling.pipes.Pipe;
@@ -42,7 +41,6 @@ import org.apache.sling.pipes.PipeBindings;
 import org.apache.sling.pipes.PipeBuilder;
 import org.apache.sling.pipes.Plumber;
 import org.apache.sling.pipes.PlumberMXBean;
-import org.apache.sling.pipes.ReferencePipe;
 import org.apache.sling.pipes.internal.inputstream.CsvPipe;
 import org.apache.sling.pipes.internal.inputstream.JsonPipe;
 import org.apache.sling.pipes.internal.inputstream.RegexpPipe;
diff --git a/src/main/java/org/apache/sling/pipes/internal/PlumberServlet.java b/src/main/java/org/apache/sling/pipes/internal/PlumberServlet.java
index 1238c94..f3a0edb 100644
--- a/src/main/java/org/apache/sling/pipes/internal/PlumberServlet.java
+++ b/src/main/java/org/apache/sling/pipes/internal/PlumberServlet.java
@@ -24,7 +24,6 @@ import org.apache.sling.api.servlets.SlingAllMethodsServlet;
 import org.apache.sling.event.jobs.Job;
 import org.apache.sling.pipes.AbstractInputStreamPipe;
 import org.apache.sling.pipes.BasePipe;
-import org.apache.sling.pipes.ContainerPipe;
 import org.apache.sling.pipes.OutputWriter;
 import org.apache.sling.pipes.Plumber;
 import org.apache.sling.pipes.internal.slingquery.ChildrenPipe;
diff --git a/src/main/java/org/apache/sling/pipes/ReferencePipe.java b/src/main/java/org/apache/sling/pipes/internal/ReferencePipe.java
similarity index 51%
rename from src/main/java/org/apache/sling/pipes/ReferencePipe.java
rename to src/main/java/org/apache/sling/pipes/internal/ReferencePipe.java
index 3429205..6c0cd7a 100644
--- a/src/main/java/org/apache/sling/pipes/ReferencePipe.java
+++ b/src/main/java/org/apache/sling/pipes/internal/ReferencePipe.java
@@ -14,20 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.pipes;
+package org.apache.sling.pipes.internal;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.pipes.Pipe;
+import org.apache.sling.pipes.PipeBindings;
+import org.apache.sling.pipes.Plumber;
+import org.apache.sling.pipes.SuperPipe;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.script.ScriptException;
 import java.util.Iterator;
 
 /**
  * executes a pipe referred in the configuration
  */
-public class ReferencePipe extends BasePipe {
+public class ReferencePipe extends SuperPipe {
     private static final Logger log = LoggerFactory.getLogger(ReferencePipe.class);
 
     public static final String RESOURCE_TYPE = "slingPipes/reference";
@@ -44,59 +47,30 @@ public class ReferencePipe extends BasePipe {
     }
 
     @Override
-    public PipeBindings getBindings() {
-        return reference.getBindings();
-    }
-
-    /**
-     * Computing the pipe this pipe refers to, and make necessary bindings
-     * @throws Exception
-     */
-    protected void computeReference() throws Exception {
-        Resource pipeResource = resolver.getResource(referencePath);
-        if (pipeResource == null) {
-            throw new Exception("Reference configuration error: There is no resource at " + getExpr());
-        }
-        reference = plumber.getPipe(pipeResource, bindings);
-        if (reference == null) {
-            throw new Exception("Unable to build out pipe out of " + getPath());
-        }
-        reference.setReferrer(this);
-        log.info("set reference to {}", reference);
-
-        //bind parent to the reference
-        if (parent != null) {
-            reference.setParent(parent);
-        }
-    }
-
-    @Override
-    protected Iterator<Resource> computeOutput() throws Exception {
+    public void buildChildren() throws Exception {
         String expression = getExpr();
-        if (StringUtils.isNotBlank(expression) && !expression.equals(referencePath)){
+        if (StringUtils.isNotBlank(expression) && !expression.equals(referencePath)) {
             referencePath = expression;
-            computeReference();
+            Resource pipeResource = resolver.getResource(referencePath);
+            if (pipeResource == null) {
+                throw new Exception("Reference configuration error: There is no resource at " + getExpr());
+            }
+            reference = plumber.getPipe(pipeResource, bindings);
+            if (reference == null) {
+                throw new Exception("Unable to build out pipe out of " + getPath());
+            }
+            reference.setParent(this);
+            log.info("set reference to {}", reference);
+
+            subpipes.clear();
+            subpipes.add(reference);
         }
-        return computeReferenceOutput();
     }
 
-    /**
-     * @return referenced pipe output
-     * @throws Exception sent by reference piped execution
-     */
-    protected Iterator<Resource> computeReferenceOutput() throws Exception {
+    @Override
+    protected Iterator<Resource> computeSubpipesOutput() throws Exception {
         log.debug("getting {} output", reference);
         return reference.getOutput();
     }
 
-    @Override
-    public Object getOutputBinding() {
-        return reference.getOutputBinding();
-    }
-
-    @Override
-    public boolean modifiesContent() {
-        //assuming true in case we don't know yet to be on the safe side
-        return reference != null ? reference.modifiesContent() : true;
-    }
 }
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/pipes/internal/TraversePipe.java b/src/main/java/org/apache/sling/pipes/internal/TraversePipe.java
index 96ea1b5..66f3bf9 100644
--- a/src/main/java/org/apache/sling/pipes/internal/TraversePipe.java
+++ b/src/main/java/org/apache/sling/pipes/internal/TraversePipe.java
@@ -137,7 +137,7 @@ public class TraversePipe extends BasePipe {
                     }
                 }
             } catch (RepositoryException e) {
-                LOGGER.error("unable to read node children", e);
+                LOGGER.error("unable to read node subpipes", e);
             }
             return currentResources != null && currentResources.hasNext();
         }
diff --git a/src/main/java/org/apache/sling/pipes/internal/WritePipe.java b/src/main/java/org/apache/sling/pipes/internal/WritePipe.java
index 15644c0..b2f1526 100644
--- a/src/main/java/org/apache/sling/pipes/internal/WritePipe.java
+++ b/src/main/java/org/apache/sling/pipes/internal/WritePipe.java
@@ -135,7 +135,7 @@ public class WritePipe extends BasePipe {
      * Write properties from the configuration to the target resource,
      * instantiating both property names & values
      *
-     * @param conf configured resource that holds all properties to write (and children)
+     * @param conf configured resource that holds all properties to write (and subpipes)
      * @param target target resource on which configured values will be written
      * @throws RepositoryException issues occuring when traversing nodes
      */
diff --git a/src/test/java/org/apache/sling/pipes/AbstractPipeTest.java b/src/test/java/org/apache/sling/pipes/AbstractPipeTest.java
index c73e109..01932af 100644
--- a/src/test/java/org/apache/sling/pipes/AbstractPipeTest.java
+++ b/src/test/java/org/apache/sling/pipes/AbstractPipeTest.java
@@ -46,7 +46,8 @@ public class AbstractPipeTest {
     protected static final String PATH_FRUITS = ROOT + BasePipe.SLASH + NN_FRUITS;
     protected static final String BANANA_SUFFIX = "/banana";
     protected static final String PATH_BANANA = PATH_FRUITS + BANANA_SUFFIX;
-    protected static final String APPLE_SUFFIX = "/apple";
+    protected static final String NN_APPLE = "apple";
+    protected static final String APPLE_SUFFIX = BasePipe.SLASH + NN_APPLE;
     protected static final String PATH_APPLE = PATH_FRUITS + APPLE_SUFFIX;
     protected static final String PATH_PEA = PATH_APPLE + "/isnota/pea";
     protected static final String PATH_CARROT = PATH_APPLE + "/isnota/carrot";
diff --git a/src/test/java/org/apache/sling/pipes/ContainerPipeTest.java b/src/test/java/org/apache/sling/pipes/ContainerPipeTest.java
index acd991d..7337cd2 100644
--- a/src/test/java/org/apache/sling/pipes/ContainerPipeTest.java
+++ b/src/test/java/org/apache/sling/pipes/ContainerPipeTest.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.pipes.internal.ContainerPipe;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -100,7 +101,7 @@ public class ContainerPipeTest extends AbstractPipeTest {
 
     @Test
     public void testOnePipe() throws Exception {
-        assertTrue("There should be children", getOutput(PATH_PIPE + "/" + NN_ONEPIPE).hasNext());
+        assertTrue("There should be subpipes", getOutput(PATH_PIPE + "/" + NN_ONEPIPE).hasNext());
     }
 
     /**
@@ -128,4 +129,11 @@ public class ContainerPipeTest extends AbstractPipeTest {
         outputs.next();
         assertTrue("time spent should be bigger than interval", System.currentTimeMillis() - start > interval);
     }
+
+    @Test
+    public void testNested() throws Exception {
+        Pipe firstPipe = plumber.newPipe(context.resourceResolver()).echo(ROOT).echo(NN_FRUITS).build();
+        Pipe superPipe = plumber.newPipe(context.resourceResolver()).ref(firstPipe.getResource().getPath()).echo("apple").build();
+        testOneResource(superPipe.getResource().getPath(), PATH_APPLE);
+    }
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/pipes/dummies/DummySearch.java b/src/test/java/org/apache/sling/pipes/dummies/DummySearch.java
index 8b09423..84e5f80 100644
--- a/src/test/java/org/apache/sling/pipes/dummies/DummySearch.java
+++ b/src/test/java/org/apache/sling/pipes/dummies/DummySearch.java
@@ -28,7 +28,7 @@ import org.apache.sling.pipes.PipeBindings;
 import org.apache.sling.pipes.Plumber;
 
 /**
- * dummy search reads its conf node children and returns them.
+ * dummy search reads its conf node subpipes and returns them.
  */
 public class DummySearch extends BasePipe {
 
diff --git a/src/test/java/org/apache/sling/pipes/internal/ReferencePipeTest.java b/src/test/java/org/apache/sling/pipes/internal/ReferencePipeTest.java
index c506566..bf6961b 100644
--- a/src/test/java/org/apache/sling/pipes/internal/ReferencePipeTest.java
+++ b/src/test/java/org/apache/sling/pipes/internal/ReferencePipeTest.java
@@ -19,7 +19,6 @@ package org.apache.sling.pipes.internal;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.pipes.AbstractPipeTest;
 import org.apache.sling.pipes.Pipe;
-import org.apache.sling.pipes.ReferencePipe;
 import org.junit.Before;
 import org.junit.Test;
 
diff --git a/src/test/java/org/apache/sling/pipes/internal/WritePipeTest.java b/src/test/java/org/apache/sling/pipes/internal/WritePipeTest.java
index 78f4156..4ee6ee8 100644
--- a/src/test/java/org/apache/sling/pipes/internal/WritePipeTest.java
+++ b/src/test/java/org/apache/sling/pipes/internal/WritePipeTest.java
@@ -128,7 +128,7 @@ public class WritePipeTest extends AbstractPipeTest {
         assertArrayEquals("Colors should be correctly set", new String[]{"green", "red"}, properties.get("colors", String[].class));
         Node appleNode = appleResource.adaptTo(Node.class);
         NodeIterator children = appleNode.getNodes();
-        assertTrue("Apple node should have children", children.hasNext());
+        assertTrue("Apple node should have subpipes", children.hasNext());
     }
 
     @Test
@@ -148,7 +148,7 @@ public class WritePipeTest extends AbstractPipeTest {
         assertArrayEquals("index property should be the same", new String[] {"apple","banana"}, property.adaptTo(String[].class));
         List<Resource> resources = IteratorUtils.toList(root.listChildren());
         List<String> children = resources.stream().map(r -> r.getPath()).collect(Collectors.toList());
-        assertEquals("there should be 2 children", 2, children.size());
+        assertEquals("there should be 2 subpipes", 2, children.size());
         assertTrue("first should be apple", children.get(0).endsWith(APPLE_SUFFIX));
         assertTrue("second should be banana", children.get(1).endsWith(BANANA_SUFFIX));
     }
diff --git a/src/test/java/org/apache/sling/pipes/it/PipeBuilderIT.java b/src/test/java/org/apache/sling/pipes/it/PipeBuilderIT.java
index aa674fc..dc897a8 100644
--- a/src/test/java/org/apache/sling/pipes/it/PipeBuilderIT.java
+++ b/src/test/java/org/apache/sling/pipes/it/PipeBuilderIT.java
@@ -93,7 +93,7 @@ public class PipeBuilderIT extends PipesTestSupport {
             }
             Collection<String> results = plumber.newPipe(resolver).echo(ROOT).traverse().run().getCurrentPathSet();
             LOGGER.info("Following results are found {}", results);
-            assertEquals("we should have root and implemented children", 11, results.size());
+            assertEquals("we should have root and implemented subpipes", 11, results.size());
         }
     }
 }
diff --git a/src/test/java/org/apache/sling/pipes/models/PipeModelTest.java b/src/test/java/org/apache/sling/pipes/models/PipeModelTest.java
index 0a02ae6..98d4621 100644
--- a/src/test/java/org/apache/sling/pipes/models/PipeModelTest.java
+++ b/src/test/java/org/apache/sling/pipes/models/PipeModelTest.java
@@ -52,7 +52,7 @@ public class PipeModelTest extends AbstractPipeTest {
 
     @Test
     /**
-     * we've loaded under NN_PIPES all the pipes from container json (direct children): all those pipes output should be mounted
+     * we've loaded under NN_PIPES all the pipes from container json (direct subpipes): all those pipes output should be mounted
      * as outputs of the model
      */
     public void testInit(){

-- 
To stop receiving notification emails like this one, please contact
npeltier@apache.org.