import uk.ac.ebi.ook.web.services.Query;
import uk.ac.ebi.ook.web.services.QueryService;
import uk.ac.ebi.ook.web.services.QueryServiceLocator;

import java.io.*;
import java.net.*;
import java.util.Iterator;
import java.util.List;

import iotools.*;

import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;

import ajaxGO.*;

/********************************************************
 * retrieve all terms from GO given by accession #s
 *******************************************************/

public class GO
{
  public GO() {}

  public void getTerms()
  {
    try
    {
      Configuration config = new Configuration();

      QueryService locator = new QueryServiceLocator();
      Query             qs = locator.getOntologyQuery();
      String search_base   = "http://www.ebi.ac.uk/ontology-lookup/ajax.view?";

      // ------------------------------------------------------------
      // --- INPUT: a file of GO IDs for terms to be fetched
      // ------------------------------------------------------------
      String     go_id_file = config.path() + "\\input\\" + config.input_GO();
      EasyReader go_id_in   = new EasyReader(go_id_file);

      // ------------------------------------------------------------
      // --- OUTPUT: a file of GO IDs mapped to their terms
      // ------------------------------------------------------------

      String     GO_term_file = config.path() + "\\output\\" + config.output_GO();
      FileWriter GO_term_out  = new FileWriter(GO_term_file);

      while (!go_id_in.eof())
      {
        // --- read a GO accession number
        String go_id = go_id_in.readString();

        // --- formulate a query for the given GO accession number
        String url = search_base + "q=termmetadata&termid=" + go_id;

        // --- launch the GO query
        URLConnection uc = new URL(url).openConnection();
        HttpURLConnection connection = (HttpURLConnection) uc;
        connection.setDoOutput(true);
        connection.setRequestMethod("GET");
        connection.connect();

        // --- fetch the query result
        String line;
        String result = "";
        InputStream inputStream = null;
        inputStream = connection.getInputStream();

        // --- write the query result into an XML file
        String     ajaxGO_file = config.path() + "\\tmp\\" + config.tmp_GO();
        FileWriter ajaxGO_out  = new FileWriter(ajaxGO_file);

        BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
        while ((line = rd.readLine()) != null) result += line;

        ajaxGO_out.write(result);
        ajaxGO_out.close();

        // --- read the GO query result saved in the following XML format:

        // ---------------------------------------------------------------------------
        // <ajax-response>
        //   <response>
        //     <item>
        //       <name>...</name>
        //       <value>...</value>
        //     </item>
        //   <response>
        //   ...
        // </ajax-response>
        // ---------------------------------------------------------------------------

        // --- prepare for XML unmarshalling
        JAXBContext jc;            // --- JAXBContext object to provide entry point to JAXB API
        Unmarshaller unmarshaller; // --- Unmarshaller object to control the process of unmarshalling

        jc = JAXBContext.newInstance("ajaxGO");
        unmarshaller = jc.createUnmarshaller();

        ajaxGO.AjaxResponse ajax_response = (ajaxGO.AjaxResponse) unmarshaller.unmarshal(new File(ajaxGO_file));
        List responseList = ajax_response.getResponse();

        // --- for all responses ---
        for(Iterator iter = responseList.iterator(); iter.hasNext(); )
        {
          AjaxResponse.Response responseElement = (AjaxResponse.Response) iter.next();
          List itemList = responseElement.getItem();

          // --- for all items ---
          for(Iterator i = itemList.iterator(); i.hasNext(); )
          {
            AjaxResponse.Response.Item itemElement = (AjaxResponse.Response.Item) i.next();

            String name = itemElement.getName();

            // --- check if the current metadata item holds a synonym
            if (name.compareTo("exact synonym") * name.compareTo("preferred name") == 0)
            {
              String id2term = go_id + "\t" + itemElement.getValue() + "\n";
              System.out.print(id2term);
              GO_term_out.write(id2term);
            }
          }
        } 

      } // --- end of: while (!go_id_in.eof())

      // --- close the input/output files
      go_id_in.close();
      GO_term_out.close();

    }
    catch (Exception e) {e.printStackTrace();}
  }
}

