001/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ 002/* 003 * BioJava development code 004 * 005 * This code may be freely distributed and modified under the 006 * terms of the GNU Lesser General Public Licence. This should 007 * be distributed with the code. If you do not have a copy, 008 * see: 009 * 010 * http://www.gnu.org/copyleft/lesser.html 011 * 012 * Copyright for this code is held jointly by the individual 013 * authors. These should be listed in @author doc comments. 014 * 015 * For more information on the BioJava project and its aims, 016 * or to join the biojava-l mailing list, visit the home page 017 * at: 018 * 019 * http://www.biojava.org/ 020 * 021 */ 022 023package org.biojava.bio.seq.db.biosql; 024 025import java.io.BufferedReader; 026import java.io.File; 027import java.io.FileReader; 028import java.io.IOException; 029import java.sql.Connection; 030import java.sql.PreparedStatement; 031import java.sql.ResultSet; 032import java.sql.SQLException; 033import java.sql.Statement; 034import java.sql.Types; 035import java.util.ArrayList; 036import java.util.Collection; 037import java.util.HashMap; 038import java.util.HashSet; 039import java.util.Iterator; 040import java.util.List; 041import java.util.Map; 042import java.util.NoSuchElementException; 043import java.util.Set; 044import java.util.Stack; 045 046import org.biojava.bio.Annotation; 047import org.biojava.bio.BioException; 048import org.biojava.bio.BioRuntimeException; 049import org.biojava.bio.taxa.CircularReferenceException; 050import org.biojava.bio.taxa.EbiFormat; 051import org.biojava.bio.taxa.Taxon; 052import org.biojava.bio.taxa.TaxonFactory; 053import org.biojava.bio.taxa.WeakTaxonFactory; 054import org.biojava.utils.ChangeVetoException; 055 056/** 057 * Methods for retrieving, storing and manipulate Taxa stored in a BioSQL database. 058 * 059 * @author Len Trigg 060 * @author Andreas Dräger 061 * @deprecated Use hibernate and org.biojavax.bio.db.* 062 */ 063public class TaxonSQL { 064 065 /** 066 * Attempts to get a Taxon object corresponding to the specified 067 * NCBI taxon ID. 068 * 069 * @param conn the connection to the database 070 * @param ncbi_taxon_id the NCBI taxon ID. 071 * @return the corresponding Taxon (which may have already been 072 * present in memory after an earlier retrieval), or null if the 073 * Taxon could not be found in the database. 074 */ 075 public static Taxon getTaxon(Connection conn, int ncbi_taxon_id) 076 { 077 PreparedStatement ps = null; 078 ResultSet rs = null; 079 Taxon t = null; 080 try { 081 ps = conn.prepareStatement( 082 "SELECT name " + 083 "FROM taxon_name, taxon " + 084 "WHERE taxon_name.taxon_id = taxon.taxon_id AND" + 085 " taxon_name.name_class LIKE 'scientific%' AND" + 086 " ncbi_taxon_id = ?"); 087 ps.setInt(1, ncbi_taxon_id); 088 rs = ps.executeQuery(); 089 if (rs.next()) t = getTaxon(conn, rs.getString(1)); 090 } catch (SQLException exc) { 091 throw new BioRuntimeException(exc); 092 } finally { 093 attemptClose(rs); 094 attemptClose(ps); 095 } 096 return t; 097 } 098 099 100 /** 101 * Attempts to get a Taxon object corresponding to the specified 102 * taxon_id (i.e. the database's internal id for the taxon). 103 * 104 * @param conn the connection to the database 105 * @param taxon_id the database-specific id for the Taxon. 106 * @return the corresponding Taxon (which may have already been 107 * present in memory after an earlier retrieval). 108 */ 109 public static Taxon getDBTaxon(Connection conn, int taxon_id) throws SQLException, ChangeVetoException 110 { 111 PreparedStatement statement = null; 112 ResultSet rs = null; 113 try { 114 // Constants for our wee id array 115 final int NCBI_ID = 1; 116 final int TAXON_ID = 0; 117 118 // First, get the taxon ids up to the root. 119 statement = conn.prepareStatement( 120 "SELECT ncbi_taxon_id, parent_taxon_id "+ 121 "FROM taxon "+ 122 "WHERE taxon_id = ? "); 123 124 ArrayList path = new ArrayList(); 125 while (taxon_id != 0) { 126 statement.setInt(1, taxon_id); 127 rs = statement.executeQuery(); 128 if (rs.next()) { 129 path.add(new int [] {taxon_id, rs.getInt(1)}); 130 taxon_id = rs.getInt(2); 131 if (rs.wasNull()) 132 taxon_id = 0; 133 } else 134 throw new BioRuntimeException("Error fetching taxonomy structure. No taxon with taxon_id=" + taxon_id); 135 rs.close(); 136 } 137 statement.close(); 138 139 // Traverse from the root down as far has has been created previously... 140 TaxonFactory factory = WeakTaxonFactory.GLOBAL; 141 Taxon taxon = factory.getRoot(); 142 int pos = path.size() - 1; 143 int []ids = (int[]) path.get(pos--); 144 Map names = getTaxonNames(conn, ids[TAXON_ID]); 145 taxon.getAnnotation().setProperty(EbiFormat.PROPERTY_NCBI_TAXON, "" + ids[NCBI_ID]); 146 taxon.getAnnotation().setProperty(EbiFormat.PROPERTY_TAXON_NAMES, names); 147 for (; pos >= 0; pos--) { 148 // Who's the next id down the path? 149 ids = (int[]) path.get(pos); 150 String nextID = "" + ids[NCBI_ID]; 151 // Now look among the children for the next child. 152 Set children = taxon.getChildren(); 153 for (Iterator it = children.iterator(); it.hasNext(); ) { 154 Taxon child = (Taxon) it.next(); 155 Annotation anno = child.getAnnotation(); 156 if (anno.containsProperty(EbiFormat.PROPERTY_NCBI_TAXON)) { 157 String childID = (String) anno.getProperty(EbiFormat.PROPERTY_NCBI_TAXON); 158 if (childID.equals(nextID)) { 159 taxon = child; 160 continue; 161 } 162 } else { 163 throw new BioRuntimeException("Taxon has not been annotated with NCBI taxon ids."); 164 } 165 } 166 // No child with desired ncbi_id has been found. 167 break; 168 } 169 170 // Now create taxa from here on down. 171 try { 172 for (; pos >= 0; pos--) 173 { 174 // Now look for the next child. 175 ids = (int[]) path.get(pos); 176 String nextID = "" + ids[NCBI_ID]; 177 names = getTaxonNames(conn, ids[TAXON_ID]); 178 String sciName = (String) names.get("scientific name"); 179 if (sciName == null) 180 throw new BioRuntimeException("No scientific name for taxon_id=" + ids[TAXON_ID]); 181 String commonName = (String) names.get("common name"); 182 taxon = factory.addChild(taxon, factory.createTaxon(sciName, commonName)); 183 taxon.getAnnotation().setProperty(EbiFormat.PROPERTY_NCBI_TAXON, nextID); 184 taxon.getAnnotation().setProperty(EbiFormat.PROPERTY_TAXON_NAMES, names); 185 taxon = getProperties(conn, taxon); 186 } 187 } catch (CircularReferenceException ex) { 188 throw new BioRuntimeException("Circular references in taxon table. taxon_id=" + ids[TAXON_ID]); 189 } 190 191 return getProperties(conn, taxon); 192 } finally { 193 attemptClose(rs); 194 attemptClose(statement); 195 } 196 } 197 198 199 /** 200 * Look up all the names associated with a taxon_id. 201 * 202 * @param conn the current <code>Connection</code>. 203 * @param taxon_id the NCBI taxon id for the taxon of interest. 204 * @return a <code>Map</code> from name_class (e.g.: "scientific 205 * name") to name. 206 */ 207 private static Map getTaxonNames(Connection conn, int taxon_id) 208 { 209 PreparedStatement statement = null; 210 ResultSet rs = null; 211 try { 212 statement = conn.prepareStatement( 213 "SELECT name_class, name "+ 214 "FROM taxon_name "+ 215 "WHERE taxon_id = ? "); 216 statement.setInt(1, taxon_id); 217 rs = statement.executeQuery(); 218 219 Map names = new HashMap(); 220 while (rs.next()) { 221 String name_class = rs.getString(1); 222 String name = rs.getString(2); 223 if ((name_class.equals("scientific name")) || 224 (name_class.equals("common name"))) 225 names.put(name_class, name); 226 else { 227 Set s = new HashSet(); 228 s.add(name); 229 if (names.containsKey(name_class)) 230 s.addAll((Collection) names.get(name_class)); 231 names.put(name_class, s); 232 } 233 } 234 235 return names; 236 } catch (SQLException ex) { 237 throw new BioRuntimeException("Error fetching taxonomy annotations", ex); 238 } finally { 239 attemptClose(rs); 240 attemptClose(statement); 241 } 242 } 243 244 245 /** 246 * Adds a <code>Taxon</code> (along with its parents) to the 247 * database. If it is already present in the database, no action 248 * is taken. Returns the id by which the database refers to the 249 * specified <code>Taxon</code> object. 250 * 251 * @param taxon a <code>Taxon</code>. The <code>Taxon</code> must 252 * be annotated with the NCBI taxon id 253 * (<code>key=EbiFormat.PROPERTY_ORGANISM</code>). 254 * @param helper for the certain database system which is in use. 255 * @return an <code>int</code> that corresponds to the 256 * <code>Taxon</code> in the database. 257 */ 258 public static int putTaxon(Connection conn, DBHelper helper, Taxon taxon) throws SQLException 259 { 260 // Find the NCBI taxon id annotation 261 Annotation anno = taxon.getAnnotation(); 262 Object t = anno.getProperty(EbiFormat.PROPERTY_NCBI_TAXON); 263 if (t instanceof List) { 264 t = (String) ((List) t).get(0); 265 } 266 int ncbi_taxon_id = Integer.parseInt((String) t); 267 PreparedStatement selectTaxon = conn.prepareStatement( 268 "select taxon_id " 269 + "from taxon " 270 + "where ncbi_taxon_id = ? " 271 ); 272 selectTaxon.setInt(1, ncbi_taxon_id); 273 ResultSet trs = selectTaxon.executeQuery(); 274 int taxon_id; 275 if (trs.next()) { 276 // entry exists - link to it 277 taxon_id = trs.getInt(1); 278 } else { 279 // Taxon entry does not exist - create it 280 Taxon parent = taxon.getParent(); 281 282 // Mein modifizierter Code: 283 String rank, gencode, mitocode, left, right; 284 285 rank = gencode = mitocode = left = right = "NULL"; 286 287 if (taxon.getAnnotation().containsProperty("rank")) 288 rank = taxon.getAnnotation().getProperty("rank").toString(); 289 if (taxon.getAnnotation().containsProperty("genetic code id")) 290 gencode = taxon.getAnnotation().getProperty("genetic code id").toString(); 291 if (taxon.getAnnotation().containsProperty("mitochondrial genetic code id")) 292 mitocode = taxon.getAnnotation().getProperty("mitochondrial genetic code id").toString(); 293 if (taxon.getAnnotation().containsProperty("left value")) 294 left = taxon.getAnnotation().getProperty("left value").toString(); 295 if (taxon.getAnnotation().containsProperty("right value")) 296 right = taxon.getAnnotation().getProperty("right value").toString(); 297 298 299 PreparedStatement createTaxon = null; 300 if (parent != null) { 301 int parent_taxon_id = putTaxon(conn, helper, parent); 302 createTaxon = conn.prepareStatement( 303 "insert into taxon " 304 + "(ncbi_taxon_id, parent_taxon_id," 305 + " node_rank, genetic_code," 306 + " mito_genetic_code, left_value," 307 + " right_value) " 308 + "values (?, ?, ?, ?, ?, ?, ?)" 309 ); 310 //System.out.println(ncbi_taxon_id+"\t"+rank+"\t"+gencode+"\t"+"\t"+mitocode+"\t"+left+"\t"+right); 311 createTaxon.setInt(1, ncbi_taxon_id); 312 createTaxon.setInt(2, parent_taxon_id); 313 if (rank.equals("NULL")) 314 createTaxon.setNull(3, Types.VARCHAR); 315 else createTaxon.setString(3, rank); 316 if (gencode.equals("NULL")) 317 createTaxon.setNull(4, Types.TINYINT); 318 else createTaxon.setInt(4, new Integer(gencode).intValue()); 319 if (mitocode.equals("NULL")) 320 createTaxon.setNull(5, Types.TINYINT); 321 else createTaxon.setInt(5, new Integer(mitocode).intValue()); 322 if (left.equals("NULL")) 323 createTaxon.setNull(6, Types.INTEGER); 324 else createTaxon.setInt(6, new Integer(left).intValue()); 325 if (right.equals("NULL")) 326 createTaxon.setNull(7, Types.INTEGER); 327 else createTaxon.setInt(7, new Integer(right).intValue()); 328 329 } else { 330 createTaxon = conn.prepareStatement( 331 "insert into taxon " 332 + "(ncbi_taxon_id, node_rank," 333 + " genetic_code, mito_genetic_code," 334 + " left_value, right_value) " 335 + "values (?, ?, ?, ?, ?, ?)" 336 ); 337 createTaxon.setInt(1, ncbi_taxon_id); 338 if (rank.equals("NULL")) 339 createTaxon.setNull(2, Types.VARCHAR); 340 else createTaxon.setString(2, rank); 341 if (gencode.equals("NULL")) 342 createTaxon.setNull(3, Types.TINYINT); 343 else createTaxon.setInt(3, new Integer(gencode).intValue()); 344 if (mitocode.equals("NULL")) 345 createTaxon.setNull(4, Types.TINYINT); 346 else createTaxon.setInt(4, new Integer(mitocode).intValue()); 347 if (left.equals("NULL")) 348 createTaxon.setNull(5, Types.INTEGER); 349 else createTaxon.setInt(5, new Integer(left).intValue()); 350 if (right.equals("NULL")) 351 createTaxon.setNull(6, Types.INTEGER); 352 else createTaxon.setInt(6, new Integer(right).intValue()); 353 } 354 createTaxon.executeUpdate(); 355 createTaxon.close(); 356 taxon_id = helper.getInsertID(conn, "taxon", "taxon_id"); 357 putTaxonNames(conn, (Map) taxon.getAnnotation().getProperty(EbiFormat.PROPERTY_TAXON_NAMES), taxon_id); 358 } 359 trs.close(); 360 selectTaxon.close(); 361 return taxon_id; 362 } 363 364 365 /** Attempts to put all the names of a taxon into the database. There's no need 366 * to access this method, it's only for internal use. 367 * @param conn the connection to the database 368 * @param names a map with the <code>name_class</code> as key and a <code>String</code> 369 * as value or a <code>Set</code> of <code>String</code>s, respectively. 370 * @param taxon_id the internal <code>taxon_id</code> within the database. 371 */ 372 private static void putTaxonNames(Connection conn, Map names, int taxon_id) throws SQLException 373 { 374 if (names != null) { 375 Iterator it = names.keySet().iterator(); 376 while (it.hasNext()) { 377 String nameClass = (String) it.next(); 378 379 // changes: 380 if (names.get(nameClass) instanceof Set) { 381 Set all_names = (Set) names.get(nameClass); 382 Iterator i = all_names.iterator(); 383 while(i.hasNext()) { 384 String name = (String) i.next(); 385 PreparedStatement createTaxon = conn.prepareStatement( 386 "insert into taxon_name " 387 + "(taxon_id, name, name_class) " 388 + "values (?, ?, ?)" 389 ); 390 createTaxon.setInt(1, taxon_id); 391 createTaxon.setString(2, name); 392 createTaxon.setString(3, nameClass); 393 createTaxon.executeUpdate(); 394 createTaxon.close(); 395 } 396 } else { 397 // normal again 398 399 String name = (String) names.get(nameClass); 400 PreparedStatement createTaxon = conn.prepareStatement( 401 "insert into taxon_name " 402 + "(taxon_id, name, name_class) " 403 + "values (?, ?, ?)" 404 ); 405 createTaxon.setInt(1, taxon_id); 406 createTaxon.setString(2, name); 407 createTaxon.setString(3, nameClass); 408 createTaxon.executeUpdate(); 409 createTaxon.close(); 410 } 411 } 412 } 413 } 414 415 416 /** Attempt to close the Statement. Continue on if there is a problem during the close. */ 417 public static void attemptClose(Statement statement) 418 { 419 if (statement != null) try { 420 statement.close(); 421 } catch (SQLException se) { 422 se.printStackTrace(); 423 } 424 } 425 426 427 /** Attempt to close the ResultSet. Continue on if there is a problem during the close. */ 428 public static void attemptClose(ResultSet resultset) 429 { 430 if (resultset != null) try { 431 resultset.close(); 432 } catch (SQLException se) { 433 se.printStackTrace(); 434 } 435 } 436 437 438 /** 439 * Attempts to get a Taxon object corresponding to the specified 440 * name. 441 * 442 * @param conn the connection to the database 443 * @param name the species scientific name 444 * @return the corresponding Taxon (which may have already been 445 * present in memory after an earlier retrieval), or null if the 446 * Taxon could not be found in the database. 447 * @throws BioRuntimeException 448 */ 449 public static Taxon getTaxon(Connection conn, String name) throws BioRuntimeException 450 { 451 PreparedStatement statement = null; 452 ResultSet rs = null; 453 try { 454 int taxon_id = 0; 455 statement = conn.prepareStatement( 456 "SELECT taxon.taxon_id " + 457 "FROM taxon, taxon_name " + 458 "WHERE taxon.taxon_id = taxon_name.taxon_id " + 459 " AND taxon_name.name LIKE ?"); 460 statement.setString(1, name); 461 rs = statement.executeQuery(); 462 if (rs.next()) { 463 taxon_id = rs.getInt(1); 464 if (rs.wasNull()) 465 taxon_id = 0; 466 } 467 rs.close(); 468 statement.close(); 469 470 return (taxon_id != 0) ? getDBTaxon(conn, taxon_id) : null; 471 } catch (ChangeVetoException ex) { 472 throw new BioRuntimeException("Couldn't manipulate in-memory taxonomy", ex); 473 } catch (SQLException ex) { 474 throw new BioRuntimeException("Error fetching taxonomy annotations", ex); 475 } finally { 476 attemptClose(rs); 477 attemptClose(statement); 478 } 479 } 480 481 482 /** Returns all the <code>scientific name</code>s, which are currently stored in the 483 * database. 484 * 485 * @param conn connection to the database 486 * @return array of lexicographically sorted <code>String</code>s 487 * @throws BioRuntimeException 488 */ 489 public static String[] getAllScientificNames(Connection conn) throws BioRuntimeException 490 { 491 String scientific_names[] = null; 492 PreparedStatement statement = null; 493 ResultSet rs = null; 494 try { 495 int taxa_counter = 0, i=0; 496 statement = conn.prepareStatement( 497 "SELECT COUNT(distinct name) " + 498 "FROM taxon_name " + 499 "WHERE name_class LIKE 'scientific name' "); 500 rs = statement.executeQuery(); 501 if (rs.next()) 502 taxa_counter = rs.getInt(1); 503 scientific_names = new String[taxa_counter]; 504 statement = conn.prepareStatement( 505 "SELECT distinct name " + 506 "FROM taxon_name " + 507 "WHERE name_class LIKE 'scientific name' " + 508 "ORDER BY name ASC"); 509 rs = statement.executeQuery(); 510 while (rs.next()) { 511 scientific_names[i++] = rs.getString(1); 512 if (rs.wasNull()) i--; 513 } 514 rs.close(); 515 statement.close(); 516 517 return (taxa_counter != 0) ? scientific_names : null; 518 } catch (SQLException exc) { 519 exc.printStackTrace(); 520 } 521 return null; 522 } 523 524 525 /** Returns the annotated properties of a given taxon. Only for internal use, 526 * since this is needed to construct a fully annotated <code>Taxon</code> object, 527 * which will be returned by one of the getTaxon... methods. 528 * @param conn database connection 529 * @param taxon the taxon to be annotated 530 * @return a fully annotated taxon. 531 * @throws BioRuntimeException 532 */ 533 private static Taxon getProperties(Connection conn, Taxon taxon) throws BioRuntimeException 534 { 535 PreparedStatement ps = null; 536 ResultSet rs = null; 537 538 try { 539 String rank = null, gencode = null, mitocode = null, left = null, right = null; 540 ps = conn.prepareStatement( 541 "SELECT node_rank, genetic_code, mito_genetic_code, left_value, right_value " + 542 "FROM taxon " + 543 "WHERE taxon_id = ?"); 544 ps.setInt(1, getTaxonID(conn, getRealScientificName(taxon))); 545 rs = ps.executeQuery(); 546 if (rs.next()) { 547 rank = rs.getString(1); 548 if (!rs.wasNull()) taxon.getAnnotation().setProperty("rank", rank); 549 gencode = rs.getString(2); 550 if (!rs.wasNull()) taxon.getAnnotation().setProperty("genetic code id", gencode); 551 mitocode = rs.getString(3); 552 if (!rs.wasNull()) taxon.getAnnotation().setProperty("mitochondrial genetic code id", mitocode); 553 left = String.valueOf(rs.getInt(4)); 554 if (!rs.wasNull()) taxon.getAnnotation().setProperty("left value", left); 555 right = String.valueOf(rs.getInt(5)); 556 if (!rs.wasNull()) taxon.getAnnotation().setProperty("right value", right); 557 } 558 } catch (SQLException exc) { 559 throw new BioRuntimeException(exc); 560 } catch (IllegalArgumentException exc) { 561 throw new BioRuntimeException(exc); 562 } catch (ChangeVetoException exc) { 563 throw new BioRuntimeException(exc); 564 } catch (BioException exc) { 565 exc.printStackTrace(); 566 } finally { 567 attemptClose(rs); 568 attemptClose(ps); 569 } 570 571 return taxon; 572 } 573 574 575 /** This returns the true scientific name of a given taxon, if there is one. 576 * This is necessary because if a taxon does not have a parent node, 577 * a <code>TaxonFactory</code> gives the scientific name 'ROOT' and the 578 * real scientific name (if there is one) is only stored in the taxon's 579 * <code>EbiFormat</code>-annotation. This name 'ROOT' applies only for 580 * in memory taxon objects. In the database the real name is stored. 581 * 582 * @param t the taxon 583 * @return Name of the taxon. 584 */ 585 public static String getRealScientificName(Taxon t) 586 { 587 String tName = "root"; 588 if (t.getScientificName() != null) tName = t.getScientificName(); 589 if (tName.toLowerCase().equals("root") && (t.getAnnotation() != null)) 590 if (t.getAnnotation().containsProperty(EbiFormat.PROPERTY_TAXON_NAMES)) 591 if (((Map) t.getAnnotation().getProperty(EbiFormat.PROPERTY_TAXON_NAMES)).containsKey("scientific name")) 592 tName = ((Map) t.getAnnotation().getProperty(EbiFormat.PROPERTY_TAXON_NAMES)).get("scientific name").toString(); 593 return tName; 594 } 595 596 597 /** Returns a <code>Set</code> containing all internal <code>taxon_id</code>s of the database. 598 * @param conn database connection 599 * @return all <code>taxon_id</code>s or internal use of the database. 600 * @throws SQLException 601 */ 602 private static Set ids(Connection conn) throws SQLException 603 { 604 Set ids = new HashSet(); 605 Statement statement = conn.createStatement(); 606 ResultSet rs = statement.executeQuery("SELECT taxon_id FROM taxon"); 607 while (rs.next()) 608 ids.add(new Integer(rs.getInt(1))); 609 attemptClose(rs); 610 statement.close(); 611 612 return ids; 613 } 614 615 616 /** Returns a <code>Set</code> of all NCBI-Taxon-IDs which are currently stored in 617 * the database. So it is easy to proove if a taxon is stored in the database or 618 * perform other operations. 619 * @param conn database connection 620 * @return a <code>Set</code> containing all NCBI-IDs. 621 * @throws BioRuntimeException 622 */ 623 public static Set NCBIids(Connection conn) throws BioRuntimeException 624 { 625 Set ids = new HashSet(); 626 Statement statement = null; 627 ResultSet rs = null; 628 try { 629 statement = conn.createStatement(); 630 rs = statement.executeQuery("SELECT ncbi_taxon_id FROM taxon"); 631 while (rs.next()) 632 ids.add(new Integer(rs.getInt(1))); 633 } catch (SQLException exc) { 634 throw new BioRuntimeException(exc); 635 } finally { 636 try { 637 rs.close(); 638 statement.close(); 639 } catch (SQLException exc1) { 640 throw new BioRuntimeException(exc1); 641 } 642 } 643 return ids; 644 } 645 646 647 /** Deletes a taxon specified by one of it's names with all it's different 648 * names, annotations and sequences from the database. This cannot be undone. 649 * The removed taxon will be returned. 650 * 651 * @param conn database connection 652 * @param helper the helper for the certain database system to be used. 653 * @param name one of the taxon's names 654 * @return the taxon, which was successfully removed and which is not longer 655 * stored in the database. 656 * @throws BioException 657 * @throws SQLException 658 */ 659 public static Taxon removeTaxon(Connection conn, DBHelper helper, String name) throws SQLException, BioException 660 { 661 //if (name.contains("'")) name = name.replace("\'", "\\\'"); 662 //if (name.contains("\"")) name = name.replace("\"", "\\\""); 663 664 return removeTaxon(conn, helper, getTaxonID(conn, name)); 665 } 666 667 668 /** This actually performs the delete operations. 669 * 670 * @param conn 671 * @param helper 672 * @param taxon_id 673 * @return taxon 674 * @throws BioRuntimeException 675 */ 676 private static Taxon removeTaxon(Connection conn, DBHelper helper, int taxon_id) throws BioRuntimeException 677 { 678 Taxon taxon = getTaxon(conn, taxon_id); 679 /* 680 * Children which don't have a parent anymore -> they become their own parent. 681 */ 682 try { 683 Stack children = getChildrenOf(conn, taxon); 684 while (!children.isEmpty()) try { 685 Taxon child = (Taxon) children.pop(); 686 setParent(conn, child, child); 687 } catch (BioRuntimeException exc) { 688 exc.printStackTrace(); 689 } 690 } catch (BioException exc) { 691 exc.printStackTrace(); 692 } 693 try { 694 Statement delete = conn.createStatement(); 695 delete.executeUpdate("DELETE FROM taxon_name WHERE taxon_id = "+taxon_id); 696 delete.close(); 697 delete = (Statement) conn.createStatement(); 698 delete.executeUpdate("DELETE FROM bioentry WHERE taxon_id = "+taxon_id); 699 delete.close(); 700 delete = (Statement) conn.createStatement(); 701 delete.executeUpdate("DELETE FROM taxon WHERE taxon_id = "+taxon_id); 702 delete.close(); 703 } catch (SQLException exc) { 704 throw new BioRuntimeException("Could not delete successfully", exc); 705 } 706 707 return taxon; 708 } 709 710 711 /** Deletes the taxon given by it's NCBI-Taxon-ID from the database and returns the 712 * removed taxon. 713 * @param conn database connection 714 * @param helper the helper for the database 715 * @param ncbi_id the ncbi-id 716 * @return the taxon wich is not stored in the database anymore. 717 * @throws BioRuntimeException 718 * @throws BioException 719 * @throws SQLException 720 */ 721 public static Taxon removeTaxon(Connection conn, int ncbi_id, DBHelper helper) throws BioRuntimeException, SQLException, BioException 722 { 723 return removeTaxon(conn, helper, getTaxonID(conn, getRealScientificName(getTaxon(conn, ncbi_id)))); 724 } 725 726 727 /** This changes the scientific name of the given taxon and stores the new name persistent 728 * in the database. 729 * @param conn database connection 730 * @param taxon the taxon to be changed 731 * @param newName the new scientific name 732 * @return the changed taxon with the new scientific name. 733 * @throws SQLException 734 */ 735 public static Taxon setScientificName(Connection conn, Taxon taxon, String newName) throws SQLException 736 { 737 PreparedStatement updateName = conn.prepareStatement( 738 "UPDATE taxon_name SET name = ? " + 739 "WHERE name LIKE ? AND " + 740 " name_class LIKE ?"); 741 updateName.setString(1, newName); 742 updateName.setString(2, taxon.getScientificName()); 743 updateName.setString(3, "scientific name"); 744 updateName.execute(); 745 attemptClose(updateName); 746 747 return getTaxon(conn, newName); 748 } 749 750 751 /** With this method the common name of the given taxon can be changed or created, 752 * if there was none before. The new common name will be stored persitently. 753 * @param conn database connection 754 * @param taxon the taxon to be updated 755 * @param newName the new common name 756 * @return the updated taxon. 757 * @throws BioException 758 * @throws SQLException 759 */ 760 public static Taxon setCommonName(Connection conn, Taxon taxon, String newName) throws BioException, SQLException 761 { 762 boolean noCommonName = false; 763 String name_class = "common name"; 764 765 /* A taxon does not necessaryly have to have a common name. Let's have a look, 766 * if we need to perform an update or insert operation. 767 */ 768 PreparedStatement question = conn.prepareStatement( 769 "SELECT COUNT(name) " + 770 "FROM taxon_name " + 771 "WHERE name_class LIKE ? AND " + 772 " taxon_id = ?"); 773 question.setString(1, name_class); 774 question.setInt(2, getTaxonID(conn, taxon.getScientificName())); 775 ResultSet rs = question.executeQuery(); 776 777 if (rs.next()) { 778 if (rs.getInt(1) > 0) { 779 attemptClose(rs); 780 attemptClose(question); 781 PreparedStatement updateName = conn.prepareStatement( 782 "UPDATE taxon_name SET name = ? " + 783 "WHERE name LIKE ? AND " + 784 " name_class LIKE ?"); 785 updateName.setString(1, newName); 786 updateName.setString(2, taxon.getScientificName()); 787 updateName.setString(3, name_class); 788 updateName.execute(); 789 attemptClose(updateName); 790 } else noCommonName = true; 791 } 792 if (noCommonName) { 793 attemptClose(rs); 794 attemptClose(question); 795 PreparedStatement insert = conn.prepareStatement( 796 "INSERT INTO taxon_name (taxon_id, name, name_class) VALUES (?, ?, ?)"); 797 try { 798 insert.setInt(1, getTaxonID(conn, taxon.getScientificName())); 799 insert.setString(2, newName); 800 insert.setString(3, name_class); 801 insert.execute(); 802 } catch (BioException exc) { 803 throw exc; 804 } catch (SQLException exc) { 805 throw exc; 806 } finally { 807 attemptClose(insert); 808 } 809 } 810 811 return getTaxon(conn, taxon.getScientificName()); 812 } 813 814 815 /** Returns the internal <code>taxon_id</code> of the taxon specified by the 816 * scientific name. Only for internal use. 817 * @param conn database connection 818 * @param scientificName the scientific name 819 * @return the internal taxon_id of the taxon. 820 * @throws SQLException 821 * @throws BioException 822 */ 823 private static int getTaxonID(Connection conn, String scientificName) throws SQLException, BioException 824 { 825 int taxon_id = -1; 826 827 PreparedStatement taxID = conn.prepareStatement( 828 "SELECT taxon_id " + 829 "FROM taxon_name " + 830 "WHERE name LIKE ? AND " + 831 " name_class LIKE ?"); 832 taxID.setString(1, scientificName); 833 taxID.setString(2, "scientific name"); 834 ResultSet rs = taxID.executeQuery(); 835 if (rs.next()) { 836 taxon_id = rs.getInt(1); 837 attemptClose(rs); 838 attemptClose(taxID); 839 return taxon_id; 840 } 841 attemptClose(rs); 842 attemptClose(taxID); 843 throw new BioException("The database does not contain a taxon named "+scientificName+"."); 844 } 845 846 847 /** Adds a new name of the given <code>nameClass</code> to the taxon. However, there must 848 * be exactly one <code>scientific name</code> and maximal one <code>common 849 * name</code>. Otherwise an <code>Exception</code> will be thrown. 850 * 851 * @param conn database connection 852 * @param taxon the taxon to be updated 853 * @param nameClass the name_class of the new name. 854 * @param newName the new name. 855 * @return the persistently updated taxon. 856 * @throws BioException 857 * @throws SQLException 858 * @throws BioRuntimeException 859 */ 860 public static Taxon addName(Connection conn, Taxon taxon, String nameClass, String newName) throws BioException, SQLException, BioRuntimeException 861 { 862 if (nameClass.equals("scientific name") || nameClass.equals("common name")) 863 throw new BioException("There can only be one "+nameClass+"."); 864 865 PreparedStatement insert = conn.prepareStatement( 866 "INSERT INTO taxon_name (taxon_id, name, name_class) VALUES (?, ?, ?)"); 867 try { 868 insert.setInt(1, getTaxonID(conn, getRealScientificName(taxon))); 869 insert.setString(2, newName); 870 insert.setString(3, nameClass); 871 insert.executeUpdate(); 872 } catch (BioException exc) { 873 throw exc; 874 } catch (SQLException exc) { 875 throw exc; 876 } finally { 877 attemptClose(insert); 878 } 879 880 return getTaxon(conn, taxon.getScientificName()); 881 } 882 883 884 /** Deletes the specified name from of the taxon from the database. 885 * The <code>scientific name</code> has to be uniqe, so this cannot be removed by 886 * this method. 887 * 888 * @param conn the database connection 889 * @param helper the helper for the used database system 890 * @param taxon the taxon to be updated 891 * @param nameClass the name_class of the name to be removed 892 * @param oldName the old name, which is not needed anymore. 893 * @return the updated taxon. 894 * @throws BioException 895 * @throws SQLException 896 */ 897 public static Taxon removeName(Connection conn, DBHelper helper, Taxon taxon, String nameClass, String oldName) throws BioException, SQLException 898 { 899 if (nameClass.equals("scientific name")) 900 throw new BioException("You can't delete the "+nameClass); 901 902 PreparedStatement delete = conn.prepareStatement( 903 "DELETE FROM taxon_name " + 904 "WHERE name_class LIKE ? AND " + 905 " name LIKE ?"); 906 delete.setString(1, nameClass); 907 delete.setString(2, oldName); 908 delete.executeUpdate(); 909 attemptClose(delete); 910 911 return getTaxon(conn, taxon.getScientificName()); 912 } 913 914 915 /** Returns all children of the specified taxon. 916 * @param conn database connection 917 * @param scientificName name of the taxon which children should be searched. 918 * @return a <code>Stac</code>, which contains the children sorted by theire 919 * <code>scientific name</code>s from top to the bottom. 920 * @throws BioException 921 * @throws SQLException 922 */ 923 public static Stack getChildrenOf(Connection conn, String scientificName) throws BioException 924 { 925 Stack children = new Stack(); 926 PreparedStatement ps = null, ps2 = null; 927 ResultSet rs = null, rs2 = null; 928 try { 929 ps = conn.prepareStatement( 930 "SELECT taxon.taxon_id " + 931 "FROM taxon, taxon_name " + 932 "WHERE taxon_name.taxon_id = taxon.taxon_id AND" + 933 " taxon_name.name_class LIKE 'scientific%' AND" + 934 " parent_taxon_id = ? " + 935 "ORDER BY taxon_name.name DESC"); 936 //if (scientificName.contains("'")) scientificName = scientificName.replace("\'", "\\\'"); 937 //if (scientificName.contains("\"")) scientificName = scientificName.replace("\"", "\\\""); 938 ps.setInt(1, getTaxonID(conn, scientificName)); 939 rs = ps.executeQuery(); 940 while (rs.next()) { 941 ps2 = conn.prepareStatement( 942 "SELECT name " + 943 "FROM taxon_name " + 944 "WHERE taxon_id = ? AND " + 945 " name_class LIKE 'scientific%'"); 946 ps2.setInt(1, rs.getInt(1)); 947 rs2 = ps2.executeQuery(); 948 if (rs2.next()) { 949 children.push(getTaxon(conn, rs2.getString(1))); 950 if (rs2.wasNull()) children.pop(); 951 } 952 } 953 } catch (SQLException exc) { 954 throw new BioException(exc); 955 } finally { 956 attemptClose(ps); 957 attemptClose(rs); 958 attemptClose(ps2); 959 attemptClose(rs2); 960 } 961 962 return children; 963 } 964 965 966 /** Returns the children as a <code>Stack</code> of this given taxon. 967 * 968 * @param conn database connection 969 * @param t the parent taxon 970 * @return a sorted <code>Stack</code> of the children, which might be empty, 971 * but not <code>null</code>. 972 * @throws BioException 973 */ 974 public static Stack getChildrenOf(Connection conn, Taxon t) throws BioException 975 { 976 String tName = t.getScientificName(); 977 if (tName.toLowerCase().equals("root") && (t.getAnnotation() != null)) 978 if (t.getAnnotation().containsProperty(EbiFormat.PROPERTY_TAXON_NAMES)) 979 if (((Map) t.getAnnotation().getProperty(EbiFormat.PROPERTY_TAXON_NAMES)).containsKey("scientific name")) 980 tName = ((Map) t.getAnnotation().getProperty(EbiFormat.PROPERTY_TAXON_NAMES)).get("scientific name").toString(); 981 982 return getChildrenOf(conn, tName); 983 } 984 985 986 /** Updates a taxon and sets it's rank to the specified <code>String</code>. 987 * @param conn database connection. 988 * @param tdb taxon to be updated 989 * @param rank the new rank (like 'kingdom', 'genus' or what ever) 990 * @throws BioRuntimeException 991 */ 992 public static void setRank(Connection conn, Taxon tdb, String rank) throws BioRuntimeException 993 { 994 PreparedStatement ps = null; 995 try { 996 ps = conn.prepareStatement( 997 "UPDATE taxon SET node_rank = ? WHERE taxon_id = ?"); 998 ps.setString(1, rank); 999 ps.setInt(2, getTaxonID(conn, getRealScientificName(tdb))); 1000 ps.executeUpdate(); 1001 } catch (SQLException exc) { 1002 throw new BioRuntimeException(exc); 1003 } catch (BioException exc) { 1004 throw new BioRuntimeException(exc); 1005 } finally { 1006 attemptClose(ps); 1007 } 1008 } 1009 1010 1011 /** Removes the rank persistently from the taxon in the database. 1012 * @param conn 1013 * @param helper 1014 * @param tdb 1015 * @throws BioRuntimeException 1016 */ 1017 public static void removeRank(Connection conn, DBHelper helper, Taxon tdb) throws BioRuntimeException 1018 { 1019 PreparedStatement ps = null; 1020 try { 1021 ps = conn.prepareStatement("UPDATE taxon SET node_rank = NULL WHERE taxon_id = ?"); 1022 ps.setInt(1, getTaxonID(conn, getRealScientificName(tdb))); 1023 ps.executeUpdate(); 1024 } catch (SQLException exc) { 1025 throw new BioRuntimeException(exc); 1026 } catch (BioException exc) { 1027 throw new BioRuntimeException(exc); 1028 } finally { 1029 attemptClose(ps); 1030 } 1031 } 1032 1033 1034 /** Updates the taxon in the database and sets its genetic code id to the specified value. 1035 * @param conn 1036 * @param tdb 1037 * @param id 1038 * @throws BioRuntimeException 1039 */ 1040 public static void setGeneticCodeID(Connection conn, Taxon tdb, int id) throws BioRuntimeException 1041 { 1042 PreparedStatement ps = null; 1043 try { 1044 ps = conn.prepareStatement( 1045 "UPDATE taxon SET genetic_code = ? WHERE taxon_id = ?"); 1046 ps.setInt(1, id); 1047 ps.setInt(2, getTaxonID(conn, getRealScientificName(tdb))); 1048 ps.executeUpdate(); 1049 } catch (SQLException exc) { 1050 throw new BioRuntimeException(exc); 1051 } catch (BioException exc) { 1052 throw new BioRuntimeException(exc); 1053 } finally { 1054 attemptClose(ps); 1055 } 1056 } 1057 1058 1059 /** Deletes the genetic code annotation from the taxon in the database. 1060 * @param conn 1061 * @param helper 1062 * @param tdb 1063 * @throws BioRuntimeException 1064 */ 1065 public static void removeGeneticCodeID(Connection conn, DBHelper helper, Taxon tdb) throws BioRuntimeException 1066 { 1067 PreparedStatement ps = null; 1068 try { 1069 ps = conn.prepareStatement("UPDATE taxon SET genetic_code = NULL WHERE taxon_id = ?"); 1070 ps.setInt(1, getTaxonID(conn, getRealScientificName(tdb))); 1071 ps.executeUpdate(); 1072 } catch (SQLException exc) { 1073 throw new BioRuntimeException(exc); 1074 } catch (BioException exc) { 1075 throw new BioRuntimeException(exc); 1076 } finally { 1077 attemptClose(ps); 1078 } 1079 } 1080 1081 1082 /** Updates the given taxon and sets it's so called mitochondrial genetic code id to 1083 * the specified value. 1084 * @param conn 1085 * @param tdb 1086 * @param id 1087 * @throws BioRuntimeException 1088 */ 1089 public static void setMitochondrialGeneticCodeID(Connection conn, Taxon tdb, int id) throws BioRuntimeException 1090 { 1091 PreparedStatement ps = null; 1092 try { 1093 ps = conn.prepareStatement( 1094 "UPDATE taxon SET mito_genetic_code = ? WHERE taxon_id = ?"); 1095 ps.setInt(1, id); 1096 ps.setInt(2, getTaxonID(conn, getRealScientificName(tdb))); 1097 ps.executeUpdate(); 1098 } catch (SQLException exc) { 1099 throw new BioRuntimeException(exc); 1100 } catch (BioException exc) { 1101 throw new BioRuntimeException(exc); 1102 } finally { 1103 attemptClose(ps); 1104 } 1105 } 1106 1107 1108 /** Deletes the so called mitochondrial genetic code annotation from the given taxon. 1109 * @param conn 1110 * @param helper 1111 * @param tdb 1112 * @throws BioRuntimeException 1113 */ 1114 public static void removeMitochondrialGeneticCodeID(Connection conn, DBHelper helper, Taxon tdb) throws BioRuntimeException 1115 { 1116 PreparedStatement ps = null; 1117 try { 1118 ps = conn.prepareStatement("UPDATE taxon SET mito_genetic_code = NULL WHERE taxon_id = ?"); 1119 ps.setInt(1, getTaxonID(conn, getRealScientificName(tdb))); 1120 ps.executeUpdate(); 1121 } catch (SQLException exc) { 1122 throw new BioRuntimeException(exc); 1123 } catch (BioException exc) { 1124 throw new BioRuntimeException(exc); 1125 } finally { 1126 attemptClose(ps); 1127 } 1128 } 1129 1130 1131 /** Updates the taxon and sets the left value to the specified value. 1132 * @param conn 1133 * @param tdb 1134 * @param left 1135 * @throws BioRuntimeException 1136 */ 1137 public static void setLeftValue(Connection conn, Taxon tdb, int left) throws BioRuntimeException 1138 { 1139 PreparedStatement ps = null; 1140 try { 1141 ps = conn.prepareStatement( 1142 "UPDATE taxon SET left_value = ? WHERE taxon_id = ?"); 1143 ps.setInt(1, left); 1144 ps.setInt(2, getTaxonID(conn, getRealScientificName(tdb))); 1145 ps.executeUpdate(); 1146 } catch (SQLException exc) { 1147 throw new BioRuntimeException(exc); 1148 } catch (BioException exc) { 1149 throw new BioRuntimeException(exc); 1150 } finally { 1151 attemptClose(ps); 1152 } 1153 } 1154 1155 1156 /** Deletes the left value from the specified taxon in the database. 1157 * @param conn 1158 * @param helper 1159 * @param tdb 1160 * @throws BioRuntimeException 1161 */ 1162 public static void removeLeftValue(Connection conn, DBHelper helper, Taxon tdb) throws BioRuntimeException 1163 { 1164 PreparedStatement ps = null; 1165 try { 1166 ps = conn.prepareStatement("UPDATE taxon SEQ left_value = NULL WHERE taxon_id = ?"); 1167 ps.setInt(1, getTaxonID(conn, getRealScientificName(tdb))); 1168 ps.executeUpdate(); 1169 } catch (SQLException exc) { 1170 throw new BioRuntimeException(exc); 1171 } catch (BioException exc) { 1172 throw new BioRuntimeException(exc); 1173 } finally { 1174 attemptClose(ps); 1175 } 1176 } 1177 1178 1179 /** Updates the taxon in the database and sets the right value to the specified value. 1180 * @param conn 1181 * @param tdb 1182 * @param right 1183 * @throws BioRuntimeException 1184 */ 1185 public static void setRightValue(Connection conn, Taxon tdb, int right) throws BioRuntimeException 1186 { 1187 PreparedStatement ps = null; 1188 try { 1189 ps = conn.prepareStatement( 1190 "UPDATE taxon SET right_value = ? WHERE taxon_id = ?"); 1191 ps.setInt(1, right); 1192 ps.setInt(2, getTaxonID(conn, getRealScientificName(tdb))); 1193 ps.executeUpdate(); 1194 } catch (SQLException exc) { 1195 throw new BioRuntimeException(exc); 1196 } catch (BioException exc) { 1197 throw new BioRuntimeException(exc); 1198 } finally { 1199 attemptClose(ps); 1200 } 1201 } 1202 1203 1204 /** Deletes the right value from the specified taxon in the database. 1205 * @param conn 1206 * @param helper 1207 * @param tdb 1208 * @throws BioRuntimeException 1209 */ 1210 public static void removeRightValue(Connection conn, DBHelper helper, Taxon tdb) throws BioRuntimeException 1211 { 1212 PreparedStatement ps = null; 1213 try { 1214 ps = conn.prepareStatement("UPDATE taxon SEQ right_value = NULL WHERE taxon_id = ?"); 1215 ps.setInt(1, getTaxonID(conn, getRealScientificName(tdb))); 1216 ps.executeUpdate(); 1217 } catch (SQLException exc) { 1218 throw new BioRuntimeException(exc); 1219 } catch (BioException exc) { 1220 throw new BioRuntimeException(exc); 1221 } finally { 1222 attemptClose(ps); 1223 } 1224 } 1225 1226 1227 /** This updates the taxonomic tree in the database and sets the parent of the given 1228 * child taxon to the parent taxon. 1229 * @param conn 1230 * @param child 1231 * @param parent 1232 * @throws BioRuntimeException 1233 */ 1234 public static void setParent(Connection conn, Taxon child, Taxon parent) throws BioRuntimeException 1235 { 1236 PreparedStatement ps = null; 1237 try { 1238 ps = conn.prepareStatement( 1239 "UPDATE taxon SET parent_taxon_id = ? WHERE taxon_id = ?"); 1240 ps.setInt(1, getTaxonID(conn, getRealScientificName(parent))); 1241 ps.setInt(2, getTaxonID(conn, getRealScientificName(child))); 1242 ps.executeUpdate(); 1243 } catch (SQLException exc) { 1244 throw new BioRuntimeException(exc); 1245 } catch (BioException exc) { 1246 throw new BioRuntimeException(exc); 1247 } finally { 1248 attemptClose(ps); 1249 } 1250 } 1251 1252 1253 1254 /** This method tries to perform a complete update according to the given 1255 * <code>TaxonFactory</code>, which already contains the newes taxa and the files 1256 * available at the NCBI-FTP-Site. 1257 * @param conn database connection 1258 * @param helper helper for the database system to be used 1259 * @param factory the TaxonFactory containing all the new taxa 1260 * @param delnodes file containing the ncbi taxon ids which don't exist anymore 1261 * @param merged file containing the ncbi taxon ids which were merged. 1262 * @throws IOException 1263 */ 1264 public static void automaticUpdate(Connection conn, DBHelper helper, TaxonFactory factory, File delnodes, File merged) throws IOException 1265 { 1266 /* 1267 * Delnodes. 1268 */ 1269 BufferedReader br = new BufferedReader(new FileReader(delnodes)); 1270 Set ids = NCBIids(conn); 1271 while (br.ready()) { 1272 String line = br.readLine().split("\t")[0]; 1273 if (ids.contains(line)) { 1274 try { 1275 removeTaxon(conn, Integer.parseInt(line), helper); 1276 ids.remove(line); 1277 } catch (NumberFormatException exc1) { 1278 exc1.printStackTrace(); 1279 } catch (BioRuntimeException exc1) { 1280 exc1.printStackTrace(); 1281 } catch (BioException exc1) { 1282 exc1.printStackTrace(); 1283 } catch (SQLException exc) { 1284 exc.printStackTrace(); 1285 } 1286 } 1287 } 1288 1289 1290 /* 1291 * TaxonFactory. 1292 */ 1293 /* 1294 * Mergenodes. 1295 */ 1296 br = new BufferedReader(new FileReader(merged)); 1297 while (br.ready()) { 1298 String[] line = br.readLine().split("\t"); 1299 if (ids.contains(line[0])) { 1300 // line[0] merged with [2]. 1301 //System.out.println(line[0]+"\t"+line[2]); 1302 /* 1303 * Change children 1304 */ 1305 // Only possible if the new parent exists in the database 1306 if (ids.contains(line[2])) try { 1307 Taxon parent = getTaxon(conn, Integer.parseInt(line[2])); 1308 Stack children = getChildrenOf(conn, getTaxon(conn, Integer.parseInt(line[0]))); 1309 while (!children.isEmpty()) { 1310 setParent(conn, (Taxon) children.pop(), parent); 1311 } 1312 /* 1313 * Sequences to the new node. 1314 */ 1315 PreparedStatement ps = conn.prepareStatement( 1316 "UPDATE bioentry SET taxon_id = ? WHERE taxon_id = ?"); 1317 ps.setInt(1, getTaxonID(conn, getRealScientificName(parent))); 1318 ps.setInt(2, getTaxonID(conn, getRealScientificName(getTaxon(conn, Integer.parseInt(line[0]))))); 1319 ps.executeUpdate(); 1320 ps.close(); 1321 } catch (NumberFormatException exc1) { 1322 exc1.printStackTrace(); 1323 } catch (BioRuntimeException exc1) { 1324 exc1.printStackTrace(); 1325 } catch (BioException exc1) { 1326 exc1.printStackTrace(); 1327 } catch (SQLException exc) { 1328 exc.printStackTrace(); 1329 } 1330 /* 1331 * Delete 1332 */ 1333 try { 1334 removeTaxon(conn, Integer.parseInt(line[0]), helper); 1335 } catch (NumberFormatException exc2) { 1336 exc2.printStackTrace(); 1337 } catch (BioRuntimeException exc2) { 1338 exc2.printStackTrace(); 1339 } catch (BioException exc2) { 1340 exc2.printStackTrace(); 1341 } catch (SQLException exc) { 1342 exc.printStackTrace(); 1343 } 1344 1345 } 1346 } 1347 1348 1349 try { 1350 /* 1351 * TaxonFactory. 1352 */ 1353 for (Iterator i=ids(conn).iterator(); i.hasNext(); ) { 1354 Taxon tDB = getTaxon(conn, ((Integer) i.next()).intValue()); 1355 Taxon tFA = factory.search(getRealScientificName(tDB)); 1356 boolean change = false; 1357 // This cannot work because the TaxonFactory doesn't provide this information. 1358 if ((tFA == null) && (tDB.getAnnotation().containsProperty(EbiFormat.PROPERTY_NCBI_TAXON))) 1359 tFA = factory.search(tDB.getAnnotation().getProperty(EbiFormat.PROPERTY_NCBI_TAXON)); 1360 if (tFA == null) continue; 1361 1362 // scientific name 1363 if (tFA.getScientificName() != null) { 1364 if (!tFA.getScientificName().equals(getRealScientificName(tDB))) try { 1365 setScientificName(conn, tDB, tFA.getScientificName()); 1366 } catch (SQLException exc2) { 1367 exc2.printStackTrace(); 1368 } 1369 } 1370 1371 // common name 1372 if (tFA.getCommonName() != null) { 1373 if (tDB.getCommonName() == null) change = true; 1374 else if (!tDB.getCommonName().equals(tFA.getCommonName())) change = true; 1375 if (change) try { 1376 setCommonName(conn, tDB, tFA.getCommonName()); 1377 } catch (BioException exc1) { 1378 exc1.printStackTrace(); 1379 } catch (SQLException exc) { 1380 exc.printStackTrace(); 1381 } finally { change = false; } 1382 } else if (tDB.getCommonName() != null) try { 1383 removeName(conn, helper, tDB, "common name", tDB.getCommonName()); 1384 } catch (BioException exc1) { 1385 exc1.printStackTrace(); 1386 } catch (SQLException exc) { 1387 exc.printStackTrace(); 1388 } 1389 1390 // annotation 1391 Annotation annoFA = tFA.getAnnotation(); 1392 Annotation annoDB = tDB.getAnnotation(); 1393 // rank 1394 if (annoFA.containsProperty("rank")) { 1395 if (!annoDB.containsProperty("rank")) change = true; 1396 else if (!annoDB.getProperty("rank").equals(annoFA.getProperty("rank"))) change = true; 1397 if (change) setRank(conn, tDB, annoFA.getProperty("rank").toString()); 1398 change = false; 1399 } else if (annoDB.containsProperty("rank")) 1400 removeRank(conn, helper, tDB); 1401 // genetic code id 1402 if (annoFA.containsProperty("genetic code id")) { 1403 if (!annoDB.containsProperty("genetic code id")) change = true; 1404 else if (!annoDB.getProperty("genetic code id").equals(annoFA)) change = true; 1405 if (change) setGeneticCodeID(conn, tDB, Integer.parseInt(annoFA.getProperty("genetic code id").toString())); 1406 change = false; 1407 } else if (annoDB.containsProperty("genetic code id")) 1408 removeGeneticCodeID(conn, helper, tDB); 1409 // mitochondrial genetic code id 1410 if (annoFA.containsProperty("mitochondrial genetic code id")) { 1411 if (!annoDB.containsProperty("mitochondrial genetic code id")) change = true; 1412 else if (!annoDB.getProperty("mitochondrial genetic code id").equals(annoFA.getProperty("mitochondrial genetic code id"))) change = true; 1413 if (change) setMitochondrialGeneticCodeID(conn, tDB, Integer.parseInt(annoFA.getProperty("mitochondrial genetic code id").toString())); 1414 change = false; 1415 } else if (annoDB.containsProperty("mitochondrial genetic code id")) 1416 removeMitochondrialGeneticCodeID(conn, helper, tDB); 1417 // left value 1418 if (annoFA.containsProperty("left value")) { 1419 if (!annoDB.containsProperty("left value")) change = true; 1420 else if (!annoDB.getProperty("left value").equals(annoFA.getProperty("left value"))) change = true; 1421 if (change) setLeftValue(conn, tDB, Integer.parseInt(annoFA.getProperty("left value").toString())); 1422 change = false; 1423 } else if (annoDB.containsProperty("left value")) 1424 removeLeftValue(conn, helper, tDB); 1425 // right value 1426 if (annoFA.containsProperty("right value")) { 1427 if (!annoDB.containsProperty("right value")) change = true; 1428 else if (!annoDB.getProperty("right value").equals(annoFA.getProperty("right value"))) change = true; 1429 if (change) setRightValue(conn, tDB, Integer.parseInt(annoFA.getProperty("right value").toString())); 1430 change = false; 1431 } else if (annoDB.containsProperty("right value")) 1432 removeRightValue(conn, helper, tDB); 1433 // other names: 1434 if (annoFA.containsProperty(EbiFormat.PROPERTY_TAXON_NAMES)) { 1435 if (annoFA.getProperty(EbiFormat.PROPERTY_TAXON_NAMES) instanceof Map) { 1436 Map names = (Map) annoFA.getProperty(EbiFormat.PROPERTY_TAXON_NAMES); 1437 Map dbNames = (Map) annoDB.getProperty(EbiFormat.PROPERTY_TAXON_NAMES); 1438 1439 /* 1440 * delete old names, if not valid anymore. 1441 */ 1442 for (Iterator j=dbNames.keySet().iterator(); j.hasNext(); ) { 1443 String key = j.next().toString(); 1444 if (dbNames.get(key) instanceof Set) { 1445 if (!names.containsKey(key)) // delete everything 1446 for (Iterator k=((Set) dbNames.get(key)).iterator(); k.hasNext(); ) try { 1447 String elem = k.next().toString(); 1448 removeName(conn, helper, tDB, key, elem); 1449 } catch (BioException exc2) { 1450 exc2.printStackTrace(); 1451 } catch (SQLException exc) { 1452 exc.printStackTrace(); 1453 } 1454 // this key is still in the new taxon. 1455 else for (Iterator k=((Set) dbNames.get(key)).iterator(); k.hasNext(); ) { 1456 String elem = k.next().toString(); 1457 // many entries for this key in the new taxon. 1458 if (names.get(key) instanceof Set) { 1459 if (!((Set) names.get(key)).contains(elem)) try { 1460 removeName(conn, helper, tDB, key, elem); 1461 } catch (BioException exc3) { 1462 exc3.printStackTrace(); 1463 } catch (SQLException exc) { 1464 exc.printStackTrace(); 1465 } 1466 1467 // in the new taxon only one entry for this key 1468 } else if (!names.get(key).equals(elem)) try { 1469 removeName(conn, helper, tDB, key, elem); 1470 } catch (BioException exc2) { 1471 exc2.printStackTrace(); 1472 } catch (SQLException exc) { 1473 exc.printStackTrace(); 1474 } 1475 } 1476 } else { // only one entry in the new animal 1477 if (!names.containsKey(key)) change = true; 1478 // many entries in the new animal. 1479 else if (names.get(key) instanceof Set) { 1480 if (!((Set) names.get(key)).contains(dbNames.get(key))) change = true; 1481 // only one entry in the new animal (what ever) 1482 } else if (!names.get(key).equals(dbNames.get(key))) change = true; 1483 if (change) try { 1484 removeName(conn, helper, tDB, key, dbNames.get(key).toString()); 1485 } catch (BioException exc2) { 1486 exc2.printStackTrace(); 1487 } 1488 change = false; 1489 } 1490 } 1491 // update: 1492 dbNames = (Map) getTaxon(conn, getRealScientificName(tDB)).getAnnotation().getProperty(EbiFormat.PROPERTY_TAXON_NAMES); 1493 1494 /* 1495 * New names. 1496 */ 1497 for (Iterator j=names.keySet().iterator(); j.hasNext(); ) { 1498 String key = j.next().toString(); 1499 // there're multiple names for this key 1500 if (names.get(key) instanceof Set) { 1501 for (Iterator k=((Set) names.get(key)).iterator(); k.hasNext(); ) { 1502 String elem = k.next().toString(); 1503 if (!dbNames.containsKey(key)) change = true; 1504 else if (dbNames.get(key) instanceof Set) { 1505 if (!((Set) dbNames.get(key)).contains(elem)) change = true; 1506 } else if (!dbNames.get(key).equals(elem)) change = true; 1507 if (change) try { 1508 addName(conn, tDB, key, elem); 1509 } catch (BioRuntimeException exc3) { 1510 exc3.printStackTrace(); 1511 } catch (BioException exc3) { 1512 exc3.printStackTrace(); 1513 } catch (SQLException exc) { 1514 exc.printStackTrace(); 1515 } 1516 change = false; 1517 } 1518 // there's only one name for this key. 1519 } else if (!dbNames.containsKey(key)) try { 1520 addName(conn, tDB, key, names.get(key).toString()); 1521 } catch (BioRuntimeException exc2) { 1522 exc2.printStackTrace(); 1523 } catch (BioException exc2) { 1524 exc2.printStackTrace(); 1525 } catch (SQLException exc) { 1526 exc.printStackTrace(); 1527 } 1528 } 1529 } 1530 } 1531 } 1532 } catch (NumberFormatException exc) { 1533 exc.printStackTrace(); 1534 } catch (BioRuntimeException exc) { 1535 exc.printStackTrace(); 1536 } catch (NoSuchElementException exc) { 1537 exc.printStackTrace(); 1538 } catch (SQLException exc) { 1539 exc.printStackTrace(); 1540 } 1541 } 1542 1543 1544}