// PopulateLocalCentralForTesting.java
//
//    senger@ebi.ac.uk
//    October 2003
//

import org.biomoby.shared.*;
import org.biomoby.client.*;

/**
 * This is a very specialized client, meant solely for testing
 * purposes, and to be used on a local installation of a Moby Central
 * registry. It register several sets of fake services, namespaces and
 * data objects. Their only purpose is to establish almost all
 * possible data connections between services and by doing that to
 * allow testing other classes dealing with graphs of Moby services.
 *<p>
 *
 * Keep in mind that it is not advisable to run this client against a
 * Moby registry containing real services and data objects because it
 * would pollute it with fake, non-existing objects. That's why the
 * default Moby Central is not the one used in the other clients.
 *<p>
 *
 * On the other hand this client may be useful as a base class for
 * those who wish to create more complex testing environment (for
 * whatever testing purposes).
 *<p>
 *
 * The command-line arguments for this client are:
 * <pre>
 *    Usage: java PopulateLocalCentralForTesting [-e <endpoint>] [-u <uri>] [-clean]
 * </pre>
 * where <em>endpoint</em> is a URL of a Moby Central registry
 * (default value is <tt>http://localhost/cgi-bin/moby</tt>) and
 * <em>uri</em> is a namespace used by that service (default value is
 * taken from
 * <tt>org.biomoby.client.CentralImpl.DEFAULT_NAMESPACE</tt>).  By
 * default the client populates given (or default) registry by
 * services, unless <em>-clean</em> option is given int which case it
 * removes the same set of services that were previously created byte
 * this client.
 *<p>
 *
 * @author <A HREF="mailto:senger@ebi.ac.uk">Martin Senger</A>
 * @version $Id: PopulateLocalCentralForTesting.java,v 1.5 2005/09/19 08:08:32 senger Exp $ */
public class PopulateLocalCentralForTesting {

    public static final String DEFAULT_ENDPOINT = "http://localhost/cgi-bin/moby";

    protected String serviceType = "ATestingServiceType";
    protected String namespace_1 = "ns1";
    protected String namespace_2 = "ns2";
    protected String dataType_1 = "dt1";
    protected String dataType_2 = "dt2";
    protected String dataType_3 = "dt3";
    protected String dataType_4 = "dt4";
    protected String dataType_5 = "dt5";
    protected String service_A = "Service_A";
    protected String service_B = "Service_B";
    protected String service_C = "Service_C";
    protected String service_D = "Service_D";
    protected String service_E = "Service_E";
    protected String service_F = "Service_F";
    protected String service_G = "Service_G";
    protected String authority = "testing.org";
    protected String serviceURL = "http://www.testing.org";
    protected String emailContact = "mail@mail.com";

    protected Central worker;
    String endpoint;
    String uri;

    public PopulateLocalCentralForTesting() {
	this (null, null);
    }

    public PopulateLocalCentralForTesting (String endpoint,
					   String uri) {
	this.endpoint = (endpoint == null ? DEFAULT_ENDPOINT : endpoint);
	this.uri = (uri == null ? CentralImpl.DEFAULT_NAMESPACE : uri);
	try {
	    start ("starting");
	    worker = new CentralImpl (this.endpoint, this.uri);
	    ok();
	} catch (MobyException e) { error (e); }
    }

    public void cleanAll() {

	// services
	MobyService[] services = createAllServices();
	for (int i = 0; i < services.length; i++) {	
	    try {
		start ("deregisterService - " + (char)('A' + i));
		worker.unregisterService (services[i]);
		ok();
	    } catch (MobyException e)            { error (e);
	    } catch (NoSuccessException e)       { maybe (e);
	    } catch (PendingCurationException e) { error (e); }
	}

	// data types
	MobyDataType[] data = createAllDataTypes();
	for (int i = data.length - 1; i >= 0; i--) {
	    try {
		start ("deregisterDataType - " + (i+1));
		worker.unregisterDataType (data[i]);
		ok();
	    } catch (MobyException e)            { error (e);
	    } catch (NoSuccessException e)       { maybe (e);
	    } catch (PendingCurationException e) { error (e); }
	}
	
	// namespaces
	MobyNamespace namespace1 = createNamespace (namespace_1);
	MobyNamespace namespace2 = createNamespace (namespace_2);
	try {
	    start ("deregisterNamespace - 2");
	    worker.unregisterNamespace (namespace2);
	    ok();
	} catch (MobyException e)            { error (e);
	} catch (NoSuccessException e)       { maybe (e);
	} catch (PendingCurationException e) { error (e); }
	try {
	    start ("deregisterNamespace - 1");
	    worker.unregisterNamespace (namespace1);
	    ok();
	} catch (MobyException e)            { error (e);
	} catch (NoSuccessException e)       { maybe (e);
	} catch (PendingCurationException e) { error (e); }

	// service type(s)
	MobyServiceType stype = createServiceType (serviceType);
	try {
	    start ("deregisterServiceType");
	    worker.unregisterServiceType (stype);
	    ok();
	} catch (MobyException e)            { error (e);
	} catch (NoSuccessException e)       { maybe (e);
	} catch (PendingCurationException e) { error (e); }
	
    }

    public void registerServiceTypes() {
	MobyServiceType stype = createServiceType (serviceType);
	try {
	    start ("registerServiceType");
	    worker.registerServiceType (stype);
	    ok();
	} catch (MobyException e)            { error (e);
	} catch (NoSuccessException e)       { error (e);
	} catch (PendingCurationException e) { error (e); }
    }

    public void registerNamespaces() {
	MobyNamespace namespace1 = createNamespace (namespace_1);
	MobyNamespace namespace2 = createNamespace (namespace_2);
	try {
	    start ("registerNamespace - 1");
	    worker.registerNamespace (namespace1);
	    ok();
	} catch (MobyException e)            { error (e);
	} catch (NoSuccessException e)       { error (e);
	} catch (PendingCurationException e) { error (e); }
	try {
	    start ("registerNamespace - 2");
	    worker.registerNamespace (namespace2);
	    ok();
	} catch (MobyException e)            { error (e);
	} catch (NoSuccessException e)       { error (e);
	} catch (PendingCurationException e) { error (e); }
    }

    public void registerDataTypes() {
	MobyDataType[] data = createAllDataTypes();
	for (int i = 0; i < data.length; i++) {
	    try {
		start ("registerDataType - " + (i+1));
		worker.registerDataType (data[i]);
		ok();
	    } catch (MobyException e)            { error (e);
	    } catch (NoSuccessException e)       { error (e);
	    } catch (PendingCurationException e) { error (e); }
	}
    }

    public void registerServices() {
	MobyService[] services = createAllServices();
	for (int i = 0; i < services.length; i++) {	
	    try {
		start ("registerService - " + (char)('A' + i));
		worker.registerService (services[i]);
		ok();
	    } catch (MobyException e)            { error (e);
	    } catch (NoSuccessException e)       { error (e);
	    } catch (PendingCurationException e) { error (e); }
	}
    }
	
    /*************************************************************************
     * Create a ServiceType object.
     *************************************************************************/
    protected MobyServiceType createServiceType (String serviceTypeName) {
	MobyServiceType stype = new MobyServiceType (serviceTypeName);
	stype.setDescription ("description for " + serviceTypeName);
	stype.setAuthority (authority);
	stype.setEmailContact (emailContact);
	return stype;
    }

    /*************************************************************************
     * Create a Namespace object.
     *************************************************************************/
    protected MobyNamespace createNamespace (String namespaceName) {
	MobyNamespace namespace = new MobyNamespace (namespaceName);
	namespace.setDescription ("description for " + namespaceName);
	namespace.setAuthority (authority);
	namespace.setEmailContact (emailContact);
	return namespace;
    }

    /*************************************************************************
     * Create a DataType object
     *************************************************************************/
    protected MobyDataType createDataType (String objectType) {
	MobyDataType data = new MobyDataType (objectType);
	data.setDescription ("description for " + objectType);
	data.setAuthority (authority);
	data.setEmailContact (emailContact);
	return data;
    }

    /*************************************************************************
     * Create all data types we use here.
     *************************************************************************/
    protected MobyDataType[] createAllDataTypes() {
	MobyDataType data1 = createDataType (dataType_1);
	data1.addParentName ("Object");
	data1.addChild ("address", "string", Central.iHASA);
	data1.addChild ("age", "integer", Central.iHASA);
	data1.addChild ("salary", "float", Central.iHASA);
	data1.addChild ("born", "datetime", Central.iHASA);
	MobyDataType data2 = createDataType (dataType_2);
	data2.addParentName ("Object");
	MobyDataType data3 = createDataType (dataType_3);
	data3.addParentName ("Object");
	MobyDataType data4 = createDataType (dataType_4);
	data4.addParentName (dataType_3);
	MobyDataType data5 = createDataType (dataType_5);
	data5.addParentName (dataType_3);
	data5.addParentName (dataType_2);
	data5.addChild ("range_min", "integer", Central.iHAS);
	data5.addChild ("range_max", "integer", Central.iHAS);

	return new MobyDataType [] { data1, data2, data3, data4, data5 };
    }

    /*************************************************************************
     * Create a Service object
     *************************************************************************/
    protected MobyService createService (String serviceName) {
	MobyService service = new MobyService (serviceName);
	service.setType (createServiceType (serviceType).getName());
	service.setDescription ("description for service " + serviceName);
	service.setAuthority (authority);
	service.setEmailContact (emailContact);
	service.setAuthoritative (true);
	service.setURL (serviceURL);
	return service;
    }

    /*************************************************************************
     * Create all services we use here.
     *************************************************************************/
    protected MobyService[] createAllServices() {

	MobyNamespace namespace1 = createNamespace (namespace_1);
	MobyNamespace namespace2 = createNamespace (namespace_2);

	MobyDataType[] data = createAllDataTypes();

	MobyPrimaryDataSimple simple1 = new MobyPrimaryDataSimple ("Simple_1");
	simple1.setDataType (data[0]);
	simple1.addNamespace (namespace1);
	simple1.addNamespace (namespace2);

	MobyPrimaryDataSimple simple2 = new MobyPrimaryDataSimple ("Simple_2");
	simple2.setDataType (data[0]);
	simple2.addNamespace (namespace2);

	MobyPrimaryDataSimple simple3 = new MobyPrimaryDataSimple ("Simple_3");
	simple3.setDataType (data[3]);
	simple3.addNamespace (namespace1);

	MobyPrimaryDataSimple simple4 = new MobyPrimaryDataSimple ("Simple_4");
	simple4.setDataType (data[0]);
	simple4.addNamespace (namespace1);

	MobyPrimaryDataSimple simple5 = new MobyPrimaryDataSimple ("Simple_5");
	simple5.setDataType (data[1]);

	MobyPrimaryDataSimple simple6 = new MobyPrimaryDataSimple ("Simple_6");
	simple6.setDataType (data[2]);
	simple6.addNamespace (namespace1);

	MobyPrimaryDataSimple simple7 = new MobyPrimaryDataSimple ("Simple_7");
	simple7.setDataType (data[0]);

	MobyPrimaryDataSimple simple8 = new MobyPrimaryDataSimple ("Simple_8");
	simple8.setDataType (data[2]);

	MobyPrimaryDataSet collection1 = new MobyPrimaryDataSet ("Collection_1");
	collection1.addElement (simple4);
	collection1.addElement (simple4);
	collection1.addElement (simple4);
	
	MobyService[] services = new MobyService [7];	

	services[0] = createService (service_A);
	services[0].addOutput (simple1);

	services[1] = createService (service_B);
	services[1].addInput (simple2);
	services[1].addOutput (simple3);

	services[2] = createService (service_C);
	services[2].addInput (simple4);
	services[2].addOutput (simple5);

	services[3] = createService (service_D);
	services[3].addInput (collection1);
	services[3].addOutput (collection1);

	services[4] = createService (service_E);
	services[4].addInput (simple5);
	services[4].addOutput (simple7);

	services[5] = createService (service_F);
	services[5].addInput (simple7);
	services[5].addInput (simple8);
	services[5].addOutput (simple1);
	services[5].addOutput (collection1);

	services[6] = createService (service_G);
	services[6].addInput (simple6);

	return services;
    }

    private static final int MAX_MSG_LEN = 35;
    protected void start (String msg) {
	System.out.print (msg);
	for (int i = MAX_MSG_LEN; i > msg.length(); i--)
	    System.out.print (" ");
    }

    protected void ok() {
	System.out.println ("OK");
    }

    protected void error (Exception e) {
	System.out.println ("FAILED");
	System.err.println (e.toString() + "\n");
    }

    protected void maybe (Exception e) {
	String msg = e.getMessage();
	if (msg.indexOf ("does not exist") > -1)
	    System.out.println ("(n/a)");
	else
	    error (e);
    }

    /*************************************************************************
     *
     * Entry point...
     *
     *************************************************************************/
    public static void main (String [] args) {
	try {

 	    String endpoint = null;
	    String uri      = null;
	    boolean clean   = false;

	    // command-line parameters
	    int i = 0;
	    while (i < args.length) {
		if (args[i].equals ("-help") || args[i].equals ("-")) {
		    System.out.println
			("Usage: java PopulateLocalCentralForTesting [-e <endpoint>] [-u <uri>] [-clean]");
		    System.exit (0);
		}
		if (args[i].equals ("-e") && i < args.length-1) {
		    endpoint = args[i+1];
		    i += 2;
		    continue;
		}
		if (args[i].equals ("-u") && i < args.length-1) {
		    uri = args[i+1];
		    i += 2;
		    continue;
		}
		if (args[i].equals ("-clean")) {
		    clean = true;
		    i += 1;
		    continue;
		}
		i++;
	    }

	    // create an instance who populates (or de-populates)
 	    PopulateLocalCentralForTesting populater =
		new PopulateLocalCentralForTesting (endpoint, uri);

	    // clear everything
	    populater.cleanAll();
	    if (clean)
		System.exit (0);

	    // register everything
	    populater.registerServiceTypes();
	    populater.registerNamespaces();
	    populater.registerDataTypes();
	    populater.registerServices();

	} catch (Exception e) {
	    System.err.println ("===ERROR===");
	    e.printStackTrace();
	    System.err.println ("===========");
	}
    }

}
