/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package javax.faces.component;

import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;

import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.behavior.Behavior;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.BehaviorEvent;
import javax.faces.event.FacesEvent;
import javax.faces.event.FacesListener;
import javax.faces.event.PostAddToViewEvent;
import javax.faces.event.PostValidateEvent;
import javax.faces.event.PreRemoveFromViewEvent;
import javax.faces.event.PreRenderComponentEvent;
import javax.faces.event.PreValidateEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
import javax.faces.render.RenderKit;
import javax.faces.render.Renderer;
import javax.faces.view.Location;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.faces.event.PhaseId;


/**
 * Standard implementation of the UIComponent base class; all standard JSF components extend this class.
 * <p>
 * <i>Disclaimer</i>: The official definition for the behaviour of this class is the JSF 1.1 specification but for legal
 * reasons the specification cannot be replicated here. Any javadoc here therefore describes the current implementation
 * rather than the spec, though this class has been verified as correctly implementing the spec.
 * 
 * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a> for
 * more.
 */
@JSFComponent(type = "javax.faces.ComponentBase", family = "javax.faces.ComponentBase",
              desc = "base component when all components must inherit",
              tagClass = "javax.faces.webapp.UIComponentELTag", configExcluded = true)
@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")
public abstract class UIComponentBase extends UIComponent
{
    private static Logger log = Logger.getLogger(UIComponentBase.class.getName());

    private static final String _STRING_BUILDER_KEY
            = "javax.faces.component.UIComponentBase.SHARED_STRING_BUILDER";

    static final int RESET_MODE_OFF = 0;
    static final int RESET_MODE_SOFT = 1;
    static final int RESET_MODE_HARD = 2;

    private _ComponentAttributesMap _attributesMap = null;
    private _PassThroughAttributesMap _passthroughAttributesMap = null;
    private List<UIComponent> _childrenList = null;
    private Map<String, UIComponent> _facetMap = null;
    private _DeltaList<FacesListener> _facesListeners = null;
    private String _clientId = null;
    private String _id = null;
    private UIComponent _parent = null;
    private boolean _transient = false;

    private String _rendererType;
    private String _markCreated;
    private String _facetName;
    
    private int _capabilities = 0;
    private final static int FLAG_IS_RENDERER_TYPE_SET = 1;
    private final static int FLAG_ADDED_BY_HANDLER = 2;
    private final static int FLAG_FACET_CREATED_UIPANEL = 4;
    private final static int FLAG_PASSTHROUGH_ATTRIBUTE_MAP_SET = 8;

    /**
     * This map holds ClientBehavior instances.
     * 
     *  Note that BehaviorBase implements PartialStateHolder, so this class 
     *  should deal with that fact on clearInitialState() and 
     *  markInitialState() methods.
     * 
     *  Also, the map used by this instance is not set from outside this class.
     *  
     *  Note it is possible (but maybe not expected/valid) to manipulate 
     *  the values of the map(the list) but not put instances on the map 
     *  directly, because ClientBehaviorHolder.getClientBehaviors says that 
     *  this method should return a non null unmodificable map.
     *  
     */
    private Map<String, List<ClientBehavior>> _behaviorsMap = null;
    private transient Map<String, List<ClientBehavior>> _unmodifiableBehaviorsMap = null;
    
    private transient FacesContext _facesContext;
    private transient Boolean _cachedIsRendered;
    private transient Renderer _cachedRenderer;
    
    public UIComponentBase()
    {
    }

    /**
     * Set an identifier for this component which is unique within the scope of the nearest ancestor NamingContainer
     * component. The id is not necessarily unique across all components in the current view.
     * <p>
     * The id must start with an underscore if it is generated by the JSF framework, and must <i>not</i> start with an
     * underscore if it has been specified by the user (eg in a JSP tag).
     * <p>
     * The first character of the id must be an underscore or letter. Following characters may be letters, digits,
     * underscores or dashes.
     * <p>
     * Null is allowed as a parameter, and will reset the id to null.
     * <p>
     * The clientId of this component is reset by this method; see getClientId for more info.
     * 
     * @throws IllegalArgumentException
     *             if the id is not valid.
     */
    @Override
    public void setId(String id)
    {
        isIdValid(id);
        _id = id;
        _clientId = null;
    }

    /**
     * <p>Set the parent <code>UIComponent</code> of this
     * <code>UIComponent</code>.</p>
     * 
     * @param parent The new parent, or <code>null</code> for the root node
     *  of a component tree
     */
    @Override
    public void setParent(UIComponent parent)
    {
        // removing kids OR this is UIViewRoot
        if (parent == null)
        {
            // not UIViewRoot...
            if (_parent != null && _parent.isInView())
            {
                // trigger the "remove event" lifecycle
                // and call setInView(false) for all children/facets
                // doing this => recursive
                FacesContext facesContext = getFacesContext();
                if (facesContext.isProcessingEvents())
                {
                    _publishPreRemoveFromViewEvent(facesContext, this);
                }
                else
                {
                    _updateInView(this, false);
                }
            }
            _parent = null;
        }
        else
        {
            _parent = parent;
            if (parent.isInView())
            {
                // trigger the ADD_EVENT and call setInView(true)
                // recursive for all kids/facets...
                // Application.publishEvent(java.lang.Class, java.lang.Object)  must be called, passing 
                // PostAddToViewEvent.class as the first argument and the newly added component as the second 
                // argument.
                FacesContext facesContext = parent.isCachedFacesContext() ?
                    parent.getFacesContext() : getFacesContext();
                if (facesContext.isProcessingEvents())
                {
                    _publishPostAddToViewEvent(facesContext, this);
                }
                else
                {
                    _updateInView(this, true);
                }
            }
        }
    }

    
    /**
     * Publish PostAddToViewEvent to the component and all facets and children.
     * 
     * @param context
     * @param component
     */
    private static void _publishPostAddToViewEvent(FacesContext context, UIComponent component)
    {
        component.setInView(true);
        context.getApplication().publishEvent(context, PostAddToViewEvent.class, component.getClass(), component);
        
        if (component.getChildCount() > 0)
        {
            // PostAddToViewEvent could cause component relocation
            // (h:outputScript, h:outputStylesheet, composite:insertChildren, composite:insertFacet)
            // so we need to check if the component was relocated or not
          
            List<UIComponent> children = component.getChildren();
            for (int i = 0; i < children.size(); i++)
            {
                // spin on same index while component removed/replaced
                // to prevent skipping components:
                while (true)
                {
                    UIComponent child = children.get(i);
                    child.pushComponentToEL(context, child);
                    try
                    {
                        _publishPostAddToViewEvent(context, child);
                    }
                    finally
                    {
                        child.popComponentFromEL(context);
                    }
                    if (i < children.size() && children.get(i) != child)
                    {
                        continue;
                    }
                    break;
                }
            }
        }
        if (component.getFacetCount() > 0)
        {
            for (UIComponent child : component.getFacets().values())
            {
                child.pushComponentToEL(context, child);
                try
                {
                    _publishPostAddToViewEvent(context, child);
                }
                finally
                {
                    child.popComponentFromEL(context);
                }
            }
        }        
    }
    
    /**
     * Publish PreRemoveFromViewEvent to the component and all facets and children.
     * 
     * @param context
     * @param component
     */
    private static void _publishPreRemoveFromViewEvent(FacesContext context, UIComponent component)
    {
        component.setInView(false);
        context.getApplication().publishEvent(context, PreRemoveFromViewEvent.class, component.getClass(), component);
        
        if (component.getChildCount() > 0)
        {
            for (int i = 0, childCount = component.getChildCount(); i < childCount; i++)
            {
                UIComponent child = component.getChildren().get(i);
                _publishPreRemoveFromViewEvent(context, child);
            }
        }
        if (component.getFacetCount() > 0)
        {
            for (UIComponent child : component.getFacets().values())
            {
                _publishPreRemoveFromViewEvent(context, child);
            }
        }        
    }    
    
    private static void _updateInView(UIComponent component, boolean isInView)
    {
        component.setInView(isInView);
        
        if (component.getChildCount() > 0)
        {
            for (int i = 0, childCount = component.getChildCount(); i < childCount; i++)
            {
                UIComponent child = component.getChildren().get(i);
                _updateInView(child, isInView);
            }
        }
        if (component.getFacetCount() > 0)
        {
            for (UIComponent child : component.getFacets().values())
            {
                _updateInView(child, isInView);
            }
        }        
    }  
    
    /**
     * 
     * @param eventName
     * @param behavior
     * 
     * @since 2.0
     */
    public void addClientBehavior(String eventName, ClientBehavior behavior)
    {
        Collection<String> eventNames = getEventNames();
        if (eventNames == null)
        {
            throw new IllegalStateException("Attempting to add a Behavior to a component, "
                    + "that does not support any event types. getEventTypes() must return a non-null Set.");
        }

        if (eventNames.contains(eventName))
        {
            if (_behaviorsMap == null)
            {
                _behaviorsMap = new HashMap<>(5, 1f);
            }

            // Normally have client only 1 client behaviour per event name, so size 2 must be sufficient:
            List<ClientBehavior> behaviorsForEvent = _behaviorsMap.computeIfAbsent(eventName,
                    k -> new _DeltaList<>(2));

            behaviorsForEvent.add(behavior);
            _unmodifiableBehaviorsMap = null;
        }
    }

    /**
     * Invoke any listeners attached to this object which are listening for an event whose type matches the specified
     * event's runtime type.
     * <p>
     * This method does not propagate the event up to parent components, ie listeners attached to parent components
     * don't automatically get called.
     * <p>
     * If any of the listeners throws AbortProcessingException then that exception will prevent any further listener
     * callbacks from occurring, and the exception propagates out of this method without alteration.
     * <p>
     * ActionEvent events are typically queued by the renderer associated with this component in its decode method;
     * ValueChangeEvent events by the component's validate method. In either case the event's source property references
     * a component. At some later time the UIViewRoot component iterates over its queued events and invokes the
     * broadcast method on each event's source object.
     * 
     * @param event
     *            must not be null.
     */
    @Override
    public void broadcast(FacesEvent event) throws AbortProcessingException
    {
        if (event == null)
        {
            throw new NullPointerException("event");
        }
        
        if (event instanceof BehaviorEvent && event.getComponent() == this)
        {
            Behavior behavior = ((BehaviorEvent) event).getBehavior();
            behavior.broadcast((BehaviorEvent) event);
        }

        if (_facesListeners == null)
        {
            return;
        }
        // perf: _facesListeners is RandomAccess instance (javax.faces.component._DeltaList)
        for (int i = 0, size = _facesListeners.size(); i < size; i++)
        {
            FacesListener facesListener = _facesListeners.get(i);
            if (event.isAppropriateListener(facesListener))
            {
                event.processListener(facesListener);
            }
        }
    }
    
    @Override
    public void clearInitialState()
    {
        super.clearInitialState();
        if (_facesListeners != null)
        {
            _facesListeners.clearInitialState();
        }
        if (_behaviorsMap != null)
        {
            for (Map.Entry<String, List<ClientBehavior>> entry : _behaviorsMap.entrySet())
            {
                ((PartialStateHolder) entry.getValue()).clearInitialState();
            }
        }
        if (_systemEventListenerClassMap != null)
        {
            for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener>> entry : 
                _systemEventListenerClassMap.entrySet())
            {
                ((PartialStateHolder) entry.getValue()).clearInitialState();
            }
        }

        _capabilities &= ~(FLAG_IS_RENDERER_TYPE_SET);
    }

    /**
     * Check the submitted form parameters for data associated with this component. This default implementation
     * delegates to this component's renderer if there is one, and otherwise ignores the call.
     */
    @Override
    public void decode(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }
        
        setCachedRenderer(null);
        Renderer renderer = getRenderer(context);
        if (renderer != null)
        {
            setCachedRenderer(renderer);
            try
            {
                renderer.decode(context, this);
            }
            finally
            {
                setCachedRenderer(null);
            }
        }

    }

    @Override
    public void encodeAll(FacesContext context) throws IOException
    {
        if (context == null)
        {
            throw new NullPointerException();
        }

        pushComponentToEL(context, this);
        try
        {
            setCachedIsRendered(null);
            boolean rendered;
            try
            {
                setCachedFacesContext(context);
                rendered = isRendered();
            }
            finally
            {
                setCachedFacesContext(null);
            } 
            setCachedIsRendered(rendered);
            if (!rendered)
            {
                setCachedIsRendered(null);
                return;
            }
            setCachedRenderer(null);
            setCachedRenderer(getRenderer(context));
        }
        finally
        {
            popComponentFromEL(context);
        }

        try
        {
            this.encodeBegin(context);

            // rendering children
            boolean rendersChildren;
            try
            {
                setCachedFacesContext(context);
                rendersChildren = this.getRendersChildren();
            }
            finally
            {
                setCachedFacesContext(null);
            }
            if (rendersChildren)
            {
                this.encodeChildren(context);
            } // let children render itself
            else
            {
                if (this.getChildCount() > 0)
                {
                    for (int i = 0; i < this.getChildCount(); i++)
                    {
                        UIComponent comp = this.getChildren().get(i);
                        comp.encodeAll(context);
                    }
                }
            }
            this.encodeEnd(context);
        }
        finally
        {
            setCachedIsRendered(null);
            setCachedRenderer(null);
        }
    }

    @Override
    public void encodeBegin(FacesContext context) throws IOException
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }

        try
        {
            setCachedFacesContext(context);
            // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
            pushComponentToEL(context, this);
    
            if (isRendered())
            {
                // If our rendered property is true, render the beginning of the current state of this
                // UIComponent to the response contained in the specified FacesContext.
    
                // Call Application.publishEvent(java.lang.Class, java.lang.Object), passing BeforeRenderEvent.class as
                // the first argument and the component instance to be rendered as the second argument.
    
                // The main issue we have here is that the listeners are normally just registered
                // to UIComponent, how do we deal with inherited ones?
                // We have to ask the EG
                context.getApplication().publishEvent(context,  PreRenderComponentEvent.class, UIComponent.class, this);
    
                Renderer renderer = getRenderer(context);
                if (renderer != null)
                {
                    // If a Renderer is associated with this UIComponent, the actual encoding will be delegated to
                    // Renderer.encodeBegin(FacesContext, UIComponent).
                    renderer.encodeBegin(context, this);
                }
            }
        }
        finally
        {
            setCachedFacesContext(null);
        }
    }

    @Override
    public void encodeChildren(FacesContext context) throws IOException
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }

        boolean isCachedFacesContext = isCachedFacesContext();
        try
        {
            if (!isCachedFacesContext)
            {
                setCachedFacesContext(context);
            }
            if (isRendered())
            {
                // If our rendered property is true, render the child UIComponents of this UIComponent.
    
                Renderer renderer = getRenderer(context);
                if (renderer == null)
                {
                    // If no Renderer is associated with this UIComponent, iterate over each of the children of this
                    // component and call UIComponent.encodeAll(javax.faces.context.FacesContext).
                    if (getChildCount() > 0)
                    {
                        for (int i = 0, childCount = getChildCount(); i < childCount; i++)
                        {
                            UIComponent child = getChildren().get(i);
                            child.encodeAll(context);
                        }
                    }
                }
                else
                {
                    // If a Renderer is associated with this UIComponent, the actual encoding will be delegated to
                    // Renderer.encodeChildren(FacesContext, UIComponent).
                    renderer.encodeChildren(context, this);
                }
            }
        }
        finally
        {
            if (!isCachedFacesContext)
            {
                setCachedFacesContext(null);
            }
        }
    }

    @Override
    public void encodeEnd(FacesContext context) throws IOException
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }
        try
        {
            setCachedFacesContext(context);
            if (isRendered())
            {
                // If our rendered property is true, render the ending of the current state of this UIComponent.
                Renderer renderer = getRenderer(context);
                if (renderer != null)
                {
                    // If a Renderer is associated with this UIComponent, the actual encoding will be delegated to
                    // Renderer.encodeEnd(FacesContext, UIComponent).
                    renderer.encodeEnd(context, this);
                }
            }
        }
        finally
        {
            // Call UIComponent.popComponentFromEL(javax.faces.context.FacesContext). before returning regardless
            // of the value of the rendered property.
            popComponentFromEL(context);
            setCachedFacesContext(null);
        }
    }
    
    /**
     * Standard method for finding other components by id, inherited by most UIComponent objects.
     * <p>
     * The lookup is performed in a manner similar to finding a file in a filesystem; there is a "base" at which to
     * start, and the id can be for something in the "local directory", or can include a relative path. Here,
     * NamingContainer components fill the role of directories, and ":" is the "path separator". Note, however, that
     * although components have a strict parent/child hierarchy, component ids are only prefixed ("namespaced") with the
     * id of their parent when the parent is a NamingContainer.
     * <p>
     * The base node at which the search starts is determined as follows:
     * <ul>
     * <li>When expr starts with ':', the search starts with the root component of the tree that this component is in
     * (ie the ancestor whose parent is null).
     * <li>Otherwise, if this component is a NamingContainer then the search starts with this component.
     * <li>Otherwise, the search starts from the nearest ancestor NamingContainer (or the root component if there is no
     * NamingContainer ancestor).
     * </ul>
     * 
     * @param expr
     *            is of form "id1:id2:id3".
     * @return UIComponent or null if no component with the specified id is found.
     */

    @Override
    public UIComponent findComponent(String expr)
    {
        if (expr == null)
        {
            throw new NullPointerException("expr");
        }
        if (expr.length() == 0)
        {
            return null;
        }

        char separatorChar = getFacesContext().getNamingContainerSeparatorChar();
        UIComponent findBase;
        if (expr.charAt(0) == separatorChar)
        {
            findBase = _ComponentUtils.getRootComponent(this);
            expr = expr.substring(1);
        }
        else
        {
            if (this instanceof NamingContainer)
            {
                findBase = this;
            }
            else
            {
                findBase = _ComponentUtils.findParentNamingContainer(this, true /* root if not found */);
            }
        }

        int separator = expr.indexOf(separatorChar);
        if (separator == -1)
        {
            return _ComponentUtils.findComponent(findBase, expr, separatorChar);
        }

        String id = expr.substring(0, separator);
        findBase = _ComponentUtils.findComponent(findBase, id, separatorChar);
        if (findBase == null)
        {
            return null;
        }

        if (!(findBase instanceof NamingContainer))
        {
            throw new IllegalArgumentException("Intermediate identifier " + id + " in search expression " + expr
                    + " identifies a UIComponent that is not a NamingContainer");
        }

        return findBase.findComponent(expr.substring(separator + 1));

    }

    /**
     * Get a map through which all the UIComponent's properties, value-bindings and non-property attributes can be read
     * and written.
     * <p>
     * When writing to the returned map:
     * <ul>
     * <li>If this component has an explicit property for the specified key then the setter method is called. An
     * IllegalArgumentException is thrown if the property is read-only. If the property is readable then the old value
     * is returned, otherwise null is returned.
     * <li>Otherwise the key/value pair is stored in a map associated with the component.
     * </ul>
     * Note that value-bindings are <i>not</i> written by put calls to this map. Writing to the attributes map using a
     * key for which a value-binding exists will just store the value in the attributes map rather than evaluating the
     * binding, effectively "hiding" the value-binding from later attributes.get calls. Setter methods on components
     * commonly do <i>not</i> evaluate a binding of the same name; they just store the provided value directly on the
     * component.
     * <p>
     * When reading from the returned map:
     * <ul>
     * <li>If this component has an explicit property for the specified key then the getter method is called. If the
     * property exists, but is read-only (ie only a setter method is defined) then an IllegalArgumentException is
     * thrown.
     * <li>If the attribute map associated with the component has an entry with the specified key, then that is
     * returned.
     * <li>If this component has a value-binding for the specified key, then the value-binding is evaluated to fetch the
     * value.
     * <li>Otherwise, null is returned.
     * </ul>
     * Note that components commonly define getter methods such that they evaluate a value-binding of the same name if
     * there isn't yet a local property.
     * <p>
     * Assigning values to the map which are not explicit properties on the underlying component can be used to "tunnel"
     * attributes from the JSP tag (or view-specific equivalent) to the associated renderer without modifying the
     * component itself.
     * <p>
     * Any value-bindings and non-property attributes stored in this map are automatically serialized along with the
     * component when the view is serialized.
     */
    @Override
    public Map<String, Object> getAttributes()
    {
        if (_attributesMap == null)
        {
            _attributesMap = new _ComponentAttributesMap(this);
        }

        return _attributesMap;
    }

    @Override
    public Map<String, Object> getPassThroughAttributes(boolean create)
    {
        // Take into account the param "create" in MyFaces case does not have
        // sense at all
        if (_passthroughAttributesMap == null)
        {
            if (!create)
            {
                if ((_capabilities & FLAG_PASSTHROUGH_ATTRIBUTE_MAP_SET) != 0)
                {
                    // Was already created, return wrapper
                    _passthroughAttributesMap = new _PassThroughAttributesMap(this);
                }
            }
            else
            {
                _passthroughAttributesMap = new _PassThroughAttributesMap(this);
                _capabilities |= FLAG_PASSTHROUGH_ATTRIBUTE_MAP_SET;
            }
        }
        return _passthroughAttributesMap;
    }

    /**
     * Return the number of direct child components this component has.
     * <p>
     * Identical to getChildren().size() except that when this component has no children this method will not force an
     * empty list to be created.
     */
    @Override
    public int getChildCount()
    {
        return _childrenList == null ? 0 : _childrenList.size();
    }

    /**
     * Return a list of the UIComponent objects which are direct children of this component.
     * <p>
     * The list object returned has some non-standard behaviour:
     * <ul>
     * <li>The list is type-checked; only UIComponent objects can be added.
     * <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
     * exception is thrown. However multiple components with a null id may be added.
     * <li>The component's parent property is set to this component. If the component already had a parent, then the
     * component is first removed from its original parent's child list.
     * </ul>
     */
    @Override
    public List<UIComponent> getChildren()
    {
        if (_childrenList == null)
        {
            _childrenList = new _ComponentChildrenList(this);
        }
        return _childrenList;
    }
    
    /**
     * 
     * @return
     * 
     * @since 2.0
     */
    public Map<String,List<ClientBehavior>> getClientBehaviors()
    {
        if(_behaviorsMap == null)
        {
            return Collections.emptyMap();
        }

        return wrapBehaviorsMap();
    }

    /**
     * Get a string which can be output to the response which uniquely identifies this UIComponent within the current
     * view.
     * <p>
     * The component should have an id attribute already assigned to it; however if the id property is currently null
     * then a unique id is generated and set for this component. This only happens when components are programmatically
     * created without ids, as components created by a ViewHandler should be assigned ids when they are created.
     * <p>
     * If this component is a descendant of a NamingContainer then the client id is of form
     * "{namingContainerId}:{componentId}". Note that the naming container's id may itself be of compound form if it has
     * an ancestor naming container. Note also that this only applies to naming containers; other UIComponent types in
     * the component's ancestry do not affect the clientId.
     * <p>
     * Finally the renderer associated with this component is asked to convert the id into a suitable form. This allows
     * escaping of any characters in the clientId which are significant for the markup language generated by that
     * renderer.
     */
    @Override
    public String getClientId(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }

        if (_clientId != null)
        {
            return _clientId;
        }

        String id = getId();
        if (id == null)
        {
            // Although this is an error prone side effect, we automatically create a new id
            // just to be compatible to the RI
            
            // The documentation of UniqueIdVendor says that this interface should be implemented by
            // components that also implements NamingContainer. The only component that does not implement
            // NamingContainer but UniqueIdVendor is UIViewRoot. Anyway we just can't be 100% sure about this
            // fact, so it is better to scan for the closest UniqueIdVendor. If it is not found use 
            // viewRoot.createUniqueId, otherwise use UniqueIdVendor.createUniqueId(context,seed).
            UniqueIdVendor parentUniqueIdVendor = _ComponentUtils.closest(UniqueIdVendor.class, this);
            if (parentUniqueIdVendor == null)
            {
                UIViewRoot viewRoot = context.getViewRoot();
                if (viewRoot != null)
                {
                    id = viewRoot.createUniqueId();
                }
                else
                {
                    // The RI throws a NPE
                    String location = getComponentLocation(this);
                    throw new FacesException("Cannot create clientId. No id is assigned for component"
                            + " to create an id and UIViewRoot is not defined: "
                            + _ComponentUtils.getPathToComponent(this)
                            + (location != null ? " created from: " + location : ""));
                }
            }
            else
            {
                id = parentUniqueIdVendor.createUniqueId(context, null);
            }
            setId(id);
        }

        UIComponent namingContainer = _ComponentUtils.findParentNamingContainer(this, false);
        if (namingContainer != null)
        {
            String containerClientId = namingContainer.getContainerClientId(context);
            if (containerClientId != null)
            {
                StringBuilder bld = _getSharedStringBuilder(context);
                _clientId = bld.append(containerClientId).append(
                                      context.getNamingContainerSeparatorChar()).append(id).toString();
            }
            else
            {
                _clientId = id;
            }
        }
        else
        {
            _clientId = id;
        }

        Renderer renderer = getRenderer(context);
        if (renderer != null)
        {
            _clientId = renderer.convertClientId(context, _clientId);
        }

        // -=Leonardo Uribe=- In jsf 1.1 and 1.2 this warning has sense, but in jsf 2.0 it is common to have
        // components without any explicit id (UIViewParameter components and UIOuput resource components) instances.
        // So, this warning is becoming obsolete in this new context and should be removed.
        //if (idWasNull && log.isLoggable(Level.WARNING))
        //{
        //    log.warning("WARNING: Component " + _clientId
        //            + " just got an automatic id, because there was no id assigned yet. "
        //            + "If this component was created dynamically (i.e. not by a JSP tag) you should assign it an "
        //            + "explicit static id or assign it the id you get from "
        //            + "the createUniqueId from the current UIViewRoot "
        //            + "component right after creation! Path to Component: " + _ComponentUtils.getPathToComponent(this));
        //}

        return _clientId;
    }
    
    /**
     * 
     * @return
     * 
     * @since 2.0
     */
    public String getDefaultEventName()
    {
        // if a default event exists for a component, this method is overriden thus assume null
        return null;
    }
    
    /**
     * 
     * @return
     * 
     * @since 2.0
     */
    public Collection<String> getEventNames()
    {
        // must be specified by the implementing component.
        // Returning null will force an error message in addClientBehavior.
        return null;
    }

    @Override
    public UIComponent getFacet(String name)
    {
        return _facetMap == null ? null : _facetMap.get(name);
    }

    /**
     * @since 1.2
     */
    @Override
    public int getFacetCount()
    {
        return _facetMap == null ? 0 : _facetMap.size();
    }

    @Override
    public Map<String, UIComponent> getFacets()
    {
        if (_facetMap == null)
        {
            _facetMap = new _ComponentFacetMap<>(this);
        }
        return _facetMap;
    }

    @Override
    public Iterator<UIComponent> getFacetsAndChildren()
    {
        // we can't use _facetMap and _childrenList here directly,
        // because some component implementation could keep their 
        // own properties for facets and children and just override
        // getFacets() and getChildren() (e.g. seen in PrimeFaces).
        // See MYFACES-2611 for details.
        if (getFacetCount() == 0)
        {
            if (getChildCount() == 0)
            {
                return Collections.<UIComponent>emptyIterator();
            }

            return getChildren().iterator();
        }
        else
        {
            if (getChildCount() == 0)
            {
                return getFacets().values().iterator();
            }

            return new _FacetsAndChildrenIterator(getFacets(), getChildren());
        }
    }

    /**
     * Get a string which uniquely identifies this UIComponent within the scope of the nearest ancestor NamingContainer
     * component. The id is not necessarily unique across all components in the current view.
     */
    @JSFProperty(rtexprvalue = true)
    @Override
    public String getId()
    {
        return _id;
    }

    @Override
    public UIComponent getParent()
    {
        return _parent;
    }

    @Override
    public String getRendererType()
    {
        // rendererType is literal-only, no ValueExpression - MYFACES-3136:
        // Even if this is true, according to JSF spec section 8 Rendering Model,
        // this part is essential to implement "delegated implementation" pattern,
        // so we can't do this optimization here. Instead, JSF developers could prevent
        // this evaluation overriding this method directly.
        if (_rendererType != null)
        {
            return _rendererType;
        }
        ValueExpression expression = getValueExpression("rendererType");
        if (expression != null)
        {
            return (String) expression.getValue(getFacesContext().getELContext());
        }
        return null;
    }

    /**
     * Indicates whether this component or its renderer manages the invocation of the rendering methods of its child
     * components. When this is true:
     * <ul>
     * <li>This component's encodeBegin method will only be called after all the child components have been created and
     * added to this component. <li>This component's encodeChildren method will be called after its encodeBegin method.
     * Components for which this method returns false do not get this method invoked at all. <li>No rendering methods
     * will be called automatically on child components; this component is required to invoke the
     * encodeBegin/encodeEnd/etc on them itself.
     * </ul>
     */
    @Override
    public boolean getRendersChildren()
    {
        Renderer renderer = getRenderer(getFacesContext());
        return renderer != null ? renderer.getRendersChildren() : false;
    }

    /**
     * <code>invokeOnComponent</code> must be implemented in <code>UIComponentBase</code> too...
     */
    @Override
    public boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback)
            throws FacesException
    {
        if (isCachedFacesContext())
        {
            return super.invokeOnComponent(context, clientId, callback);
        }
        else
        {
            try
            {
                setCachedFacesContext(context);
                return super.invokeOnComponent(context, clientId, callback);
            }
            finally
            {
                setCachedFacesContext(null);
            }
        }
    }

    @Override
    public boolean visitTree(VisitContext context, VisitCallback callback)
    {
        if (isCachedFacesContext())
        {
            return super.visitTree(context, callback);
        }
        else
        {
            try
            {
                setCachedFacesContext(context.getFacesContext());
                return super.visitTree(context, callback);
            }
            finally
            {
                setCachedFacesContext(null);
            }
        }
    }

    /**
     * A boolean value that indicates whether this component should be rendered. Default value: true.
     **/
    @Override
    @JSFProperty
    public boolean isRendered()
    {
        if (_cachedIsRendered != null)
        {
            return Boolean.TRUE.equals(_cachedIsRendered);
        }
        return (Boolean) getStateHelper().eval(PropertyKeys.rendered, DEFAULT_RENDERED);
    }

    @JSFProperty(literalOnly = true, istransient = true, tagExcluded = true)
    @Override
    public boolean isTransient()
    {
        return _transient;
    }
    
    @Override
    public void markInitialState()
    {
        super.markInitialState();
        
        // Enable copyFullInitialState behavior when delta is written into this component.
        ((_DeltaStateHelper)getStateHelper()).setCopyFullInitialState(true);
        
        if (_facesListeners != null)
        {
            _facesListeners.markInitialState();
        }
        if (_behaviorsMap != null)
        {
            for (Map.Entry<String, List<ClientBehavior>> entry : _behaviorsMap.entrySet())
            {
                ((PartialStateHolder) entry.getValue()).markInitialState();
            }
        }
        if (_systemEventListenerClassMap != null)
        {
            for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener>> entry : 
                _systemEventListenerClassMap.entrySet())
            {
                ((PartialStateHolder) entry.getValue()).markInitialState();
            }
        }
    }

    @Override
    protected void addFacesListener(FacesListener listener)
    {
        if (listener == null)
        {
            throw new NullPointerException("listener");
        }
        if (_facesListeners == null)
        {
            // How many facesListeners have single component normally? 
            _facesListeners = new _DeltaList<>(5);
        }
        _facesListeners.add(listener);
    }

    @Override
    protected FacesContext getFacesContext()
    {
        if (_facesContext == null)
        {
            return FacesContext.getCurrentInstance();
        }
        else
        {
            return _facesContext;
        }
    }

    // FIXME: Notify EG for generic usage
    @Override
    protected FacesListener[] getFacesListeners(Class clazz)
    {
        if (clazz == null)
        {
            throw new NullPointerException("Class is null");
        }
        if (!FacesListener.class.isAssignableFrom(clazz))
        {
            throw new IllegalArgumentException("Class " + clazz.getName() + " must implement " + FacesListener.class);
        }

        if (_facesListeners == null)
        {
            return (FacesListener[]) Array.newInstance(clazz, 0);
        }

        List<FacesListener> lst = null;
        // perf: _facesListeners is RandomAccess instance (javax.faces.component._DeltaList)
        for (int i = 0, size = _facesListeners.size(); i < size; i++)
        {
            FacesListener facesListener = _facesListeners.get(i);
            if (facesListener != null && clazz.isAssignableFrom(facesListener.getClass()))
            {
                if (lst == null)
                {
                    lst = new ArrayList<>(5);
                }
                lst.add(facesListener);
            }
        }

        if (lst == null || lst.isEmpty())
        {
            return (FacesListener[]) Array.newInstance(clazz, 0);
        }

        return lst.toArray((FacesListener[]) Array.newInstance(clazz, lst.size()));
    }

    @Override
    protected Renderer getRenderer(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }
        Renderer renderer = getCachedRenderer();
        if (renderer != null)
        {
            return renderer;
        }
        String rendererType = getRendererType();
        if (rendererType == null)
        {
            return null;
        }
        
        RenderKit renderKit = context.getRenderKit();
        renderer = renderKit.getRenderer(getFamily(), rendererType);
        if (renderer == null)
        {
            String location = getComponentLocation(this);
            String logStr = "No Renderer found for component " + _ComponentUtils.getPathToComponent(this)
                    + " (component-family=" + getFamily()
                    + ", renderer-type=" + rendererType + ')'
                    + (location != null ? " created from: " + location : "");
            
            getFacesContext().getExternalContext().log(logStr);
            log.warning(logStr);
        }
        return renderer;
    }

    @Override
    protected void removeFacesListener(FacesListener listener)
    {
        if (listener == null)
        {
            throw new NullPointerException("listener is null");
        }

        if (_facesListeners != null)
        {
            _facesListeners.remove(listener);
        }
    }

    @Override
    public void queueEvent(FacesEvent event)
    {
        if (event == null)
        {
            throw new NullPointerException("event");
        }
        UIComponent parent = getParent();
        if (parent == null)
        {
            throw new IllegalStateException("component is not a descendant of a UIViewRoot");
        }
        parent.queueEvent(event);
    }

    @Override
    public void processDecodes(FacesContext context)
    {
        try
        {
            setCachedFacesContext(context);
            // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
            pushComponentToEL(context, this);
            if (_isPhaseExecutable(context))
            {
                // Call the processDecodes() method of all facets and children of this UIComponent, in the order
                // determined by a call to getFacetsAndChildren().
                int facetCount = getFacetCount();
                if (facetCount > 0)
                {
                    for (UIComponent facet : getFacets().values())
                    {
                        facet.processDecodes(context);
                    }
                }
                for (int i = 0, childCount = getChildCount(); i < childCount; i++)
                {
                    UIComponent child = getChildren().get(i);
                    child.processDecodes(context);
                }

                try
                {
                    // Call the decode() method of this component.
                    decode(context);
                }
                catch (RuntimeException e)
                {
                    // If a RuntimeException is thrown during decode processing, call FacesContext.renderResponse()
                    // and re-throw the exception.
                    context.renderResponse();
                    throw e;
                }
            }
        }
        finally
        {
            // Call UIComponent.popComponentFromEL(javax.faces.context.FacesContext) from inside of a finally
            // block, just before returning.

            popComponentFromEL(context);
            setCachedFacesContext(null);
        }
    }

    @Override
    public void processValidators(FacesContext context)
    {
        try
        {
            setCachedFacesContext(context);
            // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
            pushComponentToEL(context, this);
            if (_isPhaseExecutable(context))
            {
                //Pre validation event dispatch for component
                context.getApplication().publishEvent(context,  PreValidateEvent.class, getClass(), this);
                
                try
                {
                    // Call the processValidators() method of all facets and children of this UIComponent, in the order
                    // determined by a call to getFacetsAndChildren().
                    int facetCount = getFacetCount();
                    if (facetCount > 0)
                    {
                        for (UIComponent facet : getFacets().values())
                        {
                            facet.processValidators(context);
                        }
                    }
    
                    for (int i = 0, childCount = getChildCount(); i < childCount; i++)
                    {
                        UIComponent child = getChildren().get(i);
                        child.processValidators(context);
                    }
                }
                finally
                {
                    context.getApplication().publishEvent(context,  PostValidateEvent.class, getClass(), this);
                }
            }
        }
        finally
        {
            popComponentFromEL(context);
            setCachedFacesContext(null);
        }
    }

    /**
     * This isn't an input component, so just pass on the processUpdates call to child components and facets that might
     * be input components.
     * <p>
     * Components that were never rendered can't possibly be receiving update data (no corresponding fields were ever
     * put into the response) so if this component is not rendered then this method does not invoke processUpdates on
     * its children.
     */
    @Override
    public void processUpdates(FacesContext context)
    {
        try
        {
            setCachedFacesContext(context);
            // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
            pushComponentToEL(context, this);
            if (_isPhaseExecutable(context))
            {
                // Call the processUpdates() method of all facets and children of this UIComponent, in the order
                // determined by a call to getFacetsAndChildren().
                int facetCount = getFacetCount();
                if (facetCount > 0)
                {
                    for (UIComponent facet : getFacets().values())
                    {
                        facet.processUpdates(context);
                    }
                }

                for (int i = 0, childCount = getChildCount(); i < childCount; i++)
                {
                    UIComponent child = getChildren().get(i);
                    child.processUpdates(context);
                }
            }
        }
        finally
        {
            // After returning from the processUpdates() method on a child or facet, call
            // UIComponent.popComponentFromEL(javax.faces.context.FacesContext)
            popComponentFromEL(context);
            
            setCachedFacesContext(null);
        }
    }

    @Override
    public Object processSaveState(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }

        if (isTransient())
        {
            // consult the transient property of this component. If true, just return null.
            return null;
        }

        // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
        pushComponentToEL(context, this);

        Map<String, Object> facetMap;

        List<Object> childrenList;
        
        Object savedState;
        try
        {
            facetMap = null;
            int facetCount = getFacetCount();
            if (facetCount > 0)
            {
                // Call the processSaveState() method of all facets and children of this UIComponent in the order
                // determined by a call to getFacetsAndChildren(), skipping children and facets that are transient.

                // To improve speed and robustness, the facets and children processing is splited to maintain the
                // facet --> state coherence based on the facet's name
                for (Map.Entry<String, UIComponent> entry : getFacets().entrySet())
                {
                    UIComponent component = entry.getValue();
                    if (!component.isTransient())
                    {
                        if (facetMap == null)
                        {
                            facetMap = new HashMap<>(facetCount, 1);
                        }

                        facetMap.put(entry.getKey(), component.processSaveState(context));
                    }
                }
            }
            childrenList = null;
            int childCount = getChildCount();
            if (childCount > 0)
            {
                // Call the processSaveState() method of all facets and children of this UIComponent in the order
                // determined by a call to getFacetsAndChildren(), skipping children and facets that are transient.

                // To improve speed and robustness, the facets and children processing is splited to maintain the
                // facet --> state coherence based on the facet's name
                for (int i = 0; i < childCount; i++)
                {
                    UIComponent child = getChildren().get(i);
                    if (!child.isTransient())
                    {
                        if (childrenList == null)
                        {
                            childrenList = new ArrayList<>(childCount);
                        }

                        Object childState = child.processSaveState(context);
                        if (childState != null)
                        { // FIXME: Isn't that check dangerous for restoration since the child isn't marked transient?
                            childrenList.add(childState);
                        }
                    }
                }
            }
            
            // Call the saveState() method of this component.
            savedState = saveState(context);
        }
        finally
        {
            // Ensure that UIComponent.popComponentFromEL(javax.faces.context.FacesContext) is called
            // correctly after each child or facet.
            popComponentFromEL(context);
        }

        // Encapsulate the child state and your state into a Serializable Object and return it.
        return new Object[] { savedState, facetMap, childrenList };
    }

    @SuppressWarnings("unchecked")
    @Override
    public void processRestoreState(FacesContext context, Object state)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }

        Object[] stateValues = (Object[]) state;

        try
        {
            // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
            pushComponentToEL(context, this);

            // Call the restoreState() method of this component.
            restoreState(context, stateValues[0]);
            
            Map<String, Object> facetMap = (Map<String, Object>) stateValues[1];
            if (facetMap != null && getFacetCount() > 0)
            {
                // Call the processRestoreState() method of all facets and children of this UIComponent in the order
                // determined by a call to getFacetsAndChildren().

                // To improve speed and robustness, the facets and children processing is splited to maintain the
                // facet --> state coherence based on the facet's name
                for (Map.Entry<String, UIComponent> entry : getFacets().entrySet())
                {
                    Object facetState = facetMap.get(entry.getKey());
                    if (facetState != null)
                    {
                        entry.getValue().processRestoreState(context, facetState);
                    }
                    else
                    {
                        context.getExternalContext().log("No state found to restore facet " + entry.getKey());
                    }
                }
            }
            List<Object> childrenList = (List<Object>) stateValues[2];
            if (childrenList != null && getChildCount() > 0)
            {
                // Call the processRestoreState() method of all facets and children of this UIComponent in the order
                // determined by a call to getFacetsAndChildren().

                // To improve speed and robustness, the facets and children processing is splited to maintain the
                // facet --> state coherence based on the facet's name
                int idx = 0;
                for (int i = 0, childCount = getChildCount(); i < childCount; i++)
                {
                    UIComponent child = getChildren().get(i);
                    if (!child.isTransient())
                    {
                        Object childState = childrenList.get(idx++);
                        if (childState != null)
                        {
                            child.processRestoreState(context, childState);
                        }
                        else
                        {
                            context.getExternalContext().log("No state found to restore child of component " + getId());
                        }
                    }
                }
            }
        }
        finally
        {
            // After returning from the processRestoreState() method on a child or facet, call
            // UIComponent.popComponentFromEL(javax.faces.context.FacesContext)
            popComponentFromEL(context);
        }
    }
    
    /**
     * Gets the Location of the given UIComponent from its attribute map.
     * @param component
     * @return
     */
    private String getComponentLocation(UIComponent component)
    {
        Location location = (Location) component.getAttributes().get(UIComponent.VIEW_LOCATION_KEY);
        return location == null ? null : location.toString();
    }

    @Override
    public void setTransient(boolean transientFlag)
    {
        _transient = transientFlag;
    }

    /**
     * Serializes objects which are "attached" to this component but which are not UIComponent children of it. Examples
     * are validator and listener objects. To be precise, it returns an object which implements java.io.Serializable,
     * and which when serialized will persist the state of the provided object.
     * <p>
     * If the attachedObject is a List then every object in the list is saved via a call to this method, and the
     * returned wrapper object contains a List object.
     * <p>
     * If the object implements StateHolder then the object's saveState is called immediately, and a wrapper is returned
     * which contains both this saved state and the original class name. However in the case where the
     * StateHolder.isTransient method returns true, null is returned instead.
     * <p>
     * If the object implements java.io.Serializable then the object is simply returned immediately; standard java
     * serialization will later be used to store this object.
     * <p>
     * In all other cases, a wrapper is returned which simply stores the type of the provided object. When deserialized,
     * a default instance of that type will be recreated.
     */
    public static Object saveAttachedState(FacesContext context, Object attachedObject)
    {
        if (context == null)
        {
            throw new NullPointerException ("context");
        }
        
        if (attachedObject == null)
        {
            return null;
        }
        // StateHolder interface should take precedence over
        // List children
        if (attachedObject instanceof StateHolder)
        {
            StateHolder holder = (StateHolder) attachedObject;
            if (holder.isTransient())
            {
                return null;
            }

            return new _AttachedStateWrapper(attachedObject.getClass(), holder.saveState(context));
        }
        else if (attachedObject instanceof Collection)
        {
            if (ArrayList.class.equals(attachedObject.getClass()))
            {
                ArrayList<?> list = (ArrayList<?>) attachedObject;
                int size = list.size();
                List<Object> lst = new ArrayList<Object>(size);
                for (int i = 0; i < size; i++)
                {
                    Object item = list.get(i);
                    if (item != null)
                    {
                        lst.add(saveAttachedState(context, item));
                    }
                }
                return new _AttachedListStateWrapper(lst);
            }
            else
            {
                List<Object> lst = new ArrayList<>(((Collection<?>) attachedObject).size());
                for (Object item : (Collection<?>) attachedObject)
                {
                    if (item != null)
                    {
                        lst.add(saveAttachedState(context, item));
                    }
                }
                return new _AttachedCollectionStateWrapper(attachedObject.getClass(), lst);
            }
        }
        else if (attachedObject instanceof Serializable)
        {
            return attachedObject;
        }
        else
        {
            return new _AttachedStateWrapper(attachedObject.getClass(), null);
        }
    }

    public static Object restoreAttachedState(FacesContext context, Object stateObj) throws IllegalStateException
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }
        if (stateObj == null)
        {
            return null;
        }
        if (stateObj instanceof _AttachedListStateWrapper)
        {
            // perf: getWrappedStateList in _AttachedListStateWrapper is always ArrayList: see saveAttachedState
            ArrayList<Object> lst = (ArrayList<Object>) ((_AttachedListStateWrapper) stateObj).getWrappedStateList();
            List<Object> restoredList = new ArrayList<Object>(lst.size());
            for (int i = 0, size = lst.size(); i < size; i++)
            {
                Object item = lst.get(i);
                restoredList.add(restoreAttachedState(context, item));
            }
            return restoredList;
        }
        else if (stateObj instanceof _AttachedCollectionStateWrapper)
        {
            _AttachedCollectionStateWrapper wrappedState = (_AttachedCollectionStateWrapper) stateObj; 
            Class<?> clazz = wrappedState.getClazz();
            List<Object> lst = wrappedState.getWrappedStateList();
            Collection restoredList;
            try
            {
                restoredList = (Collection) clazz.newInstance();
            }
            catch (InstantiationException e)
            {
                throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName()
                        + " (missing no-args constructor?)", e);
            }
            catch (IllegalAccessException e)
            {
                throw new RuntimeException(e);
            }

            for (int i = 0; i < lst.size(); i++)
            {
                Object item = lst.get(i);
                restoredList.add(restoreAttachedState(context, item));
            }
            return restoredList;

        }
        else if (stateObj instanceof _AttachedStateWrapper)
        {
            Class<?> clazz = ((_AttachedStateWrapper) stateObj).getClazz();
            Object restoredObject;
            try
            {
                restoredObject = clazz.newInstance();
            }
            catch (InstantiationException e)
            {
                throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName()
                        + " (missing no-args constructor?)", e);
            }
            catch (IllegalAccessException e)
            {
                throw new RuntimeException(e);
            }
            if (restoredObject instanceof StateHolder)
            {
                _AttachedStateWrapper wrapper = (_AttachedStateWrapper) stateObj;
                Object wrappedState = wrapper.getWrappedStateObject();

                StateHolder holder = (StateHolder) restoredObject;
                holder.restoreState(context, wrappedState);
            }
            return restoredObject;
        }
        else
        {
            return stateObj;
        }
    }
    
    private static final int FULL_STATE_ARRAY_SIZE = 10;

    /**
     * Invoked after the render phase has completed, this method returns an object which can be passed to the
     * restoreState of some other instance of UIComponentBase to reset that object's state to the same values as this
     * object currently has.
     */
    @Override
    public Object saveState(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException ("context");
        }
        
        if (context.getViewRoot() != null)
        {
            if (context.getViewRoot().getResetSaveStateMode() == RESET_MODE_SOFT)
            {
                // Force FacesContext cleanup to prevent leak it.
                setCachedFacesContext(null);
                // Reset state to recalculate state first.
                StateHelper stateHelper = getStateHelper(false);
                if (stateHelper != null)
                {
                    ((_DeltaStateHelper)stateHelper).resetSoftState(context);
                }
            }
            if (context.getViewRoot().getResetSaveStateMode() == RESET_MODE_HARD)
            {
                // Force FacesContext cleanup to prevent leak it.
                setCachedFacesContext(null);
                // Reset state to recalculate state first.
                StateHelper stateHelper = getStateHelper(false);
                if (stateHelper != null)
                {
                    ((_DeltaStateHelper)stateHelper).resetHardState(context);
                }
            }
        }
        if (initialStateMarked())
        {
            //Delta
            //_id and _clientId was already restored from template
            //and never changes during component life.
            Object facesListenersSaved = saveFacesListenersList(context);
            Object behaviorsMapSaved = saveBehaviorsMap(context);
            Object systemEventListenerClassMapSaved = saveSystemEventListenerClassMap(context);
            Object stateHelperSaved = null;
            StateHelper stateHelper = getStateHelper(false);
            if (stateHelper != null)
            {
                stateHelperSaved = stateHelper.saveState(context);
            }
            
            if (facesListenersSaved == null && stateHelperSaved == null && 
                behaviorsMapSaved == null && systemEventListenerClassMapSaved == null &&
               !((_capabilities & FLAG_IS_RENDERER_TYPE_SET) != 0))
            {
                return null;
            }
            
            Object transientState = null;
            if (context.getCurrentPhaseId() != null && 
                !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
            {
                transientState = saveTransientState(context);
            }
            
            if (transientState != null)
            {
                if ((_capabilities & FLAG_IS_RENDERER_TYPE_SET) != 0)
                {
                    return new Object[] {facesListenersSaved, stateHelperSaved, behaviorsMapSaved,
                                        systemEventListenerClassMapSaved, transientState,
                                        _rendererType};
                }
                else
                {
                    return new Object[] {facesListenersSaved, stateHelperSaved, behaviorsMapSaved,
                        systemEventListenerClassMapSaved, transientState};
                }
            }
            else
            {
                if ((_capabilities & FLAG_IS_RENDERER_TYPE_SET) != 0)
                {
                    return new Object[] {facesListenersSaved, stateHelperSaved, behaviorsMapSaved,
                                        systemEventListenerClassMapSaved, null,
                                        _rendererType};
                }
                else
                {
                    return new Object[] {facesListenersSaved, stateHelperSaved, behaviorsMapSaved,
                        systemEventListenerClassMapSaved};
                }
            }
        }
        else
        {
            //Full
            Object values[] = new Object[FULL_STATE_ARRAY_SIZE];
            values[0] = saveFacesListenersList(context);
            StateHelper stateHelper = getStateHelper(false);
            if (stateHelper != null)
            {
                values[1] = stateHelper.saveState(context);
            }
            values[2] = saveBehaviorsMap(context);
            values[3] = saveSystemEventListenerClassMap(context);
            values[4] = _id;
            values[5] = _clientId;
            values[6] = _markCreated;
            values[7] = _rendererType;
            values[8] = _capabilities;
            if (context.getCurrentPhaseId() != null && 
                !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
            {
                values[9] = saveTransientState(context);
            }
 
            return values;
        }
    }

    /**
     * Invoked in the "restore view" phase, this initialises this object's members from the values saved previously into
     * the provided state object.
     * <p>
     * 
     * @param state
     *            is an object previously returned by the saveState method of this class.
     */
    @SuppressWarnings("unchecked")
    @Override
    public void restoreState(FacesContext context, Object state)
    {
        if (context == null)
        {
            throw new NullPointerException ("context");
        }
        
        if (state == null)
        {
            //Only happens if initialStateMarked return true
            
            if (initialStateMarked())
            {
                return;
            }
            
            throw new NullPointerException ("state");
        }
        
        Object values[] = (Object[]) state;
        
        if ( values.length == FULL_STATE_ARRAY_SIZE && initialStateMarked())
        {
            //Delta mode is active, but we are restoring a full state.
            //we need to clear the initial state, to restore state without
            //take into account delta.
            clearInitialState();
        }
        
        if (values[0] instanceof _AttachedDeltaWrapper)
        {
            //Delta: check for null is not necessary since _facesListener field
            //is only set once and never reset
            ((StateHolder)_facesListeners).restoreState(context,
                    ((_AttachedDeltaWrapper) values[0]).getWrappedStateObject());
        }
        else if (values[0] != null || (values.length == FULL_STATE_ARRAY_SIZE))
        {
            //Full
            _facesListeners = (_DeltaList<FacesListener>)
                restoreAttachedState(context,values[0]);
        }
        // Note that if values[0] == null && initialStateMarked(),
        // means delta is null, not that _facesListeners == null. 
        // We can do this here because _facesListeners instance once
        // is created is never replaced or set to null.
        
        getStateHelper().restoreState(context, values[1]);
        
        if (values.length == FULL_STATE_ARRAY_SIZE)
        {
            _id = (String) values[4];
            _clientId = (String) values[5];
            _markCreated = (String) values[6];
            _rendererType = (String) values[7];
            _capabilities = (Integer) values[8];
        }
        else if (values.length == 6)
        {
            restoreTransientState(context, values[4]);
            _rendererType = (String) values[5];
            _capabilities |= FLAG_IS_RENDERER_TYPE_SET;
        }
        else if (values.length == 5)
        {
            restoreTransientState(context, values[4]);
        }
        
        
        // rendererType needs to be restored before SystemEventListener,
        // otherwise UIComponent.getCurrentComponent(context).getRenderer(context)
        // will not work correctly
        if (values.length == FULL_STATE_ARRAY_SIZE)
        {
            //Full restore
            restoreFullBehaviorsMap(context, values[2]);
            restoreFullSystemEventListenerClassMap(context, values[3]);
            restoreTransientState(context, values[9]);
        }
        else
        {
            //Delta restore
            restoreDeltaBehaviorsMap(context, values[2]);
            restoreDeltaSystemEventListenerClassMap(context, values[3]);
        }
    }
    
    private Object saveFacesListenersList(FacesContext facesContext)
    {
        PartialStateHolder holder = (PartialStateHolder) _facesListeners;
        if (initialStateMarked() && _facesListeners != null && holder.initialStateMarked())
        {                
            Object attachedState = holder.saveState(facesContext);
            if (attachedState != null)
            {
                return new _AttachedDeltaWrapper(_facesListeners.getClass(), attachedState);
            }
            //_facesListeners instances once is created never changes, we can return null
            return null;
        }
        else
        {
            return saveAttachedState(facesContext,_facesListeners);
        }            
    }

    @SuppressWarnings("unchecked")
    private void restoreFullBehaviorsMap(FacesContext facesContext, Object stateObj)
    {
        if (stateObj != null)
        {
            Map<String, Object> stateMap = (Map<String, Object>) stateObj;
            int initCapacity = (stateMap.size() * 4 + 3) / 3;
            _behaviorsMap = new HashMap<>(initCapacity);
            _unmodifiableBehaviorsMap = null;
            for (Map.Entry<String, Object> entry : stateMap.entrySet())
            {
                _behaviorsMap.put(entry.getKey(),
                                  (List<ClientBehavior>) restoreAttachedState(facesContext, entry.getValue()));
            }
        }
        else
        {
            _behaviorsMap = null;
            _unmodifiableBehaviorsMap = null;
        }        
    }
    
    @SuppressWarnings("unchecked")
    private void restoreDeltaBehaviorsMap(FacesContext facesContext, Object stateObj)
    {
        if (stateObj != null)
        {
            _unmodifiableBehaviorsMap = null;
            Map<String, Object> stateMap = (Map<String, Object>) stateObj;
            int initCapacity = (stateMap.size() * 4 + 3) / 3;
            if (_behaviorsMap == null)
            {
                _behaviorsMap = new HashMap<>(initCapacity);
            }
            for (Map.Entry<String, Object> entry : stateMap.entrySet())
            {
                Object savedObject = entry.getValue(); 
                if (savedObject instanceof _AttachedDeltaWrapper)
                {
                    StateHolder holderList = (StateHolder) _behaviorsMap.get(entry.getKey());
                    holderList.restoreState(facesContext,
                                            ((_AttachedDeltaWrapper) savedObject).getWrappedStateObject());
                }
                else
                {
                    _behaviorsMap.put(entry.getKey(),
                                      (List<ClientBehavior>) restoreAttachedState(facesContext, savedObject));
                }
            }
        }
    }
    
    private Object saveBehaviorsMap(FacesContext facesContext)
    {
        if (_behaviorsMap != null)
        {
            if (initialStateMarked())
            {
                HashMap<String, Object> stateMap = new HashMap<>(_behaviorsMap.size(), 1);
                boolean nullDelta = true;
                for (Map.Entry<String, List<ClientBehavior> > entry : _behaviorsMap.entrySet())
                {
                    // The list is always an instance of _DeltaList so we can cast to
                    // PartialStateHolder 
                    PartialStateHolder holder = (PartialStateHolder) entry.getValue();
                    if (holder.initialStateMarked())
                    {
                        Object attachedState = holder.saveState(facesContext);
                        if (attachedState != null)
                        {
                            stateMap.put(entry.getKey(), new _AttachedDeltaWrapper(_behaviorsMap.getClass(),
                                    attachedState));
                            nullDelta = false;
                        }
                    }
                    else
                    {
                        stateMap.put(entry.getKey(), saveAttachedState(facesContext, holder));
                        nullDelta = false;
                    }
                }
                if (nullDelta)
                {
                    return null;
                }
                return stateMap;
            }
            else
            {
                //Save it in the traditional way
                HashMap<String, Object> stateMap = new HashMap<>(_behaviorsMap.size(), 1);
                for (Map.Entry<String, List<ClientBehavior> > entry : _behaviorsMap.entrySet())
                {
                    stateMap.put(entry.getKey(), saveAttachedState(facesContext, entry.getValue()));
                }
                return stateMap;
            }
        }
        else
        {
            return null;
        }
    }
    
    @SuppressWarnings("unchecked")
    private void restoreFullSystemEventListenerClassMap(FacesContext facesContext, Object stateObj)
    {
        if (stateObj != null)
        {
            Map<Class<? extends SystemEvent>, Object> stateMap = (Map<Class<? extends SystemEvent>, Object>) stateObj;
            _systemEventListenerClassMap = new HashMap<>(stateMap.size(), 1f);
            for (Map.Entry<Class<? extends SystemEvent>, Object> entry : stateMap.entrySet())
            {
                _systemEventListenerClassMap.put(entry.getKey(),
                        (List<SystemEventListener>) restoreAttachedState(facesContext, entry.getValue()));
            }
        }
        else
        {
            _systemEventListenerClassMap = null;
        }        
    }
    
    @SuppressWarnings("unchecked")
    private void restoreDeltaSystemEventListenerClassMap(FacesContext facesContext, Object stateObj)
    {
        if (stateObj != null)
        {
            Map<Class<? extends SystemEvent>, Object> stateMap = (Map<Class<? extends SystemEvent>, Object>) stateObj;
            if (_systemEventListenerClassMap == null)
            {
                _systemEventListenerClassMap = new HashMap<>(stateMap.size(), 1f);
            }
            for (Map.Entry<Class<? extends SystemEvent>, Object> entry : stateMap.entrySet())
            {
                Object savedObject = entry.getValue(); 
                if (savedObject instanceof _AttachedDeltaWrapper)
                {
                    StateHolder holderList = (StateHolder) _systemEventListenerClassMap.get(entry.getKey());
                    holderList.restoreState(facesContext,
                                            ((_AttachedDeltaWrapper) savedObject).getWrappedStateObject());
                }
                else
                {
                    _systemEventListenerClassMap.put(entry.getKey(),
                            (List<SystemEventListener>) restoreAttachedState(facesContext, savedObject));
                }
            }
        }
    }
    
    private Object saveSystemEventListenerClassMap(FacesContext facesContext)
    {
        if (_systemEventListenerClassMap != null)
        {
            if (initialStateMarked())
            {
                HashMap<Class<? extends SystemEvent>, Object> stateMap
                        = new HashMap<>(_systemEventListenerClassMap.size(), 1);
                boolean nullDelta = true;
                for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener> > entry
                        : _systemEventListenerClassMap.entrySet())
                {
                    // The list is always an instance of _DeltaList so we can cast to
                    // PartialStateHolder 
                    PartialStateHolder holder = (PartialStateHolder) entry.getValue();
                    if (holder.initialStateMarked())
                    {
                        Object attachedState = holder.saveState(facesContext);
                        if (attachedState != null)
                        {
                            stateMap.put(entry.getKey(),
                                    new _AttachedDeltaWrapper(_systemEventListenerClassMap.getClass(), attachedState));
                            nullDelta = false;
                        }
                    }
                    else
                    {
                        stateMap.put(entry.getKey(), saveAttachedState(facesContext, holder));
                        nullDelta = false;
                    }
                }
                if (nullDelta)
                {
                    return null;
                }
                return stateMap;
            }
            else
            {
                //Save it in the traditional way
                HashMap<Class<? extends SystemEvent>, Object> stateMap = 
                    new HashMap<>(_systemEventListenerClassMap.size(), 1);
                for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener>> entry
                        : _systemEventListenerClassMap.entrySet())
                {
                    stateMap.put(entry.getKey(), saveAttachedState(facesContext, entry.getValue()));
                }
                return stateMap;
            }
        }
        else
        {
            return null;
        }
    }
    
    /**
     * @param string
     *            the component id, that should be a vaild one.
     */
    private void isIdValid(String string)
    {
        // is there any component identifier ?
        if (string == null)
        {
            return;
        }

        // Component identifiers must obey the following syntax restrictions:
        // 1. Must not be a zero-length String.
        if (string.length() == 0)
        {
            throw new IllegalArgumentException("component identifier must not be a zero-length String");
        }

        // If new id is the same as old it must be valid
        if (string.equals(_id))
        {
            return;
        }

        // 2. First character must be a letter or an underscore ('_').
        char firstChar = string.charAt(0);
        if (!Character.isLetter(firstChar) && firstChar != '_')
        {
            throw new IllegalArgumentException("component identifier's first character must be a letter "
                                               + "or an underscore ('_')! But it is \""
                                               + firstChar + '"');
        }
        for (int i = 1; i < string.length(); i++)
        {
            char c = string.charAt(i);
            // 3. Subsequent characters must be a letter, a digit, an underscore ('_'), or a dash ('-').
            if (!Character.isLetterOrDigit(c) && c != '-' && c != '_')
            {
                throw new IllegalArgumentException("Subsequent characters of component identifier must be a letter, "
                                                   + "a digit, an underscore ('_'), or a dash ('-')! "
                                                   + "But component identifier \"" + string + "\" contains \""
                                                   + c + '"');
            }
        }
    }

    private boolean _isPhaseExecutable(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }

        // If the rendered property of this UIComponent is false, skip further processing.
        return isRendered();
    }

    @Override
    boolean isCachedFacesContext()
    {
        return _facesContext != null;
    }
    
    @Override
    void setCachedFacesContext(FacesContext facesContext)
    {
        _facesContext = facesContext;
    }
    
    Renderer getCachedRenderer()
    {
        return _cachedRenderer;
    }
    
    void setCachedRenderer(Renderer renderer)
    {
        _cachedRenderer = renderer;
    }

    Boolean isCachedIsRendered()
    {
        return _cachedIsRendered;
    }
    
    void setCachedIsRendered(Boolean rendered)
    {
       _cachedIsRendered = rendered;
    }

    void setOamVfMarkCreated(String markCreated)
    {
        _markCreated = markCreated;
    }
    
    String getOamVfMarkCreated()
    {
        return _markCreated;
    }
    
    String getOamVfFacetName()
    {
        return _facetName;
    }
    
    void setOamVfFacetName(String facetName)
    {
        _facetName = facetName;
    }
    
    boolean isOamVfAddedByHandler()
    {
        return (_capabilities & FLAG_ADDED_BY_HANDLER) != 0;
    }
    
    void setOamVfAddedByHandler(boolean addedByHandler)
    {
        if (addedByHandler)
        {
            _capabilities |= FLAG_ADDED_BY_HANDLER;
        }
        else
        {
            _capabilities &= ~(FLAG_ADDED_BY_HANDLER);
        }
    }
    
    boolean isOamVfFacetCreatedUIPanel()
    {
        return (_capabilities & FLAG_FACET_CREATED_UIPANEL) != 0;
    }
    
    void setOamVfFacetCreatedUIPanel(boolean facetCreatedUIPanel)
    {
        if (facetCreatedUIPanel)
        {
            _capabilities |= FLAG_FACET_CREATED_UIPANEL;
        }
        else
        {
            _capabilities &= ~(FLAG_FACET_CREATED_UIPANEL);
        }
    }

    /**
     * <p>
     * This gets a single FacesContext-local shared stringbuilder instance, each time you call
     * _getSharedStringBuilder it sets the length of the stringBuilder instance to 0.
     * </p><p>
     * This allows you to use the same StringBuilder instance over and over.
     * You must call toString on the instance before calling _getSharedStringBuilder again.
     * </p>
     * Example that works
     * <pre><code>
     * StringBuilder sb1 = _getSharedStringBuilder();
     * sb1.append(a).append(b);
     * String c = sb1.toString();
     *
     * StringBuilder sb2 = _getSharedStringBuilder();
     * sb2.append(b).append(a);
     * String d = sb2.toString();
     * </code></pre>
     * <br><br>
     * Example that doesn't work, you must call toString on sb1 before
     * calling _getSharedStringBuilder again.
     * <pre><code>
     * StringBuilder sb1 = _getSharedStringBuilder();
     * StringBuilder sb2 = _getSharedStringBuilder();
     *
     * sb1.append(a).append(b);
     * String c = sb1.toString();
     *
     * sb2.append(b).append(a);
     * String d = sb2.toString();
     * </code></pre>
     *
     * @param facesContext
     */
    static StringBuilder _getSharedStringBuilder(FacesContext facesContext)
    {
        Map<Object, Object> attributes = facesContext.getAttributes();

        StringBuilder sb = (StringBuilder) attributes.get(_STRING_BUILDER_KEY);

        if (sb == null)
        {
            sb = new StringBuilder();
            attributes.put(_STRING_BUILDER_KEY, sb);
        }
        else
        {
            // clear out the stringBuilder by setting the length to 0
            sb.setLength(0);
        }

        return sb;
    }

    // ------------------ GENERATED CODE BEGIN (do not modify!) --------------------

    private static final Boolean DEFAULT_RENDERED = Boolean.TRUE;

    @Override
    public void setRendered(boolean rendered)
    {
        getStateHelper().put(PropertyKeys.rendered, rendered );
        setCachedIsRendered(null);
    }

    @Override
    public void setRendererType(String rendererType)
    {
        this._rendererType = rendererType;
        if (initialStateMarked())
        {
            //This flag just indicates the rendererType 
            //should be included on the delta
            _capabilities |= FLAG_IS_RENDERER_TYPE_SET;
        }
        setCachedRenderer(null);
    }

    // ------------------ GENERATED CODE END ---------------------------------------

    private Map<String, List<ClientBehavior>> wrapBehaviorsMap()
    {
        if (_unmodifiableBehaviorsMap == null)
        {
            _unmodifiableBehaviorsMap = Collections.unmodifiableMap(_behaviorsMap); 
        }
        return _unmodifiableBehaviorsMap; 
    }
}
