/*
 * Created on 2004-2-29
 *
 * To change the template for this generated file go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
package org.huihoo.willow;

import java.beans.PropertyChangeListener;

/**
 * @author zosatapo
 *
 * To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
public interface Container
{

	// ----------------------------------------------------- Manifest TypeConstants

	/**
	 * The ContainerEvent event type sent when a child container is added
	 * by <code>addChild()</code>.
	 */
	public static final String ADD_CHILD_EVENT = "addChild";

	/**
	 * The ContainerEvent event type sent when a child container is removed
	 * by <code>removeChild()</code>.
	 */
	public static final String REMOVE_CHILD_EVENT = "removeChild";

	// ------------------------------------------------------------- Properties

	/**
	 * Return descriptive information about this Container implementation and
	 * the corresponding version number, in the format
	 * <code>&lt;description&gt;/&lt;version&gt;</code>.
	 */
	public String getInfo();

	/**
	 * Return the Loader with which this Container is associated.  If there is
	 * no associated Loader, return the Loader associated with our parent
	 * Container (if any); otherwise, return <code>null</code>.
	 */
	public Loader getLoader();

	/**
	 * Set the Loader with which this Container is associated.
	 *
	 * @param loader The newly associated loader
	 */
	public void setLoader(Loader loader);

	/**
	 * Return the Logger with which this Container is associated.  If there is
	 * no associated Logger, return the Logger associated with our parent
	 * Container (if any); otherwise return <code>null</code>.
	 */
	public Logger getLogger();

	/**
	 * Set the Logger with which this Container is associated.
	 *
	 * @param logger The newly associated Logger
	 */
	public void setLogger(Logger logger);


	/**
	 * Get the delay between the invocation of the backgroundProcess method on
	 * this container and its children. Child containers will not be invoked
	 * if their delay value is not negative (which would mean they are using 
	 * their own thread). Setting this to a positive value will cause 
	 * a thread to be spawn. After waiting the specified amount of time, 
	 * the thread will invoke the executePeriodic method on this container 
	 * and all its children.
	 */
	public int getBackgroundProcessorDelay();

	/**
	 * Set the delay between the invocation of the execute method on this
	 * container and its children.
	 * 
	 * @param delay The delay in seconds between the invocation of 
	 *              backgroundProcess methods
	 */
	public void setBackgroundProcessorDelay(int delay);

	/**
	 * Return a name string (suitable for use by humans) that describes this
	 * Container.  Within the set of child containers belonging to a particular
	 * parent, Container names must be unique.
	 */
	public String getName();

	/**
	 * Set a name string (suitable for use by humans) that describes this
	 * Container.  Within the set of child containers belonging to a particular
	 * parent, Container names must be unique.
	 *
	 * @param name New name of this container
	 *
	 * @exception IllegalStateException if this Container has already been
	 *  added to the children of a parent Container (after which the name
	 *  may not be changed)
	 */
	public void setName(String name);

	/**
	 * Return the Container for which this Container is a child, if there is
	 * one.  If there is no defined parent, return <code>null</code>.
	 */
	public Container getParent();

	/**
	 * Set the parent Container to which this Container is being added as a
	 * child.  This Container may refuse to become attached to the specified
	 * Container by throwing an exception.
	 *
	 * @param container Container to which this Container is being added
	 *  as a child
	 *
	 * @exception IllegalArgumentException if this Container refuses to become
	 *  attached to the specified Container
	 */
	public void setParent(Container container);

	/**
	 * Return the parent class loader (if any) for workflow applications.
	 */
	public ClassLoader getParentClassLoader();

	/**
	 * Set the parent class loader (if any) for web applications.
	 * This call is meaningful only <strong>before</strong> a Loader has
	 * been configured, and the specified value (if non-null) should be
	 * passed as an argument to the class loader constructor.
	 *
	 * @param parent The new parent class loader
	 */
	public void setParentClassLoader(ClassLoader parent);
	
	// --------------------------------------------------------- Public Methods

	/**
	 * Execute a periodic task, such as reloading, etc. This method will be
	 * invoked inside the classloading context of this container. Unexpected
	 * throwables will be caught and logged.
	 */
	public void backgroundProcess();

	/**
	 * Add a new child Container to those associated with this Container,
	 * if supported.  Prior to adding this Container to the set of children,
	 * the child's <code>setParent()</code> method must be called, with this
	 * Container as an argument.  This method may thrown an
	 * <code>IllegalArgumentException</code> if this Container chooses not
	 * to be attached to the specified Container, in which case it is not added
	 *
	 * @param child New child Container to be added
	 *
	 * @exception IllegalArgumentException if this exception is thrown by
	 *  the <code>setParent()</code> method of the child Container
	 * @exception IllegalArgumentException if the new child does not have
	 *  a name unique from that of existing children of this Container
	 * @exception IllegalStateException if this Container does not support
	 *  child Containers
	 */
	public void addChild(Container child);

	/**
	 * Add a container event listener to this component.
	 *
	 * @param listener The listener to add
	 */
	public void addContainerListener(ContainerListener listener);

	/**
	 * Add a property change listener to this component.
	 *
	 * @param listener The listener to add
	 */
	public void addPropertyChangeListener(PropertyChangeListener listener);

	/**
	 * Return the child Container, associated with this Container, with
	 * the specified name (if any); otherwise, return <code>null</code>
	 *
	 * @param name Name of the child Container to be retrieved
	 */
	public Container findChild(String name);

	/**
	 * Return the set of children Containers associated with this Container.
	 * If this Container has no children, a zero-length array is returned.
	 */
	public Container[] findChildren();

	/**
	 * Return the set of container listeners associated with this Container.
	 * If this Container has no registered container listeners, a zero-length
	 * array is returned.
	 */
	public ContainerListener[] findContainerListeners();

	/**
	 * Remove an existing child Container from association with this parent
	 * Container.
	 *
	 * @param child Existing child Container to be removed
	 */
	public void removeChild(Container child);

	/**
	 * Remove a container event listener from this component.
	 *
	 * @param listener The listener to remove
	 */
	public void removeContainerListener(ContainerListener listener);

	/**
	 * Remove a property change listener from this component.
	 *
	 * @param listener The listener to remove
	 */
	public void removePropertyChangeListener(PropertyChangeListener listener);

}
