import java.util.Vector;
import java.sql.Types.*;
import java.math.BigDecimal;

/**
 * Encap's class
 * It holds the name/value pairs and the database table_name.
 * You can use it to interact with Database with DBConnect's class
 * or you just use it to hold name/value pair.
 *
 * For Example of usage:
 * Encap en = new Encap("table_name");
 * en.setNameVal("field_name1",1); // set integer value
 * en.setNameVal("field_name2","1"); // set String value
 * 
 * long lnValue = 1.00;
 * double dbValue = 1.00;
 * BigDecimal bd = new BigDecimal("1.00");
 *
 * en.setNameVal("field_name3",lnValue); // set long value
 * en.setNameVal("field_name4",dbValue); // set double value
 * en.setNameVal("field_name5",bd); // set BigDecimal value
 *
 * // to view content of Encap, use DBConnect's static method
 * DBConnect.viewEncap(en);
 *
 * @author Edison Chindrawaly
 * @version 1.1 [last modified 7/2/2004]
 */

public class Encap implements Encapsulation,Cloneable
{
 public final static int INT = java.sql.Types.INTEGER;
 public final static int STR = java.sql.Types.VARCHAR; 
 public final static int FLT = java.sql.Types.FLOAT;
 public final static int DBL = java.sql.Types.DOUBLE;
 public final static int LNG = java.sql.Types.BIGINT;
 public final static int VAR = 99;
 public final static int DAT = java.sql.Types.DATE;
 public final static int TIM = java.sql.Types.TIME;
 public final static int DEC = java.sql.Types.DECIMAL;

 private StringBuffer encapCond = null; // the database condition set
 private StringBuffer encapTable= null; // the database table name 
 private StringBuffer encapVar  = null; // the database variable (ie, @user) 
 // the value of the encap data
 private Vector encapValues;
 private Vector encapNames;
 private Vector encapTypes;

/**
 * default constructor
 */
 public Encap() { init(); }

/**
 * constructor with String's parameter. It sets the table name
 * @param String table - contains the table name
 */
 public Encap(String table) 
 { 
  init(); 
  setTable(table); 
 }

/**
 * constructor with all field parameters setting of String value
 * @param String table - contains table_name
 *        String name - contains the field_name
 *        String value - contains the field_value
 */
 public Encap(String table,String name,String value)
 {
  init();
  setTable(table);
  setNameVal(name,value);
 }

/**
 * constructor with all field parameters setting of int value
 * @param String table - contains table_name
 *        String name - contains the field_name
 *        int value - contains the field_value
 */
 public Encap(String table,String name,int value)
 {
  init();
  setTable(table);
  setNameVal(name,value);
 }

/**
 * constructor with all field parameters setting of long value
 * @param String table - contains table_name
 *        String name - contains the field_name
 *        String value - contains the field_value
 */
 public Encap(String table,String name,long value)
 {
  init();
  setTable(table);
  setNameVal(name,value);
 }

/**
 * constructor with all field parameters setting of float value
 * @param String table - contains table_name
 *        String name - contains the field_name
 *        float value - contains the field_value
 */
 public Encap(String table,String name,float value)
 {
  init();
  setTable(table);
  setNameVal(name,value);
 }

/**
 * constructor with all field parameters setting of double value
 * @param String table - contains table_name
 *        String name - contains the field_name
 *        double value - contains the field_value
 */
 public Encap(String table,String name,double value)
 {
  init();
  setTable(table);
  setNameVal(name,value);
 }

/**
 * constructor with all field parameters setting of double/BigDecimal value
 * @param String table - contains table_name
 *        String name - contains the field_name
 *        double value - contains the field_value
 *        boolean dec - contains true 
 */
 public Encap(String table,String name,double value,boolean dec)
 {
  init();
  setTable(table);
  setNameVal(name,value,dec);
 }

/**
 * constructor with all field parameters setting of BigDecimal value
 * @param String table - contains the table_name
 *        String name - contains the field_name
 *        BigDecimal value - contains the field_value
 */
 public Encap(String table,String name,BigDecimal value)
 {
  init();
  setTable(table);
  setNameVal(name,value);
 }

/**
 * init's method is to initialize all the vectors that hold the parameters
 * @param none
 * @return none
 */
 public void init()
 {
  encapValues = new Vector();
  encapNames = new Vector();
  encapTypes = new Vector();
  encapVar   = new StringBuffer();
  encapTable = new StringBuffer();
  encapCond  = new StringBuffer();
 }

/**
 * clear's method is to clear all parameters
 * @param none
 * @return none
 */
 public void clear()
 {
  if(!encapValues.isEmpty())
   encapValues.removeAllElements();
  if(!encapNames.isEmpty())
   encapNames.removeAllElements();
  if(!encapTypes.isEmpty())
   encapTypes.removeAllElements();
  if(encapCond.length()>0)
   encapCond.delete(0,encapCond.length());
  if(encapTable.length()>0)
   encapTable.delete(0,encapTable.length());
  if(encapVar.length()>0)
   encapVar.delete(0,encapVar.length());
 }

/**
 * removeNameVal's method is to remove name/value given the position
 * @param int pos - contains position
 * @return none
 */
 public void removeNameVal(int pos)
 { 
  removeVal(pos); 
  removeName(pos);
 }

/**
 * removeVal's method is to remove value given the position
 * @param int pos - contains position
 * @return none
 */
 public void removeVal(int pos)
 {
  encapValues.removeElementAt(pos);
  encapTypes.removeElementAt(pos);
 }

/**
 * removeName's method is to remove field_name given the position
 * @param int pos - contains position
 * @return none
 */
 public void removeName(int pos)
 { encapNames.removeElementAt(pos); }

/**
 * setNameVal's method is to set name/value of String
 * @param String name - contains the field_name
 *        String value - contains the field_value
 * @return none
 */
 public void setNameVal(String name, String value)
 { 
  setName(name); 
  setValue(value); 
 }

/**
 * setNameVal's method is to set name/value of integer
 * @param String name - contains the field_name
 *        int value - contains the integer value
 * @return none
 */
 public void setNameVal(String name, int value)
 { 
  setName(name); 
  setValue(value); 
 }

/**
 * setNameVal's method is to set name/value of float
 * @param String name - contains the field_name
 *        float value - contains the field_value 
 * @return none
 */
 public void setNameVal(String name, float value)
 { 
  setName(name); 
  setValue(value); 
 }
/**
 * setNameVal's method is to set name/value of float
 * @param String name - contains the field_name
 *        double value - contains the field_value 
 * @return none
 */
 public void setNameVal(String name, double value)
 { 
  setName(name); 
  setValue(value); 
 }
/**
 * setNameVal's method is to set name/value of float
 * @param String name - contains the field_name
 *        long value - contains the field_value 
 * @return none
 */
 public void setNameVal(String name, long value)
 {
  setName(name);
  setValue(value);
 }

/**
 * setNameVal's method is to set name/value of float
 * @param String name - contains the field_name
 *        BigDecimal value - contains the field_value 
 * @return none
 */
 public void setNameVal(String name, BigDecimal value)
 {
  setName(name);
  setValue(value);
 }

/**
 * setNameVal's method is to set all parameters name/value of BigDecimal
 * given the double's value
 * @param String name - field_name
 *        double value - field_value of double that is converted to BigDecimal
 *        boolean dec - deprecrated
 * @return none
 */
 public void setNameVal(String name, double value, boolean dec)
 {
  setName(name);
  setDecValue(value);
 }

/**
 * setTable's method is to set the table name
 * @param String table - contains table_name
 * @return none
 */
 public void setTable(String table)
 { 
  if(encapTable.length()>0) encapTable.delete(0,encapTable.length());
  encapTable.append(table); 
 }

/**
 * setName's method is set field_name
 * @param String name - contains field_name
 * @return none
 */
 public void setName(String name)
 { encapNames.add(new String(name)); }

/**
 * setCondition's method is to set the condition
 * @param String cond - contains the condition
 * @return none
 */
 public void setCondition(String cond)
 { encapCond.append(cond); } 

/**
 * setVariable's method is to set the variable
 * @param String name - contains the variable
 * @return none
 */
 public void setVariable(String name)
 { encapVar.append(name); }

/**
 * setValue's method is to set BigDecimal's value and type of value
 * @param BigDecimal value
 * @return none
 */
 public void setValue(BigDecimal value)
 { encapValues.add(value); encapTypes.add(new Integer(DEC)); }

/**
 * setValue's method is to set integer value and type of value
 * @param int value
 * @return none
 */
 public void setValue(int value)
 { encapValues.add(new Integer(value)); encapTypes.add(new Integer(INT)); }

/**
 * setValue's method is to set the float value and type of value
 * @param float value.
 * @return none
 */
 public void setValue(float value)
 { encapValues.add(new Float(value)); encapTypes.add(new Float(FLT));  }

/**
 * setValue's method is to set the double value and the type of value
 * @param double value 
 * @return none
 */
 public void setValue(double value)
 { encapValues.add(new Double(value)); encapTypes.add(new Integer(DBL)); }

/**
 * setDecValue's method is to set the BigDecimal value and type of value
 * @param double value - contains the double value to be converted 
 * to BigDecimal
 * @return none
 */
 public void setDecValue(double value)
 { encapValues.add(new BigDecimal(value)); encapTypes.add(new Integer(DEC)); }

/**
 * setValue's method is to set the long value. it also sets the type of value
 * @param long value - contains the long value
 * @return none
 */
 public void setValue(long value)
 { encapValues.add(new Long(value)); encapTypes.add(new Integer(LNG)); }

/**
 * setValue's method is to set value given the value in String.
 * It also determine the type of value. If the value is null, it fills
 * the field_value with "none".
 * @param String value - contains the value
 * @return none
 */
 public void setValue(String value)
 { 
  if(value == null)
  {
   encapValues.add(new String("none"));
   encapTypes.add(new Integer(STR));
  }
  else if(value.length()==0 || value.compareToIgnoreCase(" ")==0)
  {
   encapValues.add(new String("none"));
   encapTypes.add(new Integer(STR));
  }
  else
  {
   encapValues.add(new String(value)); 
   if(value.charAt(0)=='@')
    encapTypes.add(new Integer(VAR));
	 else if(value.startsWith("("))
		encapTypes.add(new Integer(VAR));
   else if(value.startsWith("PASSWORD"))
    encapTypes.add(new Integer(VAR));
   else if(value.compareToIgnoreCase("CURRENT_DATE")==0)
    encapTypes.add(new Integer(DAT));
   else if(value.compareToIgnoreCase("CURRENT_TIME")==0)
    encapTypes.add(new Integer(TIM));
   else
    encapTypes.add(new Integer(STR)); 
  }
 }

/**
 * getPosition's method is to get the position given the field_name
 * @param String name - contains the field name
 * @return int position
 */
 public int getPosition(String name)
 { return encapNames.indexOf(name); }

/**
 * getSize's method is to get the size of the encap's field_name
 * @param none
 * @return int size
 */
 public int getSize()
 { return encapNames.size(); }

/**
 * getCondition's method is to get condition
 * @param none
 * @return String condition
 */
 public String getCondition()
 { 
  if(encapCond.length()==0)
   return null; 
  return encapCond.toString(); 
 }

/**
 * getVariable's method is to get variable
 * @param none
 * @return String value
 */
 public String getVariable()
 { 
  if(encapVar.length()==0)
   return null;
  return encapVar.toString(); 
 }

/**
 * getValueSize's method is to get the size of the value's parameters.
 * The values are hold in the vector.
 * @param none
 * @return int size
 */
 public int getValueSize()
 { return encapValues.size(); }

/**
 * getType's method is to return the type of value given the position
 * @param int pos - contains the position
 * @return int type of value
 */
 public int getType(int pos)
 { return ((Integer)encapTypes.elementAt(pos)).intValue(); }

/**
 * getValue's method is to return all type of value as String.
 * @param int pos - contains the position
 * @return String value
 */
 public String getValue(int pos)
 { 
  switch(getType(pos))
  {
   case INT : return ((Integer)encapValues.elementAt(pos)).toString();
   case DAT :
   case VAR :
   case TIM : 
   case STR : return encapValues.elementAt(pos).toString(); 
   case FLT : return ((Float)encapValues.elementAt(pos)).toString();
   case DBL : return ((Double)encapValues.elementAt(pos)).toString(); 
   case DEC : return ((BigDecimal)encapValues.elementAt(pos)).toString();
   case LNG : return ((Long)encapValues.elementAt(pos)).toString();
   default  : 
  }
  return null;
 }

/**
 * getIntValue's method is to get the integer value given the position
 * @param int pos - contains the position
 * @return int value
 */
 public int getIntValue(int pos)
 { return ((Integer)encapValues.elementAt(pos)).intValue(); } 

/**
 * getFloatValue's method is to get the float's value given the position
 * @param int pos - contains the position
 * @return float value
 */
 public float getFloatValue(int pos)
 { return ((Float)encapValues.elementAt(pos)).floatValue(); }

/**
 * getDoubleValue's method is to get the double value given the position
 * @param int pos - contains position
 * @return double value
 */
 public double getDoubleValue(int pos)
 { return ((Double)encapValues.elementAt(pos)).doubleValue(); }

/**
 * getLongValue's method is to get long's value given the position
 * @param int pos - contains the position
 * @return long value
 */
 public long getLongValue(int pos)
 { return ((Long)encapValues.elementAt(pos)).longValue(); }

/**
 * getIntLongValue's method is to get integer value out of the long's type
 * value given the position
 * @param int pos - contains the position
 * @return int value
 */
 public int getIntLongValue(int pos)
 { return ((Long)encapValues.elementAt(pos)).intValue(); }

/**
 * getDecDoubleValue's method is to get the double value out of the
 * BigDecimal's type of value.
 * @param int pos - contains the position
 * @return double value
 */
 public double getDecDoubleValue(int pos)
 { return ((BigDecimal)encapValues.elementAt(pos)).doubleValue(); }

/**
 * getDecValue's method is to get the BigDecimal's value given the position
 * @param int pos - contains the position
 * @return BigDecimal value
 */
 public BigDecimal getDecValue(int pos)
 { return (BigDecimal)encapValues.elementAt(pos); }

/**
 * getStringValue's method is to get the string value given the position
 * @param int pos - contains the position
 * @return String value
 */
 public String getStringValue(int pos)
 { return (String)encapValues.elementAt(pos); }

/**
 * getTable's method is to get table_name 
 * @param none
 * @return String table_name
 */
 public String getTable()
 { 
  if(encapTable.length()==0)
   return null;
  return encapTable.toString(); 
 }

/**
 * getName's method is to get field_name given the position
 * @param int pos - contains the position
 * @return String name
 */
 public String getName(int pos)
 { return (String)encapNames.elementAt(pos); }

/**
 * extractAll's method is to extract all value method given the field_name
 * but it will return value in form of String irregardless the type of
 * the value.
 * @param String name - contains the field_name
 * @return String value - contains the field_value
 */
 public String extractAll(String name)
 {
  int p = getPosition(name);
  if(p<0) return null;
  return getValue(p);
 }

/**
 * extractDouble's method is to extract the double value given the field_name
 * @param String name - contains the field name
 * @return double value
 */
 public double extractDouble(String name)
 {
  int p = getPosition(name);
  if(p<0) return 0;
  if(((Integer)encapTypes.elementAt(p)).intValue() == DEC)
    return getDecDoubleValue(p);
  return getDoubleValue(p);
 }

/**
 * extractBigDecimal's method is to extract the BigDecimal's value 
 * given the field_name.
 * @param String name contains the field_name
 * @return BigDecimal value
 */
 public BigDecimal extractBigDecimal(String name)
 {
  int p = getPosition(name);
  if(p<0) return null;
  return getDecValue(p);
 }

/**
 * extractFloat's method is to extract the Float value given the field_name
 * @param String name - contains the field name
 * @return float value
 */
 public float extractFloat(String name)
 {
  int p = getPosition(name);
  if(p<0) return 0;
  return getFloatValue(p);
 }

/**
 * extractString's method is to extract String's value given the field name
 * and the field_value OR without the field_value
 * @param String name - contains the field_name
 *        String value - contains the field_value [optional]
 * @return String value
 */
 public String extractString(String name,String value)
 {
  int p = getPosition(name);
  if(p<0) return null;
  if(value == null) 
   return getStringValue(p);
  while((p<getSize())&&(p>0))
  {
   if(getStringValue(p).compareToIgnoreCase(value)==0)
    return getStringValue(p);
   p = encapNames.indexOf(name,p+1); 
  }
  return null;
 }

/**
 * extractInteger's method is to extract Integer's value given the field_name
 * and the field_value OR without the field_value
 * @param String name - contains the field_name
 *        int value - contains the value [optional]
 * @return int value.
 */
 public int extractInteger(String name,int value)
 {
  int p = getPosition(name);
  if(p<0) return 0;
  if(value<=0) return getIntValue(p);
  while((p<getSize())&&(p>0))
  {
   if(getIntValue(p)==value)
    return getIntValue(p);
   p = encapNames.indexOf(name,p+1);
  }
  return 0;
 }

/**
 * extractName's method is to extract the field_name given the field_value
 * @param String value - contains the value which is needed to find the name.
 * @return String of name that is pair with that value
 */
 public String extractName(String value)
 {
  int p = encapValues.indexOf(value);
  if(p<0) return null;
  return getName(p);
 }

/**
 * replaceValue's method is to replace the value of the encap.
 * the type of the value HAS TO BE the same. If the previous value is
 * String then the replace value must be String also.
 * @param int pos - contains the position of the replace value
 *        Object obj - contains the new value
 * @return none
 */
 public void replaceValue(int pos,Object obj)
 {
  int valType = getType(pos);
  switch(valType)
  {
	 case TIM :
	 case DAT :
   case VAR :
   case STR : encapValues.setElementAt((String)obj,pos); break;
   case INT : encapValues.setElementAt((Integer)obj,pos); break;
   case FLT : encapValues.setElementAt((Float)obj,pos); break;
   case DBL : encapValues.setElementAt((Double)obj,pos); break;
   case LNG : encapValues.setElementAt((Long)obj,pos); break; 
   case DEC : encapValues.setElementAt((BigDecimal)obj,pos); break;
  }
  return;
 }

/**
 * clone's method is to clone the Encap to another Encap. 
 * It does the deep copy.
 * @param none
 * @return Object of the clone's Encap
 */
 protected Object clone()
 {
  try
  {
   Encap enCopy = (Encap)super.clone(); 
   enCopy.init();
   enCopy.encapNames = (Vector)encapNames.clone();
   enCopy.encapValues= (Vector)encapValues.clone();
   enCopy.encapTypes = (Vector)encapTypes.clone();
   if(getTable()!= null)
    enCopy.setTable(getTable());
   if(getCondition()!= null)
    enCopy.setCondition(getCondition());
   if(getVariable()!=null)
    enCopy.setVariable(getVariable());
   return enCopy;
  }
  catch(CloneNotSupportedException e)
  {
   e.printStackTrace(System.out);
  }
  return this;
 }
}
