/*
* Copyright (c) 2007 Genome Research Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program; see the file COPYING.LIB. If not, write to
* the Free Software Foundation Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307 USA
*/
package org.genedb.db.taxon;
import org.apache.log4j.Logger;
import org.genedb.db.dao.PhylogenyDao;
import org.gmod.schema.mapped.Phylonode;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class TaxonNodeManager implements InitializingBean {
private static Logger logger = Logger.getLogger(TaxonNodeManager.class);
private PhylogenyDao phylogenyDao;
private Map<String, TaxonNode> labelTaxonNodeMap = new HashMap<String, TaxonNode>();
private Map<String, TaxonNode> taxonTaxonNodeMap = new HashMap<String, TaxonNode>();
private Map<String, TaxonNode> fullNameTaxonNodeMap = new HashMap<String, TaxonNode>();
private Map<String, TaxonNode> nickNameTaxonNodeMap = new HashMap<String, TaxonNode>();
@Transactional
public void afterPropertiesSet() throws Exception {
//Session session = SessionFactoryUtils.doGetSession(sessionFactory, true);
//TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
try {
//System.err.println("Session is '"+session+"'");
Set<TaxonNode> nodes = new HashSet<TaxonNode>();
List<Phylonode> phylonodes = phylogenyDao.getAllPhylonodes();
if (phylonodes == null || phylonodes.size() == 0) {
throw new RuntimeException("Got empty list for phylonodes");
}
for (Phylonode phylonode: phylonodes) {
TaxonNode tn = new TaxonNode(phylonode);
nodes.add(tn);
labelTaxonNodeMap.put(tn.getLabel(), tn);
taxonTaxonNodeMap.put(tn.getTaxonId(), tn);
fullNameTaxonNodeMap.put(tn.getName(TaxonNameType.FULL), tn);
String tmp = tn.getName(TaxonNameType.NICKNAME);
if (tmp != null) {
nickNameTaxonNodeMap.put(tn.getName(TaxonNameType.NICKNAME), tn);
}
}
// Set up all child/parent relationships
while (nodes.size() > 0) {
Set<TaxonNode> tempNodes = new HashSet<TaxonNode>();
for (TaxonNode tn: nodes) {
Phylonode phylonode = tn.getPhylonode();
Phylonode parent = phylonode.getParent();
if (parent != null) {
if (labelTaxonNodeMap.containsKey(parent.getLabel())) {
TaxonNode parentTn = labelTaxonNodeMap.get(parent.getLabel());
parentTn.addChild(tn);
} else {
//System.err.println("No match for '"+node.getLabel()+"'");
tempNodes.add(tn);
}
} else {
logger.trace("Skipping one - maybe Root?");
}
}
nodes = tempNodes;
}
//System.err.println("Session is '"+session+"'");
//Initialise phylonodes with organism features
findPhylonodeWithOrganismFeatures();
}
finally {
//TransactionSynchronizationManager.unbindResource(sessionFactory);
//SessionFactoryUtils.closeSession(session);
}
}
/**
* Initialise taxons with organism features with boolean flag
*/
private void findPhylonodeWithOrganismFeatures(){
TaxonNode root = getTaxonNodeForLabel("Root");
if (root == null){
throw new RuntimeException("No taxon with \"Root\" has label exists");
}else{
List<TaxonNode> children = root.getAllChildren();
for (TaxonNode child : children) {
if (!child.isOrganism()) {
continue;
}
if (child.isPopulated()) {
child.setChildrenPopulated(true);
}
}
//System.out.println("Filtering the taxons....");
//initPhylonodeWithOrganismFeatures(node);
}
}
/**
* Initialise taxons with organism features with boolean flag
* @param node
* @return
*/
// private boolean initPhylonodeWithOrganismFeatures(TaxonNode node){
// List<TaxonNode> childNodes = node.getChildren();
// if (childNodes.size() > 0) {
// for (TaxonNode childNode : childNodes) {
// if (initPhylonodeWithOrganismFeatures(childNode)) {
// //node.setHasOrganismFeature(true);
// }
// }
// } else {
// if (phylogenyDao.isPhylonodeWithOrganismFeature(node.getPhylonode())) {
// //node.setHasOrganismFeature(true);
// }
// }
// return true;//node.hasOrganismFeature();
// }
boolean validateTaxons(List<String> taxons, List<String> problems) {
boolean problem = false;
Set<String> uniqs = new HashSet<String>(taxons.size());
for (String taxon : taxons) {
if (!validateTaxon(taxon)) {
problems.add(taxon);
problem = true;
} else {
uniqs.add(taxon);
}
}
// If collections are same size no problems and no dupes so leave taxons be
if (uniqs.size() < taxons.size()) {
taxons.clear();
taxons.addAll(uniqs);
}
return problem;
}
public List<TaxonNode> getHierarchy(TaxonNode start) {
TaxonNode node = start;
List<TaxonNode> ret = new LinkedList<TaxonNode>();
ret.add(node);
while (!node.isRoot()) {
node = node.getParent();
ret.add(0, node);
}
return ret;
}
boolean validateTaxon(String taxon) {
return false; // FIXME
}
String getNameForTaxonId(String taxonId) {
return null; // FIXME
}
public TaxonNode getTaxonNodeForLabel(String label) {
return labelTaxonNodeMap.get(label);
}
public TaxonNode getTaxonNodeByString(String name, boolean includeNickName) {
TaxonNode ret = getTaxonNodeForLabel(name);
if (ret != null) {
return ret;
}
ret = taxonTaxonNodeMap.get(name);
if (ret != null) {
return ret;
}
ret = fullNameTaxonNodeMap.get(name);
if (ret != null) {
return ret;
}
if (!includeNickName) {
return ret;
}
return nickNameTaxonNodeMap.get(name);
}
@Required
public void setPhylogenyDao(PhylogenyDao phylogenyDao) {
this.phylogenyDao = phylogenyDao;
}
public List<String> getNamesListForTaxons(TaxonNodeList taxons) {
if (taxons == null || taxons.getNodeCount() == 0) {
return Collections.emptyList();
}
Set<String> dupes = new HashSet<String>();
logger.error("The size of taxon array is '"+taxons.getNodeCount()+"'");
for (TaxonNode taxonNode : taxons.getNodes()) {
logger.error("taxonNode: "+taxonNode);
dupes.addAll(taxonNode.getAllChildrenNames());
}
return new ArrayList<String>(dupes);
}
public String getSingleStringVersion(List<String> orgNames) {
if (orgNames == null || orgNames.size() > 0) {
return "Root";
}
return StringUtils.collectionToDelimitedString(orgNames, ":");
}
// the method below had been removed because we now need to filter on organisms that aren't public
// public List<String> getAllOrgNamesUnlessRoot(TaxonNodeList taxonNodeList) {
// if (taxonNodeList.getNodes().size() == 1 && taxonNodeList.getNodes().get(0).isRoot()) {
// return null;
// }
// List<String> ret = Lists.newArrayList();
// if (taxonNodeList.getNodes().size() > 0) {
// for (TaxonNode tn : taxonNodeList.getNodes()) {
// ret.addAll(tn.getAllChildrenNames());
// }
// }
// return ret;
// }
}