Commit 628ba59c authored by Piotr Gawron's avatar Piotr Gawron
Browse files

fix on chebi connector (new version is used that uses https instead of http)

parent 30641f7c
package lcsb.mapviewer.annotation.services.annotators;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
......@@ -7,6 +9,7 @@ import java.util.List;
import java.util.Queue;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.WebServiceException;
import org.apache.log4j.Logger;
......@@ -44,464 +47,466 @@ import uk.ac.ebi.chebi.webapps.chebiWS.model.StarsCategory;
*/
public class ChebiAnnotator extends ElementAnnotator implements IExternalService {
/**
* What is the maximum number of results that should be retrieved from chebi
* API.
*/
static final int MAX_SEARCH_RESULTS_FROM_CHEBI_API = 50;
/**
* Prefix used for entries identified by chebi id.
*/
public static final String ID_PREFIX = "id: ";
/**
* Prefix used for ontology list for single chebi id.
*/
static final String ONTOLOGY_PREFIX = "ontology: ";
/**
* Length of the prefix used for entries identified by chebi id.
*/
private static final int ID_PREFIX_LENGTH = ID_PREFIX.length();
/**
* Prefix used for entries identified by name.
*/
private static final String NAME_PREFIX = "name: ";
/**
* Length of the prefix used for entries identified by name.
*/
private static final int NAME_PREFIX_LENGTH = NAME_PREFIX.length();
/**
* Class used for some simple operations on {@link BioEntity} elements.
*/
private ElementUtils elementUtils = new ElementUtils();
@Override
public String refreshCacheQuery(Object query) throws SourceNotAvailable {
String result = null;
try {
if (query instanceof String) {
String name = (String) query;
if (name.startsWith(ID_PREFIX)) {
String id = name.substring(ID_PREFIX_LENGTH);
result = chebiSerializer.objectToString(getChebiElementForChebiId(new MiriamData(MiriamType.CHEBI, id)));
} else if (name.startsWith(ONTOLOGY_PREFIX)) {
String id = name.substring(ONTOLOGY_PREFIX.length());
result = miriamListToStringList(getOntologyChebiIdsForChebi(new MiriamData(MiriamType.CHEBI, id)));
} else if (name.startsWith(NAME_PREFIX)) {
name = name.substring(NAME_PREFIX_LENGTH);
MiriamData md = getChebiForChebiName(name);
if (md != null) {
result = md.getResource();
}
} else {
throw new InvalidArgumentException("Don't know what to do with string \"" + query + "\"");
}
} else {
throw new InvalidArgumentException("Don't know what to do with class: " + query.getClass());
}
} catch (ChebiSearchException e) {
throw new SourceNotAvailable(e);
}
return result;
}
/**
* Default class logger.
*/
private static Logger logger = Logger.getLogger(ChebiAnnotator.class);
/**
* Client to chebi API.
*/
private ChebiWebServiceClient client = null;
/**
* Object that allows to serialize {@link Chebi} elements into xml string and
* deserialize xml into {@link Chebi} objects.
*/
private XmlSerializer<Chebi> chebiSerializer;
/**
* Default constructor. Initializes structures used for transforming
* {@link Chebi} from/to xml.
*/
public ChebiAnnotator() {
super(ChebiAnnotator.class, new Class[] { Chemical.class }, true);
chebiSerializer = new XmlSerializer<>(Chebi.class);
}
/**
* Returns {@link MiriamData} for given chebi name.
*
* @param name
* name of the entry in chebi database.
* @return {@link MiriamData} entry for given chebi name
* @throws ChebiSearchException
* thrown when there is aproblem with accessing data from external
* chebi database
*/
public MiriamData getChebiForChebiName(String name) throws ChebiSearchException {
if (name == null) {
return null;
}
// Japanese people use strange dash symbol
name = name.replace("−", "-").toLowerCase().trim();
String id = getCacheValue("name: " + name);
if (id != null) {
return new MiriamData(MiriamType.CHEBI, id);
}
try {
ChebiWebServiceClient client = getClient();
LiteEntityList entities = client.getLiteEntity(name, SearchCategory.CHEBI_NAME, MAX_SEARCH_RESULTS_FROM_CHEBI_API, StarsCategory.ALL);
List<LiteEntity> resultList = entities.getListElement();
for (LiteEntity liteEntity : resultList) {
Entity entity = client.getCompleteEntity(liteEntity.getChebiId());
String chebiName = entity.getChebiAsciiName();
if (chebiName.trim().equalsIgnoreCase(name)) {
setCacheValue("name: " + name, entity.getChebiId());
return new MiriamData(MiriamType.CHEBI, entity.getChebiId());
}
for (DataItem dataItem : entity.getFormulae()) {
String synonym = dataItem.getData();
if (synonym.trim().equalsIgnoreCase(name)) {
setCacheValue("name: " + name, entity.getChebiId());
return new MiriamData(MiriamType.CHEBI, entity.getChebiId());
}
}
for (DataItem dataItem : entity.getSynonyms()) {
String synonym = dataItem.getData();
if (synonym.trim().equalsIgnoreCase(name)) {
setCacheValue("name: " + name, entity.getChebiId());
return new MiriamData(MiriamType.CHEBI, entity.getChebiId());
}
}
}
entities = client.getLiteEntity(name, SearchCategory.ALL, MAX_SEARCH_RESULTS_FROM_CHEBI_API, StarsCategory.ALL);
resultList = entities.getListElement();
for (LiteEntity liteEntity : resultList) {
Entity entity = client.getCompleteEntity(liteEntity.getChebiId());
for (DataItem dataItem : entity.getFormulae()) {
String formula = dataItem.getData();
if (formula.trim().equalsIgnoreCase(name)) {
setCacheValue("name: " + name, entity.getChebiId());
return new MiriamData(MiriamType.CHEBI, entity.getChebiId());
}
}
for (DataItem dataItem : entity.getSynonyms()) {
String synonym = dataItem.getData();
if (synonym.trim().equalsIgnoreCase(name)) {
setCacheValue("name: " + name, entity.getChebiId());
return new MiriamData(MiriamType.CHEBI, entity.getChebiId());
}
}
}
} catch (ChebiWebServiceFault_Exception e) {
throw new ChebiSearchException("Problem with chebi connection", e);
}
return null;
}
/**
* This method returns list of ChEBI identifiers that correspond to the whole
* chebi tree for a given chemical name.
*
* @param name
* - name of chemical
* @return - list of ChEBI identifiers
* @throws ChebiSearchException
* thrown when there is aproblem with accessing data from external
* chebi database
*/
public List<MiriamData> getOntologyChebiIdsForChebiName(String name) throws ChebiSearchException {
// Japanese people use strange dash symbol
name = name.replace("−", "-").toLowerCase().trim();
MiriamData md = getChebiForChebiName(name);
return getOntologyChebiIdsForChebi(md);
}
/**
* This method returns list of ChEBI identifiers that correspond to the whole
* chebi tree for a given chebi identifier.
*
* @param md
* - chebi identifier
* @return - list of ChEBI identifiers
* @throws ChebiSearchException
* thrown when there is a problemw ith accessing information from
* external chebi database
*/
public List<MiriamData> getOntologyChebiIdsForChebi(MiriamData md) throws ChebiSearchException {
if (md == null) {
return new ArrayList<>();
}
String query = ONTOLOGY_PREFIX + md.getResource();
String res = getCacheValue(query);
if (res != null) {
return chebiStringListToMiriam(res);
}
List<MiriamData> result = new ArrayList<MiriamData>();
try {
ChebiWebServiceClient client = getClient();
Set<String> children = new HashSet<String>();
children.add(md.getResource());
Queue<String> queue = new LinkedList<String>();
queue.add(md.getResource());
while (!queue.isEmpty()) {
String element = queue.poll();
result.add(new MiriamData(MiriamRelationType.BQ_BIOL_IS_DESCRIBED_BY, MiriamType.CHEBI, element));
Entity entity = client.getCompleteEntity(element);
for (OntologyDataItem di : entity.getOntologyChildren()) {
if (!children.contains(di.getChebiId()) && "is a".equals(di.getType())) {
children.add(di.getChebiId());
queue.add(di.getChebiId());
}
}
}
Set<String> parents = new HashSet<String>();
parents.add(md.getResource());
queue = new LinkedList<String>();
queue.add(md.getResource());
while (!queue.isEmpty()) {
String element = queue.poll();
Entity entity = client.getCompleteEntity(element);
for (OntologyDataItem di : entity.getOntologyParents()) {
if (!parents.contains(di.getChebiId()) && "is a".equals(di.getType())) {
result.add(new MiriamData(MiriamRelationType.BQ_BIOL_IS_DESCRIBED_BY, MiriamType.CHEBI, di.getChebiId()));
parents.add(di.getChebiId());
queue.add(di.getChebiId());
}
}
}
String value = miriamListToStringList(result);
setCacheValue(query, value);
} catch (ChebiWebServiceFault_Exception e) {
throw new ChebiSearchException("Problem with chebi", e);
}
return result;
}
/**
* Serialize list of chebi identifiers.
*
* @param list
* list of chebi identfiers
* @return string with identifiers
*/
private String miriamListToStringList(List<MiriamData> list) {
StringBuilder result = new StringBuilder("");
boolean first = true;
for (MiriamData miriamData : list) {
if (!first) {
result.append(",");
}
first = false;
result.append(miriamData.getResource());
}
return result.toString();
}
/**
* Deserialize list of chebi identifiers.
*
* @param res
* text with list of chebi identifeirs
* @return list with chebi identifiers
*/
private List<MiriamData> chebiStringListToMiriam(String res) {
String[] tmp = res.split(",");
List<MiriamData> result = new ArrayList<MiriamData>();
for (String string : tmp) {
result.add(new MiriamData(MiriamType.CHEBI, string));
}
return result;
}
/**
* This method returns ChEBI structure for identifier given as a parameter.
*
* @param md
* {@link MiriamData} with ChEBI identifier
* @return - ChEBI structure
* @throws ChebiSearchException
* thrown when there is a problemw ith accessing information from
* external chebi database
*/
public Chebi getChebiElementForChebiId(MiriamData md) throws ChebiSearchException {
if (!MiriamType.CHEBI.equals(md.getDataType())) {
throw new InvalidArgumentException(MiriamType.CHEBI + " expected");
}
String id = md.getResource().toLowerCase().trim();
if (!id.contains("chebi")) {
id = "chebi:" + id;
}
Chebi result = chebiSerializer.xmlToObject(getCacheNode("id: " + id));
if (result != null) {
return result;
}
try {
ChebiWebServiceClient client = getClient();
LiteEntityList entities = client.getLiteEntity(id, SearchCategory.CHEBI_ID, MAX_SEARCH_RESULTS_FROM_CHEBI_API, StarsCategory.ALL);
List<LiteEntity> resultList = entities.getListElement();
for (LiteEntity liteEntity : resultList) {
Entity entity = client.getCompleteEntity(liteEntity.getChebiId());
if (entity.getChebiId().trim().equalsIgnoreCase(id)) {
result = new Chebi(entity);
}
}
if (result != null) {
setCacheValue("id: " + id, chebiSerializer.objectToString(result));
}
return result;
} catch (ChebiWebServiceFault_Exception e) {
throw new ChebiSearchException("Problem with chebi", e);
}
}
/**
* This method returns common name for chemical identified by chebi id.
*
* @param id
* - chebi identifier in format (XXXXX represents numerical
* identifier): "CHEBI:XXXXX" or "XXXXX"
* @return common name of chemical
* @throws ChebiSearchException
* thrown when there is a problemw ith accessing information from
* external chebi database
*/
protected String getChebiNameForChebiId(MiriamData id) throws ChebiSearchException {
if (id == null) {
return null;
}
Chebi chebi = getChebiElementForChebiId(id);
if (chebi == null) {
return null;
}
return chebi.getName();
}
@Override
public ExternalServiceStatus getServiceStatus() {
ExternalServiceStatus status = new ExternalServiceStatus(getCommonName(), getUrl());
GeneralCacheInterface cacheCopy = getCache();
this.setCache(null);
try {
MiriamData data = getChebiForChebiName("water");
status.setStatus(ExternalServiceStatusType.OK);
if (data == null || !data.getResource().equals("CHEBI:15377")) {
status.setStatus(ExternalServiceStatusType.CHANGED);
}
} catch (Exception e) {
logger.error(status.getName() + " is down", e);
status.setStatus(ExternalServiceStatusType.DOWN);
}
this.setCache(cacheCopy);
return status;
}
/**
*
* @return {@link #client}
* @throws ChebiSearchException
* thrown when there is a problemw ith accessing information from
* external chebi database
*/
private ChebiWebServiceClient getClient() throws ChebiSearchException {
if (client == null) {
try {
client = new ChebiWebServiceClient();
} catch (WebServiceException exception) {
throw new ChebiSearchException("Cannot initialize chebi connector", exception);
}
}
return client;
}
@Override
public void annotateElement(BioEntity element) throws AnnotatorException {
if (isAnnotatable(element)) {
try {
String warnPrefix = elementUtils.getElementTag(element, this);
if (element.getMiriamData().size() == 0) {
MiriamData chebi = getChebiForChebiName(element.getName());
if (chebi != null) {
element.addMiriamData(chebi);
} else {
logger.warn(warnPrefix + "Chemical name cannot be found in chebi: " + element.getName());
}
}
Chebi chebi = null;
for (MiriamData md : element.getMiriamData()) {
if (MiriamType.CHEBI.equals(md.getDataType())) {
chebi = getChebiElementForChebiId(md);
}
}
Chemical species = (Chemical) element;
if (chebi != null) {
super.setFullName(species, chebi.getName(), warnPrefix);
setInchi(species, chebi.getInchi(), warnPrefix);
setInchiKey(species, chebi.getInchiKey(), warnPrefix);
setSmile(species, chebi.getSmiles(), warnPrefix);
if (species.getSynonyms().size() == 0) {
species.addSynonyms(chebi.getSynonyms());
} else {
StringSetComparator stringSetComparator = new StringSetComparator();
Set<String> set1 = new HashSet<String>();
Set<String> set2 = new HashSet<String>();
set1.addAll(species.getSynonyms());
set2.addAll(chebi.getSynonyms());
if (stringSetComparator.compare(set1, set2) != 0) {
logger.warn(warnPrefix + "Different set of synonyms: " + species.getFullName() + ", " + chebi.getName());
}
}
}
} catch (ChebiSearchException e) {
throw new AnnotatorException("Problem with getting information about chebi", e);
}
}
}
@Override
public String getCommonName() {
return MiriamType.CHEBI.getCommonName();
}
@Override
public String getUrl() {
return MiriamType.CHEBI.getDbHomepage();
}
/**
* @param client
* the client to set
* @see #client
*/
void setClient(ChebiWebServiceClient client) {
this.client = client;
}
/**
* What is the maximum number of results that should be retrieved from chebi
* API.
*/
static final int MAX_SEARCH_RESULTS_FROM_CHEBI_API = 50;
/**
* Prefix used for entries identified by chebi id.
*/
public static final String ID_PREFIX = "id: ";
/**
* Prefix used for ontology list for single chebi id.
*/
static final String ONTOLOGY_PREFIX = "ontology: ";
/**
* Length of the prefix used for entries identified by chebi id.
*/
private static final int ID_PREFIX_LENGTH = ID_PREFIX.length();
/**
* Prefix used for entries identified by name.
*/
private static final String NAME_PREFIX = "name: ";
/**
* Length of the prefix used for entries identified by name.
*/
private static final int NAME_PREFIX_LENGTH = NAME_PREFIX.length();
/**
* Class used for some simple operations on {@link BioEntity} elements.
*/
private ElementUtils elementUtils = new ElementUtils();
@Override
public String refreshCacheQuery(Object query) throws SourceNotAvailable {
String result = null;
try {
if (query instanceof String) {
String name = (String) query;
if (name.startsWith(ID_PREFIX)) {
String id = name.substring(ID_PREFIX_LENGTH);
result = chebiSerializer.objectToString(getChebiElementForChebiId(new MiriamData(MiriamType.CHEBI, id)));
} else if (name.startsWith(ONTOLOGY_PREFIX)) {
String id = name.substring(ONTOLOGY_PREFIX.length());
result = miriamListToStringList(getOntologyChebiIdsForChebi(new MiriamData(MiriamType.CHEBI, id)));
} else if (name.startsWith(NAME_PREFIX)) {
name = name.substring(NAME_PREFIX_LENGTH);
MiriamData md = getChebiForChebiName(name);
if (md != null) {
result = md.getResource();
}
} else {
throw new InvalidArgumentException("Don't know what to do with string \"" + query + "\"");
}
} else {
throw new InvalidArgumentException("Don't know what to do with class: " + query.getClass());
}
} catch (ChebiSearchException e) {
throw new SourceNotAvailable(e);
}
return result;
}
/**
* Default class logger.
*/
private static Logger logger = Logger.getLogger(ChebiAnnotator.class);
/**
* Client to chebi API.
*/
private ChebiWebServiceClient client = null;
/**
* Object that allows to serialize {@link Chebi} elements into xml string and
* deserialize xml into {@link Chebi} objects.
*/
private XmlSerializer<Chebi> chebiSerializer;
/**
* Default constructor. Initializes structures used for transforming
* {@link Chebi} from/to xml.
*/
public ChebiAnnotator() {