Coverage Report - org.apache.myfaces.view.facelets.compiler.RefreshDynamicComponentListener
 
Classes in this File Line Coverage Branch Coverage Complexity
RefreshDynamicComponentListener
0%
0/68
0%
0/24
3
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.myfaces.view.facelets.compiler;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.util.Map;
 23  
 import javax.faces.FacesException;
 24  
 import javax.faces.component.StateHolder;
 25  
 import javax.faces.component.UIComponent;
 26  
 import javax.faces.context.FacesContext;
 27  
 import javax.faces.event.ComponentSystemEvent;
 28  
 import javax.faces.event.ComponentSystemEventListener;
 29  
 import javax.faces.view.facelets.Facelet;
 30  
 import org.apache.myfaces.config.RuntimeConfig;
 31  
 import org.apache.myfaces.view.facelets.AbstractFacelet;
 32  
 import org.apache.myfaces.view.facelets.FaceletFactory;
 33  
 import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
 34  
 import org.apache.myfaces.view.facelets.tag.composite.CompositeResourceLibrary;
 35  
 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
 36  
 
 37  
 /**
 38  
  * This listener must be attached to PostRestoreStateEvent so when the view is restored, 
 39  
  * the algorithm refresh the component that was created using facelets, restoring the
 40  
  * transient markup.
 41  
  *
 42  
  * @author lu4242
 43  
  */
 44  
 public final class RefreshDynamicComponentListener implements 
 45  
     ComponentSystemEventListener, StateHolder
 46  
 {
 47  
     private String taglibURI;
 48  
     private String tagName;
 49  
     private Map<String,Object> attributes;
 50  
     private String baseKey;
 51  
 
 52  
     public RefreshDynamicComponentListener(String taglibURI, String tagName, 
 53  
         Map<String, Object> attributes, String baseKey)
 54  0
     {
 55  0
         this.taglibURI = taglibURI;
 56  0
         this.tagName = tagName;
 57  0
         this.attributes = attributes;
 58  0
         this.baseKey = baseKey;
 59  0
     }
 60  
 
 61  
     public RefreshDynamicComponentListener()
 62  0
     {
 63  0
     }
 64  
     
 65  
     public void processEvent(ComponentSystemEvent event)
 66  
     {
 67  0
         FacesContext facesContext = FacesContext.getCurrentInstance();
 68  
         //if (!PhaseId.RESTORE_VIEW.equals(facesContext.getCurrentPhaseId()))
 69  
         //{
 70  
             // This listener is only active when PostAddToViewEvent occur
 71  
             // on restore view phase. 
 72  
             //return;
 73  
         //}
 74  
         
 75  0
         FaceletViewDeclarationLanguage vdl = (FaceletViewDeclarationLanguage) 
 76  
             facesContext.getApplication().getViewHandler().getViewDeclarationLanguage(
 77  
                 facesContext, facesContext.getViewRoot().getViewId());
 78  
         
 79  
         Facelet componentFacelet;
 80  0
         FaceletFactory faceletFactory = vdl.getFaceletFactory();
 81  
             
 82  0
         FaceletFactory.setInstance(faceletFactory);
 83  
         try
 84  
         {
 85  0
             componentFacelet
 86  
                     = faceletFactory.compileComponentFacelet(taglibURI, tagName, attributes);
 87  
         }
 88  
         finally
 89  
         {
 90  0
             FaceletFactory.setInstance(null);
 91  0
         }
 92  
         try
 93  
         {
 94  0
             UIComponent component = event.getComponent();
 95  
             
 96  0
             facesContext.getAttributes().put(FaceletViewDeclarationLanguage.REFRESHING_TRANSIENT_BUILD,
 97  
                 Boolean.TRUE);
 98  
             
 99  
             
 100  
             // Detect the relationship between parent and child, to ensure the component is properly created
 101  
             // and refreshed. In facelets this is usually done by core.FacetHandler, but since it is a 
 102  
             // dynamic component, we need to do it here before apply the handler
 103  0
             UIComponent parent = component.getParent();
 104  0
             String facetName = null;
 105  0
             if (parent.getFacetCount() > 0 && !parent.getChildren().contains(component))
 106  
             {
 107  0
                 facetName = ComponentSupport.findFacetNameByComponentInstance(parent, component);
 108  
             }
 109  
 
 110  
             try
 111  
             {
 112  0
                 if (facetName != null)
 113  
                 {
 114  0
                     parent.getAttributes().put(org.apache.myfaces.view.facelets.tag.jsf.core.FacetHandler.KEY, 
 115  
                             facetName);
 116  
                 }            
 117  
                 // The trick here is restore MARK_CREATED, just to allow ComponentTagHandlerDelegate to
 118  
                 // find the component. Then we reset it to exclude it from facelets refresh algorithm.
 119  
                 // Note oam.vf.GEN_MARK_ID helps to identify when there is a wrapper component or not,
 120  
                 // and in that way identify which component is the parent.
 121  0
                 String markId = (String) component.getAttributes().get("oam.vf.GEN_MARK_ID");
 122  0
                 if (markId == null)
 123  
                 {
 124  0
                     ((AbstractFacelet)componentFacelet).applyDynamicComponentHandler(
 125  
                         facesContext, component, baseKey);
 126  
                 }
 127  
                 else
 128  
                 {
 129  
                     try
 130  
                     {
 131  0
                         component.getAttributes().put(ComponentSupport.MARK_CREATED, markId);
 132  0
                         ((AbstractFacelet)componentFacelet).applyDynamicComponentHandler(
 133  
                             facesContext, component.getParent(), baseKey);
 134  
                     }
 135  
                     finally
 136  
                     {
 137  0
                         component.getAttributes().put(ComponentSupport.MARK_CREATED, null);
 138  0
                     }
 139  
                 }
 140  
             }
 141  
             finally
 142  
             {
 143  0
                 if (facetName != null)
 144  
                 {
 145  0
                     parent.getAttributes().remove(org.apache.myfaces.view.facelets.tag.jsf.core.FacetHandler.KEY);
 146  
                 }
 147  
             }
 148  
         }
 149  0
         catch (IOException e)
 150  
         {
 151  0
             throw new FacesException(e);
 152  
         }
 153  
         finally
 154  
         {
 155  0
             facesContext.getAttributes().remove(
 156  
                 FaceletViewDeclarationLanguage.REFRESHING_TRANSIENT_BUILD);
 157  0
         }
 158  0
     }
 159  
 
 160  
     public Object saveState(FacesContext context)
 161  
     {
 162  0
         RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(
 163  
             context.getExternalContext());
 164  0
         Object[] values = new Object[4];
 165  0
         Integer tagId = runtimeConfig.getIdByNamespace().get(taglibURI);
 166  0
         if (tagId != null)
 167  
         {
 168  0
             values[0] = tagId;
 169  
         }
 170  0
         else if (taglibURI.startsWith(CompositeResourceLibrary.NAMESPACE_PREFIX))
 171  
         {
 172  0
             values[0] = new Object[]{0, taglibURI.substring(35)};
 173  
         }
 174  0
         else if(taglibURI.startsWith(CompositeResourceLibrary.ALIAS_NAMESPACE_PREFIX))
 175  
         {
 176  0
             values[0] = new Object[]{1, taglibURI.substring(34)};
 177  
         }
 178  
         else
 179  
         {
 180  0
             values[0] = taglibURI;
 181  
         }
 182  0
         values[1] = tagName;
 183  0
         values[2] = attributes;
 184  0
         values[3] = baseKey;
 185  0
         return values;
 186  
     }
 187  
 
 188  
     public void restoreState(FacesContext context, Object state)
 189  
     {
 190  0
         Object[] values = (Object[]) state;
 191  0
         if (values[0] instanceof String)
 192  
         {
 193  0
             taglibURI = (String) values[0];
 194  
         }
 195  0
         else if (values[0] instanceof Integer)
 196  
         {
 197  0
             RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(
 198  
                 context.getExternalContext());
 199  0
             taglibURI = runtimeConfig.getNamespaceById().get((Integer)values[0]);
 200  0
         }
 201  0
         else if (values[0] instanceof Object[])
 202  
         {
 203  0
             Object[] def = (Object[])values[0];
 204  0
             String ns = ( ((Integer)def[0]).intValue() == 0) ? 
 205  
                 CompositeResourceLibrary.NAMESPACE_PREFIX :
 206  
                 CompositeResourceLibrary.ALIAS_NAMESPACE_PREFIX;
 207  0
             taglibURI = ns + (String)(((Object[])values[0])[1]);
 208  
         }
 209  0
         tagName = (String)values[1];
 210  0
         attributes = (Map<String,Object>) values[2];
 211  0
         baseKey = (String)values[3];
 212  0
     }
 213  
 
 214  
     public boolean isTransient()
 215  
     {
 216  0
         return false;
 217  
     }
 218  
 
 219  
     public void setTransient(boolean newTransientValue)
 220  
     {
 221  0
     }
 222  
 
 223  
 }