Coverage Report - javax.faces.component.UIComponentBase
 
Classes in this File Line Coverage Branch Coverage Complexity
UIComponentBase
0%
0/652
0%
0/420
0
 
 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 javax.faces.component;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.io.Serializable;
 23  
 import java.lang.reflect.Array;
 24  
 import java.util.ArrayList;
 25  
 import java.util.Collection;
 26  
 import java.util.Collections;
 27  
 import java.util.HashMap;
 28  
 import java.util.Iterator;
 29  
 import java.util.List;
 30  
 import java.util.Map;
 31  
 import java.util.logging.Level;
 32  
 import java.util.logging.Logger;
 33  
 
 34  
 import javax.el.ValueExpression;
 35  
 import javax.faces.FacesException;
 36  
 import javax.faces.component.behavior.Behavior;
 37  
 import javax.faces.component.behavior.ClientBehavior;
 38  
 import javax.faces.component.visit.VisitCallback;
 39  
 import javax.faces.component.visit.VisitContext;
 40  
 import javax.faces.context.FacesContext;
 41  
 import javax.faces.el.ValueBinding;
 42  
 import javax.faces.event.AbortProcessingException;
 43  
 import javax.faces.event.BehaviorEvent;
 44  
 import javax.faces.event.FacesEvent;
 45  
 import javax.faces.event.FacesListener;
 46  
 import javax.faces.event.PostAddToViewEvent;
 47  
 import javax.faces.event.PreRemoveFromViewEvent;
 48  
 import javax.faces.event.PreRenderComponentEvent;
 49  
 import javax.faces.event.SystemEvent;
 50  
 import javax.faces.event.SystemEventListener;
 51  
 import javax.faces.render.RenderKit;
 52  
 import javax.faces.render.Renderer;
 53  
 import javax.faces.view.Location;
 54  
 
 55  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
 56  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
 57  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
 58  
 
 59  
 
 60  
 /**
 61  
  * TODO: IMPLEMENT HERE - Delta state saving support
 62  
  * 
 63  
  * Standard implementation of the UIComponent base class; all standard JSF components extend this class.
 64  
  * <p>
 65  
  * <i>Disclaimer</i>: The official definition for the behaviour of this class is the JSF 1.1 specification but for legal
 66  
  * reasons the specification cannot be replicated here. Any javadoc here therefore describes the current implementation
 67  
  * rather than the spec, though this class has been verified as correctly implementing the spec.
 68  
  * 
 69  
  * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a> for
 70  
  * more.
 71  
  * 
 72  
  * @author Manfred Geiler (latest modification by $Author: lu4242 $)
 73  
  * @version $Revision: 953875 $ $Date: 2010-06-11 16:16:37 -0500 (Fri, 11 Jun 2010) $
 74  
  */
 75  
 @JSFComponent(type = "javax.faces.ComponentBase", family = "javax.faces.ComponentBase", desc = "base component when all components must inherit", tagClass = "javax.faces.webapp.UIComponentELTag", configExcluded = true)
 76  
 @JSFJspProperty(name = "binding", returnType = "javax.faces.component.UIComponent", longDesc = "Identifies a backing bean property (of type UIComponent or appropriate subclass) to bind to this component instance. This value must be an EL expression.", desc = "backing bean property to bind to this component instance")
 77  
 public abstract class UIComponentBase extends UIComponent
 78  
 {
 79  
     //private static Log log = LogFactory.getLog(UIComponentBase.class);
 80  0
     private static Logger log = Logger.getLogger(UIComponentBase.class.getName());
 81  
 
 82  0
     private static final ThreadLocal<StringBuilder> _STRING_BUILDER = new ThreadLocal<StringBuilder>();
 83  
 
 84  0
     private static final Iterator<UIComponent> _EMPTY_UICOMPONENT_ITERATOR = new _EmptyIterator<UIComponent>();
 85  
 
 86  0
     private _ComponentAttributesMap _attributesMap = null;
 87  0
     private List<UIComponent> _childrenList = null;
 88  0
     private Map<String, UIComponent> _facetMap = null;
 89  0
     private _DeltaList<FacesListener> _facesListeners = null;
 90  0
     private String _clientId = null;
 91  0
     private String _id = null;
 92  0
     private UIComponent _parent = null;
 93  0
     private boolean _transient = false;
 94  
 
 95  
     /**
 96  
      * This map holds ClientBehavior instances.
 97  
      * 
 98  
      *  Note that BehaviorBase implements PartialStateHolder, so this class 
 99  
      *  should deal with that fact on clearInitialState() and 
 100  
      *  markInitialState() methods.
 101  
      * 
 102  
      *  Also, the map used by this instance is not set from outside this class.
 103  
      *  
 104  
      *  Note it is possible (but maybe not expected/valid) to manipulate 
 105  
      *  the values of the map(the list) but not put instances on the map 
 106  
      *  directly, because ClientBehaviorHolder.getClientBehaviors says that 
 107  
      *  this method should return a non null unmodificable map.
 108  
      *  
 109  
      */
 110  0
     private Map<String, List<ClientBehavior>> _behaviorsMap = null;
 111  0
     private transient Map<String, List<ClientBehavior>> _unmodifiableBehaviorsMap = null;
 112  
     
 113  
     private transient FacesContext _facesContext;
 114  
     
 115  
     public UIComponentBase()
 116  0
     {
 117  0
     }
 118  
 
 119  
     /**
 120  
      * Put the provided value-binding into a map of value-bindings associated with this component.
 121  
      * 
 122  
      * @deprecated Replaced by setValueExpression
 123  
      */
 124  
     @Override
 125  
     public void setValueBinding(String name, ValueBinding binding)
 126  
     {
 127  0
         setValueExpression(name, binding == null ? null : new _ValueBindingToValueExpression(binding));
 128  0
     }
 129  
 
 130  
     /**
 131  
      * Set an identifier for this component which is unique within the scope of the nearest ancestor NamingContainer
 132  
      * component. The id is not necessarily unique across all components in the current view.
 133  
      * <p>
 134  
      * The id must start with an underscore if it is generated by the JSF framework, and must <i>not</i> start with an
 135  
      * underscore if it has been specified by the user (eg in a JSP tag).
 136  
      * <p>
 137  
      * The first character of the id must be an underscore or letter. Following characters may be letters, digits,
 138  
      * underscores or dashes.
 139  
      * <p>
 140  
      * Null is allowed as a parameter, and will reset the id to null.
 141  
      * <p>
 142  
      * The clientId of this component is reset by this method; see getClientId for more info.
 143  
      * 
 144  
      * @throws IllegalArgumentException
 145  
      *             if the id is not valid.
 146  
      */
 147  
     @Override
 148  
     public void setId(String id)
 149  
     {
 150  0
         isIdValid(id);
 151  0
         _id = id;
 152  0
         _clientId = null;
 153  0
     }
 154  
 
 155  
     /**
 156  
      * <p>Set the parent <code>UIComponent</code> of this
 157  
      * <code>UIComponent</code>.</p>
 158  
      * 
 159  
      * @param parent The new parent, or <code>null</code> for the root node
 160  
      *  of a component tree
 161  
      */
 162  
     @Override
 163  
     public void setParent(UIComponent parent)
 164  
     {
 165  
         // removing kids OR this is UIViewRoot
 166  0
         if (parent == null)
 167  
         {
 168  
             // not UIViewRoot...
 169  0
             if (_parent != null && _parent.isInView())
 170  
             {
 171  
                 // trigger the "remove event" lifecycle
 172  
                 // and call setInView(false) for all children/facets
 173  
                 // doing this => recursive
 174  0
                 _publishPreRemoveFromViewEvent(getFacesContext(), this);
 175  
             }
 176  0
             _parent = parent;
 177  
         } else {
 178  0
             _parent = parent;
 179  0
             if (parent.isInView())
 180  
             {
 181  
                 // trigger the ADD_EVENT and call setInView(true)
 182  
                 // recursive for all kids/facets...
 183  
                 // Application.publishEvent(java.lang.Class, java.lang.Object)  must be called, passing 
 184  
                 // PostAddToViewEvent.class as the first argument and the newly added component as the second 
 185  
                 // argument.
 186  0
                 _publishPostAddToViewEvent(getFacesContext(), this);
 187  
             }
 188  
         }
 189  0
     }
 190  
 
 191  
     
 192  
     /**
 193  
      * Publish PostAddToViewEvent to the component and all facets and children.
 194  
      * 
 195  
      * @param context
 196  
      * @param component
 197  
      */
 198  
     private static void _publishPostAddToViewEvent(FacesContext context, UIComponent component)
 199  
     {
 200  0
         component.setInView(true);
 201  0
         context.getApplication().publishEvent(context, PostAddToViewEvent.class, UIComponent.class, component);
 202  
         
 203  0
         if (component.getChildCount() > 0)
 204  
         {
 205  
             // PostAddToViewEvent could cause component relocation
 206  
             // (h:outputScript, h:outputStylesheet, composite:insertChildren, composite:insertFacet)
 207  
             // so we need to check if the component was relocated or not
 208  
           
 209  
             // is this all really needed ?
 210  0
             List<UIComponent> children = component.getChildren();
 211  0
             UIComponent child = null;
 212  0
             UIComponent currentChild = null;
 213  0
             int i = 0;
 214  0
             while (i < children.size())
 215  
             {
 216  0
                 child = children.get(i);
 217  
                 // Iterate over the same index if the component was removed
 218  
                 // This prevents skip components when processing
 219  
                 do 
 220  
                 {
 221  0
                     _publishPostAddToViewEvent(context, child);
 222  0
                     currentChild = child;
 223  
                 }
 224  0
                 while ((i < children.size()) &&
 225  
                        ((child = children.get(i)) != currentChild) );
 226  0
                 i++;
 227  
             }
 228  
         }
 229  0
         if (component.getFacetCount() > 0)
 230  
         {
 231  0
             for (UIComponent child : component.getFacets().values())
 232  
             {
 233  0
                 _publishPostAddToViewEvent(context, child);
 234  
             }
 235  
         }        
 236  0
     }
 237  
     
 238  
     /**
 239  
      * Publish PreRemoveFromViewEvent to the component and all facets and children.
 240  
      * 
 241  
      * @param context
 242  
      * @param component
 243  
      */
 244  
     private static void _publishPreRemoveFromViewEvent(FacesContext context, UIComponent component)
 245  
     {
 246  0
         component.setInView(false);
 247  0
         context.getApplication().publishEvent(context, PreRemoveFromViewEvent.class, UIComponent.class, component);
 248  
         
 249  0
         if (component.getChildCount() > 0)
 250  
         {
 251  0
             for (UIComponent child : component.getChildren())
 252  
             {
 253  0
                 _publishPreRemoveFromViewEvent(context, child);
 254  
             }
 255  
         }
 256  0
         if (component.getFacetCount() > 0)
 257  
         {
 258  0
             for (UIComponent child : component.getFacets().values())
 259  
             {
 260  0
                 _publishPreRemoveFromViewEvent(context, child);
 261  
             }
 262  
         }        
 263  0
     }    
 264  
     
 265  
     /**
 266  
      * 
 267  
      * @param eventName
 268  
      * @param behavior
 269  
      * 
 270  
      * @since 2.0
 271  
      */
 272  
     public void addClientBehavior(String eventName, ClientBehavior behavior)
 273  
     {
 274  0
         Collection<String> eventNames = getEventNames();
 275  
         
 276  0
         if(eventNames == null)
 277  
         {
 278  
             //component didn't implement getEventNames properly
 279  
             //log an error and return
 280  0
             if(log.isLoggable(Level.SEVERE))
 281  
             {
 282  0
                 log.severe("attempted to add a behavior to a component which did not properly implement getEventNames.  getEventNames must not return null");
 283  0
                 return;
 284  
             }
 285  
         }
 286  
         
 287  0
         if(eventNames.contains(eventName))
 288  
         {
 289  0
             if(_behaviorsMap == null)
 290  
             {
 291  0
                 _behaviorsMap = new HashMap<String,List<ClientBehavior>>();
 292  
             }
 293  
             
 294  0
             List<ClientBehavior> behaviorsForEvent = _behaviorsMap.get(eventName);
 295  0
             if(behaviorsForEvent == null)
 296  
             {
 297  0
                 behaviorsForEvent = new _DeltaList<ClientBehavior>(new ArrayList<ClientBehavior>());
 298  0
                 _behaviorsMap.put(eventName, behaviorsForEvent);
 299  
             }
 300  
             
 301  0
             behaviorsForEvent.add(behavior);
 302  0
             _unmodifiableBehaviorsMap = null;
 303  
         }
 304  0
     }
 305  
 
 306  
     /**
 307  
      * Invoke any listeners attached to this object which are listening for an event whose type matches the specified
 308  
      * event's runtime type.
 309  
      * <p>
 310  
      * This method does not propagate the event up to parent components, ie listeners attached to parent components
 311  
      * don't automatically get called.
 312  
      * <p>
 313  
      * If any of the listeners throws AbortProcessingException then that exception will prevent any further listener
 314  
      * callbacks from occurring, and the exception propagates out of this method without alteration.
 315  
      * <p>
 316  
      * ActionEvent events are typically queued by the renderer associated with this component in its decode method;
 317  
      * ValueChangeEvent events by the component's validate method. In either case the event's source property references
 318  
      * a component. At some later time the UIViewRoot component iterates over its queued events and invokes the
 319  
      * broadcast method on each event's source object.
 320  
      * 
 321  
      * @param event
 322  
      *            must not be null.
 323  
      */
 324  
     @Override
 325  
     public void broadcast(FacesEvent event) throws AbortProcessingException
 326  
     {
 327  0
         if (event == null)
 328  0
             throw new NullPointerException("event");
 329  
         try
 330  
         {
 331  0
             if (event instanceof BehaviorEvent && event.getComponent() == this)
 332  
             {
 333  0
                 Behavior behavior = ((BehaviorEvent) event).getBehavior();
 334  0
                 behavior.broadcast((BehaviorEvent) event);
 335  
             }
 336  
             
 337  0
             if (_facesListeners == null)
 338  0
                 return;
 339  0
             for (Iterator<FacesListener> it = _facesListeners.iterator(); it.hasNext();)
 340  
             {
 341  0
                 FacesListener facesListener = it.next();
 342  0
                 if (event.isAppropriateListener(facesListener))
 343  
                 {
 344  0
                     event.processListener(facesListener);
 345  
                 }
 346  0
             }
 347  
         }
 348  0
         catch (Exception ex)
 349  
         {
 350  0
             if (ex instanceof AbortProcessingException)
 351  
             {
 352  0
                 throw (AbortProcessingException) ex;
 353  
             }
 354  0
             String location = getComponentLocation(this);
 355  0
             throw new FacesException("Exception while calling broadcast on component : " 
 356  
                     + getPathToComponent(this) 
 357  
                     + (location != null ? " created from: " + location : ""), ex);
 358  0
         }
 359  0
     }
 360  
     
 361  
     public void clearInitialState()
 362  
     {
 363  0
         super.clearInitialState();
 364  0
         if (_facesListeners != null)
 365  
         {
 366  0
             _facesListeners.clearInitialState();
 367  
         }
 368  0
         if (_behaviorsMap != null)
 369  
         {
 370  0
             for (Map.Entry<String, List<ClientBehavior> > entry : _behaviorsMap.entrySet())
 371  
             {
 372  0
                 ((PartialStateHolder) entry.getValue()).clearInitialState();
 373  
             }
 374  
         }
 375  0
         if (_systemEventListenerClassMap != null)
 376  
         {
 377  
             for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener>> entry : 
 378  0
                 _systemEventListenerClassMap.entrySet())
 379  
             {
 380  0
                 ((PartialStateHolder) entry.getValue()).clearInitialState();
 381  
             }
 382  
         }
 383  0
     }
 384  
 
 385  
     /**
 386  
      * Check the submitted form parameters for data associated with this component. This default implementation
 387  
      * delegates to this component's renderer if there is one, and otherwise ignores the call.
 388  
      */
 389  
     @Override
 390  
     public void decode(FacesContext context)
 391  
     {
 392  0
         if (context == null)
 393  0
             throw new NullPointerException("context");
 394  
         try
 395  
         {
 396  0
             Renderer renderer = getRenderer(context);
 397  0
             if (renderer != null)
 398  
             {
 399  0
                 renderer.decode(context, this);
 400  
             }
 401  
         }
 402  0
         catch (Exception ex)
 403  
         {
 404  0
             String location = getComponentLocation(this);
 405  0
             throw new FacesException("Exception while decoding component : " 
 406  
                     + getPathToComponent(this) 
 407  
                     + (location != null ? " created from: " + location : ""), ex);
 408  0
         }
 409  0
     }
 410  
 
 411  
     @Override
 412  
     public void encodeBegin(FacesContext context) throws IOException
 413  
     {
 414  0
         if (context == null)
 415  
         {
 416  0
             throw new NullPointerException("context");
 417  
         }
 418  
 
 419  
         try
 420  
         {
 421  0
             setCachedFacesContext(context);
 422  
             // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
 423  0
             pushComponentToEL(context, this);
 424  
     
 425  0
             if (isRendered())
 426  
             {
 427  
                 // If our rendered property is true, render the beginning of the current state of this UIComponent to the
 428  
                 // response contained in the specified FacesContext.
 429  
     
 430  
                 // Call Application.publishEvent(java.lang.Class, java.lang.Object), passing BeforeRenderEvent.class as
 431  
                 // the first argument and the component instance to be rendered as the second argument.
 432  
     
 433  
                 //The main issue we have here is that the listeners are normally just registered to UIComponent, how do we deal with inherited ones?
 434  
                 //We have to ask the EG
 435  0
                 context.getApplication().publishEvent(context,  PreRenderComponentEvent.class, UIComponent.class, this);
 436  
     
 437  0
                 Renderer renderer = getRenderer(context);
 438  0
                 if (renderer != null)
 439  
                 {
 440  
                     // If a Renderer is associated with this UIComponent, the actual encoding will be delegated to
 441  
                     // Renderer.encodeBegin(FacesContext, UIComponent).
 442  0
                     renderer.encodeBegin(context, this);
 443  
                 }
 444  
             }
 445  
         }
 446  
         finally
 447  
         {
 448  0
             setCachedFacesContext(null);
 449  0
         }
 450  0
     }
 451  
 
 452  
     @Override
 453  
     public void encodeChildren(FacesContext context) throws IOException
 454  
     {
 455  0
         if (context == null)
 456  
         {
 457  0
             throw new NullPointerException("context");
 458  
         }
 459  
 
 460  0
         boolean isCachedFacesContext = isCachedFacesContext();
 461  
         try
 462  
         {
 463  0
             if (!isCachedFacesContext)
 464  
             {
 465  0
                 setCachedFacesContext(context);
 466  
             }
 467  0
             if (isRendered())
 468  
             {
 469  
                 // If our rendered property is true, render the child UIComponents of this UIComponent.
 470  
     
 471  0
                 Renderer renderer = getRenderer(context);
 472  0
                 if (renderer == null)
 473  
                 {
 474  
                     // If no Renderer is associated with this UIComponent, iterate over each of the children of this
 475  
                     // component and call UIComponent.encodeAll(javax.faces.context.FacesContext).
 476  0
                     if (getChildCount() > 0)
 477  
                     {
 478  0
                         for (UIComponent child : getChildren())
 479  
                         {
 480  0
                             child.encodeAll(context);
 481  
                         }
 482  
                     }
 483  
                 }
 484  
                 else
 485  
                 {
 486  
                     // If a Renderer is associated with this UIComponent, the actual encoding will be delegated to
 487  
                     // Renderer.encodeChildren(FacesContext, UIComponent).
 488  0
                     renderer.encodeChildren(context, this);
 489  
                 }
 490  
             }
 491  
         }
 492  
         finally
 493  
         {
 494  0
             if (!isCachedFacesContext)
 495  
             {
 496  0
                 setCachedFacesContext(null);
 497  
             }
 498  
         }
 499  0
     }
 500  
 
 501  
     @Override
 502  
     public void encodeEnd(FacesContext context) throws IOException
 503  
     {
 504  
         try
 505  
         {
 506  0
             if (context == null)
 507  
             {
 508  0
                 throw new NullPointerException("context");
 509  
             }
 510  0
             setCachedFacesContext(context);
 511  0
             if (isRendered())
 512  
             {
 513  
                 // If our rendered property is true, render the ending of the current state of this UIComponent.
 514  0
                 Renderer renderer = getRenderer(context);
 515  0
                 if (renderer != null)
 516  
                 {
 517  
                     // If a Renderer is associated with this UIComponent, the actual encoding will be delegated to
 518  
                     // Renderer.encodeEnd(FacesContext, UIComponent).
 519  0
                     renderer.encodeEnd(context, this);
 520  
                 }
 521  
             }
 522  
         }
 523  
         finally
 524  
         {
 525  
             // Call UIComponent.popComponentFromEL(javax.faces.context.FacesContext). before returning regardless
 526  
             // of the value of the rendered property.
 527  0
             popComponentFromEL(context);
 528  0
             setCachedFacesContext(null);
 529  0
         }
 530  0
     }
 531  
     
 532  
     /**
 533  
      * Standard method for finding other components by id, inherited by most UIComponent objects.
 534  
      * <p>
 535  
      * The lookup is performed in a manner similar to finding a file in a filesystem; there is a "base" at which to
 536  
      * start, and the id can be for something in the "local directory", or can include a relative path. Here,
 537  
      * NamingContainer components fill the role of directories, and ":" is the "path separator". Note, however, that
 538  
      * although components have a strict parent/child hierarchy, component ids are only prefixed ("namespaced") with the
 539  
      * id of their parent when the parent is a NamingContainer.
 540  
      * <p>
 541  
      * The base node at which the search starts is determined as follows:
 542  
      * <ul>
 543  
      * <li>When expr starts with ':', the search starts with the root component of the tree that this component is in
 544  
      * (ie the ancestor whose parent is null).
 545  
      * <li>Otherwise, if this component is a NamingContainer then the search starts with this component.
 546  
      * <li>Otherwise, the search starts from the nearest ancestor NamingContainer (or the root component if there is no
 547  
      * NamingContainer ancestor).
 548  
      * </ul>
 549  
      * 
 550  
      * @param expr
 551  
      *            is of form "id1:id2:id3".
 552  
      * @return UIComponent or null if no component with the specified id is found.
 553  
      */
 554  
 
 555  
     @Override
 556  
     public UIComponent findComponent(String expr)
 557  
     {
 558  0
         if (expr == null)
 559  0
             throw new NullPointerException("expr");
 560  0
         if (expr.length() == 0)
 561  0
             return null;
 562  
 
 563  0
         final char separatorChar = UINamingContainer.getSeparatorChar(getFacesContext());
 564  
         UIComponent findBase;
 565  0
         if (expr.charAt(0) == separatorChar)
 566  
         {
 567  0
             findBase = _ComponentUtils.getRootComponent(this);
 568  0
             expr = expr.substring(1);
 569  
         }
 570  
         else
 571  
         {
 572  0
             if (this instanceof NamingContainer)
 573  
             {
 574  0
                 findBase = this;
 575  
             }
 576  
             else
 577  
             {
 578  0
                 findBase = _ComponentUtils.findParentNamingContainer(this, true /* root if not found */);
 579  
             }
 580  
         }
 581  
 
 582  0
         int separator = expr.indexOf(separatorChar);
 583  0
         if (separator == -1)
 584  
         {
 585  0
             return _ComponentUtils.findComponent(findBase, expr, separatorChar);
 586  
         }
 587  
 
 588  0
         String id = expr.substring(0, separator);
 589  0
         findBase = _ComponentUtils.findComponent(findBase, id, separatorChar);
 590  0
         if (findBase == null)
 591  
         {
 592  0
             return null;
 593  
         }
 594  
 
 595  0
         if (!(findBase instanceof NamingContainer))
 596  0
             throw new IllegalArgumentException("Intermediate identifier " + id + " in search expression " + expr
 597  
                     + " identifies a UIComponent that is not a NamingContainer");
 598  
 
 599  0
         return findBase.findComponent(expr.substring(separator + 1));
 600  
 
 601  
     }
 602  
 
 603  
     /**
 604  
      * Get a map through which all the UIComponent's properties, value-bindings and non-property attributes can be read
 605  
      * and written.
 606  
      * <p>
 607  
      * When writing to the returned map:
 608  
      * <ul>
 609  
      * <li>If this component has an explicit property for the specified key then the setter method is called. An
 610  
      * IllegalArgumentException is thrown if the property is read-only. If the property is readable then the old value
 611  
      * is returned, otherwise null is returned.
 612  
      * <li>Otherwise the key/value pair is stored in a map associated with the component.
 613  
      * </ul>
 614  
      * Note that value-bindings are <i>not</i> written by put calls to this map. Writing to the attributes map using a
 615  
      * key for which a value-binding exists will just store the value in the attributes map rather than evaluating the
 616  
      * binding, effectively "hiding" the value-binding from later attributes.get calls. Setter methods on components
 617  
      * commonly do <i>not</i> evaluate a binding of the same name; they just store the provided value directly on the
 618  
      * component.
 619  
      * <p>
 620  
      * When reading from the returned map:
 621  
      * <ul>
 622  
      * <li>If this component has an explicit property for the specified key then the getter method is called. If the
 623  
      * property exists, but is read-only (ie only a setter method is defined) then an IllegalArgumentException is
 624  
      * thrown.
 625  
      * <li>If the attribute map associated with the component has an entry with the specified key, then that is
 626  
      * returned.
 627  
      * <li>If this component has a value-binding for the specified key, then the value-binding is evaluated to fetch the
 628  
      * value.
 629  
      * <li>Otherwise, null is returned.
 630  
      * </ul>
 631  
      * Note that components commonly define getter methods such that they evaluate a value-binding of the same name if
 632  
      * there isn't yet a local property.
 633  
      * <p>
 634  
      * Assigning values to the map which are not explicit properties on the underlying component can be used to "tunnel"
 635  
      * attributes from the JSP tag (or view-specific equivalent) to the associated renderer without modifying the
 636  
      * component itself.
 637  
      * <p>
 638  
      * Any value-bindings and non-property attributes stored in this map are automatically serialized along with the
 639  
      * component when the view is serialized.
 640  
      */
 641  
     @Override
 642  
     public Map<String, Object> getAttributes()
 643  
     {
 644  0
         if (_attributesMap == null)
 645  
         {
 646  0
             _attributesMap = new _ComponentAttributesMap(this);
 647  
         }
 648  
 
 649  0
         return _attributesMap;
 650  
     }
 651  
 
 652  
     /**
 653  
      * Return the number of direct child components this component has.
 654  
      * <p>
 655  
      * Identical to getChildren().size() except that when this component has no children this method will not force an
 656  
      * empty list to be created.
 657  
      */
 658  
     @Override
 659  
     public int getChildCount()
 660  
     {
 661  0
         return _childrenList == null ? 0 : _childrenList.size();
 662  
     }
 663  
 
 664  
     /**
 665  
      * Return a list of the UIComponent objects which are direct children of this component.
 666  
      * <p>
 667  
      * The list object returned has some non-standard behaviour:
 668  
      * <ul>
 669  
      * <li>The list is type-checked; only UIComponent objects can be added.
 670  
      * <li>If a component is added to the list with an id which is the same as some other component in the list then an
 671  
      * exception is thrown. However multiple components with a null id may be added.
 672  
      * <li>The component's parent property is set to this component. If the component already had a parent, then the
 673  
      * component is first removed from its original parent's child list.
 674  
      * </ul>
 675  
      */
 676  
     @Override
 677  
     public List<UIComponent> getChildren()
 678  
     {
 679  0
         if (_childrenList == null)
 680  
         {
 681  0
             _childrenList = new _ComponentChildrenList(this);
 682  
         }
 683  0
         return _childrenList;
 684  
     }
 685  
     
 686  
     /**
 687  
      * 
 688  
      * @return
 689  
      * 
 690  
      * @since 2.0
 691  
      */
 692  
     public Map<String,List<ClientBehavior>> getClientBehaviors()
 693  
     {
 694  0
         if(_behaviorsMap == null)
 695  
         {
 696  0
             return Collections.emptyMap();
 697  
         }
 698  
 
 699  0
         return wrapBehaviorsMap();
 700  
     }
 701  
 
 702  
     /**
 703  
      * Get a string which can be output to the response which uniquely identifies this UIComponent within the current
 704  
      * view.
 705  
      * <p>
 706  
      * The component should have an id attribute already assigned to it; however if the id property is currently null
 707  
      * then a unique id is generated and set for this component. This only happens when components are programmatically
 708  
      * created without ids, as components created by a ViewHandler should be assigned ids when they are created.
 709  
      * <p>
 710  
      * If this component is a descendant of a NamingContainer then the client id is of form
 711  
      * "{namingContainerId}:{componentId}". Note that the naming container's id may itself be of compound form if it has
 712  
      * an ancestor naming container. Note also that this only applies to naming containers; other UIComponent types in
 713  
      * the component's ancestry do not affect the clientId.
 714  
      * <p>
 715  
      * Finally the renderer associated with this component is asked to convert the id into a suitable form. This allows
 716  
      * escaping of any characters in the clientId which are significant for the markup language generated by that
 717  
      * renderer.
 718  
      */
 719  
     @Override
 720  
     public String getClientId(FacesContext context)
 721  
     {
 722  0
         if (context == null)
 723  0
             throw new NullPointerException("context");
 724  
 
 725  0
         if (_clientId != null)
 726  0
             return _clientId;
 727  
 
 728  
         //boolean idWasNull = false;
 729  0
         String id = getId();
 730  0
         if (id == null)
 731  
         {
 732  
             // Although this is an error prone side effect, we automatically create a new id
 733  
             // just to be compatible to the RI
 734  
             
 735  
             // The documentation of UniqueIdVendor says that this interface should be implemented by
 736  
             // components that also implements NamingContainer. The only component that does not implement
 737  
             // NamingContainer but UniqueIdVendor is UIViewRoot. Anyway we just can't be 100% sure about this
 738  
             // fact, so it is better to scan for the closest UniqueIdVendor. If it is not found use 
 739  
             // viewRoot.createUniqueId, otherwise use UniqueIdVendor.createUniqueId(context,seed).
 740  0
             UniqueIdVendor parentUniqueIdVendor = _ComponentUtils.findParentUniqueIdVendor(this);
 741  0
             if (parentUniqueIdVendor == null)
 742  
             {
 743  0
                 UIViewRoot viewRoot = context.getViewRoot();
 744  0
                 if (viewRoot != null)
 745  
                 {
 746  0
                     id = viewRoot.createUniqueId();
 747  
                 }
 748  
                 else
 749  
                 {
 750  
                     // The RI throws a NPE
 751  0
                     String location = getComponentLocation(this);
 752  0
                     throw new FacesException("Cannot create clientId. No id is assigned for component"
 753  
                             + " to create an id and UIViewRoot is not defined: "
 754  
                             + getPathToComponent(this)
 755  
                             + (location != null ? " created from: " + location : ""));
 756  
                 }
 757  0
             }
 758  
             else
 759  
             {
 760  0
                 id = parentUniqueIdVendor.createUniqueId(context, null);
 761  
             }
 762  0
             setId(id);
 763  
             // We remember that the id was null and log a warning down below
 764  
             // idWasNull = true;
 765  
         }
 766  
 
 767  0
         UIComponent namingContainer = _ComponentUtils.findParentNamingContainer(this, false);
 768  0
         if (namingContainer != null)
 769  
         {
 770  0
             String containerClientId = namingContainer.getContainerClientId(context);
 771  0
             if (containerClientId != null)
 772  
             {
 773  0
                 StringBuilder bld = __getSharedStringBuilder();
 774  0
                 _clientId = bld.append(containerClientId).append(UINamingContainer.getSeparatorChar(context)).append(id).toString();
 775  0
             }
 776  
             else
 777  
             {
 778  0
                 _clientId = id;
 779  
             }
 780  0
         }
 781  
         else
 782  
         {
 783  0
             _clientId = id;
 784  
         }
 785  
 
 786  0
         Renderer renderer = getRenderer(context);
 787  0
         if (renderer != null)
 788  
         {
 789  0
             _clientId = renderer.convertClientId(context, _clientId);
 790  
         }
 791  
 
 792  
         // -=Leonardo Uribe=- In jsf 1.1 and 1.2 this warning has sense, but in jsf 2.0 it is common to have
 793  
         // components without any explicit id (UIViewParameter components and UIOuput resource components) instances.
 794  
         // So, this warning is becoming obsolete in this new context and should be removed.
 795  
         //if (idWasNull && log.isLoggable(Level.WARNING))
 796  
         //{
 797  
         //    log.warning("WARNING: Component " + _clientId
 798  
         //            + " just got an automatic id, because there was no id assigned yet. "
 799  
         //            + "If this component was created dynamically (i.e. not by a JSP tag) you should assign it an "
 800  
         //            + "explicit static id or assign it the id you get from "
 801  
         //            + "the createUniqueId from the current UIViewRoot "
 802  
         //            + "component right after creation! Path to Component: " + getPathToComponent(this));
 803  
         //}
 804  
 
 805  0
         return _clientId;
 806  
     }
 807  
     
 808  
     /**
 809  
      * 
 810  
      * @return
 811  
      * 
 812  
      * @since 2.0
 813  
      */
 814  
     public String getDefaultEventName()
 815  
     {
 816  
         // if a default event exists for a component, this method is overriden thus assume null
 817  0
         return null;
 818  
     }
 819  
     
 820  
     /**
 821  
      * 
 822  
      * @return
 823  
      * 
 824  
      * @since 2.0
 825  
      */
 826  
     public Collection<String> getEventNames()
 827  
     {
 828  
         // must be specified by the implementing component.  Returning null will force an error message in addClientBehavior.
 829  0
         return null;
 830  
     }
 831  
 
 832  
     @Override
 833  
     public UIComponent getFacet(String name)
 834  
     {
 835  0
         return _facetMap == null ? null : _facetMap.get(name);
 836  
     }
 837  
 
 838  
     /**
 839  
      * @since 1.2
 840  
      */
 841  
     @Override
 842  
     public int getFacetCount()
 843  
     {
 844  0
         return _facetMap == null ? 0 : _facetMap.size();
 845  
     }
 846  
 
 847  
     @Override
 848  
     public Map<String, UIComponent> getFacets()
 849  
     {
 850  0
         if (_facetMap == null)
 851  
         {
 852  0
             _facetMap = new _ComponentFacetMap<UIComponent>(this);
 853  
         }
 854  0
         return _facetMap;
 855  
     }
 856  
 
 857  
     @Override
 858  
     public Iterator<UIComponent> getFacetsAndChildren()
 859  
     {
 860  
         // we can't use _facetMap and _childrenList here directly,
 861  
         // because some component implementation could keep their 
 862  
         // own properties for facets and children and just override
 863  
         // getFacets() and getChildren() (e.g. seen in PrimeFaces).
 864  
         // See MYFACES-2611 for details.
 865  0
         if (getFacetCount() == 0)
 866  
         {
 867  0
             if (getChildCount() == 0)
 868  0
                 return _EMPTY_UICOMPONENT_ITERATOR;
 869  
 
 870  0
             return getChildren().iterator();
 871  
         }
 872  
         else
 873  
         {
 874  0
             if (getChildCount() == 0)
 875  0
                 return getFacets().values().iterator();
 876  
 
 877  0
             return new _FacetsAndChildrenIterator(getFacets(), getChildren());
 878  
         }
 879  
     }
 880  
 
 881  
     /**
 882  
      * Get a string which uniquely identifies this UIComponent within the scope of the nearest ancestor NamingContainer
 883  
      * component. The id is not necessarily unique across all components in the current view.
 884  
      */
 885  
     @JSFProperty(rtexprvalue = true)
 886  
     public String getId()
 887  
     {
 888  0
         return _id;
 889  
     }
 890  
 
 891  
     @Override
 892  
     public UIComponent getParent()
 893  
     {
 894  0
         return _parent;
 895  
     }
 896  
 
 897  
     @Override
 898  
     public String getRendererType()
 899  
     {
 900  0
         return (String) getStateHelper().eval(PropertyKeys.rendererType);
 901  
     }
 902  
 
 903  
     /**
 904  
      * Indicates whether this component or its renderer manages the invocation of the rendering methods of its child
 905  
      * components. When this is true:
 906  
      * <ul>
 907  
      * <li>This component's encodeBegin method will only be called after all the child components have been created and
 908  
      * added to this component. <li>This component's encodeChildren method will be called after its encodeBegin method.
 909  
      * Components for which this method returns false do not get this method invoked at all. <li>No rendering methods
 910  
      * will be called automatically on child components; this component is required to invoke the
 911  
      * encodeBegin/encodeEnd/etc on them itself.
 912  
      * </ul>
 913  
      */
 914  
     @Override
 915  
     public boolean getRendersChildren()
 916  
     {
 917  0
         Renderer renderer = getRenderer(getFacesContext());
 918  0
         return renderer != null ? renderer.getRendersChildren() : false;
 919  
     }
 920  
 
 921  
     /**
 922  
      * Get the named value-binding associated with this component.
 923  
      * <p>
 924  
      * Value-bindings are stored in a map associated with the component, though there is commonly a property
 925  
      * (setter/getter methods) of the same name defined on the component itself which evaluates the value-binding when
 926  
      * called.
 927  
      * 
 928  
      * @deprecated Replaced by getValueExpression
 929  
      */
 930  
     @Override
 931  
     public ValueBinding getValueBinding(String name)
 932  
     {
 933  0
         ValueExpression expression = getValueExpression(name);
 934  0
         if (expression != null)
 935  
         {
 936  0
             if (expression instanceof _ValueBindingToValueExpression)
 937  
             {
 938  0
                 return ((_ValueBindingToValueExpression) expression).getValueBinding();
 939  
             }
 940  0
             return new _ValueExpressionToValueBinding(expression);
 941  
         }
 942  0
         return null;
 943  
     }
 944  
     
 945  
     public boolean initialStateMarked()
 946  
     {
 947  
         // TODO: IMPLEMENT HERE
 948  
         // FIXME: Nofity EG, this method should be in the specification
 949  0
         return super.initialStateMarked();
 950  
     }
 951  
     
 952  
     /**
 953  
      * <code>invokeOnComponent</code> must be implemented in <code>UIComponentBase</code> too...
 954  
      */
 955  
     @Override
 956  
     public boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback)
 957  
             throws FacesException
 958  
     {
 959  0
         if (isCachedFacesContext())
 960  
         {
 961  0
             return super.invokeOnComponent(context, clientId, callback);
 962  
         }
 963  
         else
 964  
         {
 965  
             try
 966  
             {
 967  0
                 setCachedFacesContext(context);
 968  0
                 return super.invokeOnComponent(context, clientId, callback);
 969  
             }
 970  
             finally
 971  
             {
 972  0
                 setCachedFacesContext(null);
 973  
             }
 974  
         }
 975  
     }
 976  
     
 977  
     
 978  
 
 979  
     @Override
 980  
     public boolean visitTree(VisitContext context, VisitCallback callback)
 981  
     {
 982  0
         if (isCachedFacesContext())
 983  
         {
 984  0
             return super.visitTree(context, callback);
 985  
         }
 986  
         else
 987  
         {
 988  
             try
 989  
             {
 990  0
                 setCachedFacesContext(context.getFacesContext());
 991  0
                 return super.visitTree(context, callback);
 992  
             }
 993  
             finally
 994  
             {
 995  0
                 setCachedFacesContext(null);
 996  
             }
 997  
         }
 998  
     }
 999  
 
 1000  
     /**
 1001  
      * A boolean value that indicates whether this component should be rendered. Default value: true.
 1002  
      **/
 1003  
     @Override
 1004  
     @JSFProperty
 1005  
     public boolean isRendered()
 1006  
     {
 1007  0
         return (Boolean) getStateHelper().eval(PropertyKeys.rendered, DEFAULT_RENDERED);
 1008  
     }
 1009  
 
 1010  
     @JSFProperty(literalOnly = true, istransient = true, tagExcluded = true)
 1011  
     public boolean isTransient()
 1012  
     {
 1013  0
         return _transient;
 1014  
     }
 1015  
     
 1016  
     public void markInitialState()
 1017  
     {
 1018  0
         super.markInitialState();
 1019  0
         if (_facesListeners != null)
 1020  
         {
 1021  0
             _facesListeners.markInitialState();
 1022  
         }
 1023  0
         if (_behaviorsMap != null)
 1024  
         {
 1025  0
             for (Map.Entry<String, List<ClientBehavior> > entry : _behaviorsMap.entrySet())
 1026  
             {
 1027  0
                 ((PartialStateHolder) entry.getValue()).markInitialState();
 1028  
             }
 1029  
         }
 1030  0
         if (_systemEventListenerClassMap != null)
 1031  
         {
 1032  
             for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener>> entry : 
 1033  0
                 _systemEventListenerClassMap.entrySet())
 1034  
             {
 1035  0
                 ((PartialStateHolder) entry.getValue()).markInitialState();
 1036  
             }
 1037  
         }
 1038  0
     }
 1039  
 
 1040  
     @Override
 1041  
     protected void addFacesListener(FacesListener listener)
 1042  
     {
 1043  0
         if (listener == null)
 1044  0
             throw new NullPointerException("listener");
 1045  0
         if (_facesListeners == null)
 1046  
         {
 1047  0
             _facesListeners = new _DeltaList<FacesListener>(new ArrayList<FacesListener>());
 1048  
         }
 1049  0
         _facesListeners.add(listener);
 1050  0
     }
 1051  
 
 1052  
     @Override
 1053  
     protected FacesContext getFacesContext()
 1054  
     {
 1055  0
         if (_facesContext == null)
 1056  
         {
 1057  0
             return FacesContext.getCurrentInstance();
 1058  
         }
 1059  
         else
 1060  
         {
 1061  0
             return _facesContext;
 1062  
         }
 1063  
     }
 1064  
 
 1065  
     // FIXME: Notify EG for generic usage
 1066  
     @Override
 1067  
     protected FacesListener[] getFacesListeners(Class clazz)
 1068  
     {
 1069  0
         if (clazz == null)
 1070  
         {
 1071  0
             throw new NullPointerException("Class is null");
 1072  
         }
 1073  0
         if (!FacesListener.class.isAssignableFrom(clazz))
 1074  
         {
 1075  0
             throw new IllegalArgumentException("Class " + clazz.getName() + " must implement " + FacesListener.class);
 1076  
         }
 1077  
 
 1078  0
         if (_facesListeners == null)
 1079  
         {
 1080  0
             return (FacesListener[]) Array.newInstance(clazz, 0);
 1081  
         }
 1082  0
         List<FacesListener> lst = null;
 1083  0
         for (Iterator<FacesListener> it = _facesListeners.iterator(); it.hasNext();)
 1084  
         {
 1085  0
             FacesListener facesListener = it.next();
 1086  0
             if (facesListener != null && clazz.isAssignableFrom(facesListener.getClass()))
 1087  
             {
 1088  0
                 if (lst == null)
 1089  0
                     lst = new ArrayList<FacesListener>();
 1090  0
                 lst.add(facesListener);
 1091  
             }
 1092  0
         }
 1093  0
         if (lst == null)
 1094  
         {
 1095  0
             return (FacesListener[]) Array.newInstance(clazz, 0);
 1096  
         }
 1097  
 
 1098  0
         return lst.toArray((FacesListener[]) Array.newInstance(clazz, lst.size()));
 1099  
     }
 1100  
 
 1101  
     @Override
 1102  
     protected Renderer getRenderer(FacesContext context)
 1103  
     {
 1104  0
         if (context == null)
 1105  0
             throw new NullPointerException("context");
 1106  0
         String rendererType = getRendererType();
 1107  0
         if (rendererType == null)
 1108  0
             return null;
 1109  
         
 1110  0
         RenderKit renderKit = context.getRenderKit();
 1111  0
         Renderer renderer = renderKit.getRenderer(getFamily(), rendererType);
 1112  0
         if (renderer == null)
 1113  
         {
 1114  0
             String location = getComponentLocation(this);
 1115  0
             String logStr = "No Renderer found for component " + getPathToComponent(this)
 1116  
                     + " (component-family=" + getFamily()
 1117  
                     + ", renderer-type=" + rendererType + ")"
 1118  
                     + (location != null ? " created from: " + location : "");
 1119  
             
 1120  0
             getFacesContext().getExternalContext().log(logStr);
 1121  0
             log.warning(logStr);
 1122  
         }
 1123  0
         return renderer;
 1124  
     }
 1125  
 
 1126  
     @Override
 1127  
     protected void removeFacesListener(FacesListener listener)
 1128  
     {
 1129  0
         if (listener == null)
 1130  
         {
 1131  0
             throw new NullPointerException("listener is null");
 1132  
         }
 1133  
 
 1134  0
         if (_facesListeners != null)
 1135  
         {
 1136  0
             _facesListeners.remove(listener);
 1137  
         }
 1138  0
     }
 1139  
 
 1140  
     @Override
 1141  
     public void queueEvent(FacesEvent event)
 1142  
     {
 1143  0
         if (event == null)
 1144  0
             throw new NullPointerException("event");
 1145  0
         UIComponent parent = getParent();
 1146  0
         if (parent == null)
 1147  
         {
 1148  0
             throw new IllegalStateException("component is not a descendant of a UIViewRoot");
 1149  
         }
 1150  0
         parent.queueEvent(event);
 1151  0
     }
 1152  
 
 1153  
     @Override
 1154  
     public void processDecodes(FacesContext context)
 1155  
     {
 1156  
         try
 1157  
         {
 1158  0
             setCachedFacesContext(context);
 1159  0
             if (_isPhaseExecutable(context))
 1160  
             {
 1161  
                 // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
 1162  0
                 pushComponentToEL(context, this);
 1163  
     
 1164  
                 try
 1165  
                 {
 1166  
                     // Call the processDecodes() method of all facets and children of this UIComponent, in the order
 1167  
                     // determined by a call to getFacetsAndChildren().
 1168  0
                     for (Iterator<UIComponent> it = getFacetsAndChildren(); it.hasNext();)
 1169  
                     {
 1170  0
                         it.next().processDecodes(context);
 1171  
                     }
 1172  
     
 1173  
                     try
 1174  
                     {
 1175  
                         // Call the decode() method of this component.
 1176  0
                         decode(context);
 1177  
                     }
 1178  0
                     catch (RuntimeException e)
 1179  
                     {
 1180  
                         // If a RuntimeException is thrown during decode processing, call FacesContext.renderResponse()
 1181  
                         // and re-throw the exception.
 1182  0
                         context.renderResponse();
 1183  0
                         throw e;
 1184  0
                     }
 1185  
                 }
 1186  
                 finally
 1187  
                 {
 1188  
                     // Call UIComponent.popComponentFromEL(javax.faces.context.FacesContext) from inside of a finally
 1189  
                     // block, just before returning.
 1190  
     
 1191  0
                     popComponentFromEL(context);
 1192  0
                 }
 1193  
             }
 1194  
         }
 1195  
         finally
 1196  
         {
 1197  0
             setCachedFacesContext(null);
 1198  0
         }
 1199  0
     }
 1200  
 
 1201  
     @Override
 1202  
     public void processValidators(FacesContext context)
 1203  
     {
 1204  
         try
 1205  
         {
 1206  0
             setCachedFacesContext(context);
 1207  0
             if (_isPhaseExecutable(context))
 1208  
             {
 1209  
                 // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
 1210  0
                 pushComponentToEL(context, this);
 1211  
     
 1212  
                 try
 1213  
                 {
 1214  
                     // Call the processValidators() method of all facets and children of this UIComponent, in the order
 1215  
                     // determined by a call to getFacetsAndChildren().
 1216  0
                     for (Iterator<UIComponent> it = getFacetsAndChildren(); it.hasNext();)
 1217  
                     {
 1218  0
                         it.next().processValidators(context);
 1219  
                     }
 1220  
                 }
 1221  
                 finally
 1222  
                 {
 1223  0
                     popComponentFromEL(context);
 1224  0
                 }
 1225  
             }
 1226  
         }
 1227  
         finally
 1228  
         {
 1229  0
             setCachedFacesContext(null);
 1230  0
         }
 1231  0
     }
 1232  
 
 1233  
     /**
 1234  
      * This isn't an input component, so just pass on the processUpdates call to child components and facets that might
 1235  
      * be input components.
 1236  
      * <p>
 1237  
      * Components that were never rendered can't possibly be receiving update data (no corresponding fields were ever
 1238  
      * put into the response) so if this component is not rendered then this method does not invoke processUpdates on
 1239  
      * its children.
 1240  
      */
 1241  
     @Override
 1242  
     public void processUpdates(FacesContext context)
 1243  
     {
 1244  
         try
 1245  
         {
 1246  0
             setCachedFacesContext(context);
 1247  0
             if (_isPhaseExecutable(context))
 1248  
             {
 1249  
                 // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
 1250  0
                 pushComponentToEL(context, this);
 1251  
     
 1252  
                 try
 1253  
                 {
 1254  
                     // Call the processUpdates() method of all facets and children of this UIComponent, in the order
 1255  
                     // determined by a call to getFacetsAndChildren().
 1256  0
                     for (Iterator<UIComponent> it = getFacetsAndChildren(); it.hasNext();)
 1257  
                     {
 1258  0
                         it.next().processUpdates(context);
 1259  
                     }
 1260  
                 }
 1261  
                 finally
 1262  
                 {
 1263  
                     // After returning from the processUpdates() method on a child or facet, call
 1264  
                     // UIComponent.popComponentFromEL(javax.faces.context.FacesContext)
 1265  0
                     popComponentFromEL(context);
 1266  0
                 }
 1267  
             }
 1268  
         }
 1269  
         finally
 1270  
         {
 1271  0
             setCachedFacesContext(null);
 1272  0
         }
 1273  0
     }
 1274  
 
 1275  
     @Override
 1276  
     public Object processSaveState(FacesContext context)
 1277  
     {
 1278  0
         if (context == null)
 1279  
         {
 1280  0
             throw new NullPointerException("context");
 1281  
         }
 1282  
 
 1283  0
         if (isTransient())
 1284  
         {
 1285  
             // consult the transient property of this component. If true, just return null.
 1286  0
             return null;
 1287  
         }
 1288  
 
 1289  
         // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
 1290  0
         pushComponentToEL(context, this);
 1291  
 
 1292  
         Map<String, Object> facetMap;
 1293  
 
 1294  
         List<Object> childrenList;
 1295  
         
 1296  
         Object savedState;
 1297  
         try
 1298  
         {
 1299  0
             facetMap = null;
 1300  0
             int facetCount = getFacetCount();
 1301  0
             if (facetCount > 0)
 1302  
             {
 1303  
                 // Call the processSaveState() method of all facets and children of this UIComponent in the order
 1304  
                 // determined by a call to getFacetsAndChildren(), skipping children and facets that are transient.
 1305  
 
 1306  
                 // To improve speed and robustness, the facets and children processing is splited to maintain the
 1307  
                 // facet --> state coherence based on the facet's name
 1308  0
                 for (Map.Entry<String, UIComponent> entry : getFacets().entrySet())
 1309  
                 {
 1310  0
                     UIComponent component = entry.getValue();
 1311  0
                     if (!component.isTransient())
 1312  
                     {
 1313  0
                         if (facetMap == null)
 1314  
                         {
 1315  0
                             facetMap = new HashMap<String, Object>(facetCount, 1);
 1316  
                         }
 1317  
 
 1318  0
                         facetMap.put(entry.getKey(), component.processSaveState(context));
 1319  
 
 1320  
                         // Ensure that UIComponent.popComponentFromEL(javax.faces.context.FacesContext) is called
 1321  
                         // correctly after each child or facet.
 1322  
                         // popComponentFromEL(context);
 1323  
                     }
 1324  0
                 }
 1325  
             }
 1326  0
             childrenList = null;
 1327  0
             int childCount = getChildCount();
 1328  0
             if (childCount > 0)
 1329  
             {
 1330  
                 // Call the processSaveState() method of all facets and children of this UIComponent in the order
 1331  
                 // determined by a call to getFacetsAndChildren(), skipping children and facets that are transient.
 1332  
 
 1333  
                 // To improve speed and robustness, the facets and children processing is splited to maintain the
 1334  
                 // facet --> state coherence based on the facet's name
 1335  0
                 for (UIComponent child : getChildren())
 1336  
                 {
 1337  0
                     if (!child.isTransient())
 1338  
                     {
 1339  0
                         if (childrenList == null)
 1340  
                         {
 1341  0
                             childrenList = new ArrayList<Object>(childCount);
 1342  
                         }
 1343  
 
 1344  0
                         Object childState = child.processSaveState(context);
 1345  0
                         if (childState != null)
 1346  
                         { // FIXME: Isn't that check dangerous for restoration since the child isn't marked transient?
 1347  0
                             childrenList.add(childState);
 1348  
                         }
 1349  
 
 1350  
                         // Ensure that UIComponent.popComponentFromEL(javax.faces.context.FacesContext) is called
 1351  
                         // correctly after each child or facet.
 1352  0
                     }
 1353  
                 }
 1354  
             }
 1355  
             
 1356  
             // Call the saveState() method of this component.
 1357  0
             savedState = saveState(context);
 1358  
         }
 1359  
         finally
 1360  
         {
 1361  0
             popComponentFromEL(context);
 1362  0
         }
 1363  
 
 1364  
         // Encapsulate the child state and your state into a Serializable Object and return it.
 1365  0
         return new Object[] { savedState, facetMap, childrenList };
 1366  
     }
 1367  
 
 1368  
     @SuppressWarnings("unchecked")
 1369  
     @Override
 1370  
     public void processRestoreState(FacesContext context, Object state)
 1371  
     {
 1372  0
         if (context == null)
 1373  
         {
 1374  0
             throw new NullPointerException("context");
 1375  
         }
 1376  
 
 1377  0
         Object[] stateValues = (Object[]) state;
 1378  
 
 1379  
         try
 1380  
         {
 1381  
             // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
 1382  0
             pushComponentToEL(context, this);
 1383  
 
 1384  
             // Call the restoreState() method of this component.
 1385  0
             restoreState(context, stateValues[0]);
 1386  
             
 1387  0
             Map<String, Object> facetMap = (Map<String, Object>) stateValues[1];
 1388  0
             if (facetMap != null && getFacetCount() > 0)
 1389  
             {
 1390  
                 // Call the processRestoreState() method of all facets and children of this UIComponent in the order
 1391  
                 // determined by a call to getFacetsAndChildren().
 1392  
 
 1393  
                 // To improve speed and robustness, the facets and children processing is splited to maintain the
 1394  
                 // facet --> state coherence based on the facet's name
 1395  0
                 for (Map.Entry<String, UIComponent> entry : getFacets().entrySet())
 1396  
                 {
 1397  0
                     Object facetState = facetMap.get(entry.getKey());
 1398  0
                     if (facetState != null)
 1399  
                     {
 1400  0
                         entry.getValue().processRestoreState(context, facetState);
 1401  
 
 1402  
                         // After returning from the processRestoreState() method on a child or facet, call
 1403  
                         // UIComponent.popComponentFromEL(javax.faces.context.FacesContext)
 1404  
                         // popComponentFromEL(context);
 1405  
                     }
 1406  
                     else
 1407  
                     {
 1408  0
                         context.getExternalContext().log("No state found to restore facet " + entry.getKey());
 1409  
                     }
 1410  0
                 }
 1411  
             }
 1412  0
             List<Object> childrenList = (List<Object>) stateValues[2];
 1413  0
             if (childrenList != null && getChildCount() > 0)
 1414  
             {
 1415  
                 // Call the processRestoreState() method of all facets and children of this UIComponent in the order
 1416  
                 // determined by a call to getFacetsAndChildren().
 1417  
 
 1418  
                 // To improve speed and robustness, the facets and children processing is splited to maintain the
 1419  
                 // facet --> state coherence based on the facet's name
 1420  0
                 int idx = 0;
 1421  0
                 for (UIComponent child : getChildren())
 1422  
                 {
 1423  0
                     if (!child.isTransient())
 1424  
                     {
 1425  0
                         Object childState = childrenList.get(idx++);
 1426  0
                         if (childState != null)
 1427  
                         {
 1428  0
                             child.processRestoreState(context, childState);
 1429  
 
 1430  
                             // After returning from the processRestoreState() method on a child or facet, call
 1431  
                             // UIComponent.popComponentFromEL(javax.faces.context.FacesContext)
 1432  
                             // popComponentFromEL(context);
 1433  
                         }
 1434  
                         else
 1435  
                         {
 1436  0
                             context.getExternalContext().log("No state found to restore child of component " + getId());
 1437  
                         }
 1438  0
                     }
 1439  
                 }
 1440  
             }
 1441  
         }
 1442  
         finally
 1443  
         {
 1444  0
             popComponentFromEL(context);
 1445  0
         }
 1446  0
     }
 1447  
     
 1448  
     /**
 1449  
      * Gets the Location of the given UIComponent from its attribute map.
 1450  
      * @param component
 1451  
      * @return
 1452  
      */
 1453  
     private String getComponentLocation(UIComponent component)
 1454  
     {
 1455  0
         Location location = (Location) component.getAttributes()
 1456  
                 .get(UIComponent.VIEW_LOCATION_KEY);
 1457  0
         if (location != null)
 1458  
         {
 1459  0
             return location.toString();
 1460  
         }
 1461  0
         return null;
 1462  
     }
 1463  
 
 1464  
     private String getPathToComponent(UIComponent component)
 1465  
     {
 1466  0
         StringBuffer buf = new StringBuffer();
 1467  
 
 1468  0
         if (component == null)
 1469  
         {
 1470  0
             buf.append("{Component-Path : ");
 1471  0
             buf.append("[null]}");
 1472  0
             return buf.toString();
 1473  
         }
 1474  
 
 1475  0
         getPathToComponent(component, buf);
 1476  
 
 1477  0
         buf.insert(0, "{Component-Path : ");
 1478  0
         buf.append("}");
 1479  
 
 1480  0
         return buf.toString();
 1481  
     }
 1482  
 
 1483  
     private void getPathToComponent(UIComponent component, StringBuffer buf)
 1484  
     {
 1485  0
         if (component == null)
 1486  0
             return;
 1487  
 
 1488  0
         StringBuffer intBuf = new StringBuffer();
 1489  
 
 1490  0
         intBuf.append("[Class: ");
 1491  0
         intBuf.append(component.getClass().getName());
 1492  0
         if (component instanceof UIViewRoot)
 1493  
         {
 1494  0
             intBuf.append(",ViewId: ");
 1495  0
             intBuf.append(((UIViewRoot) component).getViewId());
 1496  
         }
 1497  
         else
 1498  
         {
 1499  0
             intBuf.append(",Id: ");
 1500  0
             intBuf.append(component.getId());
 1501  
         }
 1502  0
         intBuf.append("]");
 1503  
 
 1504  0
         buf.insert(0, intBuf.toString());
 1505  
 
 1506  0
         getPathToComponent(component.getParent(), buf);
 1507  0
     }
 1508  
 
 1509  
     public void setTransient(boolean transientFlag)
 1510  
     {
 1511  0
         _transient = transientFlag;
 1512  0
     }
 1513  
 
 1514  
     /**
 1515  
      * Serializes objects which are "attached" to this component but which are not UIComponent children of it. Examples
 1516  
      * are validator and listener objects. To be precise, it returns an object which implements java.io.Serializable,
 1517  
      * and which when serialized will persist the state of the provided object.
 1518  
      * <p>
 1519  
      * If the attachedObject is a List then every object in the list is saved via a call to this method, and the
 1520  
      * returned wrapper object contains a List object.
 1521  
      * <p>
 1522  
      * If the object implements StateHolder then the object's saveState is called immediately, and a wrapper is returned
 1523  
      * which contains both this saved state and the original class name. However in the case where the
 1524  
      * StateHolder.isTransient method returns true, null is returned instead.
 1525  
      * <p>
 1526  
      * If the object implements java.io.Serializable then the object is simply returned immediately; standard java
 1527  
      * serialization will later be used to store this object.
 1528  
      * <p>
 1529  
      * In all other cases, a wrapper is returned which simply stores the type of the provided object. When deserialized,
 1530  
      * a default instance of that type will be recreated.
 1531  
      */
 1532  
     public static Object saveAttachedState(FacesContext context, Object attachedObject)
 1533  
     {
 1534  0
         if (context == null)
 1535  
         {
 1536  0
             throw new NullPointerException ("context");
 1537  
         }
 1538  
         
 1539  0
         if (attachedObject == null)
 1540  0
             return null;
 1541  
         // StateHolder interface should take precedence over
 1542  
         // List children
 1543  0
         if (attachedObject instanceof StateHolder)
 1544  
         {
 1545  0
             StateHolder holder = (StateHolder) attachedObject;
 1546  0
             if (holder.isTransient())
 1547  
             {
 1548  0
                 return null;
 1549  
             }
 1550  
 
 1551  0
             return new _AttachedStateWrapper(attachedObject.getClass(), holder.saveState(context));
 1552  
         }        
 1553  0
         else if (attachedObject instanceof List)
 1554  
         {
 1555  0
             List<Object> lst = new ArrayList<Object>(((List<?>) attachedObject).size());
 1556  0
             for (Object item : (List<?>) attachedObject)
 1557  
             {
 1558  0
                 if (item != null)
 1559  
                 {
 1560  0
                     lst.add(saveAttachedState(context, item));
 1561  
                 }
 1562  
             }
 1563  
 
 1564  0
             return new _AttachedListStateWrapper(lst);
 1565  
         }
 1566  0
         else if (attachedObject instanceof Serializable)
 1567  
         {
 1568  0
             return attachedObject;
 1569  
         }
 1570  
         else
 1571  
         {
 1572  0
             return new _AttachedStateWrapper(attachedObject.getClass(), null);
 1573  
         }
 1574  
     }
 1575  
 
 1576  
     public static Object restoreAttachedState(FacesContext context, Object stateObj) throws IllegalStateException
 1577  
     {
 1578  0
         if (context == null)
 1579  0
             throw new NullPointerException("context");
 1580  0
         if (stateObj == null)
 1581  0
             return null;
 1582  0
         if (stateObj instanceof _AttachedListStateWrapper)
 1583  
         {
 1584  0
             List<Object> lst = ((_AttachedListStateWrapper) stateObj).getWrappedStateList();
 1585  0
             List<Object> restoredList = new ArrayList<Object>(lst.size());
 1586  0
             for (Object item : lst)
 1587  
             {
 1588  0
                 restoredList.add(restoreAttachedState(context, item));
 1589  
             }
 1590  0
             return restoredList;
 1591  
         }
 1592  0
         else if (stateObj instanceof _AttachedStateWrapper)
 1593  
         {
 1594  0
             Class<?> clazz = ((_AttachedStateWrapper) stateObj).getClazz();
 1595  
             Object restoredObject;
 1596  
             try
 1597  
             {
 1598  0
                 restoredObject = clazz.newInstance();
 1599  
             }
 1600  0
             catch (InstantiationException e)
 1601  
             {
 1602  0
                 throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName()
 1603  
                         + " (missing no-args constructor?)", e);
 1604  
             }
 1605  0
             catch (IllegalAccessException e)
 1606  
             {
 1607  0
                 throw new RuntimeException(e);
 1608  0
             }
 1609  0
             if (restoredObject instanceof StateHolder)
 1610  
             {
 1611  0
                 _AttachedStateWrapper wrapper = (_AttachedStateWrapper) stateObj;
 1612  0
                 Object wrappedState = wrapper.getWrappedStateObject();
 1613  
 
 1614  0
                 StateHolder holder = (StateHolder) restoredObject;
 1615  0
                 holder.restoreState(context, wrappedState);
 1616  
             }
 1617  0
             return restoredObject;
 1618  
         }
 1619  
         else
 1620  
         {
 1621  0
             return stateObj;
 1622  
         }
 1623  
     }
 1624  
 
 1625  
     /**
 1626  
      * Invoked after the render phase has completed, this method returns an object which can be passed to the
 1627  
      * restoreState of some other instance of UIComponentBase to reset that object's state to the same values as this
 1628  
      * object currently has.
 1629  
      */
 1630  
     public Object saveState(FacesContext context)
 1631  
     {
 1632  0
         if (context == null)
 1633  
         {
 1634  0
             throw new NullPointerException ("context");
 1635  
         }
 1636  
         
 1637  0
         if (initialStateMarked())
 1638  
         {
 1639  
             //Delta
 1640  
             //_id and _clientId was already restored from template
 1641  
             //and never changes during component life.
 1642  0
             Object facesListenersSaved = saveFacesListenersList(context);
 1643  0
             Object behaviorsMapSaved = saveBehaviorsMap(context);
 1644  0
             Object systemEventListenerClassMapSaved = saveSystemEventListenerClassMap(context);
 1645  0
             Object stateHelperSaved = null;
 1646  0
             StateHelper stateHelper = getStateHelper(false);
 1647  0
             if (stateHelper != null)
 1648  
             {
 1649  0
                 stateHelperSaved = stateHelper.saveState(context);
 1650  
             }
 1651  
             
 1652  0
             if (facesListenersSaved == null && stateHelperSaved == null && 
 1653  
                 behaviorsMapSaved == null && systemEventListenerClassMapSaved == null)
 1654  
             {
 1655  0
                 return null;
 1656  
             }
 1657  
             
 1658  0
             return new Object[] {facesListenersSaved, stateHelperSaved, behaviorsMapSaved, systemEventListenerClassMapSaved};
 1659  
         }
 1660  
         else
 1661  
         {
 1662  
             //Full
 1663  0
             Object values[] = new Object[6];
 1664  0
             values[0] = saveFacesListenersList(context);
 1665  0
             StateHelper stateHelper = getStateHelper(false);
 1666  0
             if (stateHelper != null)
 1667  
             {
 1668  0
                 values[1] = stateHelper.saveState(context);
 1669  
             }
 1670  0
             values[2] = saveBehaviorsMap(context);
 1671  0
             values[3] = saveSystemEventListenerClassMap(context);
 1672  0
             values[4] = _id;
 1673  0
             values[5] = _clientId;
 1674  
 
 1675  0
             return values;
 1676  
         }
 1677  
     }
 1678  
 
 1679  
     /**
 1680  
      * Invoked in the "restore view" phase, this initialises this object's members from the values saved previously into
 1681  
      * the provided state object.
 1682  
      * <p>
 1683  
      * 
 1684  
      * @param state
 1685  
      *            is an object previously returned by the saveState method of this class.
 1686  
      */
 1687  
     @SuppressWarnings("unchecked")
 1688  
     public void restoreState(FacesContext context, Object state)
 1689  
     {
 1690  0
         if (context == null)
 1691  
         {
 1692  0
             throw new NullPointerException ("context");
 1693  
         }
 1694  
         
 1695  0
         if (state == null)
 1696  
         {
 1697  
             //Only happens if initialStateMarked return true
 1698  
             
 1699  0
             if (initialStateMarked()) {
 1700  0
                 return;
 1701  
             }
 1702  
             
 1703  0
             throw new NullPointerException ("state");
 1704  
         }
 1705  
         
 1706  0
         Object values[] = (Object[]) state;
 1707  
         
 1708  0
         if ( values.length == 6 && initialStateMarked())
 1709  
         {
 1710  
             //Delta mode is active, but we are restoring a full state.
 1711  
             //we need to clear the initial state, to restore state without
 1712  
             //take into account delta.
 1713  0
             clearInitialState();
 1714  
         }
 1715  
         
 1716  0
         if (values[0] instanceof _AttachedDeltaWrapper)
 1717  
         {
 1718  
             //Delta: check for null is not necessary since _facesListener field
 1719  
             //is only set once and never reset
 1720  
             //if (_facesListeners != null)
 1721  
             //{
 1722  0
                 ((StateHolder)_facesListeners).restoreState(context,
 1723  
                         ((_AttachedDeltaWrapper) values[0]).getWrappedStateObject());
 1724  
             //}
 1725  
         }
 1726  0
         else if (values[0] != null || (values.length == 6))
 1727  
         {
 1728  
             //Full
 1729  0
             _facesListeners = (_DeltaList<FacesListener>)
 1730  
                 restoreAttachedState(context,values[0]);
 1731  
         }
 1732  
         // Note that if values[0] == null && initialStateMarked(),
 1733  
         // means delta is null, not that _facesListeners == null. 
 1734  
         // We can do this here because _facesListeners instance once
 1735  
         // is created is never replaced or set to null.
 1736  
         
 1737  0
         getStateHelper().restoreState(context, values[1]);
 1738  
         
 1739  0
         if (values.length == 6)
 1740  
         {
 1741  
             //Full restore
 1742  0
             restoreFullBehaviorsMap(context, values[2]);
 1743  0
             restoreFullSystemEventListenerClassMap(context, values[3]);
 1744  
         }
 1745  
         else
 1746  
         {
 1747  
             //Delta restore
 1748  0
             restoreDeltaBehaviorsMap(context, values[2]);
 1749  0
             restoreDeltaSystemEventListenerClassMap(context, values[3]);
 1750  
         }
 1751  
         
 1752  0
         if (values.length == 6)
 1753  
         {
 1754  0
             _id = (String) values[4];
 1755  0
             _clientId = (String) values[5];
 1756  
         }
 1757  0
     }
 1758  
     
 1759  
     private Object saveFacesListenersList(FacesContext facesContext)
 1760  
     {
 1761  0
         PartialStateHolder holder = (PartialStateHolder) _facesListeners;
 1762  0
         if (initialStateMarked() && _facesListeners != null && holder.initialStateMarked())
 1763  
         {                
 1764  0
             Object attachedState = holder.saveState(facesContext);
 1765  0
             if (attachedState != null)
 1766  
             {
 1767  0
                 return new _AttachedDeltaWrapper(_facesListeners.getClass(),
 1768  
                         attachedState);
 1769  
             }
 1770  
             //_facesListeners instances once is created never changes, we can return null
 1771  0
             return null;
 1772  
         }
 1773  
         else
 1774  
         {
 1775  0
             return saveAttachedState(facesContext,_facesListeners);
 1776  
         }            
 1777  
     }
 1778  
 
 1779  
     @SuppressWarnings("unchecked")
 1780  
     private void restoreFullBehaviorsMap(FacesContext facesContext, Object stateObj)
 1781  
     {
 1782  0
         if (stateObj != null)
 1783  
         {
 1784  0
             Map<String, Object> stateMap = (Map<String, Object>) stateObj;
 1785  0
             int initCapacity = (stateMap.size() * 4 + 3) / 3;
 1786  0
             _behaviorsMap = new HashMap<String,  List<ClientBehavior> >(initCapacity);
 1787  0
             _unmodifiableBehaviorsMap = null;
 1788  0
             for (Map.Entry<String, Object> entry : stateMap.entrySet())
 1789  
             {
 1790  0
                 _behaviorsMap.put(entry.getKey(), (List<ClientBehavior>) restoreAttachedState(facesContext, entry.getValue()));
 1791  
             }
 1792  0
         }
 1793  
         else
 1794  
         {
 1795  0
             _behaviorsMap = null;
 1796  0
             _unmodifiableBehaviorsMap = null;
 1797  
         }        
 1798  0
     }
 1799  
     
 1800  
     @SuppressWarnings("unchecked")
 1801  
     private void restoreDeltaBehaviorsMap(FacesContext facesContext, Object stateObj)
 1802  
     {
 1803  0
         if (stateObj != null)
 1804  
         {
 1805  0
             _unmodifiableBehaviorsMap = null;
 1806  0
             Map<String, Object> stateMap = (Map<String, Object>) stateObj;
 1807  0
             int initCapacity = (stateMap.size() * 4 + 3) / 3;
 1808  0
             if (_behaviorsMap == null)
 1809  
             {
 1810  0
                 _behaviorsMap = new HashMap<String,  List<ClientBehavior> >(initCapacity);
 1811  
             }
 1812  0
             for (Map.Entry<String, Object> entry : stateMap.entrySet())
 1813  
             {
 1814  0
                 Object savedObject = entry.getValue(); 
 1815  0
                 if (savedObject instanceof _AttachedDeltaWrapper)
 1816  
                 {
 1817  0
                     StateHolder holderList = (StateHolder) _behaviorsMap.get(entry.getKey());
 1818  0
                     holderList.restoreState(facesContext, ((_AttachedDeltaWrapper) savedObject).getWrappedStateObject());
 1819  0
                 }
 1820  
                 else
 1821  
                 {
 1822  0
                     _behaviorsMap.put(entry.getKey(), (List<ClientBehavior>) restoreAttachedState(facesContext, savedObject));
 1823  
                 }
 1824  0
             }
 1825  
         }
 1826  0
     }
 1827  
     
 1828  
     private Object saveBehaviorsMap(FacesContext facesContext)
 1829  
     {
 1830  0
         if (_behaviorsMap != null)
 1831  
         {
 1832  0
             if (initialStateMarked())
 1833  
             {
 1834  0
                 HashMap<String, Object> stateMap = new HashMap<String, Object>(_behaviorsMap.size(), 1);
 1835  0
                 boolean nullDelta = true;
 1836  0
                 for (Map.Entry<String, List<ClientBehavior> > entry : _behaviorsMap.entrySet())
 1837  
                 {
 1838  
                     // The list is always an instance of _DeltaList so we can cast to
 1839  
                     // PartialStateHolder 
 1840  0
                     PartialStateHolder holder = (PartialStateHolder) entry.getValue();
 1841  0
                     if (holder.initialStateMarked())
 1842  
                     {
 1843  0
                         Object attachedState = holder.saveState(facesContext);
 1844  0
                         if (attachedState != null)
 1845  
                         {
 1846  0
                             stateMap.put(entry.getKey(), new _AttachedDeltaWrapper(_behaviorsMap.getClass(),
 1847  
                                     attachedState));
 1848  0
                             nullDelta = false;
 1849  
                         }
 1850  0
                     }
 1851  
                     else
 1852  
                     {
 1853  0
                         stateMap.put(entry.getKey(), saveAttachedState(facesContext, holder));
 1854  0
                         nullDelta = false;
 1855  
                     }
 1856  0
                 }
 1857  0
                 if (nullDelta)
 1858  
                 {
 1859  0
                     return null;
 1860  
                 }
 1861  0
                 return stateMap;
 1862  
             }
 1863  
             else
 1864  
             {
 1865  
                 //Save it in the traditional way
 1866  0
                 HashMap<String, Object> stateMap = 
 1867  
                     new HashMap<String, Object>(_behaviorsMap.size(), 1);
 1868  0
                 for (Map.Entry<String, List<ClientBehavior> > entry : _behaviorsMap.entrySet())
 1869  
                 {
 1870  0
                     stateMap.put(entry.getKey(), saveAttachedState(facesContext, entry.getValue()));
 1871  
                 }
 1872  0
                 return stateMap;
 1873  
             }
 1874  
         }
 1875  
         else
 1876  
         {
 1877  0
             return null;
 1878  
         }
 1879  
     }
 1880  
     
 1881  
     @SuppressWarnings("unchecked")
 1882  
     private void restoreFullSystemEventListenerClassMap(FacesContext facesContext, Object stateObj)
 1883  
     {
 1884  0
         if (stateObj != null)
 1885  
         {
 1886  0
             Map<Class<? extends SystemEvent>, Object> stateMap = (Map<Class<? extends SystemEvent>, Object>) stateObj;
 1887  0
             int initCapacity = (stateMap.size() * 4 + 3) / 3;
 1888  0
             _systemEventListenerClassMap = new HashMap<Class<? extends SystemEvent>, List<SystemEventListener>>(initCapacity);
 1889  0
             for (Map.Entry<Class<? extends SystemEvent>, Object> entry : stateMap.entrySet())
 1890  
             {
 1891  0
                 _systemEventListenerClassMap.put(entry.getKey(), (List<SystemEventListener>) restoreAttachedState(facesContext, entry.getValue()));
 1892  
             }
 1893  0
         }
 1894  
         else
 1895  
         {
 1896  0
             _systemEventListenerClassMap = null;
 1897  
         }        
 1898  0
     }
 1899  
     
 1900  
     @SuppressWarnings("unchecked")
 1901  
     private void restoreDeltaSystemEventListenerClassMap(FacesContext facesContext, Object stateObj)
 1902  
     {
 1903  0
         if (stateObj != null)
 1904  
         {
 1905  0
             Map<Class<? extends SystemEvent>, Object> stateMap = (Map<Class<? extends SystemEvent>, Object>) stateObj;
 1906  0
             int initCapacity = (stateMap.size() * 4 + 3) / 3;
 1907  0
             if (_systemEventListenerClassMap == null)
 1908  
             {
 1909  0
                 _systemEventListenerClassMap = new HashMap<Class<? extends SystemEvent>, List<SystemEventListener>>(initCapacity);
 1910  
             }
 1911  0
             for (Map.Entry<Class<? extends SystemEvent>, Object> entry : stateMap.entrySet())
 1912  
             {
 1913  0
                 Object savedObject = entry.getValue(); 
 1914  0
                 if (savedObject instanceof _AttachedDeltaWrapper)
 1915  
                 {
 1916  0
                     StateHolder holderList = (StateHolder) _systemEventListenerClassMap.get(entry.getKey());
 1917  0
                     holderList.restoreState(facesContext, ((_AttachedDeltaWrapper) savedObject).getWrappedStateObject());
 1918  0
                 }
 1919  
                 else
 1920  
                 {
 1921  0
                     _systemEventListenerClassMap.put(entry.getKey(), (List<SystemEventListener>) restoreAttachedState(facesContext, savedObject));
 1922  
                 }
 1923  0
             }
 1924  
         }
 1925  0
     }
 1926  
     
 1927  
     private Object saveSystemEventListenerClassMap(FacesContext facesContext)
 1928  
     {
 1929  0
         if (_systemEventListenerClassMap != null)
 1930  
         {
 1931  0
             if (initialStateMarked())
 1932  
             {
 1933  0
                 HashMap<Class<? extends SystemEvent>, Object> stateMap = new HashMap<Class<? extends SystemEvent>, Object>(_systemEventListenerClassMap.size(), 1);
 1934  0
                 boolean nullDelta = true;
 1935  0
                 for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener> > entry : _systemEventListenerClassMap.entrySet())
 1936  
                 {
 1937  
                     // The list is always an instance of _DeltaList so we can cast to
 1938  
                     // PartialStateHolder 
 1939  0
                     PartialStateHolder holder = (PartialStateHolder) entry.getValue();
 1940  0
                     if (holder.initialStateMarked())
 1941  
                     {
 1942  0
                         Object attachedState = holder.saveState(facesContext);
 1943  0
                         if (attachedState != null)
 1944  
                         {
 1945  0
                             stateMap.put(entry.getKey(), new _AttachedDeltaWrapper(_systemEventListenerClassMap.getClass(),
 1946  
                                     attachedState));
 1947  0
                             nullDelta = false;
 1948  
                         }
 1949  0
                     }
 1950  
                     else
 1951  
                     {
 1952  0
                         stateMap.put(entry.getKey(), saveAttachedState(facesContext, holder));
 1953  0
                         nullDelta = false;
 1954  
                     }
 1955  0
                 }
 1956  0
                 if (nullDelta)
 1957  
                 {
 1958  0
                     return null;
 1959  
                 }
 1960  0
                 return stateMap;
 1961  
             }
 1962  
             else
 1963  
             {
 1964  
                 //Save it in the traditional way
 1965  0
                 HashMap<Class<? extends SystemEvent>, Object> stateMap = 
 1966  
                     new HashMap<Class<? extends SystemEvent>, Object>(_systemEventListenerClassMap.size(), 1);
 1967  0
                 for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener> > entry : _systemEventListenerClassMap.entrySet())
 1968  
                 {
 1969  0
                     stateMap.put(entry.getKey(), saveAttachedState(facesContext, entry.getValue()));
 1970  
                 }
 1971  0
                 return stateMap;
 1972  
             }
 1973  
         }
 1974  
         else
 1975  
         {
 1976  0
             return null;
 1977  
         }
 1978  
     }
 1979  
     
 1980  
     /*
 1981  
     private Object saveBindings(FacesContext context)
 1982  
     {
 1983  
         if (bindings != null)
 1984  
         {
 1985  
             HashMap<String, Object> stateMap = new HashMap<String, Object>(bindings.size(), 1);
 1986  
             for (Iterator<Entry<String, ValueExpression>> it = bindings.entrySet().iterator(); it.hasNext();)
 1987  
             {
 1988  
                 Entry<String, ValueExpression> entry = it.next();
 1989  
                 stateMap.put(entry.getKey(), saveAttachedState(context, entry.getValue()));
 1990  
             }
 1991  
             return stateMap;
 1992  
         }
 1993  
 
 1994  
         return null;
 1995  
     }
 1996  
 
 1997  
     @SuppressWarnings("unchecked")
 1998  
     private void restoreValueExpressionMap(FacesContext context, Object stateObj)
 1999  
     {
 2000  
         if (stateObj != null)
 2001  
         {
 2002  
             Map<String, Object> stateMap = (Map<String, Object>) stateObj;
 2003  
             int initCapacity = (stateMap.size() * 4 + 3) / 3;
 2004  
             bindings = new HashMap<String, ValueExpression>(initCapacity);
 2005  
             for (Map.Entry<String, Object> entry : stateMap.entrySet())
 2006  
             {
 2007  
                 bindings.put(entry.getKey(), (ValueExpression) restoreAttachedState(context, entry.getValue()));
 2008  
             }
 2009  
         }
 2010  
         else
 2011  
         {
 2012  
             bindings = null;
 2013  
         }
 2014  
     }*/
 2015  
 
 2016  
     /**
 2017  
      * @param string
 2018  
      *            the component id, that should be a vaild one.
 2019  
      */
 2020  
     private void isIdValid(String string)
 2021  
     {
 2022  
 
 2023  
         // is there any component identifier ?
 2024  0
         if (string == null)
 2025  0
             return;
 2026  
 
 2027  
         // Component identifiers must obey the following syntax restrictions:
 2028  
         // 1. Must not be a zero-length String.
 2029  0
         if (string.length() == 0)
 2030  
         {
 2031  0
             throw new IllegalArgumentException("component identifier must not be a zero-length String");
 2032  
         }
 2033  
 
 2034  
         // If new id is the same as old it must be valid
 2035  0
         if (string.equals(_id))
 2036  
         {
 2037  0
             return;
 2038  
         }
 2039  
 
 2040  
         // 2. First character must be a letter or an underscore ('_').
 2041  0
         if (!Character.isLetter(string.charAt(0)) && string.charAt(0) != '_')
 2042  
         {
 2043  0
             throw new IllegalArgumentException(
 2044  
                                                "component identifier's first character must be a letter or an underscore ('_')! But it is \""
 2045  
                                                        + string.charAt(0) + "\"");
 2046  
         }
 2047  0
         for (int i = 1; i < string.length(); i++)
 2048  
         {
 2049  0
             char c = string.charAt(i);
 2050  
             // 3. Subsequent characters must be a letter, a digit, an underscore ('_'), or a dash ('-').
 2051  0
             if (!Character.isLetterOrDigit(c) && c != '-' && c != '_')
 2052  
             {
 2053  0
                 throw new IllegalArgumentException(
 2054  
                                                    "Subsequent characters of component identifier must be a letter, a digit, an underscore ('_'), or a dash ('-')! But component identifier contains \""
 2055  
                                                            + c + "\"");
 2056  
             }
 2057  
         }
 2058  0
     }
 2059  
 
 2060  
     private boolean _isPhaseExecutable(FacesContext context)
 2061  
     {
 2062  0
         if (context == null)
 2063  
         {
 2064  0
             throw new NullPointerException("context");
 2065  
         }
 2066  
 
 2067  
         // If the rendered property of this UIComponent is false, skip further processing.
 2068  0
         return isRendered();
 2069  
     }
 2070  
 
 2071  
     boolean isCachedFacesContext()
 2072  
     {
 2073  0
         return _facesContext != null;
 2074  
     }
 2075  
     
 2076  
     void setCachedFacesContext(FacesContext facesContext)
 2077  
     {
 2078  0
         _facesContext = facesContext;
 2079  0
     }
 2080  
     
 2081  
     <T> T getExpressionValue(String attribute, T explizitValue, T defaultValueIfExpressionNull)
 2082  
     {
 2083  0
         return _ComponentUtils.getExpressionValue(this, attribute, explizitValue, defaultValueIfExpressionNull);
 2084  
     }
 2085  
 
 2086  
 /**
 2087  
      * <p>
 2088  
      * This gets a single threadlocal shared stringbuilder instance, each time you call
 2089  
      * __getSharedStringBuilder it sets the length of the stringBuilder instance to 0.
 2090  
      * </p><p>
 2091  
      * This allows you to use the same StringBuilder instance over and over.
 2092  
      * You must call toString on the instance before calling __getSharedStringBuilder again.
 2093  
      * </p>
 2094  
      * Example that works
 2095  
      * <pre><code>
 2096  
      * StringBuilder sb1 = __getSharedStringBuilder();
 2097  
      * sb1.append(a).append(b);
 2098  
      * String c = sb1.toString();
 2099  
      *
 2100  
      * StringBuilder sb2 = __getSharedStringBuilder();
 2101  
      * sb2.append(b).append(a);
 2102  
      * String d = sb2.toString();
 2103  
      * </code></pre>
 2104  
      * <br><br>
 2105  
      * Example that doesn't work, you must call toString on sb1 before
 2106  
      * calling __getSharedStringBuilder again.
 2107  
      * <pre><code>
 2108  
      * StringBuilder sb1 = __getSharedStringBuilder();
 2109  
      * StringBuilder sb2 = __getSharedStringBuilder();
 2110  
      *
 2111  
      * sb1.append(a).append(b);
 2112  
      * String c = sb1.toString();
 2113  
      *
 2114  
      * sb2.append(b).append(a);
 2115  
      * String d = sb2.toString();
 2116  
      * </code></pre>
 2117  
      *
 2118  
      */
 2119  
     static StringBuilder __getSharedStringBuilder()
 2120  
     {
 2121  0
         StringBuilder sb = _STRING_BUILDER.get();
 2122  
 
 2123  0
         if (sb == null)
 2124  
         {
 2125  0
             sb = new StringBuilder();
 2126  0
             _STRING_BUILDER.set(sb);
 2127  
         }
 2128  
 
 2129  
         // clear out the stringBuilder by setting the length to 0
 2130  0
         sb.setLength(0);
 2131  
 
 2132  0
         return sb;
 2133  
     }
 2134  
 
 2135  
     // ------------------ GENERATED CODE BEGIN (do not modify!) --------------------
 2136  
 
 2137  0
     private static final Boolean DEFAULT_RENDERED = Boolean.TRUE;
 2138  
 
 2139  
     @Override
 2140  
     public void setRendered(boolean rendered)
 2141  
     {
 2142  0
         getStateHelper().put(PropertyKeys.rendered, rendered ); 
 2143  0
     }
 2144  
 
 2145  
     @Override
 2146  
     public void setRendererType(String rendererType)
 2147  
     {
 2148  0
         getStateHelper().put(PropertyKeys.rendererType, rendererType ); 
 2149  0
     }
 2150  
 
 2151  
     // ------------------ GENERATED CODE END ---------------------------------------
 2152  
 
 2153  
     private Map<String, List<ClientBehavior>> wrapBehaviorsMap()
 2154  
     {
 2155  0
         if (_unmodifiableBehaviorsMap == null)
 2156  
         {
 2157  0
             _unmodifiableBehaviorsMap = Collections.unmodifiableMap(_behaviorsMap); 
 2158  
         }
 2159  0
         return _unmodifiableBehaviorsMap; 
 2160  
     }
 2161  
 }