// file: Bug.java
//

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

/**
 * ISIP_Varmint_Bug
 *
 */
public class Bug {

    //*************************************************
    //
    // private data
    //
    //*************************************************
	
    /**
     *  Vector to hold all bug strings
     */
    private Vector roadkill = null;
    
    /**
     *  Vector to hold single bug fields
     */    
    private Vector record = null;

    /**
     * modes for the getfield telling it whether or not to remove the
     * SQL encoding - LEAVE = 0
     */
    public final int LEAVE   = 0;

    /**
     * modes for the getfield telling it whether or not to remove the
     * SQL encoding - CONVERT = 1
     */
    public final int CONVERT = 1;


    //*************************************************
    //
    // constructor methods
    //
    //*************************************************
    
    /**
     * Default constructor
     * Sets up an empty bug
     */
    public Bug() {
		
	// an empty Bug should contain all it's field names
	// call something to set up the empty fields
	//
	initBug();
	
	// done
	//

    }

    /**
     *  Copy constructor
     */   
    public Bug(Bug varmint) {
	
	// record's size needs to be two at the start
	//
	record.setSize(2);

	// add the strings from varmint.roadkill to local roadkill
	//
	int n = varmint.roadkill.size();
	int i = 0;
	while( (n != 0) && (i < n) ){
	    roadkill.addElement(varmint.roadkill.elementAt(i));
	    i++;
	}
 
	// done
	//

    }

    //*************************************************
    //
    // inspector methods
    //
    //*************************************************

    /**
     * Gets the field given the fieldName and mode
     *
     * @param fieldName column name of column to look at
     * @param mode Either 1 or 0 depending whether or not a conversion is
     *             desired or not. For a conversion, mode = 1, and to leave
     *             mode = 0.
     */
    public String getField(String fieldName, int mode) {
	
	// set up some counters
	//
	int n = roadkill.size();
	int i = 0;

	// look for the fieldName in roadkill
	//
	while (i < n) {
	    // records are stored as vectors
	    // we search by the inner vector's elt zero
	    //
	    String column = ((String)((Vector)
				      roadkill.elementAt(i)).elementAt(0));
	    // we have to cast roadkill.elementAt(i) to a Vector
	    // to check its inner element
	    //
	    //System.out.println(((Vector)roadkill.elementAt(i)).elementAt(0));
	    if (column.equals(fieldName)) {
		// we found the field, return its value
		// the value is stored in a vector at position 1
		//

		// we have to cast roadkill.elementAt(i) to a Vector to
		// check its inner element
		// then we have to cast all that back to a String to return
		//

		if (mode == CONVERT)
		    return convertFromSQL((String)((Vector)roadkill.
						   elementAt(i)).elementAt(1));
		else
		    return (String)((Vector)roadkill.
				    elementAt(i)).elementAt(1);
	    }
	    else {
		// we didn't find it, roll on
		//
		i++;
	    }
	}
	
	// we didn't find the field at all, maybe it's spelled wrong
	//
	return "";

	// done
	//

    }

    /**
     * Gets the field given the fieldName
     *
     * @param fieldName column name of column to look at
     * 
     */
    public String getField(String fieldName) {
	
	// set up some counters
	//
	int n = roadkill.size();
	int i = 0;

	// look for the fieldName in roadkill
	//
	while (i < n) {
	    // records are stored as vectors
	    // we search by the inner vector's elt zero
	    //
	    String column = ((String)((Vector)
				      roadkill.elementAt(i)).elementAt(0));
	    // we have to cast roadkill.elementAt(i) to a Vector
	    // to check its inner element
	    //
	    //System.out.println(((Vector)roadkill.elementAt(i)).elementAt(0));
	    if (column.equals(fieldName)) {
		// we found the field, return its value
		// the value is stored in a vector at position 1
		//

		// we have to cast roadkill.elementAt(i) to a Vector to
		// check its inner element
		// then we have to cast all that back to a String to return
		//

		return convertFromSQL((String)((Vector)roadkill.
						   elementAt(i)).elementAt(1));
	    }
	    else {
		// we didn't find it, roll on
		//
		i++;
	    }
	}
	
	// we didn't find the field at all, maybe it's spelled wrong
	//
	return "";

	// done
	//

    }

    //*****************************************************
    //
    // mutator methods
    //
    //*****************************************************

    /**
     * Sets the field given the fieldName and content. Replaces the vector
     * in the column with a vector of size two.  The first elementis the
     * column name or field name.  The second is the content.
     *
     * @param fieldName Column name of field to set
     * @param content String to be assigned
     * @return true if the column was matched to a field name and reassigned;
     *         false if the column was not matched and no reassignment was made
     */
    public boolean setField(String fieldName, String content) {
	// set up some counters
	//
	int n = roadkill.size();
	int i = 0;

	content = convertToSQL(content);

	//	System.out.println("input: " + fieldName + "; " + content);
	//System.out.println(((Vector)roadkill.elementAt(i)).elementAt(0));
	// look for the fieldName
	//
	while (i < n) {
	    // records are stored as vectors
	    // we search by the inner vector's elt zero
	    //
	    String column = ((String)((Vector)
				      roadkill.elementAt(i)).elementAt(0));
	    // we have to cast roadkill.elementAr(i) to a Vector to
	    // check its inner element
	    //

	    //System.out.println(((Vector)roadkill.elementAt(i)).elementAt(0));

	    if (column.equals(fieldName)) {
		// we found the field, set the new value
		// 
		//		System.out.println("Inside set part");
		// make a temp vector
		//
		Vector temp = new Vector();

		// set its size
		//
		temp.setSize(2);
		
		// add the new Strings to temp
		//
		temp.setElementAt(fieldName, 0);
		temp.setElementAt(content, 1);

		// replace current elt in roadkill with temp
		//
		roadkill.setElementAt(temp, i);
		//		System.out.println("setting: " + 
		//				   ((Vector)roadkill.elementAt(i)).elementAt(0));   
		// we did good, tell the caller
		//
		return true;
	    }
	    else {
		// we didn't find it, roll on
		//
		i++;
	    }
	}
	
	// we didn't find the field at all, maybe it's spelled wrong
	// tell the caller it didn't work
	//

	//	System.out.println("end setField");

	return false;

        // done
        //
	
    }
    /**
     * Converts a String to be able to use SQL
     *
     * @param from String to be converted
     * @return String that can be put into a field of the roadkill vector
     */
    public static String convertToSQL(String from) {

	//	System.out.println("\0, \n, \t, \r, \b, \', \", \\, \%, \_");
	if (from == null)
	    return null;

	StringTokenizer tokenizer = new StringTokenizer(from, "\'%?\\", true);
	String token = null;
	String returnString = new String("");
	while(tokenizer.hasMoreTokens()) {
	    token = tokenizer.nextToken();
	    
	    if(token.equals("\'"))
		returnString += "\\\'";
	    
	    else if(token.equals("%"))
		returnString += "\\%";

	    else if(token.equals("?"))
		returnString += "\\?";

	    else if(token.equals("\\"))
		returnString += "\\\\"; 
	    else
		returnString += token;
	}

	//	System.out.println("ConvertToSQL:  " + returnString);

	return returnString;
    }

    /**
     * Extratcs a string from SQL
     *
     * @param to String to be converted
     * @return Converted string from SQL to be read from a field of roadkill
     *         vector
     */
    public static String convertFromSQL(String to) {
	
	if (to == null)
	    return null;
	
	StringTokenizer tokenizer = new StringTokenizer(to, "\\", true);
	String token = null;
	String returnString = new String("");
	while(tokenizer.hasMoreTokens()) {
	    token = tokenizer.nextToken();
	    
	    if(token.equals("\\"))
		returnString += "";
	    else
		returnString += token;
	}

	//	System.out.println("ConvertFromSQL:  " + returnString);

	return returnString;
	
    }

    //*************************************
    //
    // protected mutator methods
    //
    //*************************************

    /**
     * This creates the roadkill vector.  The record vector gets reassigned
     * many times and added to the roadkill vector each time.
     */
    public void initBug() {

	// ensure we have empty vectors
	//
	roadkill = new Vector(20,5);
	record = new Vector(2);

	// set record to default size
	//
	record.setSize(2);

	// we have two empty vectors, one for fields, one for whole records
	// we'll put empty fields into the field vector
	// then we'll add the field to the record vector
	// then we'll do it again for the next field
	//
	record.setElementAt("BugNumber", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Title", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Owner", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Status", 0);
	record.setElementAt("Open", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Priority", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Severity", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("DBase", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("OpenedBy", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("OpenDate", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Environment", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Component", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("TestCase", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Class", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("ResolvedBy", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Resolution", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("ResolvedDate", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("ReviewDate", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Inspected", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Due", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("Description", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);
	record.setElementAt("ModifyDate", 0);
	record.setElementAt("", 1);
	roadkill.addElement(record);
	record = new Vector(2);
	record.setSize(2);

	// done
	//

    }

    // end of class
    //

};


