package org.isatools.isacreator.ontologymanager.bioportal.jsonresulthandlers; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import net.minidev.json.JSONValue; import org.apache.commons.collections15.map.ListOrderedMap; import org.apache.commons.httpclient.HostConfiguration; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.lang.StringUtils; import org.isatools.isacreator.configuration.Ontology; import org.isatools.isacreator.ontologymanager.BioPortal4Client; import org.isatools.isacreator.ontologymanager.OntologyManager; import org.isatools.isacreator.ontologymanager.OntologySourceRefObject; import org.isatools.isacreator.ontologymanager.bioportal.io.AcceptedOntologies; import org.isatools.isacreator.ontologymanager.common.OntologyTerm; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class BioPortalSearchResultHandler { public static final String API_KEY = "fd88ee35-6995-475d-b15a-85f1b9dd7a42"; public static final String PARENTS = "ancestors"; public static final String CHILDREN = "children"; public Map<String, List<OntologyTerm>> getSearchResults(String term, String ontologyIds, String subtree) { return getSearchResults(term, ontologyIds, subtree, false); } /** * Returns the result of the search operation * * @param term - the string being searched for * @param ontologyIds - the ontologies the search is being restricted to * @param @nullable subtree - a subtree, if any to be searched under (optional) * @return - Map from the id of the ontology to the list of terms found under it. */ public Map<String, List<OntologyTerm>> getSearchResults(String term, String ontologyIds, String subtree, boolean exactMatch) { // map from ontology id to the list of terms found for that id. Map<String, List<OntologyTerm>> result = new HashMap<String, List<OntologyTerm>>(); String content = querySearchEndpoint(term, ontologyIds, subtree, exactMatch); JSONObject obj = (JSONObject) JSONValue.parse(content); JSONArray results = (JSONArray) obj.get("collection"); if (results == null) return result; for (Object result1 : results) { JSONObject resultItem = (JSONObject) result1; String ontologyId = extractOntologyId(resultItem); if (!result.containsKey(ontologyId)) { result.put(ontologyId, new ArrayList<OntologyTerm>()); } OntologyTerm ontologyTerm = createOntologyTerm(resultItem); result.get(ontologyId).add(ontologyTerm); } return result; } private String extractOntologyId(JSONObject ontologyItemJsonDictionary) { JSONObject links = (JSONObject) ontologyItemJsonDictionary.get("links"); return links.get("ontology").toString(); } private void extractDefinitionFromOntologyTerm(JSONObject ontologyItemJsonDictionary, OntologyTerm ontologyTerm) { JSONArray definitions = (JSONArray) ontologyItemJsonDictionary.get("definition"); if (definitions != null && definitions.size() > 0) { ontologyTerm.addToComments("definition", definitions.get(0).toString()); } } private void extractSynonymsFromOntologyTerm(JSONObject ontologyItemJsonDictionary, OntologyTerm ontologyTerm) { JSONArray synonyms = (JSONArray) ontologyItemJsonDictionary.get("synonyms"); if (synonyms != null && synonyms.size() > 0) { StringBuilder synonymList = new StringBuilder(); int count = 0; for (Object value : synonyms) { synonymList.append(value.toString()); if (count != synonyms.size() - 1) { synonymList.append(","); } count++; } ontologyTerm.addToComments("synonyms", synonymList.toString()); } } private String querySearchEndpoint(String term, String ontologyIds, String subtree, boolean exactMatch) { try { HttpClient client = new HttpClient(); PostMethod method = new PostMethod(BioPortal4Client.REST_URL + "search"); // Configure the form parameters method.addParameter("q", term); if (StringUtils.trimToNull(subtree) != null) { method.addParameter("subtree", subtree); if (ontologyIds != null) method.addParameter("ontology", ontologyIds); } else if (!ontologyIds.equals("all")) { method.addParameter("ontologies", ontologyIds); } method.addParameter("apikey", API_KEY); method.addParameter("pagesize", "100"); method.addParameter("no_context", "true"); if (exactMatch) { method.addParameter("exact_match", "true"); } try { setHostConfiguration(client); } catch (Exception e) { System.err.println("Problem encountered setting host configuration for search"); } long startTime = System.currentTimeMillis(); int statusCode = client.executeMethod(method); if (statusCode != -1) { System.out.println("It took " + (System.currentTimeMillis() - startTime) + "ms to do that query..."); String contents = method.getResponseBodyAsString(); method.releaseConnection(); return contents; } } catch (Exception e) { e.printStackTrace(); } return null; } public Map<String, Ontology> getAllOntologies() { Map<String, Ontology> result = new HashMap<String, Ontology>(); String content = queryOntologyEndpoint(); JSONArray obj = (JSONArray) JSONValue.parse(content); for (Object resultItem : obj) { addOntology(result, (JSONObject) resultItem); } return result; } private void addOntology(Map<String, Ontology> result, JSONObject resultItem) { JSONObject ontology = (JSONObject) resultItem.get("ontology"); boolean summaryOnly = Boolean.valueOf(ontology.get("summaryOnly") != null ? ontology.get("summaryOnly").toString() : "false"); if (!summaryOnly) { Ontology newOntology = new Ontology(ontology.get("@id").toString(), "version", ontology.get("acronym").toString(), ontology.get("name").toString()); if (!newOntology.getOntologyAbbreviation().contains("test") && !newOntology.getOntologyDisplayLabel().contains("test")) { String version = resultItem.get("version") != null ? resultItem.get("version").toString() : ""; String submissionId = resultItem.get("submissionId") != null ? resultItem.get("submissionId").toString() : ""; String homepage = resultItem.get("homepage") != null ? resultItem.get("homepage").toString() : ""; newOntology.setHomePage(homepage); newOntology.setOntologyVersion(version); newOntology.setSubmissionId(submissionId); result.put(resultItem.get("@id").toString(), newOntology); } } } public String queryOntologyEndpoint() { try { HttpClient client = new HttpClient(); //http://data.bioontology.org/submissions GetMethod method = new GetMethod(BioPortal4Client.REST_URL + "submissions?apikey=" + API_KEY); try { setHostConfiguration(client); } catch (Exception e) { System.err.println("Problem encountered setting host configuration for ontology search"); } int statusCode = client.executeMethod(method); if (statusCode != -1) { String contents = method.getResponseBodyAsString(); method.releaseConnection(); return contents; } } catch (Exception e) { e.printStackTrace(); } return null; } private void setHostConfiguration(HttpClient client) { HostConfiguration configuration = new HostConfiguration(); configuration.setHost("http://data.bioontology.org"); String proxyPort = System.getProperty("http.proxyPort"); if (proxyPort == null) return; configuration.setProxy(System.getProperty("http.proxyHost"), Integer.valueOf(System.getProperty("http.proxyPort"))); client.setHostConfiguration(configuration); } public OntologyTerm getTermMetadata(String termId, String ontologyId) { String content = queryTermMetadataEndpoint(termId, ontologyId); JSONObject obj = (JSONObject) JSONValue.parse(content); // if we have a nice error free page, continue if (!obj.containsKey("errors")) { OntologySourceRefObject osro = getOntologySourceRefObject(ontologyId); OntologyTerm ontologyTerm = new OntologyTerm( obj.get("prefLabel").toString(), obj.get("@id").toString(), obj.get("@id").toString(), osro); ontologyTerm.addToComments("Service Provider", OntologyManager.BIO_PORTAL); extractDefinitionFromOntologyTerm(obj, ontologyTerm); extractSynonymsFromOntologyTerm(obj, ontologyTerm); System.out.println(ontologyTerm.getOntologyTermName() + " - " + ontologyTerm.getOntologyTermAccession() + " - " + ontologyTerm.getOntologyTermURI()); return ontologyTerm; } else { return null; } } private OntologySourceRefObject getOntologySourceRefObject(String ontologyId) { Ontology associatedOntologySource = AcceptedOntologies.getAcceptedOntologies().get(ontologyId); return new OntologySourceRefObject(associatedOntologySource.getOntologyAbbreviation(), associatedOntologySource.getOntologyID(), associatedOntologySource.getOntologyVersion(), associatedOntologySource.getOntologyDisplayLabel()); } public String queryTermMetadataEndpoint(String termId, String ontologyURI) { try { HttpClient client = new HttpClient(); String url = ontologyURI + "/classes/" + URLEncoder.encode(termId, "UTF-8") + "?apikey=" + API_KEY; GetMethod method = new GetMethod(url); System.out.println(method.getURI().toString()); try { setHostConfiguration(client); } catch (Exception e) { System.err.println("Problem encountered setting host configuration for ontology search"); } int statusCode = client.executeMethod(method); if (statusCode != -1) { String contents = method.getResponseBodyAsString(); System.out.println(contents); method.releaseConnection(); return contents; } } catch (Exception e) { System.err.println("Unable to retrieve term metadata"); } return null; } public Map<String, OntologyTerm> getOntologyRoots(String ontologyAbbreviation) { Map<String, OntologyTerm> roots = new HashMap<String, OntologyTerm>(); String queryContents = generalQueryEndpoint(BioPortal4Client.REST_URL + "ontologies/" + ontologyAbbreviation + "/classes/roots?apikey=" + API_KEY); System.out.println(BioPortal4Client.REST_URL + "ontologies/" + ontologyAbbreviation + "/classes/roots?apikey=" + API_KEY); JSONArray ontologyTerms = (JSONArray) JSONValue.parse(queryContents); for (Object annotationItem : ontologyTerms) { JSONObject annotationObject = (JSONObject) annotationItem; OntologySourceRefObject osro = getOntologySourceRefObject(extractOntologyId(annotationObject)); OntologyTerm ontologyTerm = createOntologyTerm(annotationObject); ontologyTerm.setOntologySourceInformation(osro); roots.put(ontologyTerm.getOntologyTermAccession(), ontologyTerm); } return roots; } private OntologyTerm createOntologyTerm(JSONObject annotationItem) { OntologyTerm ontologyTerm = new OntologyTerm(annotationItem.get("prefLabel").toString(), annotationItem.get("@id").toString(), annotationItem.get("@id").toString(), null); ontologyTerm.addToComments("Service Provider", OntologyManager.BIO_PORTAL); extractDefinitionFromOntologyTerm(annotationItem, ontologyTerm); extractSynonymsFromOntologyTerm(annotationItem, ontologyTerm); String ontologyId = extractOntologyId(annotationItem); if (ontologyId != null) { String ontologyAbbreviation = ontologyId.substring(ontologyId.lastIndexOf('/') + 1); OntologySourceRefObject sourceRefObject = OntologyManager.getOntologySourceReferenceObjectByAbbreviation(ontologyAbbreviation); if (sourceRefObject != null) ontologyTerm.setOntologySourceInformation(sourceRefObject); } return ontologyTerm; } /** * @param url * @return */ private String generalQueryEndpoint(String url) { try { HttpClient client = new HttpClient(); GetMethod method = new GetMethod(url); try { setHostConfiguration(client); } catch (Exception e) { System.err.println("Problem encountered setting host configuration for ontology search"); } int statusCode = client.executeMethod(method); if (statusCode != -1) { String contents = method.getResponseBodyAsString(); method.releaseConnection(); return contents; } } catch (Exception e) { e.printStackTrace(); } return null; } public Map<String, OntologyTerm> getTermParents(String termAccession, String ontologyAbbreviation) { return getTermChildrenOrParents(termAccession, ontologyAbbreviation, PARENTS); } public Map<String, OntologyTerm> getTermChildren(String termAccession, String ontologyAbbreviation) { return getTermChildrenOrParents(termAccession, ontologyAbbreviation, CHILDREN); } /** * Will make a call to get the parents or children of a term, identified by its termAccession in a particular * ontology, defined by the ontologyAbbreviation. * * @param termAccession - e.g. http://purl.obolibrary.org/obo/OBI_0000785 * @param ontologyAbbreviation - e.g. EFO * @param parentsOrChildren - 'parents' or 'children' as an input value * @return Map from the ontology term id to its OntologyTerm object. */ public Map<String, OntologyTerm> getTermChildrenOrParents(String termAccession, String ontologyAbbreviation, String parentsOrChildren) { try { Map<String, OntologyTerm> parents = new ListOrderedMap<String, OntologyTerm>(); String queryContents = generalQueryEndpoint(BioPortal4Client.REST_URL + "ontologies/" + ontologyAbbreviation + "/classes/" + URLEncoder.encode(termAccession, "UTF-8") + "/" + parentsOrChildren + "?apikey=" + API_KEY); Object obj = JSONValue.parse(queryContents); JSONArray rootArray; if (obj instanceof JSONObject) { // the children result returns a dictionary, or JsonStructure, so we have to go down one level to get // the collection of results. rootArray = (JSONArray) ((JSONObject) obj).get("collection"); } else { // the parents result returns an array directly, so we can just use it immediately. rootArray = (JSONArray) obj; } for (Object arrayValue: rootArray) { JSONObject annotationItem = (JSONObject) arrayValue; OntologySourceRefObject osro = getOntologySourceRefObject(extractOntologyId(annotationItem)); OntologyTerm ontologyTerm = createOntologyTerm(annotationItem); ontologyTerm.setOntologySourceInformation(osro); parents.put(ontologyTerm.getOntologyTermAccession(), ontologyTerm); } return parents; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } }