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

/**
 * @author Martin Scholz
 * @version $Id: Windowing.java,v 1.4 2006/04/11 14:10:16 euler Exp $
 */
public class Windowing {
    private DbConnector connector;
    private ResultSet rSet;
    private int wndSize;	    // current window size
    private int distance; 	    // distance between two data windows
    private boolean firstWnd;	    // true, if the current window is the first one
    private int sourceCol;	    // index of the source column
    private int timeCol;	            // index of the primary key column
    private String[] results;	    // the data window
    private String[] timeStamps;    // the time stamp window

    // Constructor
    // in :
    // - wndSize : size of a data window
    // - distance : distance between two data windows
    public Windowing(DbConnector connector) throws SQLException {
	wndSize    = 5;
	distance   = 1;
	sourceCol  = 1;
	timeCol    = 2;
	firstWnd   = true;
	results    = new String[wndSize];
	timeStamps = new String[wndSize];

	this.connector = connector;
    }

    public Windowing(int wndSize, int distance, DbConnector connector) throws SQLException {
	this.wndSize  = wndSize;
	this.distance = distance;
	
	sourceCol  = 1;
	timeCol    = 2;
	firstWnd   = true;
	results    = new String[wndSize];
	timeStamps = new String[wndSize];
	
	this.connector = connector;
    }

    // setWindowSize
    // description : sets a new window size
    // in :
    // - size : new size
    public void setWndSize(int size) {
	wndSize = size;
	results = new String[wndSize];
    }

    // setDistance
    // description : sets a new distance
    // in :
    // - distance : new distance
    public void setDistance(int distance) {
	this.distance = distance;
    }

    // setSourceCol
    // description : sets the source column index
    // in :
    // - col : the column's index in the source table
    public void setSourceCol(int col) {
	sourceCol = col;
    }

    // setSourceCol
    // desctiption : sets the source column index
    // in :
    // - col : the column's index in the source table
    public void setPrimaryKeyCol(int timeCol) {
	this.timeCol = timeCol;
    }

    // open
    // description : opens the target table and sends a sql command
    public boolean open(String sql) {
	try {
	    Statement stmt = connector.getConnection().createStatement();
	    rSet = stmt.executeQuery(sql);
	    
	    return true;
	}
	catch (Exception e) {
	    DbConnector.infoOutput("Error while opening " + sql);
	    return false;
	}
    }

    // deallocates the database connection for this window 
    public void close() {
	if (this.rSet != null) {
	    try {
		this.rSet.close();
	    } catch (SQLException e) {
		DbConnector.infoOutput("Closing ResultSet in class Windowing failed:\n" + e);
	    }
	    this.rSet = null;
	}
    }

    // shiftArray
    // description : shifts all values in the array n indexes left
    // in :
    // - array : the array
    // - n : number of indexes to shift
    private void shiftArray(String[] array, int n) {
	for (int i = 0; i < array.length; i++)
	    array[i] = (i + n < array.length) ? array[i + n] : "0";
    }
    
    // getNextWnd
    // desctiontion : returns the next data window
    // out :
    // - String[] : the new window
    public String[] getNextWnd() {
	if (this.rSet == null)
	    return null;

	try {
	    if (firstWnd) {
		// if this is the first window, simply initialize it
		for (int i = 0; i < wndSize; i++) {
		    if (rSet.next()) {
			results[i] = rSet.getString(sourceCol);
			timeStamps[i] = rSet.getString(timeCol);
			
			// if current value is a SQL NULL, get next value
			if (results[i] == null) i--;
		    }
		    else {
			return null;
		    }
		}
		firstWnd = false;
		
		return results;
	    }

	    // two windows are overlapping
	    if (distance < wndSize) {
		shiftArray(results,distance);
		shiftArray(timeStamps,distance);
		
		for (int i = wndSize - distance; i < wndSize; i++) {
		    if (rSet.next()) {
			results[i] = rSet.getString(sourceCol);
			timeStamps[i] = rSet.getString(timeCol);
			
			// if current value is a SQL NULL, get next value
			if (results[i] == null) i--;
		    }
		    else {
			return null;
		    }
		}
	    }
	    // two windows are disjunct
	    else {
		// move to next window
		for (int i = 0; i < distance - wndSize; i++)
		    if (!rSet.next()) return null;
		
		// fill  array with values
		for (int i = 0; i < wndSize; i++)
		    {
			if (rSet.next()) {
			    results[i]    = rSet.getString(sourceCol);
			    timeStamps[i] = rSet.getString(timeCol);
			    
			    // if current value is a SQL NULL, get next value
			    if (results[i] == null) i--;
			}
			else {
			    return null;
			}
		    }
	    }
	    
	    return results;
	}
	catch (SQLException e) {
	    return null;
	}
    }
    
    public String getTimeFirstEntry() {
	if ((timeStamps == null) || (timeStamps.length == 0))
	    return null;
	return (timeStamps[0]);
    }

    public String getTimeLastEntry() {
	if ((timeStamps == null) || (timeStamps.length == 0))
	    return null;
	return (timeStamps[timeStamps.length-1]);
    }

}
/*
 *$Log: Windowing.java,v $
 *Revision 1.4  2006/04/11 14:10:16  euler
 *Updated license text.
 *
 *Revision 1.3  2006/04/06 16:31:16  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!
 * 
 */
