package org.biomoby.shared.parser;

import org.biomoby.shared.data.MobyProvisionInfo;

import org.jdom.Element;
import org.jdom.Namespace;

import java.util.Iterator;
import java.util.Vector;

public class JDOMUtils{
    /**************************************************************************
     *
     *************************************************************************/
    public static Element toXMLElement(ServiceException se) {
	Element elem = MobyPackage.getXMLElement (MobyTags.MOBYEXCEPTION);
	MobyPackage.setXMLAttribute (elem, MobyTags.SEVERITY, se.getSeverityAsString());
	if (se.getJobId() != null)
	    MobyPackage.setXMLAttribute (elem, MobyTags.REFQUERYID, se.getJobId());
	if (se.getDataName() != null)
	    MobyPackage.setXMLAttribute (elem, MobyTags.REFELEMENT, se.getDataName());
	Element elemCode = MobyPackage.getXMLElement (MobyTags.EXCEPTIONCODE);
	elemCode.setText (""+se.getErrorCode());
	elem.addContent (elemCode);
	String desc = se.getMessage();
	if (desc != null) {
	    Element elemDesc = MobyPackage.getXMLElement (MobyTags.EXCEPTIONMESSAGE);
	    elemDesc.setText (desc);
	    elem.addContent (elemDesc);
	}
	return elem;
    }

    /**************************************************************************
     * Extract all exceptions from a <em>serviceNotes</em> XML
     * element. This is a convenient method that can be used when
     * dealing with an XML response from a service without parsing the
     * whole response to a {@link MobyPackage}. <p>
     *
     * @param serviceNotes a piece of XML
     * <tt>&lt;serviceNotes&gt;...&lt;/serviceNotes&gt;</tt>
     *
     * @return an array, potentially an empty array, of all exceptions
     * extracted from the 'serviceNotes'
     *************************************************************************/
    public static ServiceException[] extractExceptions (Element serviceNotes) {
	if (serviceNotes == null)
	    return new ServiceException[] {};

	Vector v = new Vector();
	for (Iterator it =
		 serviceNotes.getChildren (MobyTags.MOBYEXCEPTION).iterator();
	     it.hasNext(); ) {
	    ServiceException ex = extractException ((Element)it.next());
	    if (ex != null)
		v.addElement (ex);
	}
	for (Iterator it =
		 serviceNotes.getChildren (MobyTags.MOBYEXCEPTION, JDOMUtils.MOBY_NS).iterator();
	     it.hasNext(); ) {
	    ServiceException ex = extractException ((Element)it.next());
	    if (ex != null)
		v.addElement (ex);
	}
	ServiceException[] result = new ServiceException [v.size()];
	v.copyInto (result);
	return result;
    }

    /**************************************************************************
     * Extract one exception from an XML element 'mobyException'.
     *************************************************************************/
    protected static ServiceException extractException (Element elem) {
	ServiceException ex = new ServiceException();
	String severity = elem.getAttributeValue (MobyTags.SEVERITY);
	if (severity == null)
	    severity = elem.getAttributeValue (MobyTags.SEVERITY, JDOMUtils.MOBY_NS);
	ex.setSeverity (severity);
	String codeStr = JDOMUtils.getChildText (elem, MobyTags.EXCEPTIONCODE);
	try {
	    ex.setErrorCode (new Integer (codeStr).intValue());
	} catch (Exception e) {
	}
	ex.setMessage (JDOMUtils.getChildText (elem, MobyTags.EXCEPTIONMESSAGE));
	return ex;
    }

    /**************************************************************************
     * Turns a PIB Object into a JDOM representation.
     *************************************************************************/
    public static Element toXMLElement(MobyProvisionInfo mpi) {
	Element provision = MobyPackage.getXMLElement (MobyTags.PROVISIONINFORMATION);

	Element software = MobyPackage.getXMLElement (MobyTags.SERVICESOFTWARE);
	MobyPackage.setXMLAttribute (software, MobyTags.SOFTWARENAME, mpi.getSoftwareName());
	MobyPackage.setXMLAttribute (software, MobyTags.SOFTWAREVERSION, mpi.getSoftwareVersion());
	MobyPackage.setXMLAttribute (software, MobyTags.SOFTWARECOMMENT, mpi.getSoftwareComment());
	provision.addContent (software);

	Element db = MobyPackage.getXMLElement (MobyTags.SERVICEDATABASE);
	MobyPackage.setXMLAttribute (db, MobyTags.DATABASENAME, mpi.getDBName());
	MobyPackage.setXMLAttribute (db, MobyTags.DATABASEVERSION, mpi.getDBVersion());
	MobyPackage.setXMLAttribute (db, MobyTags.DATABASECOMMENT, mpi.getDBComment());
	provision.addContent (db);

	if (mpi.getComment() != null) {
            Element comment = MobyPackage.getXMLElement (MobyTags.SERVICECOMMENT);
            comment.setText (mpi.getComment());
            provision.addContent (comment);
	}

	return provision;
    }


    /**************************************************************************
     * Get a child by 'name' from 'parent'. It tries first a child
     * withnout any namespace, then with {@link #MOBY_NS}. <p>
     *
     * @param parent whose child is returned
     * @param name child name
     * @return a child element, or null
     *************************************************************************/
    public static Element getChild (Element parent, String name) {
	if (parent == null) return null;
	Element child = parent.getChild (name);
	if (child == null)
	    child = parent.getChild (name, MOBY_NS);
	return child;
    }

    /**************************************************************************
     * Get text of a child 'name' from 'parent'. It tries first a
     * child withnout any namespace, then with {@link #MOBY_NS}. <p>
     *
     * @param parent whose child's text is returned
     * @param name child name
     * @return a text from named child, or null
     *************************************************************************/
    public static String getChildText (Element parent, String name) {
	Element child = getChild (parent, name);
	if (child == null) return null;
	return child.getText();
    }

    /**************************************************************************
     * A Biomoby namespace.
     *************************************************************************/
    public static final Namespace MOBY_NS =
	Namespace.getNamespace (MobyTags.MOBY_XML_NS_PREFIX,
				MobyTags.MOBY_XML_NS);
    

}
