// $Id: itinerary2map.java,v 1.4 2003/02/18 22:23:30 tself Exp $


/**
 * show the specified itinerary.
 * Create a Point for each airport and a Line for each flight.
 */
public class itinerary2map
{
    /**
     * DAML input
     */
    static com.hp.hpl.mesa.rdf.jena.model.Model itinerary = new com.hp.hpl.mesa.rdf.jena.mem.ModelMem();

    /**
     * DAML output
     */
    static com.hp.hpl.mesa.rdf.jena.model.Model map = new com.hp.hpl.mesa.rdf.jena.mem.ModelMem();
    static com.hp.hpl.mesa.rdf.jena.model.Resource layer;

    /**
     * map Airport Resource to Location Resource.
     */
    static java.util.Hashtable airports = new java.util.Hashtable();

    /**
     * return the portion of the URI following #.
     */
    static String fragment(com.hp.hpl.mesa.rdf.jena.model.Resource resource)
    {
	String string = resource.toString();
	int pound = string.indexOf('#');
	if (pound != (-1))
	    return string.substring(pound + 1);
	else
	    return string;
    }

    /**
     * identify this airport, if we haven't already.
     */
    static void maybeCreateAirport(com.hp.hpl.mesa.rdf.jena.model.Resource airport)
	throws Exception
    {
	if (airports.get(airport) == null)
	    {
		String code = fragment(airport);

		// create location
		com.hp.hpl.mesa.rdf.jena.model.Resource location = map.createResource("#" + code + "-location");
		map.add(location,
			com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
			map_ont.Location);
		map.add(location,
			map_ont.latitude,
			getValue(itinerary, airport, locations.latitude));
		map.add(location,
			map_ont.longitude,
			getValue(itinerary, airport, locations.longitude));

		// create point
		com.hp.hpl.mesa.rdf.jena.model.Resource point = map.createResource("#" + code + "-point");
		map.add(point,
			com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
			map_ont.Point);
		map.add(point,
			map_ont.label,
			code);
		map.add(point,
			map_ont.location,
			location);
		map.add(layer,
			map_ont.object,
			point);

		// remember
		airports.put(airport, location);
	    }
    }

    static com.hp.hpl.mesa.rdf.jena.model.Resource getLocation(com.hp.hpl.mesa.rdf.jena.model.Resource airport)
    {
	return (com.hp.hpl.mesa.rdf.jena.model.Resource) airports.get(airport);
    }
    
    static class BadCardinality
	extends Exception
    {
	com.hp.hpl.mesa.rdf.jena.model.Resource subject;
	com.hp.hpl.mesa.rdf.jena.model.Property property;

	BadCardinality(com.hp.hpl.mesa.rdf.jena.model.Resource subject,
		       com.hp.hpl.mesa.rdf.jena.model.Property property)
	{
	    this.subject = subject;
	    this.property = property;
	}

	public String toString()
	{
	    return "BadCardinality for " + property + " of " + subject;
	}
    }

    /**
     * return the single property of cardinality 1
     */
    public static com.hp.hpl.mesa.rdf.jena.model.RDFNode getValue(com.hp.hpl.mesa.rdf.jena.model.Model model,
							   com.hp.hpl.mesa.rdf.jena.model.Resource subject,
							   com.hp.hpl.mesa.rdf.jena.model.Property property)
	throws BadCardinality,
	       Exception
    {
	com.hp.hpl.mesa.rdf.jena.model.RDFNode retval;
	com.hp.hpl.mesa.rdf.jena.model.NodeIterator nodeIterator = model.listObjectsOfProperty(subject, property);
	if (! nodeIterator.hasNext())
	    throw new BadCardinality(subject, property);
	retval = nodeIterator.next();
	if (nodeIterator.hasNext())
	    throw new BadCardinality(subject, property);
	nodeIterator.close();
	return retval;
    }

    public static void usage()
    {
	System.err.println("Usage:  uri ...");
	System.exit(1);
    }

    public static void main(String args[])
	throws Exception
    {
	// parse arguments
	if (args.length < 1)
	    usage();
	for (int i = 0; i < args.length; i++)
	    {
		String arg = args[i];
		if (arg.indexOf(':') == (-1))
		    arg = "file:" + arg;
		itinerary.read(arg);
	    }
	
	com.hp.hpl.mesa.rdf.jena.model.Resource mapRoot = map.createResource("#map");
	map.add(mapRoot,
		com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
		map_ont.Map);
	layer = map.createResource("#layer");
	map.add(layer,
		com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
		map_ont.DrawingLayer);
	map.add(mapRoot,
		map_ont.layer,
		layer);

	com.hp.hpl.mesa.rdf.jena.model.ResIterator flightIterator = itinerary.listSubjectsWithProperty(com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
												       itinerary_ont.Flight);
	while (flightIterator.hasNext())
	    {
		com.hp.hpl.mesa.rdf.jena.model.Resource flight = flightIterator.next();
		com.hp.hpl.mesa.rdf.jena.model.Resource origin = (com.hp.hpl.mesa.rdf.jena.model.Resource) getValue(itinerary, flight, itinerary_ont.origin);
		com.hp.hpl.mesa.rdf.jena.model.Resource destination = (com.hp.hpl.mesa.rdf.jena.model.Resource) getValue(itinerary, flight, itinerary_ont.destination);
		
		// create airport Points
		maybeCreateAirport(origin);
		maybeCreateAirport(destination);

		// draw line
		com.hp.hpl.mesa.rdf.jena.model.Resource originLocation = getLocation(origin);
		com.hp.hpl.mesa.rdf.jena.model.Resource destinationLocation = getLocation(destination);
		com.hp.hpl.mesa.rdf.jena.model.Resource line = map.createResource("#" + fragment(origin) + "-" + fragment(destination) + "-line");
		map.add(line,
			com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
			map_ont.Line);
		map.add(line, map_ont.location, originLocation);
		map.add(line, map_ont.location, destinationLocation);
		map.add(layer, map_ont.object, line);
	    }

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