diff --git a/jami-batch/pom.xml b/jami-batch/pom.xml index a6ad9a4de1..b4b43bdc82 100644 --- a/jami-batch/pom.xml +++ b/jami-batch/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-batch diff --git a/jami-bridges/bridges-core/pom.xml b/jami-bridges/bridges-core/pom.xml index 9e2f87066c..de4afc2c5b 100644 --- a/jami-bridges/bridges-core/pom.xml +++ b/jami-bridges/bridges-core/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 bridges-core diff --git a/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/InteractorFetcher.java b/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/InteractorFetcher.java index 6c64cebe29..4a5b977892 100644 --- a/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/InteractorFetcher.java +++ b/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/InteractorFetcher.java @@ -3,14 +3,15 @@ import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; import psidev.psi.mi.jami.model.Interactor; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; /** * Fetches the complete records which match an interactor. * * @author Gabriel Aldam (galdam@ebi.ac.uk) * @since 14/05/13 - */ public interface InteractorFetcher { @@ -18,21 +19,29 @@ public interface InteractorFetcher { * Takes a string identifier and returns the interactors which match. * Returns an empty collection of no entries are returned * - * @param identifier The identifier to search for. - * @return The proteins which match the search term. Empty if no matches. + * @param identifier The identifier to search for. + * @return The proteins which match the search term. Empty if no matches. * @throws psidev.psi.mi.jami.bridges.exception.BridgeFailedException A problem has been encountered when contacting the service */ - public Collection fetchByIdentifier(String identifier) - throws BridgeFailedException; + default Collection fetchByIdentifier(String identifier) + throws BridgeFailedException { + return fetchByIdentifiers(List.of(identifier)); + } /** * Takes a collection of string identifiers and returns the interactors which match. * Returns an empty collection of no entries are returned. * - * @param identifiers The identifiers to search for. - * @return The proteins which match the search term. Empty if no matches. + * @param identifiers The identifiers to search for. + * @return The proteins which match the search term. Empty if no matches. * @throws psidev.psi.mi.jami.bridges.exception.BridgeFailedException if any. */ - public Collection fetchByIdentifiers(Collection identifiers) - throws BridgeFailedException; + default Collection fetchByIdentifiers(Collection identifiers) + throws BridgeFailedException { + List list = new ArrayList<>(); + for (String identifier : identifiers) { + list.addAll(fetchByIdentifier(identifier)); + } + return list; + } } diff --git a/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/NucleicAcidFetcher.java b/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/NucleicAcidFetcher.java new file mode 100644 index 0000000000..f55e83bb9b --- /dev/null +++ b/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/NucleicAcidFetcher.java @@ -0,0 +1,49 @@ +package psidev.psi.mi.jami.bridges.fetcher; + +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.model.Gene; +import psidev.psi.mi.jami.model.NucleicAcid; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * A fetcher for genes. + * + * @author Gabriel Aldam (galdam@ebi.ac.uk) + * @since 08/08/13 + */ +public interface NucleicAcidFetcher extends InteractorFetcher { + + /** + *

fetchByIdentifier.

+ * + * @param identifier The identifier of the Nucleic Acid + * @param taxID The organism the gene is from. + * @return The genes matching the search terms. + * @throws BridgeFailedException if any. + */ + Collection fetchByIdentifier(String identifier, int taxID) + throws BridgeFailedException; + + + /** + *

fetchByIdentifiers.

+ * + * @param identifiers The identifiers of the Nucleic Acid + * @param taxID The organism the gene is from. + * @return The genes matching the search terms. + * @throws BridgeFailedException if any. + */ + default Collection fetchByIdentifiers(Collection identifiers, int taxID) + throws BridgeFailedException { + List list = new ArrayList<>(); + for (String identifier : identifiers) { + list.addAll(fetchByIdentifier(identifier, taxID)); + } + return list; + + } +} diff --git a/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/mock/MockNucleicAcidFetcher.java b/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/mock/MockNucleicAcidFetcher.java new file mode 100644 index 0000000000..e860c0ca4b --- /dev/null +++ b/jami-bridges/bridges-core/src/main/java/psidev/psi/mi/jami/bridges/fetcher/mock/MockNucleicAcidFetcher.java @@ -0,0 +1,73 @@ +package psidev.psi.mi.jami.bridges.fetcher.mock; + +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.bridges.fetcher.NucleicAcidFetcher; +import psidev.psi.mi.jami.model.NucleicAcid; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * A mock fetcher for testing. + * It extends all the methods of the true fetcher, but does not access an external service. + * Instead, it holds a map which can be loaded with objects and keys. which are then returned. + * It attempts to replicate the responses of the fetcher in most scenarios. + * + * @author Marine Dumousseau (marine@ebi.ac.uk) + * @version $Id$ + * @since
23/05/13
+ */ +public class MockNucleicAcidFetcher + extends AbstractMockFetcher> + implements NucleicAcidFetcher { + + /** + * {@inheritDoc} + */ + protected Collection getEntry(String identifier) throws BridgeFailedException { + if (identifier == null) throw new IllegalArgumentException( + "Attempted to query mock NucleicAcid fetcher for null identifier."); + + if (!localMap.containsKey(identifier)) { + return new ArrayList<>(); + } else { + return super.getEntry(identifier); + } + } + + /** + * {@inheritDoc} + */ + public Collection fetchByIdentifier(String identifier) throws BridgeFailedException { + return getEntry(identifier); + } + + /** + * {@inheritDoc} + */ + public Collection fetchByIdentifiers(Collection identifiers) throws BridgeFailedException { + Collection resultsList = new ArrayList<>(); + for (String identifier : identifiers) { + resultsList.addAll(getEntry(identifier)); + } + return resultsList; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection fetchByIdentifier(String identifier, int taxID) throws BridgeFailedException { + return getEntry(identifier); + } + + @Override + public Collection fetchByIdentifiers(Collection identifiers, int taxID) throws BridgeFailedException { + Collection resultsList = new ArrayList<>(); + for (String identifier : identifiers) { + resultsList.addAll(getEntry(identifier)); + } + return resultsList; + } + +} diff --git a/jami-bridges/jami-chebi/pom.xml b/jami-bridges/jami-chebi/pom.xml index b5881de287..326bf087c8 100644 --- a/jami-bridges/jami-chebi/pom.xml +++ b/jami-bridges/jami-chebi/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 jami-chebi diff --git a/jami-bridges/jami-ensembl/pom.xml b/jami-bridges/jami-ensembl/pom.xml new file mode 100644 index 0000000000..5aee9cd465 --- /dev/null +++ b/jami-bridges/jami-ensembl/pom.xml @@ -0,0 +1,67 @@ + + 4.0.0 + + psidev.psi.mi.jami.bridges + jami-bridges + 3.5.0 + + + jami-ensembl + jar + + PSI :: JAMI - Bridges - Ensembl + JAMI - Ensembl bridge + + + UTF-8 + 1.18.28 + + + + + + psidev.psi.mi.jami.bridges + bridges-core + ${project.version} + + + + psidev.psi.mi.jami.bridges + jami-ols + ${project.version} + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + com.fasterxml.jackson.core + jackson-databind + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + diff --git a/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/AbstractEnsemblFetcher.java b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/AbstractEnsemblFetcher.java new file mode 100644 index 0000000000..49840c4691 --- /dev/null +++ b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/AbstractEnsemblFetcher.java @@ -0,0 +1,280 @@ +package psidev.psi.mi.jami.bridges.ensembl; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.bridges.fetcher.InteractorFetcher; +import psidev.psi.mi.jami.bridges.ols.CachedOlsCvTermFetcher; +import psidev.psi.mi.jami.bridges.ols.CachedOlsOntologyTermFetcher; +import psidev.psi.mi.jami.model.Alias; +import psidev.psi.mi.jami.model.CvTerm; +import psidev.psi.mi.jami.model.Gene; +import psidev.psi.mi.jami.model.Interactor; +import psidev.psi.mi.jami.model.NucleicAcid; +import psidev.psi.mi.jami.model.OntologyTerm; +import psidev.psi.mi.jami.model.Organism; +import psidev.psi.mi.jami.model.Xref; +import psidev.psi.mi.jami.model.impl.DefaultAlias; +import psidev.psi.mi.jami.model.impl.DefaultCvTerm; +import psidev.psi.mi.jami.model.impl.DefaultGene; +import psidev.psi.mi.jami.model.impl.DefaultNucleicAcid; +import psidev.psi.mi.jami.model.impl.DefaultOrganism; +import psidev.psi.mi.jami.model.impl.DefaultXref; + +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Consumer; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public abstract class AbstractEnsemblFetcher implements InteractorFetcher { + + public static final Pattern identifierPattern = Pattern.compile("^((ENS[FPTGE]\\d{11}(\\.\\d+)?)|(FB\\w{2}\\d{7})|(Y[A-Z]{2}\\d{3}[a-zA-Z](-[A-Z])?))$"); + public static final String GET_SUFFIX = "%s?content-type=application/json"; + public static final String MAIN_URL = "https://rest.ensembl.org/lookup/id"; + public static final String SEQUENCE_URL = "https://rest.ensembl.org/sequence/id/"; + public static final String UNIPROT_URL = "https://rest.ensembl.org/xrefs/id/" + GET_SUFFIX; + public static final String MI_ONTOLOGY_NAME = "psi-mi"; + + private final CachedOlsOntologyTermFetcher ontologyFetcher = new CachedOlsOntologyTermFetcher(); + + private final Map biotypeToCVId = new HashMap<>(Map.of( + "protein_coding", this.getCVByMIId("MI:0324"), // mRNA + "protein_coding_CDS_not_defined", this.getCVByMIId("MI:2190"), // lncRNA + "lncRNA", this.getCVByMIId("MI:2190"), // lncRNA + "miRNA", this.getCVByMIId("MI:2204"), // miRNA + "snRNA", this.getCVByMIId("MI:0607") // snRNA + )); + + private final Map biotypeToShortestType = new HashMap<>(); + + public final CvTerm intactCV = new DefaultCvTerm("intact", "MI:0469"); + public final CvTerm ensemblCV = new DefaultCvTerm("ensembl", "MI:0476"); + public final CvTerm uniprotCV = new DefaultCvTerm("uniprot knowledge base", "MI:0486"); + public final CvTerm rnaCV = new DefaultCvTerm("ribonucleic acid", "MI:0320"); + public final CvTerm identityCv = new DefaultCvTerm(Xref.IDENTITY, Xref.IDENTITY_MI); + public final CvTerm geneCV = new DefaultCvTerm("gene ref", new DefaultXref(intactCV, "IA:3594", identityCv)); // TODO change to new MI ID + public final CvTerm geneNameCV = new DefaultCvTerm("gene name", "MI:0301"); + public final CvTerm geneProductCV = new DefaultCvTerm("gene product", "MI:0251"); + public final CvTerm transcriptCV = new DefaultCvTerm("transcript", new DefaultXref(intactCV, "IA:3522", identityCv)); // TODO change to new MI ID + + public final static Set supportedTypes = Set.of(ObjectType.GENE, ObjectType.TRANSCRIPT); + private final ObjectMapper mapper = JsonMapper.builder() + .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true) + .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true) + .build(); + + private final HttpClient client = HttpClient.newHttpClient(); + private final CachedOlsCvTermFetcher cvFetcher = new CachedOlsCvTermFetcher(); + private final HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() + .header("Content-Type", "application/json") + .header("Accept", "application/json"); + + + public AbstractEnsemblFetcher() throws BridgeFailedException { + } + + @Override + public Collection fetchByIdentifiers(Collection identifiers) throws BridgeFailedException { + try { + List ids = identifiers.stream() + .filter(Objects::nonNull) + .filter(id -> identifierPattern.matcher(id).find()) + .map(id -> id.split("\\.")[0]) + .collect(Collectors.toList()); + + + Map idToInteractor = new HashMap<>(); + Map translationIdToInteractor = new HashMap<>(); + + queryInteractors(ids, idToInteractor, translationIdToInteractor); + + List transcriptIds = idToInteractor.entrySet().stream().filter(entry -> entry.getValue() instanceof NucleicAcid).map(Map.Entry::getKey).collect(Collectors.toList()); + + querySequences(transcriptIds, idToInteractor); + + queryUniprotXrefs(translationIdToInteractor); + + + return idToInteractor.values(); + } catch (Exception e) { + e.printStackTrace(); + throw new BridgeFailedException(e.getMessage()); + } + } + + private void queryInteractors(List ids, Map output, Map translationIdToInteractor) throws IOException, InterruptedException { + this.postRequest(ids, MAIN_URL, new HashMap<>(Map.of("expand", 1)), new TypeReference>() { + }, idToEntree -> output.putAll(idToEntree.entrySet().stream() + .filter(entry -> entry.getValue() != null) + .filter(entry -> supportedTypes.contains(entry.getValue().getObjectType())) + .collect(Collectors.toMap(Map.Entry::getKey, entry -> buildInteractor(entry.getKey(), entry.getValue(), translationIdToInteractor)))) + ); + } + + private void querySequences(List ids, Map idToInteractor) throws IOException, InterruptedException { + this.postRequest(ids, SEQUENCE_URL, new HashMap<>(Map.of("type", "cdna")), new TypeReference>() { + }, sequences -> sequences.forEach( + apiSequence -> ((NucleicAcid) idToInteractor.get(apiSequence.getId())) + .setSequence(apiSequence.getSeq())) + ); + } + + private void queryUniprotXrefs(Map translationIdToInteractor) throws IOException { + for (String id : translationIdToInteractor.keySet()) { + URL uniprotURL = new URL(String.format(UNIPROT_URL, id)); + Collection xrefs = translationIdToInteractor.get(id).getXrefs(); + Arrays.stream(mapper.readValue(uniprotURL, ApiXref[].class)) + .filter(apiXref -> apiXref.getDbname().toUpperCase().contains("UNIPROT")) + .forEach(apiXref -> xrefs.add( + new DefaultXref(uniprotCV, apiXref.getPrimaryId(), geneProductCV) + )); + } + } + + private void postRequest(List ids, String url, Map extraParams, TypeReference returnType, Consumer consumer) throws IOException, InterruptedException { + if (ids == null || ids.isEmpty()) return; + extraParams.put("ids", ids); + HttpRequest request = requestBuilder + .uri(URI.create(url)) + .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(extraParams))) + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + consumer.accept(mapper.readValue(response.body(), returnType)); + } + + protected abstract T buildInteractor(String identifier, ApiObject entree, Map translationIdToInteractor); + + protected Gene buildGeneInteractor(String identifier, ApiObject entree, Map translationIdToInteractor) { + DefaultXref id = new DefaultXref(ensemblCV, identifier, identityCv); + OntologyTerm speciesTaxon = getTermByName(entree.getSpecies().replace("_", " "), "ncbi taxonomy"); + + int taxId = Integer.parseInt(speciesTaxon.getIdentifiers().iterator().next().getId().split(":")[1]); + Organism organism = new DefaultOrganism(taxId, speciesTaxon.getShortName()); + + String name, fullName; + + name = entree.getDisplayName(); + fullName = extractPureIdentifier(entree.getDescription()); + DefaultGene gene = new DefaultGene(name, fullName, organism, id); + + gene.setEnsembl(identifier); + gene.getAliases().add(new DefaultAlias(geneNameCV, entree.getDisplayName())); + gene.getXrefs().add(new DefaultXref(ensemblCV, extractPureIdentifier(entree.getCanonicalTranscript()), transcriptCV)); + + + Stream.of(entree.getTranscripts()) // Transcripts + .filter(Objects::nonNull) + .flatMap(List::stream) + + .filter(ApiObject::isCanonical) // Canonical transcripts (normally 1) + .map(ApiObject::getTranslations) // Translations (normally 1) + .filter(Objects::nonNull) + .flatMap(List::stream) + + .map(ApiObject::getId) // Translation Ids + .forEach(translationId -> translationIdToInteractor.put(translationId, gene)); + + return gene; + } + + protected NucleicAcid buildNucleicAcid(String identifier, ApiObject entree, Map translationIdToInteractor) { + DefaultXref id = new DefaultXref(ensemblCV, identifier, identityCv); + OntologyTerm speciesTaxon = getTermByName(entree.getSpecies().replace("_", " "), "ncbi taxonomy"); + + int taxId = Integer.parseInt(speciesTaxon.getIdentifiers().iterator().next().getId().split(":")[1]); + Organism organism = new DefaultOrganism(taxId, speciesTaxon.getShortName()); + + String name, fullName; + + CvTerm type = biotypeToCVId.computeIfAbsent(entree.getBiotype(), s -> getCVByName(entree.getBiotype(), rnaCV)); + String shortType = biotypeToShortestType.computeIfAbsent(entree.getBiotype(), biotype -> getShortestSynonym(type)); + String geneName = entree.getDisplayName().split("-")[0]; + name = MessageFormat.format("{0}_{1}", shortType, geneName); + fullName = entree.getDisplayName(); + + DefaultNucleicAcid nucleicAcid = new DefaultNucleicAcid(name, fullName, type, organism, id); + + nucleicAcid.getXrefs().add(new DefaultXref(ensemblCV, entree.getParentId(), geneCV)); + nucleicAcid.getAliases().add(new DefaultAlias(geneNameCV, geneName)); + + Stream.of(entree.getTranslations()) // Translations (normally 1) + .filter(Objects::nonNull) + .flatMap(List::stream) + + .map(ApiObject::getId) // Translation Ids + .forEach(translationId -> translationIdToInteractor.put(translationId, nucleicAcid)); + + return nucleicAcid; + } + + private String extractPureIdentifier(String id) { + return id.split("\\.")[0]; + } + + private CvTerm getCVByMIId(String id) { + if (id == null) return null; + try { + return ontologyFetcher.fetchByIdentifier(id, MI_ONTOLOGY_NAME); + } catch (BridgeFailedException e) { + throw new RuntimeException(e); + } + } + + private CvTerm getCVByMIId(String id, CvTerm defaultValue) { + CvTerm cv = getCVByMIId(id); + return cv != null ? cv : defaultValue; + } + + private CvTerm getCVByName(String name) { + if (name == null) return null; + try { + return cvFetcher.fetchByName(name, MI_ONTOLOGY_NAME); + } catch (BridgeFailedException e) { + throw new RuntimeException(e); + } + } + + private OntologyTerm getTermByName(String name, String ontologyId) { + if (name == null) return null; + try { + return ontologyFetcher.fetchByName(name, ontologyId); + } catch (BridgeFailedException e) { + throw new RuntimeException(e); + } + } + + private CvTerm getCVByName(String name, CvTerm defaultValue) { + CvTerm cv = getCVByName(name); + return cv != null ? cv : defaultValue; + } + + private String getShortestSynonym(CvTerm term) { + return Stream.concat(Stream.of(term.getShortName()), term.getSynonyms().stream().map(Alias::getName)) + .min((s1, s2) -> { + int diff = s1.length() - s2.length(); + if (diff !=0) return diff; + if (s1.equals(s2)) return 0; + return s1.chars().anyMatch(Character::isUpperCase) ? -1 : 1; + }).orElse(term.getShortName()); + } + +} \ No newline at end of file diff --git a/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ApiObject.java b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ApiObject.java new file mode 100644 index 0000000000..281ca25e8d --- /dev/null +++ b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ApiObject.java @@ -0,0 +1,52 @@ +package psidev.psi.mi.jami.bridges.ensembl; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; + +import java.util.List; + +@Jacksonized +@Data +@Builder +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +class ApiObject { + private String source; + /** + * Format: homo_sapiens + */ + private String species; + private int strand; + private int version; + private boolean isCanonical; + private String canonicalTranscript; + private ObjectType objectType; + private String id; + private String dbType; + private String displayName; + private String logicName; + private String biotype; + private String assemblyName; + private String seqRegionName; + private String description; + + private long start; + private long end; + + @JsonProperty("Parent") + private String parentId; + @JsonProperty("Transcript") + private List transcripts; + @JsonProperty("Translation") + private List translations; + @JsonProperty("Exon") + private List exons; +} + + + diff --git a/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ApiSequence.java b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ApiSequence.java new file mode 100644 index 0000000000..0b1f373ccb --- /dev/null +++ b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ApiSequence.java @@ -0,0 +1,22 @@ +package psidev.psi.mi.jami.bridges.ensembl; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; + +@Jacksonized +@Data +@Builder +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +class ApiSequence { + private String desc; + private String seq; + private String id; + private String query; + private String molecule; + private int version; +} diff --git a/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ApiXref.java b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ApiXref.java new file mode 100644 index 0000000000..09038ee997 --- /dev/null +++ b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ApiXref.java @@ -0,0 +1,26 @@ +package psidev.psi.mi.jami.bridges.ensembl; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; + +import java.util.List; + +@Jacksonized +@Data +@Builder +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +class ApiXref { + private List synonyms; + private String dbname; + private String version; + private String primaryId; + private String description; + private String infoText; + private String displayId; + private String dbDisplayName; +} diff --git a/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblGeneFetcher.java b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblGeneFetcher.java new file mode 100644 index 0000000000..82bc390bfc --- /dev/null +++ b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblGeneFetcher.java @@ -0,0 +1,29 @@ +package psidev.psi.mi.jami.bridges.ensembl; + +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.bridges.fetcher.GeneFetcher; +import psidev.psi.mi.jami.model.Gene; +import psidev.psi.mi.jami.model.Interactor; + +import java.util.Collection; +import java.util.Map; + +public class EnsemblGeneFetcher extends AbstractEnsemblFetcher implements GeneFetcher { + + public EnsemblGeneFetcher() throws BridgeFailedException { + } + + protected Gene buildInteractor(String identifier, ApiObject entree, Map translationIdToInteractor) { + return buildGeneInteractor(identifier, entree, translationIdToInteractor); + } + + @Override + public Collection fetchByIdentifier(String identifier, int taxID) throws BridgeFailedException { + return fetchByIdentifier(identifier); + } + + @Override + public Collection fetchByIdentifiers(Collection identifiers, int taxID) throws BridgeFailedException { + return fetchByIdentifiers(identifiers); + } +} \ No newline at end of file diff --git a/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblInteractorFetcher.java b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblInteractorFetcher.java new file mode 100644 index 0000000000..b2c78cd7c7 --- /dev/null +++ b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblInteractorFetcher.java @@ -0,0 +1,26 @@ +package psidev.psi.mi.jami.bridges.ensembl; + +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.model.*; + +import java.util.*; + +public class EnsemblInteractorFetcher extends AbstractEnsemblFetcher { + + public EnsemblInteractorFetcher() throws BridgeFailedException { + } + + protected Interactor buildInteractor(String identifier, ApiObject entree, Map translationIdToInteractor) { + + switch (entree.getObjectType()) { + case GENE: + return buildGeneInteractor(identifier, entree, translationIdToInteractor); + case TRANSCRIPT: + return buildNucleicAcid(identifier, entree, translationIdToInteractor); + case TRANSLATION: + case EXON: + break; + } + return null; + } +} \ No newline at end of file diff --git a/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblNucleicAcidFetcher.java b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblNucleicAcidFetcher.java new file mode 100644 index 0000000000..166b873b81 --- /dev/null +++ b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblNucleicAcidFetcher.java @@ -0,0 +1,29 @@ +package psidev.psi.mi.jami.bridges.ensembl; + +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.bridges.fetcher.NucleicAcidFetcher; +import psidev.psi.mi.jami.model.Interactor; +import psidev.psi.mi.jami.model.NucleicAcid; + +import java.util.Collection; +import java.util.Map; + +public class EnsemblNucleicAcidFetcher extends AbstractEnsemblFetcher implements NucleicAcidFetcher { + + public EnsemblNucleicAcidFetcher() throws BridgeFailedException { + } + + protected NucleicAcid buildInteractor(String identifier, ApiObject entree, Map translationIdToInteractor) { + return buildNucleicAcid(identifier, entree, translationIdToInteractor); + } + + @Override + public Collection fetchByIdentifier(String identifier, int taxID) throws BridgeFailedException { + return fetchByIdentifier(identifier); + } + + @Override + public Collection fetchByIdentifiers(Collection identifiers, int taxID) throws BridgeFailedException { + return NucleicAcidFetcher.super.fetchByIdentifiers(identifiers, taxID); + } +} \ No newline at end of file diff --git a/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ObjectType.java b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ObjectType.java new file mode 100644 index 0000000000..8e042c4731 --- /dev/null +++ b/jami-bridges/jami-ensembl/src/main/java/psidev/psi/mi/jami/bridges/ensembl/ObjectType.java @@ -0,0 +1,16 @@ +package psidev.psi.mi.jami.bridges.ensembl; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +enum ObjectType { + GENE("Gene", 'G'), + TRANSLATION("Translation", 'P'), + TRANSCRIPT("Transcript", 'T'), + EXON("Exon", 'E'); + + private final String name; + private final char reprChar; +} diff --git a/jami-bridges/jami-ensembl/src/test/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblInteractorFetcherTest.java b/jami-bridges/jami-ensembl/src/test/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblInteractorFetcherTest.java new file mode 100644 index 0000000000..eff7add40a --- /dev/null +++ b/jami-bridges/jami-ensembl/src/test/java/psidev/psi/mi/jami/bridges/ensembl/EnsemblInteractorFetcherTest.java @@ -0,0 +1,90 @@ +package psidev.psi.mi.jami.bridges.ensembl; + +import org.junit.Before; +import org.junit.Test; +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.model.Gene; +import psidev.psi.mi.jami.model.Interactor; +import psidev.psi.mi.jami.model.NucleicAcid; +import psidev.psi.mi.jami.model.Xref; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import static org.junit.Assert.*; + +public class EnsemblInteractorFetcherTest { + + EnsemblInteractorFetcher fetcher; + + @Before + public void setUp() throws Exception { + fetcher = new EnsemblInteractorFetcher(); + } + + @Test + public void test() throws BridgeFailedException { + Collection interactors = fetcher.fetchByIdentifier("ENST00000650905"); + assertNotEquals(0, interactors.size()); + } + + @Test + public void fetchGene() throws BridgeFailedException { + // https://rest.ensembl.org/lookup/id/ENSG00000157764?content-type=application/json + Collection interactors = fetcher.fetchByIdentifier("ENSG00000157764"); + if (interactors.isEmpty()) fail(); + assertEquals(1, interactors.size()); + Interactor interactor = interactors.iterator().next(); + assertTrue(interactor instanceof Gene); + Gene gene = (Gene) interactor; + + assertNotNull(gene.getPreferredIdentifier()); + assertNotNull(gene.getShortName()); + assertNotNull(gene.getFullName()); + assertNotNull(gene.getEnsembl()); + + assertEquals("Should have 1 gene name alias",1, gene.getAliases().stream().filter(alias -> alias.getType().getShortName().equals("gene name")).count()); + assertEquals("Should have 1 gene product xref, to UniProt/SWISSPROT as it is canonical",1, gene.getXrefs().stream().map(Xref::getQualifier).filter(Objects::nonNull).filter(qualifier -> qualifier.getShortName().equals("gene product")).count()); + assertEquals("Should have 1 transcript xref",1, gene.getXrefs().stream().map(Xref::getQualifier).filter(Objects::nonNull).filter(qualifier -> qualifier.getShortName().equals("transcript")).count()); + } + + @Test + public void fetchTranscript() throws BridgeFailedException { + // https://rest.ensembl.org/lookup/id/ENST00000646891?content-type=application/json + Collection interactors = fetcher.fetchByIdentifier("ENST00000646891"); + if (interactors.isEmpty()) fail(); + assertEquals(1, interactors.size()); + Interactor interactor = interactors.iterator().next(); + assertTrue(interactor instanceof NucleicAcid); + NucleicAcid rna = (NucleicAcid) interactor; + + assertNotNull(rna.getPreferredIdentifier()); + assertEquals("mRNA_BRAF",rna.getShortName()); + assertNotNull(rna.getFullName()); + assertNotNull(rna.getSequence()); + + assertEquals("Should have 1 gene name alias",1, rna.getAliases().stream().filter(alias -> alias.getType().getShortName().equals("gene name")).count()); + assertEquals("Should have 1 gene product xref, to UniProt/TrEMBL",1, rna.getXrefs().stream().map(Xref::getQualifier).filter(Objects::nonNull).filter(qualifier -> qualifier.getShortName().equals("gene product")).count()); + assertEquals("Should have 1 gene ref xref",1, rna.getXrefs().stream().map(Xref::getQualifier).filter(Objects::nonNull).filter(qualifier -> qualifier.getShortName().equals("gene ref")).count()); + } + + @Test + public void fetchCollection() throws BridgeFailedException { + List identifiers = new ArrayList<>(); + identifiers.add(null); // Should not be queried + identifiers.add(""); // Should not be queried + identifiers.add("ksdjbfejwhfbwjehfbwef");// Should not be queried + identifiers.add("ENSG00000157764.14"); // Should be queried without version + identifiers.add("ENST00000646891");// Should be queried + identifiers.add("ENSE00003828230");// Should be queried but not having return (Exon not supported) + identifiers.add("ENSP00000419060");// Should be queried but not having return (Translation not supported) + + Collection interactors = fetcher.fetchByIdentifiers(identifiers); + assertEquals(2, interactors.size()); + assertEquals(1, interactors.stream().filter(interactor -> interactor instanceof Gene).count()); + assertEquals(1, interactors.stream().filter(interactor -> interactor instanceof NucleicAcid).count()); + + } +} \ No newline at end of file diff --git a/jami-bridges/jami-europubmedcentral/pom.xml b/jami-bridges/jami-europubmedcentral/pom.xml index c08e1c7db3..8e095fe882 100644 --- a/jami-bridges/jami-europubmedcentral/pom.xml +++ b/jami-bridges/jami-europubmedcentral/pom.xml @@ -4,7 +4,7 @@ jami-bridges psidev.psi.mi.jami.bridges - 3.4.1 + 3.5.0 jami-europubmedcentral diff --git a/jami-bridges/jami-imexcentral/pom.xml b/jami-bridges/jami-imexcentral/pom.xml index 8e842be30a..60dcd7d0d1 100644 --- a/jami-bridges/jami-imexcentral/pom.xml +++ b/jami-bridges/jami-imexcentral/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 jami-imexcentral diff --git a/jami-bridges/jami-obo/pom.xml b/jami-bridges/jami-obo/pom.xml index 575b52c5d6..1352bc6db8 100644 --- a/jami-bridges/jami-obo/pom.xml +++ b/jami-bridges/jami-obo/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 jami-obo diff --git a/jami-bridges/jami-obo/src/main/java/psidev/psi/mi/jami/bridges/obo/AbstractOboLoader.java b/jami-bridges/jami-obo/src/main/java/psidev/psi/mi/jami/bridges/obo/AbstractOboLoader.java index 26bb462418..7f3a9fcecc 100644 --- a/jami-bridges/jami-obo/src/main/java/psidev/psi/mi/jami/bridges/obo/AbstractOboLoader.java +++ b/jami-bridges/jami-obo/src/main/java/psidev/psi/mi/jami/bridges/obo/AbstractOboLoader.java @@ -339,38 +339,42 @@ protected void processXref(String db, String accession, T ontologyTerm) { ontologyTerm.getAnnotations().add(validation); } // search url - else if (db == null && accession.startsWith(SEARCH_URL)){ - String url = accession.substring(SEARCH_URL.length()); + else if (db == null) { + if (accession.startsWith(SEARCH_URL)) { + String url = accession.substring(SEARCH_URL.length()); - if (url.startsWith("\\")){ - url = url.substring(1); - } - if (url.endsWith("\\")){ - url = url.substring(0, url.length() - 1); - } - - Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref - ontologyTerm.getAnnotations().add(validation); - } - else if (db.equalsIgnoreCase(SEARCH_URL)){ - String url = accession.trim(); + if (url.startsWith("\\")) { + url = url.substring(1); + } + if (url.endsWith("\\")) { + url = url.substring(0, url.length() - 1); + } - Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref - ontologyTerm.getAnnotations().add(validation); + Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref + ontologyTerm.getAnnotations().add(validation); + } } - else if (db.startsWith(SEARCH_URL)){ - String prefix = db.substring(SEARCH_URL.length()); - String url = prefix + META_XREF_SEPARATOR + accession; + else { + if (db.equalsIgnoreCase(SEARCH_URL)){ + String url = accession.trim(); - if (url.startsWith("\"")){ - url = url.substring(1); - } - if (url.endsWith("\"")){ - url = url.substring(0, url.length() - 1); + Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref + ontologyTerm.getAnnotations().add(validation); } + else if (db.startsWith(SEARCH_URL)){ + String prefix = db.substring(SEARCH_URL.length()); + String url = prefix + META_XREF_SEPARATOR + accession; - Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref - ontologyTerm.getAnnotations().add(validation); + if (url.startsWith("\"")){ + url = url.substring(1); + } + if (url.endsWith("\"")){ + url = url.substring(0, url.length() - 1); + } + + Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref + ontologyTerm.getAnnotations().add(validation); + } } } @@ -393,27 +397,28 @@ protected void processDefinition(Term term, T ontologyTerm) { * @param ontologyTerm a T object. */ protected void processDefinition(String definition, T ontologyTerm) { - if ( definition.contains( LINE_BREAK ) ) { - String[] defArray = definition.split( LINE_BREAK ); + if (definition != null) { + if (definition.contains(LINE_BREAK)) { + String[] defArray = definition.split(LINE_BREAK); - String otherInfoString = null; + String otherInfoString = null; - if ( defArray.length == 2 ) { - createDefinitionFor(defArray[0], ontologyTerm); - otherInfoString = defArray[1]; - processInfoInDescription(definition, otherInfoString, ontologyTerm); - } else if ( defArray.length > 2 ) { - createDefinitionFor(defArray[0], ontologyTerm); - - for (int i = 1; i < defArray.length; i++){ - otherInfoString = defArray[i]; + if (defArray.length == 2) { + createDefinitionFor(defArray[0], ontologyTerm); + otherInfoString = defArray[1]; processInfoInDescription(definition, otherInfoString, ontologyTerm); + } else if (defArray.length > 2) { + createDefinitionFor(defArray[0], ontologyTerm); + + for (int i = 1; i < defArray.length; i++) { + otherInfoString = defArray[i]; + processInfoInDescription(definition, otherInfoString, ontologyTerm); + } } + } else { + processInfoInDescription(definition, definition, ontologyTerm); } } - else { - processInfoInDescription(definition, definition, ontologyTerm); - } } /** diff --git a/jami-bridges/jami-obo/src/main/java/psidev/psi/mi/jami/bridges/obo/OntologyOboLoader.java b/jami-bridges/jami-obo/src/main/java/psidev/psi/mi/jami/bridges/obo/OntologyOboLoader.java index 6b55bdab7b..32a9b8c9bf 100644 --- a/jami-bridges/jami-obo/src/main/java/psidev/psi/mi/jami/bridges/obo/OntologyOboLoader.java +++ b/jami-bridges/jami-obo/src/main/java/psidev/psi/mi/jami/bridges/obo/OntologyOboLoader.java @@ -239,38 +239,42 @@ protected void processXref(String db, String accession, OntologyTerm ontologyTer ontologyTerm.getAnnotations().add(validation); } // search url - else if (db == null && accession.startsWith(SEARCH_URL)){ - String url = accession.substring(SEARCH_URL.length()); + else if (db == null) { + if (accession.startsWith(SEARCH_URL)) { + String url = accession.substring(SEARCH_URL.length()); - if (url.startsWith("\\")){ - url = url.substring(1); - } - if (url.endsWith("\\")){ - url = url.substring(0, url.length() - 1); - } - - Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref - ontologyTerm.getAnnotations().add(validation); - } - else if (db.equalsIgnoreCase(SEARCH_URL)){ - String url = accession.trim(); + if (url.startsWith("\\")) { + url = url.substring(1); + } + if (url.endsWith("\\")) { + url = url.substring(0, url.length() - 1); + } - Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref - ontologyTerm.getAnnotations().add(validation); + Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref + ontologyTerm.getAnnotations().add(validation); + } } - else if (db.startsWith(SEARCH_URL)){ - String prefix = db.substring(SEARCH_URL.length()); - String url = prefix + META_XREF_SEPARATOR + accession; + else { + if (db.equalsIgnoreCase(SEARCH_URL)){ + String url = accession.trim(); - if (url.startsWith("\"")){ - url = url.substring(1); - } - if (url.endsWith("\"")){ - url = url.substring(0, url.length() - 1); + Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref + ontologyTerm.getAnnotations().add(validation); } + else if (db.startsWith(SEARCH_URL)){ + String prefix = db.substring(SEARCH_URL.length()); + String url = prefix + META_XREF_SEPARATOR + accession; - Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref - ontologyTerm.getAnnotations().add(validation); + if (url.startsWith("\"")){ + url = url.substring(1); + } + if (url.endsWith("\"")){ + url = url.substring(0, url.length() - 1); + } + + Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, SEARCH_URL_MI_REF, url); // MI xref + ontologyTerm.getAnnotations().add(validation); + } } } @@ -293,27 +297,28 @@ protected void processDefinition(Term term, OntologyTerm ontologyTerm) { * @param ontologyTerm a {@link psidev.psi.mi.jami.model.OntologyTerm} object. */ protected void processDefinition(String definition, OntologyTerm ontologyTerm) { - if ( definition.contains( LINE_BREAK ) ) { - String[] defArray = definition.split( LINE_BREAK ); + if (definition != null) { + if (definition.contains(LINE_BREAK)) { + String[] defArray = definition.split(LINE_BREAK); - String otherInfoString = null; + String otherInfoString = null; - if ( defArray.length == 2 ) { - ontologyTerm.setDefinition(defArray[0]); - otherInfoString = defArray[1]; - processInfoInDescription(definition, otherInfoString, ontologyTerm); - } else if ( defArray.length > 2 ) { - ontologyTerm.setDefinition(defArray[0]); - - for (int i = 1; i < defArray.length; i++){ - otherInfoString = defArray[i]; + if (defArray.length == 2) { + ontologyTerm.setDefinition(defArray[0]); + otherInfoString = defArray[1]; processInfoInDescription(definition, otherInfoString, ontologyTerm); + } else if (defArray.length > 2) { + ontologyTerm.setDefinition(defArray[0]); + + for (int i = 1; i < defArray.length; i++) { + otherInfoString = defArray[i]; + processInfoInDescription(definition, otherInfoString, ontologyTerm); + } } + } else { + processInfoInDescription(definition, definition, ontologyTerm); } } - else { - processInfoInDescription(definition, definition, ontologyTerm); - } } /** diff --git a/jami-bridges/jami-ols/pom.xml b/jami-bridges/jami-ols/pom.xml index 55d691d095..b7710b3e96 100644 --- a/jami-bridges/jami-ols/pom.xml +++ b/jami-bridges/jami-ols/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 jami-ols diff --git a/jami-bridges/jami-ols/src/main/java/psidev/psi/mi/jami/bridges/ols/AbstractOlsFetcher.java b/jami-bridges/jami-ols/src/main/java/psidev/psi/mi/jami/bridges/ols/AbstractOlsFetcher.java index 952071ca40..bc50b4182d 100644 --- a/jami-bridges/jami-ols/src/main/java/psidev/psi/mi/jami/bridges/ols/AbstractOlsFetcher.java +++ b/jami-bridges/jami-ols/src/main/java/psidev/psi/mi/jami/bridges/ols/AbstractOlsFetcher.java @@ -2,13 +2,14 @@ import org.springframework.http.HttpStatus; import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestClientException; import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; import psidev.psi.mi.jami.bridges.fetcher.CvTermFetcher; import psidev.psi.mi.jami.model.CvTerm; import psidev.psi.mi.jami.model.Xref; import psidev.psi.mi.jami.utils.XrefUtils; import uk.ac.ebi.pride.utilities.ols.web.service.client.OLSClient; -import uk.ac.ebi.pride.utilities.ols.web.service.config.OLSWsConfigProd; +import uk.ac.ebi.pride.utilities.ols.web.service.config.OLSWsConfig; import uk.ac.ebi.pride.utilities.ols.web.service.model.Identifier; import uk.ac.ebi.pride.utilities.ols.web.service.model.Term; @@ -32,7 +33,7 @@ public abstract class AbstractOlsFetcher implements CvTermFetc * @throws psidev.psi.mi.jami.bridges.exception.BridgeFailedException if any. */ public AbstractOlsFetcher() throws BridgeFailedException { - this.olsClient = new OLSClient(new OLSWsConfigProd()); + this.olsClient = new OLSClient(new OLSWsConfig("www.ebi.ac.uk/ols4/")); initialiseDbMap(); } @@ -89,6 +90,7 @@ public T fetchByIdentifier(String termIdentifier, String miOntologyName) throws if(!HttpStatus.NOT_FOUND.equals(e.getStatusCode())){ throw new BridgeFailedException(e); } + } catch (RestClientException ignored) { } // 2) if no results, return null diff --git a/jami-bridges/jami-ols/src/main/java/psidev/psi/mi/jami/bridges/ols/LazyCvTerm.java b/jami-bridges/jami-ols/src/main/java/psidev/psi/mi/jami/bridges/ols/LazyCvTerm.java index 87f79b2b63..75c5e1be9d 100644 --- a/jami-bridges/jami-ols/src/main/java/psidev/psi/mi/jami/bridges/ols/LazyCvTerm.java +++ b/jami-bridges/jami-ols/src/main/java/psidev/psi/mi/jami/bridges/ols/LazyCvTerm.java @@ -373,38 +373,42 @@ private void processXref(String db, String accession) { super.getAnnotations().add(validation); } // search url - else if (db == null && accession.startsWith(SEARCH_URL)){ - String url = accession.substring(SEARCH_URL.length()); + else if (db == null) { + if (accession.startsWith(SEARCH_URL)) { + String url = accession.substring(SEARCH_URL.length()); - if (url.startsWith("\\")){ - url = url.substring(1); - } - if (url.endsWith("\\")){ - url = url.substring(0, url.length() - 1); - } - - Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, Annotation.SEARCH_URL_MI, url); // MI xref - super.getAnnotations().add(validation); - } - else if (db != null && db.equalsIgnoreCase(SEARCH_URL)){ - String url = accession.trim(); + if (url.startsWith("\\")) { + url = url.substring(1); + } + if (url.endsWith("\\")) { + url = url.substring(0, url.length() - 1); + } - Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, Annotation.SEARCH_URL_MI, url); // MI xref - super.getAnnotations().add(validation); + Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, Annotation.SEARCH_URL_MI, url); // MI xref + super.getAnnotations().add(validation); + } } - else if (db != null && db.startsWith(SEARCH_URL)){ - String prefix = db.substring(SEARCH_URL.length()); - String url = prefix + META_XREF_SEPARATOR + accession; + else { + if (db.equalsIgnoreCase(SEARCH_URL)){ + String url = accession.trim(); - if (url.startsWith("\"")){ - url = url.substring(1); - } - if (url.endsWith("\"")){ - url = url.substring(0, url.length() - 1); + Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, Annotation.SEARCH_URL_MI, url); // MI xref + super.getAnnotations().add(validation); } + else if (db.startsWith(SEARCH_URL)){ + String prefix = db.substring(SEARCH_URL.length()); + String url = prefix + META_XREF_SEPARATOR + accession; - Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, Annotation.SEARCH_URL_MI, url); // MI xref - super.getAnnotations().add(validation); + if (url.startsWith("\"")){ + url = url.substring(1); + } + if (url.endsWith("\"")){ + url = url.substring(0, url.length() - 1); + } + + Annotation validation = AnnotationUtils.createAnnotation(SEARCH_URL, Annotation.SEARCH_URL_MI, url); // MI xref + super.getAnnotations().add(validation); + } } } diff --git a/jami-bridges/jami-ontology-manager/pom.xml b/jami-bridges/jami-ontology-manager/pom.xml index d0bb188b3c..e7c8a8b8c9 100644 --- a/jami-bridges/jami-ontology-manager/pom.xml +++ b/jami-bridges/jami-ontology-manager/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 jami-ontology-manager diff --git a/jami-bridges/jami-rna-central/pom.xml b/jami-bridges/jami-rna-central/pom.xml new file mode 100644 index 0000000000..c654545e31 --- /dev/null +++ b/jami-bridges/jami-rna-central/pom.xml @@ -0,0 +1,67 @@ + + 4.0.0 + + psidev.psi.mi.jami.bridges + jami-bridges + 3.5.0 + + + jami-rna-central + jar + + PSI :: JAMI - Bridges - RNA Central + JAMI - RNA Central bridge + + + UTF-8 + 1.18.28 + + + + + + psidev.psi.mi.jami.bridges + bridges-core + ${project.version} + + + + psidev.psi.mi.jami.bridges + jami-ols + ${project.version} + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + com.fasterxml.jackson.core + jackson-databind + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/ApiEntree.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/ApiEntree.java new file mode 100644 index 0000000000..2974cf3795 --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/ApiEntree.java @@ -0,0 +1,41 @@ +package psidev.psi.mi.jami.bridges.rna.central; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; + +import java.net.URL; +import java.util.List; + +@Jacksonized +@Data +@Builder +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +class ApiEntree { + private URL url; + @JsonProperty("rnacentral_id") + private String RNACentralId; + private String md5; + private String sequence; + private Integer length; + private String description; + private String shortDescription; + private String species; + private Integer taxid; + private URL xrefsURL; + private URL publicationURL; + private Boolean isActive; + private String rnaType; + private Integer countDistinctOrganisms; + private List distinctDatabases; + + public void setDistinctDatabases(List distinctDatabases) { + if (distinctDatabases.size() == 1) this.distinctDatabases = List.of(distinctDatabases.get(0).split(",")); + else this.distinctDatabases = distinctDatabases; + } +} diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/ApiPublication.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/ApiPublication.java new file mode 100644 index 0000000000..a1494bc9f9 --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/ApiPublication.java @@ -0,0 +1,38 @@ +package psidev.psi.mi.jami.bridges.rna.central; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; + +import java.net.URL; +import java.util.List; + +@Jacksonized +@Data +@Builder +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +class ApiPublication { + private Integer count; + private URL next; + private URL previous; + private List results; + + @Jacksonized + @Data + @Builder + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + static class Result { + private String title; + private List authors; + private String publication; + private String pubmedId; + private String doi; + private String pubId; + private String expertDb; + } +} diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/ApiXrefs.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/ApiXrefs.java new file mode 100644 index 0000000000..31b40d3b51 --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/ApiXrefs.java @@ -0,0 +1,131 @@ +package psidev.psi.mi.jami.bridges.rna.central; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; + +import java.net.URL; +import java.util.Date; +import java.util.List; + +@Jacksonized +@Data +@Builder +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +class ApiXrefs { + private Integer count; + private URL next; + private URL previous; + private List results; + + @Jacksonized + @Data + @Builder + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + static class Result { + private String upi; + private String database; + private Boolean isActive; + @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss") + private Date firstSeen; + @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss") + private Date lastSeen; + private Integer taxid; + + private Accession accession; + + private List modifications; + private Boolean isRfamSeed; + + private String ncbiGeneId; + private URL ndbExternalUrl; + private URL ncbiExternalUrl; + + private URL mirbasePrecursor; + private List mirbaseMatureProducts; + + private URL refseqMirnaPrecursor; + private List refseqMirnaMatureProducts; + private List refseqSpliceVariants; + + private URL ensemblUrl; + private List ensemblSpliceVariants; + + private String gencodeTranscriptId; + private URL gencodeEnsemblUrl; + + private List quickgoHits; + + @Jacksonized + @Data + @Builder + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + public static class Accession { + private URL url; + private String id; + private String parentAc; + private Integer sequenceVersion; + private Integer featureStart; + private Integer featureEnd; + private String featureName; + private String description; + private String externalId; + private String optionalId; + private String locusTag; + private String species; + private String inference; + private String rnaType; + private String gene; + private String product; + private String organelle; + private String standardName; + private String pdbEntityId; + private String hgncEnemblId; + private String hgncId; + private String biotype; + private String srpdbId; + @JsonProperty("ensembl_species_url") + private String ensemblSpecies; + + private List malacardsDiseases; + private Structure pdbStructuredNote; + + + private URL citations; + + private URL expertDbUrl; + private URL enaUrl; + + @Jacksonized + @Data + @Builder + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + static class Disease { + private String name; + private URL url; + } + + @Jacksonized + @Data + @Builder + @JsonIgnoreProperties(ignoreUnknown = true) + static class Structure { + @JsonFormat(pattern = "yyyy-MM-dd") + private Date releaseDate; + private String structureTitle; + private String resolution; + private String experimentalTechnique; + private URL url; + } + } + } +} diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/RNACentralFetcher.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/RNACentralFetcher.java new file mode 100644 index 0000000000..5d301ae8ae --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/RNACentralFetcher.java @@ -0,0 +1,122 @@ +package psidev.psi.mi.jami.bridges.rna.central; + +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.bridges.fetcher.NucleicAcidFetcher; +import psidev.psi.mi.jami.bridges.rna.central.partials.PartialAlias; +import psidev.psi.mi.jami.bridges.rna.central.partials.PartialCvTerm; +import psidev.psi.mi.jami.bridges.rna.central.partials.PartialXref; +import psidev.psi.mi.jami.bridges.rna.central.utils.OLSUtils; +import psidev.psi.mi.jami.model.CvTerm; +import psidev.psi.mi.jami.model.NucleicAcid; +import psidev.psi.mi.jami.model.Organism; +import psidev.psi.mi.jami.model.Xref; +import psidev.psi.mi.jami.model.impl.*; + +import java.io.IOException; +import java.net.URL; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +public class RNACentralFetcher implements NucleicAcidFetcher { + + public static final Pattern identifierPattern = Pattern.compile("^(?URS[A-Z0-9]+)(_(?\\d+))?$"); + public static final String MAIN_URL = "https://rnacentral.org/api/v1/rna/%s.json"; + public static final String XREFS_URL = "https://rnacentral.org/api/v1/rna/%s/xrefs.json"; + public static final String PUBLICATIONS_URL = "https://rnacentral.org/api/v1/rna/%s/publications.json"; + + public RNACentralFetcher() throws BridgeFailedException { + } + + @Override + public Collection fetchByIdentifier(String identifier) throws BridgeFailedException { + Matcher matcher = identifierPattern.matcher(identifier); + if (matcher.find()) { + return fetchByIdentifier(identifier, Integer.parseInt(matcher.group("taxid"))); + } + return Collections.emptyList(); + } + + @Override + public Collection fetchByIdentifier(String identifier, int taxID) throws BridgeFailedException { + try { + Matcher matcher = identifierPattern.matcher(identifier); + if (matcher.find()) { + String pureIdentifier = matcher.group("id"); + URL entreeURI = new URL(String.format(MAIN_URL, identifier)); + ApiEntree entree = OLSUtils.mapper.readValue(entreeURI, ApiEntree.class); + + DefaultXref id = new DefaultXref(OLSUtils.rnaCentral, identifier, OLSUtils.identityCV); + CvTerm type = OLSUtils.olsFetcher.fetchByName(entree.getRnaType(), CvTerm.PSI_MI); + if (type == null) type = OLSUtils.rnaCV; + Organism organism = new DefaultOrganism(entree.getTaxid(), entree.getSpecies()); + + DefaultNucleicAcid nucleicAcid = new DefaultNucleicAcid(entree.getShortDescription(), type, organism, id); + nucleicAcid.setSequence(entree.getSequence()); + nucleicAcid.setFullName(entree.getDescription()); + addXRefs(nucleicAcid, pureIdentifier, organism); + if (type == OLSUtils.rnaCV) nucleicAcid.getAnnotations().add(new DefaultAnnotation(OLSUtils.getCVByName("comment"), "RNA-Central type: " + entree.getRnaType())); + + return List.of(nucleicAcid); + } else return List.of(); + } catch (Exception e) { + e.printStackTrace(); + throw new BridgeFailedException(e.getMessage()); + } + } + + private void addXRefs(NucleicAcid nucleicAcid, String pureIdentifier, Organism organism) { + try { + URL url = new URL(String.format(XREFS_URL, pureIdentifier)); + + while (url != null) { + ApiXrefs xrefs = OLSUtils.mapper.readValue(url, ApiXrefs.class); + url = xrefs.getNext() != null ? new URL(xrefs.getNext().toString().replace("http", "https")) : null; + xrefs.getResults().stream() + .filter(result -> result.getAccession().getSpecies().equals(organism.getScientificName()) || result.getTaxid().equals(organism.getTaxId())) + .forEach(result -> this.extractXrefsAndAliases(nucleicAcid, result)); + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void extractXrefsAndAliases(NucleicAcid nucleicAcid, ApiXrefs.Result result) { + Collection xrefs = nucleicAcid.getXrefs(); + + XrefType xrefType = XrefType.getByDatabase(result.getDatabase()); + + CvTerm database = OLSUtils.getCVByName(result.getDatabase()); + + if (database != null) { + CvTerm qualifier = Stream.of(xrefType) + .map(type -> type.qualifierIdBuilder.apply(result)) + .filter(Objects::nonNull) + .map(PartialCvTerm::complete) + .findFirst().orElse(OLSUtils.secondaryAcCV); + + xrefs.add(new DefaultXref(database, result.getAccession().getExternalId(), qualifier)); + + xrefType.extraReferenceBuilders.stream() + .map(builder -> builder.apply(result)) + .map(partialXref -> partialXref.complete( + PartialXref.builder() + .database(PartialCvTerm.from(database)) + .build())) + .forEach(xrefs::add); + } + + xrefType.aliasBuilders.stream() + .map(builder -> builder.apply(result)) + .map(PartialAlias::complete) + .forEach(alias -> nucleicAcid.getAliases().add(alias)); + + xrefType.extraValueSetters.forEach(builder -> builder.accept(result, nucleicAcid)); + } + +} diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/XrefType.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/XrefType.java new file mode 100644 index 0000000000..589b5bc659 --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/XrefType.java @@ -0,0 +1,96 @@ +package psidev.psi.mi.jami.bridges.rna.central; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import psidev.psi.mi.jami.bridges.rna.central.partials.PartialAlias; +import psidev.psi.mi.jami.bridges.rna.central.partials.PartialCvTerm; +import psidev.psi.mi.jami.bridges.rna.central.partials.PartialXref; +import psidev.psi.mi.jami.bridges.rna.central.utils.OLSUtils; +import psidev.psi.mi.jami.model.Alias; +import psidev.psi.mi.jami.model.NucleicAcid; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Getter +enum XrefType { + DEFAULT("DEFAULT", result -> null, List.of(), List.of(), List.of()), + HGNC("HGNC", + result -> PartialCvTerm.builder() + .id("MI:0361") + .build(), + List.of(), + List.of( + result -> PartialAlias.builder() + .name(result.getAccession().getGene()) + .type(PartialCvTerm.builder().id(Alias.GENE_NAME_MI).build()) + .build() + ), + List.of()), + REF_SEQ("RefSeq", + result -> null, + List.of(), + List.of(), + List.of() + ), + ENSEMBL("Ensembl", + result -> { + switch (result.getAccession().getExternalId().charAt(3)) { + case 'T': + return PartialCvTerm.builder() + .id("IA:3522") + .name("transcript") + .ontology(OLSUtils.intactCV) + .build(); // TODO Update to new MI id + case 'G': + return PartialCvTerm.builder() + .id("IA:3594") + .name("gene ref") + .ontology(OLSUtils.intactCV) + .build(); // TODO Update to new MI id + case 'P': + return PartialCvTerm.builder() + .id("MI:0251") + .name("gene product") + .build(); // gene product + default: + return null; + } + }, + List.of( + result -> PartialXref.builder() + .identifier(result.getAccession().getGene().split("\\.")[0]) + .qualifier(PartialCvTerm.builder() + .id("IA:3594") + .name("gene ref") + .ontology(OLSUtils.intactCV) + .build()) + .build()), + List.of(), + List.of() + ); + public final String database; + public final Function qualifierIdBuilder; + public final List> extraReferenceBuilders; + public final List> aliasBuilders; + public final List> extraValueSetters; + + private static final Map map = Arrays.stream(XrefType.values()) + .collect(Collectors.toMap( + type -> type.database, + type -> type) + ); + + public static XrefType getByDatabase(String database) { + return map.getOrDefault(database, DEFAULT); + } + + + + +} diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/Partial.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/Partial.java new file mode 100644 index 0000000000..ee7573503a --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/Partial.java @@ -0,0 +1,24 @@ +package psidev.psi.mi.jami.bridges.rna.central.partials; + +import java.util.Arrays; + +public interface Partial { + T complete(); + default Partial combine(Partial other) { + Arrays.stream(this.getClass().getDeclaredFields()).forEach(field -> { + try { + field.setAccessible(true); + field.set(this, field.get(other) != null ? field.get(other) : field.get(this)); + field.setAccessible(false); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + }); + return this; + } + + default T complete(Partial other) { + return this.combine(other).complete(); + } +} + diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/PartialAlias.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/PartialAlias.java new file mode 100644 index 0000000000..209ed90fd2 --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/PartialAlias.java @@ -0,0 +1,17 @@ +package psidev.psi.mi.jami.bridges.rna.central.partials; + +import lombok.Builder; +import lombok.Data; +import psidev.psi.mi.jami.model.Alias; +import psidev.psi.mi.jami.model.impl.DefaultAlias; + +@Data +@Builder +public class PartialAlias implements Partial { + private String name; + private PartialCvTerm type; + + public Alias complete() { + return new DefaultAlias(type.complete(), name); + } +} diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/PartialCvTerm.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/PartialCvTerm.java new file mode 100644 index 0000000000..1081d0d7ea --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/PartialCvTerm.java @@ -0,0 +1,31 @@ +package psidev.psi.mi.jami.bridges.rna.central.partials; + +import lombok.Builder; +import lombok.Data; +import psidev.psi.mi.jami.bridges.rna.central.utils.OLSUtils; +import psidev.psi.mi.jami.model.CvTerm; +import psidev.psi.mi.jami.model.impl.DefaultCvTerm; +import psidev.psi.mi.jami.model.impl.DefaultXref; + +@Data +@Builder +public class PartialCvTerm implements Partial { + private String name; + private String id; + @Builder.Default + private CvTerm ontology = OLSUtils.miCV; + + @Override + public CvTerm complete() { + if (name != null) return new DefaultCvTerm(name, new DefaultXref(ontology, id, OLSUtils.identityCV)); + else if (id != null && ontology == OLSUtils.miCV) return OLSUtils.getCVByMIId(id); + else return null; + } + + public static PartialCvTerm from(CvTerm term) { + return PartialCvTerm.builder() + .id(term.getMIIdentifier()) + .name(term.getShortName()) + .build(); + } +} diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/PartialXref.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/PartialXref.java new file mode 100644 index 0000000000..be6a2964d4 --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/partials/PartialXref.java @@ -0,0 +1,19 @@ +package psidev.psi.mi.jami.bridges.rna.central.partials; + +import lombok.Builder; +import lombok.Data; +import psidev.psi.mi.jami.model.Xref; +import psidev.psi.mi.jami.model.impl.DefaultXref; + +@Data +@Builder +public class PartialXref implements Partial { + private PartialCvTerm database; + private String identifier; + private PartialCvTerm qualifier; + + @Override + public Xref complete() { + return new DefaultXref(database.complete(), identifier, qualifier.complete()); + } +} diff --git a/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/utils/OLSUtils.java b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/utils/OLSUtils.java new file mode 100644 index 0000000000..544f3e0fa1 --- /dev/null +++ b/jami-bridges/jami-rna-central/src/main/java/psidev/psi/mi/jami/bridges/rna/central/utils/OLSUtils.java @@ -0,0 +1,49 @@ +package psidev.psi.mi.jami.bridges.rna.central.utils; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.bridges.ols.CachedOlsCvTermFetcher; +import psidev.psi.mi.jami.model.CvTerm; +import psidev.psi.mi.jami.model.Interactor; +import psidev.psi.mi.jami.model.NucleicAcid; +import psidev.psi.mi.jami.model.Xref; +import psidev.psi.mi.jami.model.impl.DefaultCvTerm; + +public class OLSUtils { + public static final CvTerm rnaCentral = new DefaultCvTerm("RNAcentral", "MI:1357"); + public static final CvTerm identityCV = new DefaultCvTerm(Xref.IDENTITY, Xref.IDENTITY_MI); + public static final CvTerm secondaryAcCV = new DefaultCvTerm(Xref.SECONDARY, Xref.SECONDARY_MI); + public static final CvTerm intactCV = new DefaultCvTerm("intact", Xref.INTACT_MI); + public static final CvTerm miCV = new DefaultCvTerm(CvTerm.PSI_MI, CvTerm.PSI_MI_MI); + public static final CvTerm rnaCV = new DefaultCvTerm("ribonucleic acid", "MI:0320"); + public static final ObjectMapper mapper = new ObjectMapper() + .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); + public static final CachedOlsCvTermFetcher olsFetcher; + + static { + try { + olsFetcher = new CachedOlsCvTermFetcher(); + } catch (BridgeFailedException e) { + throw new RuntimeException(e); + } + } + + public static CvTerm getCVByMIId(String id) { + if (id == null) return null; + try { + return olsFetcher.fetchByIdentifier(id, CvTerm.PSI_MI); + } catch (BridgeFailedException e) { + throw new RuntimeException(e); + } + } + + public static CvTerm getCVByName(String name) { + if (name == null) return null; + try { + return olsFetcher.fetchByName(name, CvTerm.PSI_MI); + } catch (BridgeFailedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jami-bridges/jami-rna-central/src/test/java/psidev/psi/mi/jami/bridges/rna/central/RNACentralFetcherTest.java b/jami-bridges/jami-rna-central/src/test/java/psidev/psi/mi/jami/bridges/rna/central/RNACentralFetcherTest.java new file mode 100644 index 0000000000..25bdf8a9c0 --- /dev/null +++ b/jami-bridges/jami-rna-central/src/test/java/psidev/psi/mi/jami/bridges/rna/central/RNACentralFetcherTest.java @@ -0,0 +1,105 @@ +package psidev.psi.mi.jami.bridges.rna.central; + +import org.junit.Before; +import org.junit.Test; +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.model.Alias; +import psidev.psi.mi.jami.model.NucleicAcid; +import psidev.psi.mi.jami.model.Xref; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.*; + +public class RNACentralFetcherTest { + + RNACentralFetcher fetcher; + + @Before + public void setUp() throws Exception { + fetcher = new RNACentralFetcher(); + } + + @Test + public void fetchByIdentifiers() throws BridgeFailedException { + // https://rnacentral.org/api/v1/rna/URS000075C808.json + Collection nucleicAcids = fetcher.fetchByIdentifier("URS000075C808_9606"); + if (nucleicAcids.isEmpty()) fail(); + assertEquals(1, nucleicAcids.size()); + NucleicAcid acid = nucleicAcids.iterator().next(); + assertNotNull(acid.getPreferredIdentifier()); + assertNotNull(acid.getFullName()); + } + + @Test + public void testPDBeXref() throws BridgeFailedException { + // https://rnacentral.org/api/v1/rna/URS0002311975_9606.json + // https://rnacentral.org/api/v1/rna/URS0002311975/xrefs.json + Collection nucleicAcids = fetcher.fetchByIdentifier("URS0002311975_9606"); + NucleicAcid acid = nucleicAcids.iterator().next(); + assertEquals("transfer rna", acid.getInteractorType().getFullName()); + List xrefs = acid.getXrefs().stream().filter(xref -> xref.getDatabase().getShortName().equals("pdbe")).collect(Collectors.toList()); + assertFalse(xrefs.isEmpty()); + assertTrue("URS0002311975_9606 should have a PDB Xref to 7ONU", + xrefs.stream().anyMatch(xref -> xref.getId().equals("7ONU"))); + } + + + @Test + public void testEnsemblXref() throws BridgeFailedException { + // https://rnacentral.org/rna/URS0000031E12/9606 + // https://rnacentral.org/api/v1/rna/URS0000031E12_9606.json + // https://rnacentral.org/api/v1/rna/URS0000031E12/xrefs.json + Collection nucleicAcids = fetcher.fetchByIdentifier("URS0000031E12_9606"); + NucleicAcid acid = nucleicAcids.iterator().next(); + List xrefs = acid.getXrefs().stream().filter(xref -> xref.getDatabase().getShortName().equals("ensembl")).collect(Collectors.toList()); + assertFalse(xrefs.isEmpty()); + assertTrue("URS0000031E12_9606 should have a transcript Xref to ENST00000362160", + xrefs.stream().anyMatch(x -> x.getId().equals("ENST00000362160") && x.getQualifier().getShortName().equals("transcript"))); + assertTrue("URS0000031E12_9606 should have a gene Xref to ENSG00000199030", + xrefs.stream().anyMatch(x -> x.getId().equals("ENSG00000199030") && x.getQualifier().getShortName().equals("gene ref"))); + assertTrue("Querying for a human identifier should only get human ensembl XRefs", + xrefs.stream().allMatch(xref -> xref.getId().startsWith("ENS"))); + + assertTrue("In case of complicated types like pre_miRNA, the default type should be RNA, but we should add an annotation specifying the RNA Central type", + acid.getAnnotations().stream().anyMatch(annotation -> annotation.getValue().contains("pre_miRNA"))); + + + // Side tests + + assertTrue("URS0000031E12_9606 should have a RefSeq Xref to NR_029480", + acid.getXrefs().stream().anyMatch(x -> x.getId().equals("NR_029480"))); + + assertTrue("URS0000031E12_9606 should have a miRBase Xref to MI0000064", + acid.getXrefs().stream().anyMatch(x -> x.getId().equals("MI0000064"))); + + assertTrue("All xrefs should have a qualifier", + acid.getXrefs().stream().allMatch(xref -> xref.getQualifier() != null)); + } + + @Test + public void testRefSeqXref() throws BridgeFailedException { + // https://rnacentral.org/api/v1/rna/URS000075C808_9606.json + // https://rnacentral.org/api/v1/rna/URS000075C808/xrefs.json + Collection nucleicAcids = fetcher.fetchByIdentifier("URS000075C808_9606"); + NucleicAcid acid = nucleicAcids.iterator().next(); + List xrefs = acid.getXrefs().stream().filter(xref -> xref.getDatabase().getShortName().equals("refseq")).collect(Collectors.toList()); + assertFalse(xrefs.isEmpty()); + assertTrue("URS000075C808_9606 should have a RefSeq Xref to NR_003716", + xrefs.stream().anyMatch(xref -> xref.getId().equals("NR_003716"))); + } + + @Test + public void testGeneNameAlias() throws BridgeFailedException { + // https://rnacentral.org/api/v1/rna/URS000075C808_9606.json + // https://rnacentral.org/api/v1/rna/URS000075C808/xrefs.json + Collection nucleicAcids = fetcher.fetchByIdentifier("URS000075C808_9606"); + NucleicAcid acid = nucleicAcids.iterator().next(); + List aliases = acid.getAliases().stream().filter(alias -> alias.getType().getShortName().equals("gene name")).collect(Collectors.toList()); + assertEquals("URS000075C808_9606 should only have one Gene Name alias", 1, aliases.size()); + assertTrue("URS000075C808_9606 gene name should be HOTAIR", + aliases.stream().anyMatch(alias -> alias.getName().equals("HOTAIR"))); + } +} \ No newline at end of file diff --git a/jami-bridges/jami-uniprot-protein-api/pom.xml b/jami-bridges/jami-uniprot-protein-api/pom.xml index 063f9b2fee..0435eef046 100644 --- a/jami-bridges/jami-uniprot-protein-api/pom.xml +++ b/jami-bridges/jami-uniprot-protein-api/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 jami-uniprot-protein-api diff --git a/jami-bridges/jami-uniprot-protein-api/src/test/java/psidev/psi/mi/jami/bridges/uniprot/rest/UniprotProteinAPIClientTest.java b/jami-bridges/jami-uniprot-protein-api/src/test/java/psidev/psi/mi/jami/bridges/uniprot/rest/UniprotProteinAPIClientTest.java index 21b4eb8f75..cef23f7c51 100644 --- a/jami-bridges/jami-uniprot-protein-api/src/test/java/psidev/psi/mi/jami/bridges/uniprot/rest/UniprotProteinAPIClientTest.java +++ b/jami-bridges/jami-uniprot-protein-api/src/test/java/psidev/psi/mi/jami/bridges/uniprot/rest/UniprotProteinAPIClientTest.java @@ -3,6 +3,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import psidev.psi.mi.jami.bridges.uniprot.rest.response.model.Entry; import uk.ac.ebi.kraken.interfaces.uniparc.UniParcEntry; @@ -83,6 +84,7 @@ public void getUniprotEntryForAccession() { } @Test + @Ignore public void getUniparcEntryForAccession() { List uniparcEntries = client.getUniparcEntryForAccession("P45532"); diff --git a/jami-bridges/jami-uniprot-taxonomy/pom.xml b/jami-bridges/jami-uniprot-taxonomy/pom.xml index 6aeaa86fd9..c3c2b8d713 100644 --- a/jami-bridges/jami-uniprot-taxonomy/pom.xml +++ b/jami-bridges/jami-uniprot-taxonomy/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 jami-uniprot-taxonomy diff --git a/jami-bridges/jami-uniprot/pom.xml b/jami-bridges/jami-uniprot/pom.xml index d1aa0d78d0..521db678f3 100644 --- a/jami-bridges/jami-uniprot/pom.xml +++ b/jami-bridges/jami-uniprot/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 jami-uniprot diff --git a/jami-bridges/jami-uniprot/src/main/java/psidev/psi/mi/jami/bridges/uniprot/UniprotGeneFetcher.java b/jami-bridges/jami-uniprot/src/main/java/psidev/psi/mi/jami/bridges/uniprot/UniprotGeneFetcher.java index 51ccd1666e..b1e14a552e 100644 --- a/jami-bridges/jami-uniprot/src/main/java/psidev/psi/mi/jami/bridges/uniprot/UniprotGeneFetcher.java +++ b/jami-bridges/jami-uniprot/src/main/java/psidev/psi/mi/jami/bridges/uniprot/UniprotGeneFetcher.java @@ -17,6 +17,7 @@ import uk.ac.ebi.kraken.interfaces.uniprot.genename.GeneNameSynonym; import uk.ac.ebi.uniprot.dataservice.client.Client; import uk.ac.ebi.uniprot.dataservice.client.QueryResult; +import uk.ac.ebi.uniprot.dataservice.client.QueryResultPage; import uk.ac.ebi.uniprot.dataservice.client.exception.ServiceException; import uk.ac.ebi.uniprot.dataservice.client.uniprot.UniProtQueryBuilder; import uk.ac.ebi.uniprot.dataservice.client.uniprot.UniProtService; @@ -70,10 +71,23 @@ public Collection fetchByIdentifier(String identifier, int taxID) query.and(UniProtQueryBuilder.taxonID(taxID)); } QueryResult entries = uniProtQueryService.getEntries(query); - while (entries.hasNext()) { - UniProtEntry e = entries.next(); - Gene gene = createGenesFromEntry(e, identifier); - genes.add(gene); + QueryResultPage currentPage = entries.getCurrentPage(); + int count = 0; + while (true) { + for (UniProtEntry e : currentPage.getResults()) { + Gene gene = createGenesFromEntry(e, identifier); + genes.add(gene); + count++; + } + if (count < entries.getNumberOfHits()) { + try { + currentPage.fetchNextPage(); + } catch (ServiceException e) { + e.printStackTrace(); + } + } else { + break; + } } }catch (ServiceException e){ uniProtQueryService.stop(); diff --git a/jami-bridges/jami-uniprot/src/main/java/psidev/psi/mi/jami/bridges/uniprot/UniprotProteinFetcher.java b/jami-bridges/jami-uniprot/src/main/java/psidev/psi/mi/jami/bridges/uniprot/UniprotProteinFetcher.java index 5f5fbaec88..792c72cff2 100644 --- a/jami-bridges/jami-uniprot/src/main/java/psidev/psi/mi/jami/bridges/uniprot/UniprotProteinFetcher.java +++ b/jami-bridges/jami-uniprot/src/main/java/psidev/psi/mi/jami/bridges/uniprot/UniprotProteinFetcher.java @@ -25,6 +25,7 @@ import uk.ac.ebi.kraken.interfaces.uniprot.genename.OrderedLocusName; import uk.ac.ebi.uniprot.dataservice.client.Client; import uk.ac.ebi.uniprot.dataservice.client.QueryResult; +import uk.ac.ebi.uniprot.dataservice.client.QueryResultPage; import uk.ac.ebi.uniprot.dataservice.client.exception.ServiceException; import uk.ac.ebi.uniprot.dataservice.client.uniprot.UniProtQueryBuilder; import uk.ac.ebi.uniprot.dataservice.client.uniprot.UniProtService; @@ -164,9 +165,22 @@ private Collection fetchMasterProteinsByIdentifier(String identifier) t uniProtQueryService.start(); Query query = UniProtQueryBuilder.accession(identifier).or(UniProtQueryBuilder.id(identifier)); QueryResult entries = uniProtQueryService.getEntries(query); - while (entries.hasNext()) { - UniProtEntry e = entries.next(); - proteins.add(createMasterProteinFromEntry(e)); + QueryResultPage currentPage = entries.getCurrentPage(); + int count = 0; + while (true) { + for (UniProtEntry e : currentPage.getResults()) { + proteins.add(createMasterProteinFromEntry(e)); + count++; + } + if (count < entries.getNumberOfHits()) { + try { + currentPage.fetchNextPage(); + } catch (ServiceException e) { + e.printStackTrace(); + } + } else { + break; + } } } catch (ServiceException e) { uniProtQueryService.stop(); @@ -199,9 +213,22 @@ private Collection fetchMasterProteinsByIdentifiers(List identi } uniProtQueryService.start(); QueryResult entries = uniProtQueryService.getEntries(query); - while (entries.hasNext()) { - UniProtEntry e = entries.next(); - proteins.add(createMasterProteinFromEntry(e)); + QueryResultPage currentPage = entries.getCurrentPage(); + int count = 0; + while (true) { + for (UniProtEntry e : currentPage.getResults()) { + proteins.add(createMasterProteinFromEntry(e)); + count++; + } + if (count < entries.getNumberOfHits()) { + try { + currentPage.fetchNextPage(); + } catch (ServiceException e) { + e.printStackTrace(); + } + } else { + break; + } } } catch (ServiceException e) { uniProtQueryService.stop(); @@ -267,14 +294,27 @@ private Collection fetchIsoformsByIdentifiers(List identifiers) } uniProtQueryService.start(); QueryResult entries = uniProtQueryService.getEntries(query); - while (entries.hasNext()) { - UniProtEntry e = entries.next(); - Collection matchingIsoform = findIsoformsInEntry(e, identifiers); - if (matchingIsoform.isEmpty()) log.warning("No isoform in entry " + e.getUniProtId()); - else { - for (AlternativeProductsIsoform isoform : matchingIsoform) { - proteins.add(createIsoformFrom(e, isoform)); + QueryResultPage currentPage = entries.getCurrentPage(); + int count = 0; + while (true) { + for (UniProtEntry e : currentPage.getResults()) { + Collection matchingIsoform = findIsoformsInEntry(e, identifiers); + if (matchingIsoform.isEmpty()) log.warning("No isoform in entry " + e.getUniProtId()); + else { + for (AlternativeProductsIsoform isoform : matchingIsoform) { + proteins.add(createIsoformFrom(e, isoform)); + } } + count++; + } + if (count < entries.getNumberOfHits()) { + try { + currentPage.fetchNextPage(); + } catch (ServiceException e) { + e.printStackTrace(); + } + } else { + break; } } } catch (ServiceException e) { @@ -307,12 +347,25 @@ private Collection fetchFeaturesByIdentifier(String identifier) .or(UniProtQueryBuilder.features(FeatureType.PROPEP, identifier))); QueryResult entries = uniProtQueryService.getEntries(query); - while (entries.hasNext()) { - UniProtEntry e = entries.next(); - Feature feature = findFeatureInEntry(e, identifier); - if (feature == null) log.warning("No feature in entry " + e.getUniProtId()); - else { - proteins.add(createProteinFeatureFrom(e, feature)); + QueryResultPage currentPage = entries.getCurrentPage(); + int count = 0; + while (true) { + for (UniProtEntry e : currentPage.getResults()) { + Feature feature = findFeatureInEntry(e, identifier); + if (feature == null) log.warning("No feature in entry " + e.getUniProtId()); + else { + proteins.add(createProteinFeatureFrom(e, feature)); + } + count++; + } + if (count < entries.getNumberOfHits()) { + try { + currentPage.fetchNextPage(); + } catch (ServiceException e) { + e.printStackTrace(); + } + } else { + break; } } } catch (ServiceException e) { diff --git a/jami-bridges/jami-unisave/pom.xml b/jami-bridges/jami-unisave/pom.xml index b2785607ec..1a21ac6019 100644 --- a/jami-bridges/jami-unisave/pom.xml +++ b/jami-bridges/jami-unisave/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami.bridges jami-bridges - 3.4.1 + 3.5.0 jami-unisave diff --git a/jami-bridges/pom.xml b/jami-bridges/pom.xml index 2d1edb461b..01b4b41f51 100644 --- a/jami-bridges/pom.xml +++ b/jami-bridges/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 psidev.psi.mi.jami.bridges @@ -25,6 +25,8 @@ jami-uniprot-protein-api jami-ontology-manager jami-imexcentral + jami-rna-central + jami-ensembl diff --git a/jami-commons/pom.xml b/jami-commons/pom.xml index 53776294d8..36579b8ba8 100644 --- a/jami-commons/pom.xml +++ b/jami-commons/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-commons diff --git a/jami-core/pom.xml b/jami-core/pom.xml index 41f2167958..faa1379873 100644 --- a/jami-core/pom.xml +++ b/jami-core/pom.xml @@ -5,7 +5,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-core diff --git a/jami-core/src/main/java/psidev/psi/mi/jami/model/Xref.java b/jami-core/src/main/java/psidev/psi/mi/jami/model/Xref.java index d81844224c..840912f0f4 100644 --- a/jami-core/src/main/java/psidev/psi/mi/jami/model/Xref.java +++ b/jami-core/src/main/java/psidev/psi/mi/jami/model/Xref.java @@ -20,6 +20,10 @@ public interface Xref { public static final String ENSEMBL = "ensembl"; /** Constant ENSEMBL_MI="MI:0476" */ public static final String ENSEMBL_MI = "MI:0476"; + /** Constant RNA_CENTRAL="RNAcentral" */ + public static final String RNA_CENTRAL = "RNAcentral"; + /** Constant RNA_CENTRAL_MI="MI:1357" */ + public static final String RNA_CENTRAL_MI = "MI:1357"; /** Constant ENSEMBL_GENOMES="ensemblgenomes" */ public static final String ENSEMBL_GENOMES = "ensemblgenomes"; /** Constant ENSEMBL_GENOMES_MI="MI:1013" */ diff --git a/jami-core/src/main/java/psidev/psi/mi/jami/utils/CvTermUtils.java b/jami-core/src/main/java/psidev/psi/mi/jami/utils/CvTermUtils.java index d5526ec2e1..544b0fa603 100644 --- a/jami-core/src/main/java/psidev/psi/mi/jami/utils/CvTermUtils.java +++ b/jami-core/src/main/java/psidev/psi/mi/jami/utils/CvTermUtils.java @@ -487,6 +487,10 @@ public static CvTerm createEnsemblGenomesDatabase(){ return createMICvTerm(Xref.ENSEMBL_GENOMES, Xref.ENSEMBL_GENOMES_MI); } + public static CvTerm createRNACentralDatabase(){ + return createMICvTerm(Xref.RNA_CENTRAL, Xref.RNA_CENTRAL_MI); + } + /** *

createEntrezGeneIdDatabase

* diff --git a/jami-crosslink-csv/pom.xml b/jami-crosslink-csv/pom.xml index 6bdeee8799..2b39c47154 100644 --- a/jami-crosslink-csv/pom.xml +++ b/jami-crosslink-csv/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-crosslink-csv diff --git a/jami-enricher/pom.xml b/jami-enricher/pom.xml index 8a5c1caab5..07a431c29b 100644 --- a/jami-enricher/pom.xml +++ b/jami-enricher/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-enricher diff --git a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/CompositeInteractorEnricher.java b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/CompositeInteractorEnricher.java index 214127e60a..c087d64b04 100644 --- a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/CompositeInteractorEnricher.java +++ b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/CompositeInteractorEnricher.java @@ -15,7 +15,7 @@ * @version $Id$ * @since
11/02/14
*/ -public class CompositeInteractorEnricher implements InteractorEnricher{ +public class CompositeInteractorEnricher implements InteractorEnricher { private AbstractInteractorEnricher interactorBaseEnricher; private InteractorEnricher polymerBaseEnricher; @@ -23,6 +23,7 @@ public class CompositeInteractorEnricher implements InteractorEnricher bioactiveEntityEnricher; private InteractorEnricher geneEnricher; + private InteractorEnricher nucleicAcidEnricher; private ComplexEnricher complexEnricher; /** @@ -30,10 +31,10 @@ public class CompositeInteractorEnricher implements InteractorEnricher interactorBaseEnricher){ + public CompositeInteractorEnricher(AbstractInteractorEnricher interactorBaseEnricher) { super(); - if (interactorBaseEnricher == null){ - throw new IllegalArgumentException("At least the interactor base enricher is needed and cannot be null") ; + if (interactorBaseEnricher == null) { + throw new IllegalArgumentException("At least the interactor base enricher is needed and cannot be null"); } this.interactorBaseEnricher = interactorBaseEnricher; } @@ -128,6 +129,14 @@ public void setGeneEnricher(InteractorEnricher geneEnricher) { this.geneEnricher = geneEnricher; } + public InteractorEnricher getNucleicAcidEnricher() { + return nucleicAcidEnricher; + } + + public void setNucleicAcidEnricher(InteractorEnricher nucleicAcidEnricher) { + this.nucleicAcidEnricher = nucleicAcidEnricher; + } + /** *

Getter for the field complexEnricher.

* @@ -162,32 +171,27 @@ public AbstractInteractorEnricher getInteractorBaseEnricher() { * @throws psidev.psi.mi.jami.enricher.exception.EnricherException if any. */ public void enrich(Interactor object) throws EnricherException { - if(object == null) + if (object == null) throw new IllegalArgumentException("Cannot enrich a null interactor."); - if (object instanceof Polymer){ - if (object instanceof Protein && this.proteinEnricher != null){ - this.proteinEnricher.enrich((Protein)object); - } - else if (this.polymerBaseEnricher != null){ - this.polymerBaseEnricher.enrich((Polymer)object); - } - else{ + if (object instanceof Polymer) { + if (object instanceof Protein && this.proteinEnricher != null) { + this.proteinEnricher.enrich((Protein) object); + } else if (this.polymerBaseEnricher != null) { + this.polymerBaseEnricher.enrich((Polymer) object); + } else { this.interactorBaseEnricher.enrich(object); } - } - else if (object instanceof Gene && this.geneEnricher != null){ - this.geneEnricher.enrich((Gene)object); - } - else if (object instanceof BioactiveEntity && this.bioactiveEntityEnricher != null){ - this.bioactiveEntityEnricher.enrich((BioactiveEntity)object); - } - else if (object instanceof Complex && this.complexEnricher != null){ - this.complexEnricher.enrich((Complex)object); - } - else if (object instanceof InteractorPool && this.interactorPoolEnricher != null){ - this.interactorPoolEnricher.enrich((InteractorPool)object); - } - else{ + } else if (object instanceof Gene && this.geneEnricher != null) { + this.geneEnricher.enrich((Gene) object); + } else if (object instanceof NucleicAcid && this.nucleicAcidEnricher != null) { + this.nucleicAcidEnricher.enrich((NucleicAcid) object); + } else if (object instanceof BioactiveEntity && this.bioactiveEntityEnricher != null) { + this.bioactiveEntityEnricher.enrich((BioactiveEntity) object); + } else if (object instanceof Complex && this.complexEnricher != null) { + this.complexEnricher.enrich((Complex) object); + } else if (object instanceof InteractorPool && this.interactorPoolEnricher != null) { + this.interactorPoolEnricher.enrich((InteractorPool) object); + } else { this.interactorBaseEnricher.enrich(object); } } @@ -199,10 +203,10 @@ else if (object instanceof InteractorPool && this.interactorPoolEnricher != null * @throws psidev.psi.mi.jami.enricher.exception.EnricherException if any. */ public void enrich(Collection objects) throws EnricherException { - if(objects == null) + if (objects == null) throw new IllegalArgumentException("Cannot enrich a null collection of interactors."); - for (Interactor object : objects){ + for (Interactor object : objects) { enrich(object); } } @@ -210,35 +214,28 @@ public void enrich(Collection objects) throws EnricherException { /** *

enrich.

* - * @param object a {@link psidev.psi.mi.jami.model.Interactor} object. + * @param object a {@link psidev.psi.mi.jami.model.Interactor} object. * @param objectSource a {@link psidev.psi.mi.jami.model.Interactor} object. * @throws psidev.psi.mi.jami.enricher.exception.EnricherException if any. */ public void enrich(Interactor object, Interactor objectSource) throws EnricherException { - if (object instanceof Polymer && objectSource instanceof Polymer){ - if (object instanceof Protein && objectSource instanceof Protein && this.proteinEnricher != null){ - this.proteinEnricher.enrich((Protein)object, (Protein)objectSource); - } - else if (this.polymerBaseEnricher != null){ - this.polymerBaseEnricher.enrich((Polymer)object, (Polymer)objectSource); - } - else{ + if (object instanceof Polymer && objectSource instanceof Polymer) { + if (object instanceof Protein && objectSource instanceof Protein && this.proteinEnricher != null) { + this.proteinEnricher.enrich((Protein) object, (Protein) objectSource); + } else if (this.polymerBaseEnricher != null) { + this.polymerBaseEnricher.enrich((Polymer) object, (Polymer) objectSource); + } else { this.interactorBaseEnricher.enrich(object, objectSource); } - } - else if (object instanceof Gene && objectSource instanceof Gene && this.geneEnricher != null){ - this.geneEnricher.enrich((Gene)object, (Gene)objectSource); - } - else if (object instanceof BioactiveEntity && objectSource instanceof BioactiveEntity && this.bioactiveEntityEnricher != null){ - this.bioactiveEntityEnricher.enrich((BioactiveEntity)object, (BioactiveEntity)objectSource); - } - else if (object instanceof Complex && objectSource instanceof Complex && this.complexEnricher != null){ - this.complexEnricher.enrich((Complex)object, (Complex)objectSource); - } - else if (object instanceof InteractorPool && objectSource instanceof InteractorPool && this.interactorPoolEnricher != null){ - this.interactorPoolEnricher.enrich((InteractorPool)object, (InteractorPool)objectSource); - } - else{ + } else if (object instanceof Gene && objectSource instanceof Gene && this.geneEnricher != null) { + this.geneEnricher.enrich((Gene) object, (Gene) objectSource); + } else if (object instanceof BioactiveEntity && objectSource instanceof BioactiveEntity && this.bioactiveEntityEnricher != null) { + this.bioactiveEntityEnricher.enrich((BioactiveEntity) object, (BioactiveEntity) objectSource); + } else if (object instanceof Complex && objectSource instanceof Complex && this.complexEnricher != null) { + this.complexEnricher.enrich((Complex) object, (Complex) objectSource); + } else if (object instanceof InteractorPool && objectSource instanceof InteractorPool && this.interactorPoolEnricher != null) { + this.interactorPoolEnricher.enrich((InteractorPool) object, (InteractorPool) objectSource); + } else { this.interactorBaseEnricher.enrich(object, objectSource); } } @@ -279,53 +276,59 @@ public OrganismEnricher getOrganismEnricher() { return this.interactorBaseEnricher.getOrganismEnricher(); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public void setListener(InteractorEnricherListener listener) { this.interactorBaseEnricher.setListener(listener); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public void setCvTermEnricher(CvTermEnricher enricher) { this.interactorBaseEnricher.setCvTermEnricher(enricher); - if (getProteinEnricher() != null){ + if (getProteinEnricher() != null) { getProteinEnricher().setCvTermEnricher(enricher); } - if (getPolymerBaseEnricher() != null){ + if (getPolymerBaseEnricher() != null) { getPolymerBaseEnricher().setCvTermEnricher(enricher); } - if (getGeneEnricher() != null){ + if (getGeneEnricher() != null) { getGeneEnricher().setCvTermEnricher(enricher); } - if (getBioactiveEntityEnricher() != null){ + if (getBioactiveEntityEnricher() != null) { getBioactiveEntityEnricher().setCvTermEnricher(enricher); } - if (getComplexEnricher() != null){ + if (getComplexEnricher() != null) { getComplexEnricher().setCvTermEnricher(enricher); } - if (getInteractorPoolEnricher() != null){ + if (getInteractorPoolEnricher() != null) { getInteractorPoolEnricher().setCvTermEnricher(enricher); } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public void setOrganismEnricher(OrganismEnricher enricher) { this.interactorBaseEnricher.setOrganismEnricher(enricher); - if (getProteinEnricher() != null){ + if (getProteinEnricher() != null) { getProteinEnricher().setOrganismEnricher(enricher); } - if (getPolymerBaseEnricher() != null){ + if (getPolymerBaseEnricher() != null) { getPolymerBaseEnricher().setOrganismEnricher(enricher); } - if (getGeneEnricher() != null){ + if (getGeneEnricher() != null) { getGeneEnricher().setOrganismEnricher(enricher); } - if (getBioactiveEntityEnricher() != null){ + if (getBioactiveEntityEnricher() != null) { getBioactiveEntityEnricher().setOrganismEnricher(enricher); } - if (getComplexEnricher() != null){ + if (getComplexEnricher() != null) { getComplexEnricher().setOrganismEnricher(enricher); } - if (getInteractorPoolEnricher() != null){ + if (getInteractorPoolEnricher() != null) { getInteractorPoolEnricher().setOrganismEnricher(enricher); } } diff --git a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/full/FullNucleicAcidEnricher.java b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/full/FullNucleicAcidEnricher.java new file mode 100644 index 0000000000..7ef5f20353 --- /dev/null +++ b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/full/FullNucleicAcidEnricher.java @@ -0,0 +1,51 @@ +package psidev.psi.mi.jami.enricher.impl.full; + +import psidev.psi.mi.jami.bridges.fetcher.GeneFetcher; +import psidev.psi.mi.jami.bridges.fetcher.NucleicAcidFetcher; +import psidev.psi.mi.jami.enricher.impl.minimal.MinimalGeneEnricher; +import psidev.psi.mi.jami.enricher.impl.minimal.MinimalNucleicAcidEnricher; +import psidev.psi.mi.jami.enricher.listener.NucleicAcidEnricherListener; +import psidev.psi.mi.jami.enricher.listener.ProteinEnricherListener; +import psidev.psi.mi.jami.model.NucleicAcid; +import psidev.psi.mi.jami.model.Protein; + +/** + * A full enricher for genes. + * + * See description of full enrichment in AbstractInteractorEnricher. + * + * The GeneFetcher is required for enriching genes. + * + * @author Gabriel Aldam (galdam@ebi.ac.uk) + * @since 04/09/13 + + */ +public class FullNucleicAcidEnricher extends MinimalNucleicAcidEnricher { + + /** + *

Constructor for FullGeneEnricher.

+ * + * @param fetcher a {@link GeneFetcher} object. + */ + public FullNucleicAcidEnricher(NucleicAcidFetcher fetcher) { + super(fetcher); + } + + /** {@inheritDoc} */ + @Override + protected boolean isFullEnrichment() { + return true; + } + + @Override + protected void processOtherProperties(NucleicAcid objectToEnrich, NucleicAcid fetched) { + + // sequence + if (objectToEnrich.getSequence() == null && fetched.getSequence() != null){ + objectToEnrich.setSequence(fetched.getSequence()); + if (getListener() instanceof NucleicAcidEnricherListener){ + ((NucleicAcidEnricherListener)getListener()).onSequenceUpdate(objectToEnrich, null); + } + } + } +} diff --git a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/full/FullNucleicAcidUpdater.java b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/full/FullNucleicAcidUpdater.java new file mode 100644 index 0000000000..60441c2c4c --- /dev/null +++ b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/full/FullNucleicAcidUpdater.java @@ -0,0 +1,53 @@ +package psidev.psi.mi.jami.enricher.impl.full; + +import psidev.psi.mi.jami.bridges.fetcher.GeneFetcher; +import psidev.psi.mi.jami.bridges.fetcher.NucleicAcidFetcher; +import psidev.psi.mi.jami.enricher.impl.minimal.MinimalGeneUpdater; +import psidev.psi.mi.jami.enricher.impl.minimal.MinimalNucleicAcidUpdater; +import psidev.psi.mi.jami.enricher.listener.NucleicAcidEnricherListener; +import psidev.psi.mi.jami.enricher.listener.ProteinEnricherListener; +import psidev.psi.mi.jami.model.NucleicAcid; +import psidev.psi.mi.jami.model.Protein; + +/** + * A full updater for genes. + * + * See description of full update in AbstractInteractorEnricher. + * + * The GeneFetcher is required for enriching genes. + * + * @author Gabriel Aldam (galdam@ebi.ac.uk) + * @since 04/09/13 + + */ +public class FullNucleicAcidUpdater extends MinimalNucleicAcidUpdater { + + /** + *

Constructor for FullGeneUpdater.

+ * + * @param fetcher a {@link GeneFetcher} object. + */ + public FullNucleicAcidUpdater(NucleicAcidFetcher fetcher) { + super(fetcher); + } + + /** {@inheritDoc} */ + @Override + protected boolean isFullEnrichment() { + return true; + } + + @Override + protected void processOtherProperties(NucleicAcid toEnrich, NucleicAcid fetched) { + + // sequence + if ((fetched.getSequence() != null && !fetched.getSequence().equalsIgnoreCase(toEnrich.getSequence()) + || (fetched.getSequence() == null && toEnrich.getSequence() != null))){ + String oldSeq = toEnrich.getSequence(); + toEnrich.setSequence(fetched.getSequence()); + if (getListener() instanceof NucleicAcidEnricherListener){ + ((NucleicAcidEnricherListener)getListener()).onSequenceUpdate(toEnrich, oldSeq); + } + } + } +} diff --git a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalGeneEnricher.java b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalGeneEnricher.java index 58edd432c9..93dbc5199b 100644 --- a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalGeneEnricher.java +++ b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalGeneEnricher.java @@ -2,6 +2,7 @@ import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; import psidev.psi.mi.jami.bridges.fetcher.GeneFetcher; +import psidev.psi.mi.jami.bridges.fetcher.InteractorFetcher; import psidev.psi.mi.jami.enricher.exception.EnricherException; import psidev.psi.mi.jami.enricher.impl.AbstractInteractorEnricher; import psidev.psi.mi.jami.enricher.listener.EnrichmentStatus; @@ -14,17 +15,26 @@ /** * A basic minimal enricher for genes. - * + *

* See description of minimal enrichment in AbstractInteractorEnricher. - * + *

* The GeneFetcher is required for enriching genes. * * @author Gabriel Aldam (galdam@ebi.ac.uk) * @since 04/09/13 - */ public class MinimalGeneEnricher extends AbstractInteractorEnricher { + protected GeneFetcher ensemblFetcher; + + public GeneFetcher getEnsemblFetcher() { + return ensemblFetcher == null ? getInteractorFetcher() : ensemblFetcher; + } + + public void setEnsemblFetcher(GeneFetcher ensemblFetcher) { + this.ensemblFetcher = ensemblFetcher; + } + /** *

Constructor for MinimalGeneEnricher.

* @@ -32,127 +42,135 @@ public class MinimalGeneEnricher extends AbstractInteractorEnricher { */ public MinimalGeneEnricher(GeneFetcher fetcher) { super(fetcher); - if (fetcher == null){ - throw new IllegalArgumentException("The gene enricher needs a non null fetcher"); - } + if (fetcher == null) throw new IllegalArgumentException("The gene enricher needs a non null fetcher"); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public GeneFetcher getInteractorFetcher() { - return (GeneFetcher)super.getInteractorFetcher(); + return (GeneFetcher) super.getInteractorFetcher(); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public Gene find(Gene geneToEnrich) throws EnricherException { int taxid = -3; - if(geneToEnrich.getOrganism() != null) { + if (geneToEnrich.getOrganism() != null) { taxid = geneToEnrich.getOrganism().getTaxId(); } Gene geneFetched = null; - if(geneToEnrich.getEnsembl() != null) - geneFetched = fetchGeneByIdentifier(geneToEnrich, geneToEnrich.getEnsembl() , taxid); + if (geneToEnrich.getEnsembl() != null) + geneFetched = fetchGeneByIdentifier(getEnsemblFetcher(), geneToEnrich, geneToEnrich.getEnsembl(), taxid); - if(geneFetched == null && geneToEnrich.getRefseq() != null) - geneFetched = fetchGeneByIdentifier(geneToEnrich, geneToEnrich.getRefseq() , taxid); + if (geneFetched == null && geneToEnrich.getRefseq() != null) + geneFetched = fetchGeneByIdentifier(getInteractorFetcher(), geneToEnrich, geneToEnrich.getRefseq(), taxid); - if(geneFetched == null && geneToEnrich.getEnsemblGenome() != null) - geneFetched = fetchGeneByIdentifier(geneToEnrich, geneToEnrich.getEnsemblGenome() , taxid); + if (geneFetched == null && geneToEnrich.getEnsemblGenome() != null) + geneFetched = fetchGeneByIdentifier(getInteractorFetcher(), geneToEnrich, geneToEnrich.getEnsemblGenome(), taxid); return geneFetched; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override - protected void onEnrichedVersionNotFound(Gene objectToEnrich) throws EnricherException{ - if(getListener() != null) + protected void onEnrichedVersionNotFound(Gene objectToEnrich) throws EnricherException { + if (getListener() != null) getListener().onEnrichmentComplete( - objectToEnrich , EnrichmentStatus.FAILED , - "Could not fetch a gene with the provided identifier [" + objectToEnrich.getPreferredIdentifier() + "]."); + objectToEnrich, EnrichmentStatus.FAILED, + "Could not fetch a gene with the provided identifier [" + objectToEnrich.getPreferredIdentifier() + "]."); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override protected boolean isFullEnrichment() { return false; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override protected void onCompletedEnrichment(Gene objectToEnrich) { - if(getListener() != null) + if (getListener() != null) getListener().onEnrichmentComplete( - objectToEnrich , EnrichmentStatus.SUCCESS , "The gene [" + objectToEnrich.getPreferredIdentifier() + "] has been successfully enriched."); + objectToEnrich, EnrichmentStatus.SUCCESS, "The gene [" + objectToEnrich.getPreferredIdentifier() + "] has been successfully enriched."); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override - protected void onInteractorCheckFailure(Gene objectToEnrich, Gene fetchedObject) throws EnricherException{ - if(getListener() != null) + protected void onInteractorCheckFailure(Gene objectToEnrich, Gene fetchedObject) throws EnricherException { + if (getListener() != null) getListener().onEnrichmentComplete( - objectToEnrich , EnrichmentStatus.FAILED , "Cannot enrich the gene [" + objectToEnrich.getPreferredIdentifier() + "] because the interactor type is not a gene type or we have a mismatch between the gene taxid to enrich and the fetched gene taxid."); + objectToEnrich, EnrichmentStatus.FAILED, "Cannot enrich the gene [" + objectToEnrich.getPreferredIdentifier() + "] because the interactor type is not a gene type or we have a mismatch between the gene taxid to enrich and the fetched gene taxid."); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override - protected boolean canEnrichInteractor(Gene entityToEnrich, Gene fetchedEntity) throws EnricherException{ - if (fetchedEntity == null){ + protected boolean canEnrichInteractor(Gene entityToEnrich, Gene fetchedEntity) throws EnricherException { + if (fetchedEntity == null) { onEnrichedVersionNotFound(entityToEnrich); return false; } // if the interactor type is not a valid bioactive entity interactor type, we cannot enrich if (entityToEnrich.getInteractorType() != null && !CvTermUtils.isCvTerm(entityToEnrich.getInteractorType(), Gene.GENE_MI, Gene.GENE) - && !CvTermUtils.isCvTerm(entityToEnrich.getInteractorType(), Interactor.UNKNOWN_INTERACTOR_MI, Interactor.UNKNOWN_INTERACTOR)){ + && !CvTermUtils.isCvTerm(entityToEnrich.getInteractorType(), Interactor.UNKNOWN_INTERACTOR_MI, Interactor.UNKNOWN_INTERACTOR)) { return false; } // if the organism is different, we cannot enrich if (entityToEnrich.getOrganism() != null && fetchedEntity.getOrganism() != null && - !OrganismTaxIdComparator.areEquals(entityToEnrich.getOrganism(), fetchedEntity.getOrganism())){ + !OrganismTaxIdComparator.areEquals(entityToEnrich.getOrganism(), fetchedEntity.getOrganism())) { return false; } return true; } - private Gene fetchGeneByIdentifier(Gene gene, String identifier , int taxid) throws EnricherException { + private Gene fetchGeneByIdentifier(GeneFetcher fetcher, Gene gene, String identifier, int taxid) throws EnricherException { Collection results; try { - results = getInteractorFetcher().fetchByIdentifier(identifier, taxid); - if(results.size() == 1){ + results = fetcher.fetchByIdentifier(identifier, taxid); + if (results.size() == 1) { return results.iterator().next(); - } - else if (!results.isEmpty()){ - if (getListener() != null){ + } else if (!results.isEmpty()) { + if (getListener() != null) { getListener().onEnrichmentError(gene, "The identifier [" + identifier + "] and taxid " + taxid + " can match " + - results.size() + " genes and it is not possible to enrich with multiple entries", new EnricherException("Multiple gene entries found for " + identifier + " and taxid " + taxid)); + results.size() + " genes and it is not possible to enrich with multiple entries", new EnricherException("Multiple gene entries found for " + identifier + " and taxid " + taxid)); } return null; - } - else{ + } else { return null; } } catch (BridgeFailedException e) { int index = 0; - while(index < getRetryCount()){ + while (index < getRetryCount()) { try { - results = getInteractorFetcher().fetchByIdentifier(identifier, taxid); - if(results.size() == 1){ + results = fetcher.fetchByIdentifier(identifier, taxid); + if (results.size() == 1) { return results.iterator().next(); - } - else if (!results.isEmpty()){ - if (getListener() != null){ + } else if (!results.isEmpty()) { + if (getListener() != null) { getListener().onEnrichmentError(gene, "The identifier [" + identifier + "] and taxid " + taxid + " can match " + results.size() + " genes and it is not possible to enrich with multiple entries", new EnricherException("Multiple gene entries found for [" + identifier + "] and taxid " + taxid)); } return null; - } - else{ + } else { return null; } } catch (BridgeFailedException ee) { @@ -160,7 +178,7 @@ else if (!results.isEmpty()){ index++; } } - throw new EnricherException("Retried "+getRetryCount()+" times to connect to the gene fetcher", e); + throw new EnricherException("Retried " + getRetryCount() + " times to connect to the gene fetcher", e); } } } diff --git a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalGeneUpdater.java b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalGeneUpdater.java index 65f415217e..9eb3178985 100644 --- a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalGeneUpdater.java +++ b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalGeneUpdater.java @@ -1,6 +1,7 @@ package psidev.psi.mi.jami.enricher.impl.minimal; import psidev.psi.mi.jami.bridges.fetcher.GeneFetcher; +import psidev.psi.mi.jami.bridges.fetcher.NucleicAcidFetcher; import psidev.psi.mi.jami.enricher.impl.AbstractInteractorEnricher; import psidev.psi.mi.jami.enricher.impl.AbstractInteractorUpdater; import psidev.psi.mi.jami.model.Gene; @@ -18,6 +19,15 @@ */ public class MinimalGeneUpdater extends AbstractInteractorUpdater { + public GeneFetcher getEnsemblFetcher() { + return ((MinimalGeneEnricher) getInteractorEnricher()).getEnsemblFetcher(); + } + + public void setEnsemblFetcher(GeneFetcher ensemblFetcher) { + ((MinimalGeneEnricher) getInteractorEnricher()).setEnsemblFetcher(ensemblFetcher); + } + + /** *

Constructor for MinimalGeneUpdater.

* diff --git a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalNucleicAcidEnricher.java b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalNucleicAcidEnricher.java new file mode 100644 index 0000000000..55307b0642 --- /dev/null +++ b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalNucleicAcidEnricher.java @@ -0,0 +1,179 @@ +package psidev.psi.mi.jami.enricher.impl.minimal; + +import psidev.psi.mi.jami.bridges.exception.BridgeFailedException; +import psidev.psi.mi.jami.bridges.fetcher.NucleicAcidFetcher; +import psidev.psi.mi.jami.enricher.exception.EnricherException; +import psidev.psi.mi.jami.enricher.impl.AbstractInteractorEnricher; +import psidev.psi.mi.jami.enricher.listener.EnrichmentStatus; +import psidev.psi.mi.jami.model.Interactor; +import psidev.psi.mi.jami.model.NucleicAcid; +import psidev.psi.mi.jami.model.Xref; +import psidev.psi.mi.jami.utils.CvTermUtils; +import psidev.psi.mi.jami.utils.comparator.organism.OrganismTaxIdComparator; + +import java.util.Collection; + +/** + * A basic minimal enricher for nucleic acids. + *

+ * See description of minimal enrichment in AbstractInteractorEnricher. + *

+ * The NucleicAcidFetcher is required for enriching nucleic acids. + * The EnsemblNucleicAcidFetcher is required for enriching ensembl identifiers + * + * @author Gabriel Aldam (galdam@ebi.ac.uk) + * @since 04/09/13 + */ +public class MinimalNucleicAcidEnricher extends AbstractInteractorEnricher { + + public static final String RNA_CENTRAL_MI = "MI:1357"; + public static final String RNA_CENTRAL = "RNACentral"; + public static final String ENSEMBL_MI = "MI:0476"; + public static final String ENSEMBL = "ensembl"; + protected NucleicAcidFetcher ensemblFetcher; + + public NucleicAcidFetcher getEnsemblFetcher() { + return ensemblFetcher == null ? getInteractorFetcher() : ensemblFetcher; + } + + public void setEnsemblFetcher(NucleicAcidFetcher ensemblFetcher) { + this.ensemblFetcher = ensemblFetcher; + } + + /** + *

Constructor for MinimalNucleicAcidEnricher.

+ * + * @param fetcher a {@link NucleicAcidFetcher} object. + */ + public MinimalNucleicAcidEnricher(NucleicAcidFetcher fetcher) { + super(fetcher); + if (fetcher == null) throw new IllegalArgumentException("The nucleic acid enricher needs a non null fetcher"); + } + + /** + * {@inheritDoc} + */ + @Override + public NucleicAcidFetcher getInteractorFetcher() { + return (NucleicAcidFetcher) super.getInteractorFetcher(); + } + + /** + * {@inheritDoc} + */ + @Override + public NucleicAcid find(NucleicAcid objectToEnrich) throws EnricherException { + Xref id = objectToEnrich.getPreferredIdentifier(); + if (CvTermUtils.isCvTerm(id.getDatabase(), RNA_CENTRAL_MI, RNA_CENTRAL)) { + return fetchNAByIdentifier(getInteractorFetcher(), objectToEnrich, id.getId()); + } else if (CvTermUtils.isCvTerm(id.getDatabase(), ENSEMBL_MI, ENSEMBL)) { + return fetchNAByIdentifier(getEnsemblFetcher(), objectToEnrich, id.getId()); + } + return null; + } + + + /** + * {@inheritDoc} + */ + @Override + protected void onEnrichedVersionNotFound(NucleicAcid objectToEnrich) throws EnricherException { + if (getListener() != null) + getListener().onEnrichmentComplete( + objectToEnrich, EnrichmentStatus.FAILED, + "Could not fetch a nucleic acid with the provided identifier [" + objectToEnrich.getPreferredIdentifier() + "]."); + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean isFullEnrichment() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + protected void onCompletedEnrichment(NucleicAcid objectToEnrich) { + if (getListener() != null) + getListener().onEnrichmentComplete( + objectToEnrich, EnrichmentStatus.SUCCESS, "The nucleic acid [" + objectToEnrich.getPreferredIdentifier() + "] has been successfully enriched."); + } + + /** + * {@inheritDoc} + */ + @Override + protected void onInteractorCheckFailure(NucleicAcid objectToEnrich, NucleicAcid fetchedObject) throws EnricherException { + if (getListener() != null) + getListener().onEnrichmentComplete( + objectToEnrich, EnrichmentStatus.FAILED, "Cannot enrich the nucleic acid [" + objectToEnrich.getPreferredIdentifier() + "] because the interactor type is not a nucleic acid type or we have a mismatch between the nucleic acid taxid to enrich and the fetched nucleic acid taxid."); + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean canEnrichInteractor(NucleicAcid entityToEnrich, NucleicAcid fetchedEntity) throws EnricherException { + if (fetchedEntity == null) { + onEnrichedVersionNotFound(entityToEnrich); + return false; + } + // if the interactor type is not a valid bioactive entity interactor type, we cannot enrich + if (entityToEnrich.getInteractorType() != null && + !CvTermUtils.isCvTerm(entityToEnrich.getInteractorType(), NucleicAcid.NULCEIC_ACID_MI, NucleicAcid.NULCEIC_ACID) + && !CvTermUtils.isCvTerm(entityToEnrich.getInteractorType(), Interactor.UNKNOWN_INTERACTOR_MI, Interactor.UNKNOWN_INTERACTOR)) { + return false; + } + + // if the organism is different, we cannot enrich + if (entityToEnrich.getOrganism() != null && fetchedEntity.getOrganism() != null && + !OrganismTaxIdComparator.areEquals(entityToEnrich.getOrganism(), fetchedEntity.getOrganism())) { + return false; + } + + return true; + } + + private NucleicAcid fetchNAByIdentifier(NucleicAcidFetcher fetcher, NucleicAcid nucleicAcid, String identifier) throws EnricherException { + Collection results; + try { + results = fetcher.fetchByIdentifier(identifier); + if (results.size() == 1) { + return results.iterator().next(); + } else if (!results.isEmpty()) { + if (getListener() != null) { + getListener().onEnrichmentError(nucleicAcid, "The identifier [" + identifier + "] can match " + + results.size() + " nucleic acids and it is not possible to enrich with multiple entries", new EnricherException("Multiple nucleicAcid entries found for " + identifier)); + } + return null; + } else { + return null; + } + } catch (BridgeFailedException e) { + int index = 0; + while (index < getRetryCount()) { + try { + results = fetcher.fetchByIdentifier(identifier); + if (results.size() == 1) { + return results.iterator().next(); + } else if (!results.isEmpty()) { + if (getListener() != null) { + getListener().onEnrichmentError(nucleicAcid, "The identifier [" + identifier + "] can match " + + results.size() + " nucleic acids and it is not possible to enrich with multiple entries", new EnricherException("Multiple nucleicAcid entries found for [" + identifier + "]")); + } + return null; + } else { + return null; + } + } catch (BridgeFailedException ee) { + ee.printStackTrace(); + index++; + } + } + throw new EnricherException("Retried " + getRetryCount() + " times to connect to the nucleicAcid fetcher", e); + } + } +} diff --git a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalNucleicAcidUpdater.java b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalNucleicAcidUpdater.java new file mode 100644 index 0000000000..0e68e005d8 --- /dev/null +++ b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/impl/minimal/MinimalNucleicAcidUpdater.java @@ -0,0 +1,48 @@ +package psidev.psi.mi.jami.enricher.impl.minimal; + +import psidev.psi.mi.jami.bridges.fetcher.NucleicAcidFetcher; +import psidev.psi.mi.jami.enricher.impl.AbstractInteractorEnricher; +import psidev.psi.mi.jami.enricher.impl.AbstractInteractorUpdater; +import psidev.psi.mi.jami.model.Gene; +import psidev.psi.mi.jami.model.NucleicAcid; + +/** + * A basic minimal updater for nucleic acids. + *

+ * See description of minimal update in AbstractInteractorUpdater. + *

+ * The NucleicAcidFetcher is required for enriching nucleic acids. + * The EnsemblNucleicAcidFetcher is required for enriching ensembl identifiers + * + * @author Gabriel Aldam (galdam@ebi.ac.uk) + * @since 04/09/13 + + */ +public class MinimalNucleicAcidUpdater extends AbstractInteractorUpdater { + + public NucleicAcidFetcher getEnsemblFetcher() { + return ((MinimalNucleicAcidEnricher) getInteractorEnricher()).getEnsemblFetcher(); + } + + public void setEnsemblFetcher(NucleicAcidFetcher ensemblFetcher) { + ((MinimalNucleicAcidEnricher) getInteractorEnricher()).setEnsemblFetcher(ensemblFetcher); + } + + /** + *

Constructor for MinimalGeneUpdater.

+ * + * @param fetcher a {@link psidev.psi.mi.jami.bridges.fetcher.GeneFetcher} object. + */ + public MinimalNucleicAcidUpdater(NucleicAcidFetcher fetcher) { + super(new MinimalNucleicAcidEnricher(fetcher)); + } + + /** + *

Constructor for MinimalGeneUpdater.

+ * + * @param interactorEnricher a {@link psidev.psi.mi.jami.enricher.impl.AbstractInteractorEnricher} object. + */ + protected MinimalNucleicAcidUpdater(AbstractInteractorEnricher interactorEnricher) { + super(interactorEnricher); + } +} diff --git a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/listener/NucleicAcidEnricherListener.java b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/listener/NucleicAcidEnricherListener.java new file mode 100644 index 0000000000..7c91e988ff --- /dev/null +++ b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/listener/NucleicAcidEnricherListener.java @@ -0,0 +1,13 @@ +package psidev.psi.mi.jami.enricher.listener; + +import psidev.psi.mi.jami.model.NucleicAcid; + +/** + * Created with IntelliJ IDEA. + * + * @author Gabriel Aldam (galdam@ebi.ac.uk) + * @since 03/09/13 + + */ +public interface NucleicAcidEnricherListener extends PolymerEnricherListener { +} diff --git a/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/listener/impl/writer/NucleicAcidEnricherStatisticsWriter.java b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/listener/impl/writer/NucleicAcidEnricherStatisticsWriter.java new file mode 100644 index 0000000000..f14b3b6b9c --- /dev/null +++ b/jami-enricher/src/main/java/psidev/psi/mi/jami/enricher/listener/impl/writer/NucleicAcidEnricherStatisticsWriter.java @@ -0,0 +1,64 @@ +package psidev.psi.mi.jami.enricher.listener.impl.writer; + +import psidev.psi.mi.jami.enricher.listener.NucleicAcidEnricherListener; +import psidev.psi.mi.jami.model.NucleicAcid; + +import java.io.File; +import java.io.IOException; + +/** + * Created with IntelliJ IDEA. + * + * @author Gabriel Aldam (galdam@ebi.ac.uk) + * @since 03/09/13 + + */ +public class NucleicAcidEnricherStatisticsWriter + extends PolymerEnricherStatisticsWriter + implements NucleicAcidEnricherListener { + + + /** Constant FILE_NAME="NucleicAcid" */ + public static final String FILE_NAME = "NucleicAcid"; + + /** + * Uses the known name of the JamiObject type as the seed to generate names for the success an failure log files. + * + * @throws IOException Thrown if a problem is encountered with file location. + */ + public NucleicAcidEnricherStatisticsWriter() throws IOException { + super(FILE_NAME); + } + + /** + * Creates the files from the provided seed file name with 'success' and 'failure' appended. + * + * @param fileName The seed to base the names of the files on. + * @throws IOException Thrown if a problem is encountered with file location. + */ + public NucleicAcidEnricherStatisticsWriter(String fileName) throws IOException { + super(fileName); + } + + /** + * Uses the provided names to create the files for successful and failed enrichment logging. + * + * @param successFileName The exact name for the file to log successful enrichments in + * @param failureFileName The exact name for the file to log failed enrichments in + * @throws IOException Thrown if a problem is encountered with file location. + */ + public NucleicAcidEnricherStatisticsWriter(String successFileName, String failureFileName) throws IOException { + super(successFileName, failureFileName); + } + + /** + * Uses the exact files provided to log successful and failed enrichments. + * + * @param successFile The file to log successful enrichments in + * @param failureFile The file to log failed enrichments in. + * @throws IOException Thrown if a problem is encountered with file location. + */ + public NucleicAcidEnricherStatisticsWriter(File successFile, File failureFile) throws IOException { + super(successFile, failureFile); + } +} diff --git a/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/FullNucleicAcidEnricherTest.java b/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/FullNucleicAcidEnricherTest.java new file mode 100644 index 0000000000..3ae65b92de --- /dev/null +++ b/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/FullNucleicAcidEnricherTest.java @@ -0,0 +1,100 @@ +package psidev.psi.mi.jami.enricher.impl; + +import org.junit.Before; +import org.junit.Test; +import psidev.psi.mi.jami.bridges.fetcher.mock.MockNucleicAcidFetcher; +import psidev.psi.mi.jami.enricher.exception.EnricherException; +import psidev.psi.mi.jami.enricher.impl.full.FullNucleicAcidEnricher; +import psidev.psi.mi.jami.model.CvTerm; +import psidev.psi.mi.jami.model.NucleicAcid; +import psidev.psi.mi.jami.model.impl.DefaultNucleicAcid; +import psidev.psi.mi.jami.model.impl.DefaultOrganism; +import psidev.psi.mi.jami.model.impl.DefaultXref; +import psidev.psi.mi.jami.utils.CvTermUtils; + +import java.util.List; + +import static junit.framework.Assert.*; + +/** + * Unit tests for MinimalProteinEnricher + * + * @author Gabriel Aldam (galdam@ebi.ac.uk) + * @since 23/05/13 + */ + +public class FullNucleicAcidEnricherTest { + + private FullNucleicAcidEnricher enricher; + private MockNucleicAcidFetcher mockNucleicAcidFetcher; + private MockNucleicAcidFetcher mockEnsemblNucleicAcidFetcher; + + private static final String TEST_SHORTNAME = "test shortName"; + private static final String TEST_FULLNAME = "test fullName"; + private static final String TEST_FULLNAME_ENSEMBL = "test fullName ENSEMBL"; + private static final String TEST_AC_FULL = "URS000055C986_4896"; + private static final String TEST_AC_ENSEMBL = "ENST00000652534"; + private static final String TEST_SEQUENCE = "GATTACA"; + private static final int TEST_ORGANISM_ID = 1234; + private static final String TEST_ORGANISM_COMMON = "Common"; + private static final String TEST_ORGANISM_SCIENTIFIC = "Scientific"; + private DefaultXref rnaCentralId; + private DefaultXref ensemblId; + + @Before + public void initialiseFetcherAndEnricher() { + mockNucleicAcidFetcher = new MockNucleicAcidFetcher(); + mockEnsemblNucleicAcidFetcher = new MockNucleicAcidFetcher(); + + enricher = new FullNucleicAcidEnricher(mockNucleicAcidFetcher); + enricher.setEnsemblFetcher(mockEnsemblNucleicAcidFetcher); + + CvTerm identity = CvTermUtils.createIdentityQualifier(); + CvTerm rnaCentral = CvTermUtils.createRNACentralDatabase(); + + + NucleicAcid fullNucleicAcid = new DefaultNucleicAcid(TEST_SHORTNAME, TEST_FULLNAME); + rnaCentralId = new DefaultXref(rnaCentral, TEST_AC_FULL, identity); + fullNucleicAcid.getIdentifiers().add(rnaCentralId); + fullNucleicAcid.setSequence(TEST_SEQUENCE); + fullNucleicAcid.setOrganism(new DefaultOrganism(TEST_ORGANISM_ID, TEST_ORGANISM_COMMON, TEST_ORGANISM_SCIENTIFIC)); + mockNucleicAcidFetcher.addEntry(TEST_AC_FULL, List.of(fullNucleicAcid)); + + NucleicAcid ensemblTranscript = new DefaultNucleicAcid(TEST_SHORTNAME, TEST_FULLNAME_ENSEMBL); + CvTerm ensembl = CvTermUtils.createEnsemblDatabase(); + ensemblId = new DefaultXref(ensembl, TEST_AC_ENSEMBL, identity); + ensemblTranscript.getIdentifiers().add(ensemblId); + mockEnsemblNucleicAcidFetcher.addEntry(TEST_AC_ENSEMBL, List.of(ensemblTranscript)); + } + + @Test + public void test_correct_fetcher_used() throws EnricherException { + NucleicAcid rnaCentral = new DefaultNucleicAcid(TEST_SHORTNAME); + rnaCentral.getIdentifiers().add(rnaCentralId); + assertNull(rnaCentral.getFullName()); + + this.enricher.enrich(rnaCentral); + + assertFalse(rnaCentral.getFullName().endsWith("ENSEMBL")); + + NucleicAcid ensembl = new DefaultNucleicAcid(TEST_SHORTNAME); + ensembl.getIdentifiers().add(ensemblId); + assertNull(ensembl.getFullName()); + + this.enricher.enrich(ensembl); + + assertTrue(ensembl.getFullName().endsWith("ENSEMBL")); + } + + @Test + public void test_sequence_added() throws EnricherException { + NucleicAcid rnaCentral = new DefaultNucleicAcid(TEST_SHORTNAME); + rnaCentral.getIdentifiers().add(rnaCentralId); + assertNull(rnaCentral.getSequence()); + + this.enricher.enrich(rnaCentral); + + assertEquals(TEST_SEQUENCE, rnaCentral.getSequence()); + } + +} diff --git a/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/MinimalGeneEnricherTest.java b/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/MinimalGeneEnricherTest.java index 4a4a7a0683..1a4d69a67e 100644 --- a/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/MinimalGeneEnricherTest.java +++ b/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/MinimalGeneEnricherTest.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.List; import static junit.framework.Assert.*; @@ -33,6 +34,7 @@ public class MinimalGeneEnricherTest { private MinimalGeneEnricher geneEnricher; + private MockGeneFetcher mockEnsemblGeneFetcher; private MockGeneFetcher mockGeneFetcher; Gene persistentGene; @@ -42,30 +44,40 @@ public class MinimalGeneEnricherTest { private static final String TEST_OLD_FULLNAME = "test old fullName"; private static final String TEST_AC_CUSTOM_GENE = "ENSG00000139617"; private static final String TEST_SHORTNAME = "test shortName"; + private static final String TEST_SHORTNAME_REF_SEQ = TEST_SHORTNAME + " : RefSeq"; private static final String TEST_FULLNAME = "test fullName"; + private static final String TEST_FULLNAME_REF_SEQ = TEST_FULLNAME + " : RefSeq"; private static final String TEST_AC_FULL_GENE = "ENSG00000139618"; private static final String TEST_AC_HALF_GENE = "ENSG00000139616"; + private static final String TEST_AC_REF_SEQ = "NM_058074.4"; private static final int TEST_ORGANISM_ID = 1234; private static final String TEST_ORGANISM_COMMON = "Common"; private static final String TEST_ORGANISM_SCIENTIFIC = "Scientific"; @Before public void initialiseFetcherAndEnricher() { + mockEnsemblGeneFetcher = new MockGeneFetcher(); mockGeneFetcher = new MockGeneFetcher(); geneEnricher = new MinimalGeneEnricher(mockGeneFetcher); + geneEnricher.setEnsemblFetcher(mockEnsemblGeneFetcher); + + Organism organism = new DefaultOrganism(TEST_ORGANISM_ID, TEST_ORGANISM_COMMON, TEST_ORGANISM_SCIENTIFIC); Gene fullGene = new DefaultGene(TEST_SHORTNAME, TEST_FULLNAME); fullGene.setEnsembl(TEST_AC_FULL_GENE); - fullGene.setOrganism(new DefaultOrganism(TEST_ORGANISM_ID, TEST_ORGANISM_COMMON, TEST_ORGANISM_SCIENTIFIC)); - Collection fullGeneList = new ArrayList(); - fullGeneList.add(fullGene); - mockGeneFetcher.addEntry(TEST_AC_FULL_GENE, fullGeneList); + fullGene.setOrganism(organism); + mockEnsemblGeneFetcher.addEntry(TEST_AC_FULL_GENE, List.of(fullGene)); Gene halfGene = new DefaultGene(TEST_SHORTNAME); halfGene.setEnsembl(TEST_AC_HALF_GENE); Collection halfGeneList = new ArrayList(); halfGeneList.add(halfGene); - mockGeneFetcher.addEntry(TEST_AC_HALF_GENE, halfGeneList); + mockEnsemblGeneFetcher.addEntry(TEST_AC_HALF_GENE, halfGeneList); + + Gene fullGeneRefSeq = new DefaultGene(TEST_SHORTNAME_REF_SEQ, TEST_FULLNAME_REF_SEQ); + fullGene.setEnsembl(TEST_AC_REF_SEQ); + fullGene.setOrganism(organism); + mockGeneFetcher.addEntry(TEST_AC_REF_SEQ, List.of(fullGeneRefSeq)); persistentGene = null; persistentInt = 0; @@ -366,7 +378,7 @@ public void test_organism_conflict_between_organism_TAXIDs_stops_enrichment() th customGene.setOrganism(new DefaultOrganism(9898)); Collection customList = new ArrayList(); customList.add(customGene); - mockGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); + mockEnsemblGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); persistentGene = new DefaultGene(TEST_OLD_SHORTNAME, TEST_OLD_FULLNAME); persistentGene.setEnsembl(TEST_AC_CUSTOM_GENE); @@ -487,7 +499,7 @@ public void test_organism_and_interactorType_conflicts_both_reported() throws En customGene.setOrganism(new DefaultOrganism(9898)); Collection customList = new ArrayList(); customList.add(customGene); - mockGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); + mockEnsemblGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); persistentGene = new DefaultGene(TEST_OLD_SHORTNAME, TEST_OLD_FULLNAME); persistentGene.setEnsembl(TEST_AC_CUSTOM_GENE); @@ -847,7 +859,7 @@ public void test_shortName_not_enriched_if_not_null() throws EnricherException { customGene.setEnsembl(TEST_AC_CUSTOM_GENE); Collection customList = new ArrayList(); customList.add(customGene); - mockGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); + mockEnsemblGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); assertNotNull(persistentGene.getShortName()); assertEquals(TEST_OLD_SHORTNAME, persistentGene.getShortName()); @@ -967,7 +979,7 @@ public void test_fullName_enriched_if_null() throws EnricherException { Collection customList = new ArrayList(); customList.add(customGene); - mockGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); + mockEnsemblGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); assertNull(persistentGene.getFullName()); @@ -1087,7 +1099,7 @@ public void test_fullName_not_enriched_if_not_null() throws EnricherException { customGene.setEnsembl(TEST_AC_CUSTOM_GENE); Collection customList = new ArrayList(); customList.add(customGene); - mockGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); + mockEnsemblGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); assertNotNull(persistentGene.getFullName()); assertEquals(TEST_OLD_FULLNAME, persistentGene.getFullName()); @@ -1210,7 +1222,7 @@ public void test_identifiers_enriched() throws EnricherException { Collection customList = new ArrayList(); customList.add(customGene); - mockGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); + mockEnsemblGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); assertEquals(2, persistentGene.getIdentifiers().size()); @@ -1354,7 +1366,7 @@ public void test_aliases_enriched() throws EnricherException { Collection customList = new ArrayList(); customList.add(customGene); - mockGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); + mockEnsemblGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); assertEquals(1, persistentGene.getAliases().size()); @@ -1497,7 +1509,7 @@ public void test_xrefs_enriched() throws EnricherException { Collection customList = new ArrayList(); customList.add(customGene); - mockGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); + mockEnsemblGeneFetcher.addEntry(TEST_AC_CUSTOM_GENE, customList); assertEquals(1, persistentGene.getXrefs().size()); @@ -1626,5 +1638,26 @@ public void test_set_organism_if_null() throws EnricherException { // TODO onRefseqUpdate, onGeneNameUpdate + // == Fetcher ==================================================================================== + @Test + public void test_correct_fetcher_used() throws EnricherException { + Gene gene_ref_seq = new DefaultGene(TEST_SHORTNAME_REF_SEQ); + gene_ref_seq.setRefseq(TEST_AC_REF_SEQ); + assertNull(gene_ref_seq.getFullName()); + + this.geneEnricher.enrich(gene_ref_seq); + + assertTrue(gene_ref_seq.getFullName().endsWith("RefSeq")); + + Gene gene_ensembl = new DefaultGene(TEST_SHORTNAME); + gene_ensembl.setEnsembl(TEST_AC_FULL_GENE); + assertNull(gene_ensembl.getFullName()); + + this.geneEnricher.enrich(gene_ensembl); + + assertFalse(gene_ensembl.getFullName().endsWith("RefSeq")); + } + + } diff --git a/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/MinimalNucleicAcidEnricherTest.java b/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/MinimalNucleicAcidEnricherTest.java new file mode 100644 index 0000000000..8e52837145 --- /dev/null +++ b/jami-enricher/src/test/java/psidev/psi/mi/jami/enricher/impl/MinimalNucleicAcidEnricherTest.java @@ -0,0 +1,100 @@ +package psidev.psi.mi.jami.enricher.impl; + +import org.junit.Before; +import org.junit.Test; +import psidev.psi.mi.jami.bridges.fetcher.mock.MockNucleicAcidFetcher; +import psidev.psi.mi.jami.enricher.exception.EnricherException; +import psidev.psi.mi.jami.enricher.impl.minimal.MinimalNucleicAcidEnricher; +import psidev.psi.mi.jami.model.*; +import psidev.psi.mi.jami.model.impl.DefaultNucleicAcid; +import psidev.psi.mi.jami.model.impl.DefaultOrganism; +import psidev.psi.mi.jami.model.impl.DefaultXref; +import psidev.psi.mi.jami.utils.CvTermUtils; + +import java.util.List; + +import static junit.framework.Assert.*; + +/** + * Unit tests for MinimalProteinEnricher + * + * @author Gabriel Aldam (galdam@ebi.ac.uk) + * @since 23/05/13 + */ + +public class MinimalNucleicAcidEnricherTest { + + private MinimalNucleicAcidEnricher enricher; + private MockNucleicAcidFetcher mockNucleicAcidFetcher; + private MockNucleicAcidFetcher mockEnsemblNucleicAcidFetcher; + + private static final String TEST_SHORTNAME = "test shortName"; + private static final String TEST_FULLNAME = "test fullName"; + private static final String TEST_FULLNAME_ENSEMBL = "test fullName ENSEMBL"; + private static final String TEST_AC_FULL = "URS000055C986_4896"; + private static final String TEST_AC_ENSEMBL = "ENST00000652534"; + private static final String TEST_SEQUENCE = "GATTACA"; + private static final int TEST_ORGANISM_ID = 1234; + private static final String TEST_ORGANISM_COMMON = "Common"; + private static final String TEST_ORGANISM_SCIENTIFIC = "Scientific"; + private DefaultXref rnaCentralId; + private DefaultXref ensemblId; + + @Before + public void initialiseFetcherAndEnricher() { + mockNucleicAcidFetcher = new MockNucleicAcidFetcher(); + mockEnsemblNucleicAcidFetcher = new MockNucleicAcidFetcher(); + + enricher = new MinimalNucleicAcidEnricher(mockNucleicAcidFetcher); + enricher.setEnsemblFetcher(mockEnsemblNucleicAcidFetcher); + + CvTerm identity = CvTermUtils.createIdentityQualifier(); + CvTerm rnaCentral = CvTermUtils.createRNACentralDatabase(); + + + NucleicAcid fullNucleicAcid = new DefaultNucleicAcid(TEST_SHORTNAME, TEST_FULLNAME); + rnaCentralId = new DefaultXref(rnaCentral, TEST_AC_FULL, identity); + fullNucleicAcid.getIdentifiers().add(rnaCentralId); + fullNucleicAcid.setSequence(TEST_SEQUENCE); + fullNucleicAcid.setOrganism(new DefaultOrganism(TEST_ORGANISM_ID, TEST_ORGANISM_COMMON, TEST_ORGANISM_SCIENTIFIC)); + mockNucleicAcidFetcher.addEntry(TEST_AC_FULL, List.of(fullNucleicAcid)); + + NucleicAcid ensemblTranscript = new DefaultNucleicAcid(TEST_SHORTNAME, TEST_FULLNAME_ENSEMBL); + CvTerm ensembl = CvTermUtils.createEnsemblDatabase(); + ensemblId = new DefaultXref(ensembl, TEST_AC_ENSEMBL, identity); + ensemblTranscript.getIdentifiers().add(ensemblId); + mockEnsemblNucleicAcidFetcher.addEntry(TEST_AC_ENSEMBL, List.of(ensemblTranscript)); + } + + @Test + public void test_correct_fetcher_used() throws EnricherException { + NucleicAcid rnaCentral = new DefaultNucleicAcid(TEST_SHORTNAME); + rnaCentral.getIdentifiers().add(rnaCentralId); + assertNull(rnaCentral.getFullName()); + + this.enricher.enrich(rnaCentral); + + assertFalse(rnaCentral.getFullName().endsWith("ENSEMBL")); + + NucleicAcid ensembl = new DefaultNucleicAcid(TEST_SHORTNAME); + ensembl.getIdentifiers().add(ensemblId); + assertNull(ensembl.getFullName()); + + this.enricher.enrich(ensembl); + + assertTrue(ensembl.getFullName().endsWith("ENSEMBL")); + } + + @Test + public void test_sequence_not_added() throws EnricherException { + NucleicAcid rnaCentral = new DefaultNucleicAcid(TEST_SHORTNAME); + rnaCentral.getIdentifiers().add(rnaCentralId); + assertNull(rnaCentral.getSequence()); + + this.enricher.enrich(rnaCentral); + + assertNull(rnaCentral.getSequence()); + + } + +} diff --git a/jami-examples/pom.xml b/jami-examples/pom.xml index 7d28340c6e..9b2e5b3f15 100644 --- a/jami-examples/pom.xml +++ b/jami-examples/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-examples diff --git a/jami-html/pom.xml b/jami-html/pom.xml index 20fc22702e..f3e8b50204 100644 --- a/jami-html/pom.xml +++ b/jami-html/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-html diff --git a/jami-imex-updater/pom.xml b/jami-imex-updater/pom.xml index 9cd1508990..a1bfa9e451 100644 --- a/jami-imex-updater/pom.xml +++ b/jami-imex-updater/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-imex-updater diff --git a/jami-interactionviewer-json/pom.xml b/jami-interactionviewer-json/pom.xml index 0760e18016..88e8857130 100644 --- a/jami-interactionviewer-json/pom.xml +++ b/jami-interactionviewer-json/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-interactionviewer-json diff --git a/jami-mitab/pom.xml b/jami-mitab/pom.xml index 15a4bca52d..4c2d825503 100644 --- a/jami-mitab/pom.xml +++ b/jami-mitab/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-mitab diff --git a/jami-xml/pom.xml b/jami-xml/pom.xml index a7aac3668c..2944308f87 100644 --- a/jami-xml/pom.xml +++ b/jami-xml/pom.xml @@ -4,7 +4,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 jami-xml diff --git a/pom.xml b/pom.xml index c1f52adf61..aef8aa372d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ psidev.psi.mi.jami psi-jami - 3.4.1 + 3.5.0 pom PSI :: JAMI - Java framework for molecular interactions @@ -15,9 +15,9 @@ UTF-8 4.3.30.RELEASE - 2.1.0 + 2.1.1 2.14-SNAPSHOT - 1.2.4 + 1.1.2 2.4 1.4.197 @@ -167,11 +167,6 @@ nexus-ebi-snapshot-repo https://www.ebi.ac.uk/Tools/maven/repos/content/groups/ebi-snapshots/ - - ebiUniprotPublic - ebi-uniprot-public - https://www.ebi.ac.uk/uniprot/artifactory/public -