/*
 * MiningMart Version 1.0
 * 
 * Copyright (C) 2006 Martin Scholz, Timm Euler, 
 *                    Daniel Hakenjos, Katharina Morik
 *
 * Contact: miningmart@ls8.cs.uni-dortmund.de
 *
 * A list of contributing developers (other than the copyright 
 * holders) can be found at
 * http://mmart.cs.uni-dortmund.de/downloads/download.html
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program, see the file MM_HOME/LICENSE; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 */
package edu.udo.cs.miningmart.m4.core;

import java.io.Serializable;
import java.util.HashMap;

import edu.udo.cs.miningmart.exception.M4Exception;

/**
 * A class to store the parameters of an operator (step).
 * 
 * @author Martin Scholz
 * @version $Id: ParamDict.java,v 1.3 2006/04/11 14:10:14 euler Exp $
*/
public class ParamDict implements Serializable, edu.udo.cs.miningmart.m4.ParamDict {

	/** Stores the parameters: */
	private final HashMap entries = new HashMap();

	// To incorporate the loopNr into the parameter name string the
	// following string plus loopNr is appended to the name, before it
	// is used as the key in the 'entries' HashMap.
	private static final String LOOPNR_DELIMITER = " #";

	/**
	 *  Add a parameter to the dictionary. For loopsteps the method with additional
	 * loopNr parameter has to be used.
	 * @param paramName the name of the parameter as found in table <i>OP_PARAM_T</i>
	 * @param theParameter a ParameterArray object representing a parameter to be stored.
	 * */
	public void put(String paramName, edu.udo.cs.miningmart.m4.ParameterArray theParameter)
		throws M4Exception {
		this.put(paramName, 0, theParameter);
	}
	
	/**
	 * @see put(String, Object), just with the loop nr as an additional parameter
	 * */
	public void put(String paramName, int loopNr, edu.udo.cs.miningmart.m4.ParameterArray theParameter)
		throws M4Exception {
		if (theParameter == null) {
			throw new M4Exception(
				"Operator.autoLoad() mechanism, internal class ParamDict:\n"
					+ "Error - Operator tried to insert null into parameter dictionary!");
		}
		if (this.containsKey(paramName, loopNr))
			throw new M4Exception("Could not store parameter in autoLoad() of class Operator: Already loaded!");
		if (loopNr > 1 && !this.containsKey(paramName, 1))
			throw new M4Exception(
				"Could not store parameter in autoLoad() of class Operator:\n"
					+ "Can't store loop nr."
					+ loopNr
					+ " before storing loop nr.1!");
		this.store(paramName, loopNr, theParameter);
	}

	/**
	 * replaces the parameter of referenced by a specific name for a specific loop nr
	 * @param paramName the name of the key - the parameter name
	 * @param loopNr the loop nr
	 * @param theParameter the new parameter value
	 */
	public void replace(String paramName, int loopNr, edu.udo.cs.miningmart.m4.ParameterArray theParameter)
		throws M4Exception
	{
		// For looped steps the loop numbers in the dictionary start with "1",
		// so we need to increase the number in this case:
		if (loopNr > 0 || this.isLooped(paramName)) {
			loopNr++;
		}
		if (this.remove(paramName, loopNr)) {
			this.store(paramName, loopNr, theParameter);
		}
		else throw new M4Exception(
				"Could not replace parameter " + paramName
					+ ", loopNr: " + loopNr
					+ " in autoLoad() of class Operator:\nOld parameter value not found!");
	}

	/**
	 * Checks whether for the given parameter name an entry is stored.
	 * This method is independent of loopstep or not, in both cases any
	 * occurence will be noticed.
	 * @param paramName the name of the parameter
	 * */
	public boolean containsKey(String paramName) {
		return (this.containsKey(paramName, 0) || this.containsKey(paramName, 1));
	}

	/** 
	 * Checks whether for the given parameter name and a specific loop nr.
	 * a parameter is stored.
	 * */
	public boolean containsKey(String paramName, int loopNr) {
		return (entries.containsKey(paramName + LOOPNR_DELIMITER + loopNr));
	}

	/** 
	 * Checks whether the given object exists as a value in the dictionary.
	 * @param paramArray the object to check for
	 * @return <code>true</code> iff the object was found
	 * */
	public boolean containsParamArray(edu.udo.cs.miningmart.m4.ParameterArray paramArray) {
		return entries.values().contains(paramArray);
	}

	/** 
	 * If the given object exists as a value in the dictionary, then
	 * this method removes it.
	 * @param paramArray the object to remove
	 * @return <code>true</code> iff the object could be removed
	 * */
	public boolean removeParamArray(edu.udo.cs.miningmart.m4.ParameterArray paramArray) {
		return entries.values().remove(paramArray);
	}

	/**
	 * @param paramName the name of the parameter to be looked up 
	 * @return the parameter if stored, <code>null</code> otherwise.
	 * in case of loopsteps use the method <code>get(String, int)</code> instead.
	 * */
	public edu.udo.cs.miningmart.m4.ParameterArray get(String paramName) throws M4Exception {
		return this.get(paramName, 0);
	}

	/**
	 * @param paramName the name of the parameter to be looked up 
	 * @param loopNr the loop nr. for which to look up the parameter.
	 * Note that the first loopNr is "0", no matter if we have a looped
	 * parameter or not.
	 * @return the parameter if stored, <code>null</code> otherwise.
	 * */
	public edu.udo.cs.miningmart.m4.ParameterArray get(String paramName, int loopNr) {
		String key = paramName + LOOPNR_DELIMITER + loopNr;
		return (edu.udo.cs.miningmart.m4.ParameterArray) this.entries.get(key);
	}

	/**
	 * @param paramName name of a parameter
	 * @return <code>true</code> iff the specified parameter is looped in the current step.
	 * */
	public boolean isLooped(String paramName) {		
		return (
			this.containsKey(paramName, 1) && !this.containsKey(paramName, 0));
	}

	private void store(String paramName, int loopNr, edu.udo.cs.miningmart.m4.ParameterArray theParameter)
	{
		String key = paramName + LOOPNR_DELIMITER + loopNr;
		this.entries.put(key, theParameter);
	}

	private boolean remove(String paramName, int loopNr) {
		String key = paramName + LOOPNR_DELIMITER + loopNr;
		return (this.entries.remove(key) != null);
	}
}
/*
 * Historie
 * --------
 * 
 * $Log: ParamDict.java,v $
 * Revision 1.3  2006/04/11 14:10:14  euler
 * Updated license text.
 *
 * Revision 1.2  2006/04/06 16:31:13  euler
 * Prepended license remark.
 *
 * Revision 1.1  2006/01/03 09:54:17  hakenjos
 * Initial version!
 *
 */
