// MobyNamespace.java
//    A container for a definition of namespace.
//
//    senger@ebi.ac.uk
//    February 2003
//

package org.biomoby.shared;

import org.biomoby.client.CentralImpl;
import org.biomoby.client.util.SplashScreenStatus;

import org.biomoby.registry.meta.Registry;

import java.util.*;
import java.util.logging.*;
import java.net.URL;

/**
 * A container representing a namespace used in the Moby registry.
 *<p>
 *
 * This container is used mainly to register a new namespace in a
 * Moby registry.
 *<p>
 *
 * @author <A HREF="mailto:senger@ebi.ac.uk">Martin Senger</A>
 * @version $Id: MobyNamespace.java,v 1.14 2010/05/13 15:54:16 gordonp Exp $
 */

public class MobyNamespace implements Comparable<MobyNamespace>, LSIDAccessible {

    protected String name;
    protected String authority = "";
    protected String emailContact = "";
    protected String description = "";
    protected String lsid = null;
    protected String id = null;
    protected Registry registry; //provenance of the namspace definition

    private static Logger logger = Logger.getLogger("org.biomoby.shared.MobyNamespace");
    private static Map<String,MobyNamespace[]> namespacesMapByURL = new HashMap<String,MobyNamespace[]>();

    /**************************************************************************
     * Default constructor. Other characteristics are empty - which is usually
     * wrong - therefore use 'set' method to fill them.
     *************************************************************************/
    public MobyNamespace (String name) {
	this.name = name;
    }

    public Registry getRegistry(){
	return registry;
    }

    public void setRegistry(Registry reg){
	reg = registry;
    }
 
    public static MobyNamespace getNamespace(String ns){
	return getNamespace(ns, null);
    }

    public static MobyNamespace getNamespace(String ns, Registry reg){
	if(ns == null){
	    return null;
	}
	
	MobyNamespace[] namespaces = null;

	// This method has not been called yet in the JVM, populate the namespaces, 
	// ensuring concurrent calls don't collide
	synchronized(namespacesMapByURL){
	    namespaces = namespacesMapByURL.get(reg == null ? "" : reg.getEndpoint());
	    if(namespaces == null){
		Central central = null;
		SplashScreenStatus.setStatus("Setting Moby Central registry");
		try{
		    central = CentralImpl.getDefaultCentral(reg);
		} catch(MobyException e){
		    logger.log(Level.WARNING,
			       "Cannot find a default Moby Central implementation",
			       e);
		    return null;
		}
		try{
		    SplashScreenStatus.setStatus("Loading Moby Central namespaces");
		    namespaces = central.getFullNamespaces();
		    namespacesMapByURL.put(reg == null ? "" : reg.getEndpoint(), 
					   namespaces);
		}
		catch(Exception e){
		    logger.log(Level.WARNING,
			       "Cannot parse MOBY Namespace Ontology: " + e);
		    e.printStackTrace();
		    return null;
		}
	    }
	}

	// Perform a linear search for the corresponding datatype to the given name or LSID.
	for(int i = 0; i < namespaces.length; i++){
	    String ns_name = namespaces[i].getName();
	    String ns_lsid = namespaces[i].getLSID();
	    if((ns_name != null && ns_name.equals(ns)) ||
	       (ns_lsid != null && ns_lsid.equals(ns))){
		return namespaces[i];
	    }
	}

	// Wasn't found if we got to here
	return null;
    }

    public String getName() {
	return name;
    }

    public String getId() {
	return id;
    }
    public void setId (String value) {
	id = value;
    }

    public String getAuthority() {
	return authority;
    }
    public void setAuthority (String value) {
	authority = (value == null ? "" : value);
    }

    public String getEmailContact() {
	return emailContact;
    }
    public void setEmailContact (String value) {
	emailContact = (value == null ? "" : value);
    }

    public String getLSID() {
 	return lsid;
    }
    public void setLSID (String value) {
	lsid = value;
    }

    public String getDescription() {
	return description;
    }
    public void setDescription (String value) {
	description = (value == null ? "" : value);
    }

    public String toString() {
	StringBuffer buf = new StringBuffer();
	buf.append ("Name:    " + name + "\n");
	buf.append ("Auth:    " + authority + "\n");
	buf.append ("Desc:    " + description + "\n");
	buf.append ("ID:      " + id + "\n");
	return new String (buf);
    }
    public String format (int indent) {
	return Utils.format (this, indent);
    }

    public int compareTo (MobyNamespace obj) {
	return name.compareToIgnoreCase ( obj.getName() );
    }

    public boolean equals(Object o){
	if(o == null){
	    return false;
	}

	// Do not compare apples to oranges
	if(!(o instanceof MobyNamespace)){
	    return false;
	}
	MobyNamespace other = (MobyNamespace) o;
	// The Same Object
	return other == this || (
	    // Or all the same fields
	    (name == null && other.name == null || name.equals(other.name)) &&
	    (authority == null && other.authority == null || authority.equals(other.authority)) &&
	    (emailContact == null && other.emailContact == null || emailContact.equals(other.emailContact)) &&
	    (description == null && other.description == null || description.equals(other.description)) &&
	    (id == null && other.id == null || id.equals(other.id)));
    }

    public static Comparator getAuthorityComparator() {
 	return new Comparator() {
 		public int compare (Object o1, Object o2) {
 		    String a1 = ((MobyNamespace)o1).getAuthority();
 		    String a2 = ((MobyNamespace)o2).getAuthority();
 		    return (a1).compareToIgnoreCase ((String)a2);
 		}
 	    };
    }
}
