/*
 * 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 java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.FactoryFinder;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.FacesListener;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.faces.render.Renderer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 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.
 * <p>
 * See Javadoc of <a href="http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/index.html">JSF Specification</a> for more.
 * 
 * @JSFComponent
 *   type = "javax.faces.ComponentBase"
 *   family = "javax.faces.ComponentBase"
 *   desc = "base component from which all components should inherit"
 *   tagClass = "javax.faces.webapp.UIComponentTag"
 *   
 * @JSFJspProperty
 *   name = "binding" 
 *   returnType = "java.lang.String"
 *   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"
 *   
 * @author Manfred Geiler (latest modification by $Author$)
 * @version $Revision$ $Date$
 */
public abstract class UIComponentBase
        extends UIComponent
{
    private static Log log = LogFactory.getLog(UIComponentBase.class);
    
    private static final Iterator _EMPTY_UICOMPONENT_ITERATOR = 
        new _EmptyIterator();    

    private _ComponentAttributesMap _attributesMap = null;
    private Map _valueBindingMap = null;
    private List _childrenList = null;
    private Map _facetMap = null;
    private List _facesListeners = null;
    private String _clientId = null;
    private String _id = null;
    private UIComponent _parent = null;
    private boolean _transient = false;

    private transient FacesContext _facesContext;

    public UIComponentBase()
    {
    }

    /**
     * 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.
     */
    public Map getAttributes()
    {
        if (_attributesMap == null)
        {
            _attributesMap = new _ComponentAttributesMap(this);
        }
        return _attributesMap;
    }

    /**
     * Get the named value-binding associated with this component.
     * <p>
     * Value-bindings are stored in a map associated with the component,
     * though there is commonly a property (setter/getter methods) 
     * of the same name defined on the component itself which
     * evaluates the value-binding when called.
     */
    public ValueBinding getValueBinding(String name)
    {
        if (name == null) throw new NullPointerException("name");
        if (_valueBindingMap == null)
        {
            return null;
        }
        else
        {
            return (ValueBinding)_valueBindingMap.get(name);
        }
    }

    /**
     * Put the provided value-binding into a map of value-bindings
     * associated with this component.
     */
    public void setValueBinding(String name,
                                ValueBinding binding)
    {
        if (name == null) throw new NullPointerException("name");
        if (_valueBindingMap == null)
        {
            _valueBindingMap = new HashMap();
        }
        _valueBindingMap.put(name, binding);
    }

    /**
     * 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.
     */
    public String getClientId(FacesContext context)
    {
        if (context == null) throw new NullPointerException("context");

        if (_clientId != null) return _clientId;

        boolean idWasNull = false;
        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
            UIViewRoot viewRoot = context.getViewRoot();
            if (viewRoot != null)
            {
                id = viewRoot.createUniqueId();
            }
            else
            {
                context.getExternalContext().log("ERROR: Cannot automatically create an id for component of type " + getClass().getName() + " because there is no viewRoot in the current facesContext!");
                id = "ERROR";
            }
            setId(id);
            //We remember that the id was null and log a warning down below
            idWasNull = true;
        }

        UIComponent namingContainer = findParentNamingContainer(this, false);
        if (namingContainer != null)
        {
            _clientId = namingContainer.getClientId(context) + NamingContainer.SEPARATOR_CHAR + id;
        }
        else
        {
            _clientId = id;
        }

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

        if (idWasNull)
        {
            context.getExternalContext().log("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!");
        }

        return _clientId;
    }

    /**
     * An identifier for this particular component instance within
     * a component view.
     * <p>
     * The id must be unique within the scope of the tag's enclosing 
     * NamingContainer (eg h:form or f:subview). The id is
     * not necessarily unique across all components in the current view
     * </p>
     * <p>
     * This value must be a static value, ie not change over the lifetime
     * of a component. It cannot be defined via an EL expression; only
     * a string is permitted.
     * </p>
     * 
     * @JSFProperty
     */
    public String getId()
    {
        return _id;
    }

    /**
     * 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.
     */
    public void setId(String id)
    {
        isIdValid(id);
        _id = id;
        _clientId = null;

        UIComponent parent = getParent();

        if(parent != null) {
            List li = getParent().getChildren();

            if(li instanceof _ComponentChildrenList) {
                ((_ComponentChildrenList) li).updateId(_id,this);
            }
        }
    }

    public UIComponent getParent()
    {
        return _parent;
    }

    public void setParent(UIComponent parent)
    {
        _parent = parent;
    }

    /**
     * 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>
     */
    public boolean getRendersChildren()
    {
        Renderer renderer = getRenderer(getFacesContext());
        if (renderer != null)
        {
            return renderer.getRendersChildren();
        }
        else
        {
            return false;
        }
    }

    /**
     * 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>
     */
    public List getChildren()
    {
        if (_childrenList == null)
        {
            _childrenList = new _ComponentChildrenList(this);
        }
        return _childrenList;
    }

    /**
     * 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.
     */
    public int getChildCount()
    {
        return _childrenList == null ? 0 : _childrenList.size();
    }

    /**
     * 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.
     */

    public UIComponent findComponent(String expr)
    {
        if (expr == null) throw new NullPointerException("expr");
        if (expr.length() == 0) throw new IllegalArgumentException("empty expr"); //TODO: not specified!

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

        int separator = expr.indexOf(NamingContainer.SEPARATOR_CHAR);
        if (separator == -1)
        {
            return findComponent(findBase, expr);
        }
        else
        {
            String id = expr.substring(0, separator);
            findBase = findComponent(findBase, id);
            if (findBase == null)
            {
                return null;
            }
            else
            {
                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));
            }
        }
    }

    static UIComponent findParentNamingContainer(UIComponent component,
                                                 boolean returnRootIfNotFound)
    {
        UIComponent parent = component.getParent();
        if (returnRootIfNotFound && parent == null)
        {
            return component;
        }
        while (parent != null)
        {
            if (parent instanceof NamingContainer) return parent;
            if (returnRootIfNotFound)
            {
                UIComponent nextParent = parent.getParent();
                if (nextParent == null)
                {
                    return parent;  //Root
                }
                parent = nextParent;
            }
            else
            {
                parent = parent.getParent();
            }
        }
        return null;
    }

    static UIComponent getRootComponent(UIComponent component)
    {
        UIComponent parent;
        for(;;)
        {
            parent = component.getParent();
            if (parent == null) return component;
            component = parent;
        }
    }

    /**
     * Find the component with the specified id starting from the specified
     * component.
     * <p>
     * Param id must not contain any NamingContainer.SEPARATOR_CHAR characters
     * (ie ":"). This method explicitly does <i>not</i> search into any
     * child naming container components; this is expected to be handled
     * by the caller of this method.
     * <p>
     * For an implementation of findComponent which does descend into
     * child naming components, see org.apache.myfaces.custom.util.ComponentUtils.
     *
     * @return findBase, a descendant of findBase, or null.
     */
    private UIComponent findComponent(UIComponent findBase, String id)
    {
        if (idsAreEqual(id, findBase)){
            return findBase;
        }

        /*UIComponent comp = findComponentCached(id, findBase);

        if(comp != null)
            return comp;*/     

        return findComponentNormal(id, findBase);
    }

    private UIComponent findComponentCached(String id, UIComponent findBase) {

        if(!(findBase.getChildren() instanceof _ComponentChildrenList)) {
            return null;
        }

        _ComponentChildrenList li = (_ComponentChildrenList) findBase.getChildren();

        UIComponent comp = li.get(id);

        if(comp != null)
            return comp;

        for (Iterator it = findBase.getFacetsAndChildren(); it.hasNext(); )
        {
            UIComponent childOrFacet = (UIComponent)it.next();
            UIComponent find = findComponentCached(id,childOrFacet);
            if (find != null) return find;
        }

        return null;
    }

    private UIComponent findComponentNormal(String id, UIComponent findBase) {
        if (idsAreEqual(id, findBase))
        {
            return findBase;
        }

        for (Iterator it = findBase.getFacetsAndChildren(); it.hasNext(); )
        {
            UIComponent childOrFacet = (UIComponent)it.next();
            // If a descendant NamingContainer is found, 
            // child components including facets are not searched,
            // so just check if this component is and continue
            // if not.
            if (childOrFacet instanceof NamingContainer){
                if (idsAreEqual(id, childOrFacet))
                {
                    return childOrFacet;
                }
            }else{
                UIComponent find = findComponentNormal(id, childOrFacet);
                if (find != null) return find;
            }
        }

        return null;
    }

    /*
     * Return true if the specified component matches the provided id.
     * This needs some quirks to handle components whose id value gets
     * dynamically "tweaked", eg a UIData component whose id gets
     * the current row index appended to it.
     */
    private boolean idsAreEqual(String id, UIComponent cmp)
    {
        if(id.equals(cmp.getId()))
            return true;

        if(cmp instanceof UIData)
        {
            UIData uiData = ((UIData) cmp);

            if(uiData.getRowIndex()==-1)
            {
                return dynamicIdIsEqual(id,cmp.getId());
            }
            else
            {
                return id.equals(cmp.getId()+NamingContainer.SEPARATOR_CHAR+uiData.getRowIndex());
            }
        }

        return false;
    }

    private boolean dynamicIdIsEqual(String dynamicId, String id)
    {
        return dynamicId.matches(id+":[0-9]*");
    }


    public Map getFacets()
    {
        if (_facetMap == null)
        {
            _facetMap = new _ComponentFacetMap(this);
        }
        return _facetMap;
    }

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

    public Iterator getFacetsAndChildren()
    {
        if (_facetMap == null)
        {
            if (_childrenList == null)
                return _EMPTY_UICOMPONENT_ITERATOR;

            if (_childrenList.size() == 0)
                return _EMPTY_UICOMPONENT_ITERATOR;
            
            return _childrenList.iterator();
        }
        else
        {
            if (_facetMap.size() == 0)
            {
                if (_childrenList == null)
                    return _EMPTY_UICOMPONENT_ITERATOR;
              
                if (_childrenList.size() == 0)
                    return _EMPTY_UICOMPONENT_ITERATOR;
            
                return _childrenList.iterator();  
            }
            else
            {
                if (_childrenList == null)
                    return _facetMap.values().iterator();
              
                if (_childrenList.size() == 0)
                    return _facetMap.values().iterator();
              
                return new _FacetsAndChildrenIterator(_facetMap, _childrenList);                            
            }
        }
    }

    /**
     * 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.
     */
    public void broadcast(FacesEvent event)
            throws AbortProcessingException
    {
        if (event == null) throw new NullPointerException("event");
        try {
            if (_facesListeners == null) return;
            for (Iterator it = _facesListeners.iterator(); it.hasNext(); )
            {
                FacesListener facesListener = (FacesListener)it.next();
                if (event.isAppropriateListener(facesListener))
                {
                    event.processListener(facesListener);
                }
            }
        } catch (Exception e) {
            if (e instanceof AbortProcessingException) {
                throw (AbortProcessingException) e;
            }
            throw new FacesException("Exception while calling broadcast on : "+getPathToComponent(this), e);
        }
    }

    /**
     * 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.
     */
    public void decode(FacesContext context)
    {
        if (context == null) throw new NullPointerException("context");
        try {
            Renderer renderer = getRenderer(context);
            if (renderer != null)
            {
                renderer.decode(context, this);
            }
        } catch (Exception e) {
            if (e instanceof AbortProcessingException)
            throw new FacesException("Exception while calling decode on : "+getPathToComponent(this), e);
        }
    }

    public void encodeBegin(FacesContext context)
            throws IOException
    {
        if (context == null) throw new NullPointerException("context");
        try {
            setCachedFacesContext(context);
            
            if (!isRendered()) return;
            Renderer renderer = getRenderer(context);
            if (renderer != null)
            {
                renderer.encodeBegin(context, this);
            }
        } catch (Exception e) {
            throw new FacesException("Exception while calling encodeBegin on : "+getPathToComponent(this), e);
        }
        finally
        {
            setCachedFacesContext(null);
        }
    }

    public void encodeChildren(FacesContext context)
            throws IOException
    {
        if (context == null) throw new NullPointerException("context");
        
        boolean isCachedFacesContext = isCachedFacesContext();
        try
        {
            if (!isCachedFacesContext)
            {
                setCachedFacesContext(context);
            }
            if (!isRendered()) return;
            Renderer renderer = getRenderer(context);
            if (renderer != null)
            {
                renderer.encodeChildren(context, this);
            }
        }
        finally
        {
            if (!isCachedFacesContext)
            {
                setCachedFacesContext(null);
            }
        }
    }

    public void encodeEnd(FacesContext context)
            throws IOException
    {
        if (context == null) throw new NullPointerException("context");
        try {
            setCachedFacesContext(context);
            if (!isRendered()) return;

            Renderer renderer = getRenderer(context);
            if (renderer != null)
            {
                renderer.encodeEnd(context, this);
            }
        } catch (Exception e) {
            throw new FacesException("Exception while calling encodeEnd on : "+getPathToComponent(this), e);
        }
        finally
        {
            setCachedFacesContext(null);
        }
    }

    protected void addFacesListener(FacesListener listener)
    {
        if (listener == null) throw new NullPointerException("listener");
        if (_facesListeners == null)
        {
            _facesListeners = new ArrayList();
        }
        _facesListeners.add(listener);
    }

    protected FacesListener[] getFacesListeners(Class clazz)
    {
        if (_facesListeners == null)
        {
            return (FacesListener[])Array.newInstance(clazz, 0);
        }
        List lst = null;
        for (Iterator it = _facesListeners.iterator(); it.hasNext(); )
        {
            FacesListener facesListener = (FacesListener)it.next();
            if (clazz.isAssignableFrom(facesListener.getClass()))
            {
                if (lst == null) lst = new ArrayList();
                lst.add(facesListener);
            }
        }
        if (lst == null)
        {
            return (FacesListener[])Array.newInstance(clazz, 0);
        }
        else
        {
            return (FacesListener[])lst.toArray((FacesListener[])Array.newInstance(clazz, lst.size()));
        }
    }

    protected void removeFacesListener(FacesListener listener)
    {
        if (_facesListeners != null)
        {
            _facesListeners.remove(listener);
        }
    }

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

    public void processDecodes(FacesContext context)
    {
        if (context == null)
            throw new NullPointerException("context");
        
        try
        {
            setCachedFacesContext(context);
            
            if (!isRendered()) return;
            
            for (Iterator it = getFacetsAndChildren(); it.hasNext(); )
            {
                UIComponent childOrFacet = (UIComponent)it.next();
                childOrFacet.processDecodes(context);
            }
            try
            {
                decode(context);
            }
            catch (RuntimeException e)
            {
                context.renderResponse();
                throw e;
            }
        }
        finally
        {
            setCachedFacesContext(null);
        }
    }


    public void processValidators(FacesContext context)
    {
        if (context == null) throw new NullPointerException("context");
        
        try
        {
            setCachedFacesContext(context);
            if (!isRendered()) return;
    
            for (Iterator it = getFacetsAndChildren(); it.hasNext(); )
            {
                UIComponent childOrFacet = (UIComponent)it.next();
                childOrFacet.processValidators(context);
            }
        }
        finally
        {
            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.
     */
    public void processUpdates(FacesContext context)
    {
        if (context == null) throw new NullPointerException("context");
        
        try
        {
            setCachedFacesContext(context);
            
            if (!isRendered()) return;
    
            for (Iterator it = getFacetsAndChildren(); it.hasNext(); )
            {
                UIComponent childOrFacet = (UIComponent)it.next();
                childOrFacet.processUpdates(context);
            }
        }
        finally
        {
            setCachedFacesContext(null);
        }
    }

    public Object processSaveState(FacesContext context)
    {
        if (context == null) throw new NullPointerException("context");
        if (isTransient()) return null;
        Map facetMap = null;
        for (Iterator it = getFacets().entrySet().iterator(); it.hasNext(); )
        {
            Map.Entry entry = (Map.Entry)it.next();
            if (facetMap == null) facetMap = new HashMap();
            UIComponent component = (UIComponent)entry.getValue();
            if (!component.isTransient())
            {
                facetMap.put(entry.getKey(), component.processSaveState(context));
            }
        }
        List childrenList = null;
        if (getChildCount() > 0)
        {
            for (Iterator it = getChildren().iterator(); it.hasNext(); )
            {
              UIComponent child = (UIComponent)it.next();
              if (childrenList == null) {
                childrenList = new ArrayList(getChildCount());
              }
              Object childState = child.processSaveState(context);
              if (childState != null) {
                childrenList.add(childState);
              }
            }
        }
        Object savedState;
        try {
             savedState = saveState(context);
        } catch (Exception e) {
            throw new FacesException("Exception while saving state of component : "+getPathToComponent(this), e);
        }

        return new Object[] {savedState,
                             facetMap,
                             childrenList};
    }

    public void processRestoreState(FacesContext context,
                                    Object state)
    {
        if (context == null) throw new NullPointerException("context");
        Object myState = ((Object[])state)[0];
        Map facetMap = (Map)((Object[])state)[1];
        List childrenList = (List)((Object[])state)[2];
        if(facetMap != null)
        {
          for (Iterator it = getFacets().entrySet().iterator(); it.hasNext(); )
          {
              Map.Entry entry = (Map.Entry)it.next();
              Object facetState = facetMap.get(entry.getKey());
              if (facetState != null)
              {
                UIComponent component = (UIComponent)entry.getValue();
                component.processRestoreState(context, facetState);
              }
              else
              {
                  context.getExternalContext().log("No state found to restore facet " + entry.getKey());
              }
          }
        }
        if (childrenList != null && getChildCount() > 0)
        {
            int idx = 0;
            for (Iterator it = getChildren().iterator(); it.hasNext(); )
            {
                UIComponent child = (UIComponent)it.next();
                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());
                  }
                }
            }
        }
        try {
            restoreState(context, myState);
        } catch (Exception e) {
            throw new FacesException("Exception while restoring state of component : "+getPathToComponent(this), e);
        }
    }

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

    protected Renderer getRenderer(FacesContext context)
    {
        if (context == null) throw new NullPointerException("context");
        String rendererType = getRendererType();
        if (rendererType == null) return null;
        
        RenderKit renderKit = context.getRenderKit();
        Renderer renderer = renderKit.getRenderer(getFamily(), rendererType);
        if (renderer == null)
        {
            getFacesContext().getExternalContext().log("No Renderer found for component " + getPathToComponent(this) + " (component-family=" + getFamily() + ", renderer-type=" + rendererType + ")");
            log.warn("No Renderer found for component " + getPathToComponent(this) + " (component-family=" + getFamily() + ", renderer-type=" + rendererType + ")");
        }
        return renderer;
    }

    private String getPathToComponent(UIComponent component)
    {
        StringBuffer buf = new StringBuffer();

        if(component == null)
        {
            buf.append("{Component-Path : ");
            buf.append("[null]}");
            return buf.toString();
        }

        getPathToComponent(component,buf);

        buf.insert(0,"{Component-Path : ");
        buf.append("}");

        return buf.toString();
    }

    private static void getPathToComponent(UIComponent component, StringBuffer buf)
    {
        if(component == null)
            return;

        StringBuffer intBuf = new StringBuffer();

        intBuf.append("[Class: ");
        intBuf.append(component.getClass().getName());
        if(component instanceof UIViewRoot)
        {
            intBuf.append(",ViewId: ");
            intBuf.append(((UIViewRoot) component).getViewId());
        }
        else
        {
            intBuf.append(",Id: ");
            intBuf.append(component.getId());
        }
        intBuf.append("]");

        buf.insert(0,intBuf.toString());

        getPathToComponent(component.getParent(), buf);
    }

    /**
     * @JSFProperty
     *   literalOnly = "true"
     *   transient = "true"
     *   tagExcluded ="true"
     */
    public boolean isTransient()
    {
        return _transient;
    }

    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 (attachedObject == null) return null;
        if (attachedObject instanceof List)
        {
            List lst = new ArrayList(((List)attachedObject).size());
            for (Iterator it = ((List)attachedObject).iterator(); it.hasNext(); )
            {
                Object value = it.next();
                if (value != null)
                {
                    lst.add(saveAttachedState(context, value));
                }
            }
            return new _AttachedListStateWrapper(lst);
        }
        else if (attachedObject instanceof StateHolder)
        {
            if (((StateHolder)attachedObject).isTransient())
            {
                return null;
            }
            else
            {
                return new _AttachedStateWrapper(attachedObject.getClass(),
                                                 ((StateHolder)attachedObject).saveState(context));
            }
        }
        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)
        {
            List lst = ((_AttachedListStateWrapper)stateObj).getWrappedStateList();
            List restoredList = new ArrayList(lst.size());
            for (Iterator it = lst.iterator(); it.hasNext(); )
            {
                restoredList.add(restoreAttachedState(context, it.next()));
            }
            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)
            {
                Object wrappedState = ((_AttachedStateWrapper)stateObj).getWrappedStateObject();
                ((StateHolder)restoredObject).restoreState(context, wrappedState);
            }
            return restoredObject;
        }
        else
        {
            return stateObj;
        }
    }


    /**
     * 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.
     */
    public Object saveState(FacesContext context)
    {
        Object values[] = new Object[7];
        values[0] = _id;
        values[1] = _rendered;
        values[2] = _rendererType;
        values[3] = _clientId;
        values[4] = saveAttributesMap();
        values[5] = saveAttachedState(context, _facesListeners);
        values[6] = saveValueBindingMap(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.
     */
    public void restoreState(FacesContext context, Object state)
    {
        Object values[] = (Object[])state;
        _id = (String)values[0];
        _rendered = (Boolean)values[1];
        _rendererType = (String)values[2];
        _clientId = (String)values[3];
        restoreAttributesMap(values[4]);
        _facesListeners = (List)restoreAttachedState(context, values[5]);
        restoreValueBindingMap(context, values[6]);
    }


    private Object saveAttributesMap()
    {
        if (_attributesMap != null)
        {
            return _attributesMap.getUnderlyingMap();
        }
        else
        {
            return null;
        }
    }

    private void restoreAttributesMap(Object stateObj)
    {
        if (stateObj != null)
        {
            _attributesMap = new _ComponentAttributesMap(this, (Map)stateObj);
        }
        else
        {
            _attributesMap = null;
        }
    }

    private Object saveValueBindingMap(FacesContext context)
    {
        if (_valueBindingMap != null)
        {
            int initCapacity = (_valueBindingMap.size() * 4 + 3) / 3;
            HashMap stateMap = new HashMap(initCapacity);
            for (Iterator it = _valueBindingMap.entrySet().iterator(); it.hasNext(); )
            {
                Map.Entry entry = (Map.Entry)it.next();
                stateMap.put(entry.getKey(),
                             saveAttachedState(context, entry.getValue()));
            }
            return stateMap;
        }
        else
        {
            return null;
        }
    }

    private void restoreValueBindingMap(FacesContext context, Object stateObj)
    {
        if (stateObj != null)
        {
            Map stateMap = (Map)stateObj;
            int initCapacity = (stateMap.size() * 4 + 3) / 3;
            _valueBindingMap = new HashMap(initCapacity);
            for (Iterator it = stateMap.entrySet().iterator(); it.hasNext(); )
            {
                Map.Entry entry = (Map.Entry)it.next();
                _valueBindingMap.put(entry.getKey(),
                                     restoreAttachedState(context, entry.getValue()));
            }
        }
        else
        {
            _valueBindingMap = 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");
        }

        //let's look at all chars inside of the ID if it is a valid ID!
        char[] chars = string.toCharArray();

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

    boolean isCachedFacesContext()
    {
        return _facesContext != null;
    }
    
    void setCachedFacesContext(FacesContext facesContext)
    {
        _facesContext = facesContext;
    }

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

    private static final boolean DEFAULT_RENDERED = true;

    private Boolean _rendered = null;
    private String _rendererType = null;



    public void setRendered(boolean rendered)
    {
        _rendered = Boolean.valueOf(rendered);
    }

    /**
     * A boolean value that indicates whether this component should be rendered.
     * Default value: true.
     * 
     * @JSFProperty
     */
    public boolean isRendered()
    {
        if (_rendered != null) return _rendered.booleanValue();
        ValueBinding vb = getValueBinding("rendered");
        Boolean v = vb != null ? (Boolean)vb.getValue(getFacesContext()) : null;
        return v != null ? v.booleanValue() : DEFAULT_RENDERED;
    }

    public void setRendererType(String rendererType)
    {
        _rendererType = rendererType;
    }

    public String getRendererType()
    {
        if (_rendererType != null) return _rendererType;
        ValueBinding vb = getValueBinding("rendererType");
        return vb != null ? _ComponentUtils.getStringValue(getFacesContext(), vb) : null;
    }


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