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();