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

import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;

import edu.udo.cs.miningmart.exception.M4CompilerError;
import edu.udo.cs.miningmart.exception.M4CompilerWarning;
import edu.udo.cs.miningmart.exception.M4Exception;
import edu.udo.cs.miningmart.m4.BaseAttribute;
import edu.udo.cs.miningmart.m4.Column;
import edu.udo.cs.miningmart.m4.Columnset;
import edu.udo.cs.miningmart.m4.Concept;
import edu.udo.cs.miningmart.m4.EstimatedStatistics;
import edu.udo.cs.miningmart.m4.Feature;
import edu.udo.cs.miningmart.m4.MultiColumnFeature;
import edu.udo.cs.miningmart.m4.Step;
import edu.udo.cs.miningmart.m4.utils.Print;

/**
 * This abstract class is the superclass for all operators whose output is a
 * concept. Operators of this type must produce at least one ColumnSet for the
 * output concept. The parameters "TheInputConcept" and "TheOutputConcept" are
 * provided by this class and are inherited by subclasses (using the methods
 * <code>getInputConcept()</code> and <code>getOutputConcept()</code>).
 *
 * @see edu.udo.cs.miningmart.operator.SingleCSOperator
 * @see edu.udo.cs.miningmart.operator.MultipleCSOperator
 * 
 * @author Martin Scholz
 * @version $Id: ConceptOperator.java,v 1.9 2006/04/11 14:10:11 euler Exp $
 */
public abstract class ConceptOperator
    extends ExecutableOperator {
    //~ Instance/static variables .............................................

    private Columnset[] myOutputColumnSets;

    //~ Constructors ..........................................................

    //~ Methods ...............................................................

    /** 
     * Method for compiling the generated sql-statement.
     * This method tests if the generated sql-statement is
     * executable on the database.
     * 
     * @see edu.udo.cs.miningmart.operator.Operator#compileStatement
     */
    public void compileStatement()
    throws SQLException, M4CompilerWarning, M4CompilerError {

        //Test select Statement
        if (myOutputColumnSets != null)
        {
            for (int i = 0; i < myOutputColumnSets.length; i++)
            {
                if (myOutputColumnSets[i].getType().equalsIgnoreCase(Columnset.CS_TYPE_VIEW)) // view
                {  this.getM4Db().createSQLView(myOutputColumnSets[i], this.getStep());  }

                if (myOutputColumnSets[i].getType().equalsIgnoreCase("SN")) // snapshot
                {  throw new M4CompilerError("ConceptOperator.compileStatement(): found output ColumnSet " +
                                             "of type 'Snapshot' (SN). This is not supported yet!");  }
                if (myOutputColumnSets[i].getType().equalsIgnoreCase("MV")) // materialized view
                {  throw new M4CompilerError("ConceptOperator.compileStatement(): found output ColumnSet " +
                                             "of type 'Materialized View' (MV). This is not supported yet!");  }
            }
        }
    }

    /**
     * Method for generating a sql-statement.
     * This method handles the process
     * of generating a sql-statement for an operator.
     *
     * @see edu.udo.cs.miningmart.operator.Operator#createStatement
     */
    public void createStatement(boolean lazy) throws M4CompilerError, M4CompilerWarning
    {
        // First update Meta-Data
        myOutputColumnSets = generateColumnSetsForOp(lazy);

        if (myOutputColumnSets == null)
        {  throw new M4CompilerError("Operator '" + this.getName() + "' did not create a new Columnset!");  }

        // Get the Inline View-Definition out of the new cs
        generatedSQLDefinitions = new String[myOutputColumnSets.length];
        for (int i = 0; i < myOutputColumnSets.length; i++)
        {
            String type = myOutputColumnSets[i].getType().toUpperCase();
            if (type.equals(Columnset.CS_TYPE_VIEW))  { type = "VIEW";  }
            if (type.equals(Columnset.CS_TYPE_TABLE))  { type = "TABLE";  }
            generatedSQLDefinitions[i] = type + " " + myOutputColumnSets[i].getName() + " AS " +
                                         myOutputColumnSets[i].getSQLDefinition();
        }

		try {
	        for (int i = 0; i < myOutputColumnSets.length; i++)
	        {  getOutputConcept().addColumnSet(myOutputColumnSets[i]);  }
		}
   		catch (M4Exception m4e)
   		{   throw new M4CompilerError("M4 interface error in " + this.getName() + ": " + m4e.getMessage());  }
    }

    /**
     * @see edu.udo.cs.miningmart.operator.ExecutableOperator#estimateStatistics(Step)
     */
    public EstimatedStatistics estimateStatistics(Step theStep) throws M4Exception {

    	// by default all estimates are copied from input to output;
    	// subclasses may overwrite this.
    	Concept outputCon = theStep.getOutputConcept();
    	EstimatedStatistics outEstStat = new edu.udo.cs.miningmart.m4.core.EstimatedStatistics(outputCon);    	
    	Collection inputCons = theStep.getAllInputConcepts();
    	if (inputCons != null && inputCons.size() == 1) {
    		outEstStat.setNumberOfRows(((Concept) inputCons.iterator().next()).getEstimatedStatistics().getNumberOfRows());
    	}
    	
    	// for every output feature try to find a corresponding input feature:
    	Iterator outIt = outputCon.getAllBaseAttributes().iterator();
    	while (outIt.hasNext()) {
			BaseAttribute outBa = (BaseAttribute) outIt.next();
			Iterator inConIt = inputCons.iterator();
			while (inConIt.hasNext()) {
				Concept inCon = (Concept) inConIt.next();
				EstimatedStatistics inEstStat = inCon.getEstimatedStatistics();
				Iterator inIt = inCon.getAllBaseAttributes().iterator();
				while (inIt.hasNext()) {
					BaseAttribute inBa = (BaseAttribute) inIt.next();
					if (inBa.correspondsTo(outBa)) {
						// corresponding input feature found!
						String iN = inBa.getName();
						String oN = outBa.getName();
						outEstStat.setBiggestValue(oN, inEstStat.getBiggestValue(iN));
						outEstStat.setLowestValue(oN, inEstStat.getLowestValue(iN));
						outEstStat.setNumberOfMissingValues(oN, inEstStat.getNumberOfMissingValues(iN));
						outEstStat.copyValueList(oN, inEstStat, iN);
					}
				}
			}
		}
		return outEstStat; // allows subclasses to extend the information. 
		                   // It will be connected to the output concept 
		                   // in the method Concept.getEstimatedStatistics(), from where
		                   // this method is called.		 
    }
    
    /**
     * Abstract method to be implemented by subclasses.
     *
     * @return An array of ColumnSet objects
     */
    public abstract Columnset[] generateColumnSetsForOp(boolean lazy) throws M4CompilerError;

	/**
	 * This method provides TheInputConcept for this operator.
	 */
    public Concept getInputConcept() throws M4CompilerError {
		return (Concept) this.getSingleParameter("TheInputConcept");
    }

	/**
	 * This method provides TheOutputConcept for this operator.
	 */
    public Concept getOutputConcept() throws M4CompilerError {
		return (Concept) this.getSingleParameter("TheOutputConcept");
    }

    /**
     * Since all operators of this type (ConceptOperator) create columnsets,
     * they can use this method to do so. This method calls <code>generateSQLDefinition()</code>,
     * to be implemented by subclasses, to find the SQL String for the new columnset.
     * This method may be overridden by some subclasses.
     *
     * @param index For MultipleCSOperators, the number of the columnset to be
     *        created, starting with 0. For SingleCSOperators, this parameter must
     *        be -1.
     * @return A new Columnset object.
     */
    protected Columnset createSingleColumnSet(int index) throws M4CompilerError
    {
        final String newName = this.getNewCSName(index);
		Columnset newCS;
        try {
	        newCS = (Columnset) this.getM4Db().createNewInstance(edu.udo.cs.miningmart.m4.core.Columnset.class);
			this.getStep().addToTrash(newCS);
        }
        catch (M4Exception e) {
        	throw new M4CompilerError(
        		"M4Exception while trying to add newly created Columnset to trash of Step "
        		+ this.getStep().getId() + " in method ConceptOperator.createSingleColumnSet(int)!\n"
        		+ e.getMessage());
        }
        newCS.setName(newName);
        try {
	        newCS.setId(0);
	        final edu.udo.cs.miningmart.m4.Columnset inputColumnSet = getInputConcept().getCurrentColumnSet();
	        if (inputColumnSet == null) {
	        	throw new M4CompilerError(
	        		"The Input Concept ('" + getInputConcept().getName()
	        		+ "') of Step '" + this.getStep().getName() + "' has no Columnsets!");
	        }
	        newCS.setSchema(inputColumnSet.getSchema());
	
	        String type = getTypeOfNewColumnSet(index).toUpperCase();
	        if ( ! (type.equals(Columnset.CS_TYPE_TABLE) || type.equals(Columnset.CS_TYPE_VIEW)))
	        {  throw new M4CompilerError("ConceptOperator: found unknown type for new ColumnSet: '" + type + "'!");  }
	
		    newCS.setType(type);
	        newCS.setTheConcept(getOutputConcept());
        }
   		catch (M4Exception m4e)
   		{   throw new M4CompilerError("M4 interface error in " + this.getName() + ": " + m4e.getMessage());  }

        // create metadata for the columns of the new Columnset:
        String columnExpr = generateColumns(newCS);

		String sqlDef = generateSQLDefinition(columnExpr, index);
		if (sqlDef.length() > edu.udo.cs.miningmart.m4.core.Columnset.MAX_SQLDEF_LENGTH) {
			sqlDef = createViewAsSqlDef(sqlDef, index);
		}
	    newCS.setSQLDefinition(sqlDef);
	        
		this.setNewCSMultiStepBranch(newCS, index);
		
        return newCS;
    }

	/**
	 * Helper method: If the SQL definition returned by the implementation of
	 * <code>generateSQLDefinition</code> gets longer than the maximum allowed
	 * in the M4 schema then we try to create a view and enter just a reference
	 * to this view as he SQL definition.
	 * This method creates the view according to sqlDef and the given index and
	 * returns the String to be entered into Columnset-&gt;SQL
	 */
	private String createViewAsSqlDef(String sqlDef, int index)
		throws M4CompilerError
	{
    	final String viewName = this.getNewCSName(index) + "_V";
    	final String viewDef = "CREATE VIEW " + viewName + " AS " + sqlDef;
    	try {
    		this.doPrint(Print.COMPILER_OP_CONTROL,
    			"View definition String is too long for database, trying to create a view '"
    			+ viewName + "' in advance!");
	    	this.getM4Db().executeBusinessSqlWrite(viewDef);
		    	String schema = null;
	    	try  {
	    		edu.udo.cs.miningmart.m4.Columnset cs = this.getInputConcept().getCurrentColumnSet();
		    	if (cs != null) {
		    		schema = cs.getSchema();
		    	}
	    	}
	    	catch (M4Exception e) {}
	    	
	    	if (schema != null) {
		    	this.getM4Db().addViewToTrash(viewName, schema, this.getStep().getId());
	    		return "(SELECT * FROM " + viewName + " )";
	    	}
	    	else {
	    		throw new M4CompilerError(this.getClass().getName()
	    			+ ": Could not find business schema we are working on!");
	    	}
	    }
	    catch (SQLException e) {
	    	throw new M4CompilerError(
	    		"SQLException when trying to create database view.\n"
	    		+ "Statement:\n" + e.getMessage());
	    }		
	}

	/**
	 * Set the information about the multistep branch into the Columnset
	 * that is created by this operator.
	 * 
	 * @param newCS the Columnset that is created by this operator
	 * @param index An index for MulipleCSOperators.
	 */
	protected void setNewCSMultiStepBranch(final Columnset newCS, int index)
		throws M4CompilerError
	{
		try {
			edu.udo.cs.miningmart.m4.Columnset inputColumnSet = getInputConcept().getCurrentColumnSet();
			newCS.setMultiStepBranch(inputColumnSet.getMultiStepBranch());
		}
   		catch (M4Exception m4e)
   		{   throw new M4CompilerError("M4 interface error in " + this.getName() + ": " + m4e.getMessage());  }
	}

    /**
     * This method must return the entry String for the M4 table "Columnset_t",
     * indicating whether the new Columnset is a view or a table. Use the constants
     * in the class Columnset, either CS_TYPE_TABLE or CS_TYPE_VIEW.
     *
     * @param index An index for MulipleCSOperators.
     * @return The type of the new Columnset, either Columnset.CS_TYPE_TABLE or Columnset.CS_TYPE_VIEW.
     */
    public abstract String getTypeOfNewColumnSet(int index);

    /**
     * This method creates new Columns for the given Columnset, one for each
     * Feature of this operator's output concept, if the method "mustCopyFeature()"
     * for this Feature returns TRUE. This method may be overridden by some subclasses.
     *
     * @param csForOutputConcept The ColumnSet for which Columns are to be produced.
     * @return A String for the "SELECT"-part of the view definition for the
     *          given ColumnSet.
     */
    protected String generateColumns(Columnset csForOutputConcept) throws M4CompilerError {
	    String columnExpr = "";  // to be returned
	    Feature inF = null;
	    int iIn = 0;
	    Feature outF = null;
	    int iOut = 0;

		try {
	        // loop through features of output concept, these are the selected features
		    for (iOut = 0; iOut < getOutputConcept().getFeatures().size(); iOut++) {
		        outF = getOutputConcept().getFeature(iOut);
	            if (mustCopyFeature(outF.getName())) {
		            iIn = 0;
	                // find input feature with same name:
		            do {
			            inF = getInputConcept().getFeature(iIn);
			            iIn++;
	                }
	                while ((iIn < getInputConcept().getFeatures().size()) && ( ! outF.correspondsTo(inF)));
	
		            if ( ! outF.correspondsTo(inF)) {
	                    this.doPrint(Print.OPERATOR, "Output Concept '" + getOutputConcept().getName() + "': skipped feature '" +
	                                  outF.getName() + "' because no corresponding input feature was found.");
	                    continue;
	                }
	                
	                if (this.isDeselectedParameter(inF)) {
	                    this.doPrint(Print.PARAM, "Output Concept '" + getOutputConcept().getName() + "': skipped feature '" +
	                                  outF.getName() + "' because the corresponding input feature was deselected by " +
	                                  "a FeatureSelection operator.");   	
	                	continue;	
	                }
	                
	                if ( ! this.getStep().isVisible(inF)) {
	                	// skip input features that are not visible in this step!
	                    continue;		                	
	                }
	
	                // copy metadata for column to output columnset
	                columnExpr = this.createMetadata(inF, outF, csForOutputConcept, columnExpr);
	            } // end if (mustCopyFeature)
			} // end for (loop through output features)
	
		    // Delete the last ", "
		    if (columnExpr.equals(""))
		    {  throw new M4CompilerError("ConceptOperator (" + this.getName() + "): No columns for output concept created!");  }
		    
		    columnExpr = columnExpr.substring(0,columnExpr.length()-2);
	
	        return columnExpr;
		}
   		catch (M4Exception m4e)
   		{   throw new M4CompilerError("M4 interface error in " + this.getName() + ": " + m4e.getMessage());  }
    } // end protected String generateColumns

	/**
	 * Copy the metadata for all the BAs in the input feature to the output feature.
	 * 
	 * @param inF A Feature from the input concept
	 * @param outF The corresponding Feature from the output concept
	 * @param csForOutputConcept The current Columnset from the output concept
	 * @param The so-far created String for the Select part of the SQL statement
	 * @return An extended String for the Select part of the SQL statement
	 */
	protected String createMetadata(Feature inF, Feature outF, Columnset csForOutputConcept, String columnExpr) 
		throws M4CompilerError {
		
		MultiColumnFeature inMCF, outMCF;
		BaseAttribute inBA, outBA;
		Collection theBAs;
		
		// copy metadata for column to output columnset
		if (outF instanceof BaseAttribute) {
			inBA = (BaseAttribute) inF;
			outBA = (BaseAttribute) outF;
			columnExpr = this.createMetadataForOneBA(inBA, outBA, csForOutputConcept, columnExpr);
		}
		else {
			if (!(outF instanceof MultiColumnFeature)) {
				throw new M4CompilerError("Operator '"+this.getName()+"': Unknown Feature type found in Concept with id: "
										  + getOutputConcept().getId() + "; Feature id: "
										  + outF.getId());
			}

			// copy metadata for each BaseAttribute in this MultiColumnFeature
			outMCF = (MultiColumnFeature) outF;
			inMCF = (MultiColumnFeature) inF;
			try {
				theBAs = outMCF.getBaseAttributes();
				if (theBAs != null)	{
					Iterator it2 = theBAs.iterator();
					while (it2.hasNext()) {
						outBA = (BaseAttribute) it2.next();
						inBA = inMCF.getBaseAttributeByName(outBA.getName());
						columnExpr = this.createMetadataForOneBA(inBA, outBA, csForOutputConcept, columnExpr);
					}
				}
			}
			catch (M4Exception m4e) {
				throw new M4CompilerError("Operator '"+this.getName()+"': M4 Exception when copying metadata: " + m4e.getMessage());
			}
			catch (NullPointerException nfe) {
			    throw new M4CompilerError("Operator '"+this.getName()+"': Mismatch between MultiColumnFeatures in in- and output concept!");
			}
			catch (ArrayIndexOutOfBoundsException aie) {
				throw new M4CompilerError("Operator '"+this.getName()+"': Mismatch between MultiColumnFeatures in in- and output concept!");
			}
		} // end else to if (feature is BA)
		return columnExpr;
	}

	/**
	 * Copy the metadata from the given input BA to the given output BA.
	 * Add the necessary SQL to the given String and return it.
	 * 
	 * @param inBA A BaseAttribute from the input concept
	 * @param outBA The corresponding BaseAttribute from the output concept
	 * @param csForOutputConcept The current Columnset from the output concept
	 * @param The so-far created String for the Select part of the SQL statement
	 * @return An extended String for the Select part of the SQL statement
	 */
	protected String createMetadataForOneBA( BaseAttribute inBA, 
	                                         BaseAttribute outBA,
	                                         Columnset csForOutputConcept, 
	                                         String columnExpr) 
	  throws M4CompilerError {
	    if (inBA == null ||outBA == null || csForOutputConcept == null) {
	    	throw new M4CompilerError("Operator '" + this.getName() + 
	    	                          "': found NULL argument when copying metadata for a BaseAttribute!");
	    }
	    try {
		    // create output column:                                   	
			Column inputColumn = inBA.getCurrentColumn();
		    Column outputColumn = inputColumn.copyColToCS(csForOutputConcept);
		    // add output column to trash:
		    this.getStep().addToTrash(outputColumn);
		    // link output column to output BA:
		    outputColumn.setBaseAttribute(outBA);
		    outBA.addColumn(outputColumn);
		    // set SQL definition of output column
		    outputColumn.setSQLDefinition(inputColumn.getName());
		    
		    // create the select part of the view creation:
			columnExpr = columnExpr + this.getStringForSelection(inputColumn) + ", ";
			
			return columnExpr;
	    }
	    catch (M4Exception m4e) {
	    	throw new M4CompilerError("Operator '" + this.getName() + 
	    	                          "': M4 exception caught when copying input BaseAttribute '"+
	    	                          inBA.getName() + "' to output BaseAttribute '" +
	    	                          outBA.getName() + "':\n" + m4e.getMessage());
	    }
	}
	
	/**
	 * This method returns a String to be used in the SELECT part
	 * of a view definition. The returned String will indicate the name
	 * of the output column that corresponds to the given input column.
	 * This method may be overwritten by subclasses.
	 * 
	 * @param inputColumn the given input column
	 * @return a String for the SELECT part of a view definition
	 */
	protected String getStringForSelection(Column inputColumn) {
	    // contribute to view-creating string:
	    String nextAttrib = inputColumn.getSQLDefinition();
	    if (! inputColumn.getName().equals(nextAttrib)) {
	    	// following line:
	       	// nextAttrib = "(" + inputColumn.getSQLPlusLocation() + ") AS " + inputColumn.getName();
	       	// was replaced because it leads to things like "schemaname.tablename.(virtualcolumndefinition)"
	       	//    which is not well-formed SQL
	       	nextAttrib = "(" + inputColumn.getSQLDefinition() + ") AS " + inputColumn.getName();
	    }
	    else {
	    	nextAttrib = inputColumn.getColumnset().getSchemaPlusName() + "." + nextAttrib;
	    }
	    return nextAttrib;
	}

	/** 
	 * This method is used to generate the name for new <code>Columnset</code>s.
	 * If an operator needs to generate specific names, this method should be
	 * overwritten.
	 * The index may be used to signal, that this operator creates more than one
	 * <code>Columnset</code>, so a suffix needs to be part of the name.
	 * The <code>Step</code> ID should always be part of the name, because
	 * otherwise during parallel execution of <code>Case</code>s intermediate
	 * results of one <code>Case</code> could be overwritten by another.
	 * 
	 * @param the index of the columnset to get the name for.
	 * 		  -1 specifies, that only a single columnset is created.
	 * @return the name
	 * */
	public String getNewCSName(int index) throws M4CompilerError {
		String name = 
					// getOutputConcept().getName() + "_" +
   	    			"CS_" +this.getStep().getId() + 
       				getInputConcept().getCurrentSuffix();
       	if (index > -1) {
        	name += "_" + index;
        }
	    return name;
	}

    /**
     * This method is for operators that do not copy all Features of the input concept
     * to the output concept.
     *
     * @param nameOfFeature Name of the feature in question.
     * @return TRUE if this feature should be copied to the output concept,
     *          FALSE if not.
     */
    protected abstract boolean mustCopyFeature(String nameOfFeature) throws M4CompilerError;

    /**
     * This method must return the SQL definition of the newly created ColumnSet.
     *
     * @param selectPart The String for the SELECT-part of the SQL definition to
     *        be created.
     * @param index An index for MultipleCSOperators.
     * @return The SQL definition for the new ColumnSet.
     */
    public abstract String generateSQLDefinition(String selectPart, int index) throws M4CompilerError;
}
/*
 * Historie
 * --------
 *
 * $Log: ConceptOperator.java,v $
 * Revision 1.9  2006/04/11 14:10:11  euler
 * Updated license text.
 *
 * Revision 1.8  2006/04/06 16:31:11  euler
 * Prepended license remark.
 *
 * Revision 1.7  2006/03/30 16:07:13  scholz
 * fixed author tags for release
 *
 * Revision 1.6  2006/03/23 11:13:45  euler
 * Improved exception handling.
 *
 * Revision 1.5  2006/03/02 16:49:59  euler
 * Many bugfixes
 *
 * Revision 1.4  2006/02/01 14:57:12  euler
 * New operator RemoveDuplicates
 *
 * Revision 1.3  2006/01/18 16:58:58  euler
 * Added some basic estimations of statistics.
 * Will need improvements.
 *
 * Revision 1.2  2006/01/05 10:27:38  hakenjos
 * Removed Javadoc Warnings!
 *
 * Revision 1.1  2006/01/03 09:54:21  hakenjos
 * Initial version!
 *
 */

/*
 * Old Historie
 * ------------
 *
 * Revision 1.32  2003/01/24 17:16:37  scholz
 * new parameter Step (rather than stepId) when calling method DB.createSqlView
 *
 * Revision 1.31  2002/12/16 12:58:48  scholz
 * removed part always calculating statistics when creating a columnset
 *
 * Revision 1.30  2002/11/27 18:46:07  scholz
 * added explicit check for deselection of input features before copying columns
 *
 * Revision 1.29  2002/11/25 12:40:18  euler
 * Throws exception if no columns are created.
 *
 * Revision 1.28  2002/10/25 13:43:26  euler
 * Changed Sql Definitions that FeatureConstruction
 * operators create. Adapted the Join operators.
 *
 * Revision 1.27  2002/10/24 10:20:05  euler
 * New Javadoc comments.
 *
 * Revision 1.26  2002/10/21 16:17:21  scholz
 * javadoc comments: fixed some invalid tags
 *
 * Revision 1.25  2002/10/14 17:26:15  scholz
 * update of columnset names (based on step id)
 * for parallel execution of cases
 *
 * Revision 1.24  2002/10/10 12:53:04  scholz
 * removal of unused local variables and parameters
 *
 * Revision 1.23  2002/10/09 17:11:25  scholz
 * Deleted control information in Case.
 * Instead an instead of DB is passed to rthe constructor of several M4Objects.
 * Operators copy the DB instance from Step during load(Step).
 * Print information is available via doPrint(..) for M4Objects.
 *
 * Status: DM Case compiles
 *
 * 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/01 14:22:30  euler
 * New Feature Selection class.
 *
 * Revision 1.20  2002/09/24 09:21:59  euler
 * *** empty log message ***
 *
 * Revision 1.19  2002/08/30 12:33:34  scholz
 * view definitions no longer inline in sql statements
 *
 * Revision 1.18  2002/08/28 19:25:05  scholz
 * First step for automatically loading parameters and checking
 * their validity:
 * Information stored in OP_PARAM_T is represented in an own
 * class and automatically loaded by class Operator.
 *
 * Unsegment:
 * The field CS_MSBRANCH (table COLUMNSET_T) is now
 * set during operator execution.
 * Each Columnset has the information attached, by which
 * segmentations (e.g.' item=19; ' or '(KMeans)=1' ) it was
 * created. This information is used by the Unsegment operator
 * to perform a UNION on subsets of all Columnsets for a
 * Concept. Additionally the segmentation value is restored
 * when "reversing" SegmentationStratified.
 * Status of Unsegment:
 * - Sources compile
 * - CS_MSBRANCH is set correctly, except for MRFC.
 *
 * Revision 1.17  2002/08/07 14:23:57  euler
 * Bugfix.
 *
 * Revision 1.16  2002/08/07 14:22:42  euler
 * Bugfix.
 *
 * Revision 1.15  2002/08/07 12:43:55  euler
 * Updates to new structure; new comments.
 *
 * Revision 1.14  2002/08/05 10:35:46  euler
 * Restructured the operator hierarchy: introduction of SingleCSOperator
 * and MultipleCSOperator. Changed this class accordingly.
 *
 * Revision 1.13  2002/07/11 08:36:34  euler
 * Changed printing of messages.
 *
 * Revision 1.12  2002/06/11 09:21:37  euler
 * Column Statistics handling added, not tested yet.
 *
 * Revision 1.11  2002/06/10 08:45:11  euler
 * Added trash index, first tests ok.
 *
 * Revision 1.10  2002/06/04 13:14:32  euler
 * Commented the code.
 *
 * Revision 1.9  2002/05/31 12:35:00  euler
 * *** empty log message ***
 *
 * Revision 1.8  2002/05/23 11:34:59  euler
 * A few tests worked, others still to be done.
 *
 * Revision 1.7  2002/05/16 10:09:49  euler
 * First version that compiles.
 *
 * Revision 1.6  2002/05/15 13:05:01  euler
 * First version that compiles.
 *
 * Revision 1.5  2002/05/14 13:19:10  wiese
 * no message
 *
 * Revision 1.4  2002/05/10 13:23:21  euler
 * First M4 extensions, does not yet compile
 *
 * Revision 1.3  2002/05/07 13:06:55  wiese
 * get+set methods
 *
 * Revision 1.2  2002/05/07 12:15:19  euler
 * First M4 extensions, does not yet compile
 *
 * Revision 1.1  2002/04/30 13:00:27  wiese
 * compileable version
 *
 * Revision 1.6  2002/04/19 15:23:12  wiese
 * Initialversion nach der uebergabe
 *
 */
