import java.sql.*;
import javax.sql.*;
import java.io.*;
import java.net.*;
import java.util.Vector;
import java.util.HashMap;
import java.math.BigDecimal;

/**
 * DBConnect's class 
 * It functions as the intermediate between the database and the calling
 * program. It uses Encap.java as the supporting class. Encap's class
 * hold the name/value pair that is needed to hold data from database or
 * to fill the database. DBConnect uses java.net package to connect
 * to the database that could be located in other machine/server.
 * DBConnect uses mysql-connector/J as the liason between it and
 * the database. It is marked by the field in the driver.
 * In this case the name of the package, for the mysql-connector/J
 * that is JDBC-compliance, is com.mysql.jdbc.Driver
 * You must put the mysql-connector/J in the classpath or 
 * copy it to JRE's ext folder.
 *
 * All of the Insert and Update's operation is transaction-safe.
 * In case of any failure, everything in the database is rollback.
 * 
 * example of usage: 
 *
 * DBConnect db = new DBConnect();
 * Encap e = new Encap("tableName");
 * e.setNameVal("field_name","field_value");
 *
 * Encap e2 = new Encap("tableName2");
 * e2.setNameVal("field_name2","field_value2");
 *
 * Encap e3 = new Encap("tableName3");
 * e3.setNameVal("field_name3","field_value3");
 *
 * // to illustriate the InsertMulti's operation
 * Vector v = new Vector(3); 
 * v.add(e.clone());
 * v.add(e2.clone());
 * v.add(e3.clone()); 
 *
 * // to illustriate Update's operation on tableName
 * Encap e4 = new Encap("tableName"); 
 * e4.setNameVal("field_name","new_field_value");
 * e4.setCondition("WHERE field_name=\"field_value\";");
 * 
 * Encap e5 = new Encap("tableName3");
 * e5.setCondition("WHERE field_name3=\"field_value3\";");
 *
 * Vector resultQuery = null;
 *
 * // to illustriate Query's operation on tableName3
 * Encap e6 = new Encap("tableName3");
 * e6.setCondition("WHERE field_name3=\"field_value3\";");
 *
 * try
 * {
 *  if(!db.makeConnection("database_name"))
 *   throw new SQLException("failure to connect to database");
 *
 *  db.InsertData(e); // insert into a single table
 *  db.InsertMulti(v); // insert into more than one table
 *
 *  // Update's operation
 *  db.UpdateData(e4); // for single table
 *  // update's operation for multiple table is the same like insert multi
 *
 *  
 *  // Query's operation
 *  Encap singleQuery = db.QuerySingle(e6); // query single result by encap
 *
 *  // query single result by specifiying directly the name of the table
 *  Encap single = 
 *   db.QuerySingle("tableName3","*","WHERE field_name3=\"field_value3\";");
 *
 *  // query multi result by specifiying directly the name of the table
 *  Vector manyResult = db.QueryMulti("tableName3","*",
 *  "WHERE field_name3=\"field_value3\";");
 *  // same with query multi with Encap
 *
 *  // view result of query
 *  db.viewEncap(singleQuery);
 *  db.viewEncap(single);
 *  for(int i=0;i<manyResult.size();i++)
 *   db.viewEncap(((Encap)manyResult.get(i)).clone());
 *
 *  // delete single entity by specifiying directly the name of the table
 *  db.DeleteSingle("tableName2","WHERE field_name2=\"field_value2\";");
 *
 *  // delete single entity by Encap
 *  db.DeleteSingle(e5);
 *
 * }
 * catch(SQLException sqle)
 * {
 *  sqle.printStackTrace(System.out); // print the cause of failure to screen
 * }
 * finally
 * {
 *  db.close();
 *  e.clear();
 *  e2.clear();
 *  v.removeAllElements();
 * }
 *
 * @author Edison Chindrawaly
 * @version 1.1 [last modified 6/2/2004]
 */
public class DBConnect implements DatabaseConnect
{
 private Connection connect;
 private boolean initConnection = false;
 private final String defdriver = "com.mysql.jdbc.Driver";
 private final String defuser   = "edisonch";
 private final String defurl    = "jdbc:mysql://alien:3306/";
 private final String defpwd    = "gblj21mysql03";
 private StringBuffer driver = new StringBuffer();
 private StringBuffer user = new StringBuffer();
 private StringBuffer url = new StringBuffer();
 private StringBuffer pwd = new StringBuffer();

/**
 * DBConnect's default constructor. It uses all the default parameters
 */
 public DBConnect()
 {
  driver.append(defdriver);
  user.append(defuser);
  url.append(defurl);
  pwd.append(defpwd);
 }

/**
 * DBConnect's parameters constructor. It sets all the driver,user,
 * url and pwd needed to connect to the Internet
 * @param String drv - the name of the driver used to connect to database
 *        String url2- the url of the database server to connect
 *        String usr - the username of the database
 *        String pass- the password of the user
 * @return none
 */
 public DBConnect(String drv,String url2,String usr,String pass)
 {
  resetInfo(drv,url2,usr,pass);
 }

/**
 * close's method is to close the connection to the database. 
 * it first checks whether the initialization of the connection was 
 * successful at first. if it fails, it automatically returns.
 * Else it proceed to close the connection 
 * @param none
 * @return none
 */
 public void close()
 {
  if(!initConnection)
   return;
  try
  {
   driver.delete(0,driver.length());
   user.delete(0,user.length());
   url.delete(0,url.length());
   pwd.delete(0,pwd.length());
   connect.close();
  }
  catch(Exception ex)
  {
   System.out.println("DBConnect failed to close : "+ex.getMessage());
  }
 }

/**
 * resetInfo's method is to reset all the needed field and set them
 * to the user's options.
 * @param String drv - contains the driver of the connector
 *        String url2 - contains the url of the server
 *        String usr - contains the user of the database
 *        String pass - contains the password of the database
 * @return none
 */
 public void resetInfo(String drv,String url2,String usr,String pass)
 {
  if(drv!=null)
	{
	 if(drv.length()>0) drv.delete(0,drv.length());
   driver.append(drv);
	}
  if(url2!=null)
	{
	 if(url.length()>0) url.delete(0,url.length());
   url.append(url2);
	}
  if(usr!=null)
	{
	 if(user.length()>0) user.delete(0,user.length());
   user.append(usr);
	}
  if(pass!=null)
	{
	 if(pwd.length()>0) pwd.delete(0,pwd.length());
   pwd.append(pass);
	}
 }

/**
 * countNames' method is to count the field names exist in a single encap.
 * It collects all the field names and put them into vector to be return.
 * @param Encap en - contains the data needed
 * @return Vector names - contains the field name
 */
 public Vector countNames(Encap en)
 {
  int size = en.getSize();
  Vector names = new Vector();
  for(int i=0;i<size;i++)
   if(!names.contains(en.getName(i)))
    names.add(en.getName(i));
  return names;
 }

/**
 * makeConnection's method is make connection to the database based on
 * the given database name. It uses all the parameters needed that is
 * previously determine by the default values or user determined values.
 * @param String dbname - contains the database name
 * @return boolean true if it can connects to database named by user else false
 */
 public boolean makeConnection(String dbname)
 {
  try
  {
   Class.forName(driver.toString()).newInstance();
   url.append(dbname);
   connect = DriverManager.getConnection(url.toString(),
		 user.toString(),pwd.toString());
  }
  catch(SQLException ex)
  {
   System.out.println("Error Connecting to database : "+ex.getMessage());
   initConnection = false;
   return false;
  }
  catch(ClassNotFoundException ce)
  {
   System.out.println("JDBC driver class not found : "+ce.getMessage());
   initConnection = false;
   return false;
  }
  catch(Exception e)
  {
   System.out.println("Exception : "+e.getMessage());
   initConnection = false;
   return false;
  }
  initConnection = true;
  return true;
 }

/**
 * InsertMulti's method is to insert multiple encap's data into database.
 * It supports transaction-safe operation. if if any exception or error
 * happens in during the transaction, the database will automatically
 * rollback all the previous command and inserted data
 * @param Vector v - contains more than Encap that need to be inserted.
 * @return none
 */
 public void InsertMulti(Vector v) throws SQLException
 {
  if(!initConnection)
   throw new SQLException("No initial connection to database establish");
	if(v == null)
	 throw new SQLException("Received null Vector");
  int size = v.size();
  Statement stmt = null;
  try
  {
   connect.setAutoCommit(false);
   stmt = connect.createStatement();
   for(int i=0;i<size;i++)
    workInsert(stmt,(Encap)v.elementAt(i));
   connect.commit();
  }
  catch(SQLException sqle)
  {
   connect.rollback();
   throw sqle;
  }
  finally
  {
   stmt.close();
  }
  return;
 } // End of InsertMulti

/**
 * InsertData's method is to insert data one by one (Encap by Encap) into the
 * database. The order of the column names and values is important into
 * filling the database from Encap. Also Encap packages have to follow their
 * biggest package in the their own container (Vector). If the biggest is
 * 3 tuples, then every package has to be 3 tuples long.
 * @param Encap en
 * @return none
 */
 public void InsertData(Encap en) throws SQLException
 {
  if(!initConnection)
   throw new SQLException("No initial connection to database establish");
  Statement stmt = null;
  try
  {
   connect.setAutoCommit(false);
   stmt = connect.createStatement();
   workInsert(stmt,en);
   connect.commit();
  }
  catch(SQLException sqle)
  {
   connect.rollback();
   throw sqle;
  }
  finally
  {
   stmt.close();
  }
  return;
 }

/**
 * workInsert's method is to string that makes up the INSERT syntax
 * given the Encap and the Vectors of names (for the column name field)
 * @param Encap en - contains the needed table name
 *        Vector names - contains all the column names field of Encap
 * @return INSERT syntax of the given Encap
 */
 private void workInsert(Statement stmt,Encap en) throws SQLException
 {
  if(en == null)
   throw new SQLException("Received null Encapsulation");
  if(en.getTable() == null)
   throw new SQLException("Received null tableName");
  int size = en.getSize();
  StringBuffer str = new StringBuffer();
  StringBuffer str2= new StringBuffer();
  str2.append("INSERT INTO "+en.getTable()+" (");
  for(int i=0;i<size;i++)
  {
   str2.append(en.getName(i));
   switch(en.getType(i))
   {
    case Encap.INT : str.append(en.getIntValue(i)); break;
    case Encap.STR : str.append("\""+en.getStringValue(i)+"\""); break;
    case Encap.FLT : str.append(en.getFloatValue(i)); break;
    case Encap.DBL : str.append(en.getDoubleValue(i)); break;
    case Encap.TIM :
    case Encap.DAT :
    case Encap.VAR : str.append(en.getStringValue(i)); break;
    case Encap.LNG : str.append(en.getLongValue(i)); break;
    case Encap.DEC : str.append(en.getValue(i)); break;
   }
   if(i!=size-1)
   {
    str.append(",");
    str2.append(",");
   }
   else
    str2.append(") ");
  }
  str2.append(" VALUES ("+str.toString()+"); ");
  stmt.executeUpdate(str2.toString());
  str.delete(0,str.length());
  if(en.getVariable()!=null)
  {
   str.append(en.getVariable());
   stmt.executeUpdate(str.toString());
  }
  str.delete(0,str.length());
  return;
 }

/**
 * work's method is to do all the work that needed to update
 * the fields of the appointed database. It is transaction-safe from
 * the calling method.
 * @param Statement stmt - contains the statement for the database
 *        Encap en - contains the data that is going to update
 * @return none
 */
 private void work(Statement stmt,Encap en) throws SQLException
 {
  int size = en.getSize();
  StringBuffer str = new StringBuffer("UPDATE "+en.getTable()+" SET ");
  for(int i=0;i<size;i++)
  {
   switch(en.getType(i))
   {
    case Encap.INT: str.append(en.getName(i)+"="+en.getIntValue(i)); break;
    case Encap.STR: str.append(en.getName(i)+"=\""+en.getStringValue(i)+"\"");
        	    break;
    case Encap.FLT: str.append(en.getName(i)+"="+en.getFloatValue(i)); break;
    case Encap.DBL: str.append(en.getName(i)+"="+en.getDoubleValue(i)); break;
    case Encap.TIM:
    case Encap.DAT: 
    case Encap.VAR: str.append(en.getName(i)+"="+en.getStringValue(i)); break;
    case Encap.LNG: str.append(en.getName(i)+"="+en.getLongValue(i)); break;
    case Encap.DEC: str.append(en.getName(i)+"="+en.getValue(i)); break;
   }
   if(i!=size-1) str.append(",");
  }
  if(en.getCondition()!=null)
   str.append(" "+en.getCondition());
  else
   str.append(";");
	System.out.println("work : "+str.toString());
  stmt.executeUpdate(str.toString());
 }

/**
 * UpdateMulti's method is to update multiple table name in a single database.
 * It calls work's method to do all the real work and when it is finish,
 * it will commit the data else it will rollback the operation.
 * @param Vector v - contains many encaps [more than 1 encap]
 * @return none
 */
 public void UpdateMulti(Vector v) throws SQLException
 {
  if(!initConnection)
    throw new SQLException("No initial connection to database establish");
  if(v == null) throw new SQLException("Passed in value is null");
  int size = v.size();
  Encap en = null;
  Statement stmt = null;
  try
  {
   connect.setAutoCommit(false);
   stmt = connect.createStatement();
   for(int i=0;i<size;i++)
   {
    en = (Encap)v.elementAt(i);
    work(stmt,en);
    en.clear();
   }
   connect.commit();
  }
  catch(SQLException sqle)
  {
   connect.rollback();
   throw sqle;
  }
  finally
  {
   stmt.close();
  }
 }

/**
 * UpdateData's method is to update single data. it uses work's method
 * to do all the real work. it is transaction-safe because it will
 * commit the operation when it is successfully update else it will
 * rollback the operation.
 * @param Encap en - contains the new data
 * @return none
 */
 public void UpdateData(Encap en) throws SQLException
 {
  if(!initConnection)
    throw new SQLException("No initial connection to database establish");
  if(en == null) throw new SQLException("Passed in value is null");
  Statement stmt = null; 
  try
  {
   connect.setAutoCommit(false);
   stmt = connect.createStatement();
   work(stmt,en);
   connect.commit();
  }
  catch(SQLException sqle)
  {
   connect.rollback();
   throw sqle;
  }
  finally
  {
   stmt.close();
  }
 }


/**
 * QueryMulti's method is query database that will result many results.
 * It will hold all the results in the vector. Each result will be encapsulated
 * into the Encap's class. That operation is done by workQuery's method.
 * @param Encap en - contains the query command.
 * @return Vector v - contains the result of the query.
 */
 public Vector QueryMulti(Encap en) throws SQLException
 {
  if(!initConnection)
    throw new SQLException("No initial connection to database establish");
  if(en == null) throw new SQLException("Passed in value is null");
  Vector names = countNames(en);
  ResultSet result = null;
  Statement stmt = null;
  Vector v = null;
  try
  {
   stmt = connect.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                  ResultSet.CONCUR_UPDATABLE);
   result = stmt.executeQuery(formSelect(names,en));
   if(result.next())
     v = workQuery(result);
  }
  catch(SQLException sqle)
  {
   System.out.println("SQLException at QueryMulti: "+sqle.getMessage());
   throw sqle;
  }
  finally
  {
   result.close();
   stmt.close();
  }
  return v;
 }

/**
 * workQuery's method is to work horse of the Query's operation. 
 * It puts each result into its own Encapsulation. 
 * @param ResultSet result - containst the result of the query
 * @return Vector v - holds the encaps of result.
 */
 private Vector workQuery(ResultSet result) throws SQLException
 {
  Encap en = new Encap();
  Vector v = new Vector();
  ResultSetMetaData rsmd = result.getMetaData();
  int columnSize = rsmd.getColumnCount();
  do
  {
   en.setTable(rsmd.getTableName(1));
   for(int i=0;i<columnSize;i++)
   {
    switch(rsmd.getColumnType(i+1))
    {
     case java.sql.Types.CHAR    :
     case java.sql.Types.VARCHAR :
      en.setNameVal(rsmd.getColumnName(i+1),result.getString(i+1));
      break;
     case java.sql.Types.SMALLINT:
     case java.sql.Types.TINYINT :
     case java.sql.Types.INTEGER : 
      en.setNameVal(rsmd.getColumnName(i+1),result.getInt(i+1));
      break;
     case java.sql.Types.FLOAT   :
      en.setNameVal(rsmd.getColumnName(i+1),result.getFloat(i+1));
      break;
     case java.sql.Types.BIGINT  :
      en.setNameVal(rsmd.getColumnName(i+1),result.getLong(i+1));
      break;
     case java.sql.Types.DECIMAL :
      en.setNameVal(rsmd.getColumnName(i+1),result.getBigDecimal(i+1));
      break;
     case java.sql.Types.DOUBLE  :
      en.setNameVal(rsmd.getColumnName(i+1),result.getDouble(i+1));
      break;
     case java.sql.Types.DATE    :
      en.setName(rsmd.getColumnName(i+1));
      if(result.getDate(i+1) == null)
       en.setValue("0000-00-00");
      else 
       en.setValue(result.getDate(i+1).toString());
      break;
     case java.sql.Types.TIME    :
      en.setName(rsmd.getColumnName(i+1));
      if(result.getTime(i+1) == null)
       en.setValue("00:00:00");
      else
       en.setValue(result.getTime(i+1).toString());
     break;
     default : 
      System.out.println("default : "+rsmd.getColumnType(i+1));
      throw new SQLException("Default error in switch statement");
    } // end of switch
   } // end of for-loop
   v.add(en.clone());
   en.clear();
  } while(result.next()); // end of while-loop
  return v;
 }

/**
 * formSelect's method is to form the syntax for Query database command.
 * @param Vector names - contains the field names of the database
 *        Encap en - contains the data
 * @return String syntax of Query database command.
 */
 private String formSelect(Vector names,Encap en) throws SQLException
 {
  if((names == null)||(names.size()==0))
   return null;
  StringBuffer str = new StringBuffer();
  str.append("SELECT ");
  int psize = names.size();
  if(psize>1)
  {
   for(int i=0;i<psize;i++)
   {
    str.append((String)(names.elementAt(i)));
    if(i<psize-1)
     str.append(",");
    else
     str.append(" ");
   }
  }
  else
   str.append((String)names.firstElement()+" ");
  str.append("FROM "+en.getTable());
  if(en.getCondition()!=null)
    str.append(" "+en.getCondition());
  return str.toString();
 }

/**
 * QuerySingle's method is to query database for a single result.
 * @param Encap en - contains the query
 * @return Encap - contains the result
 */
 public Encap QuerySingle(Encap en) throws SQLException
 {
  if(!initConnection)
    throw new SQLException("No initial connection to database establish");
  if(en == null) throw new SQLException("Passed in value is null");
  Vector names = countNames(en);
  Encap en2 = null;
  ResultSet result = null;
  Statement stmt = null;
  ResultSetMetaData rsmd = null;
  try
  {
   connect.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
   stmt = connect.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
     				  ResultSet.CONCUR_UPDATABLE);
   result = stmt.executeQuery(formSelect(names,en));
   if(result.next())
   {
    rsmd = result.getMetaData();
    int columnSize = rsmd.getColumnCount();
    en2 = new Encap();
    do
    {
     en2.setTable(rsmd.getTableName(1));
     for(int i=0;i<columnSize;i++)
     {
      switch(rsmd.getColumnType(i+1))
      {
       case java.sql.Types.CHAR    :
       case java.sql.Types.VARCHAR :
        en2.setNameVal(rsmd.getColumnName(i+1),result.getString(i+1));
        break;
       case java.sql.Types.SMALLINT:
       case java.sql.Types.TINYINT :
       case java.sql.Types.INTEGER :
        en2.setNameVal(rsmd.getColumnName(i+1),result.getInt(i+1));
        break;
       case java.sql.Types.BIGINT  :
	      en2.setNameVal(rsmd.getColumnName(i+1),result.getLong(i+1));
	      break;
       case java.sql.Types.FLOAT   :
        en2.setNameVal(rsmd.getColumnName(i+1),result.getFloat(i+1));
        break;
       case java.sql.Types.DECIMAL :
	      en2.setNameVal(rsmd.getColumnName(i+1),result.getBigDecimal(i+1));
	      break;
       case java.sql.Types.DOUBLE  :
        en2.setNameVal(rsmd.getColumnName(i+1),result.getDouble(i+1));
        break;
       case java.sql.Types.TIME    :
	      if(result.getTime(i+1) == null)
         en2.setNameVal(rsmd.getColumnName(i+1),"00:00:00");
	      else 
         en2.setNameVal(rsmd.getColumnName(i+1),
	      result.getTime(i+1).toString());
        break;
       case java.sql.Types.DATE    :
	      if(result.getDate(i+1) == null)
         en2.setNameVal(rsmd.getColumnName(i+1),"0000-00-00");
	      else 
         en2.setNameVal(rsmd.getColumnName(i+1),
	      result.getDate(i+1).toString());
        break;
       default : 
      	throw new SQLException("Default error in switch statement");
      } // end of switch
     } // end of for-loop
    } while(result.next());
   } // end of if
  }
  catch(SQLException sqle)
  {
   System.out.println("SQLException at QuerySingle: "+sqle.getMessage());
   throw sqle;
  }
  finally
  {
   if(result!=null) result.close();
   if(stmt!=null) stmt.close();
  }
  return en2;
 }

/**
 * QueryMulti's method is to query database for multiple results using
 * the direct table_name and column_name and if exist the condition.
 * if you would like to get all the column name use wildcard's character: '*'.
 * The method takes all the user direct query and pack them into Encap
 * and call the QueryMulti with parameter Encap.
 *
 * Example usage: 
 * DBConnect db = new DBConnect();
 * // to get all the column names:
 * Vector result = db.QueryMulti("table_name1","*","WHERE cond=1;");
 * // to get the specific column names:
 * Vector result = db.QueryMulti("table_name1","col_name","WHERE cond=1;");
 *
 * @param String table - contains table_name
 *        String col - contains column_name
 *        String condition - contains condition if none, pass null value.
 * @return Vector result
 */
 public Vector QueryMulti(String table,String col,String condition)
  throws SQLException
 {
  if(!initConnection)
    throw new SQLException("No initial connection to database establish");
  Encap en = new Encap(table);
  int p = col.indexOf(',');
  if(p<0) en.setName(col);
  else
   en = phraseNames(p,col,en);
  if(condition!=null) en.setCondition(condition);
  return QueryMulti(en);
 }

/**
 * QuerySingle's method is to query single result using direct user's
 * words. It collects all the parameters and pack them into Encap.
 * It uses QuerySingle's with Encap parameter to do the real work.
 * @param String table - contains the table name
 *        String col - contains column name
 *        String condition - contains the condition
 * @return Encap - contains the result.
 */
 public Encap QuerySingle(String table,String col,String condition)
  throws SQLException
 {
  if(!initConnection)
    throw new SQLException("No initial connection to database establish");
  Encap en = new Encap(table);
  int p = col.indexOf(',');
  if(p<0) en.setName(col);
  else
   en = phraseNames(p,col,en);
  if(condition!=null) en.setCondition(condition);
  return QuerySingle(en);
 }

/**
 * DeleteSingle's method is to delete data from the database using
 * user direct syntax of string table_name and string condition.
 * It is transaction-safe operation
 * @param String table - contains table_name
 *        String condition - contains the condition
 * @return none
 */
 public void DeleteSingle(String table,String condition) throws SQLException
 {
  if(!initConnection)
   throw new SQLException("No initial connection to database establish");
  Encap en = new Encap(table);
  en.setCondition(condition);
  DeleteSingle((Encap)en.clone());
  en.clear();
 }

/**
 * DeleteSingle's method is to delete data from the database.
 * The user sets condition determine how many data will be deleted.
 * It is transaction-safe operation
 * @param Encap en - contains syntax of delete command
 * @return none
 */
 public void DeleteSingle(Encap en) throws SQLException
 {
  if(!initConnection)
   throw new SQLException("No initial connection to database establish");
  if(en == null) throw new SQLException("Passed null value");
  StringBuffer q = new StringBuffer(32);
  q.append("DELETE FROM "+en.getTable()+" "+en.getCondition());
  Statement stmt = null;
  try
  {
   connect.setAutoCommit(false);
   stmt = connect.createStatement();
   stmt.executeUpdate(q.toString());
	 connect.commit();
  }
  catch(SQLException sqle)
  {
   connect.rollback();
   throw sqle;
  }
  finally
  {
   stmt.close();
  }
 }

/**
 * UpdateSpecial's method is to update with the special syntax other than
 * the usual Update's syntax. It is transaction-safe operation
 * @param String table - contains the table name
 *        String setting - contains the parameters' setting
 *        String condition - contains the condition of the update
 * @return none
 */
 public void UpdateSpecial(String table,String setting,String condition)
	throws SQLException
 {
  if(!initConnection)
   throw new SQLException("No initial connection to database establish");
	if(table == null || setting == null || condition == null)
	 throw new SQLException("One of the parameters is null");
	StringBuffer q = new StringBuffer(64);
	q.append("UPDATE "+table+" SET "+setting+" "+condition);
  Statement stmt = null;
	try
	{
   connect.setAutoCommit(false);
   stmt = connect.createStatement();
   stmt.executeUpdate(q.toString());
	 connect.commit();
	}
	catch(SQLException sqle)
	{
   connect.rollback();
   throw sqle;
	}
	finally
	{
   stmt.close();
	}
 }

/**
 * UpdateSpecialMany's method is for update's operation that requires a special
 * syntax other than the usual Update's syntax. It is transaction-safe
 * operation
 * @param Vector v - contains the Vector of String 
 * @return none
 */
 public void UpdateSpecialMany(Vector v) throws SQLException
 {
  if(!initConnection)
   throw new SQLException("No initial connection to database establish");
	if(v == null)
	 throw new SQLException("null Vector");
  if(v.isEmpty())
	 throw new SQLException("Empty Vector");
  Statement stmt = null;
	try
	{
   connect.setAutoCommit(false);
   stmt = connect.createStatement();
	 while(!v.isEmpty()) 
    stmt.executeUpdate((String)v.remove(0));
	 connect.commit();
	}
	catch(SQLException sqle)
	{
   connect.rollback();
   throw sqle;
	}
	finally
	{
   stmt.close();
	}
 }

/**
 * phraseNames' method is to phrase the column_names and put them in Encap
 * for later Query.
 * @param int p - contains the position of the first delimiter
 *        String col - contains the entire column_names to be phrase
 *        Encap en - contains the data
 * @return Encap contains the complete query syntax.
 */
 private Encap phraseNames(int p,String col,Encap en)
 {
  int start = 0;
  do
  {
   en.setName(col.substring(start,p));
   start = p;
   p = col.indexOf(',',start+1);
   if(p<0) en.setName(col.substring(start+1,col.length()));
  } while(p>0);
  return en;
 }

/**
 * viewEncap's method is to view the content of Encap.
 * @param Encap en - contains the data
 * @return none
 */
 public static void viewEncap(Encap en)
 {
  int size = en.getSize();
  System.out.println("Encap Table: "+en.getTable());
  for(int i=0;i<size;i++)
  {
   System.out.print(i+" EncapName: "+en.getName(i));
   if(en.getValueSize()>0)
    System.out.print(" EncapValue: "+en.getValue(i));
   System.out.println("");
  }
  if(en.getVariable()!=null)
   System.out.print("variable: "+en.getVariable()+" ");
  if(en.getCondition()!=null)
   System.out.print("condition: "+en.getCondition()+" ");
	System.out.println("");
 }

}
