/** 
 * Project    : KANT (LMT)
 * Source Name: Concept.java
 * Copyright  : Copyright (c) LTI, Carnegie Mellon University
 * Description: Class for concept
 * @version     1.0 (created by jko - 10/01/01)
 **/

package lmt;

import java.util.*;
import java.sql.*;

public class Concept {
  String	concept_id;
  String	term_id;
  String	concept_symbol;
  String	cte_entry;
  String	capitalization;
  String	irr_capitalization;
  String	ambiguity;
  String	date_created;
  String	author_creating;
  String	date_updated;
  String	author_updating;
  String  source;
  String	active;

  String		pos;
  Vector		comment;
  Vector		definition;
  Vector		ncri;	
  Morphology	morph;
  Syntax		syntax;
  SemanticVerb	semanticVerb;
  SQLConnection con;
	
  /** constructor 
   **/
  public Concept(SQLConnection con) {
    this.con = con;
    term_id = "";
    concept_id = "";
    concept_symbol = "";
    cte_entry = "";
    ambiguity = "";
    capitalization = "";
    irr_capitalization = "";
    date_created = "";
    author_creating = "";
    date_updated = "";
    author_updating = "";
    source = "";
    active = "T";
		
    pos	= "";
    comment		= null;
    definition	= null;
    ncri		= null;
    semanticVerb= null;
    morph		= null;
    syntax		= null;		
  }	
	
  public Concept(SQLConnection con, String pos) {
    this(con);	
    this.pos = pos;
  }	

  // getters & setters
  public String getTermID() {
    return term_id;
  }	
  public void setTermID(String term_id) {
    if ( term_id == null) 
      term_id = "";
    this.term_id = term_id;
  }	
  public String getConceptID() {
    return concept_id;
  }	
  public void setConceptID(String concept_id) {
    if ( concept_id == null) 
      concept_id = "";
    this.concept_id = concept_id;
  }		
  public String getConceptSymbol() {
    return concept_symbol;
  }	
  public void setConceptSymbol(String concept_symbol) {
    if ( concept_symbol == null) 
      concept_symbol = "";
    this.concept_symbol = concept_symbol;
  }
  public void setCteEntry (String cte_entry) {
    if ( cte_entry == null) 
      cte_entry = "";
    this.cte_entry = cte_entry;
  }
  public String getCteEntry () {
    return cte_entry;
  }
  public void setAmbiguity (String ambiguity) {
    if ( ambiguity == null) 
      ambiguity = "";
    this.ambiguity = ambiguity;
  }
  public String getAmbiguity () {
    return ambiguity;
  }
  public void setCapitalization (String capitalization) {
    if ( capitalization == null) 
      capitalization = "";
    this.capitalization = capitalization;
  }
  public String getCapitalization () {
    return capitalization;
  }
  public void setIrrCapitalization (String irr_capitalization) {
    if ( irr_capitalization == null) 
      irr_capitalization = "";
    this.irr_capitalization = irr_capitalization;
  }
  public String getIrrCapitalization () {
    return irr_capitalization;
  }
  public void setDateCreated (String date) {
    if ( date_created == null) 
      date_created = "";
    this.date_created = date;
  }
  public String getDateCreated () {
    return date_created;
  }

  public void setAuthorCreating (String author) {
    if ( author_creating == null) 
      author_creating = "";
    this.author_creating = author;
  }	
  public String getAuthorCreating () {
    return author_creating;
  }		
  public void setDateUpdated (String date) {
    if ( date_updated == null) 
      date_updated = "";
    this.date_updated = date;
  }
  public String getDateUpdated () {
    return date_updated;
  }	
  public void setAuthorUpdating (String author) {
    if ( author_updating == null) 
      author_updating = "";
    this.author_updating = author;
  }		
  public String getAuthorUpdating () {
    return author_updating;
  }	
  public void setSource (String source) {
    if ( source == null) 
      source = "";
    this.source = source;
  }	
  public String getSource () {
    return source;
  }	
  public void setActive (String active) {
    if ( active == null) 
      active = "";
    this.active = active;
  }	
  public void setPos(String p) {
    pos = p;
  }	
  public String getPos() {
    return pos;
  }	
	
  /** get comments
   * @return Vector containing all comments of this concept
   **/
  public Vector getComments() {
    if ( comment == null )
      comment = Comment.fetchComments(con, concept_id);	
    return comment;
  }
	
  /** get NCRI
   * @return Vector containing all NCRIs of this concept
   **/
  public Vector getNCRI() {
    if ( ncri == null )		
      ncri = NCRI.fetchNCRI(con, concept_id);	
    return ncri;
  }	

  /** get definitions
   * @return Vector containing all definitions of this concept
   **/
  public Vector getDefinitions() {
    if ( definition == null )				
      definition = Definition.fetchDefinitions(con, concept_id);
    return definition;	
  }

  /** get definition
   * @param index integer representing the specific index of definition vector
   * @return Definition located in definition vector 
   **/
  public Definition getDefinition(int index) {
    if ( index >=0 && index < definition.size() )
      return (Definition)definition.elementAt(index);	
    else
      return null;
  }	
  /** get semantic
   * @return SemanticVerb of this concept
   **/
  public SemanticVerb getSemanticVerb() {
    if ( semanticVerb == null )	
      semanticVerb = SemanticVerb.fetchSemanticVerb(con, concept_id);	
    return semanticVerb;
  }	

  /** get Morpholgy
   * @return Morpholgy of this concept
   **/
  public Morphology getMorphology() {
    if ( morph == null  )	
      morph = Morphology.fetchMorph(con, pos, concept_id);	
    return morph;
  }	

  /** get Syntatic information
   * @return Syntax of this concept
   **/
  public Syntax getSyntax() {
    if ( syntax == null )
      syntax = Syntax.fetchSyntax(con, pos, concept_id);	
    return syntax;
  }		
	
  public void changePos(String p) {
    pos = p;
    morph = null;
    syntax = null;
    syntax = null;			
    //		System.out.println("** pos: " + pos);
  }
	
  /** Get all concepts which have the term and pos
   * @param pos a string representing part-of-speech
   * @param term_id a string representing term_id
   * @return Vector all concepts fetched from the database.
   **/		
  public static Vector fetchConcepts(Term term) {
    Vector conceptVector = new Vector();
		
    String sql = "SELECT * FROM LMT_CONCEPTS WHERE ";
    sql += " TERM_ID = '" + term.getTermID() + "'";
    sql += " ORDER BY CONCEPT_ID";

    Debug.debug("-- fetchconcept: " + sql);		

    SQLConnection con = term.getConn();
		
    try {
      SQLConnection.Result r = con.query(sql);
      while (r!=null &&r.hasData()){
	Concept concept = new Concept(con, term.getPos());

	concept.setConceptID(r.rs.getString(1));				 
	concept.setTermID(r.rs.getString(2));				 
	concept.setConceptSymbol(r.rs.getString(3));				 
	concept.setCteEntry(r.rs.getString(4));
	concept.setCapitalization(changeCapForUI(r.rs.getString(5)));	
	concept.setIrrCapitalization(r.rs.getString(6));	
	concept.setAmbiguity(r.rs.getString(7));
	concept.setDateCreated(r.rs.getString(8));	
	concept.setAuthorCreating(r.rs.getString(9));	
	concept.setDateUpdated(r.rs.getString(10));	
	concept.setAuthorUpdating(r.rs.getString(11));	
	concept.setSource(r.rs.getString(12));	
	concept.setActive(r.rs.getString(13));	
					
	concept.getComments();
	concept.getDefinitions();
	concept.getSyntax();
	concept.getMorphology();
	concept.getNCRI();
	concept.getSemanticVerb();
	conceptVector.addElement(concept);
      }
      if (r!=null) r.close();
    } catch (SQLException E) {
      Debug.debug("SQLException: " + E.getMessage());
    }	

    return conceptVector;
  }
	
  /** Get all concepts which have the specific concept_symbol
   * @param concept_symbol a string representing concept. It could include wildcard.
   * @return Vector all concepts fetched from the database.
   **/	
  public static Vector fetchConcepts(SQLConnection con, String concept_symbol) {
    Vector conceptVector = new Vector();
		
    String sql = "SELECT CONCEPT_SYMBOL, TERM_STRING, POS, LMT_TERMS.TERM_ID";
    sql += " FROM LMT_CONCEPTS, LMT_TERMS";
    sql += " WHERE LMT_CONCEPTS.TERM_ID = LMT_TERMS.TERM_ID AND ";

    // replace single quote 
    concept_symbol = Util.replaceSingleQuote(concept_symbol);
		
    // search string
    if (concept_symbol.indexOf("%%") >= 0 ) {		//  LIKE '%\%%' escape '\'
      sql += " CONCEPT_SYMBOL LIKE \'%\\%%\' escape \'\\\'";
    } else if (concept_symbol.indexOf("%") >= 0 || concept_symbol.indexOf("_") >= 0 ) {
      sql += " CONCEPT_SYMBOL LIKE '" + concept_symbol + "'";
    } else {
      sql += " CONCEPT_SYMBOL = '" + concept_symbol + "'";
    }
		
    sql += " ORDER BY CONCEPT_SYMBOL";
		
    Debug.debug("-- fetchconcept: " + sql);		
		
    try {
      SQLConnection.Result r = con.query(sql);
      while (r!=null &&r.hasData()){
	Vector concept = new Vector();
	concept.addElement(r.rs.getString(1));				 
	concept.addElement(r.rs.getString(2));
	concept.addElement(Term.changePosForUI(r.rs.getString(3)));
	concept.addElement(r.rs.getString(4));
	conceptVector.addElement(concept);
      }
      if (r!=null) r.close();
    } catch (SQLException E) {
      Debug.debug("SQLException: " + E.getMessage());
    }	

    //Debug.debug("   size of result: " + conceptVector.size());
    return conceptVector;
  }

  /** change POS to match the screen contents with the database contents	
   * @param	string to represent captilization info of the screen
   */
  public static String changeCapForDB(String cap) {
    String newCap = "";
		
    if (cap != null) {
      if (cap.equals("All")) 
	newCap = "A";
      else if (cap.equals("Each")) 
	newCap = "E";
      else if (cap.equals("First")) 
	newCap = "F";			
      else if (cap.equals("Any")) 
	newCap = "N";
      else if (cap.equals("Irr")) 
	newCap = "I";				
    }	
    return newCap;
  }

  /** change POS to match the screen contents with the database contents	
   * @param	string to represent captilization info of the database
   */
  public static String changeCapForUI(String cap) {
    String newCap = "";
		
    if (cap != null) {
      if (cap.equals("A")) 
	newCap = "All";
      else if (cap.equals("E")) 
	newCap = "Each";
      else if (cap.equals("F")) 
	newCap = "First";			
      else if (cap.equals("N")) 
	newCap = "Any";
      else if (cap.equals("I")) 
	newCap = "Irr";
    }	
    return newCap;
  }
	
  /** insert the new data into the table.
   * @return integer representing the result of operation
   **/			
  public int insert() {

    // check duplication
    if (isDuplicate())
      return Constants.DUPLICATION;
				
    concept_id = con.getNewID("CONCEPT_ID");						
    String sql = makeInsertQuery();
    Debug.debug("-- Concept inserted : " + sql);		
		
    return con.insert(sql);
  }
	
  /** delete this data from the table.
   * @return integer representing the result of operation
   **/		
  public int delete() {
    // call stored procedure in the database
    boolean ret = con.callProcedure("DeleteConcept", concept_id);
    Debug.debug("-- delete concept result: " + ret);
		
    if (ret) 
      return Constants.SUCCESS;
    else
      return Constants.FAIL;
  }
	
  /** update all concepts 
   * @return integer representing the result of operation
   **/		
  public static int update(SQLConnection con, Vector conVector) {
    // make query
    Vector queryVector = new Vector();
    makeQuery(queryVector, conVector);
		
    // run the update transaction
    return con.update(queryVector);
  }
	
  /** update all concepts 
   * @return integer representing the result of operation
   **/		
  public int update() {
    // make query
    String query = "";
    query = "UPDATE LMT_CONCEPTS SET";
    query += " concept_symbol = '" + Util.replaceSingleQuote(getConceptSymbol()) + "',";
    query += " cte_entry = '" + getCteEntry() + "',";
    query += " capitalization = '" + changeCapForDB(getCapitalization()) + "',";
    query += " ambiguity = '" + getAmbiguity() + "',";
    query += " irr_capitalization = '" + Util.replaceSingleQuote(getIrrCapitalization()) + "',";
    query += " date_updated = '" + getDateUpdated() + "',";
    query += " author_updating = '" + getAuthorUpdating() + "',";		
    query += " source = '" + Util.replaceSingleQuote(getSource()) + "'";		
    query += " WHERE concept_id = '" + getConceptID() + "'";
			
    return con.update(query);
  }	

  /** check whether the data already exists in the database
   * @return boolean representing the result of operation
   **/		
  public boolean isDuplicate() {
		
    String sql = "SELECT * FROM LMT_CONCEPTS WHERE ";
    sql += " concept_symbol = '" + Util.replaceSingleQuote(concept_symbol) + "'";
    sql += " AND term_id = '" + term_id + "'";

    //Debug.debug("-- isDuplicated concept string: " + sql);	
		
    return con.isExistent(sql);
  }

  /** check whether the term has only one concept
   * @return boolean representing the result of operation
   **/		
  public boolean isOneConcept() {
		
    String sql = "SELECT COUNT(*) AS cnt FROM LMT_CONCEPTS WHERE TERM_ID IN ";
    sql += " (SELECT TERM_ID FROM LMT_CONCEPTS WHERE CONCEPT_ID = '" + concept_id + "')";
		
    Debug.debug("-- isOneConcept : " + sql);	

    try {
      int ret = 0;
      SQLConnection.Result r = con.query(sql);
      if (r!=null &&r.hasData())
	ret = r.rs.getInt("cnt");
      if (r!=null) r.close();
      return (ret == 1);
    } catch (SQLException E) {
      Debug.debug("SQLException: " + E.getMessage());
      return false;
    }	
  }

  /** check whether the concept exists or not
   * @return boolean representing the result of operation
   **/		
  public boolean isExistent() {
		
    String sql = "SELECT * FROM LMT_CONCEPTS WHERE ";
    sql += " concept_id = '" + concept_id + "'";
		
    return con.isExistent(sql);
  }

  /** make the query using input vector
   * @param comVector	vector which has objects of this class
   * @return String[] array including SQL
   **/	
  public static void makeQuery(Vector queryVector, Vector conVector) {
    if (conVector == null)
      return;
		
    String query;
    for ( int i=0; i<conVector.size(); i++) {
      Concept c = (Concept)conVector.elementAt(i);
      query = "UPDATE LMT_CONCEPTS SET";
      query += " concept_symbol = '" + Util.replaceSingleQuote(c.getConceptSymbol()) + "',";
      query += " cte_entry = '" + c.getCteEntry() + "',";
      query += " capitalization = '" + changeCapForDB(c.getCapitalization()) + "',";
      query += " ambiguity = '" + c.getAmbiguity() + "',";
      query += " irr_capitalization = '" + Util.replaceSingleQuote(c.getIrrCapitalization()) + "',";
      query += " date_updated = '" + c.getDateUpdated() + "',";
      query += " author_updating = '" + c.getAuthorUpdating() + "',";	
      query += " source = '" + Util.replaceSingleQuote(c.getSource()) + "'";		
      query += " WHERE concept_id = '" + c.getConceptID() + "'";
      //Debug.debug("-- update Concept: " + query);
      queryVector.addElement(query);
    }
  }
	
  /** make the query using input vector
   * @param comVector	vector which has objects of this class
   * @return String[] array including SQL
   **/	
  public String makeInsertQuery() {
    String sql = "INSERT INTO LMT_CONCEPTS VALUES (";
    sql += "'" + concept_id + "',";
    sql += "'" + term_id + "',";
    sql += "'" + Util.replaceSingleQuote(concept_symbol) + "',";
    sql += "'" + cte_entry + "',";
    sql += "'" + changeCapForDB(capitalization) + "',";
    sql += "'" + Util.replaceSingleQuote(irr_capitalization)+ "',";
    sql += "'" + ambiguity + "',";
    sql += "'" + date_created + "',";
    sql += "'" + author_creating + "',";
    sql += "'" + date_updated + "',";
    sql += "'" + author_updating + "',";
    sql += "'" + Util.replaceSingleQuote(source) + "',";		
    sql += "'" + active + "')";
    return sql;
  }	
	
  public static String generateConceptSymbol(Term term) {
		
    String concept = "";
    String termPos = term.getPos();
    String termString = term.getTermString().replace(' ', '-');
		
    //Debug.debug("GenerateConcept: new concept=" + concept + " term=" + termString);
		
    if (termPos.equals("VERB"))
      concept= "*A-" + termString;
    else if ( termPos.equals("ADVERB") )
      concept= "*M-" + termString;
    else if ( termPos.equals("NOUN") )
      concept= "*O-" + termString;
    else if ( termPos.equals("ADJ") )
      concept= "*P-" + termString;
    else if (termPos.equals("PREP"))
      concept= "*K-" + termString;
    else if (termPos.equals("UNIT"))
      concept= "*U-" + termString;
    else if (termPos.equals("MOD") || 
	     termPos.equals("AUX") ||  
	     termPos.equals("DET") || 
	     termPos.equals("INF") || 
	     termPos.equals("SP"))
      concept= "*SP-" + termString;
    else if (termPos.equals("CARD") ||  
	     termPos.equals("CONJ") || 
	     termPos.equals("INT") || 
	     termPos.equals("PRON") || 
	     termPos.equals("PROP") || 
	     termPos.equals("QUANT") || 
	     termPos.equals("SYM") || 
	     termPos.equals("ORD"))
      concept= "*" + termPos + "-" + termString;

    // add the number of concepts to the string
    /*		int size = term.getConcepts().size();
      if ( concept.length() > 0 && size > 0 ) {
      concept += "-" + (size+1);	
      }
    */		
    //Debug.debug("GenerateConcept: new concept=" + concept + " term=" + termString);
    return concept.toUpperCase();
  } 
	
}
