001 /* 002 * CRIMSON 003 * Copyright (c) 2006, Stephen Fisher, Susan Davidson, and Junhyong Kim, 004 * University of Pennsylvania. 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU General Public License as 008 * published by the Free Software Foundation; either version 2 of the 009 * License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, but 012 * WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 * 02110-1301 USA. 020 * 021 * @(#)Trees.java 022 */ 023 024 package edu.upenn.crimson.io; 025 026 import edu.upenn.crimson.*; 027 import java.util.ArrayList; 028 import java.util.Iterator; 029 030 /** 031 * Functions related to the TREES table. 032 * 033 * @author Stephen Fisher 034 * @version $Id: Trees.java,v 1.28 2009/07/16 16:19:52 fisher Exp $ 035 */ 036 037 public class Trees { 038 039 //-------------------------------------------------------------------------- 040 // Miscellaneous Methods 041 042 /** This will load all trees from the TREES table. */ 043 public static void loadAll() { 044 // make sure a database is open. We don't need to check for 045 // the existance of the TREES database because this was done 046 // when the database was opened. 047 if (! Database.isOpen()) { 048 CrimsonUtils.printError("Unable to build tree list, no open database."); 049 return; 050 } 051 052 // clear the lists before we start 053 ObjectHandles.clearTreeLists(); 054 055 CrimsonUtils.printMsg("Loading tree info..."); 056 057 // get the list of trees in the TREES table. 058 String sql = "SELECT id, model_id, notes, num_species, num_leaves, "; 059 sql += "is_binary, is_ultrametric, min_level, max_level, min_temp_depth, max_temp_depth, "; 060 sql += "min_stem_length, max_stem_length FROM TREES"; 061 ArrayList results = Database.sqlToArray(sql); 062 063 // if the query failed then exit 064 if (results == null) { 065 CrimsonUtils.printError("Unable to build tree lists, error accessing TREES table."); 066 return; 067 } 068 069 // convert each row in the results to a Tree 070 for (Iterator rows = results.iterator(); rows.hasNext();) { 071 ArrayList row = (ArrayList) rows.next(); 072 073 // we load the stats from the table so we don't need 074 // to build the tree and compute the stats. 075 new Tree(String.valueOf(row.get(0)), null, 076 ObjectHandles.getModel(String.valueOf(row.get(1))), 077 String.valueOf(row.get(2)), 078 Integer.parseInt(String.valueOf(row.get(3))), 079 Integer.parseInt(String.valueOf(row.get(4))), 080 (String.valueOf(row.get(5)).equals("1") ? true : false), 081 (String.valueOf(row.get(6)).equals("1") ? true : false), 082 Integer.parseInt(String.valueOf(row.get(7))), 083 Integer.parseInt(String.valueOf(row.get(8))), 084 Double.parseDouble(String.valueOf(row.get(9))), 085 Double.parseDouble(String.valueOf(row.get(10))), 086 Double.parseDouble(String.valueOf(row.get(11))), 087 Double.parseDouble(String.valueOf(row.get(12)))); 088 } 089 } 090 091 /** 092 * Removes a tree from the database. When trees are deleted, the 093 * database will automatically remove the related entries in the 094 * PARTITIONS and PART_DATA table. If delQueries is true then 095 * remove any queries that reference this tree. If delQueries is 096 * false, then quit on error if any queries reference this tree. 097 * @XXX We aren't relying on the database sutomatic cascade 098 * deleting of records because the version of MySQL prior to 5.1 099 * do not support this fuction for MyISAM tables, which are the 100 * tables we are using. 101 */ 102 public static boolean delete(String id, boolean delQueries) { 103 if (! ObjectHandles.containsTree(id)) { 104 CrimsonUtils.printWarning("Tree '" + id + "' doesn't exist and thus can't be deleted."); 105 return false; 106 } 107 108 id = id.toUpperCase(); 109 String queries = ""; 110 ArrayList qToDelete = new ArrayList(); 111 for (Iterator i = ObjectHandles.queryIterator(); i.hasNext();) { 112 Query query = (Query) i.next(); 113 if (id.equals(query.getTreeID())) { 114 if (delQueries) { 115 CrimsonUtils.printWarning("Query '" + query.getID() + "' being deleted."); 116 qToDelete.add(query.getID()); 117 } else { 118 queries += " Query: " + query.getID() + "\n"; 119 } 120 } 121 } 122 123 if (! CrimsonUtils.isEmpty(queries)) { 124 CrimsonUtils.printError("Queries exist that reference the tree '" + id + "'."); 125 CrimsonUtils.printError("These queries must be changed to reference other trees before this tree can be deleted."); 126 CrimsonUtils.printError("If these queries are in the database, then the changes must be published to the database.\n" + queries); 127 return false; 128 } else if (qToDelete.size() > 0) { 129 for (Iterator i = qToDelete.iterator(); i.hasNext();) { 130 Queries.delete((String) i.next()); 131 } 132 } 133 134 Tree tree = ObjectHandles.getTree(id); 135 for (Iterator i = tree.getPartitions().iterator(); i.hasNext();) { 136 Partition partition = (Partition) i.next(); 137 if (! Partitions.delete(partition.getID())) return false; 138 } 139 140 // if successfully delete all partitions, then delete the tree 141 if (! Database.delete("TREES", id)) return false; 142 143 // rebuild tree and partition list 144 loadAll(); 145 Partitions.loadAll(); 146 147 return true; 148 } 149 150 /** 151 * This will return true if a tree exists in TREES with an id 152 * equal to 'id'. 153 */ 154 public static boolean dbContains(String id) { 155 ArrayList out = Database.sqlToArray("SELECT id FROM TREES WHERE id = '" + id.toUpperCase() + "'"); 156 if ((out == null) || (out.size() == 0)) return false; 157 else return true; 158 } 159 160 /** 161 * Returns the non-Blob columns in the TREES table. Each table 162 * record will be separated by a '\n' in the output. 163 */ 164 public String toString() { 165 // SELECT id, species, max_temp_depth, notes FROM trees; 166 String sql = "SELECT ID, MODEL_ID, NOTES FROM TREES"; 167 ArrayList results = Database.sqlToArray(sql); 168 169 if (results == null) { 170 CrimsonUtils.printError("Error printing TREES table."); 171 return ""; 172 } 173 174 StringBuffer out = new StringBuffer(""); 175 out.append("ID \t MODEL_ID \t NOTES\n"); 176 for (Iterator rows = results.iterator(); rows.hasNext();) { 177 ArrayList row = (ArrayList) rows.next(); 178 for (int i = 0; i < 2; i++) out.append(String.valueOf(row.get(i)) + " \t "); 179 out.append(String.valueOf(row.get(2)) + "\n"); 180 } 181 182 return out.toString().trim(); 183 } 184 185 } // Trees.java