/*
 * 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.compiler.utils;

import java.util.Collection;
import java.util.Iterator;

import edu.udo.cs.miningmart.db.DB;
import edu.udo.cs.miningmart.exception.M4Exception;
import edu.udo.cs.miningmart.m4.core.BaseAttribute;
import edu.udo.cs.miningmart.m4.core.Column;
import edu.udo.cs.miningmart.m4.utils.Print;

/**
 * A tool similar to <code>Binarify</code>. It creates a Step that uses
 * the GenericFeatureConstruction operator to pivotize one attribute. Pivotizing 
 * means that for each value that occurs in the column of an "index" attribute, a new
 * attribute is created. This new attribute contains the value of the pivotized 
 * attribute iff the index attribute took the value that corresponds to the new
 * attribute. Otherwise the new attribute contains <code>NULL</code>.
 * 
 * Example (I = index attribute, P = pivotised attribute)
 * 
 * Input              Output
 * 
 * ID | I | P         ID | P_M | P_F
 * ----------         --------------
 * 1  | M | 4   =>     1 |  4  | NULL
 * 2  | M | 2          2 |  2  | NULL
 * 3  | F | 6          3 | NULL| 6
 *
 * @author Timm Euler
 * @version $Id: PivotizeWithoutAggregation.java,v 1.3 2006/04/11 14:10:18 euler Exp $
 */
public class PivotizeWithoutAggregation extends AttributeCreationTool {	
	
	// The op_id of the operator that the step created by this tool uses
	private final int GENERIC_FEAT_CONSTR_ID = 90;
	
	private Column myPivotColumn;
	private BaseAttribute myPivotBA;

	/**
	 * Constructor. We expect the input concept, the index attribute,
	 * the attribute to be pivotised and the chain to which the new step
	 * will belong.
	 * 
	 * @param inputConcept The Input Concept for the Step to be created.
	 * @param indexBA The index attribute
	 * @param pivotBA The attribute to be pivotised
	 * @param chain The Chain to which to add the new Step
	 */
	public PivotizeWithoutAggregation( edu.udo.cs.miningmart.m4.Concept inputConcept, 
			                           edu.udo.cs.miningmart.m4.BaseAttribute indexBA, 
			                           edu.udo.cs.miningmart.m4.BaseAttribute pivotBA,
			                           edu.udo.cs.miningmart.m4.Chain chain)
		throws M4Exception
	{
		super(inputConcept, indexBA, chain);
		
		String msgIntro = "Constructor of " + this.getClass().getName() + ":\n";
		
		if (pivotBA == null) {
			throw new M4Exception(msgIntro + "The given Pivot BaseAttribute is NULL!");
		}
		if (! inputConcept.equals(pivotBA.getConcept())) {
			throw new M4Exception(msgIntro + "The specified BaseAttribute to be pivotized does not belong to the InputConcept!");
		}
			
		this.myPivotBA = (BaseAttribute) pivotBA;
		
		Collection pivotColCollection = this.myPivotBA.getColumns();
		if (pivotColCollection.size() != 1) {
			boolean exception = true;
			if (pivotColCollection.size() > 1) {
				Iterator it = pivotColCollection.iterator();
			 L: while (it.hasNext()) {
					Column col = (Column) it.next();
					if (col != null && this.myInputColumnset.equals(col.getColumnset())) {
						this.myDB.getCasePrintObject().doPrint(Print.MAX, msgIntro +
							"WARNING: found multiple Columns in Pivot BaseAttribute, choosing the one linked to the found Columnset!");
						pivotColCollection.clear();
						pivotColCollection.add(col);
						exception = false;
						break L;
					}
				}	
			}
			if (exception) {
				throw new M4Exception(msgIntro + "Found no (suitable) Column for Pivot BaseAttribute!");
			}
		}
		this.myPivotColumn = (Column) pivotColCollection.iterator().next();
		if (this.myPivotColumn == null) {
			throw new M4Exception(msgIntro + "Pivot BaseAttribute has a null entry instead of the column!");
		}
	}	
	
	/**
	 * @see miningmart.compiler.utils.AttributeCreationTool#insertSpecificParameters(int, int, String)
	 */
	protected void insertSpecificParameters(int loopNr, int parNr, String targetValS) throws M4Exception {
		
		int stringConDT =  1; // conceptual datatype 'nominal'

		boolean indexBaNominal = (this.myIndexBA.getConceptualDataType() == 1 ||
		                          this.myIndexBA.getConceptualDataType() == 2);

		// create the SQL String which will be translated by GenericFeatureConstruction:
		String theSQL = "(CASE WHEN " +
		                this.myIndexBA.getName() + 
		                " = " +
		                (indexBaNominal ? DB.quote(targetValS) : targetValS) +
		                " THEN " +
		                this.myPivotBA.getName() +
		                " ELSE NULL END)";

		this.createInputValueParameter("SQL_String", loopNr, theSQL, stringConDT, parNr++);
	}
	
	/**
	 * @see miningmart.compiler.utils.AttributeCreationTool#getIdOfOperator()
	 */	 
	protected int getIdOfOperator() {
		return GENERIC_FEAT_CONSTR_ID;
	}
	
	/**
	 * @see miningmart.compiler.utils.AttributeCreationTool#getNameOfOperator()
	 */	 
	protected String getNameOfOperator() {
		return "GenericFeatureConstruction";
	}
	 
	/**
	 * @see miningmart.compiler.utils.AttributeCreationTool#getNameOfNewStep()
	 */
	protected String getNameOfNewStep() {
		return "Pivotize Attribute w/o Aggr.";
	}
	
	/**
	 * @see miningmart.compiler.utils.AttributeCreationTool#getConceptualDatatypeNameOfNewAttributes()
	 */	 
	protected String getConceptualDatatypeNameOfNewAttributes() throws M4Exception {
		return this.myIndexBA.getConceptualDataTypeName();
	}
}
/*
 * Historie
 * --------
 *
 * $Log: PivotizeWithoutAggregation.java,v $
 * Revision 1.3  2006/04/11 14:10:18  euler
 * Updated license text.
 *
 * Revision 1.2  2006/04/06 16:31:18  euler
 * Prepended license remark.
 *
 * Revision 1.1  2006/01/03 09:54:35  hakenjos
 * Initial version!
 *
 */
