//----------------------------BEGIN LICENSE----------------------------
/* 
 * Willow : the Open Source WorkFlow Project
 * Distributable under GNU LGPL license by gun.org
 *
 * Copyright (C) 2004-2010  huihoo.org 
 * Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com> 
 * 
 * ====================================================================
 * Project Homepage : http://www.huihoo.org/willow
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : willow@lists.sourceforge.net 
 */
//----------------------------END  LICENSE-----------------------------
package org.huihoo.willow;

import java.beans.PropertyChangeListener;

import javax.naming.directory.DirContext;

public interface Container
{

	// ------------------------------------------------------------- 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) workflow applications.
	 */
	public ClassLoader getParentClassLoader();

	
	/**
	 * Set the parent class loader (if any) for workflow 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);
	

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


	/**
	 * Set the RealmDatabase with which this Container is associated.
	 *
	 * @param realm The newly associated RealmDatabase
	 */
	public void setRealmDatabase(RealmDatabase realm);
	

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


	/**
	 * Set the Resources object with which this Container is associated.
	 *
	 * @param resources The newly associated Resources
	 */
	public void setResources(DirContext resources);
	
	// --------------------------------------------------------- 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 Context to those associated with this ,
	 * if supported.  Prior to adding this Context 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 Context chooses not
	 * to be attached to the specified Context, in which case it is not added
	 *
	 * @param child New child Context to be added
	 *
	 * @exception IllegalArgumentException if this exception is thrown by
	 *  the <code>setEngine()</code> method of the child Context
	 * @exception IllegalArgumentException if the new child does not have
	 *  a name unique from that of existing children of this Context
	 */
	public void addChild(Container child);

	
	/**
	 * Return the child Container, associated with this Context, 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();


	/**
	 * Remove an existing child Container from association with this parent
	 * Context.
	 *
	 * @param child Existing child Container to be removed
	 */
	public void removeChild(Container child);
	
	
	/**
	 * Add a container event listener to this component.
	 *
	 * @param listener The listener to add
	 */
	public void addContainerListener(ContainerListener listener);
	
	
	/**
	 * 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 a container event listener from this component.
	 *
	 * @param listener The listener to remove
	 */
	public void removeContainerListener(ContainerListener listener);
	
	
	/**
	 * Add a property change listener to this component.
	 *
	 * @param listener The listener to add
	 */
	public void addPropertyChangeListener(PropertyChangeListener listener);
	/**
	 * Remove a property change listener from this component.
	 *
	 * @param listener The listener to remove
	 */
	public void removePropertyChangeListener(PropertyChangeListener listener);

}
