// TestingCentral.java
//    A client testing methods of a Moby Central.
//
//    senger@ebi.ac.uk
//    November 2002
//

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

import java.util.*;

/**
 * This is a testing client that calls as many Moby methods as possible
 * in order to test whether they return an error or not. Many pieces are
 * there hard-coded - so there is no much sense to use it for anything
 * else than just testing.
 *<p>
 *
 * The command-line arguments for this client are:
 * <pre>
 *    Usage: java TestingCentral [-e <endpoint>] [-u <uri>] [-debug]
 * </pre>
 * where <em>endpoint</em> is a URL of a Moby Central registry
 * (default value is taken from <tt>org.biomoby.client.CentralImpl.DEFAULT_ENDPOINT</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>).
 * With <em>-debug</em> the whole XML input that is being sent to the Moby Central 
 * registry is printed.
 *<p>
 *
 * @author <A HREF="mailto:senger@ebi.ac.uk">Martin Senger</A>
 * @version $Id: TestingCentral.java,v 1.11 2008/03/02 12:45:25 senger Exp $ */
public class TestingCentral {

    private String emailContact = "mail@mail.com";

    /*************************************************************************
     * Create a ServiceType object.
     *************************************************************************/
    protected MobyServiceType createServiceType (String serviceTypeName) {
	MobyServiceType stype = new MobyServiceType (serviceTypeName);
	stype.setDescription ("description for " + serviceTypeName);
	stype.setAuthority ("testing.org");
	stype.setEmailContact (emailContact);
	stype.addParentName ("Service");
	return stype;
    }

    /*************************************************************************
     * Create a Namespace object.
     *************************************************************************/
    protected MobyNamespace createNamespace (String namespaceName) {
	MobyNamespace namespace = new MobyNamespace (namespaceName);
	namespace.setDescription ("description for " + namespaceName);
	namespace.setAuthority ("testing.org");
	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 ("testing.org");
	data.setEmailContact (emailContact);
	return data;
    }

    /*************************************************************************
     * Create a Service object
     *************************************************************************/
    protected MobyService createService (String serviceName) {
	MobyService service = new MobyService (serviceName);
	service.setDescription ("description for service " + serviceName);
	service.setAuthority ("testing.org");
	service.setEmailContact (emailContact);
	service.setAuthoritative (true);
	service.setURL ("http://www.testing.org");
	return service;
    }

    /*************************************************************************
     * Create a SecondaryData object
     *************************************************************************/
    protected MobySecondaryData createSecondaryData (String objectName, String type) {
	MobySecondaryData data = new MobySecondaryData (objectName);
	try{
            data.setDataType (type);
        } catch(Exception e){
            e.printStackTrace(); // will default to String if unrecognized 
        }
	if (type.equalsIgnoreCase ("Integer")) {
	    data.setDefaultValue ("123");
	    data.setMaxValue     ("234");
	    data.setMinValue     ("23");
	    data.addAllowedValue ("30");
	    data.addAllowedValue ("40");
	    data.addAllowedValue ("50");
	} else if (type.equalsIgnoreCase ("String")) {
	    data.setDefaultValue ("nice default");
	    data.addAllowedValue ("Mark");
	    data.addAllowedValue ("Jason");
	    data.addAllowedValue ("Martin");
	}
	return data;
    }

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

	    // default values
 	    String endpoint = CentralImpl.DEFAULT_ENDPOINT;
	    String uri      = CentralImpl.DEFAULT_NAMESPACE;
            boolean debug = false;
	    boolean deregister = true;

	    // command-line parameters
	    int i = 0;
	    while (i < args.length) {
		if (args[i].equals ("-help") || args[i].equals ("-h")) {
		    System.out.println
			("Usage: java TestingCentral [-e <endpoint>] [-u <uri>] [-debug]");
		    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 ("-debug")) {
		    debug = true;
		    i += 1;
		    continue;
		}

		// this is intentionally undocumented option - because
		// if you use it you are polluting Moby Central with
		// fake objects - it's intented to be used for
		// debugging, and only for your local Moby Central
		// mirror
		if (args[i].equals ("-do-not-deregister")) {
		    deregister = false;
		    i += 1;
		    continue;
		}

		i++;
	    }

	    // create service proxy...
 	    TestingCentral helper = new TestingCentral();
	    Central worker = new CentralImpl (endpoint, uri);
	    worker.setDebug (debug);

	    // ...and call other methods:
	    
	    // retrieve things
	    try {
		start ("retrieveServiceNames");
		worker.getServiceNamesByAuthority();
		ok();
	    } catch (MobyException e) { error (e); }

	    try {
		start ("retrieveServiceProviders");
		worker.getProviders();
		ok();
	    } catch (MobyException e) {	error (e); }

	    try {
		start ("retrieveServiceTypes");
		worker.getServiceTypes();
		ok();
	    } catch (MobyException e) {	error (e); }

	    try {
		start ("retrieveNamespaces");
		worker.getFullNamespaces();
		ok();
	    } catch (MobyException e) {	error (e); }

 	    try {
		start ("retrieveObjectNames");
		worker.getDataTypeNames();
		ok();
	    } catch (MobyException e) {	error (e); }

	    // register service type
	    String uniqueName = "MyTestingServiceType_" + new Date().getTime();
	    MobyServiceType stype = helper.createServiceType (uniqueName);
 	    try {
		start ("registerServiceType");
		worker.registerServiceType (stype);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }

	    // register namespace(s)
	    MobyNamespace namespace1 = helper.createNamespace ("MyTestingNamespace_" + new Date().getTime() + 1);
	    MobyNamespace namespace2 = helper.createNamespace ("MyTestingNamespace_" + new Date().getTime() + 2);
 	    try {
		start ("registerNamespace - 1");
		worker.registerNamespace (namespace1);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }
 	    try {
		start ("registerNamespace - 2");
		worker.registerNamespace (namespace2);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }

	    // register data type(s)
	    String name1 = "MyTestingDataType_" + new Date().getTime() + 1;
	    String name2 = "MyTestingDataType_" + new Date().getTime() + 2;
	    String name3 = "MyTestingDataType_" + new Date().getTime() + 3;
	    MobyDataType data1 = helper.createDataType (name1);
	    MobyDataType data2 = helper.createDataType (name2);
	    MobyDataType data3 = helper.createDataType (name3);
 	    try {
		start ("registerDataType - 1");
		data1.addParentName ("Object");
		worker.registerDataType (data1);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }
 	    try {
		start ("registerDataType - 3");
 		data3.addParentName ("Object");
		worker.registerDataType (data3);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }
 	    try {
		start ("registerDataType - 2");
		data2.addParentName (data1.getName());
		data2.addChild ("len", "Integer", Central.iHASA);
		data2.addChild ("sub", "String", Central.iHAS);
		data2.addChild ("real_type", data3.getName(), Central.iHASA);
		worker.registerDataType (data2);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }

 	    try {
		start ("getDataTypeDefinition - 2");
		worker.getDataType (data2.getName());
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }

	    // register a service
	    MobyPrimaryDataSimple simpleData = new MobyPrimaryDataSimple ("Simple_A");
	    simpleData.setDataType (data2);
	    simpleData.addNamespace (namespace1);
	    simpleData.addNamespace (namespace2);

	    MobyPrimaryDataSimple simpleData1 = new MobyPrimaryDataSimple ("Simple_B");
	    simpleData1.setDataType (data1);
	    simpleData.addNamespace (namespace1);
	    MobyPrimaryDataSimple simpleData2 = new MobyPrimaryDataSimple ("Simple_C");
	    simpleData2.setDataType (data2);
	    simpleData.addNamespace (namespace1);
	    MobyPrimaryDataSimple simpleData3 = new MobyPrimaryDataSimple ("Simple_D");
	    simpleData3.setDataType (data3);
	    simpleData.addNamespace (namespace1);
	    MobyPrimaryDataSet collection = new MobyPrimaryDataSet ("Collection_A");
	    collection.addElement (simpleData1);
// 	    collection.addElement (simpleData2);
// 	    collection.addElement (simpleData3);

	    MobySecondaryData secData1 = helper.createSecondaryData ("Secondary_A", "Integer");
	    MobySecondaryData secData2 = helper.createSecondaryData ("Secondary_B", "String");
// 	    MobySecondaryData secData3 = helper.createSecondaryData ("Secondary_C", name3);
	    MobySecondaryData secData3 = helper.createSecondaryData ("Secondary_C", "DateTime");

	    MobyService service = helper.createService ("MyTestingService_" + new Date().getTime());
	    service.setType (stype.getName());
	    service.addInput (simpleData);
	    service.addInput (collection);
	    service.addInput (secData1);
	    service.addInput (secData2);
	    service.addInput (secData3);

 	    try {
		start ("registerService");
		worker.registerService (service);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }

	    // TBD: find service
	    // ..

	    if (! deregister)
		System.exit (0);

	    // deregister everything
 	    try {
		start ("deregisterService");
		worker.unregisterService (service);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }

 	    try {
		start ("deregisterDataType - 2");
		worker.unregisterDataType (data2);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }
 	    try {
		start ("deregisterDataType - 3");
		worker.unregisterDataType (data3);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }
 	    try {
		start ("deregisterDataType - 1");
		worker.unregisterDataType (data1);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }

 	    try {
		start ("deregisterNamespace - 2");
		worker.unregisterNamespace (namespace2);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }
 	    try {
		start ("deregisterNamespace - 1");
		worker.unregisterNamespace (namespace1);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }

 	    try {
		start ("deregisterServiceType");
		worker.unregisterServiceType (stype);
		ok();
	    } catch (MobyException e)      { error (e);
	    } catch (NoSuccessException e) { error (e); }



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

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

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

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