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

import java.io.IOException;
import java.sql.SQLException;
import java.util.logging.Level;

import edu.udo.cs.miningmart.db.DB;
import edu.udo.cs.miningmart.m4.utils.Print;


/** 
 * The class <i>CreateCompiler</i> can be used for local compiler tests.
 * It does not use the client/server framework. It consists only of the
 * method <code>main</code>.
 *
 * @author Martin Scholz, Timm Euler
 * @version $Id: CreateCompiler.java,v 1.3 2006/04/11 14:10:09 euler Exp $
 * 
 */
public class CreateCompiler {

	/**
     * Method main for class CreateCompiler.
     * Usage: 
     * java CreateCompiler &lt;databaseConfigFile&gt; &lt;action&gt; &lt;object-id&gt; &lt;lazy-mode&gt;
     * &lt;verbosity&gt;, where<br />
     * &lt;databaseConfigFile&gt; is the filename with complete path for the file with DB access info,<br />
	 * &lt;action&gt; is one of <i>step</i>, <i>case</i>, <i>status</i>, <i>stat-con</i>, <i>stat-cs</i>,
	 *                <i>stat-col</i>, <i>gc-step</i>, <i>gc-case</i>, <i>ready</i><br />, <i>restOf</i><br />
     * &lt;object-id&gt; is a number (the id of an M4 object, depends on the action to be performed), and<br />
     * &lt;lazy-mode&gt; is either 'y' or 'n' to run the compiler in lazy mode or not. This is not supported
     *                   for all actions.<br />
     * &lt;verbosity&gt; a string specifying the verbosity level of the compiler. This is not supported
     *                   for all actions.
     */
    public static void main(String args[]) throws Exception
	{
	  L: if (args.length > 2) {
			CreateCompiler c = new CreateCompiler(args[0]);
			final String command = args[1];
			final int numArgs = args.length;
			{
				String[] tmp = new String[numArgs - 2];
				for (int i = 0; i < tmp.length; i++) {
					tmp[i] = args[i+2];
				}
				args = tmp;
			}
			if (command.equals("step")) {
				c.compileStep(args);
			} else if (command.equalsIgnoreCase("stepFrom")) {
				c.compileStepFrom(args);
			} else if (command.equalsIgnoreCase("case")) {
				c.compileCase(args);
			} else if (command.equalsIgnoreCase("status")) {
				c.printStatus(args);
			} else if (command.equalsIgnoreCase("stat-con")) {
				c.updateConceptStatistics(args);
			} else if (command.equalsIgnoreCase("stat-cs")) {
				c.updateColumnsetStatistics(args);
			} else if (command.equalsIgnoreCase("stat-col")) {
				c.updateColumnStatistics(args);
			} else if (command.equalsIgnoreCase("gc-step")) {
				c.garbageCollectionForStep(args);
			} else if (command.equalsIgnoreCase("gc-case")) {
				c.garbageCollectionForCase(args);
			} else if (command.equalsIgnoreCase("ready")) {
				c.checkStepReady(args);
			} else if (command.equalsIgnoreCase("restOf")) {
				c.compileRestOfCase(args);
			} else {
				break L;	
			}
			
			DB db = c.getCompilerAccess().getM4db();
			if (db != null) {
				db.updateDatabase();
			}
			System.exit(0);
		}
		System.err.println("Usage: java miningmart.compiler.CreateCompiler <db.config file>\n"
			             + "          status   <caseId> [ numberOfLines ]\n"
			             + "        | case     <caseId> [<lazy> [<verbosity>]]\n"
			             + "        | step     <stepId> [<lazy> [<verbosity>]]\n"
			             + "        | stepFrom <stepId> [<lazy> [<verbosity>]]\n"
			             + "        | restOf   <caseId> [<lazy> [<verbosity>]]\n "
			             + "        | stat-con <conceptId>\n"
			             + "        | stat-cs  <columnsetId>\n"
			             + "        | stat-col <columnId>\n"
			             + "        | gc-step  <stepId>\n"
			             + "        | gc-case  <caseId>\n"
			             + "        | ready    <stepId>\n"
			             );
		System.exit(-1);
    }

	// -----------------------------------------------------------

	private final String dbConfig;
	private CompilerAccessLogic c;
	private Level verbosity = Level.ALL;

	private CreateCompiler(String dbConfig) {
		this.dbConfig = dbConfig;		
	}

	private CompilerAccessLogic getCompilerAccess() 
		throws IOException, SQLException 
	{
		if (this.c == null) {
			this.c = (this.verbosity.intValue() < 0) ?
						new CompilerAccessLogic(dbConfig)
					  : new CompilerAccessLogic(dbConfig, this.verbosity);
		}
		return this.c;	
	}

	private void setVerbosity(Level verbosity) {
		if (this.verbosity.intValue() < 0) {
			this.verbosity = verbosity;	
		}
	}

	/* ----------------------------------------------------------------- */
	    
    private void printStatus(String[] args) throws Exception
    {
		int numberOfLines = 30;
		try {
			if (args.length > 1)
				numberOfLines = Integer.parseInt(args[1]);
		}
		catch (NumberFormatException e) {}
		System.out.println("---------------------------------- Status ----------------------------------\n");
		String msg = this.getCompilerAccess().getStatusMessage(getObjId(args[0]), numberOfLines);
		if (msg == null) {
			msg = "<null>";	
		}
		System.out.println(msg);
		System.out.println("\n----------------------------------------------------------------------------");
		System.exit(0);
    }
    
	private void compileCase(String[] args) throws Exception
	{
		long objId = getObjId(args[0]);
		boolean lazyMode = (args.length > 1) ? getLazyMode(args[1]) : false;
		System.out.println("Trying to compile case " + objId);

		String v = "";
		if (args.length > 2) {
			v = ", " + args[2];
			this.setVerbosity(getVerbosity(v));
		}
		this.getCompilerAccess().compileAll(objId, lazyMode);
		System.out.println(
			"Returned from compileAll(" + objId + ", "
			+ (lazyMode ? "lazy" : "eager")	+ v	+ ");");
	}   
	
    private void compileStep(String[] args) throws Exception
    {
		long objId = getObjId(args[0]);
		boolean lazyMode = (args.length > 1) ? getLazyMode(args[1]) : false;
		System.out.println("Trying to compile step " + objId + ".");

		String v = "";
		if (args.length > 2) {
			v = ", " + args[2];
			this.setVerbosity(getVerbosity(v));
		}
		this.getCompilerAccess().compileStep(objId, lazyMode);
		System.out.println("Returned from compileStep(" + objId + ", "
						+ (lazyMode ? "lazy" : "eager") + v + ");");
    }
    
    private void compileStepFrom(String[] args) throws Exception
    {
		long objId = getObjId(args[0]);
		boolean lazyMode = (args.length > 1) ? getLazyMode(args[1]) : false;
		System.out.println("Trying to compile all steps dependent on step " + objId + ".");

		String v = "";
		if (args.length > 2) {
			v = ", " + args[2];
			this.setVerbosity(getVerbosity(v));
		}
		this.getCompilerAccess().compileStepFrom(objId, lazyMode);
		System.out.println("Returned from compileStepFrom(" + objId + ", "
						+ (lazyMode ? "lazy" : "eager") + v + ");");
    }

    private void updateConceptStatistics(String[] args) throws Exception
	{
		long objId = getObjId(args[0]);
		System.out.println("Updating Concept statistics for Concept " + objId + ".");
		this.getCompilerAccess().updateStatisticsForConcept(objId);
		System.out.println("Statistics updated for object with id: " + objId + " !");	
    }
    
    private void updateColumnsetStatistics(String[] args) throws Exception
	{
		long objId = getObjId(args[0]);
		System.out.println("Updating Columnset statistics for Columnset " + objId + ".");	
		this.getCompilerAccess().updateColumnsetStatistics(objId);
		System.out.println("Statistics updated for object with id: " + objId + " !");	
    }

    private void updateColumnStatistics(String[] args) throws Exception
	{
		long objId = getObjId(args[0]);
		System.out.println("Updating Column statistics for Column " + objId + ".");	
		this.getCompilerAccess().updateColumnStatistics(objId);
		System.out.println("Statistics updated for object with id: " + objId + " !");	
    }

    private void garbageCollectionForStep(String[] args) throws Exception
	{
		long objId = getObjId(args[0]);
		System.out.println("Running Garbage Collection for Step " + objId + ".");	
		this.getCompilerAccess().deleteTrashForStep(objId);
		System.out.println("Garbage for Step with id " + objId + " collected!");	
    }

    private void garbageCollectionForCase(String[] args) throws Exception
	{
		long objId = getObjId(args[0]);
		System.out.println("Running Garbage Collection for Case " + objId + ".");	
		this.getCompilerAccess().deleteTrashForCase(objId);
		System.out.println("Garbage for Case with id " + objId + " collected!");
    }

    private void checkStepReady(String[] args) throws Exception
	{
		long objId = getObjId(args[0]);
		System.out.println("Checking if Step " + objId + " is ready for compilation.");	
		boolean ready = this.getCompilerAccess().isReadyForCompilation(objId);
		System.out.println("Step with id " + objId + " is" + (ready ? "" : " not")
						   + " ready for compilation!");
		System.exit(0);
    }

    private void compileRestOfCase(String[] args) throws Exception
    {
		long objId = getObjId(args[0]);
		boolean lazyMode = (args.length > 1) ? getLazyMode(args[1]) : false;
		System.out.println("Trying to compile rest of case " + objId);

		String v = "";
		if (args.length > 2) {
			v = ", " + args[2];
			this.setVerbosity(getVerbosity(v));
		}
		this.getCompilerAccess().compileRestOfCase(objId, lazyMode);
		System.out.println(
			"Returned from compileAll(" + objId + ", "
			+ (lazyMode ? "lazy" : "eager")	+ v	+ ");");
    }
    
   	// -----------------------------------------------------------

	private static long getObjId(String s) {
		try {
			return Long.parseLong(s.trim());
		}
		catch (NumberFormatException e) {
			return -1;
		}
	}

	private static boolean getLazyMode(String s) {
		String lazyString = s.trim().toLowerCase();
		return (lazyString.startsWith("l") || lazyString.startsWith("y"));		
	}

	private static Level getVerbosity(String s) {
		return Print.getVerbosityLevelForName(s);
/*		try {
			return Integer.parseInt(s.trim());
		}
		catch (NumberFormatException e) {
			return 0;
		}*/
	}

}
/*
 * Historie
 * --------
 *
 * $Log: CreateCompiler.java,v $
 * Revision 1.3  2006/04/11 14:10:09  euler
 * Updated license text.
 *
 * Revision 1.2  2006/04/06 16:31:09  euler
 * Prepended license remark.
 *
 * Revision 1.1  2006/01/03 09:54:31  hakenjos
 * Initial version!
 *
 */

/*
 * Old Historie
 * ------------
 *
 * Revision 1.2  2005/05/12 10:48:54  hakenjos
 * *** empty log message ***
 *
 * Revision 1.1  2004/11/09 13:47:23  euler
 * Changed ConfigReader.
 *
 * Revision 1.34  2003/06/05 09:52:02  euler
 * Organised imports.
 *
 * Revision 1.33  2003/03/24 21:48:41  scholz
 * *** empty log message ***
 *
 * Revision 1.32  2002/12/04 13:03:16  scholz
 * added call to method 'compileRestOfCase' in CompilerAccessLogic
 *
 * Revision 1.31  2002/11/25 14:11:56  euler
 * Added compileStepFrom.
 *
 * Revision 1.30  2002/11/07 10:28:17  scholz
 * corrected usage messgae
 *
 * Revision 1.29  2002/11/04 09:06:29  euler
 * compiler warning fixed
 *
 * Revision 1.28  2002/10/30 18:20:28  scholz
 * javadoc fix
 *
 * Revision 1.27  2002/10/30 14:10:09  scholz
 * bugfixes
 *
 * Revision 1.26  2002/10/30 13:47:24  scholz
 * a reimplementation - now supporting the new interface methods
 *
 * Revision 1.25  2002/10/23 11:02:28  euler
 * New Javadoc comments
 *
 * Revision 1.24  2002/10/11 14:38:00  scholz
 * added verbosity level to main method
 *
 * Revision 1.23  2002/10/10 12:53:04  scholz
 * removal of unused local variables and parameters
 *
 * Revision 1.22  2002/10/08 18:07:56  scholz
 * Prepared code for parallel execution of multiple compile-Threads.
 * Calls to static fields like DB.m4Db were removed. Now each
 * Thread has its own DB object, reachable via
 * CompilerAccessLogic or Case.
 * The methods getCase() and getM4Db() were added to M4Object.
 * The static methods of Parameter now need an additional
 * parameter of type DB.
 * All direct calls from Operators to these Parameter methods were
 * removed.
 * All old load() and print() routines were removed.
 * The static calls to Print were removed. Now CompilerAccessLogic
 * references a valid Print object for the current Thread. This is
 * reachable via Case. The methods doPrint for messages and
 * Exceptions were added to M4Object.
 * The Print mechanism is not fully functional, yet.
 * A getStatus method was added to the Interface. It is not
 * functional yet for multiple Threads.
 *
 * Status: Compiles.
 *
 * Revision 1.21  2002/10/02 16:30:47  scholz
 * bugfix
 *
 * Revision 1.20  2002/09/27 10:34:13  euler
 * Bugfix.
 *
 * Revision 1.19  2002/09/26 14:27:49  scholz
 * - added compileStepFrom
 * - adjusted garbage collection to stepsequence-graphs
 *
 * Revision 1.18  2002/09/25 18:58:11  scholz
 * - bugfix in compileAll() and class Sequentializer
 * - added interface method compileAll()
 * - some code cleanup
 *
 * Revision 1.17  2002/09/18 08:58:02  euler
 * Removed the option to have statistics
 * computed.
 *
 * Revision 1.16  2002/07/19 10:09:26  euler
 * Bugfix.
 *
 * Revision 1.15  2002/07/12 10:49:39  euler
 * Prepared the code for using two DB connections.
 *
 * Revision 1.14  2002/07/11 08:36:33  euler
 * Changed printing of messages.
 *
 * Revision 1.13  2002/07/10 08:31:25  euler
 * Quicker debugging.
 *
 * Revision 1.12  2002/07/04 10:15:18  scholz
 * *** empty log message ***
 *
 * Revision 1.11  2002/06/27 17:39:56  scholz
 *
 * Uses the new class CompilerAccessLogic in order to run just the server side.
 *
 * Revision 1.10  2002/06/20 13:16:11  agrawal
 *
 * Added Support for running StepSequence .
 *
 * Revision 1.8  2002/06/18 08:12:28  euler
 * Uses the CompilerInterface now.
 *
 * Revision 1.7  2002/06/10 08:45:11  euler
 * Added trash index, first tests ok.
 *
 * Revision 1.6  2002/05/31 12:35:00  euler
 * *** empty log message ***
 *
 * Revision 1.5  2002/05/21 12:51:00  euler
 * First beta test ok.
 *
 * Revision 1.4  2002/05/17 21:21:01  scholz
 *
 * now reads jdbc:oracle:... from the database configuration file, as well
 *
 * Revision 1.3  2002/05/17 14:20:13  scholz
 *
 *
 * Now the main method of the CreateCompiler class reads the database
 * connection data from a specified file rather than as command line
 * parameters.
 *
 * Revision 1.2  2002/05/10 13:23:21  euler
 * First M4 extensions, does not yet compile
 *
 * Revision 1.1  2002/04/30 14:39:24  wiese
 * new main class
 *
 * Revision 1.1  2002/04/30 13:00:28  wiese
 * compileable version
 *
 * Revision 1.6  2002/04/19 15:23:12  wiese
 * Initialversion nach der uebergabe
 *
 */


