//  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 java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

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.ChangeObserver;
import org.apache.tapestry.event.PageDetachListener;
import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.event.PageRenderListener;
import org.apache.tapestry.event.PageValidateListener;
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;

/**
 *  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 Collections.unmodifiableMap(_components);

    }

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

        return Collections.unmodifiableMap(_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);
    }
}