//  Copyright 2004 The Apache Software Foundation
//
// Licensed 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 org.apache.tapestry;

import ognl.OgnlRuntime;
import org.apache.tapestry.bean.BeanProvider;
import org.apache.tapestry.bean.BeanProviderPropertyAccessor;
import org.apache.tapestry.engine.IPageLoader;
import org.apache.tapestry.event.*;
import org.apache.tapestry.listener.ListenerMap;
import org.apache.tapestry.param.ParameterManager;
import org.apache.tapestry.spec.BaseLocatable;
import org.apache.tapestry.spec.IComponentSpecification;
import org.apache.tapestry.util.prop.OgnlUtils;
import org.apache.tapestry.util.prop.PropertyFinder;
import org.apache.tapestry.util.prop.PropertyInfo;

import java.util.*;

/**
 *  Abstract base class implementing the {@link IComponent} interface.
 *
 *  @author Howard Lewis Ship
 *  @version $Id$
 * 
 **/

public abstract class AbstractComponent extends BaseLocatable implements IComponent
{
    /**
     * Used to check that subclasses invoke this implementation of prepareForRender().
     * @see Tapestry#checkMethodInvocation(Object, String, Object)
     * @since 3.0
     */
    private final static String PREPAREFORRENDER_METHOD_ID = "AbstractComponent.prepareForRender()";

    /**
     * Used to check that subclasses invoke this implementation of cleanupAfterRender().
     * @see Tapestry#checkMethodInvocation(Object, String, Object)
     * @since 3.0
     */

    private final static String CLEANUPAFTERRENDER_METHOD_ID =
        "AbstractComponent.cleanupAfterRender()";

    static {
        // Register the BeanProviderHelper to provide access to the
        // beans of a bean provider as named properties.

        OgnlRuntime.setPropertyAccessor(IBeanProvider.class, new BeanProviderPropertyAccessor());
    }

    /**
     *  The specification used to originally build the component.
     *
     * 
     **/

    private IComponentSpecification _specification;

    /**
     *  The page that contains the component, possibly itself (if the component is
     *  in fact, a page).
     *
     * 
     **/

    private IPage _page;

    /**
     *  The component which contains the component.  This will only be
     *  null if the component is actually a page.
     *
     **/

    private IComponent _container;

    /**
     *  The simple id of this component.
     *
     * 
     **/

    private String _id;

    /**
     *  The fully qualified id of this component.  This is calculated the first time
     *  it is needed, then cached for later.
     *
     **/

    private String _idPath;

    private static final int MAP_SIZE = 5;

    /**
     *  A {@link Map} of all bindings (for which there isn't a corresponding
     *  JavaBeans property); the keys are the names of formal and informal
     *  parameters.
     *
     **/

    private Map _bindings;

    private Map _components;
    private static final int BODY_INIT_SIZE = 5;

    private INamespace _namespace;

    /**
     *  Used in place of JDK 1.3's Collections.EMPTY_MAP (which is not
     *  available in JDK 1.2).
     *
     **/

    private static final Map EMPTY_MAP = Collections.unmodifiableMap(new HashMap(1));

    /**
     *  The number of {@link IRender} objects in the body of
     *  this component.
     *
     * 
     **/

    private int _bodyCount = 0;

    /**
     *  An aray of elements in the body of this component.
     *
     * 
     **/

    private IRender[] _body;

    /**
     *  The components' asset map.
     *
     **/

    private Map _assets;

    /**
     *  A mapping that allows public instance methods to be dressed up
     *  as {@link IActionListener} listener
     *  objects.
     *
     *  @since 1.0.2
     * 
     **/

    private ListenerMap _listeners;

    /**
     *  A bean provider; these are lazily created as needed.
     *
     *  @since 1.0.4
     * 
     **/

    private IBeanProvider _beans;

    /**
     *  Manages setting and clearing parameter properties for the component.
     * 
     *  @since 2.0.3
     * 
     **/

    private ParameterManager _parameterManager;

    /**
     *  Provides access to localized Strings for this component.
     * 
     *  @since 2.0.4
     * 
     **/

    private IMessages _strings;

    public void addAsset(String name, IAsset asset)
    {
        if (_assets == null)
            _assets = new HashMap(MAP_SIZE);

        _assets.put(name, asset);
    }

    public void addComponent(IComponent component)
    {
        if (_components == null)
            _components = new HashMap(MAP_SIZE);

        _components.put(component.getId(), component);
    }

    /**
     *  Adds an element (which may be static text or a component) as a body
     *  element of this component.  Such elements are rendered
     *  by {@link #renderBody(IMarkupWriter, IRequestCycle)}.
     *
     *  @since 2.2
     * 
     **/

    public void addBody(IRender element)
    {
        // Should check the specification to see if this component
        // allows body.  Curently, this is checked by the component
        // in render(), which is silly.

        if (_body == null)
        {
            _body = new IRender[BODY_INIT_SIZE];
            _body[0] = element;

            _bodyCount = 1;
            return;
        }

        // No more room?  Make the array bigger.

        if (_bodyCount == _body.length)
        {
            IRender[] newWrapped;

            newWrapped = new IRender[_body.length * 2];

            System.arraycopy(_body, 0, newWrapped, 0, _bodyCount);

            _body = newWrapped;
        }

        _body[_bodyCount++] = element;
    }

    /**
     *  Registers this component as a listener of the page if it
     *  implements {@link org.apache.tapestry.event.PageDetachListener} or 
     *  {@link org.apache.tapestry.event.PageRenderListener}.
     * 
     *  <p>
     *  Invokes {@link #finishLoad()}.  Subclasses may overide as needed, but
     *  must invoke this implementation.
     *  {@link BaseComponent}
     *  loads its HTML template. 
     *
     **/

    public void finishLoad(
        IRequestCycle cycle,
        IPageLoader loader,
        IComponentSpecification specification)
    {
        if (this instanceof PageDetachListener)
            _page.addPageDetachListener((PageDetachListener) this);

        if (this instanceof PageRenderListener)
            _page.addPageRenderListener((PageRenderListener) this);

        if (this instanceof PageValidateListener)
            _page.addPageValidateListener((PageValidateListener) this);

        finishLoad();
    }

    /**
     * @deprecated To be removed in 3.1. 
     * Use {@link Tapestry#fireObservedChange(IComponent, String, int)} instead.
     */
    protected void fireObservedChange(String propertyName, int newValue)
    {
        Tapestry.fireObservedChange(this, propertyName, newValue);
    }

    /**
     * @deprecated To be removed in 3.1. 
     * Use {@link Tapestry#fireObservedChange(IComponent, String, Object)} instead.
     */
    protected void fireObservedChange(String propertyName, Object newValue)
    {
        Tapestry.fireObservedChange(this, propertyName, newValue);
    }

    /**
     * @deprecated To be removed in 3.1. 
     * Use {@link Tapestry#fireObservedChange(IComponent, String, boolean)} instead.
     */
    protected void fireObservedChange(String propertyName, boolean newValue)
    {
        Tapestry.fireObservedChange(this, propertyName, newValue);
    }

    /**
     * @deprecated To be removed in 3.1. 
     * Use {@link Tapestry#fireObservedChange(IComponent, String, double)} instead.
     */
    protected void fireObservedChange(String propertyName, double newValue)
    {
        Tapestry.fireObservedChange(this, propertyName, newValue);
    }

    /**
     * @deprecated To be removed in 3.1. 
     * Use {@link Tapestry#fireObservedChange(IComponent, String, float)} instead.
     */
    protected void fireObservedChange(String propertyName, float newValue)
    {
        Tapestry.fireObservedChange(this, propertyName, newValue);
    }

    /**
     * @deprecated To be removed in 3.1. 
     * Use {@link Tapestry#fireObservedChange(IComponent, String, long)} instead.
     */
    protected void fireObservedChange(String propertyName, long newValue)
    {
        Tapestry.fireObservedChange(this, propertyName, newValue);
    }

    /**
     * @deprecated To be removed in 3.1. 
     * Use {@link Tapestry#fireObservedChange(IComponent, String, char)} instead.
     */
    protected void fireObservedChange(String propertyName, char newValue)
    {
        Tapestry.fireObservedChange(this, propertyName, newValue);
    }

    /**
     * @deprecated To be removed in 3.1. 
     * Use {@link Tapestry#fireObservedChange(IComponent, String, byte)} instead.
     */
    protected void fireObservedChange(String propertyName, byte newValue)
    {
        Tapestry.fireObservedChange(this, propertyName, newValue);
    }

    /**
     * @deprecated To be removed in 3.1. 
     * Use {@link Tapestry#fireObservedChange(IComponent, String, short)} instead.
     */
    protected void fireObservedChange(String propertyName, short newValue)
    {
        Tapestry.fireObservedChange(this, propertyName, newValue);
    }

    /**
     *  @deprecated To be removed in 3.1.  Use 
     *  {@link #renderInformalParameters(IMarkupWriter, IRequestCycle)}
     *  instead.
     * 
     **/

    protected void generateAttributes(IMarkupWriter writer, IRequestCycle cycle)
    {
        renderInformalParameters(writer, cycle);
    }

    /**
     *  Converts informal parameters into additional attributes on the
     *  curently open tag.
     *
     *  <p>Invoked from subclasses to allow additional attributes to
     *  be specified within a tag (this works best when there is a
     *  one-to-one corespondence between an {@link IComponent} and a
     *  HTML element.
     *
     *  <p>Iterates through the bindings for this component.  Filters
     *  out bindings when the name matches a formal parameter (as of 1.0.5,
     *  informal bindings are weeded out at page load / template load time,
     *  if they match a formal parameter, or a specificied reserved name).
     *  For the most part, all the bindings here are either informal parameter,
     *  or formal parameter without a corresponding JavaBeans property.
     *
     *  <p>For each acceptible key, the value is extracted using {@link IBinding#getObject()}.
     *  If the value is null, no attribute is written.
     *
     *  <p>If the value is an instance of {@link IAsset}, then
     *  {@link IAsset#buildURL(IRequestCycle)} is invoked to convert the asset
     *  to a URL.
     *
     *  <p>Finally, {@link IMarkupWriter#attribute(String,String)} is
     *  invoked with the value (or the URL).
     *
     *  <p>The most common use for informal parameters is to support
     *  the HTML class attribute (for use with cascading style sheets)
     *  and to specify JavaScript event handlers.
     *
     *  <p>Components are only required to generate attributes on the
     *  result phase; this can be skipped during the rewind phase.
     **/

    protected void renderInformalParameters(IMarkupWriter writer, IRequestCycle cycle)
    {
        String attribute;

        if (_bindings == null)
            return;

        Iterator i = _bindings.entrySet().iterator();

        while (i.hasNext())
        {
            Map.Entry entry = (Map.Entry) i.next();
            String name = (String) entry.getKey();

            IBinding binding = (IBinding) entry.getValue();

            Object value = binding.getObject();
            if (value == null)
                continue;

            if (value instanceof IAsset)
            {
                IAsset asset = (IAsset) value;

                // Get the URL of the asset and insert that.

                attribute = asset.buildURL(cycle);
            }
            else
                attribute = value.toString();

            writer.attribute(name, attribute);
        }

    }

    /**
     *  Returns an object used to resolve classes.
     *  @since 3.0
     *
     **/
    private IResourceResolver getResourceResolver()
    {
        return getPage().getEngine().getResourceResolver();
    }

	/**
	 *  Returns the named binding, or null if it doesn't exist.
	 *
	 *  <p>This method looks for a JavaBeans property with an
	 *  appropriate name, of type {@link IBinding}.  The property
	 *  should be named <code><i>name</i>Binding</code>.  If it exists
	 *  and is both readable and writable, then it is accessor method
	 *  is invoked.  Components which implement such methods can
	 *  access their own binding through their instance variables
	 *  instead of invoking this method, a performance optimization.
	 *
	 *  @see #setBinding(String,IBinding)
	 *
	 **/

	public IBinding getBinding(String name)
	{
		String bindingPropertyName = name + Tapestry.PARAMETER_PROPERTY_NAME_SUFFIX;
		PropertyInfo info = PropertyFinder.getPropertyInfo(getClass(), bindingPropertyName);

		if (info != null && info.isReadWrite() && info.getType().equals(IBinding.class))
		{
			IResourceResolver resolver = getPage().getEngine().getResourceResolver();

			return (IBinding) OgnlUtils.get(bindingPropertyName, resolver, this);
		}

		if (_bindings == null)
			return null;

		return (IBinding) _bindings.get(name);
	}


    /**
     *  Return's the page's change observer.  In practical terms, this
     *  will be an {@link org.apache.tapestry.engine.IPageRecorder}.
     *
     *  @see IPage#getChangeObserver()
     *  @deprecated To be removed in 3.1; use {@link IPage#getChangeObserver()}.
     **/

    public ChangeObserver getChangeObserver()
    {
        return _page.getChangeObserver();
    }

    public IComponent getComponent(String id)
    {
        IComponent result = null;

        if (_components != null)
            result = (IComponent) _components.get(id);

        if (result == null)
            throw new ApplicationRuntimeException(
                Tapestry.format("no-such-component", this, id),
                this,
                null,
                null);

        return result;
    }

    public IComponent getContainer()
    {
        return _container;
    }

    public void setContainer(IComponent value)
    {
        if (_container != null)
            throw new ApplicationRuntimeException(
                Tapestry.getMessage("AbstractComponent.attempt-to-change-container"));

        _container = value;
    }

    /**
     *  Returns the name of the page, a slash, and this component's id path.
     *  Pages are different, they simply return their name.
     *
     *  @see #getIdPath()
     *
     **/

    public String getExtendedId()
    {
        if (_page == null)
            return null;

        return _page.getPageName() + "/" + getIdPath();
    }

    public String getId()
    {
        return _id;
    }

    public void setId(String value)
    {
        if (_id != null)
            throw new ApplicationRuntimeException(
                Tapestry.getMessage("AbstractComponent.attempt-to-change-component-id"));

        _id = value;
    }

    public String getIdPath()
    {
        String containerIdPath;

        if (_container == null)
            throw new NullPointerException(
                Tapestry.format("AbstractComponent.null-container", this));

        containerIdPath = _container.getIdPath();

        if (containerIdPath == null)
            _idPath = _id;
        else
            _idPath = containerIdPath + "." + _id;

        return _idPath;
    }

    public IPage getPage()
    {
        return _page;
    }

    public void setPage(IPage value)
    {
        if (_page != null)
            throw new ApplicationRuntimeException(
                Tapestry.getMessage("AbstractComponent.attempt-to-change-page"));

        _page = value;
    }

    public IComponentSpecification getSpecification()
    {
        return _specification;
    }

    public void setSpecification(IComponentSpecification value)
    {
        if (_specification != null)
            throw new ApplicationRuntimeException(
                Tapestry.getMessage("AbstractComponent.attempt-to-change-spec"));

        _specification = value;
    }

    /**
     *  Renders all elements wrapped by the receiver.
     *
     **/

    public void renderBody(IMarkupWriter writer, IRequestCycle cycle)
    {
        for (int i = 0; i < _bodyCount; i++)
            _body[i].render(writer, cycle);
    }

	/**
	 *  Adds the binding with the given name, replacing any existing binding
	 *  with that name.
	 *
	 *  <p>This method checks to see if a matching JavaBeans property
	 *  (with a name of <code><i>name</i>Binding</code> and a type of
	 *  {@link IBinding}) exists.  If so, that property is updated.
	 *  An optimized component can simply implement accessor and
	 *  mutator methods and then access its bindings via its own
	 *  instance variables, rather than going through {@link
	 *  #getBinding(String)}.
	 *
	 *  <p>Informal parameters should <em>not</em> be stored in
	 *  instance variables if {@link
	 *  #renderInformalParameters(IMarkupWriter, IRequestCycle)} is to be used.
	 *  It relies on using the collection of bindings (to store informal parameters).
	 **/

	public void setBinding(String name, IBinding binding)
	{
		String bindingPropertyName = name + Tapestry.PARAMETER_PROPERTY_NAME_SUFFIX;

		PropertyInfo info = PropertyFinder.getPropertyInfo(getClass(), bindingPropertyName);

		if (info != null && info.isReadWrite() && info.getType().equals(IBinding.class))
		{
			IResourceResolver resolver = getPage().getEngine().getResourceResolver();
			OgnlUtils.set(bindingPropertyName, resolver, this, binding);
			return;
		}

		if (_bindings == null)
			_bindings = new HashMap(MAP_SIZE);

		_bindings.put(name, binding);
	}


    public String toString()
    {
        StringBuffer buffer;

        buffer = new StringBuffer(super.toString());

        buffer.append('[');

        buffer.append(getExtendedId());

        buffer.append(']');

        return buffer.toString();
    }

    /**
     *  Returns an unmodifiable {@link Map} of components, keyed on component id.
     *  Never returns null, but may return an empty map.  The returned map is
     *  immutable.
     *
     **/

    public Map getComponents()
    {
        if (_components == null)
            return EMPTY_MAP;

        return _components;
    }

    public Map getAssets()
    {
        if (_assets == null)
            return EMPTY_MAP;

        return _assets;
    }

    public IAsset getAsset(String name)
    {
        if (_assets == null)
            return null;

        return (IAsset) _assets.get(name);
    }

    public Collection getBindingNames()
    {
        // If no conainer, i.e. a page, then no bindings.

        if (_container == null)
            return null;

        HashSet result = new HashSet();

        // All the informal bindings go into the bindings Map. 

        if (_bindings != null)
            result.addAll(_bindings.keySet());

        // Now, iterate over the formal parameters and add the formal parameters
        // that have a binding.

        List names = _specification.getParameterNames();

        int count = names.size();

        for (int i = 0; i < count; i++)
        {
            String name = (String) names.get(i);

            if (result.contains(name))
                continue;

            if (getBinding(name) != null)
                result.add(name);
        }

        return result;
    }

    /** 
     *
     *  Returns a {@link Map} of all bindings for this component.  This implementation
     *  is expensive, since it has to merge the disassociated bindings (informal parameters,
     *  and parameters without a JavaBeans property) with the associated bindings (formal
     *  parameters with a JavaBeans property).
     *
     * @since 1.0.5
     *
     **/

    public Map getBindings()
    {
        Map result = new HashMap();

        // Add any informal parameters.

        if (_bindings != null)
            result.putAll(_bindings);

        // Now work on the formal parameters

        Iterator i = _specification.getParameterNames().iterator();
        while (i.hasNext())
        {
            String name = (String) i.next();

            if (result.containsKey(name))
                continue;

            IBinding binding = getBinding(name);

            if (binding != null)
                result.put(name, binding);
        }

        return result;
    }

    /**
     *  Returns a {@link ListenerMap} for the component.  A {@link ListenerMap} contains a number of
     *  synthetic read-only properties that implement the {@link IActionListener} 
     *  interface, but in fact, cause public instance methods to be invoked.
     *
     *  @since 1.0.2
     **/

    public ListenerMap getListeners()
    {
        if (_listeners == null)
            _listeners = new ListenerMap(this);

        return _listeners;
    }

    /**
     *  Returns the {@link IBeanProvider} for this component.  This is lazily created the
     *  first time it is needed.
     *
     *  @since 1.0.4
     *
     **/

    public IBeanProvider getBeans()
    {
        if (_beans == null)
            _beans = new BeanProvider(this);

        return _beans;
    }

    /**
     * 
     *  Invoked, as a convienience, 
     *  from {@link #finishLoad(IRequestCycle, IPageLoader, IComponentSpecification)}.
     *  This implemenation does nothing.  Subclasses may override without invoking
     *  this implementation.
     * 
     *  @since 1.0.5
     *
     **/

    protected void finishLoad()
    {
    }

    /**
     *  The main method used to render the component.  
     *  Invokes {@link #prepareForRender(IRequestCycle)}, then
     *  {@link #renderComponent(IMarkupWriter, IRequestCycle)}.
     *  {@link #cleanupAfterRender(IRequestCycle)} is invoked in a 
     *  <code>finally</code> block.
     * 	 
     *  <p>Subclasses should not override this method; instead they
     *  will implement {@link #renderComponent(IMarkupWriter, IRequestCycle)}.
     * 
     *  @since 2.0.3
     * 
     **/

    public final void render(IMarkupWriter writer, IRequestCycle cycle)
    {
        try
        {
            Tapestry.clearMethodInvocations();

            prepareForRender(cycle);

            Tapestry.checkMethodInvocation(PREPAREFORRENDER_METHOD_ID, "prepareForRender()", this);

            renderComponent(writer, cycle);
        }
        finally
        {
            Tapestry.clearMethodInvocations();

            cleanupAfterRender(cycle);

            Tapestry.checkMethodInvocation(
                CLEANUPAFTERRENDER_METHOD_ID,
                "cleanupAfterRender()",
                this);
        }
    }

    /**
     *  Invoked by {@link #render(IMarkupWriter, IRequestCycle)}
     *  to prepare the component to render.  This implementation
     *  sets JavaBeans properties from matching bound parameters.
     *  Subclasses that override this method must invoke this
     *  implementation as well.
     * 
     *  @since 2.0.3
     * 
     **/

    protected void prepareForRender(IRequestCycle cycle)
    {
        Tapestry.addMethodInvocation(PREPAREFORRENDER_METHOD_ID);

        if (_parameterManager == null)
        {
            // Pages inherit from this class too, but pages (by definition)
            // never have parameters.

            if (getSpecification().isPageSpecification())
                return;

            _parameterManager = new ParameterManager(this);
        }

        _parameterManager.setParameters(cycle);
    }

    /**
     *  Invoked by {@link #render(IMarkupWriter, IRequestCycle)}
     *  to actually render the component (with any parameter values
     *  already set).  This is the method that subclasses must implement.
     * 
     *  @since 2.0.3
     * 
     **/

    protected abstract void renderComponent(IMarkupWriter writer, IRequestCycle cycle);

    /**
     *  Invoked by {@link #render(IMarkupWriter, IRequestCycle)}
     *  after the component renders, to clear any parameters back to
     *  null (or 0, or false, or whatever the correct default is).  
     *  Primarily, this is used to ensure
     *  that the component doesn't hold onto any objects that could
     *  otherwise be garbage collected.
     * 
     *  <p>Subclasses may override this implementation, but must
     *  also invoke it.
     * 
     *  @since 2.0.3
     * 
     **/

    protected void cleanupAfterRender(IRequestCycle cycle)
    {
        Tapestry.addMethodInvocation(CLEANUPAFTERRENDER_METHOD_ID);

        if (_parameterManager != null)
            _parameterManager.resetParameters(cycle);
    }

    /** @since 3.0 **/

    public IMessages getMessages()
    {
        if (_strings == null)
            _strings = getPage().getEngine().getComponentMessagesSource().getMessages(this);

        return _strings;
    }

    /**
     *  Obtains the {@link IMessages} for this component
     *  (if necessary), and gets the string from it.
     * 
     **/

    public String getString(String key)
    {
        return getMessages().getMessage(key);
    }

    public String getMessage(String key)
    {
        // Invoke the deprecated implementation (for code coverage reasons).
        // In 3.1, remove getString() and move its implementation
        // here.

        return getString(key);
    }

    /**
     *  Formats a message string, using
     *  {@link IMessages#format(java.lang.String, java.lang.Object[])}.
     * 
     *  @param key the key used to obtain a localized pattern using
     *  {@link #getString(String)}
     *  @param arguments passed to the formatter
     * 
     *  @since 2.2
     *  @deprecated To be removed in 3.1.  Use {@link #format(String, Object[])} instead.
     **/

    public String formatString(String key, Object[] arguments)
    {
        return getMessages().format(key, arguments);
    }

    /**
     * Formats a localized message string, using
     * {@link IMessages#format(java.lang.String, java.lang.Object[])}.
     *
     * @param key the key used to obtain a localized pattern using
     * {@link #getString(String)}
     * @param arguments passed to the formatter
     * 
     * @since 3.0
     */

    public String format(String key, Object[] arguments)
    {
        // SOP: New name invokes deprecated method (consistency and 
        // code coverage); in 3.1 we move the implementation here.

        return formatString(key, arguments);
    }

    /**
     *  Convienience method for invoking {@link IMessages#format(String, Object[])}
     * 
     *  @since 2.2
     *  @deprecated To be removed in 3.1.  Use {@link #format(String, Object)} instead.
     * 
     **/

    public String formatString(String key, Object argument)
    {
        return getMessages().format(key, argument);
    }

    /**
     * Convienience method for invoking {@link IMessages#format(String, Object)}
     * 
     * @since 3.0
     * 
     */

    public String format(String key, Object argument)
    {
        return formatString(key, argument);
    }

    /**
     *  Convienience method for invoking {@link IMessages#format(String, Object, Object)}.
     * 
     *  @since 2.2
     *  @deprecated To be removed in 3.1.  Use {@link #format(String, Object, Object)} instead.
     **/

    public String formatString(String key, Object argument1, Object argument2)
    {
        return getMessages().format(key, argument1, argument2);
    }

    /**
     * Convienience method for invoking {@link IMessages#format(String, Object, Object)}.
     * 
     * @since 3.0
     * 
     **/

    public String format(String key, Object argument1, Object argument2)
    {
        return formatString(key, argument1, argument2);
    }

    /**
     * Convienience method for {@link IMessages#format(String, Object, Object, Object)}.
     * 
     * @since 2.2
     * @deprecated To be removed in 3.1.  Use {@link #format(String, Object, Object, Object)} instead.
     */

    public String formatString(String key, Object argument1, Object argument2, Object argument3)
    {
        return getMessages().format(key, argument1, argument2, argument3);
    }

    /**
     * Convienience method for {@link IMessages#format(String, Object, Object, Object)}.
     * 
     * @since 3.0
     */

    public String format(String key, Object argument1, Object argument2, Object argument3)
    {
        return formatString(key, argument1, argument2, argument3);
    }

    public INamespace getNamespace()
    {
        return _namespace;
    }

    public void setNamespace(INamespace namespace)
    {
        _namespace = namespace;
    }

    /**
     *  Returns the body of the component, the element (which may be static HTML or components)
     *  that the component immediately wraps.  May return null.  Do not modify the returned
     *  array.  The array may be padded with nulls.
     * 
     *  @since 2.3
     *  @see #getBodyCount()
     * 
     **/

    public IRender[] getBody()
    {
        return _body;
    }

    /**
     *  Returns the active number of elements in the the body, which may be zero.
     * 
     *  @since 2.3
     *  @see #getBody()
     * 
     **/

    public int getBodyCount()
    {
        return _bodyCount;
    }

    /**
     * Empty implementation of
     * {@link org.apache.tapestry.event.PageRenderListener#pageEndRender(PageEvent)}.
     * This allows classes to implement
     * {@link org.apache.tapestry.event.PageRenderListener} and only
     * implement the
     * {@link org.apache.tapestry.event.PageRenderListener#pageBeginRender(PageEvent)}
     * method.
     * @since 3.0
     */

    public void pageEndRender(PageEvent event)
    {
    }

    /**
     *  Sets a property of a component.
     *  @see IComponent 
     *  @since 3.0
     */
    public void setProperty(String propertyName, Object value)
    {
        IResourceResolver resolver = getResourceResolver();
        OgnlUtils.set(propertyName, resolver, this, value);
    }
    /**
     *  Gets a property of a component.
     *  @see IComponent 
     *  @since 3.0
     */
    public Object getProperty(String propertyName)
    {
        IResourceResolver resolver = getResourceResolver();
        return OgnlUtils.get(propertyName, resolver, this);
    }
}