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

import java.sql.SQLException;

/**
 * @author Martin Scholz
 * @version $Id: SMF.java,v 1.4 2006/04/11 14:10:16 euler Exp $
 */
public class SMF {

    private final DbConnector connector;
    private final Windowing   window; // for the input
    private final OutputColumnset out; // for the output

    private static final int INDEXONATTRIB = 2;

    /**
     * Constructor
     * @param dbc source of database connection if not used as stored procedure
     * @param source source table
     * @param time   time column of source table
     * @param column value column of source table
     * @param target name of the target table to be created
     * @param timeStartOut name of the interval start attribute
     * for the output table
     * @param timeEndOut name of the interval end attribute
     * for the output table
     * @param columnOut name of the output value attribute
     * @param windowSize size of the window
     * @param distance step size for windowing
     * @throws SQLException
     * @throws TimeOperatorException
    */    
    public SMF(BusinessDbConnectionSource dbc,
				String source, String time, String column, String target,
				String timeStartOut, String timeEndOut, String columnOut,
				int windowSize, int distance)
		throws SQLException, TimeOperatorException
	{
		this.connector = new DbConnector(dbc);
		final String timeDT =
			DataType.getColumnDataType(source, time, this.connector);
		final String columnDT =
			DataType.getColumnDataType(source, column, this.connector);

		// Input:
		final Attribute timeAttr = new Attribute(time, timeDT, timeDT);
		final Attribute columnAttr =
			new Attribute(column, columnDT, dbc.getNameOfNumericDatatype());
		if (!timeAttr.isConvertable())
			DataType.wrongDataType(target, timeAttr);
		if (!columnAttr.isConvertable())
			DataType.wrongDataType(target, columnAttr);

		// Output:
		final Attribute timeStartAttr =
			new Attribute(timeStartOut, timeDT, timeDT);
		final Attribute timeEndAttr = new Attribute(timeEndOut, timeDT, timeDT);
		final Attribute columnOutAttr =
			new Attribute(columnOut, columnDT, dbc.getNameOfNumericDatatype());
		Attribute[] allAttributes =
			new Attribute[] { timeStartAttr, timeEndAttr, columnOutAttr };
		this.out =
			new OutputColumnset(
				target,
				allAttributes,
				this.connector.getConnection());

		// Prepare Windowing:
		window = new Windowing(windowSize, distance, this.connector);
		if (!window
			.open(
				"SELECT "
					+ columnAttr.getConvertedInput()
					+ ", "
					+ timeAttr.getConvertedInput()
					+ " FROM "
					+ source)) {
			DbConnector.infoOutput("Error while opening " + source);
			throw new TimeOperatorException(
				"Could not read from table '" + source + "'!");
		}
	}
    
    /** 
     * Method calc() reads from the column(s) specified in the constructor
     * and writes to the specified target, using windowing.
     * <!-- Finally an index is created on the target table. -->
     */
    public void calc() throws TimeOperatorException {
		String[] ret = null;
		do {
	    	ret = getWindow().getNextWnd();
		    if (ret != null) {
				Long start = new Long(this.getWindow().getTimeFirstEntry());
				Long   end = new Long(this.getWindow().getTimeLastEntry());
				Double val = new Double(calcSum(ret) / ret.length);
				this.getOutputColumnset().insert(new Object[] { start, end, val });
	    	}
		} while (ret != null);

		// this.getOutputColumnset().createIndexOn(INDEXONATTRIB);
		// *** No index is created in this compiler version! ***
	
		this.getWindow().close();
		this.connector.close();
    }

    protected Windowing getWindow() {
		return this.window;
    }

    protected OutputColumnset getOutputColumnset() {
		return this.out;
    }


    /** calculates the sum of all values stored in an array */
    private double calcSum(String array[]) {
		double ret = 0;		 // the value to return
		for (int i = 0; i < array.length; i++) {
	    	ret+= Double.parseDouble(array[i]);
		}
		return (ret);
    }


    /**
     * This function has to be used in the database as a stored
     * procedure for calculating an SMA.
    */
    public static void dbSMF(Object dbc,
    						 String source, String time, String column, 
							 String target, String timeStartOut, String timeEndOut,
							 String columnOut, int windowSize, int distance)
		throws SQLException, TimeOperatorException
    {
    	BusinessDbConnectionSource dbcCasted =
			(dbc instanceof BusinessDbConnectionSource) ?
				((BusinessDbConnectionSource) dbc) : null;
		
    	
		SMF smf = new SMF(dbcCasted, source, time, column, target, timeStartOut,
						  timeEndOut, columnOut, windowSize, distance);
		smf.calc();
		smf = null;
    }
}
/*
 *$Log: SMF.java,v $
 *Revision 1.4  2006/04/11 14:10:16  euler
 *Updated license text.
 *
 *Revision 1.3  2006/04/06 16:31:15  euler
 *Prepended license remark.
 *
 *Revision 1.2  2006/03/30 16:07:15  scholz
 *fixed author tags for release
 *
 *Revision 1.1  2006/01/03 09:54:23  hakenjos
 *Initial version!
 * 
 */
