You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by de...@apache.org on 2017/09/17 12:30:39 UTC

[myfaces-trinidad] 16/36: The first problem we have had is that components need to separate the context setup and teardown needed to process their children from the context setup and tear down of the components themselves. For example, consider a composite component that establishes an EL context for its children--that context should only be setup when the children are being processed, not when the component is processing its own attributes.

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

deki pushed a commit to branch 1.2.12.2-branch
in repository https://gitbox.apache.org/repos/asf/myfaces-trinidad.git

commit 821819f003a220e41d7b05ffd73fb446bc2699a0
Author: Blake Sullivan <bs...@apache.org>
AuthorDate: Tue Feb 9 18:34:05 2010 +0000

    The first problem we have had is that components need to separate the context setup and teardown needed to process their children from the context setup and tear down of the components themselves.  For example, consider a composite component that establishes an EL context for its children--that context should only be setup when the children are being processed, not when the component is processing its own attributes.
    
    In the case of encoding, we want to delegate to the Renderer to ensure that the setup and teardown of context for child processing is consistent between optimized rendering using tree visiting and full rendering traversals.
    
    The second problem was that UIXComponent.setUpEncodingContext was named differently than all of the other set up methods.  I've made the spelling consistent (which after a quick check of the dictionary is consitently wrong through out Trinidad setup as a compound word is a noun and as a verb is two words, so it should have been setUp.  Drat!) and temporarily left a final deprecated version in that I will whack shortly.
    
    The third issue is that iterating components often want to modify only the manner in which their data is iterated over.  To simplify this, we add a hook visitData() to UIXCollection.
    
    UIXComponent:
    
    /**
     * Hook for subclasses to override the manner in which the component's children are visited.  The default
     * implementation visits all of the children and facets of the Component.
     * <code>setupChildrenVisitingContext</code> will have been called before this method is
     * invoked and <code>tearDownChildrenVisitingContext</code> will be called after.
     * respectively.  If the purpose of this visit was to encode the component and the
     * component uses a CoreRenderer, the CoreRenderer's
     * <code>setupChildrenEncodingContext</code> and <code>tearDownChildrenEncodingContext</code>
     * will be called before and after this method is invoked, respectively.
     * @param visitContext the <code>VisitContext</code> for this visit
     * @param callback the <code>VisitCallback</code> instance
     * @return <code>true</code> if the visit is complete.
     * @see #setupChildrenVisitingContext
     * @see #tearDownChildrenVisitingContext
     * @see org.apache.myfaces.trinidad.render.CoreRenderer#setupChildrenEncodingContext
     * @see org.apache.myfaces.trinidad.render.CoreRenderer#tearDownChildrenEncodingContext
     */
     protected boolean visitChildren(
       VisitContext visitContext,
       VisitCallback callback)
    
     /**
      * <p>Sets up the context necessary to visit or invoke the children of a component for all phases.
      * </p>
      * <p>The default implementation does nothing.</p>
      * <p>If a subclass overrides this method, it should override
      * <code>tearDownChildrenVisitingContext</code> as well.</p>
      * <p>It is guaranteed that if <code>setupChildrenVisitingContext</code> completes
      * <code>tearDownChildrenVisitingContext</code> will be called for this component</p>
      * @param context FacesContext
      * @see #visitChildren
      * @see #tearDownChildrenVisitingContext
      */
     protected void setupChildrenVisitingContext(@SuppressWarnings("unused") FacesContext context)
    
     /**
      * <p>Tears down context created in order to visit or invoke the children of a component
      * for all phases.</p>
      * <p>The default implementation does nothing.</p>
      * <p>A subclass should only override this method if it overrode
      * <code>setupChildrenVisitingContext</code> as well</p>
      * <p>It is guaranteed that <code>tearDownChildrenVisitingContext</code> will be called only after
      * <code>setupChildrenVisitingContext</code> has been called for this component</p>
      * @param context FacesContext
      * @see #setupChildrenVisitingContext
      * @see #visitChildren
      */
     protected void tearDownChildrenVisitingContext(@SuppressWarnings("unused") FacesContext context)
    
    CoreRenderer
    
      * <p>
      * Called before rendering the current component's children in order to set
      * up any special context.
      * </p>
      * <p>If <code>setupChildrenEncodingContext</code> succeeds then
      * <code>tearDownChildrenEncodingContext</code> will be called for the same component.
      * </p>
      * <p>The default implementation does nothing</p>
      * @param context FacesContext for this request
      * @param rc RenderingContext for this encoding pass
      * @param component Component to encode using this Renderer
      * @see #tearDownChildrenEncodingContext
      */
     public void setupChildrenEncodingContext(
       @SuppressWarnings("unused") FacesContext context,
       @SuppressWarnings("unused") RenderingContext rc,
       @SuppressWarnings("unused") UIComponent component)
    
     /**
      * <p>
      * Called after rendering the current component's children in order to tear
      * down any special context.
      * </p>
      * <p>
      * <code>tearDownChildrenEncodingContext</code> will be called on the component if
      * <code>setupChildrenEncodingContext</code> succeeded.
      * </p>
      * <p>The default implementation does nothing</p>
      * @param context FacesContext for this request
      * @param rc RenderingContext for this encoding pass
      * @param component Component to encode using this Renderer
      * @see #setupChildrenEncodingContext
      */
     public void tearDownChildrenEncodingContext(
       @SuppressWarnings("unused") FacesContext context,
       @SuppressWarnings("unused") RenderingContext rc,
       @SuppressWarnings("unused") UIComponent component)
    
    UIXCollection:
    
     /**
      * Visit the rows and children of the columns of the collection per row-index. This should
      * not visit row index -1 (it will be perfomed in the visitTree method). The columns
      * themselves should not be visited, only their children in this function.
      *
      * @param visitContext The visiting context
      * @param callback The visit callback
      * @return true if the visiting should stop
      * @see #visitChildren(VisitContext, VisitCallback)
      */
     protected abstract boolean visitData(
       VisitContext  visitContext,
       VisitCallback callback);
---
 .../trinidad/component/UIXIteratorTemplate.java    | 280 ++++++++++++--
 .../component/UIXNavigationLevelTemplate.java      |  52 ++-
 .../component/UIXNavigationPathTemplate.java       |  74 ++++
 .../component/UIXNavigationTreeTemplate.java       |  42 ++-
 .../trinidad/component/UIXPageTemplate.java        |  87 ++++-
 .../trinidad/component/UIXProcessTemplate.java     |  54 ++-
 .../trinidad/component/UIXTableTemplate.java       |   1 -
 .../trinidad/component/UIXTreeTableTemplate.java   | 112 +++++-
 .../trinidad/component/UIXTreeTemplate.java        |  28 +-
 .../myfaces/trinidad/component/HierarchyUtils.java |  59 +--
 .../myfaces/trinidad/component/StampState.java     |   6 -
 .../myfaces/trinidad/component/TableUtils.java     |   8 +-
 .../myfaces/trinidad/component/UIXCollection.java  | 306 ++++++++++++++--
 .../myfaces/trinidad/component/UIXComponent.java   | 408 ++++++++++++++++-----
 .../trinidad/component/UIXComponentBase.java       |  64 +++-
 .../myfaces/trinidad/component/UIXHierarchy.java   | 106 +++++-
 .../trinidad/component/visit/VisitCallback.java    |   7 +-
 .../trinidad/component/visit/VisitContext.java     |   5 +-
 .../myfaces/trinidad/render/CoreRenderer.java      |  88 +++--
 .../myfaces/trinidad/util/CollectionUtils.java     |   2 -
 .../trinidad/component/UIComponentTestCase.java    |   4 +
 .../myfaces/trinidad/component/UIXProcessTest.java |  16 +
 .../component/core/nav/CoreBreadCrumbsTest.java    |  13 +
 .../trinidadinternal/context/FullVisitContext.java |  10 +-
 .../context/PartialVisitContext.java               |  12 +-
 .../renderkit/core/ppr/PartialPageContextImpl.java |  31 +-
 .../renderkit/core/xhtml/FormRenderer.java         |  19 -
 27 files changed, 1571 insertions(+), 323 deletions(-)

diff --git a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXIteratorTemplate.java b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXIteratorTemplate.java
index 7152e2b..85bafad 100644
--- a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXIteratorTemplate.java
+++ b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXIteratorTemplate.java
@@ -6,9 +6,9 @@
  *  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
@@ -21,25 +21,34 @@ package org.apache.myfaces.trinidad.component;
 import java.io.IOException;
 
 import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
-
 import java.util.Map;
 import java.util.Set;
+
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
 import javax.faces.event.PhaseId;
 
 import javax.faces.render.Renderer;
+
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
 import org.apache.myfaces.trinidad.model.CollectionModel;
 import org.apache.myfaces.trinidad.model.LocalRowKeyIndex;
 import org.apache.myfaces.trinidad.model.ModelUtils;
 
+import org.apache.myfaces.trinidad.render.ClientRowKeyManager;
+
 /**
  * This component iterates over some given data.
  * Each child is repeatedly stamped as many times as necessary.
  * Iteration is done starting at the index given by {@link #getFirst()}
  * for as many indices as specified by {@link #getRows()}.
- * If {@link #getRows()} returns 0, then the iteration continues until 
+ * If {@link #getRows()} returns 0, then the iteration continues until
  * there are no more elements in the underlying data.
  */
 public abstract class UIXIteratorTemplate extends UIXCollection implements FlattenedComponent, LocalRowKeyIndex
@@ -70,7 +79,7 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
     // Mimic what would normally happen in the non-flattening case for encodeBegin():
     __processFlattenedChildrenBegin();
 
-    Runner runner = new Runner(cpContext)
+    Runner runner = new IndexedRunner(cpContext)
     {
       @Override
       protected void process(UIComponent kid, ComponentProcessingContext cpContext) throws IOException
@@ -79,7 +88,7 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
       }
     };
     boolean processedChildren = runner.run();
-    Exception exp = runner.exception;
+    Exception exp = runner.getException();
     if (exp != null)
     {
       if (exp instanceof RuntimeException)
@@ -125,7 +134,7 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
     }
     else // this is not the table. it must be the iterator
     {
-      Runner runner = new Runner()
+      Runner runner = new IndexedRunner()
       {
         @Override
         protected void process(UIComponent kid,
@@ -135,7 +144,7 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
         }
       };
       runner.run();
-      Exception exp = runner.exception;
+      Exception exp = runner.getException();
       if (exp != null)
       {
         if (exp instanceof RuntimeException)
@@ -167,7 +176,7 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
       public Object get(Object key)
       {
         // some of these keys are from <c:forEach>, ie:
-        // javax.servlet.jsp.jstl.core.LoopTagStatus 
+        // javax.servlet.jsp.jstl.core.LoopTagStatus
         if ("begin".equals(key)) // from jstl
         {
           return Integer.valueOf(getFirst());
@@ -202,7 +211,7 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
     CollectionModel current,
     Object value)
   {
-    CollectionModel model = ModelUtils.toCollectionModel(value); 
+    CollectionModel model = ModelUtils.toCollectionModel(value);
     // initialize to -1. we need to do this incase some application logic
     // changed this index. Also, some JSF1.0 RI classes were initially starting
     // with a rowIndex of 0.
@@ -217,7 +226,7 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
     final FacesContext context,
     final PhaseId phaseId)
   {
-    Runner runner = new Runner()
+    Runner runner = new IndexedRunner()
     {
       @Override
       protected void process(UIComponent kid, ComponentProcessingContext cpContext)
@@ -228,6 +237,109 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
     runner.run();
   }
   
+  // Extract the current row token from the clientId
+  private String _getClientToken(String clientIdPrefix, String cellClientId)
+  {
+    int tokenStartIndex = clientIdPrefix.length() + 1;
+    int tokenEndIndex = cellClientId.indexOf(':', tokenStartIndex);
+    
+    if (tokenEndIndex != -1)
+    {
+      return cellClientId.substring(tokenStartIndex, tokenEndIndex);
+    }
+    else
+    {
+      return null;
+    }
+  }
+  
+  @Override
+  protected boolean visitData(
+    final VisitContext  visitContext,
+    final VisitCallback visitCallback)
+  {
+    Collection<String> subtreeIds = visitContext.getSubtreeIdsToVisit(this);
+ 
+    String ourClientIdPrefix = getClientId(visitContext.getFacesContext());
+   
+    int subtreeIdCount = subtreeIds.size();
+    
+    // build up a set of the row keys to visit rather than iterating
+    // and visiting every row
+    Set<String> rowsToVisit;
+    
+    if (subtreeIdCount > 1)
+    {
+      rowsToVisit = new HashSet<String>(subtreeIdCount);
+
+      for (String currClientId : subtreeIds)
+      {
+        String clientToken = _getClientToken(ourClientIdPrefix, currClientId);
+        
+        if (clientToken != null)
+        {
+          rowsToVisit.add(clientToken);          
+        }
+      }
+    }
+    else
+    {
+      String clientToken = _getClientToken(ourClientIdPrefix,
+                                           subtreeIds.iterator().next());
+      
+      if (clientToken != null)
+      {
+        rowsToVisit = Collections.singleton(clientToken);
+      }
+      else
+      {
+        rowsToVisit = Collections.emptySet();
+      }
+    }
+    
+    // we didn't visit any data
+    if (rowsToVisit.isEmpty())
+      return false;
+    
+    // create a special VisitContext that doesn't visit the Facets
+    // of column components since they aren't visited on each row
+    final VisitContext noColumnFacetContext = new NoColumnFacetsVisitContext(visitContext);
+    
+    // visit only the rows
+    Runner runner = new KeyedRunner(rowsToVisit)
+    {
+      @Override
+      protected void process(
+        UIComponent                kid,
+        ComponentProcessingContext cpContext
+        ) throws IOException
+      {
+        if (kid.getChildCount() > 0)
+        {
+          for (UIComponent grandKid : kid.getChildren())
+          {
+            if (UIXComponent.visitTree(noColumnFacetContext, grandKid, visitCallback))
+            {
+              throw new AbortProcessingException();
+            }
+          }
+        }
+      }
+    };
+
+    try
+    {
+      runner.run();
+    }
+    finally
+    {
+      return (runner.getException() instanceof AbortProcessingException);
+    }
+  }
+
+  /**
+   * Abstract class for processing rows
+   */
   private abstract class Runner implements ComponentProcessor<Object>
   {
     public Runner()
@@ -240,9 +352,79 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
       _cpContext = cpContext;
     }
     
+    public abstract boolean run();
+
+    /**
+     * Sets up the context for the child and processes it
+     */
+    public void processComponent(
+      FacesContext context,
+      ComponentProcessingContext cpContext,
+      UIComponent component,
+      Object callbackContext) throws IOException
+    {
+      try
+      {
+        process(component, cpContext);
+      }
+      catch (IOException ioe)
+      {
+        throw ioe;
+      }
+      catch (AbortProcessingException ape)
+      {
+        // we're done, so abort
+        _exception = ape;        
+        throw ape;
+      }
+      catch (Exception e)
+      {
+        _exception = e;
+      }
+    }
+    
+    public Exception getException()
+    {
+      return _exception;
+    }
+
+    protected abstract void process(UIComponent comp, ComponentProcessingContext cpContext)
+      throws Exception;
+
+    protected final ComponentProcessingContext getComponentProcessingContext()
+    {
+      return _cpContext;
+    }
+
+    public final void setException(Exception e)
+    {
+      _exception = e;
+    }
+    
+    private Exception _exception = null;
+
+    private final ComponentProcessingContext _cpContext;
+  }
+
+  /**
+   * Class for visiting getRows() by index rows starting getFirst()
+   */
+  private abstract class IndexedRunner extends Runner
+  {
+    public IndexedRunner()
+    {
+      this(null);
+    }
+
+    public IndexedRunner(ComponentProcessingContext cpContext)
+    {
+      super(cpContext);
+    }
+    
     public final boolean run()
     {
       FacesContext context = FacesContext.getCurrentInstance();
+      ComponentProcessingContext cpContext = getComponentProcessingContext();
       
       List<UIComponent> stamps = getStamps();
       int oldIndex = getRowIndex();
@@ -262,8 +444,8 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
           if (isRowAvailable())
           {
             // latch processedChild the first time we process a child
-            processedChild |= (_cpContext != null)
-              ? UIXComponent.processFlattenedChildren(context, _cpContext, this, stamps, null)
+            processedChild |= (cpContext != null)
+              ? UIXComponent.processFlattenedChildren(context, cpContext, this, stamps, null)
               : UIXComponent.processFlattenedChildren(context, this, stamps, null);
           }
           else
@@ -272,7 +454,7 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
       }
       catch (IOException e)
       {
-        exception = e;
+        setException(e);
       }
       finally
       {
@@ -281,38 +463,63 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
       
       return processedChild;
     }
+  }
 
-    /**
-     * Sets up the context for the child and processes it
-     */
-    public void processComponent(
-      FacesContext context,
-      ComponentProcessingContext cpContext,
-      UIComponent component,
-      Object callbackContext) throws IOException
+  /**
+   * Runner that visits the rows specified by the client row key tokens
+   */
+  private abstract class KeyedRunner extends Runner
+  {
+    public KeyedRunner(Iterable<String> clientKeys)
     {
+      super();
+      _clientKeys = clientKeys;
+    }
+    
+    public final boolean run()
+    {
+      FacesContext context = FacesContext.getCurrentInstance();
+     
+      List<UIComponent> stamps = getStamps();
+      int oldIndex = getRowIndex();
+            
+      boolean processedChild = false;
+            
       try
       {
-        process(component, cpContext);
+        // need to convert row key tokens to row keys
+        ClientRowKeyManager rowKeyManager = getClientRowKeyManager();
+
+        for(String clientKey : _clientKeys)
+        {
+          Object rowKey = rowKeyManager.getRowKey(context, UIXIterator.this, clientKey);
+          
+          if (rowKey != null)
+          {
+            setRowKey(rowKey);
+            if (isRowAvailable())
+            {
+              // latch processedChild the first time we process a child
+              processedChild |= UIXComponent.processFlattenedChildren(context, this, stamps, null);
+            }
+          }
+        }
       }
-      catch (IOException ioe)
+      catch (IOException e)
       {
-        throw ioe;
+        setException(e);
       }
-      catch (Exception e)
+      finally
       {
-        exception = e;
+        setRowIndex(oldIndex);
       }
+      
+      return processedChild;
     }
-
-    protected abstract void process(UIComponent comp, ComponentProcessingContext cpContext)
-      throws Exception;
-
-    public Exception exception = null;
-
-    private final ComponentProcessingContext _cpContext;
+    
+    private final Iterable<String> _clientKeys;
   }
-
+  
   @Override
   void __encodeBegin(FacesContext context) throws IOException
   {
@@ -355,7 +562,7 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
           first = 0;
         else
         {
-          // scroll to the last page: 
+          // scroll to the last page:
           first = size - rows;
           model.setRowIndex(first);
           // make sure the row is indeed available:
@@ -375,5 +582,4 @@ public abstract class UIXIteratorTemplate extends UIXCollection implements Flatt
       model.setRowIndex(oldIndex);
     }
   }
-
 }
diff --git a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationLevelTemplate.java b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationLevelTemplate.java
index e40e606..08cf59a 100644
--- a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationLevelTemplate.java
+++ b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationLevelTemplate.java
@@ -18,9 +18,13 @@
  */
 package org.apache.myfaces.trinidad.component;
 
+import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import javax.faces.event.PhaseId;
 
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+
 
 /**
  * Base class for the NavigationLevel component.
@@ -39,17 +43,61 @@ abstract public class UIXNavigationLevelTemplate extends UIXNavigationHierarchy
   {
     Object oldPath = getRowKey();
     HierarchyUtils.__setStartDepthPath(this, getLevel());
+    
     // process stamp for one level
     HierarchyUtils.__processLevel(context, phaseId, this);
     setRowKey(oldPath);
 
-
     // process the children
     TableUtils.__processChildren(context, this, phaseId);
   }
 
+  @Override
+  protected boolean visitChildren(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    boolean done = visitData(visitContext, callback);
 
+    if (!done)
+    {
+      // process the children
+      int childCount = getChildCount();
+      if (childCount > 0)
+      {
+        for (UIComponent child : getChildren())
+        {
+          done = UIXComponent.visitTree(visitContext, child, callback);
+          
+          if (done)
+            break;
+        }
+      }          
+    }
+    
+    return done;
+  }
+  
+  @Override
+  protected boolean visitData(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    Object oldKey = getRowKey();
+       
+    boolean done;
 
+    HierarchyUtils.__setStartDepthPath(this, getLevel());
 
-
+    try
+    {
+      done = visitLevel(visitContext, callback, getStamps());
+    }
+    finally
+    {
+      setRowKey(oldKey);
+    }
+    
+    return done;
+  }
 }
diff --git a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationPathTemplate.java b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationPathTemplate.java
index 10c7d23..f2e7d71 100644
--- a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationPathTemplate.java
+++ b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationPathTemplate.java
@@ -25,6 +25,9 @@ import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import javax.faces.event.PhaseId;
 
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+
 
 /**
  * Base class for the NavigationPath component.
@@ -68,5 +71,76 @@ abstract public class UIXNavigationPathTemplate extends UIXNavigationHierarchy
     TableUtils.__processChildren(context, this, phaseId);
   }  
 
+  @Override
+  protected boolean visitChildren(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    boolean done = visitData(visitContext, callback);
+    
+    if (!done)
+    {
+      // process the children
+      int childCount = getChildCount();
+      if (childCount > 0)
+      {
+        for (UIComponent child : getChildren())
+        {
+          done = UIXComponent.visitTree(visitContext, child, callback);
+          
+          if (done)
+            break;
+        }
+      }          
+    }
+    
+    return done;
+  }
+  
+  @Override
+  protected boolean visitData(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    Object focusPath = getFocusRowKey();
+    Object oldRowKey = null;
+    
+    boolean done = false;
+    
+    // start from the focused area
+    if (focusPath != null)
+    {
+      List<UIComponent> stamps = getStamps();
+      
+      if (!stamps.isEmpty())
+      {
+        List<Object> paths =  new ArrayList<Object>(getAllAncestorContainerRowKeys(focusPath));
+        paths.add(focusPath);
+        
+        int focusPathSize = paths.size();
+        
+        try
+        {
+          for (int i = 0; i < focusPathSize && !done; i++)
+          {
+            setRowKey(paths.get(i));
+            
+            for (UIComponent stamp : stamps)
+            {
+              done = UIXComponent.visitTree(visitContext, stamp, callback);
+              
+              if (done)
+                break;
+            }
+          }
+        }
+        finally
+        {
+          setRowKey(oldRowKey);
+        }
+      }
+    }
     
+    return done;
+  } 
 }
diff --git a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationTreeTemplate.java b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationTreeTemplate.java
index daaf0b8..37da902 100644
--- a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationTreeTemplate.java
+++ b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXNavigationTreeTemplate.java
@@ -29,6 +29,9 @@ import javax.faces.event.PhaseId;
 
 import org.apache.myfaces.trinidad.bean.FacesBean;
 import org.apache.myfaces.trinidad.bean.PropertyKey;
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+import org.apache.myfaces.trinidad.component.visit.VisitHint;
 import org.apache.myfaces.trinidad.model.CollectionModel;
 import org.apache.myfaces.trinidad.model.RowKeySet;
 import org.apache.myfaces.trinidad.model.RowKeySetTreeImpl;
@@ -93,7 +96,7 @@ abstract public class UIXNavigationTreeTemplate extends UIXNavigationHierarchy
     // this component has no facets that need to be processed once.
     // instead process the "nodeStamp" facet as many times as necessary:
     Object oldPath = getRowKey();
-    HierarchyUtils.__setStartLevelPath(this, getStartLevel());
+    HierarchyUtils.__setStartDepthPath(this, getStartLevel());
     HierarchyUtils.__iterateOverTree(context,
                                       phaseId,
                                       this,
@@ -103,6 +106,43 @@ abstract public class UIXNavigationTreeTemplate extends UIXNavigationHierarchy
   }
 
   @Override
+  protected boolean visitChildren(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    return visitData(visitContext, callback);
+  }
+  
+  @Override
+  protected boolean visitData(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    Object oldRowKey = getRowKey();
+
+    // if we are only visiting rendered stamps, then pass in the disclosed row keys, otherwise
+    // pass in null, indicating that all row keys should be visited
+    RowKeySet disclosedRowKeys = (visitContext.getHints().contains(VisitHint.SKIP_UNRENDERED))
+                                   ? getDisclosedRowKeys()
+                                   : null;
+    
+    boolean done;
+
+    HierarchyUtils.__setStartDepthPath(this, getStartLevel());
+
+    try
+    {
+      done = visitHierarchy(visitContext, callback, getStamps(), disclosedRowKeys);
+    }
+    finally
+    {
+      setRowKey(oldRowKey);
+    }
+    
+    return done;
+  }
+  
+  @Override
   void __encodeBegin(FacesContext context) throws IOException
   {
     HierarchyUtils.__handleEncodeBegin(this, getDisclosedRowKeys());
diff --git a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXPageTemplate.java b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXPageTemplate.java
index fc79abf..71920e5 100644
--- a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXPageTemplate.java
+++ b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXPageTemplate.java
@@ -25,13 +25,15 @@ import java.util.Map;
 
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
-import javax.faces.el.MethodBinding;
 import javax.faces.event.AbortProcessingException;
 import javax.faces.event.FacesEvent;
 import javax.faces.event.PhaseId;
 
 import org.apache.myfaces.trinidad.bean.FacesBean;
 import org.apache.myfaces.trinidad.bean.PropertyKey;
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+import org.apache.myfaces.trinidad.component.visit.VisitHint;
 import org.apache.myfaces.trinidad.model.CollectionModel;
 import org.apache.myfaces.trinidad.model.RowKeySet;
 import org.apache.myfaces.trinidad.model.RowKeySetTreeImpl;
@@ -115,7 +117,90 @@ abstract public class UIXPageTemplate extends UIXMenuHierarchy
         processComponent(context, facets.get(facetKey), phaseId);
       }
     }
+  }
+  
+  @Override
+  protected boolean visitChildren(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    boolean done = visitData(visitContext, callback);
+    
+    if (!done)
+    {
+      // process the children
+      int childCount = getChildCount();
+      if (childCount > 0)
+      {
+        for (UIComponent child : getChildren())
+        {
+          done = UIXComponent.visitTree(visitContext, child, callback);
+          
+          if (done)
+            break;
+        }
+      }
+      
+      // process the non-stamp facet children
+      if (!done)
+      {
+        // Visit the facets except for the node stamp
+        int facetCount = getFacetCount();
+        
+        if (facetCount > 0)
+        {
+          UIComponent nodeStamp = getNodeStamp();
+          
+          // if our only facet is the node stamp, we don't need to do this
+          if ((facetCount > 1) || (nodeStamp == null))
+          {
+            for (UIComponent facet : getFacets().values())
+            {
+              // ignore the nodeStamp facet, since it is stamped
+              if (facet != nodeStamp)
+              {
+                if (UIXComponent.visitTree(visitContext, facet, callback))
+                {
+                  done = true;
+                  break;
+                }
+              }
+            }
+          }
+        }        
+      }
+    }
+    
+    return done;
+  }
+  
+  @Override
+  protected boolean visitData(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    Object oldPath = getRowKey();
+
+    // if we are only visiting rendered stamps, then pass in the disclosed row keys, otherwise
+    // pass in null, indicating that all row keys should be visited
+    RowKeySet disclosedRowKeys = (visitContext.getHints().contains(VisitHint.SKIP_UNRENDERED))
+                                   ? getDisclosedRowKeys()
+                                   : null;
 
+    setRowKey(null);
+
+    boolean done;
+    
+    try
+    {
+      done = visitHierarchy(visitContext, callback, getStamps(), disclosedRowKeys);
+    }
+    finally
+    {
+      setRowKey(oldPath);
+    }
+    
+    return done;
   }
 
   @Override
diff --git a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXProcessTemplate.java b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXProcessTemplate.java
index 0169371..91dd258 100644
--- a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXProcessTemplate.java
+++ b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXProcessTemplate.java
@@ -18,9 +18,13 @@
  */
 package org.apache.myfaces.trinidad.component;
 
+import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import javax.faces.event.PhaseId;
 
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+
 
 /**
  * Base class for the Process component, which shows the steps of a process.
@@ -44,9 +48,55 @@ abstract public class UIXProcessTemplate extends UIXMenuHierarchy
     
     // process the children
     TableUtils.__processChildren(context, this, phaseId);
-    
   }  
 
+  @Override
+  protected boolean visitChildren(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    boolean done = visitData(visitContext, callback);
+    
+    if (!done)
+    {
+      // process the children
+      int childCount = getChildCount();
+      if (childCount > 0)
+      {
+        for (UIComponent child : getChildren())
+        {
+          done = UIXComponent.visitTree(visitContext, child, callback);
+          
+          if (done)
+            break;
+        }
+      }          
+    }
+    
+    return done;
+  }
   
-  
+  @Override
+  protected boolean visitData(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    Object oldKey = getRowKey();
+       
+    Object focusPath = getFocusRowKey();    
+    setRowKey(focusPath);  
+    
+    boolean done;
+
+    try
+    {
+      done = visitLevel(visitContext, callback, getStamps());
+    }
+    finally
+    {
+      setRowKey(oldKey);
+    }
+        
+    return done;
+  }
 }
diff --git a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTableTemplate.java b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTableTemplate.java
index e2f09ec..2b286aa 100644
--- a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTableTemplate.java
+++ b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTableTemplate.java
@@ -24,7 +24,6 @@ import java.util.ArrayList;
 import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Set;
 
 import javax.el.MethodExpression;
 
diff --git a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTreeTableTemplate.java b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTreeTableTemplate.java
index b7ff644..31c9f6a 100644
--- a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTreeTableTemplate.java
+++ b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTreeTableTemplate.java
@@ -36,11 +36,12 @@ import javax.faces.event.AbortProcessingException;
 import javax.faces.event.FacesEvent;
 import javax.faces.event.PhaseId;
 
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
 import org.apache.myfaces.trinidad.event.FocusEvent;
 import org.apache.myfaces.trinidad.event.RangeChangeEvent;
 import org.apache.myfaces.trinidad.event.RangeChangeListener;
 import org.apache.myfaces.trinidad.model.RowKeySet;
-import org.apache.myfaces.trinidad.model.TreeModel;
 
 /**
  * Base class for TreeTable component. The behaviours implemented by the
@@ -274,19 +275,36 @@ abstract public class UIXTreeTableTemplate extends UIXTree
    */
   // TODO cache the result.
   @Override
-  @SuppressWarnings("unchecked")
-  protected final List getStamps()
+  protected final List<UIComponent> getStamps()
   {
+    
     List<UIComponent> children = getChildren();
-    UIComponent nodeStamp = getNodeStamp();
-    if (nodeStamp != null)
+    List<UIComponent> stamps;
+    
+    if (children.isEmpty())
+    {
+      // no children, so use Node stamps as the stamp
+      stamps = super.getStamps();
+    }
+    else
     {
-      List<UIComponent> stamps = new ArrayList<UIComponent>(children.size() + 1);
-      stamps.addAll(children);
-      stamps.add(nodeStamp);
-      return stamps;
+      UIComponent nodeStamp = getNodeStamp();
+      
+      if (nodeStamp == null)
+      {
+        // no node stamp, so stamp, is only the children
+        stamps = children;
+      }
+      else
+      {
+        // stamps are the children plus the node stamp
+        stamps = new ArrayList<UIComponent>(children.size() + 1);
+        stamps.addAll(children);
+        stamps.add(nodeStamp);
+      }
     }
-    return children;
+    
+    return stamps;
   }
 
   /**
@@ -383,6 +401,80 @@ abstract public class UIXTreeTableTemplate extends UIXTree
     }
   }
 
+  @Override
+  protected boolean visitChildren(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    // need to override to do the default since our superclass
+    // UIXTree does stuff here we don't want
+    return defaultVisitChildren(visitContext, callback);
+  }
+
+  @Override
+  protected boolean visitUnstampedFacets(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    // Visit the facets except for the node stamp
+    int facetCount = getFacetCount();
+    
+    if (facetCount > 0)
+    {
+      UIComponent nodeStamp = getNodeStamp();
+      
+      // if our only facet is the node stamp, we don't need to do this
+      if ((facetCount > 1) || (nodeStamp == null))
+      {
+        for (UIComponent facet : getFacets().values())
+        {
+          // ignore the nodeStamp facet, since it is stamped
+          if (facet != nodeStamp)
+          {
+            if (UIXComponent.visitTree(visitContext, facet, callback))
+            {
+              return true;
+            }
+          }
+        }
+      }
+    }
+
+    return false;
+  }
+
+  @Override
+  protected boolean visitData(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    Object focusedPath = getFocusRowKey();
+    Object oldRowKey = null;
+    
+    // start from the focused area
+    if (focusedPath != null)
+    {
+      oldRowKey = getRowKey();
+      setRowKey(focusedPath);
+    }
+    
+    boolean done;
+    
+    try
+    {
+      done = super.visitData(new NoColumnFacetsVisitContext(visitContext), callback);
+    }
+    finally
+    {
+      if (focusedPath != null)
+      {
+        setRowKey(oldRowKey);
+      }
+    }
+    
+    return done;
+  }
+
   /**
    * Gets the path of the parent
    */
diff --git a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTreeTemplate.java b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTreeTemplate.java
index 928c06d..099c1db 100644
--- a/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTreeTemplate.java
+++ b/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXTreeTemplate.java
@@ -31,6 +31,9 @@ import javax.faces.event.PhaseId;
 
 import org.apache.myfaces.trinidad.bean.FacesBean;
 import org.apache.myfaces.trinidad.bean.PropertyKey;
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+import org.apache.myfaces.trinidad.component.visit.VisitHint;
 import org.apache.myfaces.trinidad.event.RowDisclosureEvent;
 import org.apache.myfaces.trinidad.event.SelectionEvent;
 import org.apache.myfaces.trinidad.model.CollectionModel;
@@ -138,17 +141,36 @@ abstract public class UIXTreeTemplate extends UIXHierarchy
   {
     // this component has no facets that need to be processed once.
     // instead process the "nodeStamp" facet as many times as necessary:
-    Object oldPath = getRowKey();
-    setRowKey(null);
     HierarchyUtils.__iterateOverTree(context,
                                      phaseId,
                                      this,
                                      getDisclosedRowKeys(),
                                      true);
-    setRowKey(oldPath);
   }
 
   @Override
+  protected boolean visitChildren(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    return visitData(visitContext, callback);
+  }
+  
+  @Override
+  protected boolean visitData(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    // if we are only visiting rendered stamps, then pass in the disclosed row keys, otherwise
+    // pass in null, indicating that all row keys should be visited
+    RowKeySet disclosedRowKeys = (visitContext.getHints().contains(VisitHint.SKIP_UNRENDERED))
+                                   ? getDisclosedRowKeys()
+                                   : null;
+    
+    return visitHierarchy(visitContext, callback, getStamps(), disclosedRowKeys);
+  }
+  
+  @Override
   void __init()
   {
     super.__init();
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/HierarchyUtils.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/HierarchyUtils.java
index 79ed000..870aea0 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/HierarchyUtils.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/HierarchyUtils.java
@@ -114,44 +114,47 @@ public final class HierarchyUtils
   {
     UIComponent nodeStamp = comp.getFacet("nodeStamp");
     int oldRow = comp.getRowIndex();
-    int first = comp.getFirst();
-    int last = TableUtils.getLast(comp, first);
-    for(int i=first; i<=last; i++)
+    
+    try
     {
-      comp.setRowIndex(i);
-      if (processChildrenAsStamps)
-        TableUtils.__processStampedChildren(context, comp, phaseId);
-      comp.processComponent(context, nodeStamp, phaseId);
-      if (comp.isContainer() && (state.isContained()))
+      int first = comp.getFirst();
+      int last = TableUtils.getLast(comp, first);
+      for(int i=first; i<=last; i++)
       {
-        comp.enterContainer();
-        __iterateOverTree( context, 
-                           phaseId, 
-                           comp, 
-                           state, 
-                           processChildrenAsStamps);
-        comp.exitContainer();
+        comp.setRowIndex(i);
+        if (processChildrenAsStamps)
+          TableUtils.__processStampedChildren(context, comp, phaseId);
+        comp.processComponent(context, nodeStamp, phaseId);
+        if (comp.isContainer() && (state.isContained()))
+        {
+          comp.enterContainer();
+          
+          try
+          {
+            __iterateOverTree( context, 
+                               phaseId, 
+                               comp, 
+                               state, 
+                               processChildrenAsStamps);
+          }
+          finally
+          {
+            comp.exitContainer();
+          }
+        }
       }
     }
-    comp.setRowIndex(oldRow);
-  }
-
-  // sets the currency to the row or container that we want to start rendering
-  // from:
-  static boolean __setStartLevelPath(
-    UIXHierarchy component,
-    int          startDepth
-  )
-  {
-    return HierarchyUtils.__setStartDepthPath(component, startDepth);
+    finally
+    {
+      comp.setRowIndex(oldRow);
+    }
   }
 
   // sets the currency to the row or container that we want to start rendering
   // from:
   static boolean __setStartDepthPath(
     UIXHierarchy component,
-    int          startDepth
-  )
+    int          startDepth)
   {
     boolean isNewPath = false;
     Object focusKey = component.getFocusRowKey();
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/StampState.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/StampState.java
index bde0858..841dd09 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/StampState.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/StampState.java
@@ -116,12 +116,6 @@ final class StampState implements Externalizable
   public static void restoreStampState(FacesContext context, UIComponent stamp,
                                        Object stampState)
   {
-    String stampId = stamp.getId();
-    // Force the ID to be reset to reset the client identifier (needed
-    // for UIComponentBase implementation which caches clientId too
-    // aggressively)
-    stamp.setId(stampId);
-
     if (stampState != null)
     {
       RowState state = (RowState) stampState;
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/TableUtils.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/TableUtils.java
index 5d00642..3a27363 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/TableUtils.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/TableUtils.java
@@ -18,7 +18,6 @@
  */
 package org.apache.myfaces.trinidad.component;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -280,6 +279,9 @@ public final class TableUtils
       @Override
       protected void process(FacesContext context, UIComponent child)
       {
+        // make sure that any cached clientIds are cleared so that
+        // the clientIds are recalculated with the new row index
+        UIXComponent.clearCachedClientIds(child);
         table.processComponent(context, child, phaseId);
       }
     }.runAlways(context, table);
@@ -299,11 +301,11 @@ public final class TableUtils
     int childCount = comp.getChildCount();
     if (childCount != 0)
     {
-      List children = comp.getChildren();
+      List<UIComponent> children = comp.getChildren();
 
       for (int i = 0; i < childCount; i++)
       {
-        UIComponent child = (UIComponent)children.get(i);
+        UIComponent child = children.get(i);
         comp.processComponent(context, child, phaseId);
       }
     }          
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
index 7b8ff6c..1b3ec68 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
@@ -23,6 +23,7 @@ import java.io.ObjectInputStream;
 import java.io.Serializable;
 
 import java.util.AbstractMap;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -40,6 +41,10 @@ import javax.faces.render.Renderer;
 
 import org.apache.myfaces.trinidad.bean.FacesBean;
 import org.apache.myfaces.trinidad.bean.PropertyKey;
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+import org.apache.myfaces.trinidad.component.visit.VisitHint;
+import org.apache.myfaces.trinidad.component.visit.VisitResult;
 import org.apache.myfaces.trinidad.event.SelectionEvent;
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.model.CollectionModel;
@@ -294,7 +299,9 @@ public abstract class UIXCollection extends UIXComponentBase
     }
     else
     {
-      superState = stampState = clientKeyMgr = null;
+      superState = null;
+      stampState = null;
+      clientKeyMgr = null;
     }
     super.restoreState(context, superState);
 
@@ -320,7 +327,7 @@ public abstract class UIXCollection extends UIXComponentBase
   /**
    * Checks to see if the current row is available. This is useful when the
    * total number of rows is not known.
-   * @see CollectionModel#isRowAvailable
+   * @see CollectionModel#isRowAvailable()
    * @return true iff the current row is available.
    */
   public final boolean isRowAvailable()
@@ -427,7 +434,7 @@ public abstract class UIXCollection extends UIXComponentBase
 
   /**
    * Gets the data for the current row.
-   * @see CollectionModel#getRowData
+   * @see CollectionModel#getRowData(int)
    * @return null if the current row is unavailable
    */
   public final Object getRowData()
@@ -536,7 +543,7 @@ public abstract class UIXCollection extends UIXComponentBase
   /**
    * Clear the rowKey-to-currencyString cache.
    * The cache is not cleared immediately; instead it will be cleared
-   * when {@link #encodeBegin} is called.
+   * when {@link #encodeBegin(FacesContext)} is called.
    * @deprecated Have your Renderer implement {@link ClientRowKeyManagerFactory}
    * and create your own {@link ClientRowKeyManager} instances. Then you can
    * manage the lifecycle of each key inside your ClientRowKeyManager.
@@ -800,6 +807,11 @@ public abstract class UIXCollection extends UIXComponentBase
     }
 
     _restoreStampState();
+
+    // ensure the client IDs are reset on the component, otherwise they will not get the
+    // proper stamped IDs. This mirrors the behavior in UIData and follows the JSF specification
+    // on when client IDs are allowed to be cached and when they must be reset
+    clearCachedClientIds();
   }
 
   /**
@@ -856,7 +868,7 @@ public abstract class UIXCollection extends UIXComponentBase
     // just having stamp state, and having stamp state + child/facet state
     assert(!(stampState instanceof Object[]));
 
-    int facetCount = _getFacetCount(stamp);
+    int facetCount = stamp.getFacetCount();
 
     Object[] state = null;
 
@@ -943,11 +955,6 @@ public abstract class UIXCollection extends UIXComponentBase
     // Just a transient component - return
     if ((stampState == Transient.TRUE) || (stampState == null))
     {
-      // ensure the client IDs are reset on the component, otherwise they will not get the
-      // proper stamped IDs. This mirrors the behavior in UIData and follows the JSF specification
-      // on when client IDs are allowed to be cached and when they must be reset
-      String id = stamp.getId();
-      stamp.setId(id);
       return;
     }
 
@@ -997,7 +1004,7 @@ public abstract class UIXCollection extends UIXComponentBase
 
   /**
    * Process a component.
-   * This method calls {@link #processDecodes},
+   * This method calls {@link #processDecodes(FacesContext)},
    * {@link #processValidators} or
    * {@link #processUpdates}
    * depending on the {#link PhaseId}.
@@ -1147,6 +1154,268 @@ public abstract class UIXCollection extends UIXComponentBase
   }
 
   /**
+   * <p>
+   * Override default children visiting code to visit the facets and facets of the columns
+   * before delegating to the <code>visitData</code> to visit the individual rows of data.
+   * </p><p>
+   * Subclasses should override this method if they wish to change the way in which the non-stamped
+   * children are visited.  If they wish to change the wash the the stamped children are visited,
+   * they should override <code>visitData</code> instead.
+   * </p>
+   * @param visitContext
+   * @param callback
+   * @return <code>true</code> if all of the children to visit have been visited
+   * @see #visitData
+   */
+  @Override
+  protected boolean visitChildren(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    return defaultVisitChildren(visitContext, callback);
+  }
+  
+  protected final boolean defaultVisitChildren(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    boolean doneVisiting;
+    
+    // Clear out the row index if one is set so that
+    // we start from a clean slate.
+    int oldRowIndex = getRowIndex();
+    setRowIndex(-1);
+
+    try
+    {
+      // visit the unstamped children
+      doneVisiting = visitUnstampedFacets(visitContext, callback);
+      
+      if (!doneVisiting)
+      {
+        doneVisiting = _visitStampedColumnFacets(visitContext, callback);
+        
+        // visit the stamped children
+        if (!doneVisiting)
+        {
+          doneVisiting = visitData(visitContext, callback);
+        }
+      }
+    }
+    finally
+    {
+      // restore the original rowIndex
+      setRowIndex(oldRowIndex);      
+    }
+    
+    return doneVisiting;    
+  }
+  
+  /**
+   * Hook method for subclasses to override to change the behavior
+   * of how unstamped facets of the UIXCollection are visited.  The
+   * Default implementation visits all of the facets of the
+   * UIXCollection.
+   */
+  protected boolean visitUnstampedFacets(
+    VisitContext  visitContext,
+    VisitCallback callback)
+  {
+    // Visit the facets with no row
+    if (getFacetCount() > 0)
+    {
+      for (UIComponent facet : getFacets().values())
+      {
+        if (UIXComponent.visitTree(visitContext, facet, callback))
+        {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+  
+  /**
+   * Wrapper implementation of VisitContext
+   */
+  private static abstract class VisitContextWrapper extends VisitContext
+  {
+    protected abstract VisitContext getWrapped();
+
+    @Override
+    public FacesContext getFacesContext()
+    {
+      return getWrapped().getFacesContext();
+    }
+    
+    @Override
+    public PhaseId getPhaseId()
+    {
+      return getWrapped().getPhaseId();
+    }
+
+    @Override
+    public Collection<String> getIdsToVisit()
+    {
+      return getWrapped().getIdsToVisit();
+    }
+
+    @Override
+    public Collection<String> getSubtreeIdsToVisit(UIComponent component)
+    {
+      return getWrapped().getSubtreeIdsToVisit(component);
+    }
+
+    @Override
+    public VisitResult invokeVisitCallback(UIComponent component, VisitCallback callback)
+    {
+      return getWrapped().invokeVisitCallback(component, callback);
+    }
+
+    @Override
+    public Set<VisitHint> getHints()
+    {
+      return getWrapped().getHints();
+    }
+  }
+  
+  /**
+   * VistiContext that visits the facets of the UIXColumn children, including
+   * nested UIXColumn childrem
+   */
+  private static class ColumnFacetsOnlyVisitContext extends VisitContextWrapper
+  {
+    public ColumnFacetsOnlyVisitContext(VisitContext wrappedContext)
+    {
+      _wrapped = wrappedContext;
+    }
+    
+    @Override
+    protected VisitContext getWrapped()
+    {
+      return _wrapped;
+    }
+    
+    @Override
+    public VisitResult invokeVisitCallback(UIComponent component, VisitCallback callback)
+    {
+      if (component instanceof UIXColumn)
+      {
+        if (component.getFacetCount() > 0)
+        {
+          // visit the facet children without filtering for just UIXColumn children
+          for (UIComponent facetChild : component.getFacets().values())
+          {
+            if (UIXComponent.visitTree(getWrapped(), facetChild, callback))
+              return VisitResult.COMPLETE;
+          }
+          
+          // visit the indexed children, recursively looking for more columns
+          for (UIComponent child : component.getChildren())
+          {
+            if (UIXComponent.visitTree(this, child, callback))
+              return VisitResult.COMPLETE;
+          }
+        }
+      }
+      
+      // at this point, we either have already manually processed the UIXColumn's children, or
+      // the component wasn't a UIXColumn and shouldn't be processed
+      return VisitResult.REJECT;
+    }
+    
+    private final VisitContext _wrapped;
+  }
+
+  /**
+   * VisitContext implementation that doesn't visit any of the Facets of
+   * UIXColumn children.  This is used when stamping children
+   */
+  protected static final class NoColumnFacetsVisitContext extends VisitContextWrapper
+  {
+    NoColumnFacetsVisitContext(VisitContext wrapped)
+    {
+      _wrapped = wrapped;
+    }
+
+    @Override
+    protected VisitContext getWrapped()
+    {
+      return _wrapped;
+    }
+
+    @Override
+    public VisitResult invokeVisitCallback(UIComponent component, VisitCallback callback)
+    {
+      if (component instanceof UIXColumn)
+      {
+        if (component.getChildCount() > 0)
+        {
+          // visit only the indexed children of the columns
+          for (UIComponent child : component.getChildren())
+          {
+            if (UIXComponent.visitTree(this, child, callback))
+              return VisitResult.COMPLETE;
+          }
+        }
+        
+        return VisitResult.REJECT;
+      }
+      else
+      {
+        if (UIXComponent.visitTree(getWrapped(), component, callback))
+          return VisitResult.COMPLETE;
+        else
+          return VisitResult.REJECT;
+      }
+    }
+    
+    private final VisitContext _wrapped;
+  }
+  
+  /**
+   * Implementation used to visit each stamped row
+   */
+  private boolean _visitStampedColumnFacets(
+    VisitContext      visitContext,
+    VisitCallback     callback)
+  {    
+    // visit the facets of the stamped columns
+    List<UIComponent> stamps = getStamps();
+    
+    if (!stamps.isEmpty())
+    {
+      VisitContext columnVisitingContext = new ColumnFacetsOnlyVisitContext(visitContext);
+      
+      for (UIComponent stamp : stamps)
+      {
+        if (UIXComponent.visitTree(columnVisitingContext, stamp, callback))
+        {
+          return true;
+        }
+      }
+    }
+    
+    return false;
+  }
+
+
+  /**
+   * Visit the rows and children of the columns of the collection per row-index. This should
+   * not visit row index -1 (it will be perfomed in the visitTree method). The columns
+   * themselves should not be visited, only their children in this function.
+   *
+   * @param visitContext The visiting context
+   * @param callback The visit callback
+   * @return true if the visiting should stop
+   * @see #visitChildren(VisitContext, VisitCallback)
+   */
+  protected abstract boolean visitData(
+    VisitContext  visitContext,
+    VisitCallback callback);
+
+  /**
    * Gets the CollectionModel to use with this component.
    *
    * @param createIfNull  creates the collection model if necessary
@@ -1359,7 +1628,7 @@ public abstract class UIXCollection extends UIXComponentBase
   
   /**
    * Indicates the caching strategy supported by the model
-   * @see LocalCachingStrategy
+   * @see LocalRowKeyIndex.LocalCachingStrategy
    * @return caching strategy supported by the model
    */
   public LocalRowKeyIndex.LocalCachingStrategy getCachingStrategy()
@@ -1585,21 +1854,8 @@ public abstract class UIXCollection extends UIXComponentBase
     return b.equals(a);
   }
 
-  //
-  // Optimized path that avoids creating the Facet map
-  // unless necessary
-  //
-  private int _getFacetCount(UIComponent component)
-  {
-    if (component instanceof UIXComponent)
-      return ((UIXComponent) component).getFacetCount();
-
-    return component.getFacets().size();
-  }
-
   private static final class DefaultClientKeyManager extends ClientRowKeyManager
   {
-
     public void clear()
     {
       _currencyCache.clear();
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java
index a80aa48..686a777 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java
@@ -226,9 +226,9 @@ abstract public class UIXComponent extends UIComponent
    * <p>
    * If a Renderer needs to
    * collect information about its possibly flattened children before calling
-   * <code>encodeFlattenedChild(FacesContext, ComponentProcessor, Iterable<UIComponent>, Object)</code>,
+   * <code>encodeFlattenedChild(FacesContext, ComponentProcessor, Iterable&lt;UIComponent&gt;, Object)</code>,
    * it should call
-   * <code>processFlattenedChildren(FacesContext, ComponentProcessor, Iterable<UIComponent>, Object)</code>
+   * <code>processFlattenedChildren(FacesContext, ComponentProcessor, Iterable&lt;UIComponent&gt;, Object)</code>
    * to collect the information.
    * <p>
    * For each FlattenedComponent child, the <code>childProcessor</code> will
@@ -239,6 +239,10 @@ abstract public class UIXComponent extends UIComponent
    * FlattenedComponents that wish to check whether they are processed for the purpose of
    * encoding can check the ProcessingHints of the ComponentProcessingContext for the
    * presence of <code>PROCESS_FOR_ENCODING hint</code>.
+   * @param context FacesContext
+   * @param childProcessor ComponentProcessor to call on each flattened child
+   * @param children Initial set of children to flatten
+   * @param callbackContext context object to pass to the childProcessor on each invocation
    * @return <code>true</code> If any children were processed
    * @see UIXComponent#processFlattenedChildren(FacesContext, ComponentProcessor, Iterable, Object)
    * @see FlattenedComponent
@@ -326,6 +330,83 @@ abstract public class UIXComponent extends UIComponent
     return visitTree(visitContext, this, callback);
   }
 
+ /**
+  * Hook for subclasses to override the manner in which the component's children are visited.  The default
+  * implementation visits all of the children and facets of the Component.
+  * <code>setupChildrenVisitingContext</code> will have been called before this method is
+  * invoked and <code>tearDownChildrenVisitingContext</code> will be called after.
+  * respectively.  If the purpose of this visit was to encode the component and the
+  * component uses a CoreRenderer, the CoreRenderer's
+  * <code>setupChildrenEncodingContext</code> and <code>tearDownChildrenEncodingContext</code>
+  * will be called before and after this method is invoked, respectively.
+  * @param visitContext the <code>VisitContext</code> for this visit
+  * @param callback the <code>VisitCallback</code> instance
+  * @return <code>true</code> if the visit is complete.
+  * @see #setupChildrenVisitingContext
+  * @see #tearDownChildrenVisitingContext
+  * @see org.apache.myfaces.trinidad.render.CoreRenderer#setupChildrenEncodingContext
+  * @see org.apache.myfaces.trinidad.render.CoreRenderer#tearDownChildrenEncodingContext
+  */
+  protected boolean visitChildren(
+    VisitContext visitContext,
+    VisitCallback callback)
+  {
+    return _visitChildrenImpl(visitContext, this, callback);
+  }
+  
+  /**
+   * Visit all of the children of the component
+   */
+  private static boolean _visitChildrenImpl(
+    VisitContext visitContext,
+    UIComponent   component,
+    VisitCallback callback)
+  {
+    // visit the children of the component
+    Iterator<UIComponent> kids = component.getFacetsAndChildren();
+
+    while(kids.hasNext())
+    {
+      boolean done;
+
+      UIComponent currChild = kids.next();
+
+      if (currChild instanceof UIXComponent)
+      {
+        UIXComponent uixChild = (UIXComponent)currChild;
+
+        // delegate to UIXComponent's visitTree implementation to allow
+        // subclassses to modify the behavior
+        done = uixChild.visitTree(visitContext, callback);
+      }
+      else
+      {
+        // use generic visit implementation
+        done = visitTree(visitContext, currChild, callback);
+      }
+
+      // If any kid visit returns true, we are done.
+      if (done)
+      {
+        return true;
+      }
+    }
+    
+    return false;
+  }
+
+  /**
+   * Returns <code>true</code> if the components are being visited
+   * for the purpose of encoding.
+   */
+  private static boolean _isEncodingVisit(VisitContext visitContext)
+  {
+    PhaseId phaseId = visitContext.getPhaseId();
+
+    return((PhaseId.RENDER_RESPONSE == phaseId) &&
+           visitContext.getHints().contains(VisitHint.EXECUTE_LIFECYCLE));
+  }
+  
   /**
   * <p>Perform a tree visit starting at the specified node in the tree.</p>
   *
@@ -350,10 +431,15 @@ abstract public class UIXComponent extends UIComponent
   * @see VisitContext#invokeVisitCallback VisitContext.invokeVisitCallback()
   */
   public static boolean visitTree(
-    VisitContext visitContext,
+    VisitContext  visitContext,
     UIComponent   component,
     VisitCallback callback)
   {
+    FacesContext context = visitContext.getFacesContext();
+    RenderingContext rc = (_isEncodingVisit(visitContext))
+                            ? RenderingContext.getCurrentInstance()
+                            : null;
+
     UIXComponent uixComponent;
 
     // determine if we should even visit this component subtree
@@ -364,6 +450,18 @@ abstract public class UIXComponent extends UIComponent
       // delegate to the UIXComponent
       if (!uixComponent.isVisitable(visitContext))
         return false;
+
+      // UIXComponents are allowed to set up their context differently for encoding
+      // than normal processing, so behave differently if this is the RenderResponse
+      // phase
+      if (rc != null)
+      {
+        uixComponent.setupEncodingContext(context, rc);
+      }
+      else
+      {
+        uixComponent.setupVisitingContext(context);
+      }
     }
     else
     {
@@ -374,110 +472,108 @@ abstract public class UIXComponent extends UIComponent
       uixComponent = null;
     }
 
-    // invoke the callback for this component
-    VisitResult result = visitContext.invokeVisitCallback(component, callback);
-
-    if (result == VisitResult.COMPLETE)
-      return true;
-    else if (result == VisitResult.ACCEPT)
+    VisitResult visitResult = VisitResult.REJECT;
+    boolean doneVisiting = false;
+    
+    try
     {
-      // now visit the children
-      FacesContext context = visitContext.getFacesContext();
-      PhaseId phaseId = visitContext.getPhaseId();
-      RenderingContext rc = (PhaseId.RENDER_RESPONSE == phaseId)
-                              ? RenderingContext.getCurrentInstance()
-                              : null;
+    // invoke the callback for this component
+      visitResult = visitContext.invokeVisitCallback(component, callback);
 
-      if (uixComponent != null)
+      if (visitResult == VisitResult.COMPLETE)
+        doneVisiting = true;
+      else if (visitResult == VisitResult.ACCEPT)
       {
-        // assume that all UIXComponent NamingContainers always act as NamingContainers,
-        // (unlike <h:form>) and this it is OK to put the optimization where we
-        // don't visit the children if we know that we don't have any ids in this
-        // subtree to visit
-        if (uixComponent instanceof NamingContainer)
-        {
-          if (visitContext.getSubtreeIdsToVisit(uixComponent).isEmpty())
-            return false;
-        }
+        // now determine whether we need to visit the children      
+        boolean skipChildren = false;
 
-        // UIXComponents are allowed to set up their context differently for encoding
-        // than normal processing, so behave differently if this is the RenderResponse
-        // phase
-        if (PhaseId.RENDER_RESPONSE == phaseId)
+        if (uixComponent != null)
         {
-          uixComponent.setUpEncodingContext(context, rc);
+          // assume that all UIXComponent NamingContainers always act as NamingContainers,
+          // (unlike <h:form>) and this it is OK to put the optimization where we
+          // don't visit the children if we know that we don't have any ids in this
+          // subtree to visit
+          if (uixComponent instanceof NamingContainer)
+          {
+            if (visitContext.getSubtreeIdsToVisit(uixComponent).isEmpty())
+              skipChildren = true;
+          }
         }
         else
         {
-          uixComponent.setupVisitingContext(context);
-        }
-      }
-      else
-      {
-        // we only optimize walking into non-UIXComponent NamingContainers
-        // if they are UINamingConainer (which is used by <f:subview>
-        if (UINamingContainer.class == component.getClass())
-        {
-          if (visitContext.getSubtreeIdsToVisit(component).isEmpty())
-            return false;
-        }
-      }
-
-      // visit the children of the component
-      try
-      {
-        Iterator<UIComponent> kids = component.getFacetsAndChildren();
-
-        while(kids.hasNext())
-        {
-          boolean done;
-
-          UIComponent currChild = kids.next();
-
-          if (currChild instanceof UIXComponent)
-          {
-            UIXComponent uixChild = (UIXComponent)currChild;
-
-            // delegate to UIXComponent's visitTree implementation to allow
-            // subclassses to modify the behavior
-            done = uixChild.visitTree(visitContext, callback);
-          }
-          else
-          {
-            // use generic visit implementation
-            done = visitTree(visitContext, currChild, callback);
-          }
-
-          // If any kid visit returns true, we are done.
-          if (done)
+          // we only optimize walking into non-UIXComponent NamingContainers
+          // if they are UINamingConainer (which is used by <f:subview>
+          if (UINamingContainer.class == component.getClass())
           {
-            return true;
+            if (visitContext.getSubtreeIdsToVisit(component).isEmpty())
+              skipChildren = true;
           }
         }
-      }
-      finally
-      {
-        // tear down the context we set up in order to visit our children
-        if (uixComponent != null)
+  
+        // visit the children of the component if we aren't supposed to skip them
+        if (!skipChildren)
         {
-          if (PhaseId.RENDER_RESPONSE == phaseId)
+          if (uixComponent != null)
           {
-            uixComponent.tearDownEncodingContext(context, rc);
+            // setup any context needed for visiting the children of the component as opposed
+            // to the component itself
+            if (rc != null)
+            {
+              uixComponent._setupChildrenEncodingContext(context, rc);
+            }
+            else
+            {
+              uixComponent.setupChildrenVisitingContext(context);
+            }
+            
+            
+            try
+            {
+              doneVisiting =  uixComponent.visitChildren(visitContext, callback);
+            }
+            finally
+            {
+              // teardown any context initialized above
+              if (rc != null)
+              {
+                uixComponent._tearDownChildrenEncodingContext(context, rc);
+              }
+              else
+              {
+                uixComponent.tearDownChildrenVisitingContext(context);
+              }
+            }
           }
           else
           {
-            uixComponent.tearDownVisitingContext(context);
+            doneVisiting = _visitChildrenImpl(visitContext, component, callback);
           }
         }
       }
+      else
+      {
+        // don't visit the children
+        assert(visitResult == VisitResult.REJECT);
+      }
     }
-    else
+    finally
     {
-      assert(result == VisitResult.REJECT);
+      // tear down the context we set up in order to visit our component
+      if (uixComponent != null)
+      {
+        if (rc != null)
+        {
+          uixComponent.tearDownEncodingContext(context, rc);
+        }
+        else
+        {
+          uixComponent.tearDownVisitingContext(context);
+        }
+      }
     }
-
+  
     // if we got this far, we're not done
-    return false;
+    return doneVisiting;
   }
 
   /**
@@ -510,6 +606,29 @@ abstract public class UIXComponent extends UIComponent
   }
 
   /**
+   * Clears all of the cached clientIds in this component subtree
+   */
+  public final void clearCachedClientIds()
+  {
+    clearCachedClientIds(this);
+  }
+
+  /**
+   * Clears all of the cached clientIds in the component's subtree
+   * @param component Component subtree to clear the cached client ids for
+   */
+  public static void clearCachedClientIds(UIComponent component)
+  {
+    String id = component.getId();
+    component.setId(id);
+    
+    Iterator<UIComponent> allChildren = component.getFacetsAndChildren();
+    
+    while (allChildren.hasNext())
+      clearCachedClientIds(allChildren.next());
+  }
+
+  /**
    * Marks this component as a partial target for this request. Typically called
    * by the {@link org.apache.myfaces.trinidad.context.RequestContext RequestContext}.
    * The component should add the client ID the desired rendered component to the context.
@@ -527,9 +646,9 @@ abstract public class UIXComponent extends UIComponent
 
   /**
    * <p>Called by
-   * {@link UIXComponent#visitTree UIXComponent.visitTree()} to determine
+   * {@link UIXComponent#visitTree(VisitContext, VisitCallback) UIXComponent.visitTree()} to determine
    * whether this component is "visitable" - ie. whether this component
-   * satisfies the {@link org.apache.myfaces.trinidad.component.visit.VisitHints} returned by
+   * satisfies the {@link org.apache.myfaces.trinidad.component.visit.VisitHint} returned by
    * {@link VisitContext#getHints VisitContext.getHints()}.</p>
    * <p>If this component is not visitable (ie. if this method returns
    * false), the tree visited is short-circuited such that neither the
@@ -537,7 +656,7 @@ abstract public class UIXComponent extends UIComponent
    * <p>Custom {@code treeVisit()} implementations may call this method
    * to determine whether the component is visitable before performing
    * any visit-related processing.</p>
-   *
+   * @param visitContext VisitingContext to use to determine if the component is visitable
    * @return true if this component should be visited, false otherwise.
    */
   protected boolean isVisitable(VisitContext visitContext)
@@ -645,11 +764,29 @@ abstract public class UIXComponent extends UIComponent
    * <code>tearDownVisitingContext</code> as well.</p>
    * <p>It is guaranteed that if <code>setupVisitingContext</code> completes
    * <code>tearDownVisitingContext</code> will be called for this component</p>
+   * @param context FacesContext
    * @see #tearDownVisitingContext
-   * @see #setUpEncodingContext
+   * @see #setupEncodingContext
    * @see #tearDownEncodingContext
    */
-  protected void setupVisitingContext(FacesContext context)
+  protected void setupVisitingContext(@SuppressWarnings("unused") FacesContext context)
+  {
+    // do nothing
+  }
+
+  /**
+   * <p>Sets up the context necessary to visit or invoke the children of a component for all phases.
+   * </p>
+   * <p>The default implementation does nothing.</p>
+   * <p>If a subclass overrides this method, it should override
+   * <code>tearDownChildrenVisitingContext</code> as well.</p>
+   * <p>It is guaranteed that if <code>setupChildrenVisitingContext</code> completes
+   * <code>tearDownChildrenVisitingContext</code> will be called for this component</p>
+   * @param context FacesContext
+   * @see #visitChildren
+   * @see #tearDownChildrenVisitingContext
+   */
+  protected void setupChildrenVisitingContext(@SuppressWarnings("unused") FacesContext context)
   {
     // do nothing
   }
@@ -662,15 +799,39 @@ abstract public class UIXComponent extends UIComponent
    * <code>setupVisitingContext</code> as well</p>
    * <p>It is guaranteed that <code>tearDownVisitingContext</code> will be called only after
    * <code>setupVisitingContext</code> has been called for this component</p>
+   * @param context FacesContext
    * @see #setupVisitingContext
-   * @see #setUpEncodingContext
+   * @see #setupEncodingContext
    * @see #tearDownEncodingContext
    */
-  protected void tearDownVisitingContext(FacesContext context)
+  protected void tearDownVisitingContext(@SuppressWarnings("unused") FacesContext context)
+  {
+    // do nothing
+  }
+
+  /**
+   * <p>Tears down context created in order to visit or invoke the children of a component
+   * for all phases.</p>
+   * <p>The default implementation does nothing.</p>
+   * <p>A subclass should only override this method if it overrode
+   * <code>setupChildrenVisitingContext</code> as well</p>
+   * <p>It is guaranteed that <code>tearDownChildrenVisitingContext</code> will be called only after
+   * <code>setupChildrenVisitingContext</code> has been called for this component</p>
+   * @param context FacesContext
+   * @see #setupChildrenVisitingContext
+   * @see #visitChildren
+   */
+  protected void tearDownChildrenVisitingContext(@SuppressWarnings("unused") FacesContext context)
   {
     // do nothing
   }
 
+  @Deprecated
+  protected final void setUpEncodingContext(FacesContext context, RenderingContext rc)
+  {
+    setupEncodingContext(context, rc);
+  }
+
   /**
    * <p>Sets up the context necessary to encode the component.</p>
    * <p>The default implementation delegates to
@@ -680,12 +841,14 @@ abstract public class UIXComponent extends UIComponent
    * <code>tearDownEncodingContext</code> as well.</p>
    * <p>It is guaranteed that if <code>setUpEncodingContext</code> completes
    * <code>tearDownEncodingContext</code> will be called for this component</p>
+   * @param context The FacesContext
+   * @param rc      RenderingContext to use for encoding
    * @see #setupVisitingContext
    * @see #tearDownVisitingContext
    * @see #tearDownEncodingContext
    * @see CoreRenderer#setupEncodingContext
    */
-  protected void setUpEncodingContext(FacesContext context, RenderingContext rc)
+  protected void setupEncodingContext(FacesContext context, RenderingContext rc)
   {
     setupVisitingContext(context);
 
@@ -700,17 +863,41 @@ abstract public class UIXComponent extends UIComponent
   }
 
   /**
+   * Sets the context necessary to encode the children of a component.
+   * @param context The FacesContext
+   * @param rc      RenderingContext to use for encoding
+   * @see #setupChildrenVisitingContext
+   * @see #_tearDownChildrenEncodingContext
+   * @see org.apache.myfaces.trinidad.render.CoreRenderer#setupChildrenEncodingContext
+   */
+  private void _setupChildrenEncodingContext(FacesContext context, RenderingContext rc)
+  {
+    setupChildrenVisitingContext(context);
+
+    Renderer renderer = getRenderer(context);
+
+    if (renderer instanceof CoreRenderer)
+    {
+      CoreRenderer coreRenderer = (CoreRenderer)renderer;
+
+      coreRenderer.setupChildrenEncodingContext(context, rc, this);
+    }    
+  }
+
+  /**
    * <p>Tears down the context created in order to encode the component</p>
    * <p>The default implementation delegates to
    * <code>CoreRenderer.tearDownEncodingContext</code> and then calls
    * <code>tearDownVisitingContext</code></p>
    * <p>A subclass should only override this method if it overrode
-   * <code>setUpEncodingContext</code> as well</p>
+   * <code>setupEncodingContext</code> as well</p>
    * <p>It is guaranteed that <code>tearDownEncodingContext</code> will be called only after
-   * <code>setUpEncodingContext</code> has been called for this component</p>
-   * @see #setUpEncodingContext
+   * <code>setupEncodingContext</code> has been called for this component</p>
+   * @param context The FacesContext
+   * @param rc      RenderingContext to use for encoding
+   * @see #setupEncodingContext
    * @see #tearDownVisitingContext
-   * @see #setUpEncodingContext
+   * @see #setupEncodingContext
    * @see CoreRenderer#tearDownEncodingContext
    */
   protected void tearDownEncodingContext(
@@ -735,6 +922,35 @@ abstract public class UIXComponent extends UIComponent
   }
 
   /**
+   * Tears down the context necessary to encode the children of a component.
+   * @param context The FacesContext
+   * @param rc      RenderingContext to use for encoding
+   * @see #setupChildrenVisitingContext
+   * @see #_tearDownChildrenEncodingContext
+   * @see org.apache.myfaces.trinidad.render.CoreRenderer#setupChildrenEncodingContext
+   */
+  private void _tearDownChildrenEncodingContext(
+    FacesContext context,
+    RenderingContext rc)
+  {
+    Renderer renderer = getRenderer(context);
+
+    try
+    {
+      if (renderer instanceof CoreRenderer)
+      {
+        CoreRenderer coreRenderer = (CoreRenderer)renderer;
+
+        coreRenderer.tearDownChildrenEncodingContext(context, rc, this);
+      }
+    }
+    finally
+    {
+      tearDownChildrenVisitingContext(context);
+    }
+  }
+
+  /**
    * Returns the FacesBean used for storing the component's state.
    */
   abstract public FacesBean getFacesBean();
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
index d886fe5..672fda8 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
@@ -304,10 +304,10 @@ abstract public class UIXComponentBase extends UIXComponent
 
   // ------------------------------------------------------------- Properties
 
-
-
-  @Override
-  public String getClientId(FacesContext context)
+  /**
+   * Calculates the clientId for the component
+   */
+  private String _calculateClientId(FacesContext context)
   {
     // the clientId is always at least the id of the current component
     // our implementation of getId() guarantees that this always
@@ -321,27 +321,53 @@ abstract public class UIXComponentBase extends UIXComponent
       if (containerComponent instanceof NamingContainer)
       {
         String contClientId;
-
+    
         // Pass additional context information to naming containers which extend UIXComponent:
         if (containerComponent instanceof UIXComponent)
           contClientId = ((UIXComponent)containerComponent).getContainerClientId(context, this);
         else
           contClientId = containerComponent.getContainerClientId(context);
-
+    
         StringBuilder bld = __getSharedStringBuilder();
         bld.append(contClientId).append(NamingContainer.SEPARATOR_CHAR).append(clientId);
         clientId = bld.toString();
         break;
       }
-
+    
       containerComponent = containerComponent.getParent();
     }
-
+    
     Renderer renderer = getRenderer(context);
     if (null != renderer)
       clientId = renderer.convertClientId(context, clientId);
+    
+    return clientId;
+  }
+  
 
+
+  @Override
+  public String getClientId(FacesContext context)
+  {
+    return _calculateClientId(context);
+/* TODO put back in when we fix all of the clientID caching issues
+    String clientId = _clientId;
+    
+    if (clientId == null)
+    {
+      clientId = _calculateClientId(context);
+      
+      if (_usesFacesBeanImpl)
+        _clientId = clientId;
+    }
+    else
+    {
+      assert clientId.equals(_calculateClientId(context)) :
+      "cached client id " + _clientId + " for " + this + " doesn't match client id:" + _calculateClientId(context);
+    }
+    
     return clientId;
+*/
   }
 
 
@@ -397,6 +423,8 @@ abstract public class UIXComponentBase extends UIXComponent
   @Override
   public void setId(String id)
   {
+    _clientId = null;
+    
     FacesBean facesBean = getFacesBean();
     
     // if we are using a FacesBeanImpl, then the FacesBean will
@@ -410,6 +438,13 @@ abstract public class UIXComponentBase extends UIXComponent
       {
         _validateId(id);
         _id = id;
+        
+        // if we're a NamingContainer then changing our id will invalidate the clientIds of all
+        // of our children
+        if ((_clientId != null) && (this instanceof NamingContainer))
+        {
+          clearCachedClientIds(this);
+        }
       }      
     }
     else
@@ -418,7 +453,7 @@ abstract public class UIXComponentBase extends UIXComponent
       facesBean.setProperty(ID_KEY, id);      
     }
   }
-
+  
   @Override
   abstract public String getFamily();
 
@@ -607,7 +642,8 @@ abstract public class UIXComponentBase extends UIXComponent
   {
     if (_children == null)
       return 0;
-    return getChildren().size();
+    else
+      return getChildren().size();
   }
 
 
@@ -631,9 +667,11 @@ abstract public class UIXComponentBase extends UIXComponent
   {
     if (facetName == null)
       throw new NullPointerException();
+    
     if (_facets == null)
       return null;
-    return getFacets().get(facetName);
+    else
+      return getFacets().get(facetName);
   }
 
 
@@ -648,7 +686,8 @@ abstract public class UIXComponentBase extends UIXComponent
   {
     if (_facets == null)
       return _EMPTY_STRING_ITERATOR;
-    return _facets.keySet().iterator();
+    else
+      return _facets.keySet().iterator();
   }
 
   @Override
@@ -1659,6 +1698,7 @@ abstract public class UIXComponentBase extends UIXComponent
   private Map<String, UIComponent> _facets;
   private UIComponent              _parent;
   private String                   _id;
+  private String                   _clientId;
   private boolean                  _usesFacesBeanImpl;
   
   // Cached instance of the Renderer for this component.
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXHierarchy.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXHierarchy.java
index a9ec25a..414301f 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXHierarchy.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXHierarchy.java
@@ -6,9 +6,9 @@
  *  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
@@ -19,11 +19,12 @@
 package org.apache.myfaces.trinidad.component;
 
 import java.util.Collections;
-
 import java.util.List;
 
 import javax.faces.component.UIComponent;
 
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
 import org.apache.myfaces.trinidad.model.CollectionModel;
 import org.apache.myfaces.trinidad.model.LocalRowKeyIndex;
 import org.apache.myfaces.trinidad.model.ModelUtils;
@@ -37,7 +38,7 @@ import org.apache.myfaces.trinidad.model.TreeModel;
  *
  * @version $Name:  $ ($Revision: adfrt/faces/adf-faces-api/src/main/java/oracle/adf/view/faces/component/UIXHierarchy.java#0 $) $Date: 10-nov-2005.19:09:52 $
  */
-abstract public class UIXHierarchy extends UIXCollection implements CollectionComponent, LocalRowKeyIndex, 
+public abstract class UIXHierarchy extends UIXCollection implements CollectionComponent, LocalRowKeyIndex, 
              TreeLocalRowKeyIndex
 {
   /**
@@ -58,7 +59,7 @@ abstract public class UIXHierarchy extends UIXCollection implements CollectionCo
   public CollectionModel createCollectionModel(CollectionModel current, Object value)
   {
     TreeModel model = ModelUtils.toTreeModel(value);
-    model.setRowKey(null);    
+    model.setRowKey(null);
     return model;
   }
 
@@ -80,7 +81,7 @@ abstract public class UIXHierarchy extends UIXCollection implements CollectionCo
   public int getRows()
   {
     return 0;
-  }  
+  }
   
   /**
   * Treats the current element as a parent element and steps into the children.
@@ -128,7 +129,6 @@ abstract public class UIXHierarchy extends UIXCollection implements CollectionCo
    */
   public boolean isContainerEmpty()
   {
-    
     return getTreeModel().isContainerEmpty();
   }
 
@@ -265,7 +265,6 @@ abstract public class UIXHierarchy extends UIXCollection implements CollectionCo
     return getTreeModel().areRowsLocallyAvailable(rowCount, disclosedRowKeys);
   }
 
-
   /**
    * Gets the TreeModel that this tree is displaying.
    */
@@ -273,7 +272,7 @@ abstract public class UIXHierarchy extends UIXCollection implements CollectionCo
   {
     TreeModel model = (TreeModel) getCollectionModel();
     return model;
-  } 
+  }
   
   @Override
   protected List<UIComponent> getStamps()
@@ -283,7 +282,94 @@ abstract public class UIXHierarchy extends UIXCollection implements CollectionCo
       return Collections.singletonList(nodeStamp);
     else
       return Collections.emptyList();
-  }  
+  }
 
   abstract public Object getFocusRowKey();
+
+  protected final boolean visitLevel(
+    VisitContext      visitContext,
+    VisitCallback     callback,
+    List<UIComponent> stamps)
+  {
+    if (getRowCount() != 0)
+    {      
+      if (!stamps.isEmpty())
+      {
+        int oldRow = getRowIndex();
+        int first = getFirst();
+        int last = TableUtils.getLast(this, first);
+
+        try
+        {
+          for (int i = first; i <= last; i++)
+          {
+            setRowIndex(i);
+
+            for (UIComponent currStamp : stamps)
+            {
+              // visit the stamps.  If we have visited all of the visit targets then return early
+              if (UIXComponent.visitTree(visitContext, currStamp, callback))
+                return true;
+            }
+          }
+        }
+        finally
+        {
+          setRowIndex(oldRow);          
+        }
+      }
+    }
+    
+    return false;
+  }
+  
+  protected final boolean visitHierarchy(
+    VisitContext      visitContext,
+    VisitCallback     callback,
+    List<UIComponent> stamps,
+    RowKeySet         disclosedRowKeys)
+  {
+    int oldRow = getRowIndex();
+    int first = getFirst();
+    int last = TableUtils.getLast(this, first);
+
+    try
+    {  
+      for(int i = first; i <= last; i++)
+      {
+        setRowIndex(i);
+        if (!stamps.isEmpty())
+        {
+          for (UIComponent currStamp : stamps)
+          {
+            // visit the stamps.  If we have visited all of the visit targets then return early
+            if (UIXComponent.visitTree(visitContext, currStamp, callback))
+              return true;
+          }
+        }
+                
+        if (isContainer() && ((disclosedRowKeys == null) || disclosedRowKeys.isContained()))
+        {
+          enterContainer();
+          
+          try
+          {
+            // visit this container.  If we have visited all of the visit targets then return early
+            if (visitHierarchy(visitContext, callback, stamps, disclosedRowKeys));
+              return true;
+          }
+          finally
+          {
+            exitContainer();
+          }
+        }
+      }
+    }
+    finally
+    {
+      setRowIndex(oldRow);
+    }    
+ 
+    return false;
+  }
 }
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitCallback.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitCallback.java
index cebb081..e1b701c 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitCallback.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitCallback.java
@@ -27,7 +27,8 @@ import javax.faces.component.UIComponent;
  * taking action on a specific UIComponent (either facet or child) during 
  * a component tree visit.</p>
  *
- * @see org.apache.myfaces.trinidad.component.UIXComponent#visitTree UIComponent.visitTree()
+ * @see org.apache.myfaces.trinidad.component.UIXComponent#visitTree(VisitContext, VisitCallback)
+ * UIComponent.visitTree()
  */
 public interface VisitCallback
 {
@@ -39,7 +40,7 @@ public interface VisitCallback
      * to be in the proper state with respect to its ancestors in the
      * View.</p>
      *
-     * @param context the {@link VisitContext} for this tree visit.
+     * @param visitContext the {@link VisitContext} for this tree visit.
      *
      * @param target the {@link UIComponent} to visit
      *
@@ -47,5 +48,5 @@ public interface VisitCallback
      *   visiting the component's subtree, skip visiting the component's
      *   subtree or end the visit.
      */
-    public VisitResult visit(VisitContext context, UIComponent target);
+    public VisitResult visit(VisitContext visitContext, UIComponent target);
 }
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitContext.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitContext.java
index 8e70308..8ada868 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitContext.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitContext.java
@@ -34,11 +34,12 @@ import javax.faces.event.PhaseId;
  * state relating to a component tree visit.</p>
  *
  * <p>Component tree visits are initiated by calling
- * {@link org.apache.myfaces.trinidad.component.UIXComponent#visitTree UIComponent.visitTree()},
+ * {@link org.apache.myfaces.trinidad.component.UIXComponent#visitTree(VisitContext,UIComponent,VisitCallback)
+ * UIComponent.visitTree()},
  * at which point both a {@link VisitContext} and a {@link VisitCallback}
  * must be provided.
  *
- * @see org.apache.myfaces.trinidad.component.UIXComponent#visitTree UIXComponent.visitTree()
+ * @see org.apache.myfaces.trinidad.component.UIXComponent#visitTree(VisitContext,UIComponent,VisitCallback) UIXComponent.visitTree()
  * @see VisitCallback
  *
  */
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/render/CoreRenderer.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/render/CoreRenderer.java
index e967c00..f470909 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/render/CoreRenderer.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/render/CoreRenderer.java
@@ -96,7 +96,7 @@ public class CoreRenderer extends Renderer
 
   /**
    * <p>
-   * Called before rendering the current component's children in order to set
+   * Called before rendering the current comopnent's children in order to set
    * up any special context.
    * </p>
    * <p>If <code>setupEncodingContext</code> succeeds then
@@ -105,31 +105,53 @@ public class CoreRenderer extends Renderer
    * <p>The default implementation does nothing</p>
    * @param context FacesContext for this request
    * @param rc RenderingContext for this encoding pass
-   * @ param component Component to encode using this Renderer
+   * @param component Component to encode using this Renderer
    * @see #tearDownEncodingContext
    */
   public void setupEncodingContext(
     FacesContext context,
     RenderingContext rc,
-    UIXComponent component)
+    UIComponent component)
   {
+    // TODO Remove after one release
+    if (component instanceof UIXComponent)
+      setupEncodingContext(context, rc, (UIXComponent)component);
   }
 
+  // TODO Remove after one release
+  @Deprecated
   public void setupEncodingContext(
-    FacesContext context,
-    RenderingContext rc,
-    UIComponent component)
+    @SuppressWarnings("unused") FacesContext context,
+    @SuppressWarnings("unused") RenderingContext rc,
+    @SuppressWarnings("unused") UIXComponent component)
   {
-    // temporary hack to change UIComponent.  Once the change has propagated through, we will
-    // remove the UIXComponent version.
-    // We need to support UIComponents so that we can use CoreRenderers against non-UIXComponents
-    if (component instanceof UIXComponent)
-      setupEncodingContext(context, rc, (UIXComponent)component);
   }
 
+
   /**
    * <p>
-   * Called after rendering the current component's children in order to tear
+   * Called before rendering the current component's children in order to set
+   * up any special context.
+   * </p>
+   * <p>If <code>setupChildrenEncodingContext</code> succeeds then
+   * <code>tearDownChildrenEncodingContext</code> will be called for the same component.
+   * </p>
+   * <p>The default implementation does nothing</p>
+   * @param context FacesContext for this request
+   * @param rc RenderingContext for this encoding pass
+   * @param component Component to encode using this Renderer
+   * @see #tearDownChildrenEncodingContext
+   */
+  public void setupChildrenEncodingContext(
+    @SuppressWarnings("unused") FacesContext context,
+    @SuppressWarnings("unused") RenderingContext rc,
+    @SuppressWarnings("unused") UIComponent component)
+  {
+  }
+
+  /**
+   * <p>
+   * Called after rendering the current component in order to tear
    * down any special context.
    * </p>
    * <p>
@@ -139,28 +161,49 @@ public class CoreRenderer extends Renderer
    * <p>The default implementation does nothing</p>
    * @param context FacesContext for this request
    * @param rc RenderingContext for this encoding pass
-   * @ param component Component to encode using this Renderer
+   * @param component Component to encode using this Renderer
    * @see #setupEncodingContext
    */
   public void tearDownEncodingContext(
     FacesContext context,
     RenderingContext rc,
-    UIXComponent     component)
+    UIComponent     component)
   {
+    // TODO Remove after one release
+    if (component instanceof UIXComponent)
+      tearDownEncodingContext(context, rc, (UIXComponent)component);
   }
 
+  // TODO Remove after one release
+  @Deprecated
   public void tearDownEncodingContext(
-    FacesContext context,
-    RenderingContext rc,
-    UIComponent     component)
+    @SuppressWarnings("unused") FacesContext context,
+    @SuppressWarnings("unused") RenderingContext rc,
+    @SuppressWarnings("unused") UIXComponent     component)
   {
-    // temporary hack to change UIComponent.  Once the change has propagated through, we will
-    // remove the UIXComponent version.
-    // We need to support UIComponents so that we can use CoreRenderers against non-UIXComponents
-    if (component instanceof UIXComponent)
-      tearDownEncodingContext(context, rc, (UIXComponent)component);
   }
 
+  /**
+   * <p>
+   * Called after rendering the current component's children in order to tear
+   * down any special context.
+   * </p>
+   * <p>
+   * <code>tearDownChildrenEncodingContext</code> will be called on the component if
+   * <code>setupChildrenEncodingContext</code> succeeded.
+   * </p>
+   * <p>The default implementation does nothing</p>
+   * @param context FacesContext for this request
+   * @param rc RenderingContext for this encoding pass
+   * @param component Component to encode using this Renderer
+   * @see #setupChildrenEncodingContext
+   */
+  public void tearDownChildrenEncodingContext(
+    @SuppressWarnings("unused") FacesContext context,
+    @SuppressWarnings("unused") RenderingContext rc,
+    @SuppressWarnings("unused") UIComponent component)
+  {
+  }
 
   //
   // COERCION HELPERS
@@ -223,6 +266,7 @@ public class CoreRenderer extends Renderer
    * Coerces an object into a resource URI, calling the view-handler.
    * @deprecated use toResourceUri
    */
+  @Deprecated
   static public String toUri(Object o)
   {
     return toResourceUri(FacesContext.getCurrentInstance(),o);
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
index 6e26ed2..b1495f8 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
@@ -1288,8 +1288,6 @@ public final class CollectionUtils
   private static final Class<? extends List> _SYNCHRONIZED_LIST;
   private static final Class<? extends Set> _EMPTY_SET = Collections.emptySet().getClass();
   private static final Class<? extends Set> _SINGLETON_SET = Collections.singleton(null).getClass();
-  
-
   private static final Queue _EMPTY_QUEUE = new EmptyQueue();
   private static final Iterator _EMPTY_ITERATOR = new EmptyIterator();
   private static final Iterator _EMPTY_LIST_ITERATOR = new EmptyListIterator();
diff --git a/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/UIComponentTestCase.java b/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/UIComponentTestCase.java
index 4cbadc7..f3bd435 100644
--- a/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/UIComponentTestCase.java
+++ b/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/UIComponentTestCase.java
@@ -26,6 +26,8 @@ import java.io.IOException;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+
+import java.util.Collections;
 import java.util.Map;
 import javax.faces.component.EditableValueHolder;
 import javax.faces.component.UIComponent;
@@ -692,6 +694,8 @@ public class UIComponentTestCase extends FacesTestCase
     
     mock.stubs().method("getParent").will(returnValue(null));
     mock.stubs().method("setParent");
+    mock.stubs().method("getFacetsAndChildren").will(returnIterator(Collections.emptyList()));
+
     mock.expects(never()).method("processRestoreState");
     mock.expects(never()).method("processDecodes");
     mock.expects(never()).method("processValidators");
diff --git a/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/UIXProcessTest.java b/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/UIXProcessTest.java
index 1b1f7c1..db1854b 100644
--- a/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/UIXProcessTest.java
+++ b/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/UIXProcessTest.java
@@ -20,12 +20,16 @@ package org.apache.myfaces.trinidad.component;
 
 import java.io.IOException;
 
+import javax.faces.component.UIComponentBase;
+
 import junit.framework.Test;
 import junit.framework.TestSuite;
 import junit.textui.TestRunner;
 
 import org.apache.myfaces.trinidad.component.UIComponentTestCase;
 
+import org.jmock.Mock;
+
 /**
  * Unit tests for UIXProcess
  *
@@ -133,4 +137,16 @@ public class UIXProcessTest extends UIComponentTestCase
     UIXProcess component = new UIXProcess();
     doTestRenderResponse(component);
   }
+  
+  protected Mock createMockUIComponent()
+  {
+    // the UIXProcess is allowed to call getId and setId on its child
+    Mock mock = super.createMockUIComponent();
+    
+    mock.stubs().method("getId");
+    mock.stubs().method("setId");
+        
+    return mock;
+  }
+
 }
diff --git a/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/core/nav/CoreBreadCrumbsTest.java b/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/core/nav/CoreBreadCrumbsTest.java
index a546087..e611286 100644
--- a/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/core/nav/CoreBreadCrumbsTest.java
+++ b/trinidad-api/src/test/java/org/apache/myfaces/trinidad/component/core/nav/CoreBreadCrumbsTest.java
@@ -25,6 +25,8 @@ import junit.framework.TestSuite;
 
 import org.apache.myfaces.trinidad.component.UIComponentTestCase;
 
+import org.jmock.Mock;
+
 /**
  * Unit tests for CoreBreadCrumbs.
  *
@@ -136,4 +138,15 @@ public class CoreBreadCrumbsTest extends UIComponentTestCase
     CoreBreadCrumbs component = new CoreBreadCrumbs();
     doTestRenderResponse(component);
   }
+
+  protected Mock createMockUIComponent()
+  {
+    // the BreadCrumbs is allowed to call getId and setId on its child
+    Mock mock = super.createMockUIComponent();
+    
+    mock.stubs().method("getId");
+    mock.stubs().method("setId");
+        
+    return mock;
+  }
 }
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/FullVisitContext.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/FullVisitContext.java
index 1fbe0a9..4ce13ac 100644
--- a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/FullVisitContext.java
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/FullVisitContext.java
@@ -33,6 +33,7 @@ import org.apache.myfaces.trinidad.component.visit.VisitCallback;
 import org.apache.myfaces.trinidad.component.visit.VisitContext;
 import org.apache.myfaces.trinidad.component.visit.VisitHint;
 import org.apache.myfaces.trinidad.component.visit.VisitResult;
+import org.apache.myfaces.trinidad.util.CollectionUtils;
 
 /**
  *
@@ -80,11 +81,10 @@ class FullVisitContext extends VisitContext
     _phaseId = phaseId;
 
     // Copy and store hints - ensure unmodifiable and non-empty
-    EnumSet<VisitHint> hintsEnumSet = ((hints == null) || (hints.isEmpty()))
-                                          ? EnumSet.noneOf(VisitHint.class)
-                                          : EnumSet.copyOf(hints);
-
-    _hints = Collections.unmodifiableSet(hintsEnumSet);
+    if (hints == null)
+      _hints = Collections.emptySet();
+    else
+      _hints = CollectionUtils.unmodifiableCopyOfEnumSet(hints);
   }
 
   /**
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialVisitContext.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialVisitContext.java
index a03d8c8..ba21daf 100644
--- a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialVisitContext.java
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialVisitContext.java
@@ -41,6 +41,7 @@ import org.apache.myfaces.trinidad.component.visit.VisitCallback;
 import org.apache.myfaces.trinidad.component.visit.VisitContext;
 import org.apache.myfaces.trinidad.component.visit.VisitHint;
 import org.apache.myfaces.trinidad.component.visit.VisitResult;
+import org.apache.myfaces.trinidad.util.CollectionUtils;
 
 /**
  * <p>A VisitContext implementation that is
@@ -130,12 +131,11 @@ class PartialVisitContext extends VisitContext
     _clientIds.addAll(clientIdSet);
 
     // Copy and store hints - ensure unmodifiable and non-empty
-    EnumSet<VisitHint> hintsEnumSet = ((hints == null) || (hints.isEmpty()))
-                                        ? EnumSet.noneOf(VisitHint.class)
-                                        : EnumSet.copyOf(hints);
-
-    _hints = Collections.unmodifiableSet(hintsEnumSet);
-  }
+    if (hints == null)
+      _hints = Collections.emptySet();
+    else
+      _hints = CollectionUtils.unmodifiableCopyOfEnumSet(hints);
+   }
 
   /**
    * @see VisitContext#getFacesContext VisitContext.getFacesContext()
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PartialPageContextImpl.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PartialPageContextImpl.java
index eee38c2..d255191 100644
--- a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PartialPageContextImpl.java
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PartialPageContextImpl.java
@@ -378,8 +378,6 @@ public class PartialPageContextImpl extends PartialPageContext
     {
       // First sure that we should visit this component - ie.
       // that this component is represented in our id set.
-      String clientId = _getVisitId(component);
-
       VisitResult result;
      
       if (component instanceof UIXComponent)
@@ -422,33 +420,12 @@ public class PartialPageContextImpl extends PartialPageContext
     public Set<VisitHint> getHints()
     {
       return _PPR_VISIT_HINTS;
-    }
-
-    // Tests whether the specified component should be visited.
-    // If so, returns its client id.  If not, returns null.
-    private String _getVisitId(UIComponent component)
-    {
-      // We first check to see whether the component's id
-      // is in our id collection.  We do this before checking
-      // for the full client id because getting the full client id
-      // is more expensive than just getting the local id.
-      String id = component.getId();
-
-      if ((id != null) && !_targetIds.contains(id))
-        return null;
-
-      // The id was a match - now check the client id.
-      // note that client id should never be null (should be
-      // generated even if id is null, so asserting this.)
-      String clientId = component.getClientId(getFacesContext());
-      assert(clientId != null);
-
-      return _targets.containsKey(clientId) ? clientId : null;
-    }                                                                      
+    }                                                             
   }
 
-  private static final Set<VisitHint> _PPR_VISIT_HINTS = EnumSet.of(VisitHint.SKIP_UNRENDERED,
-                                                                    VisitHint.EXECUTE_LIFECYCLE);
+  private static final Set<VisitHint> _PPR_VISIT_HINTS = Collections.unmodifiableSet(
+                                                         EnumSet.of(VisitHint.SKIP_UNRENDERED,
+                                                                    VisitHint.EXECUTE_LIFECYCLE));
   private final FacesContext _context;
   
   // if the value is TRUE, then this target has been rendered.  If false, it has yet to be rendered
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
index 6e03fd3..afee029 100644
--- a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
@@ -105,15 +105,6 @@ public class FormRenderer extends XhtmlRenderer
     _targetFrameKey = type.findKey("targetFrame");
   }
 
-  @Override
-  public void setupEncodingContext(
-    FacesContext context,
-    RenderingContext rc,
-    UIXComponent component)
-  {
-    // temp hack
-    setupEncodingContext(context, rc, (UIComponent)component);
-  }
   
   @Override
   public void setupEncodingContext(
@@ -425,16 +416,6 @@ public class FormRenderer extends XhtmlRenderer
     if (postscriptId != null)
       rw.endElement("span");
   }
-
-  @Override
-  public void tearDownEncodingContext(
-    FacesContext context,
-    RenderingContext rc,
-    UIXComponent     component)
-  {
-    // temp hack
-    tearDownEncodingContext(context, rc, (UIComponent)component);
-  }
   
   @Override
   public void tearDownEncodingContext(

-- 
To stop receiving notification emails like this one, please contact
"commits@myfaces.apache.org" <co...@myfaces.apache.org>.