You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/01/29 01:54:50 UTC
svn commit: r904329 - in
/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets: ./
compiler/ impl/ tag/composite/ tag/jsf/
Author: lu4242
Date: Fri Jan 29 00:54:49 2010
New Revision: 904329
URL: http://svn.apache.org/viewvc?rev=904329&view=rev
Log:
MYFACES-2502 Component state is lost for composite component childs of facets relocated by composite:insertChildren or composite:insertFacet
Modified:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/UIInstructionHandler.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/ImplementationHandler.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertChildrenHandler.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertFacetHandler.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InterfaceHandler.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java Fri Jan 29 00:54:49 2010
@@ -228,4 +228,29 @@
*/
public abstract void pushEnclosingValidatorIdToStack(String validatorId);
+ /**
+ * Check if this build is being refreshed, adding transient components
+ * and adding/removing components under c:if or c:forEach or not.
+ *
+ * @return
+ * @since 2.0
+ */
+ public abstract boolean isRefreshingTransientBuild();
+
+ /**
+ * Check if this build should be marked as initial state. In other words,
+ * all components must call UIComponent.markInitialState.
+ *
+ * @return
+ * @since 2.0
+ */
+ public abstract boolean isMarkInitialState();
+
+ /**
+ * Check if this build is for build composite component metadata
+ *
+ * @return
+ * @since 2.0
+ */
+ public abstract boolean isBuildingCompositeComponentMetadata();
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java Fri Jan 29 00:54:49 2010
@@ -56,6 +56,8 @@
import javax.faces.event.MethodExpressionActionListener;
import javax.faces.event.MethodExpressionValueChangeListener;
import javax.faces.event.PhaseId;
+import javax.faces.event.PostAddToViewEvent;
+import javax.faces.event.PreRemoveFromViewEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.render.RenderKit;
import javax.faces.validator.MethodExpressionValidator;
@@ -178,6 +180,8 @@
public final static String BUILDING_VIEW_METADATA = "org.apache.myfaces.BUILDING_VIEW_METADATA";
+ public final static String REFRESHING_TRANSIENT_BUILD = "org.apache.myfaces.REFRESHING_TRANSIENT_BUILD";
+
/**
* Marker to indicate tag handlers the view currently being built is using
* partial state saving and it is necessary to call UIComponent.markInitialState
@@ -234,6 +238,7 @@
}
boolean usePartialStateSavingOnThisView = _usePartialStateSavingOnThisView(renderedViewId);
+ boolean refreshTransientBuild = (view.getChildCount() > 0);
if (usePartialStateSavingOnThisView)
{
@@ -248,11 +253,44 @@
//Add a key to indicate ComponentTagHandlerDelegate to
//call UIComponent.markInitialState after it is populated
- context.getAttributes().put(MARK_INITIAL_STATE_KEY, Boolean.TRUE);
+ if (!refreshTransientBuild)
+ {
+ context.getAttributes().put(MARK_INITIAL_STATE_KEY, Boolean.TRUE);
+ }
}
- // populate UIViewRoot
- _getFacelet(renderedViewId).apply(context, view);
+ try
+ {
+ if (refreshTransientBuild)
+ {
+ context.getAttributes().put(REFRESHING_TRANSIENT_BUILD, Boolean.TRUE);
+
+ context.setProcessingEvents(false);
+ }
+ // populate UIViewRoot
+ _getFacelet(renderedViewId).apply(context, view);
+ }
+ finally
+ {
+ if (refreshTransientBuild)
+ {
+ context.setProcessingEvents(true);
+
+ context.getAttributes().remove(REFRESHING_TRANSIENT_BUILD);
+
+ if (!usePartialStateSavingOnThisView)
+ {
+ // When the facelet is applied, all components are removed and added from view,
+ // but the difference resides in the ordering. Since the view is
+ // being refreshed, if we don't do this manually, some tags like
+ // cc:insertChildren or cc:insertFacet will not work correctly, because
+ // we expect PostAddToViewEvent will be propagated from parent to child, and
+ // facelets refreshing algorithm do the opposite.
+ FaceletViewDeclarationLanguage._publishPreRemoveFromViewEvent(context, view);
+ FaceletViewDeclarationLanguage._publishPostAddToViewEvent(context, view);
+ }
+ }
+ }
// set this view as filled
setFilledView(context, view);
@@ -274,13 +312,70 @@
// DefaultFaceletsStateManagement.restoreView after calling
// _publishPostBuildComponentTreeOnRestoreViewEvent(), to ensure
// relocated components are not retrieved later on getClientIdsRemoved().
- if (!(context.isPostback() && PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId())))
+ if (!(refreshTransientBuild && PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId())))
{
((DefaultFaceletsStateManagementStrategy) getStateManagementStrategy(context, view.getViewId())).suscribeListeners(view);
}
}
}
+ private static void _publishPreRemoveFromViewEvent(FacesContext context, UIComponent component)
+ {
+ context.getApplication().publishEvent(context, PreRemoveFromViewEvent.class, UIComponent.class, component);
+
+ if (component.getChildCount() > 0)
+ {
+ for (UIComponent child : component.getChildren())
+ {
+ _publishPreRemoveFromViewEvent(context, child);
+ }
+ }
+ if (component.getFacetCount() > 0)
+ {
+ for (UIComponent child : component.getFacets().values())
+ {
+ _publishPreRemoveFromViewEvent(context, child);
+ }
+ }
+ }
+
+ public static void _publishPostAddToViewEvent(FacesContext context, UIComponent component)
+ {
+ context.getApplication().publishEvent(context, PostAddToViewEvent.class, UIComponent.class, component);
+
+ if (component.getChildCount() > 0)
+ {
+ // PostAddToViewEvent could cause component relocation
+ // (h:outputScript, h:outputStylesheet, composite:insertChildren, composite:insertFacet)
+ // so we need to check if the component was relocated or not
+ List<UIComponent> children = component.getChildren();
+ UIComponent child = null;
+ UIComponent currentChild = null;
+ int i = 0;
+ while (i < children.size())
+ {
+ child = children.get(i);
+ // Iterate over the same index if the component was removed
+ // This prevents skip components when processing
+ do
+ {
+ _publishPostAddToViewEvent(context, child);
+ currentChild = child;
+ }
+ while ((i < children.size()) &&
+ ((child = children.get(i)) != currentChild) );
+ i++;
+ }
+ }
+ if (component.getFacetCount() > 0)
+ {
+ for (UIComponent child : component.getFacets().values())
+ {
+ _publishPostAddToViewEvent(context, child);
+ }
+ }
+ }
+
private boolean isFilledView(FacesContext context, UIViewRoot view)
{
// The view is only built on restoreView or renderView, but if
@@ -395,6 +490,16 @@
return context.getAttributes().containsKey(BUILDING_VIEW_METADATA);
}
+ public static boolean isRefreshingTransientBuild(FacesContext context)
+ {
+ return context.getAttributes().containsKey(REFRESHING_TRANSIENT_BUILD);
+ }
+
+ public static boolean isMarkInitialState(FacesContext context)
+ {
+ return context.getAttributes().containsKey(MARK_INITIAL_STATE_KEY);
+ }
+
/**
* In short words, this method take care of "target" an "attached object".
* <ul>
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/UIInstructionHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/UIInstructionHandler.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/UIInstructionHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/UIInstructionHandler.java Fri Jan 29 00:54:49 2010
@@ -20,6 +20,8 @@
import java.io.IOException;
import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
import javax.el.ELException;
import javax.faces.FacesException;
@@ -30,6 +32,8 @@
import org.apache.myfaces.view.facelets.AbstractFaceletContext;
import org.apache.myfaces.view.facelets.el.ELText;
+import org.apache.myfaces.view.facelets.tag.composite.InsertChildrenHandler;
+import org.apache.myfaces.view.facelets.tag.composite.InsertFacetHandler;
import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
import org.apache.myfaces.view.facelets.util.FastWriter;
@@ -139,6 +143,44 @@
ComponentSupport.finalizeForDeletion(c);
parent.getChildren().remove(c);
}
+ if ( ((AbstractFaceletContext)ctx).isRefreshingTransientBuild()
+ && UIComponent.isCompositeComponent(parent))
+ {
+ // Save the child structure behind this component, so it can be
+ // used later by InsertChildrenHandler and InsertFacetHandler
+ // to update components correctly.
+ String facetName = this.getFacetName(ctx, parent);
+ if (facetName != null)
+ {
+ if (parent.getAttributes().containsKey(InsertFacetHandler.INSERT_FACET_TARGET_ID+facetName))
+ {
+ List<String> ordering = (List<String>) parent.getAttributes().get(
+ InsertFacetHandler.INSERT_FACET_ORDERING+facetName);
+ if (ordering == null)
+ {
+ ordering = new ArrayList<String>();
+ parent.getAttributes().put(InsertFacetHandler.INSERT_FACET_ORDERING+facetName, ordering);
+ }
+ ordering.remove(id);
+ ordering.add(id);
+ }
+ }
+ else
+ {
+ if (parent.getAttributes().containsKey(InsertChildrenHandler.INSERT_CHILDREN_TARGET_ID))
+ {
+ List<String> ordering = (List<String>) parent.getAttributes().get(
+ InsertChildrenHandler.INSERT_CHILDREN_ORDERING);
+ if (ordering == null)
+ {
+ ordering = new ArrayList<String>();
+ parent.getAttributes().put(InsertChildrenHandler.INSERT_CHILDREN_ORDERING, ordering);
+ }
+ ordering.remove(id);
+ ordering.add(id);
+ }
+ }
+ }
this.addComponent(ctx, parent, c);
}
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java Fri Jan 29 00:54:49 2010
@@ -45,6 +45,7 @@
import javax.faces.view.facelets.FaceletException;
import org.apache.myfaces.view.facelets.AbstractFaceletContext;
+import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
import org.apache.myfaces.view.facelets.TemplateClient;
import org.apache.myfaces.view.facelets.el.DefaultVariableMapper;
import org.apache.myfaces.view.facelets.tag.jsf.core.AjaxHandler;
@@ -91,6 +92,12 @@
private final StringBuilder _uniqueIdBuilder = new StringBuilder(30);
private final List<TemplateManager> _clients;
+
+ private final boolean _isRefreshingTransientBuild;
+
+ private final boolean _isMarkInitialState;
+
+ private final boolean _isBuildingCompositeComponentMetadata;
public DefaultFaceletContext(DefaultFaceletContext ctx,
DefaultFacelet facelet)
@@ -107,6 +114,9 @@
_faceletHierarchy.addAll(ctx._faceletHierarchy);
_faceletHierarchy.add(facelet);
_facelet = facelet;
+ _isRefreshingTransientBuild = ctx._isRefreshingTransientBuild;
+ _isMarkInitialState = ctx._isMarkInitialState;
+ _isBuildingCompositeComponentMetadata = ctx._isBuildingCompositeComponentMetadata;
//Update FACELET_CONTEXT_KEY on FacesContext attribute map, to
//reflect the current facelet context instance
@@ -130,6 +140,12 @@
_varMapper = new DefaultVariableMapper();
}
_fnMapper = _ctx.getFunctionMapper();
+ _isRefreshingTransientBuild = FaceletViewDeclarationLanguage.
+ isRefreshingTransientBuild(faces);
+ _isMarkInitialState = FaceletViewDeclarationLanguage.
+ isMarkInitialState(faces);
+ _isBuildingCompositeComponentMetadata = FaceletViewDeclarationLanguage.
+ isBuildingCompositeComponentMetadata(faces);
//Set FACELET_CONTEXT_KEY on FacesContext attribute map, to
//reflect the current facelet context instance
@@ -798,4 +814,22 @@
enclosingValidatorIdsStack.addFirst(validatorId);
}
+
+ @Override
+ public boolean isRefreshingTransientBuild()
+ {
+ return _isRefreshingTransientBuild;
+ }
+
+ @Override
+ public boolean isMarkInitialState()
+ {
+ return _isMarkInitialState;
+ }
+
+ @Override
+ public boolean isBuildingCompositeComponentMetadata()
+ {
+ return _isBuildingCompositeComponentMetadata;
+ }
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java Fri Jan 29 00:54:49 2010
@@ -24,6 +24,8 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
@@ -146,58 +148,64 @@
super.applyNextHandler(ctx, c);
applyCompositeComponentFacelet(ctx,c);
-
- FacesContext facesContext = ctx.getFacesContext();
-
- ViewDeclarationLanguage vdl = facesContext.getApplication().getViewHandler().
- getViewDeclarationLanguage(facesContext, facesContext.getViewRoot().getViewId());
-
- List<AttachedObjectHandler> handlers = (List<AttachedObjectHandler>)
- c.getAttributes().get(ATTACHED_OBJECT_HANDLERS_KEY);
-
- if (handlers != null)
+
+ if (ComponentHandler.isNew(c))
{
- vdl.retargetAttachedObjects(facesContext, c, handlers);
+ FacesContext facesContext = ctx.getFacesContext();
- // Since handlers list is not serializable and it is not necessary to
- // keep them anymore on attribute map, it is better to remove it from
- // component attribute map
- c.getAttributes().remove(ATTACHED_OBJECT_HANDLERS_KEY);
- }
-
- vdl.retargetMethodExpressions(facesContext, c);
-
- if (ctx.getFacesContext().getAttributes().containsKey(
- FaceletViewDeclarationLanguage.MARK_INITIAL_STATE_KEY))
- {
- // Call it only if we are using partial state saving
- c.markInitialState();
- // Call it to other components created not bound by a tag handler
- c.getFacet(UIComponent.COMPOSITE_FACET_NAME).markInitialState();
+ ViewDeclarationLanguage vdl = facesContext.getApplication().getViewHandler().
+ getViewDeclarationLanguage(facesContext, facesContext.getViewRoot().getViewId());
+
+ List<AttachedObjectHandler> handlers = (List<AttachedObjectHandler>)
+ c.getAttributes().get(ATTACHED_OBJECT_HANDLERS_KEY);
+
+ if (handlers != null)
+ {
+ vdl.retargetAttachedObjects(facesContext, c, handlers);
+
+ // Since handlers list is not serializable and it is not necessary to
+ // keep them anymore on attribute map, it is better to remove it from
+ // component attribute map
+ c.getAttributes().remove(ATTACHED_OBJECT_HANDLERS_KEY);
+ }
+
+ vdl.retargetMethodExpressions(facesContext, c);
+
+ if ( ((AbstractFaceletContext)ctx).isMarkInitialState())
+ {
+ // Call it only if we are using partial state saving
+ c.markInitialState();
+ // Call it to other components created not bound by a tag handler
+ c.getFacet(UIComponent.COMPOSITE_FACET_NAME).markInitialState();
+ }
}
}
protected void applyCompositeComponentFacelet(FaceletContext faceletContext, UIComponent compositeComponentBase)
throws IOException
{
- UIPanel compositeFacetPanel = (UIPanel)
- faceletContext.getFacesContext().getApplication().createComponent(UIPanel.COMPONENT_TYPE);
- compositeComponentBase.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, compositeFacetPanel);
-
- // Set an id to the created facet component, to prevent id generation and make
- // partial state saving work without problem.
AbstractFaceletContext actx = (AbstractFaceletContext) faceletContext;
- UniqueIdVendor uniqueIdVendor = actx.getUniqueIdVendorFromStack();
- if (uniqueIdVendor == null)
+ UIPanel compositeFacetPanel = (UIPanel) compositeComponentBase.getFacets().get(UIComponent.COMPOSITE_FACET_NAME);
+ if (compositeFacetPanel == null)
{
- uniqueIdVendor = ComponentSupport.getViewRoot(faceletContext, compositeComponentBase);
- }
- if (uniqueIdVendor != null)
- {
- // UIViewRoot implements UniqueIdVendor, so there is no need to cast to UIViewRoot
- // and call createUniqueId()
- String uid = uniqueIdVendor.createUniqueId(faceletContext.getFacesContext(),null);
- compositeFacetPanel.setId(uid);
+ compositeFacetPanel = (UIPanel)
+ faceletContext.getFacesContext().getApplication().createComponent(UIPanel.COMPONENT_TYPE);
+ compositeComponentBase.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, compositeFacetPanel);
+
+ // Set an id to the created facet component, to prevent id generation and make
+ // partial state saving work without problem.
+ UniqueIdVendor uniqueIdVendor = actx.getUniqueIdVendorFromStack();
+ if (uniqueIdVendor == null)
+ {
+ uniqueIdVendor = ComponentSupport.getViewRoot(faceletContext, compositeComponentBase);
+ }
+ if (uniqueIdVendor != null)
+ {
+ // UIViewRoot implements UniqueIdVendor, so there is no need to cast to UIViewRoot
+ // and call createUniqueId()
+ String uid = uniqueIdVendor.createUniqueId(faceletContext.getFacesContext(),null);
+ compositeFacetPanel.setId(uid);
+ }
}
// Before call applyCompositeComponent we need to add ajax behaviors
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/ImplementationHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/ImplementationHandler.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/ImplementationHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/ImplementationHandler.java Fri Jan 29 00:54:49 2010
@@ -57,19 +57,19 @@
public void apply(FaceletContext ctx, UIComponent parent)
throws IOException
{
- if (!FaceletViewDeclarationLanguage.
- isBuildingCompositeComponentMetadata(ctx.getFacesContext()))
+ AbstractFaceletContext actx = ((AbstractFaceletContext)ctx);
+ if (!actx.isBuildingCompositeComponentMetadata())
{
// If this tag is found in a facelet, the compiler has trimmed all
// tags outside this one excluding composite:interface, so "parent"
// is a component used as value for the facet key
// UIComponent.COMPOSITE_FACET_NAME in a composite component.
- ((AbstractFaceletContext)ctx).pushCompositeComponentToStack(parent.getParent());
+ actx.pushCompositeComponentToStack(parent.getParent());
nextHandler.apply(ctx, parent);
- ((AbstractFaceletContext)ctx).popCompositeComponentToStack();
+ actx.popCompositeComponentToStack();
}
else
{
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertChildrenHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertChildrenHandler.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertChildrenHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertChildrenHandler.java Fri Jan 29 00:54:49 2010
@@ -21,6 +21,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import javax.faces.component.StateHolder;
import javax.faces.component.UIComponent;
@@ -28,14 +29,15 @@
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.ComponentSystemEventListener;
import javax.faces.event.PostAddToViewEvent;
+import javax.faces.view.facelets.ComponentHandler;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagConfig;
import javax.faces.view.facelets.TagHandler;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
import org.apache.myfaces.view.facelets.AbstractFaceletContext;
-import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
import org.apache.myfaces.view.facelets.PostBuildComponentTreeOnRestoreViewEvent;
+import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
/**
* @author Leonardo Uribe (latest modification by $Author$)
@@ -44,6 +46,9 @@
@JSFFaceletTag(name="composite:insertChildren")
public class InsertChildrenHandler extends TagHandler
{
+ public static String USES_INSERT_CHILDREN = "org.apache.myfaces.USES_INSERT_CHILDREN";
+ public static String INSERT_CHILDREN_TARGET_ID = "org.apache.myfaces.INSERT_CHILDREN_TARGET_ID";
+ public static String INSERT_CHILDREN_ORDERING = "org.apache.myfaces.INSERT_CHILDREN_ORDERING";
public InsertChildrenHandler(TagConfig config)
{
@@ -55,6 +60,23 @@
{
UIComponent parentCompositeComponent = ((AbstractFaceletContext)ctx).getCompositeComponentFromStack();
+ if (!ComponentHandler.isNew(parentCompositeComponent))
+ {
+ //Prevent deletion of components present on parentCompositeComponent. This components will not be changed.
+ List<UIComponent> childList = new ArrayList<UIComponent>(parent.getChildren());
+
+ for (UIComponent tcChild : childList)
+ {
+ if (tcChild.getAttributes().remove(USES_INSERT_CHILDREN) != null)
+ {
+ ComponentSupport.finalizeForDeletion(tcChild);
+ parent.getChildren().remove(tcChild);
+ parent.getChildren().add(tcChild);
+ }
+ }
+ return;
+ }
+
parentCompositeComponent.subscribeToEvent(PostAddToViewEvent.class,
new RelocateAllChildrenListener(parent, parent.getChildCount()));
/*
@@ -69,10 +91,15 @@
public static final class RelocateAllChildrenListener
implements ComponentSystemEventListener, StateHolder
{
- private final UIComponent _targetComponent;
-
- private final int _childIndex;
+ private UIComponent _targetComponent;
+ private String _targetClientId;
+ private int _childIndex;
+
+ public RelocateAllChildrenListener()
+ {
+ }
+
public RelocateAllChildrenListener(UIComponent targetComponent, int childIndex)
{
_targetComponent = targetComponent;
@@ -82,12 +109,71 @@
public void processEvent(ComponentSystemEvent event)
{
UIComponent parentCompositeComponent = event.getComponent();
-
+
+ if (_targetComponent == null)
+ {
+ //All composite components are NamingContainer and the target is inside it, so we can remove the prefix.
+ _targetComponent = parentCompositeComponent.findComponent(_targetClientId.substring(parentCompositeComponent.getClientId().length()+1));
+ }
+
+ if (parentCompositeComponent.getChildCount() <= 0)
+ {
+ return;
+ }
+
List<UIComponent> childList = new ArrayList<UIComponent>(parentCompositeComponent.getChildren());
List<UIComponent> targetChildrenList = _targetComponent.getChildren();
- targetChildrenList.addAll(_childIndex, childList);
+ Map<String, Object> ccAttributes = parentCompositeComponent.getAttributes();
+ if (!ccAttributes.containsKey(INSERT_CHILDREN_TARGET_ID))
+ {
+ //Save the target and the ordering of ids inserted
+ ccAttributes.put(INSERT_CHILDREN_TARGET_ID, _targetComponent.getClientId());
+
+ targetChildrenList.addAll(_childIndex, childList);
+ }
+ else
+ {
+ //Add one to one based on the ordering set at first time
+ List<String> ids = (List<String>) ccAttributes.get(INSERT_CHILDREN_ORDERING);
+ if (ids != null && _childIndex < targetChildrenList.size())
+ {
+ int i = 0;
+ int j = _childIndex;
+ int k = 0;
+ while (i < ids.size() && j < targetChildrenList.size() && k < childList.size())
+ {
+ if (ids.get(i) != null)
+ {
+ if (ids.get(i).equals(childList.get(k).getAttributes().get(ComponentSupport.MARK_CREATED)))
+ {
+ if (!ids.get(i).equals(targetChildrenList.get(j).getAttributes().get(ComponentSupport.MARK_CREATED)))
+ {
+ targetChildrenList.add(j, childList.get(k));
+ k++;
+ }
+ j++;
+ }
+ else if (ids.get(i).equals(targetChildrenList.get(j).getAttributes().get(ComponentSupport.MARK_CREATED)))
+ {
+ j++;
+ }
+ }
+ i++;
+ }
+ while (k < childList.size())
+ {
+ targetChildrenList.add(j, childList.get(k));
+ k++;
+ j++;
+ }
+ }
+ else
+ {
+ targetChildrenList.addAll(_childIndex, childList);
+ }
+ }
// After check, the commented code is not necessary because at this
// point there is no any call to getClientId() yet. But it is better
@@ -109,17 +195,19 @@
public Object saveState(FacesContext context)
{
- return null;
+ return new Object[]{_targetComponent != null ? _targetComponent.getClientId() : _targetClientId , _childIndex};
}
public void restoreState(FacesContext context, Object state)
{
- // no-op as listener is transient
+ Object[] values = (Object[])state;
+ _targetClientId = (String) values[0];
+ _childIndex = (Integer) values[1];
}
public boolean isTransient()
{
- return true;
+ return false;
}
public void setTransient(boolean newTransientValue)
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertFacetHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertFacetHandler.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertFacetHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InsertFacetHandler.java Fri Jan 29 00:54:49 2010
@@ -19,6 +19,9 @@
package org.apache.myfaces.view.facelets.tag.composite;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import javax.faces.component.StateHolder;
import javax.faces.component.UIComponent;
@@ -26,6 +29,7 @@
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.ComponentSystemEventListener;
import javax.faces.event.PostAddToViewEvent;
+import javax.faces.view.facelets.ComponentHandler;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagAttribute;
import javax.faces.view.facelets.TagConfig;
@@ -35,8 +39,7 @@
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
import org.apache.myfaces.view.facelets.AbstractFaceletContext;
-import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
-import org.apache.myfaces.view.facelets.PostBuildComponentTreeOnRestoreViewEvent;
+import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
/**
* Insert or move the facet from the composite component body to the expected location.
@@ -47,6 +50,10 @@
@JSFFaceletTag(name="composite:insertFacet")
public class InsertFacetHandler extends TagHandler
{
+ public static String USES_INSERT_FACET = "org.apache.myfaces.USES_INSERT_FACET";
+ public static String INSERT_FACET_TARGET_ID = "org.apache.myfaces.INSERT_FACET_TARGET_ID.";
+ public static String INSERT_FACET_ORDERING = "org.apache.myfaces.INSERT_FACET_ORDERING.";
+
/**
* The name that identify the current facet.
*/
@@ -85,6 +92,27 @@
+parentCompositeComponent.getClientId(ctx.getFacesContext()));
}
+ if (!ComponentHandler.isNew(parentCompositeComponent))
+ {
+ UIComponent facet = parent.getFacet(facetName);
+ if (facet != null)
+ {
+ if (facet.getAttributes().containsKey(ComponentSupport.FACET_CREATED_UIPANEL_MARKER))
+ {
+ ComponentSupport.markForDeletion(facet);
+ for (UIComponent child : facet.getChildren())
+ {
+ if (child.getAttributes().remove(USES_INSERT_FACET) != null)
+ {
+ ComponentSupport.finalizeForDeletion(child);
+ }
+ }
+ }
+ ComponentSupport.finalizeForDeletion(facet);
+ }
+ return;
+ }
+
parentCompositeComponent.subscribeToEvent(PostAddToViewEvent.class,
new RelocateFacetListener(parent, facetName));
/*
@@ -99,10 +127,14 @@
public static final class RelocateFacetListener
implements ComponentSystemEventListener, StateHolder
{
- private final UIComponent _targetComponent;
-
- private final String _facetName;
+ private UIComponent _targetComponent;
+ private String _targetClientId;
+ private String _facetName;
+ public RelocateFacetListener()
+ {
+ }
+
public RelocateFacetListener(UIComponent targetComponent, String facetName)
{
_targetComponent = targetComponent;
@@ -115,25 +147,90 @@
UIComponent facetComponent = parentCompositeComponent.getFacet(_facetName);
+ if (_targetComponent == null)
+ {
+ //All composite components are NamingContainer and the target is inside it, so we can remove the prefix.
+ _targetComponent = parentCompositeComponent.findComponent(_targetClientId.substring(parentCompositeComponent.getClientId().length()+1));
+ }
+
if (facetComponent != null)
{
- _targetComponent.getFacets().put(_facetName, facetComponent);
+ Map<String, Object> ccAttributes = parentCompositeComponent.getAttributes();
+ UIComponent oldFacet = _targetComponent.getFacets().get(_facetName);
+ String insertFacetKey = INSERT_FACET_TARGET_ID+_facetName;
+
+ if (!ccAttributes.containsKey(insertFacetKey))
+ {
+ ccAttributes.put(insertFacetKey, _targetComponent.getClientId());
+ }
+
+ if (oldFacet != null && Boolean.TRUE.equals(oldFacet.getAttributes().get(ComponentSupport.FACET_CREATED_UIPANEL_MARKER)))
+ {
+ List<UIComponent> childList = new ArrayList<UIComponent>(facetComponent.getChildren());
+
+ List<UIComponent> targetChildrenList = oldFacet.getChildren();
+
+ List<String> ids = (List<String>) ccAttributes.get(INSERT_FACET_ORDERING+_facetName);
+ if (ids != null && targetChildrenList.size() > 0)
+ {
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ while (i < ids.size() && j < targetChildrenList.size() && k < childList.size())
+ {
+ if (ids.get(i) != null)
+ {
+ if (ids.get(i).equals(childList.get(k).getAttributes().get(ComponentSupport.MARK_CREATED)))
+ {
+ if (!ids.get(i).equals(targetChildrenList.get(j).getAttributes().get(ComponentSupport.MARK_CREATED)))
+ {
+ targetChildrenList.add(j, childList.get(k));
+ k++;
+ }
+ j++;
+ }
+ else if (ids.get(i).equals(targetChildrenList.get(j).getAttributes().get(ComponentSupport.MARK_CREATED)))
+ {
+ j++;
+ }
+ }
+ i++;
+ }
+ while (k < childList.size())
+ {
+ targetChildrenList.add(j, childList.get(k));
+ k++;
+ j++;
+ }
+ }
+ else
+ {
+ _targetComponent.getFacets().put(_facetName, facetComponent);
+ }
+ }
+ else
+ {
+ _targetComponent.getFacets().put(_facetName, facetComponent);
+ }
+
}
}
public Object saveState(FacesContext context)
{
- return null;
+ return new Object[]{_targetComponent != null ? _targetComponent.getClientId() : _targetClientId , _facetName};
}
public void restoreState(FacesContext context, Object state)
{
- // no-op as listener is transient
+ Object[] values = (Object[])state;
+ _targetClientId = (String) values[0];
+ _facetName = (String) values[1];
}
public boolean isTransient()
{
- return true;
+ return false;
}
public void setTransient(boolean newTransientValue)
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InterfaceHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InterfaceHandler.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InterfaceHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/InterfaceHandler.java Fri Jan 29 00:54:49 2010
@@ -32,6 +32,7 @@
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
+import org.apache.myfaces.view.facelets.AbstractFaceletContext;
import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
import org.apache.myfaces.view.facelets.tag.TagHandlerUtils;
@@ -157,8 +158,7 @@
{
// Only apply if we are building composite component metadata,
// in other words we are calling ViewDeclarationLanguage.getComponentMetadata
- if (FaceletViewDeclarationLanguage.
- isBuildingCompositeComponentMetadata(ctx.getFacesContext()))
+ if ( ((AbstractFaceletContext)ctx).isBuildingCompositeComponentMetadata())
{
UIComponent compositeBaseParent = _getCompositeBaseParent(parent);
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java?rev=904329&r1=904328&r2=904329&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java Fri Jan 29 00:54:49 2010
@@ -20,6 +20,7 @@
import java.io.IOException;
import java.util.HashMap;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -52,6 +53,8 @@
import org.apache.myfaces.view.facelets.AbstractFaceletContext;
import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
import org.apache.myfaces.view.facelets.tag.MetaRulesetImpl;
+import org.apache.myfaces.view.facelets.tag.composite.InsertChildrenHandler;
+import org.apache.myfaces.view.facelets.tag.composite.InsertFacetHandler;
import org.apache.myfaces.view.facelets.tag.jsf.core.AjaxHandler;
import org.apache.myfaces.view.facelets.tag.jsf.core.FacetHandler;
@@ -111,6 +114,7 @@
* @throws TagException
* if the UIComponent parent is null
*/
+ @SuppressWarnings("unchecked")
@Override
public void apply(FaceletContext ctx, UIComponent parent) throws IOException
{
@@ -133,6 +137,48 @@
// grab our component
UIComponent c = ComponentSupport.findChildByTagId(parent, id);
+
+ // Check if the component was relocated using
+ // composite:insertChildren or composite:insertFacet
+ boolean componentFoundInserted = false;
+
+ if (c == null && UIComponent.isCompositeComponent(parent))
+ {
+ if (facetName == null)
+ {
+ String targetClientId = (String) parent.getAttributes().get(InsertChildrenHandler.INSERT_CHILDREN_TARGET_ID);
+ if (targetClientId != null)
+ {
+ UIComponent targetComponent = parent.findComponent(targetClientId.substring(parent.getClientId().length()+1));
+ if (targetComponent != null)
+ {
+ c = ComponentSupport.findChildByTagId(targetComponent, id);
+ }
+ }
+ if (c != null)
+ {
+ c.getAttributes().put(InsertChildrenHandler.USES_INSERT_CHILDREN, Boolean.TRUE);
+ componentFoundInserted = true;
+ }
+ }
+ else
+ {
+ String targetClientId = (String) parent.getAttributes().get(InsertFacetHandler.INSERT_FACET_TARGET_ID+facetName);
+ if (targetClientId != null)
+ {
+ UIComponent targetComponent = parent.findComponent(targetClientId.substring(parent.getClientId().length()+1));
+ if (targetComponent != null)
+ {
+ c = ComponentSupport.findChildByTagId(targetComponent, id);
+ if (c != null)
+ {
+ c.getAttributes().put(InsertFacetHandler.USES_INSERT_FACET, Boolean.TRUE);
+ componentFoundInserted = true;
+ }
+ }
+ }
+ }
+ }
boolean componentFound = false;
if (c != null)
{
@@ -206,13 +252,54 @@
{
ComponentSupport.finalizeForDeletion(c);
- if (facetName == null)
+ if (!componentFoundInserted)
{
- parent.getChildren().remove(c);
+ if (facetName == null)
+ {
+ parent.getChildren().remove(c);
+ }
+ else
+ {
+ ComponentSupport.removeFacet(ctx, parent, c, facetName);
+ }
+ }
+ }
+
+ if (actx.isRefreshingTransientBuild() &&
+ UIComponent.isCompositeComponent(parent))
+ {
+ // Save the child structure behind this component, so it can be
+ // used later by InsertChildrenHandler and InsertFacetHandler
+ // to update components correctly.
+ if (facetName != null)
+ {
+ if (parent.getAttributes().containsKey(InsertFacetHandler.INSERT_FACET_TARGET_ID+facetName))
+ {
+ List<String> ordering = (List<String>) parent.getAttributes().get(
+ InsertFacetHandler.INSERT_FACET_ORDERING+facetName);
+ if (ordering == null)
+ {
+ ordering = new ArrayList<String>();
+ parent.getAttributes().put(InsertFacetHandler.INSERT_FACET_ORDERING+facetName, ordering);
+ }
+ ordering.remove(id);
+ ordering.add(id);
+ }
}
else
{
- ComponentSupport.removeFacet(ctx, parent, c, facetName);
+ if (parent.getAttributes().containsKey(InsertChildrenHandler.INSERT_CHILDREN_TARGET_ID))
+ {
+ List<String> ordering = (List<String>) parent.getAttributes().get(
+ InsertChildrenHandler.INSERT_CHILDREN_ORDERING);
+ if (ordering == null)
+ {
+ ordering = new ArrayList<String>();
+ parent.getAttributes().put(InsertChildrenHandler.INSERT_CHILDREN_ORDERING, ordering);
+ }
+ ordering.remove(id);
+ ordering.add(id);
+ }
}
}
@@ -237,17 +324,35 @@
_delegate.onComponentPopulated(ctx, c, parent);
- // add to the tree afterwards
- // this allows children to determine if it's
- // been part of the tree or not yet
- if (facetName == null)
+ if (!componentFoundInserted)
{
- parent.getChildren().add(c);
+ // add to the tree afterwards
+ // this allows children to determine if it's
+ // been part of the tree or not yet
+ if (facetName == null)
+ {
+ parent.getChildren().add(c);
+ }
+ else
+ {
+ ComponentSupport.addFacet(ctx, parent, c, facetName);
+ }
}
+ /*
else
{
- ComponentSupport.addFacet(ctx, parent, c, facetName);
- }
+ if (facetName != null)
+ {
+ if (UIComponent.isCompositeComponent(parent))
+ {
+ UIComponent facet = parent.getFacet(facetName);
+ if (Boolean.TRUE.equals(facet.getAttributes().get(ComponentSupport.FACET_CREATED_UIPANEL_MARKER)))
+ {
+ facet.getAttributes().put(InsertFacetHandler.USES_INSERT_FACET, Boolean.TRUE);
+ }
+ }
+ }
+ }*/
if (c instanceof UniqueIdVendor)
{
@@ -256,8 +361,7 @@
c.popComponentFromEL(facesContext);
- if (facesContext.getAttributes().containsKey(
- FaceletViewDeclarationLanguage.MARK_INITIAL_STATE_KEY))
+ if (actx.isMarkInitialState())
{
//Call it only if we are using partial state saving
c.markInitialState();