//  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.ExpressionEvaluator;
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.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;

    private ExpressionEvaluator _evaluator;

    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))
		{
            return (IBinding) getEvaluator().read(this, bindingPropertyName);
            //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))
		{
            getEvaluator().write(this, bindingPropertyName, binding);
            // 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)
    {
    }

    ExpressionEvaluator getEvaluator()
    {
        if (_evaluator == null)
        {
            _evaluator = _page.getEngine().getExpressionEvaluator();
        }

        return _evaluator;
    }

    /**
     *  Sets a property of a component.
     *  @see IComponent 
     *  @since 3.0
     */
    public void setProperty(String propertyName, Object value)
    {
        getEvaluator().write(this, propertyName, 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)
    {
        return getEvaluator().read(this, propertyName);
        
        //IResourceResolver resolver = getResourceResolver();
        //return OgnlUtils.get(propertyName, resolver, this);
    }
}