You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2009/01/21 00:18:44 UTC
svn commit: r736165 [1/2] - in /myfaces/trinidad/trunk_1.2.x:
trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/
trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/
trinidad-api/src/main/java/org/apache/myfaces/tr...
Author: matzew
Date: Tue Jan 20 15:18:43 2009
New Revision: 736165
URL: http://svn.apache.org/viewvc?rev=736165&view=rev
Log:
TRINIDAD-1368 - Backport JSF 2.0 Component Tree Visiting and Optimize PPR Rendering
thanks to blake for the patch
Added:
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitCallback.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitContext.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitHint.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitResult.java
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/FullVisitContext.java
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialVisitContext.java
Modified:
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXComponentRefTemplate.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXMenuTemplate.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXSubformTemplate.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/PartialPageContext.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/render/CoreRenderer.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/test/java/org/apache/myfaces/trinidad/context/MockRequestContext.java
myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ComponentEditorHandler.java
myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml
myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/editor.jspf
myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/showDetailItem.jspx
myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/demos/carDemo.jspx
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/RequestContextImpl.java
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/CoreRenderingContext.java
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PartialPageContextImpl.java
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/PanelPartialRootRenderer.java
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/PartialPageUtils.java
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MRequestContext.java
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXComponentRefTemplate.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXComponentRefTemplate.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXComponentRefTemplate.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXComponentRefTemplate.java Tue Jan 20 15:18:43 2009
@@ -51,27 +51,8 @@
ContextCallback callback)
throws FacesException
{
- String thisClientId = getClientId(context);
-
- if (clientId.equals(thisClientId))
- {
- callback.invokeContextCallback(context, this);
- return true;
- }
-
- // This component is a naming container. If the client id shows it's inside this naming container,
- // then process further.
- // Otherwise we know the client id we're looking for is not in this naming container,
- // so for improved performance short circuit and return false.
- else if (clientId.startsWith(thisClientId) &&
- (clientId.charAt(thisClientId.length()) ==
- NamingContainer.SEPARATOR_CHAR))
- {
-
- return super.invokeOnComponent(context, clientId, callback);
- }
-
- return false;
+ // optimize case where clientId isn't in NamingContainer
+ return invokeOnNamingContainerComponent(context, clientId, callback);
}
@Override
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java Tue Jan 20 15:18:43 2009
@@ -88,27 +88,8 @@
ContextCallback callback)
throws FacesException
{
- String thisClientId = getClientId(context);
-
- if (clientId.equals(thisClientId))
- {
- callback.invokeContextCallback(context, this);
- return true;
- }
-
- // This component is a naming container. If the client id shows it's inside this naming container,
- // then process further.
- // Otherwise we know the client id we're looking for is not in this naming container,
- // so for improved performance short circuit and return false.
- else if (clientId.startsWith(thisClientId) &&
- (clientId.charAt(thisClientId.length()) ==
- NamingContainer.SEPARATOR_CHAR))
- {
-
- return super.invokeOnComponent(context, clientId, callback);
- }
-
- return false;
+ // optimize case where clientId isn't in NamingContainer
+ return invokeOnNamingContainerComponent(context, clientId, callback);
}
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXMenuTemplate.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXMenuTemplate.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXMenuTemplate.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXMenuTemplate.java Tue Jan 20 15:18:43 2009
@@ -38,27 +38,7 @@
ContextCallback callback)
throws FacesException
{
- String thisClientId = getClientId(context);
-
- if (clientId.equals(thisClientId))
- {
- callback.invokeContextCallback(context, this);
- return true;
- }
-
- // This component is a naming container. If the client id shows it's inside this naming container,
- // then process further.
- // Otherwise we know the client id we're looking for is not in this naming container,
- // so for improved performance short circuit and return false.
- else if (clientId.startsWith(thisClientId) &&
- (clientId.charAt(thisClientId.length()) ==
- NamingContainer.SEPARATOR_CHAR))
- {
-
- return super.invokeOnComponent(context, clientId, callback);
- }
-
- return false;
+ // optimize case where clientId isn't in NamingContainer
+ return invokeOnNamingContainerComponent(context, clientId, callback);
}
-
}
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXSubformTemplate.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXSubformTemplate.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXSubformTemplate.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXSubformTemplate.java Tue Jan 20 15:18:43 2009
@@ -86,27 +86,8 @@
ContextCallback callback)
throws FacesException
{
- String thisClientId = getClientId(context);
-
- if (clientId.equals(thisClientId))
- {
- callback.invokeContextCallback(context, this);
- return true;
- }
-
- // This component is a naming container. If the client id shows it's inside this naming container,
- // then process further.
- // Otherwise we know the client id we're looking for is not in this naming container,
- // so for improved performance short circuit and return false.
- else if (clientId.startsWith(thisClientId) &&
- (clientId.charAt(thisClientId.length()) ==
- NamingContainer.SEPARATOR_CHAR))
- {
-
- return super.invokeOnComponent(context, clientId, callback);
- }
-
- return false;
+ // optimize case where clientId isn't in NamingContainer
+ return invokeOnNamingContainerComponent(context, clientId, callback);
}
@SuppressWarnings("unchecked")
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java Tue Jan 20 15:18:43 2009
@@ -1030,32 +1030,45 @@
if (clientId.startsWith(thisClientId) &&
(clientId.charAt(thisClientIdLength) == NamingContainer.SEPARATOR_CHAR))
{
- if (!_getAndMarkFirstInvokeForRequest(context, thisClientId))
- {
- // Call _init() since _flushCachedModel() assumes that
- // selectedRowKeys and disclosedRowKeys are initialized to be non-null
- _init();
-
- _flushCachedModel();
- }
-
- String postId = clientId.substring(thisClientIdLength + 1);
- int sepIndex = postId.indexOf(NamingContainer.SEPARATOR_CHAR);
- // If there's no separator character afterwards, then this
- // isn't a row key
- if (sepIndex < 0)
- return super.invokeOnComponent(context, clientId, callback);
- String currencyString = postId.substring(0, sepIndex);
- Object oldRowKey = getRowKey();
+ setupVisitingContext(context);
+
try
{
- setCurrencyString(currencyString);
- return super.invokeOnComponent(context, clientId, callback);
+ if (!_getAndMarkFirstInvokeForRequest(context, thisClientId))
+ {
+ // Call _init() since _flushCachedModel() assumes that
+ // selectedRowKeys and disclosedRowKeys are initialized to be non-null
+ _init();
+
+ _flushCachedModel();
+ }
+
+ String postId = clientId.substring(thisClientIdLength + 1);
+ int sepIndex = postId.indexOf(NamingContainer.SEPARATOR_CHAR);
+ // If there's no separator character afterwards, then this
+ // isn't a row key
+ if (sepIndex < 0)
+ return invokeOnChildrenComponents(context, clientId, callback);
+ else
+ {
+ String currencyString = postId.substring(0, sepIndex);
+ Object oldRowKey = getRowKey();
+ try
+ {
+ setCurrencyString(currencyString);
+
+ return invokeOnChildrenComponents(context, clientId, callback);
+ }
+ finally
+ {
+ // And restore the currency
+ setRowKey(oldRowKey);
+ }
+ }
}
finally
{
- // And restore the currency
- setRowKey(oldRowKey);
+ tearDownVisitingContext(context);
}
}
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java Tue Jan 20 15:18:43 2009
@@ -20,14 +20,29 @@
import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+
import javax.faces.component.UIComponent;
import javax.el.MethodExpression;
+import javax.faces.component.NamingContainer;
+import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+import javax.faces.render.Renderer;
+
import org.apache.myfaces.trinidad.bean.FacesBean;
+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.context.PartialPageContext;
+import org.apache.myfaces.trinidad.context.RenderingContext;
import org.apache.myfaces.trinidad.event.AttributeChangeListener;
+import org.apache.myfaces.trinidad.render.CoreRenderer;
/**
* Pure abstract base class for all UIX components.
@@ -194,6 +209,379 @@
}
/**
+ * <p>Perform a tree visit starting at
+ * this node in the tree.</p>
+ *
+ * <p>UIXComponent.visitTree() implementations do not invoke the
+ * {@code VisitCallback} directly, but instead call
+ * {@code VisitContext.invokeVisitCallback()} to invoke the
+ * callback. This allows {@code VisitContext} implementations
+ * to provide optimized tree traversals, for example by only
+ * calling the {@code VisitCallback} for a subset of components.</p>
+ *
+ * @param visitContext the <code>VisitContext</code> for this visit
+ * @param callback the <code>VisitCallback</code> instance
+ * whose <code>visit</code> method will be called
+ * for each node visited.
+ * @return component implementations may return <code>true</code>
+ * to indicate that the tree visit is complete (eg. all components
+ * that need to be visited have been visited). This results in
+ * the tree visit being short-circuited such that no more components
+ * are visited.
+ *
+ * @see VisitContext#invokeVisitCallback VisitContext.invokeVisitCallback()
+ */
+ public boolean visitTree(
+ VisitContext visitContext,
+ VisitCallback callback)
+ {
+ return visitTree(visitContext, this, callback);
+ }
+
+ /**
+ * <p>Perform a tree visit starting at the specified node in the tree.</p>
+ *
+ * <p>UIXComponent.visitTree() implementations do not invoke the
+ * {@code VisitCallback} directly, but instead call
+ * {@code VisitContext.invokeVisitCallback()} to invoke the
+ * callback. This allows {@code VisitContext} implementations
+ * to provide optimized tree traversals, for example by only
+ * calling the {@code VisitCallback} for a subset of components.</p>
+ *
+ * @param visitContext the <code>VisitContext</code> for this visit
+ * @param component the <code>UIComponent</code> to start the visit from
+ * @param callback the <code>VisitCallback</code> instance
+ * whose <code>visit</code> method will be called
+ * for each node visited.
+ * @return component implementations may return <code>true</code>
+ * to indicate that the tree visit is complete (eg. all components
+ * that need to be visited have been visited). This results in
+ * the tree visit being short-circuited such that no more components
+ * are visited.
+ *
+ * @see VisitContext#invokeVisitCallback VisitContext.invokeVisitCallback()
+ */
+ public static boolean visitTree(
+ VisitContext visitContext,
+ UIComponent component,
+ VisitCallback callback)
+ {
+ UIXComponent uixComponent;
+
+ // determine if we should even visit this component subtree
+ if (component instanceof UIXComponent)
+ {
+ uixComponent = (UIXComponent)component;
+
+ // delegate to the UIXComponent
+ if (!uixComponent.isVisitable(visitContext))
+ return false;
+ }
+ else
+ {
+ // use generic isVisitable implemetation
+ if (!_isVisitable(visitContext, component))
+ return false;
+
+ 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)
+ {
+ // now visit the children
+ FacesContext context = visitContext.getFacesContext();
+ PhaseId phaseId = visitContext.getPhaseId();
+ RenderingContext rc = (PhaseId.RENDER_RESPONSE == phaseId)
+ ? RenderingContext.getCurrentInstance()
+ : null;
+
+ if (uixComponent != null)
+ {
+ // 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;
+ }
+
+ // 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)
+ {
+ uixComponent.setUpEncodingContext(context, rc);
+ }
+ 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)
+ {
+ return true;
+ }
+ }
+ }
+ finally
+ {
+ // tear down the context we set up in order to visit our children
+ if (uixComponent != null)
+ {
+ if (PhaseId.RENDER_RESPONSE == phaseId)
+ {
+ uixComponent.tearDownEncodingContext(context, rc);
+ }
+ else
+ {
+ uixComponent.tearDownVisitingContext(context);
+ }
+ }
+ }
+ }
+ else
+ {
+ assert(result == VisitResult.REJECT);
+ }
+
+ // if we got this far, we're not done
+ return false;
+ }
+
+
+
+ /**
+ * <p>Called by
+ * {@link UIXComponent#visitTree 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
+ * {@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
+ * component nor any of its descendents will be visited></p>
+ * <p>Custom {@code treeVisit()} implementations may call this method
+ * to determine whether the component is visitable before performing
+ * any visit-related processing.</p>
+ *
+ * @return true if this component should be visited, false otherwise.
+ */
+ protected boolean isVisitable(VisitContext visitContext)
+ {
+ return _isVisitable(visitContext, this);
+ }
+
+ /**
+ * default implementation checking the <code>VisitHint.SKIP_TRANSIENT</code> and
+ * <code>VisitHint.SKIP_UNRENDERED</code> hints.
+ */
+ private static boolean _isVisitable(VisitContext visitContext, UIComponent component)
+ {
+ Collection<VisitHint> hints = visitContext.getHints();
+
+ if (hints.contains(VisitHint.SKIP_TRANSIENT) && component.isTransient())
+ return false;
+
+ if (hints.contains(VisitHint.SKIP_UNRENDERED) && !component.isRendered())
+ return false;
+
+ return true;
+ }
+
+ /**
+ * <p>
+ * Called when visiting the component during optimized partial page encoding so that the
+ * component can modify what is actually encoded. For example tab controls often
+ * render the tabs for the ShowDetailItems in the tab bar before delegating to the
+ * disclosed ShowDetailItem to render the tab content. As a result, the tab control
+ * needs to encode its tab bar if any of its ShowDetailItems are partial targets so that
+ * the tab labels, for example, are up-to-date.
+ * </p>
+ * <p>
+ * The default implementation delegates to the CoreRenderer if this component has one, otherwise
+ * it calls the VisitCallback and returns its result if this UIXComponent is a partial
+ * target of the current encoding.
+ * </p>
+ * @param visitContext VisitContext to pass to the VisitCallback
+ * @param partialContext PartialPageContext for the current partial encoding
+ * @param callback VisitCallback to call if this component is a partial target
+ * @return The VisitResult controlling continued iteration of the visit.
+ */
+ public VisitResult partialEncodeVisit(
+ VisitContext visitContext,
+ PartialPageContext partialContext,
+ VisitCallback callback)
+ {
+ FacesContext context = visitContext.getFacesContext();
+ Renderer renderer = getRenderer(context);
+
+ if (renderer instanceof CoreRenderer)
+ {
+ // delegate to the CoreRenderer
+ return ((CoreRenderer)renderer).partialEncodeVisit(visitContext,
+ partialContext,
+ this,
+ callback);
+ }
+ else
+ {
+ // check that this is a component instance that should be encoded
+ if (partialContext.isPossiblePartialTarget(getId()) &&
+ partialContext.isPartialTarget(getClientId(context)))
+ {
+ // visit the component instance
+ return callback.visit(visitContext, this);
+ }
+ else
+ {
+ // Not visiting this component, but allow visit to
+ // continue into this subtree in case we've got
+ // visit targets there.
+ return VisitResult.ACCEPT;
+ }
+ }
+ }
+
+ /**
+ * <p>Sets up the context necessary to visit or invoke the component for all phases.</p>
+ * <p>The default implementation does nothing.</p>
+ * <p>If a subclass overrides this method, it should override
+ * <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>
+ * @see #tearDownVisitingContext
+ * @see #setUpEncodingContext
+ * @see #tearDownEncodingContext
+ */
+ protected void setupVisitingContext(FacesContext context)
+ {
+ // do nothing
+ }
+
+ /**
+ * <p>Tears down context created in order to visit or invoke the component
+ * for all phases.</p>
+ * <p>The default implementation does nothing.</p>
+ * <p>A subclass should only override this method if it overrode
+ * <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>
+ * @see #setupVisitingContext
+ * @see #setUpEncodingContext
+ * @see #tearDownEncodingContext
+ */
+ protected void tearDownVisitingContext(FacesContext context)
+ {
+ // do nothing
+ }
+
+ /**
+ * <p>Sets up the context necessary to encode the component.</p>
+ * <p>The default implementation delegates to
+ * <code>CoreRenderer.setupEncodingContext</code> and then calls
+ * <code>setupVisitingContext</code></p>
+ * <p>If a subclass overrides this method, it should override
+ * <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>
+ * @see #setupVisitingContext
+ * @see #tearDownVisitingContext
+ * @see #tearDownEncodingContext
+ * @see CoreRenderer#setupEncodingContext
+ */
+ protected void setUpEncodingContext(FacesContext context, RenderingContext rc)
+ {
+ setupVisitingContext(context);
+
+ Renderer renderer = getRenderer(context);
+
+ if (renderer instanceof CoreRenderer)
+ {
+ CoreRenderer coreRenderer = (CoreRenderer)renderer;
+
+ coreRenderer.setupEncodingContext(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>
+ * <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
+ * @see #tearDownVisitingContext
+ * @see #setUpEncodingContext
+ * @see CoreRenderer#tearDownEncodingContext
+ */
+ protected void tearDownEncodingContext(
+ FacesContext context,
+ RenderingContext rc)
+ {
+ Renderer renderer = getRenderer(context);
+
+ try
+ {
+ if (renderer instanceof CoreRenderer)
+ {
+ CoreRenderer coreRenderer = (CoreRenderer)renderer;
+
+ coreRenderer.tearDownEncodingContext(context, rc, this);
+ }
+ }
+ finally
+ {
+ tearDownVisitingContext(context);
+ }
+ }
+
+ /**
* Returns the FacesBean used for storing the component's state.
*/
abstract public FacesBean getFacesBean();
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java Tue Jan 20 15:18:43 2009
@@ -35,6 +35,8 @@
import javax.el.MethodExpression;
import javax.el.ValueExpression;
+import javax.faces.FacesException;
+import javax.faces.component.ContextCallback;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
@@ -1290,6 +1292,130 @@
}
}
+ /**
+ * Convenience method to call <code>invokeOnComponent</code> on all of the
+ * children of a component. This is useful when a component sometimes optimizes
+ * away calling <code>invokeOnComponent</code> on its children
+ */
+ protected final boolean invokeOnChildrenComponents(
+ FacesContext context,
+ String clientId,
+ ContextCallback callback)
+ throws FacesException
+ {
+ Iterator<UIComponent> children = getFacetsAndChildren();
+
+ boolean found = false;
+
+ while (children.hasNext() && !found)
+ {
+ found = children.next().invokeOnComponent(context, clientId, callback);
+ }
+
+ return found;
+ }
+
+ /**
+ * <p>
+ * Optimized implementation of <code>invokeOnComponent</code> for NamingContainers.
+ * If the clientId isn't within the NamingContainer, invocation of the
+ * NamingContainer's children is skipped.
+ * </p>
+ * <p>Subclasses implementing NamingContainer should override
+ * <code>invokeOnComponent</code> and delegate to this method.</p>
+ */
+ protected final boolean invokeOnNamingContainerComponent(
+ FacesContext context,
+ String clientId,
+ ContextCallback callback)
+ throws FacesException
+ {
+ assert this instanceof NamingContainer : "Only use invokeOnNamingContainerComponent on NamingContainers";
+
+ String thisClientId = getClientId(context);
+
+ if (clientId.equals(thisClientId))
+ {
+ // this is the component we want, so invoke the callback
+ callback.invokeContextCallback(context, this);
+ return true;
+ }
+ else
+ {
+ // if this is a NamingContainer, only traverse into it if the clientId we are looking for
+ // is inside of it
+ if ((!clientId.startsWith(thisClientId) ||
+ (clientId.charAt(thisClientId.length()) != NamingContainer.SEPARATOR_CHAR)))
+ {
+ return false;
+ }
+
+ boolean invokedComponent = false;
+
+ // set up the context for visiting the children
+ setupVisitingContext(context);
+
+ try
+ {
+ // iterate through children. We inline this code instead of calling super in order
+ // to avoid making an extra call to getClientId().
+ invokedComponent = invokeOnChildrenComponents(context, clientId, callback);
+ }
+ finally
+ {
+ // teardown the context now that we have visited the children
+ tearDownVisitingContext(context);
+ }
+
+ return invokedComponent;
+ }
+ }
+
+
+ /**
+ * Override to calls the hooks for setting up and tearing down the
+ * context before the children are visited.
+ * @see #setupVisitingContext
+ * @see #tearDownVisitingContext
+ */
+ @Override
+ public boolean invokeOnComponent(
+ FacesContext context,
+ String clientId,
+ ContextCallback callback)
+ throws FacesException
+ {
+ String thisClientId = getClientId(context);
+
+ if (clientId.equals(thisClientId))
+ {
+ callback.invokeContextCallback(context, this);
+ return true;
+ }
+ else
+ {
+ boolean invokedComponent = false;
+
+ // set up the context for visiting the children
+ setupVisitingContext(context);
+
+ try
+ {
+ // iterate through children. We inline this code instead of calling super in order
+ // to avoid making an extra call to getClientId().
+ invokedComponent = invokeOnChildrenComponents(context, clientId, callback);
+ }
+ finally
+ {
+ // teardown the context now that we have visited the children
+ tearDownVisitingContext(context);
+ }
+
+ return invokedComponent;
+ }
+ }
+
+
/**
* <p>
Added: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitCallback.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitCallback.java?rev=736165&view=auto
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitCallback.java (added)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitCallback.java Tue Jan 20 15:18:43 2009
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.trinidad.component.visit;
+
+import javax.faces.component.UIComponent;
+
+/**
+ *
+ * <p>A simple callback interface that enables
+ * 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()
+ */
+public interface VisitCallback
+{
+ /**
+ * <p>This method is called during component tree visits by
+ * {@link VisitContext#invokeVisitCallback VisitContext.invokeVisitCallback()}
+ * to visit the specified component. At the point in time when this
+ * method is called, the argument {@code target} is guaranteed
+ * 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 target the {@link UIComponent} to visit
+ *
+ * @return a {@link VisitResult} that indicates whether to continue
+ * visiting the component's subtree, skip visiting the component's
+ * subtree or end the visit.
+ */
+ public VisitResult visit(VisitContext context, UIComponent target);
+}
Added: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitContext.java?rev=736165&view=auto
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitContext.java (added)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitContext.java Tue Jan 20 15:18:43 2009
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.trinidad.component.visit;
+
+import java.util.AbstractCollection;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+
+/**
+ *
+ * <p>A context object that is used to hold
+ * 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()},
+ * 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 VisitCallback
+ *
+ */
+abstract public class VisitContext
+{
+ // Design notes: The VisitContext contract could be defined
+ // as an interface. However, there is the potential that we
+ // may need to add new methods in the future, so leaving as
+ // an abstract class in order to have room to grow.
+ //
+ // Since we are an abstract class rather than an interface,
+ // we could provide implementations of of some of the simpler
+ // methods (eg. getFacesContext() and getHints()) to avoid
+ // duplicating this code in VisitContext implementations.
+ // However, doing so would mean that "wrapping" VisitContext
+ // implementations would be forced to pick up such implementations,
+ // so going with a pure contract (no implementation).
+
+ /**
+ * <p>This unmodifiable Collection is returned by
+ * VisitContext.getIdsToVisit() and getSubtreeIdsToVisit( in cases where all ids
+ * should be visited.</p>
+ * <p>To simplify logic for visitTree() implementations, this Collection
+ * always return {@code false} for {@code isEmpty}. All other methods
+ * throw {@code UnsupportedOperationException}.</p>
+ */
+ // Note: We cannot use Collections.emptyList() as that returns
+ // a shared instance - we want to unique instance to allow for
+ // identity tests.
+ static public final Collection<String> ALL_IDS =
+ new AbstractCollection<String>()
+ {
+ @Override
+ public Iterator<String> iterator()
+ {
+ throw new UnsupportedOperationException(
+ "VisitContext.ALL_IDS does not support this operation");
+ }
+
+ @Override
+ public int size()
+ {
+ throw new UnsupportedOperationException(
+ "VisitContext.ALL_IDS does not support this operation");
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return false;
+ }
+ };
+
+ /**
+ * <p>Returns the FacesContext for the current request.</p>
+ */
+ abstract public FacesContext getFacesContext();
+
+ /**
+ * <p>Returns the PhaseId, if any that, that this visit is ocurring under
+ * @return the current PhaseId
+ */
+ public abstract PhaseId getPhaseId();
+
+ /**
+ * <p>
+ * Returns the ids of the components to visit.
+ * </p>
+ * <p>
+ * In the case of a full tree visit, this method returns the
+ * ALL_IDS collection. Otherwise, if a partial visit is being
+ * performed, returns a modifiable collection containing the
+ * client ids of the components that should be visited.
+ * </p>
+ * @return {@code VisitContext.ALL_IDS}, or a modifiable
+ * Collection of client ids.
+ */
+ abstract public Collection<String> getIdsToVisit();
+
+ /**
+ * <p>
+ * Given a NamingContainer component, returns the client ids of
+ * any components underneath the NamingContainer that should be
+ * visited.
+ * </p>
+ * <p>
+ * This method is called by NamingContainer visitTree() implementations
+ * to determine whether the NamingContainer contains components to be
+ * visited. In the case where no such components exist, the
+ * NamingContainer can short-circuit the tree visit and avoid
+ * descending into child subtrees.
+ * </p>
+ * <p>
+ * In addition, iterating components such as UIData may be able to
+ * use the returned ids to determine which iterated states (ie. rows)
+ * need to be visited. This allows the visit traversal to be
+ * contstrained such only those rows that contain visit targets
+ * need to be traversed.
+ * </p>
+ * @param component a NamingContainer component
+ * @return an unmodifiable Collection containing the client ids of
+ * any components underneath the NamingContainer that are known to be
+ * targets of the tree visit. If no such components exist, returns
+ * an empty Collection. If all components underneath the
+ * NamingContainer should be visited, returns the
+ * {@code VisitContext.ALL_IDS} collection.
+ * @throws IllegalArgumentException if {@code component} is not
+ * an instance of NamingContainer
+ */
+ abstract public Collection<String> getSubtreeIdsToVisit(UIComponent component);
+
+ /**
+ * <p>Called by {@link org.apache.myfaces.trinidad.component.UIXComponent#visitTree UIXComponent.visitTree()}
+ * to visit a single component.</p>
+ *
+ * @param component the component to visit
+ * @param callback the VisitCallback to call
+ * @return a VisitResult value that indicates whether to continue
+ * visiting the component's subtree, skip visiting the component's
+ * subtree or abort the visit altogether.
+ */
+ abstract public VisitResult invokeVisitCallback(UIComponent component,
+ VisitCallback callback);
+
+ /**
+ * <p>Returns hints that influence the behavior of the tree visit.</p>
+ *
+ * <p>Interested parties, such as
+ * {@link org.apache.myfaces.trinidad.component.UIXComponent#visitTree UIComponent.visitTree()} implementations,
+ * may check to see whether a particular hint is present by calling
+ * {@code VisitContext.getHints().contains()}, passing in one of the
+ * hints defined by {@link VisitHint}.
+ *
+ * @return a non-empty, unmodifiable collection of VisitHints
+ */
+ abstract public Set<VisitHint> getHints();
+}
Added: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitHint.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitHint.java?rev=736165&view=auto
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitHint.java (added)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitHint.java Tue Jan 20 15:18:43 2009
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.apache.myfaces.trinidad.component.visit;
+
+/**
+ *
+ * <p>An enum that specifies hints that impact
+ * the behavior of a component tree visit.</p>
+ *
+ * @see VisitContext#getHints VisitContext.getHints()
+ */
+public enum VisitHint
+{
+ /**
+ * Hint that indicates that only the rendered subtree should be visited.
+ */
+ SKIP_UNRENDERED,
+
+ /**
+ * Hint that indicates that only non-transient subtrees should be visited.
+ */
+ SKIP_TRANSIENT,
+
+ /**
+ * Hint that indicates that the visit is being performed as part of
+ * lifecycle phase execution and as such phase-specific actions
+ * (initialization) may be taken.
+ */
+ EXECUTE_LIFECYCLE
+}
Added: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitResult.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitResult.java?rev=736165&view=auto
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitResult.java (added)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/visit/VisitResult.java Tue Jan 20 15:18:43 2009
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.trinidad.component.visit;
+
+/**
+ *
+ * <p>An enum that specifies the possible
+ * results of a call to {@link VisitCallback#visit VisitCallback.visit()}.
+ * </p>
+ *
+ * @see VisitCallback#visit VisitCallback.visit()
+ */
+public enum VisitResult
+{
+ /**
+ * This result indicates that the tree visit should descend into
+ * current component's subtree.
+ */
+ ACCEPT,
+
+ /**
+ * This result indicates that the tree visit should continue, but
+ * should skip the current component's subtree.
+ */
+ REJECT,
+
+ /**
+ * This result indicates that the tree visit should be terminated.
+ */
+ COMPLETE
+}
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/PartialPageContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/PartialPageContext.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/PartialPageContext.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/PartialPageContext.java Tue Jan 20 15:18:43 2009
@@ -20,6 +20,8 @@
import java.util.Iterator;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+
/**
* Context object which is used to track the targets of a partial
@@ -43,10 +45,33 @@
}
/**
- * Tests whether the specified id is the client id of a UIComponent that
+ * Tests whether the specified client id is the client id of a UIComponent that
* should be rendered as part of the partial rendering pass.
+ * @return <code>true</code> if a compoennt with this client id should be rendered.
+ * @see #isPossiblePartialTarget
*/
- abstract public boolean isPartialTarget(String id);
+ abstract public boolean isPartialTarget(String clientId);
+
+ /**
+ * <p>
+ * Tests whether the specified component id is a component id of a UIComponent that
+ * might be rendered in this partial rendering pass.
+ * </p>
+ * <p>
+ * As calculating clientIds is expensive, this method allows a cheap test to reject components
+ * that shouldn't be rendered. If this method returns true, a more
+ * exact test using <code>isPartialTarget</code> with the desired clientId should be performed.
+ * </p>
+ * @return <code>true</code> if a component with this id should be rendered.
+ * @see #isPartialTarget
+ */
+ abstract public boolean isPossiblePartialTarget(String componentId);
+
+ /**
+ * Returns <code>true</code> if all of the partial targets have been rendered.
+ * @return <code>true</code> if all of the partial targets have been rendered.
+ */
+ public abstract boolean areAllTargetsProcessed();
/**
* Returns the set of partial targets for this rendering pass.
@@ -80,5 +105,15 @@
*/
abstract public void addRenderedPartialTarget(String id);
+ /**
+ * Returns the client ids of the partial targets that have been rendered so far.
+ * @return the client ids of the partial targets that have been rendered so far.
+ */
abstract public Iterator<String> getRenderedPartialTargets();
+
+ /**
+ * Returns the VisitContext to use when partial rendering.
+ * @return the VisitContext to use when partial rendering.
+ */
+ abstract public VisitContext getVisitContext();
}
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java Tue Jan 20 15:18:43 2009
@@ -19,6 +19,8 @@
package org.apache.myfaces.trinidad.context;
import java.awt.Color;
+
+import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -32,10 +34,13 @@
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+
import org.apache.myfaces.trinidad.change.ChangeManager;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+import org.apache.myfaces.trinidad.component.visit.VisitHint;
import org.apache.myfaces.trinidad.config.RegionManager;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
-import org.apache.myfaces.trinidad.util.ComponentUtils;
import org.apache.myfaces.trinidad.webapp.UploadedFileProcessor;
/**
@@ -475,6 +480,25 @@
// Miscellaneous functionality
//
+ /**
+ * <p>Creates a VisitContext instance for use with
+ * {@link org.apache.myfaces.trinidad.component.UIXComponent#visitTree UIComponent.visitTree()}.</p>
+ *
+ * @param context the FacesContext for the current request
+ * @param ids the client ids of the components to visit. If null,
+ * all components will be visited.
+ * @param hints the VisitHints to apply to the visit
+ * @param phaseId. PhaseId if any for this visit. If PhaseId is specified,
+ * hints must contain VisitHint.EXECUTE_LIFECYCLE
+ * @return a VisitContext instance that is initialized with the
+ * specified ids and hints.
+ */
+ public abstract VisitContext createVisitContext(
+ FacesContext context,
+ Collection<String> ids,
+ Set<VisitHint> hints,
+ PhaseId phaseId);
+
public abstract UploadedFileProcessor getUploadedFileProcessor();
/**
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/render/CoreRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/render/CoreRenderer.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/render/CoreRenderer.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/render/CoreRenderer.java Tue Jan 20 15:18:43 2009
@@ -30,7 +30,11 @@
import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.component.UIXComponent;
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+import org.apache.myfaces.trinidad.component.visit.VisitResult;
import org.apache.myfaces.trinidad.context.Agent;
+import org.apache.myfaces.trinidad.context.PartialPageContext;
import org.apache.myfaces.trinidad.context.RequestContext;
import org.apache.myfaces.trinidad.context.RenderingContext;
@@ -50,7 +54,89 @@
{
}
+ /**
+ * <p>
+ * Called when visiting the CoreRenderer's component during optimized partial page encoding so
+ * that the CoreRenderer can modify what is actually encoded. For example tab controls often
+ * render the tabs for the ShowDetailItems in the tab bar before delegating to the
+ * disclosed ShowDetailItem to render the tab content. As a result, the tab control
+ * needs to encode its tab bar if any of its ShowDetailItems are partial targets so that
+ * the tab labels, for example, are up-to-date.
+ * </p>
+ * <p>
+ * The default implementation calls the VisitCallback and returns its result if this UIXComponent
+ * is a partial target of the current encoding.
+ * </p>
+ * @param visitContext VisitContext to pass to the VisitCallback
+ * @param partialContext PartialPageContext for the current partial encoding
+ * @param component The component for the CoreRenderer to visit
+ * @param callback VisitCallback to call if this component is a partial target
+ * @return The VisitResult controlling continued iteration of the visit.
+ */
+ public VisitResult partialEncodeVisit(
+ VisitContext visitContext,
+ PartialPageContext partialContext,
+ UIComponent component,
+ VisitCallback callback)
+ {
+ if (partialContext.isPossiblePartialTarget(component.getId()) &&
+ partialContext.isPartialTarget(component.getClientId(visitContext.getFacesContext())))
+ {
+ // visit the component instance
+ return callback.visit(visitContext, component);
+ }
+ else
+ {
+ // Not visiting this component, but allow visit to
+ // continue into this subtree in case we've got
+ // visit targets there.
+ return VisitResult.ACCEPT;
+ }
+ }
+ /**
+ * <p>
+ * Called before rendering the current component's children in order to set
+ * up any special context.
+ * </p>
+ * <p>If <code>setupEncodingContext</code> succeeds then
+ * <code>tearDownEncodingContext</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 #tearDownEncodingContext
+ */
+ public void setupEncodingContext(
+ FacesContext context,
+ RenderingContext rc,
+ UIXComponent component)
+ {
+ }
+
+ /**
+ * <p>
+ * Called after rendering the current component's children in order to tear
+ * down any special context.
+ * </p>
+ * <p>
+ * <code>tearDownEncodingContext</code> will be called on the component if
+ * <code>setupEncodingContext</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 #setupEncodingContext
+ */
+ public void tearDownEncodingContext(
+ FacesContext context,
+ RenderingContext rc,
+ UIXComponent component)
+ {
+ }
+
//
// COERCION HELPERS
//
@@ -186,7 +272,7 @@
@Override
public final void encodeBegin(FacesContext context,
UIComponent component) throws IOException
- {
+ {
if (!getRendersChildren())
{
RenderingContext arc = RenderingContext.getCurrentInstance();
@@ -596,7 +682,9 @@
RenderingContext arc,
UIComponent component,
FacesBean bean)
- {}
+ {
+ setupEncodingContext(context, arc, (UIXComponent)component);
+ }
/**
* Hook method that gets invoked after the component is encoded
@@ -609,7 +697,9 @@
RenderingContext arc,
UIComponent component,
FacesBean bean)
- {}
+ {
+ tearDownEncodingContext(context, arc, (UIXComponent)component);
+ }
//
// Rendering convenience methods.
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java Tue Jan 20 15:18:43 2009
@@ -25,6 +25,7 @@
import java.io.Serializable;
import java.lang.reflect.Array;
+import java.util.AbstractQueue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -34,7 +35,8 @@
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
-import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Queue;
import java.util.RandomAccess;
import java.util.Set;
@@ -49,6 +51,49 @@
{
// no-op
}
+
+ /**
+ * Returns an ArrayList containing all of the elements of the
+ * Iterator
+ * @param iterator Iterator to copy the contexts of
+ * @return an ArrayList containing a copy of the iterator contents
+ */
+ public static <T> ArrayList<T> arrayList(Iterator<T> iterator)
+ {
+ ArrayList<T> arrayList = new ArrayList<T>();
+
+ while (iterator.hasNext())
+ arrayList.add(iterator.next());
+
+ return arrayList;
+ }
+
+ /**
+ * Returns an empty, unmodifiable, Serializable Queue.
+ * @return an empty, unmodifiable, Serializable Queue.
+ */
+ public static <T> Queue<T> emptyQueue()
+ {
+ return (Queue<T>)_EMPTY_QUEUE;
+ }
+
+ /**
+ * Returns an empty, unmodifiable, Iterator.
+ * @return an empty, unmodifiable, Iterator.
+ */
+ public static <T> Iterator<T> emptyIterator()
+ {
+ return (Iterator<T>)_EMPTY_ITERATOR;
+ }
+
+ /**
+ * Returns an empty, unmodifiable, ListIterator.
+ * @return an empty, unmodifiable, ListIterator.
+ */
+ public static <T> ListIterator<T> emptyListIterator()
+ {
+ return (ListIterator<T>)_EMPTY_LIST_ITERATOR;
+ }
/**
* Returns a Collection based on the passed in Collection <code>c</code>,
@@ -725,6 +770,104 @@
private final Map<K, V> _delegate;
}
+ private static class EmptyIterator implements Iterator
+ {
+ public boolean hasNext()
+ {
+ return false;
+ }
+
+ public Object next()
+ {
+ throw new NoSuchElementException();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static final class EmptyListIterator extends EmptyIterator implements ListIterator
+ {
+ public boolean hasPrevious()
+ {
+ return false;
+ }
+
+ public Object previous()
+ {
+ throw new NoSuchElementException();
+ }
+
+ public int nextIndex()
+ {
+ return 0;
+ }
+
+ public int previousIndex()
+ {
+ return -1;
+ }
+
+ public void set(Object e)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void add(Object e)
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static final class EmptyQueue extends AbstractQueue implements Serializable
+ {
+ public Iterator iterator()
+ {
+ return _EMPTY_ITERATOR;
+ }
+
+ public int size()
+ {
+ return 0;
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean contains(Object o)
+ {
+ return false;
+ }
+
+ public boolean offer(Object e)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object poll()
+ {
+ return null;
+ }
+
+ public Object peek()
+ {
+ return null;
+ }
+
+ private Object readResolve()
+ {
+ return _EMPTY_QUEUE;
+ }
+
+ private static final long serialVersionUID = 0L;
+ }
+
//
// Build up references to implementation classes used by Collections to implement the following
// features. This way we can detect when these classes are used and work around problems.
@@ -732,6 +875,10 @@
private static final Class<? extends List> _CHECKED_LIST;
private static final Class<? extends List> _UNMODIFIABLE_LIST;
private static final Class<? extends List> _SYNCHRONIZED_LIST;
+ 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();
+
static
{
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/test/java/org/apache/myfaces/trinidad/context/MockRequestContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/test/java/org/apache/myfaces/trinidad/context/MockRequestContext.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/test/java/org/apache/myfaces/trinidad/context/MockRequestContext.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/test/java/org/apache/myfaces/trinidad/context/MockRequestContext.java Tue Jan 20 15:18:43 2009
@@ -19,6 +19,8 @@
package org.apache.myfaces.trinidad.context;
import java.awt.Color;
+
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -30,7 +32,11 @@
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+
import org.apache.myfaces.trinidad.change.ChangeManager;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+import org.apache.myfaces.trinidad.component.visit.VisitHint;
import org.apache.myfaces.trinidad.config.RegionManager;
import org.apache.myfaces.trinidad.webapp.UploadedFileProcessor;
@@ -348,6 +354,16 @@
throw new UnsupportedOperationException("Not implemented yet");
}
+ @Override
+ public VisitContext createVisitContext(
+ FacesContext context,
+ Collection<String> ids,
+ Set<VisitHint> hints,
+ PhaseId phaseId)
+ {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
static private final TimeZone _FIXED_TIME_ZONE =
TimeZone.getTimeZone("America/Los_Angeles");
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ComponentEditorHandler.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ComponentEditorHandler.java?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ComponentEditorHandler.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ComponentEditorHandler.java Tue Jan 20 15:18:43 2009
@@ -31,10 +31,14 @@
import javax.faces.component.UIComponent;
+import org.apache.myfaces.trinidad.context.RequestContext;
+
public class ComponentEditorHandler
{
public String update()
{
+ boolean rendered = _editedComponent.isRendered();
+
List<PropertyOfComponent> list = _list;
if (list != null)
{
@@ -44,6 +48,14 @@
}
}
+ RequestContext rc = RequestContext.getCurrentInstance();
+
+ // If we toggled rendered, we'd better toggle the parent
+ if (rendered != _editedComponent.isRendered())
+ rc.addPartialTarget(_editedComponent.getParent());
+ else
+ rc.addPartialTarget(_editedComponent);
+
return null;
}
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml Tue Jan 20 15:18:43 2009
@@ -42,6 +42,12 @@
<param-value>false</param-value>
</context-param>
+ <!-- Temporary internal flag to set to enabled and test Optimized PPR -->
+ <context-param>
+ <param-name>org.apache.myfaces.trinidadinternal.ENABLE_PPR_OPTIMIZATION</param-name>
+ <param-value>false</param-value>
+ </context-param>
+
<!-- Parameter to set the maximum number of client view state tokens.
Uncomment this to test low-token-count scenarios.
<context-param>
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/editor.jspf
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/editor.jspf?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/editor.jspf (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/editor.jspf Tue Jan 20 15:18:43 2009
@@ -47,6 +47,6 @@
</tr:column>
<f:facet name="footer">
<tr:commandButton text="Update"
- action="#{editor.update}"/>
+ action="#{editor.update}" partialSubmit="true"/>
</f:facet>
</tr:table>
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/showDetailItem.jspx
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/showDetailItem.jspx?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/showDetailItem.jspx (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/components/showDetailItem.jspx Tue Jan 20 15:18:43 2009
@@ -47,7 +47,7 @@
</tr:inputText>
</tr:panelFormLayout>
<tr:panelTabbed>
- <tr:showDetailItem binding="#{editor.component}" text="Tab 1">
+ <tr:showDetailItem id="editedComponent" binding="#{editor.component}" text="Tab 1">
<tr:panelHeader text="Header 1">
<tr:panelFormLayout>
<tr:inputText readOnly="true" label="Label 1-1" value="Value"
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/demos/carDemo.jspx
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/demos/carDemo.jspx?rev=736165&r1=736164&r2=736165&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/demos/carDemo.jspx (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-examples/trinidad-demo/src/main/webapp/demos/carDemo.jspx Tue Jan 20 15:18:43 2009
@@ -66,14 +66,14 @@
<!-- A link to show the options; it starts out disabled -->
<tr:commandLink id="launchOptions" disabled="true"
shortDesc="Click to pick new options"
- partialTriggers="modelsChoice makeChoice"
+ partialTriggers="modelsChoice makesChoice"
returnListener="#{carBacking.returnOptions}"
binding="#{carBacking.launchOptions}"
useWindow="true"
action="dialog:optionsDialog" text="Pick options: "/>
<tr:outputText id="options"
binding="#{carBacking.options}"
- partialTriggers="launchOptions modelsChoice makeChoice"/>
+ partialTriggers="launchOptions modelsChoice makesChoice"/>
</tr:panelGroupLayout>
</tr:panelPage>
Added: myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/FullVisitContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/FullVisitContext.java?rev=736165&view=auto
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/FullVisitContext.java (added)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/FullVisitContext.java Tue Jan 20 15:18:43 2009
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.trinidadinternal.context;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import javax.faces.component.NamingContainer;
+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;
+import org.apache.myfaces.trinidad.component.visit.VisitHint;
+import org.apache.myfaces.trinidad.component.visit.VisitResult;
+
+/**
+ *
+ * <p>A VisitContext implementation that is
+ * used when performing a full component tree visit.</p>
+ */
+class FullVisitContext extends VisitContext
+{
+
+ /**
+ * Creates a FullVisitorContext instance.
+ * @param facesContext the FacesContext for the current request
+ * @throws NullPointerException if {@code facesContext}
+ * is {@code null}
+ */
+ public FullVisitContext(FacesContext facesContext)
+ {
+ this(facesContext, null, null);
+ }
+
+ /**
+ * Creates a FullVisitorContext instance with the specified
+ * hints.
+ *
+ * @param facesContext the FacesContext for the current request
+ * @param hints a the VisitHints for this visit
+ * @param phaseId PhaseId, if any that visit is ocurring under
+ * @throws NullPointerException if {@code facesContext}
+ * is {@code null}
+ * @throws IllegalArgumentException if the phaseId is specified and
+ * hints does not contain VisitHint.EXECUTE_LIFECYCLE
+ */
+ public FullVisitContext(
+ FacesContext facesContext,
+ Set<VisitHint> hints,
+ PhaseId phaseId)
+ {
+ if (facesContext == null)
+ throw new NullPointerException();
+
+ if ((phaseId != null) && ((hints == null) || (!hints.contains(VisitHint.EXECUTE_LIFECYCLE))))
+ throw new IllegalArgumentException();
+
+ _facesContext = facesContext;
+ _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);
+ }
+
+ /**
+ * @see VisitContext#getFacesContext VisitContext.getFacesContext()
+ */
+ @Override
+ public FacesContext getFacesContext()
+ {
+ return _facesContext;
+ }
+
+ /**
+ * <p>Returns the PhaseId, if any that, that this visit is ocurring under
+ * @return the current PhaseId
+ */
+ public PhaseId getPhaseId()
+ {
+ return _phaseId;
+ }
+
+ /**
+ * @see VisitContext#getIdsToVisit VisitContext.getIdsToVisit()
+ */
+ @Override
+ public Collection<String> getIdsToVisit()
+ {
+ // We always visits all ids
+ return ALL_IDS;
+ }
+
+ /**
+ * @see VisitContext#getSubtreeIdsToVisit VisitContext.getSubtreeIdsToVisit()
+ */
+ @Override
+ public Collection<String> getSubtreeIdsToVisit(UIComponent component)
+ {
+ // Make sure component is a NamingContainer
+ if (!(component instanceof NamingContainer))
+ {
+ throw new IllegalArgumentException("Component is not a NamingContainer: " + component);
+ }
+
+ // We always visits all ids
+ return ALL_IDS;
+ }
+
+ /**
+ * @see VisitContext#getHints VisitContext.getHints
+ */
+ @Override
+ public Set<VisitHint> getHints()
+ {
+ return _hints;
+ }
+
+ /**
+ * @see VisitContext#invokeVisitCallback VisitContext.invokeVisitCallback()
+ */
+ @Override
+ public VisitResult invokeVisitCallback(
+ UIComponent component,
+ VisitCallback callback)
+ {
+ // Nothing interesting here - just invoke the callback.
+ // (PartialVisitContext.invokeVisitCallback() does all of the
+ // interesting work.)
+ return callback.visit(this, component);
+ }
+
+ // The FacesContext for this request
+ private final FacesContext _facesContext;
+
+ // Our visit hints
+ private final Set<VisitHint> _hints;
+ private final PhaseId _phaseId;
+}