/*
 * 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.m4.core;
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.utils.M4Info;
import edu.udo.cs.miningmart.m4.utils.M4InfoEntry;
import edu.udo.cs.miningmart.m4.utils.XmlInfo;
/**
 * @author Martin Scholz
 * @version $Id: ColumnsetStatistics.java,v 1.6 2006/04/11 14:10:14 euler Exp $
 */
public class ColumnsetStatistics extends M4Data implements XmlInfo, edu.udo.cs.miningmart.m4.ColumnsetStatistics {
	
	// ***** Database constants for the Column table *****
	public static final String M4_TABLE_NAME = "csstatist_t";
	public static final String ATTRIB_CSSTAT_ID = "csst_id";
	public static final String ATTRIB_CSSTAT_CS = "csst_csid";
	public static final String ATTRIB_CSSTAT_ALL = "csst_all";
	public static final String ATTRIB_CSSTAT_ORD = "csst_ord";
	public static final String ATTRIB_CSSTAT_NOM = "csst_nom";
	public static final String ATTRIB_CSSTAT_TIME = "csst_time";

	/** Cache for getM4Info() */
	public static M4Info m4Info = null;

	/** @see M4Table.getM4TableName() */
	public String getM4TableName() {
		return M4_TABLE_NAME;
	}

	/** @see M4Table.getIdAttributeName() */
	public String getIdAttributeName() {
		return ATTRIB_CSSTAT_ID;
	}

	/** @see M4Table.getM4Info() */
	public M4Info getM4Info() {
		if (m4Info == null) {
			M4InfoEntry[] m4i = {
				new M4InfoEntry(ATTRIB_CSSTAT_ID,   "getId",              "setId",                 long.class,      NOT_NULL),
				new M4InfoEntry(ATTRIB_CSSTAT_CS,   "getTheColumnset",    "primitiveSetColumnset", edu.udo.cs.miningmart.m4.Columnset.class, NOT_NULL),
				new M4InfoEntry(ATTRIB_CSSTAT_ALL,  "getNrOfAllTuples",   "setNrOfAllTuples",      Integer.class),
				new M4InfoEntry(ATTRIB_CSSTAT_ORD,  "getNrOfOrdAttribs",  "setNrOfOrdAttribs",     Integer.class),
				new M4InfoEntry(ATTRIB_CSSTAT_NOM,  "getNrOfNomAttribs",  "setNrOfNomAttribs",     Integer.class),
				new M4InfoEntry(ATTRIB_CSSTAT_TIME, "getNrOfTimeAttribs", "setNrOfTimeAttribs",    Integer.class)
			};
			m4Info = new M4Info(m4i);
		}
		return m4Info;
	}
	
	// ***** Method from the XmlInfo interface *****

	/** Cache for getXmlInfo() */
	private static M4Info xmlInfo = null;

	/** @see XmlInfo.getXmlInfo() */
	public M4Info getXmlInfo() {
		if (xmlInfo == null) {
			M4InfoEntry[] m4i = {
				new M4InfoEntry("Columnset",   "getTheColumnset",    "setTheColumnset",    edu.udo.cs.miningmart.m4.Columnset.class),
				new M4InfoEntry("NrOfTuples",  "getNrOfAllTuples",   "setNrOfAllTuples",   Integer.class),
				new M4InfoEntry("OrdinalAttr", "getNrOfOrdAttribs",  "setNrOfOrdAttribs",  Integer.class),
				new M4InfoEntry("NominalAttr", "getNrOfNomAttribs",  "setNrOfNomAttribs",  Integer.class),
				new M4InfoEntry("TimeAttr",    "getNrOfTimeAttribs", "setNrOfTimeAttribs", Integer.class)
			};
			xmlInfo = new M4Info(m4i);
		}
		return xmlInfo;
	}
	// *****
	
	private Columnset myColumnset;
	
	private Integer noOfRows, noOfOrdAttr, noOfNomAttr, noOfTimeAttr;
	
	public ColumnsetStatistics(DB db) {
		super(db);
	}
	
	public edu.udo.cs.miningmart.m4.Columnset getTheColumnset() {
		return this.myColumnset;
	}
	
	public void setTheColumnset(edu.udo.cs.miningmart.m4.Columnset columnset) throws M4Exception {
		Columnset.csstat.updateReferenceTo(this, columnset);
	}
	
	public void primitiveSetColumnset(edu.udo.cs.miningmart.m4.Columnset columnset) {
		this.setDirty();
		this.myColumnset = (Columnset) columnset;
	}
	
	/** Print the information about this column statistics. */
	public void print() {}
	
	/** Remove the Column reference of this statistic object. */
	public void removeAllM4References() throws M4Exception {
		this.setTheColumnset(null);
	}
	
	/**
	 * @see edu.udo.cs.miningmart.m4.core.M4Data#getObjectsInNamespace(Class)
	 */
	protected Collection getObjectsInNamespace(Class typeOfObjects) throws M4Exception {
		return null;
	}
	
	public Integer getNrOfAllTuples() {
		return this.noOfRows;
	}
	
	public void setNrOfAllTuples(Integer nrOfRows) {
		this.noOfRows = nrOfRows;
	}
	
	public Integer getNrOfOrdAttribs() {
		return this.noOfOrdAttr;
	}
	
	public void setNrOfOrdAttribs(Integer nrOfOrdinalAttributes) {
		this.noOfOrdAttr = nrOfOrdinalAttributes;
	}
	
	public Integer getNrOfNomAttribs() {
		return this.noOfNomAttr;
	}
	
	public void setNrOfNomAttribs(Integer nrOfNominalAttributes) {
		this.noOfNomAttr = nrOfNominalAttributes;
	}
	
	public Integer getNrOfTimeAttribs() {
		return this.noOfTimeAttr;
	}
	
	public void setNrOfTimeAttribs(Integer nrOfTimeAttributes) {
		this.noOfTimeAttr = nrOfTimeAttributes;
	}
	
	/**
	 * This method updates the statistics on demand.
	 * All values already available are not changed.
	 * It is expected that the garbage collection removes deprecated values.
	 * Changing DB Concepts are not yet supported.
	 * 
	 * @throws M4Exception
	 */
	public void update() throws M4Exception
	{
		final edu.udo.cs.miningmart.m4.Columnset myCS = this.getTheColumnset();
		if (myCS == null)
			return;

		/* --- Calculate csstAll: COUNT(*) of the Columnset --- */
		this.updateCount();

		/* --- Count number of columns of different type:  --- */
		final String pre =
			"SELECT COUNT(*) FROM COLUMN_T WHERE col_coldtid = ";
		final String post = " AND col_csid = " + myCS.getId();
 
		try {
			if (this.getNrOfOrdAttribs() == null) {
				String csstOrd = this.executeM4SingleValueSqlRead(pre + "12"
						+ post);
				this.setNrOfOrdAttribs((csstOrd == null) ? null : new Integer(
						csstOrd));
			}

			if (this.getNrOfNomAttribs() == null) {
				String csstNom = this.executeM4SingleValueSqlRead(pre + "13"
						+ post);
				this.setNrOfNomAttribs((csstNom == null) ? null : new Integer(
						csstNom));
			}

			if (this.getNrOfTimeAttribs() == null) {
				String csstTime = this.executeM4SingleValueSqlRead(pre + "14"
						+ post);
				this.setNrOfTimeAttribs((csstTime == null) ? null
						: new Integer(csstTime));
			}
		}
		catch (NumberFormatException e) {
			// This should not happen, because of we query for a count. 
			throw new M4Exception(
				"Columnset.updateStatistics for ColumnSet with ID "
					+ myCS.getId()
					+ ":\nStatistic calculation yielded a String not parseable to Integer.");
		}

		/* --- Calculate the statistics of all the embedded columns.  ---*/
		Collection cols = myCS.getColumns();
		Iterator it = cols.iterator();
		while (it.hasNext()) {
			Column column = (Column) it.next();
			column.updateStatistics();
		}
	}

	
    /**
     * Computes and updates the number of rows of this ColumnSet.
     */
    public void updateCount() throws M4Exception
    {
		final edu.udo.cs.miningmart.m4.Columnset myCS = this.getTheColumnset();
		if (myCS == null)
			return;

		Integer count = this.getNrOfAllTuples();
        if (count == null)
        {
            String query = "SELECT COUNT(*) FROM " + myCS.getSchemaPlusName();
			String newCount = this.executeBusinessSingleValueSqlRead(query);

			if (newCount == null) {
				throw new M4Exception(
					"Could not compute count for columnset '"
					+ this.getName() + "'!");
			}

			try {
				count = new Integer(newCount);
			}
			catch (NumberFormatException e) {
				throw new M4Exception(
					"Internal error when computing number of tuples. Query did not return an integer:\n"
					+ query
				);
			}

            this.setNrOfAllTuples(count);
		}
    }

	
}
/*
 * Historie
 * --------
 * 
 * $Log: ColumnsetStatistics.java,v $
 * Revision 1.6  2006/04/11 14:10:14  euler
 * Updated license text.
 *
 * Revision 1.5  2006/04/06 16:31:13  euler
 * Prepended license remark.
 *
 * Revision 1.4  2006/01/13 01:19:46  scholz
 * improved statistics computation
 *
 * Revision 1.3  2006/01/12 20:35:18  scholz
 * bugfix statistics
 *
 * Revision 1.2  2006/01/12 17:32:03  scholz
 * Changed getter for tuple count of Columnset into an active getter.
 * The SQL query is fairly simple and this simplifies things for the HCI.
 *
 * Revision 1.1  2006/01/03 09:54:17  hakenjos
 * Initial version!
 *
 */
