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

import edu.udo.cs.miningmart.db.DB;
import edu.udo.cs.miningmart.exception.DbConnectionClosed;
import edu.udo.cs.miningmart.exception.M4CompilerError;
import edu.udo.cs.miningmart.exception.M4Exception;
import edu.udo.cs.miningmart.m4.utils.InterM4BaseattributeColumn;
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;

/**
 * This class represents a BaseAttribute. It is a subclass of
 * <code>Feature</code>.
 * 
 * @see edu.udo.cs.miningmart.m4.core.Feature
 * @see edu.udo.cs.miningmart.m4.core.M4Data
 * 
 * @author Martin Scholz
 * @version $Id: BaseAttribute.java,v 1.5 2006/04/11 14:10:14 euler Exp $
 */
public class BaseAttribute extends Feature implements XmlInfo, edu.udo.cs.miningmart.m4.BaseAttribute {

	// ***** Database constants for the BaseAttribute table *****

	/** The name of the M4 table representing base attributes */
	public static final String M4_TABLE_NAME = "baseattrib_t";

	/** db level: the attribute for the base attribute's IDs */
	public static final String ATTRIB_BASEATTRIBUTE_ID = "ba_id"; // NOT NULL NUMBER

	/** db level: the attribute for the base attribute's names */
	public static final String ATTRIB_BASEATTRIBUTE_NAME = "ba_name"; // NOT NULL VARCHAR2(100)

	/** db level: the attribute for the base attribute's conceptual datatype number */
	public static final String ATTRIB_BASEATTRIBUTE_CONCEPTUAL_DT = "ba_condtid"; // NOT NULL NUMBER

	/** db level: the attribute for the base attribute's relevance (unused) */
	public static final String ATTRIB_BASEATTRIBUTE_RELEVANCE = "ba_relevance"; // VARCHAR2(5)

	/** db level: the attribute for the base attribute's type (db or mining) */
	public static final String ATTRIB_BASEATTRIBUTE_TYPE = "ba_attribtype"; // NOT NULL VARCHAR2(15)

	/** db level: the attribute specifying the ID of the embedding MultiColumnFeature or NULL */
	public static final String ATTRIB_BASEATTRIBUTE_MCF_ID = "ba_mcfid"; // NUMBER


	// ***** Database constants for the BaseAttribute to Concept cross-table *****

	/** The name of the BaseAttribute to Concept cross-table */
	public static final String M4_TABLE_BA_CON = "ba_concept_t";

	/** The primary key attribute of the BaseAttribute to Concept cross-table */
	public static final String ATTRIB_BA_CON_TUPLE_ID = "bc_id";

	/** The Concept ID attribute of the BaseAttribute to Concept cross-table */
	public static final String ATTRIB_BA_CON_CONID = "bc_conid";

	/** The BaseAttribute ID of the BaseAttribute to Concept cross-table */
	public static final String ATTRIB_BA_CON_BAID = "bc_baid";



	// ***** Static helper fields *****

	/** Inter M4 communication class between base attributes (container) and columns */	
	static final InterM4BaseattributeColumn ba2col = new InterM4BaseattributeColumn();

	/** The only instance of Conceptual datypes, <code>null</code> means not loaded yet! */
	private static ConceptualDatatypes dataTypeMapping = null;

	/**
	 * Active getter for the datatype id to name and vice versa mapping.
	 * @param db a <code>DB</code> object for reading from the M4 system table
	 * */
	private ConceptualDatatypes getConceptualDatatypeMapping(DB db)
		throws DbConnectionClosed, M4Exception
	{
    	if (dataTypeMapping == null) {
    		dataTypeMapping = new ConceptualDatatypes(db);
    	}
    	return dataTypeMapping;
	}


	// ***** Methods from the M4Table interface *****

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

	/** @see M4Table.getM4Info() */
	public M4Info getM4Info() {
		if (m4Info == null) {
			M4InfoEntry[] m4i = {
				new M4InfoEntry(ATTRIB_BASEATTRIBUTE_ID,            "getId",                 "setId",                 long.class,     NOT_NULL),
				new M4InfoEntry(ATTRIB_BASEATTRIBUTE_NAME,          "getName",               "setName",               String.class,   NOT_NULL),
				new M4InfoEntry(ATTRIB_BASEATTRIBUTE_CONCEPTUAL_DT, "getConceptualDataType", "setConceptualDataType", long.class,     NOT_NULL),
				new M4InfoEntry(ATTRIB_BASEATTRIBUTE_RELEVANCE,     "getRelevantS",          "setRelevantS",          String.class),
				new M4InfoEntry(ATTRIB_BASEATTRIBUTE_TYPE,          "getDBAttribS",          "setDBAttribS",          String.class,   NOT_NULL),
				new M4InfoEntry(ATTRIB_BASEATTRIBUTE_MCF_ID,        "getMCFeature",          "primitiveSetMCFeature", edu.udo.cs.miningmart.m4.MultiColumnFeature.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("Name",               "getName",                   "setName",                   String.class),
				new M4InfoEntry("ConDatatype",        "getConceptualDataTypeName", "setConceptualDataTypeName", String.class),
				new M4InfoEntry("Relevant",           "getRelevantS",              "setRelevantS",              String.class),
				new M4InfoEntry("Type",               "getDBAttribS",              "setDBAttribS",              String.class),
				new M4InfoEntry("MultiColumnFeature", "getMCFeature",              "setMCFeature",              edu.udo.cs.miningmart.m4.MultiColumnFeature.class),
				new M4InfoEntry("Concept",            "getConcept",                "setConcept",                edu.udo.cs.miningmart.m4.Concept.class),
				new M4InfoEntry("Docu",               "getDocumentation",          "setDocumentation",          String.class)
			};
			xmlInfo = new M4Info(m4i);
		}
		return xmlInfo;
	}

	// ***** The private fields of the instances *****

    // BaseAttrib Variables from M4-DB (Name inherited from Feature.java)
    private long         dataType;
    private final Vector myColumns = new Vector(); // Vector of Column objects
    private boolean      allColumnsLoaded = false;
    private boolean    	 relevant;
    private boolean    	 dbAttrib;
    private MultiColumnFeature myMCFeature;



	// ***** Constructor *****

	/**
	 * @see edu.udo.cs.miningmart.m4.core.M4Data#Constructor
	 */
    public BaseAttribute(DB m4Db) { super(m4Db); }


	// ***** 

	/**
	 * @see edu.udo.cs.miningmart.m4.core.Parameter#print
	 */
    public void print() {
    	String dtName;
    	try {
    		dtName = this.getConceptualDataTypeName();
    	}
    	catch (Exception e) {
    		dtName = " <Conceptual datatype Id: " + this.getConceptualDataType() + "> ";
    	}
    	
        String toPrint = "Base Attribute " + getName() + " (Id: " + myId +"): "
        			   + dtName + " of concepts: ";
        Concept c;
        try {
        	if ((c = (Concept) this.getConcept()) != null) {
        		toPrint += c.getName() + ", "; 
        	}
            else  {  toPrint += "(not loaded)";  }
        }
        catch (M4Exception m4e) {
            this.doPrint(m4e);
        }
	    this.doPrint(Print.M4_OBJECT, toPrint);
        if (myColumns != null) {
        	Iterator it = this.myColumns.iterator();
     		while (it.hasNext()) {
     			Column col = (Column) it.next();
            	if (col != null)
            		col.print();           
            }
        }
    }

	/**
	 * Do not use spaces in BaseAttribute names, because these names
	 * are also used at the DB level for Column names.
	 * @param name the new name to be set
	 * 
	 * @see M4Object#setName(String)
	 */
	public void setName(String name) {
		name = this.replaceSpacesInName(name);
		super.setName(name);
	}
		
	/**
	 * Makes a copy of this BaseAttribute.
	 * 
	 * @return A clone of this BaseAttribute, but with Id 0 since it 
	 * 	 	   is not written into the database yet.
	 */
    public edu.udo.cs.miningmart.m4.BaseAttribute copy() throws M4Exception
    {
        BaseAttribute ret = (BaseAttribute) this.getM4Db().createNewInstance(edu.udo.cs.miningmart.m4.core.BaseAttribute.class);
        ret.setId(0);
        ret.setConceptualDataType(this.getConceptualDataType());
        ret.setDBAttrib(this.isDBAttrib());
        ret.setName(this.getName());
        ret.setRelevant(this.isRelevant());

        return ret;
    }

	/**
	 * Create a copy of this BaseAttribute and connect it to the given Concept.
	 * 
	 * @param newConcept the concept to add the copy of this BaseAttribute to
	 * @return a copy of this BaseAttribute; the copy is connected to the given Concept
	 */
	public edu.udo.cs.miningmart.m4.Feature copy(edu.udo.cs.miningmart.m4.Concept newConcept) throws M4Exception {
		
		edu.udo.cs.miningmart.m4.core.Feature theCopy = 
			(edu.udo.cs.miningmart.m4.core.BaseAttribute) this.copy();

        String nameOfCopy = newConcept.getValidName(this.getName(), BaseAttribute.class);
        theCopy.setName(nameOfCopy);
    	theCopy.setConcept(newConcept);	
    	
    	return theCopy;
    }
    
	/**
	 * Add a column to this BaseAttribute's columns.
	 * 
	 * @param c The new column.
	 */
	public void addColumn(edu.udo.cs.miningmart.m4.Column column) throws M4Exception {
    	ba2col.add(this, (edu.udo.cs.miningmart.m4.core.Column) column);
    }
	
	/**
	 * Create a Column with the given name and add it to this BaseAttribute's
	 * columns.
	 *  
	 * @param name name for the Column
	 * @return the Columm
	 * @throws M4Exception
	 */
	public edu.udo.cs.miningmart.m4.Column createColumn(String name) throws M4Exception {
		edu.udo.cs.miningmart.m4.Column newCol = (Column) this.getM4Db().createNewInstance(Column.class);
		newCol.setName(name);
		this.addColumn(newCol);
		return newCol;
	}

	/**
	 * @param col a <code>Column</code>
	 * @return <code>true</code> if a column with the same ID is already linked to this
	 * <code>BaseAttribute</code>
	 * */
	public boolean hasColumn(edu.udo.cs.miningmart.m4.Column col) throws M4Exception {
		Collection columns = this.getColumns();
		if (col == null || columns == null) {
			return false;	
		}
		return columns.contains(col);
	}
	
	/**
	 * @return <code>true</code> if at least one column is linked to this
	 * <code>BaseAttribute</code>
	 * */
	public boolean hasColumns() throws M4Exception {
		Collection columns = this.getColumns();
		if (columns == null || columns.isEmpty()) {
			return false;	
		}
		return true;
	}

	/**
	 * Remove a column from this BaseAttribute's columns.
	 * 
	 * @param c The column to remove
	 * @return <code>true</code> if removing succeeded
	 */
	public boolean removeColumn(edu.udo.cs.miningmart.m4.Column column) throws M4Exception {
		return ba2col.remove(this, (edu.udo.cs.miningmart.m4.core.Column) column);
    }	

	public void removeLinkToColumns() throws M4Exception {
		ba2col.setCollectionTo(this, null);
	}
	
	/**
	 * Set the conceptual data type.
	 * 
	 * @param type The new type.
	 */ 
    public void setConceptualDataType(long type) {   
    	this.setDirty();
    	this.dataType = type;
    }

	/**
	 * @return the conceptual data type.
	 */
    public long getConceptualDataType()
    {   return dataType;   }

	/**
	 * Set the name of the conceptual data type.
	 * 
	 * @param dtname The new name of the conceptual data type.
	 */
    public void setConceptualDataTypeName(String dtname)
    	throws M4Exception {
    	try {
    		long type = getConceptualDatatypeMapping(this.getM4Db()).getIdForName(dtname);
    		this.setConceptualDataType(type);
    	}
    	catch (DbConnectionClosed c) {
    		throw new M4Exception("BaseAttribute.setConceptualDataTypeName: DbConnectionClosed Exception caught: "+ c.getMessage());
    	}
    }

	/**
	 * @return The name of this BaseAttribute's conceptual data type.
	 */
    public String getConceptualDataTypeName()
    	throws M4Exception {
    	try {
    		long type = this.getConceptualDataType();
    		return getConceptualDatatypeMapping(this.getM4Db()).getNameForId(type);
    	}
    	catch (DbConnectionClosed c) {
    		throw new M4Exception("BaseAttribute.setConceptualDataTypeName: DbConnectionClosed Exception caught: "+ c.getMessage());
    	}
    }

	/**
	 * Set all columns of this BaseAttribute.
	 * 
	 * @param theColumns A <code>Collection</code> of <code>Column</code> objects
	 */
    public void setColumns(Collection theColumns) throws M4Exception {
    	ba2col.setCollectionTo(this, theColumns);
    }

	/**
	 * @return The columns that belong to this BaseAttribute.
	 */
    public Collection getColumns() throws M4Exception
    {
     	if (allColumnsLoaded == false && ( ! this.isNew())) {
	       	this.allColumnsLoaded = true;
            this.readColumnsForBA();
     	}
        return myColumns;
    }
    
    /**
     * Get a specific column that belongs to this BaseAttribute.
     * 
     * @param The number of the column to be returned.
     * @return The column with the given number.
     */
    public edu.udo.cs.miningmart.m4.Column getColumn(int index) throws M4Exception
    {
        this.getColumns();
        if ((myColumns != null) && (index > -1) && (index < myColumns.size()))
        {  return (edu.udo.cs.miningmart.m4.Column) myColumns.get(index); }
        else
        {  throw new M4Exception("BaseAttribute.getColumn(): No Columnarray exists, or wrong index!");  }
    }

	/*
	 * Return the Column that belongs to the given Columnset.
	 */
    private edu.udo.cs.miningmart.m4.Column getColumnForColumnSet(Columnset cs) throws M4Exception
    {
        Collection columns = this.getColumns();
        if (columns != null) {
	        Iterator it = columns.iterator();
    	    while (it.hasNext()) {
		        Column col = (Column) it.next();
        	  	if (col != null) {
        	  		edu.udo.cs.miningmart.m4.Columnset myCs = col.getColumnset();
    	        	if (myCs != null && myCs.getId() == cs.getId())
	        	    {  return col;  }
        	  	}
            }
        }
        return null;
    }

    /**
     * This method replaces "getColumnForColumnSet". The current column is
     * the one that belongs to the current columnset of the concept that this
     * BaseAttribute belongs to. 
     * 
     * @return The current column.
     * 
     * @see edu.udo.cs.miningmart.m4.core.Concept
     */
    public edu.udo.cs.miningmart.m4.Column getCurrentColumn() throws M4Exception
    {
        // take current columnset of this BA's concept, and find the column
        // for it:
    	edu.udo.cs.miningmart.m4.Concept c = this.getConcept();

        if (c != null) 
        {
        	Columnset cs = (Columnset) c.getCurrentColumnSet();
            return this.getColumnForColumnSet(cs);
        }
        else
        {   return null;   }
    }

	/**
	 * If this BaseAttribute belongs to a MultiColumnFeature, set it here.
	 * 
	 * @param mcf The MultiColumnFeature this BaseAttribute belongs to.
	 * 
	 * @see edu.udo.cs.miningmart.m4.core.MultiColumnFeature
	 */
    public void setMCFeature(edu.udo.cs.miningmart.m4.MultiColumnFeature mcf) throws M4Exception {
    	MultiColumnFeature.mcf2ba.checkNameExists(this, mcf);
    	MultiColumnFeature.mcf2ba.updateReferenceTo(this, mcf);
    }

	/**
	 * If this BaseAttribute belongs to a MultiColumnFeature, get it here.
	 * 
	 * @return The MultiColumnFeature if this BaseAttribute belongs to one,
	 * 	       <code>null</code> otherwise.
	 * 
	 * @see edu.udo.cs.miningmart.m4.core.MultiColumnFeature
	 */
    public edu.udo.cs.miningmart.m4.MultiColumnFeature getMCFeature()
    {   return myMCFeature;   }

	/**
	 * @return TRUE if this BaseAttribute is relevant.
	 */
    public boolean isRelevant()
    {   return relevant;   }

	/**
	 * @return the relevance of this BaseAttribute using the
	 *         database <code>String</code> representation
	 */
    public String getRelevantS()
	{   return (this.isRelevant() ? DB.c_yes : DB.c_no); }


	/**
	 * Set the relevance of this BaseAttribute.
	 * 
	 * @param r The new boolean value of the relevance.
	 */
    public void setRelevant(boolean r)
    {   
    	this.setDirty();
    	this.relevant = r;
    }

	/**
	 * Set the relevance of this BaseAttribute.
	 * 
	 * @param r The value of the relevance in thedatabase <code>String</code>
	 * 		  representation
	 */
	public void setRelevantS(String r) {
		this.setRelevant(DB.c_yes.equals(r));
	}

	/**
	 * @return TRUE if this BaseAttribute is a DB Attribute.
	 */
    public boolean isDBAttrib()
    {   return dbAttrib;   }

	/**
	 * Getter for the DB Attribute property
	 * @return the boolean flag in its database <code>String</code> representation
	 */
	public String getDBAttribS() {
		return (this.isDBAttrib() ? DB.c_db : DB.c_mining);
	}

	public String getType() {
		return this.getDBAttribS();
	}
	
	/**
	 * Setter for DBAttrib.
	 * 
	 * @param a The new boolean value.
	 */
    public void setDBAttrib(boolean a)
    {   
    	this.setDirty();
    	this.dbAttrib = a;
    }

	/**
	 * Setter for DBAttrib.
	 * 
	 * @param attrib The boolean value in its database <code>String</code> representation.
	 */
	public void setDBAttribS(String attrib) {
		this.setDBAttrib(DB.c_db.equals(attrib));	
	}
	
	public void setType(String type) throws M4Exception {
		if (type.equals(TYPE_BASE)) {
			throw new M4Exception("M4 error when trying to set type for BaseAttribute '" +
					              this.getName() + "': the type '" + 
					              TYPE_BASE + "' is no longer supported!");
		}
		if ( ! ( type.equals(TYPE_DB) || type.equals(TYPE_MINING) )) {
			throw new M4Exception("M4 error when trying to set type for BaseAttribute '" +
					 	          this.getName() + "': unknown type '" + type + "'!");
		}
		this.setDBAttribS(type);
	}
	
	/**
	 * @return <code>true</code> iff this <code>BaseAttribute</code> has
	 * been &quot;deselected&quot; by a <code>FeatureSelection</code> operator
	 * or has not been connected by the user.
	 * */
    public boolean isDeselected() throws M4CompilerError {
    	try {
	    	return (this.getCurrentColumn() == null);
    	}
    	catch (M4Exception e)
    	{   throw new M4CompilerError("Error getting current column for BA with Id " + this.getId() +
    		                          ": " + e.getMessage());  
    	}
    }
    	
	/**
	 * Sets all columns that are found in the database as belonging to 
	 * the given BaseAttribute into the BaseAttribute object.
	 * Executed by an active getter.
	 * 
	 * @param ba The BaseAttribute
	 */
    private void readColumnsForBA() throws M4Exception
    {
		Collection theColumns = this.getObjectsReferencingMe(Column.class);
		this.setColumns(theColumns);
    }

	/**
	 * Sets the concept that is found in the database as belonging to this BA.
	 * Executed at loading time.
	 */
    private void readConceptForBA() throws M4Exception {
	    String query = 
	           "SELECT " + ATTRIB_BA_CON_CONID +
	           " FROM "  + M4_TABLE_BA_CON +
	           " WHERE " + ATTRIB_BA_CON_BAID +
	           " = " + this.getId();

    	Long conId = this.executeM4SingleValueSqlReadL(query);
    	Concept c = null;
		if (conId != null) {
			c = (Concept) this.getM4Db().getM4Object(conId.longValue(), Concept.class);
	    }
	    this.primitiveSetConcept(c);
    }    
	
	/**
	 * Primitive setter, do not use.
	 * @param mcf the <code>MultiColumnFeature</code> to be set
	 * */
    public void primitiveSetMCFeature(edu.udo.cs.miningmart.m4.MultiColumnFeature mcf) {
    	this.setDirty();
    	this.myMCFeature = (MultiColumnFeature) mcf;	
    }


	/**
	 * This method returns information about the relational validity
	 * of the object. A BaseAttribute is valid if it is connected to a
	 * Concept, and 
	 *  - for type DB: if it has a Column 
	 *  - for type MINING: if it is an output BA, or part of an output MCF or output Concept
	 */
	public boolean isRelationallyValid() throws M4Exception	{
        if (this.getConcept() == null) {   
        	return false; 
		}
		if (this.isDBAttrib()) {   
			Collection columns = this.getColumns();			
			if (columns == null || columns.isEmpty()) {   
				return false;  
			}
		}
		else {
			boolean valid = false;
			
			// check if this BA is part of an output concept...
			Iterator it = null;
			it = this.getConcept().getParameterReferences().iterator();
			
			while (it.hasNext()) {   
				if (((Parameter) it.next()).getParameterType() == Parameter.TYPE_OUTPUT)
				{   valid = true;   }
			}
			
			// ... or part of an output MCF...
			if (( ! valid) && this.getMCFeature() != null) {
				it = this.getMCFeature().getParameterReferences().iterator();
				while (it.hasNext()) {   
					if (((Parameter) it.next()).getParameterType() == Parameter.TYPE_OUTPUT)
					{   valid = true;   }
				}
			}
				
			// ... or an output BA.
			if ( ! valid) {
				it = this.getParameterReferences().iterator();
				while (it.hasNext())
				{   if (((Parameter) it.next()).getParameterType() == Parameter.TYPE_OUTPUT)
					{   valid = true;  }
				}
			}
			return valid;
		}
	    return true;
	}

    
	/**
	 * Reads this object's <code>Concept</code> from a cross-table
	 * at loading time.
	 */
	protected void readFromDbLocal() throws M4Exception {
		this.readConceptForBA();
	}
     
    /**
	 * This method stores the pseudo foreign key reference to this objects's
	 * <code>Concept</code>, which is still realized by a cross-table
	 *(<i>BA_CONCEPT_T</i>).
	 */
	protected void storeLocal() throws M4Exception {
		super.storeLocal();
		
		{ // Delete all references to concept first:
			String sql = "DELETE FROM " + M4_TABLE_BA_CON
			           + " WHERE " + ATTRIB_BA_CON_BAID
				           + " = " + this.getId();
			
			this.executeM4SqlWrite(sql);
		}

		// If there is no concept there is nothing else to do.		
		if (this.getConcept() != null)
		{ // Otherwise write the reference to the concept:
			String conceptId = Long.toString(this.getConcept().getId());

			String sql = "INSERT INTO " + M4_TABLE_BA_CON
					   + " ( " + ATTRIB_BA_CON_TUPLE_ID
					   + ", " + ATTRIB_BA_CON_BAID
					   + ", " + ATTRIB_BA_CON_CONID
					   + " ) VALUES ( "
					   + this.getNextM4SequenceValue()
					   + ", " + this.getId()
					   + ", " + conceptId + " )";
					
			this.executeM4SqlWrite(sql);
		}
	}
	
	/**
	 * Overwrites the superclass method to ensure that
	 * the cross table entries are deleted first
	 */
	protected void deleteLocal() throws M4Exception {
		super.deleteLocal();
		
		String sql = "DELETE FROM " + M4_TABLE_BA_CON
		           + " WHERE " + ATTRIB_BA_CON_BAID
		           + " = " + this.getId();
			
		this.executeM4SqlWrite(sql);	
		
		sql = "DELETE FROM " + Column.M4_TABLE_COL_BA
        + " WHERE " + Column.ATTRIB_COL_BA_BAID
        + " = " + this.getId();
	
		this.executeM4SqlWrite(sql);
	}
	
	/** @see M4Data#removeAllM4References() */
	protected void removeAllM4References() throws M4Exception {
		super.removeAllM4References();
		this.setColumns(new Vector());
		this.setConcept(null);  
		this.setMCFeature(null);
		this.removeDocObject();
	}

	/** @see M4Data#getDependentObjects */
	public Collection getDependentObjects() throws M4Exception {
		Collection ret = super.getDependentObjects();
		ret.addAll(this.getColumns());
		return ret;
	}
 
}
/*
 * Historie
 * --------
 * 
 * $Log: BaseAttribute.java,v $
 * Revision 1.5  2006/04/11 14:10:14  euler
 * Updated license text.
 *
 * Revision 1.4  2006/04/06 16:31:13  euler
 * Prepended license remark.
 *
 * Revision 1.3  2006/01/06 16:25:04  euler
 * Updates and bugfixes in the delete-Mechanism for M4Data objects.
 *
 * Revision 1.2  2006/01/03 11:19:53  euler
 * Bugfix in method removeLinkToColumns
 *
 * Revision 1.1  2006/01/03 09:54:17  hakenjos
 * Initial version!
 *
 */
