// $Id: trip.java,v 1.6 2001/07/11 03:11:16 mdean Exp $


/**
 * convert BBN Expense Report info from trip.bas into DAML. 
 */
class trip
{
    static com.hp.hpl.mesa.rdf.jena.model.Model model = new com.hp.hpl.mesa.rdf.jena.mem.ModelMem();

    /**
     * ISO date format
     */
    static java.text.DateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd");

    /**
     * maps String to String.
     */
    static java.util.TreeMap trips = new java.util.TreeMap(); 

    static class Expense
    {
	/**
	 * offset from trip start (0 if unknown)
	 */
	int day;
	String value;

	Expense(int day, String value)
	{
	    this.day = day;
	    this.value = value;
	}
    }
    
    /**
     * maps Vector(trip, type) to Vector of Expense
     */
    static java.util.Hashtable expenses = new java.util.Hashtable();

    static void store(String trip, String type, int day, String value)
    {
	java.util.Vector key = new java.util.Vector();
	key.add(trip);
	key.add(type);

	Expense expense = new Expense(day, value);

	java.util.Vector list = (java.util.Vector) expenses.get(key);
	if (list == null)
	    {
		list = new java.util.Vector();
		expenses.put(key, list);
	    }
	list.add(expense);

	// remember trip
	trips.put(trip, trip);
    }

    static java.util.Vector get(String trip, String type)
    {
	java.util.Vector key = new java.util.Vector();
	key.add(trip);
	key.add(type);

	return (java.util.Vector) expenses.get(key);
    }

    static void processFile(String path)
	throws Exception
    {
	java.io.BufferedReader stream = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(path)));
	String line;
	while ((line = stream.readLine()) != null)
	    {
		java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(line, "\t");
		String xls = tokenizer.nextToken();
		String cell = tokenizer.nextToken();
		String type = tokenizer.nextToken();
		String value;
		try {
		    value = tokenizer.nextToken();
		} catch (java.util.NoSuchElementException e) {
		    value = "";
		}
		int space = xls.indexOf(' ');
		String trip = xls.substring(0, space);
		int day = (int) cell.charAt(0) - (int) 'C';

		store(trip, type, day, value);
	    }
    }

    /**
     * convert from Excel numeric day to ISO 8601 date format.
     */
    static String convertDate(String string, int offset)
    {
	long msec = (Long.parseLong(string) - 25569 + 1463 + offset) * 60 * 60 * 24 * 1000L;
	java.util.Date date = new java.util.Date(msec);
	return df.format(date);
    }

    /**
     * return a singleton value
     */
    static String getSingle(String trip,
			    String type)
    {
	java.util.Vector vector = get(trip, type);
	if (vector == null)
	    {
		System.err.println("no " + type + " for " + trip);
		return "";
	    }
	Expense expense = (Expense) vector.elementAt(0);
	return expense.value;
    }

    static void processFormula(String formula,
			       String date,
			       com.hp.hpl.mesa.rdf.jena.model.Resource tripResource,
			       com.hp.hpl.mesa.rdf.jena.model.Property property)
	throws Exception
    {
	java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(formula, "=+-");

	while (tokenizer.hasMoreTokens())
	    {
		String amount = tokenizer.nextToken();
		
		if (amount.length() == 0)
		    continue;

		com.hp.hpl.mesa.rdf.jena.model.Resource expenseResource = new com.hp.hpl.mesa.rdf.jena.common.ResourceImpl();

		model.add(expenseResource,
			  com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
			  trip_ont.Expense);
		model.add(expenseResource,
			  trip_ont.date,
			  date);
		model.add(expenseResource,
			  trip_ont.amount,
			  eecr.round(amount));

		model.add(tripResource,
			  property,
			  expenseResource);
	    }
    }

    static void processExpenses(String trip,
				String type,
				String start,
				com.hp.hpl.mesa.rdf.jena.model.Resource tripResource,
				com.hp.hpl.mesa.rdf.jena.model.Property property)
	throws Exception
    {
	java.util.Vector list = (java.util.Vector) get(trip, type);

	// no expenses for this type?
	if (list == null)
	    return;

	java.util.Iterator iterator = list.iterator();
	while (iterator.hasNext())
	    {
		Expense expense = (Expense) iterator.next();

		// empty cell
		if (expense.value.length() == 0)
		    continue;

		processFormula(expense.value,
			       convertDate(start, expense.day),
			       tripResource,
			       property);
	    }
    }

    static void processTrip(String trip)
	throws Exception
    {
	String start = getSingle(trip, "start");

	// check for old spreadsheet
	if (start.length() == 0)
	    return;

	String end = getSingle(trip, "end");
	String total = getSingle(trip, "total");

	com.hp.hpl.mesa.rdf.jena.model.Resource tripResource = new com.hp.hpl.mesa.rdf.jena.common.ResourceImpl("#" + trip);
	model.add(tripResource,
		  com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
		  trip_ont.Trip);
	model.add(tripResource,
		  trip_ont.start,
		  convertDate(start, 0));
	model.add(tripResource,
		  trip_ont.end,
		  convertDate(end, 0));
	model.add(tripResource,
		  trip_ont.total,
		  eecr.round(total));

	processExpenses(trip, "hotel", start, tripResource, trip_ont.hotel);
	processExpenses(trip, "airfare", start, tripResource, trip_ont.airfare);
	processExpenses(trip, "car", start, tripResource, trip_ont.car);
	processExpenses(trip, "parking", start, tripResource, trip_ont.parking);
    }

    static void usage()
    {
	System.err.println("Usage:  tab-delimited-file");
    }
    
    public static void main(String args[])
	throws Exception
    {
	// argument parsing
	if (args.length != 1)
	    usage();
	String path = args[0];

	processFile(path);

	java.util.Iterator iterator = trips.values().iterator();
	while (iterator.hasNext())
	    {
		String trip = (String) iterator.next();
		processTrip(trip);
	    }

	// write model
	java.io.PrintWriter stream = new java.io.PrintWriter(System.out);
	model.write(stream);
    }
}
