+ synchronized private static void inferTaxonomyFromDescendents( final PhylogenyNode n,
+ final SortedSet<String> not_found )
+ throws IOException {
+ if ( n.isExternal() ) {
+ throw new IllegalArgumentException( "attempt to infer taxonomy from descendants of external node" );
+ }
+ n.getNodeData().setTaxonomy( null );
+ final List<PhylogenyNode> descs = n.getDescendants();
+ final List<String[]> lineages = new ArrayList<String[]>();
+ int shortest_lin_length = Integer.MAX_VALUE;
+ for( final PhylogenyNode desc : descs ) {
+ if ( desc.getNodeData().isHasTaxonomy()
+ && ( isHasAppropriateId( desc.getNodeData().getTaxonomy() )
+ || !ForesterUtil.isEmpty( desc.getNodeData().getTaxonomy().getScientificName() )
+ || !ForesterUtil.isEmpty( desc.getNodeData().getTaxonomy().getTaxonomyCode() ) || !ForesterUtil
+ .isEmpty( desc.getNodeData().getTaxonomy().getCommonName() ) ) ) {
+
+ final UniProtTaxonomy up_tax = obtainUniProtTaxonomy( desc.getNodeData().getTaxonomy(), null, null );
+ String[] lineage = null;
+ if ( up_tax != null ) {
+ //lineage = obtainLineagePlusOwnScientificName( up_tax );
+ lineage = up_tax.getLineageAsArray();
+ }
+ if ( ( lineage == null ) || ( lineage.length < 1 ) ) {
+ //TODO remove me
+ System.out.println( "node " + desc.getNodeData().getTaxonomy().toString() + " has no lineage!" );
+ not_found.add( desc.getNodeData().getTaxonomy().asText().toString() );
+ return;
+ }
+ if ( lineage.length < shortest_lin_length ) {
+ shortest_lin_length = lineage.length;
+ }
+ lineages.add( lineage );
+ }
+ else {
+ String msg = "Node(s) with no or inappropriate taxonomic information found";
+ String node = "";
+ if ( !ForesterUtil.isEmpty( desc.getName() ) ) {
+ node = "\"" + desc.getName() + "\"";
+ }
+ else {
+ node = "[" + desc.getId() + "]";
+ }
+ msg = "Node " + node + " has no or inappropriate taxonomic information";
+ // final List<PhylogenyNode> e = desc.getAllExternalDescendants();
+ //TODO remove me!
+// System.out.println();
+// int x = 0;
+// for( final PhylogenyNode object : e ) {
+// System.out.println( x + ":" );
+// System.out.println( object.getName() + " " );
+// x++;
+// }
+// System.out.println();
+ //
+ throw new IllegalArgumentException( msg );
+ }
+ }
+ String last_common_lineage = null;
+ if ( shortest_lin_length > 0 ) {
+ I: for( int i = 0; i < shortest_lin_length; ++i ) {
+ final String lineage_0 = lineages.get( 0 )[ i ];
+ for( int j = 1; j < lineages.size(); ++j ) {
+ if ( !lineage_0.equals( lineages.get( j )[ i ] ) ) {
+ break I;
+ }
+ }
+ last_common_lineage = lineage_0;
+ }
+ }
+ if ( last_common_lineage == null ) {
+ System.out.println( "No common lineage for:" );
+ int counter = 0;
+ for( final String[] strings : lineages ) {
+ System.out.print( counter + ": " );
+ ++counter;
+ for( final String string : strings ) {
+ System.out.print( string + " " );
+ }
+ System.out.println();
+ }
+ return;
+ }
+ final Taxonomy tax = new Taxonomy();
+ n.getNodeData().setTaxonomy( tax );
+ tax.setScientificName( last_common_lineage );
+ final UniProtTaxonomy up_tax = obtainUniProtTaxonomyFromSn( last_common_lineage, lineage );
+ if ( up_tax != null ) {
+ if ( !ForesterUtil.isEmpty( up_tax.getRank() ) ) {
+ try {
+ tax.setRank( up_tax.getRank().toLowerCase() );
+ }
+ catch ( final PhyloXmlDataFormatException ex ) {
+ tax.setRank( "" );
+ }
+ }
+ if ( !ForesterUtil.isEmpty( up_tax.getId() ) ) {
+ tax.setIdentifier( new Identifier( up_tax.getId(), "uniprot" ) );
+ }
+ if ( !ForesterUtil.isEmpty( up_tax.getCommonName() ) ) {
+ tax.setCommonName( up_tax.getCommonName() );
+ }
+ if ( !ForesterUtil.isEmpty( up_tax.getSynonym() ) && !tax.getSynonyms().contains( up_tax.getSynonym() ) ) {
+ tax.getSynonyms().add( up_tax.getSynonym() );
+ }
+ if ( up_tax.getLineage() != null ) {
+ tax.setLineage( new ArrayList<String>() );
+ for( final String lin : up_tax.getLineage() ) {
+ if ( !ForesterUtil.isEmpty( lin ) ) {
+ tax.getLineage().add( lin );
+ }
+ }
+ }
+
+ }
+ for( final PhylogenyNode desc : descs ) {
+ if ( !desc.isExternal() && desc.getNodeData().isHasTaxonomy()
+ && desc.getNodeData().getTaxonomy().isEqual( tax ) ) {
+ desc.getNodeData().setTaxonomy( null );
+ }
+ }
+ }