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

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.Print;
import edu.udo.cs.miningmart.m4.utils.XmlInfo;

/**
 * Instances of this class represent an entry in the table
 * DOCU_T.
 * 
 * @author Timm Euler
 * @version $Id: Docu.java,v 1.4 2006/04/11 14:10:14 euler Exp $
 */
public class Docu extends M4Data implements XmlInfo, edu.udo.cs.miningmart.m4.Docu {
	
	/** The M4 table name storing documentation information. */
	public static final String M4_TABLE_NAME = "docu_t";
	
	/** DB level: The attribute storing the local docu IDs. */
	public static final String ATTRIB_DOC_ID = "doc_id";
	
	/** DB level: The attribute storing the doc-entry's object IDs. */
	public static final String ATTRIB_OBJECT_ID = "doc_objid";
	
	/** DB level: The attribute storing the object types. */
	public static final String ATTRIB_OBJECT_TYPE = "doc_objtype";

	/** DB level: The attribute storing the documentation */
	public static final String ATTRIB_TEXT = "doc_text";

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

	/**
	 * @see edu.udo.cs.miningmart.m4.utils.M4Table#getM4TableName()
	 */
	public String getM4TableName()
	{	return M4_TABLE_NAME;   }

	/**
	 * @see edu.udo.cs.miningmart.m4.utils.M4Table#getIdAttributeName()
	 */
	public String getIdAttributeName()
	{	return ATTRIB_DOC_ID;	}

	/**
	 * @see edu.udo.cs.miningmart.m4.utils.M4Table#getM4Info()
	 */
	public M4Info getM4Info()
	{
		if (m4Info == null) {
			M4InfoEntry[] m4i = {
				new M4InfoEntry(ATTRIB_DOC_ID,      "getId",         "setId",         long.class, NOT_NULL),
//				new M4InfoEntry(ATTRIB_OBJECT_ID,   "getObjectId",   "primitiveSetM4Object",   M4Data.class),
				new M4InfoEntry(ATTRIB_OBJECT_ID,   "getM4Object",   "primitiveSetM4Object",   edu.udo.cs.miningmart.m4.M4Data.class, NOT_NULL),
				new M4InfoEntry(ATTRIB_OBJECT_TYPE, "getObjectType", "setObjectType", String.class, NOT_NULL),
				new M4InfoEntry(ATTRIB_TEXT,        "getText",       "setText",       String.class, NOT_NULL)
			};
			m4Info = new M4Info(m4i);
		}
		return m4Info;
	}

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

	/** @see XmlInfo.getXmlInfo() */
	public M4Info getXmlInfo() {
		if (xmlInfo == null) {
			M4InfoEntry[] m4i = {
				new M4InfoEntry("M4Object", "getM4Object", "setM4Object", edu.udo.cs.miningmart.m4.M4Data.class),
				new M4InfoEntry("Text",     "getText",     "setText",     String.class)
			};
			xmlInfo = new M4Info(m4i);
		}
		return xmlInfo;
	}
	
	private M4Data myM4Object;
	private String myText, myObjectType;
	private long myM4ObjectId = -1;

	/**
	 * Constructor for Docu.
	 * @param m4Db
	 */
	public Docu(DB m4Db)
	{	super(m4Db);   }
	
	/**
	 * @see edu.udo.cs.miningmart.m4.core.M4Object#print()
	 */
	public void print()
	{
		this.doPrint(Print.M4_OBJECT, "Documentation for M4 Object of type " + this.getM4Object().getClass().getName() +
		                              ", Id " + this.getId() + ": " + this.getText());
	}
	
	/**
	 * @see edu.udo.cs.miningmart.m4.core.M4Data#getObjectsInNamespace(Class)
	 */
	protected Collection getObjectsInNamespace(Class typeOfObjects) throws M4Exception {
		return null;
	}
	
	/**
	 * Returns the M4Object that this documentation entry belongs to.
	 * 
	 * @return M4Object
	 */
	public edu.udo.cs.miningmart.m4.M4Object getM4Object()
	{	return myM4Object;	}

	/**
	 * Returns the actual documentation entry (the description String).
	 * 
	 * @return String
	 */
	public String getText()
	{	return myText;	}

	/**
	 * Primitive setter. Do not use!
	 * 
	 * @param newM4Object The new M4Object to set
	 */
	public void primitiveSetM4Object(edu.udo.cs.miningmart.m4.M4Data newM4Object) throws M4Exception
	{	this.myM4Object = (M4Data) newM4Object;	
		if (newM4Object != null)
		{
			this.myM4ObjectId = newM4Object.getId();
			this.myObjectType = this.findTypeNameForClass(newM4Object.getClass());
		}
	}
	
	/**
	 * Set the connection to the M4 object that this
	 * documentation object is associated with.
	 */
	public void setM4Object(edu.udo.cs.miningmart.m4.M4Data newM4Object) throws M4Exception
	{   M4Data.m4o2doc.setReciprocalReferences((M4Object) newM4Object, this);   }

	/**
	 * Sets the text (the description String for the M4 Object 
	 * that this Documentation object belongs to).
	 * 
	 * @param newText The new text to set
	 */
	public void setText(String newText)
	{	
		this.setDirty();
		this.myText = newText;	
	}
	
	/**
	 * Returns the id of the M4 object associated with
	 * this documentation object.
	 * 
	 * @return long
	 */
	public long getObjectId()
	{	
		if (this.myM4ObjectId > -1)
		{   return this.myM4ObjectId;  }
		else
		{   return 0;   }
	}

	/**
	 * Returns the type of the M4 object associated with
	 * this documentation object.
	 * 
	 * @return String
	 */
	public String getObjectType()
	{	return this.myObjectType;   }

	/**
	 * Sets the id of the M4 object associated with
	 * this documentation object.
	 * 
	 * @param id The id to set
	 */
	public void setObjectId(long id) throws M4Exception
	{	
		this.setDirty();
		this.myM4ObjectId = id;
		
		if (this.getObjectType() != null)
		{   
			Class c = this.findClassForTypeName(this.getObjectType());
			this.setM4Object((edu.udo.cs.miningmart.m4.M4Data) this.getM4Db().getM4Object(id, c));
		}
	}

	/** @see M4Data#removeAllM4References() */
	protected void removeAllM4References() throws M4Exception {
		this.setM4Object(null);
	}

	/** @see M4Data#getDependentObjects */
	public Collection getDependentObjects() {
		// Do not call the super method to avoid getting the
		// documentation of the documentation!
		return new Vector();
	}

	/**
	 * Sets the the type of the M4 object associated with
	 * this documentation object.
	 * 
	 * @param type The class of the M4 object.
	 */
	public void setObjectType(String type) throws M4Exception
	{	
		this.setDirty();
		this.myObjectType = type;	
		if (this.getObjectId() > -1)
		{   
			Class c = this.findClassForTypeName(type);
			this.setM4Object((edu.udo.cs.miningmart.m4.M4Data) this.getM4Db().getM4Object(this.getObjectId(), c));
		}	
	}
	
	// returns a String which is used as a representation for the type
	// of the given object in the database table
	private Class findClassForTypeName(String typeName) throws M4Exception
	{
		String classname = null;
		for (int i = 0; i < this.mapping.length; i++)
		{   if (typeName.equals(mapping[i][1]))
			{   classname = mapping[i][0];  }
		}
		if (classname == null)
		{   throw new M4Exception("Docu.findClassForTypeName: unknown type name '" + typeName + "'!");  }
		
		Class c = null;
		try {
		    c = Class.forName(classname);
		}
		catch (ClassNotFoundException cnfe)
		{   throw new M4Exception("Docu.findClassForTypeName: Class not found: " + c.getName());  }
		
		return c;
	}
	
	private String findTypeNameForClass(Class type) throws M4Exception
	{
		// check if we get the right type of object:
		if ( ! edu.udo.cs.miningmart.m4.M4Object.class.isAssignableFrom(type)) {
			throw new M4Exception("Docu.findTypeNameForClass: expected an M4 object but got " + type.getName() + "!");
		}
		
		for (int i = 0; i < this.mapping.length; i++)
		{   if (mapping[i][0].equals(type.getName()))
			{   return mapping[i][1];  }
		}
		throw new M4Exception("Docu.findTypeNameForClass: unknown class " + type.getName() + "!"); 
	}
	
	// this mapping gives the String for ATTRIB_OBJECT_TYPE
	private String[][] mapping = {
        {"edu.udo.cs.miningmart.m4.core.Assertion", "Assertion" },
        {"edu.udo.cs.miningmart.m4.core.BaseAttribute", "BaseAttribute"},
        {"edu.udo.cs.miningmart.m4.core.Case", "Case"},
        {"edu.udo.cs.miningmart.m4.core.Chain", "Chain"},
        {"edu.udo.cs.miningmart.m4.core.Column", "Column"},
        {"edu.udo.cs.miningmart.m4.core.Columnset", "Columnset"},
        {"edu.udo.cs.miningmart.m4.core.Concept", "Concept"},
        {"edu.udo.cs.miningmart.m4.core.Condition", "Condition"},
        {"edu.udo.cs.miningmart.m4.core.Constraint", "Constraint"},
        {"edu.udo.cs.miningmart.m4.core.Feature", "Feature"},
        {"edu.udo.cs.miningmart.m4.core.ForeignKey", "ForeignKey"},
        {"edu.udo.cs.miningmart.m4.core.PrimaryKey", "PrimaryKey"},
        {"edu.udo.cs.miningmart.m4.core.KeyMember", "KeyMember"},
        {"edu.udo.cs.miningmart.m4.core.MultiColumnFeature", "MultiColumnFeature"},
        {"edu.udo.cs.miningmart.m4.core.OpParam", "OperatorParameter"},
        {"edu.udo.cs.miningmart.m4.core.Operator", "OPERATOR"},
        {"edu.udo.cs.miningmart.m4.core.Parameter", "Parameter"},
        {"edu.udo.cs.miningmart.m4.core.Projection", "Projection"},
        {"edu.udo.cs.miningmart.m4.core.Relation", "Relationship"},
        {"edu.udo.cs.miningmart.m4.core.Step", "Step"},
        {"edu.udo.cs.miningmart.m4.core.Value", "Value"}
	};
}
/*
 * Historie
 * --------
 * 
 * $Log: Docu.java,v $
 * Revision 1.4  2006/04/11 14:10:14  euler
 * Updated license text.
 *
 * Revision 1.3  2006/04/06 16:31:14  euler
 * Prepended license remark.
 *
 * Revision 1.2  2006/03/24 13:14:58  euler
 * Bugfix
 *
 * Revision 1.1  2006/01/03 09:54:18  hakenjos
 * Initial version!
 *
 */
