package org.nextprot.api.core.service.impl; import com.google.common.collect.ImmutableList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nextprot.api.commons.constants.TerminologyCv; import org.nextprot.api.commons.utils.Tree; import org.nextprot.api.commons.utils.Tree.Node; import org.nextprot.api.core.dao.TerminologyDao; import org.nextprot.api.core.domain.CvTerm; import org.nextprot.api.core.domain.Terminology; import org.nextprot.api.core.service.TerminologyService; import org.nextprot.api.core.utils.TerminologyUtils; import org.nextprot.api.core.utils.graph.OntologyDAG; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; @Service class TerminologyServiceImpl implements TerminologyService { private static final Log LOGGER = LogFactory.getLog(TerminologyServiceImpl.class); @Autowired private TerminologyDao terminologyDao; @Override @Cacheable("terminology-by-accession") public CvTerm findCvTermByAccession(String accession) { return terminologyDao.findTerminologyByAccession(accession); } private static void appendAncestor(Node<CvTerm> node, Set<String> result) { result.add(node.getValue().getAccession()); if (node.getParents() != null && !node.getParents().isEmpty()) { for (Node<CvTerm> parent : node.getParents()) { appendAncestor(parent, result); } } } //TODO TRY TO PLACE THIS ELSEWHERE, BUT PROBABLY SHOULD BE CACHED! @Cacheable("terminology-ancestor-sets") public Set<String> getAncestorSets(List<Tree<CvTerm>> trees, String accession) { Set<String> result = new TreeSet<String>(); for(Tree<CvTerm> tree : trees){ List<Node<CvTerm>> nodes = TerminologyUtils.getNodeListByName(tree, accession); for (Node<CvTerm> node : nodes) { appendAncestor(node, result); } } result.remove(accession); // a term is not it's own ancestor return result; } @Override @Cacheable("terminology-tree-depth") public Terminology findTerminology(TerminologyCv terminologyCv) { List<CvTerm> terms = findCvTermsByOntology(terminologyCv.name()); List<Tree<CvTerm>> result = TerminologyUtils.convertCvTermsToTerminology(terms, 1000); return new Terminology(result, terminologyCv); } @Override @Cacheable("terminology-by-ontology") public List<CvTerm> findCvTermsByOntology(String ontology) { List<CvTerm> terms = terminologyDao.findTerminologyByOntology(ontology); // returns a immutable list when the result is cacheable (this prevents // modifying the cache, since the cache returns a reference) copy on // read and copy on write is too much time consuming return new ImmutableList.Builder<CvTerm>().addAll(terms).build(); } @Override @Cacheable("ontology-dag") public OntologyDAG findOntologyGraph(TerminologyCv terminologyCv) { return new OntologyDAG(terminologyCv, this); } @Override @Cacheable("terminology-all") public List<CvTerm> findAllCVTerms() { List<CvTerm> terms = terminologyDao.findAllTerminology(); // returns a immutable list when the result is cacheable (this prevents // modifying the cache, since the cache returns a reference) copy on // read and copy on write is too much time consuming return new ImmutableList.Builder<CvTerm>().addAll(terms).build(); } @Override @Cacheable("enzyme-terminology") // TODO there should be an utiliy method on // entry to get the enzymes... public List<CvTerm> findEnzymeByMaster(String entryName) { Set<String> accessions = new HashSet<String>(terminologyDao.findEnzymeAcsByMaster(entryName)); if (!accessions.isEmpty()) { // is found accessions gets the // corresponding terminology List<CvTerm> terms = terminologyDao.findTerminologyByAccessions(accessions); // returns a immutable list when the result is cacheable (this // prevents modifying the cache, since the cache returns a // reference) copy on read and copy on write is too much time // consuming return new ImmutableList.Builder<CvTerm>().addAll(terms).build(); } else return new ImmutableList.Builder<CvTerm>().build(); // returns // empty // list } @Override public List<CvTerm> findCvTermsByAccessions(Set<String> terminologyAccessions) { List<CvTerm> terms = terminologyDao.findTerminologyByAccessions(terminologyAccessions); // returns a immutable list when the result is cacheable (this prevents // modifying the cache, since the cache returns a reference) copy on // read and copy on write is too much time consuming return new ImmutableList.Builder<CvTerm>().addAll(terms).build(); } @Override @Cacheable("terminology-names") public List<String> findTerminologyNamesList() { return new ImmutableList.Builder<String>().addAll(terminologyDao.findTerminologyNamesList()).build(); } }