/*
Copyright (c) 2002, Matthias Bauer, LIVINGLOGIC AG, BAYREUTH
All rights reserved.

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are 
met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright 
       notice, this list of conditions and the following disclaimer in the 
       documentation and/or other materials provided with the distribution.
    3. The end-user documentation included with the redistribution, if
       any, must include the following acknowlegement:
       "This product includes software developed by 
        Matthias Bauer, LIVINGLOGIC AG, BAYREUTH 
        (http://www.livinglogic.de/)."
       Alternately, this acknowlegement may appear in the software itself,
       if and wherever such third-party acknowlegements normally appear.
    4. Neither the name of Matthias Bauer, nor the LIVINGLOGIC AG nor the 
       names of the other contributors may be used to endorse or promote 
       products derived from this software without specific prior written
       permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF SUCH DAMAGE.
 */

package es.ejie.frmk.presentacion.base;


import java.io.Serializable;
import java.util.Hashtable;
import java.util.Set;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;


/**
 * Class that represents and stores information about
 * a labeled workflow.
 *
 * @author A. Lamm, M. Bauer
 * @version 1.0
 */

public class Q70Workflow implements Serializable
{
	/**
	 * The registered attributes
	 */
	private Hashtable workflowAttributes = null;
	
	/**
	 * The registered cleanup objects
	 */
	private Vector workflowCleanupObjects = null;
	
	/**
	 * The labels of the registered cleanup objects and the reference to their instance
	 */
	private Hashtable workflowCleanupObjectTable = null;
	
	/**
	 * @return The names of all known cleanup objects for this workflow. May be null
	 *    if there are none
	 */
	public Set getCleanupObjectNames() 
	{
		Set retVal = null;
		
		if(null != workflowCleanupObjects) 
		{
			retVal = workflowCleanupObjectTable.keySet();
		}
		return retVal;
	}

	/**
	 * @return The names of all known attributes for this workflow. May be null if
	 * there are no known attributes.
	 */
	public Set getAttributeNames() 
	{
		Set retVal = null;
		
		if (null != workflowAttributes) 
		{
			retVal = workflowAttributes.keySet();
		}
		
		return retVal;
	}

	/**
	 * Retrieve the value associated with the specified name.
	 * @param attributeName The name of the requested value
	 * @return The value associated with the specified name. May be null if the
	 *     attribute with the specified name is unknown.
	 */
	public Object getAttribute(String attributeName) 
	{
		Object retVal = null;

		if (null != workflowAttributes) 
		{
			retVal = workflowAttributes.get(attributeName);
		}
		
		return retVal;
	}

	/**
	 * Remove the value associated with the specified name and return it.
	 * @param attributeName The name of the value that is to be removed.
	 * @return The value associated with the specified name that was removed.
	 *    May be null if the attribute with the specified name is unknown.
	 */
	public Object removeAttribute(String attributeName) 
	{
		Object retVal = null;

		if (null != workflowAttributes) 
		{
			retVal = workflowAttributes.remove(attributeName);
		}
		
		return retVal;
	}

	/**
	 * Associate a value with the specified name which will remain available until
	 * this workflow terminates or it is removed using the removeAttribute() method.
	 * @param attributeName The name associated with the value to be stored.
	 * @param attributeValue The value to be associated with the name and stored. If
	 * an attribute is already stored under the specified name for this workflow, it
	 * is replaced by this one.
	 * @throws IllegalArgmentException If the attribute name is null.
	 */
	public void setAttribute(String attributeName, Object attributeValue)
		throws IllegalArgumentException 
	{
		if(null == attributeName) 
		{
			throw new IllegalArgumentException("Attribute name cannot be null");
		}

		if (null == workflowAttributes) 
		{
			workflowAttributes = new Hashtable();
		}

		workflowAttributes.put(attributeName, attributeValue);
	}

	/**
	 * Clears all known names/values.
	 */
	public void clearAttributes() 
	{
		if(null != workflowAttributes) 
		{
			workflowAttributes.clear();
			workflowAttributes = null;
		}
	}

	/**
	 * Registers a named implementation of the Q70WorkflowCleanup command pattern
	 * to be processed at the termination of this workflow. The order in which
	 * cleanup objects are executed is the reverse order in which they are added, i. e.
	 * the object that was added last will be processed first. 
	 * @param name symbolic name under which the object is known. If an object is
	 *     already registered under the specified name for this workflow, an exception
	 *     is thrown
	 * @param object command pattern implementation to be processed.
	 * @exception IllegalArgumentException, if a cleanup object with the name of an 
	 *     already existing one is added 
	 */
	public void addCleanupObject(String name, Q70WorkflowCleanup object)
		throws IllegalArgumentException
	{
		if (null == workflowCleanupObjects) 
		{
			workflowCleanupObjects = new Vector();
			workflowCleanupObjectTable = new Hashtable();
		}
		else
		{
			if (workflowCleanupObjectTable.containsKey(name))
			{
				throw new IllegalArgumentException("There is already a cleanup object with the specified name defined.");
			}
		}
		workflowCleanupObjects.add(object);
		workflowCleanupObjectTable.put(name, object);
	}

	/**
	 * Called by the framework at the point of workflow termination to process the
	 * set of registered cleanup objects.
	 * @param request The servlet request we are processing
	 */
	void performCleanup(HttpServletRequest request) 
	{
		int size = 0;

		if (null != workflowCleanupObjects) 
		{
			size = workflowCleanupObjects.size();
		}

		for (int i=size-1; i>=0; i--)
		{
			((Q70WorkflowCleanup) workflowCleanupObjects.get(i)).cleanup(request);
		}
	}

	/**
	 * The label of the current state
	 */
	private String currentState;

	/**
	 * Returns the label of the current state.
	 */
	public String getCurrentState()
	{
		return currentState;
	}

	/**
	 * Sets the label of the current state.
	 * @param currentState the label of the current state
	 */
	public void setCurrentState(String currentState)
	{
		this.currentState = currentState;
	}

	/**
	 * The set of labels of the states one of which has to follow the
	 * current state.
	 */
	private Set definedNextStates;

	/**
	 * Returns the set of labels of the states one of which has to
	 * follow the current state.
	 */
	public Set getDefinedNextStates()
	{
		return definedNextStates;
	}

	/**
	 * Sets a new value for the set of labels of the states one of
	 * which has to follow the current state.
	 * @param definedNextStates the set of labels of the states
	 *      one of which has to follow the current state.
	 */
	public void setDefinedNextStates(Set definedNextStates)
	{
		this.definedNextStates = definedNextStates;
	}
}

