001/* 002 * Copyright (c) 2008-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2012-01-19 22:42:22 +0000 (Thu, 19 Jan 2012) $' 007 * '$Revision: 29261 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.util.sql; 031 032import java.util.HashMap; 033import java.util.HashSet; 034import java.util.LinkedHashMap; 035import java.util.Map; 036import java.util.Set; 037 038/** 039 * 040 * A generic representation of an SQL table. A Table can contain 041 * columns, constraints, and foreign keys. 042 * 043 * @author Daniel Crawl 044 * @version $Id: Table.java 29261 2012-01-19 22:42:22Z crawl $ 045 * 046 */ 047 048public class Table 049{ 050 /** Construct a new Table. */ 051 Table(String name) 052 { 053 _tableName = name; 054 055 _columnMap = new LinkedHashMap<String,Column>(); 056 _constraintMap = new LinkedHashMap<String,ColumnConstraint>(); 057 _fkMap = new LinkedHashMap<String,ForeignKey>(); 058 059 _columnConstraintsMap = new HashMap<String,Set<String>>(); 060 _columnFKsMap = new HashMap<String,Set<String>>(); 061 } 062 063 /** Get the columns. */ 064 public Set<Column> columns() 065 { 066 return new HashSet<Column>(_columnMap.values()); 067 } 068 069 /** Get the column names. */ 070 public Set<String> columnNames() 071 { 072 return new HashSet<String>(_columnMap.keySet()); 073 } 074 075 /** Get the constraint names. */ 076 public Set<String> constraintNames() 077 { 078 return _constraintMap.keySet(); 079 } 080 081 /** Get the foreign key names. */ 082 public Set<String> foreignKeyNames() 083 { 084 return _fkMap.keySet(); 085 } 086 087 /** Get a specific column. */ 088 public Column getColumn(String name) 089 { 090 return _columnMap.get(name); 091 } 092 093 /** Get a specific constraint. */ 094 public ColumnConstraint getConstraint(String name) 095 { 096 return _constraintMap.get(name); 097 } 098 099 /** Get a specific foreign key. */ 100 public ForeignKey getForeignKey(String name) 101 { 102 return _fkMap.get(name); 103 } 104 105 /** Get the column(s) for an index. */ 106 public String getIndexColumns(String indexName) 107 { 108 return _indexNameColumnsMap.get(indexName); 109 } 110 111 /** Get the index type. */ 112 public IndexType getIndexType(String name) 113 { 114 return _indexNameTypeMap.get(name); 115 } 116 117 /** Get the table name. */ 118 public String getName() 119 { 120 return _tableName; 121 } 122 123 /** Returns true if column references another table. */ 124 public boolean isForeignKey(String columnName) 125 { 126 return _columnFKsMap.containsKey(columnName); 127 } 128 129 /** Get the indexes. */ 130 public Set<String> indexes() 131 { 132 return new HashSet<String>(_indexNameTypeMap.keySet()); 133 } 134 135 /** Add a new or replace an existing column with no foreign key or index. */ 136 public void putColumn(String name, Column column) 137 { 138 putColumn(name, column, null, null); 139 } 140 141 /** Add a new or replace an existing column with a default value. */ 142 public void putColumn(String name, Column column, String defaultValue) 143 { 144 putColumn(name, column, null, null, defaultValue); 145 } 146 147 /** Add a new or replace an existing column. 148 * @param name the column name 149 * @param column the column type 150 * @param fkTable the referenced table in foreign key 151 * @param fkColumn the referenced column in foreign key 152 */ 153 public void putColumn(String columnName, Column column, String fkTable, 154 String fkColumn) 155 { 156 putColumn(columnName, column, fkTable, fkColumn, null); 157 } 158 159 /** Add a new or replace an existing column. 160 * @param name the column name 161 * @param column the column type 162 * @param fkTable the referenced table in foreign key 163 * @param fkColumn the referenced column in foreign key 164 * @param defaultValue the default value 165 */ 166 public void putColumn(String columnName, Column column, String fkTable, 167 String fkColumn, String defaultValue) 168 { 169 // NOTE: we make a copy of the column since we set the 170 // name and table, and don't want to overwrite these values 171 // in one of the static columns. 172 Column columnClone = new Column(column); 173 _columnMap.put(columnName, columnClone); 174 columnClone._setTable(this); 175 columnClone.setName(columnName); 176 if(defaultValue != null) 177 { 178 columnClone._setDefaultValue(defaultValue); 179 } 180 181 if(fkTable != null && fkColumn != null) 182 { 183 String fkName = _tableName + "_" + columnName + "_fk"; 184 putForeignKey(fkName, columnName, fkTable, fkColumn); 185 } 186 } 187 188 /** Add a new or replace an existing constraint. */ 189 public void putConstraint(String constraintName, String columnName, 190 String constraintValue) 191 { 192 ColumnConstraint constraint = new ColumnConstraint(columnName, constraintValue); 193 _constraintMap.put(constraintName, constraint); 194 _addColumnConstraint(columnName, constraintName); 195 } 196 197 /** Add an index on one or more columns. */ 198 public void putIndex(String columnName) 199 { 200 putIndex(columnName.replaceAll("[,\\s]", "_") + "_idx", columnName); 201 } 202 203 /** Add a new or replace an existing index. */ 204 public void putIndex(String indexName, String columnName) 205 { 206 putIndex(indexName, columnName, IndexType.Default); 207 } 208 209 /** Add a new or replace an index index specifying the type of index. */ 210 public void putIndex(String indexName, String columnName, IndexType type) 211 { 212 _indexNameTypeMap.put(indexName, type); 213 _indexNameColumnsMap.put(indexName, columnName); 214 } 215 216 /** Add a new or replace an existing foreign key. */ 217 public void putForeignKey(String fkName, String columnName, String fkTable, 218 String fkColumn) 219 { 220 ForeignKey fk = new ForeignKey(columnName, fkTable, fkColumn); 221 _fkMap.put(fkName, fk); 222 223 _addColumnForeignKey(columnName, fkName); 224 } 225 226 /** Remove a column. */ 227 public void removeColumn(String columnName) 228 { 229 _columnMap.remove(columnName); 230 231 // remove any constraints associated with this column 232 Set<String> constraintSet = _columnConstraintsMap.remove(columnName); 233 if(constraintSet != null) 234 { 235 for(String constraintName : constraintSet) 236 { 237 removeConstraint(constraintName); 238 } 239 } 240 241 // remove any foriegn keys associated with this column 242 Set<String> fkSet = _columnFKsMap.remove(columnName); 243 if(fkSet != null) 244 { 245 for(String fkName : fkSet) 246 { 247 _fkMap.remove(fkName); 248 } 249 } 250 } 251 252 /** Remove a constraint. */ 253 public void removeConstraint(String name) 254 { 255 _constraintMap.remove(name); 256 257 //XXX update columnConstraintsMap? 258 } 259 260 /** Remove a foreign key. */ 261 public void removeForeignKey(String name) 262 { 263 _fkMap.remove(name); 264 265 //XXX update columnFKsMap? 266 } 267 268 /** Get a string representation of the table. */ 269 public String toString() 270 { 271 StringBuilder retval = new StringBuilder("table "); 272 retval.append(_tableName); 273 retval.append("\n"); 274 for(Column column : columns()) 275 { 276 retval.append("{"); 277 retval.append(column.toString()); 278 retval.append("}\n"); 279 } 280 return retval.toString(); 281 } 282 283 //////////////////////////////////////////////////////////////////////// 284 //// public fields 285 286 /** Index types. */ 287 public enum IndexType 288 { 289 Bitmap, 290 Default, 291 } 292 293 //////////////////////////////////////////////////////////////////////// 294 //// protected classes 295 296 protected static class ColumnConstraint 297 { 298 private ColumnConstraint(String columnName, String constraintValue) 299 { 300 _columnName = columnName; 301 _value = constraintValue; 302 } 303 304 public String getColumnName() 305 { 306 return _columnName; 307 } 308 309 public String getConstraintValue() 310 { 311 return _value; 312 } 313 314 private String _columnName; 315 private String _value; 316 } 317 318 /** A class for foreign keys. */ 319 protected static class ForeignKey 320 { 321 /** Construct a new ForeignKey with a column name, and referent 322 * table and column names. This is private since only Table 323 * may create new ForeignKeys. 324 */ 325 private ForeignKey(String columnName, String refTable, String refColumn) 326 { 327 _column = columnName; 328 _refColumn = refColumn; 329 _refTable = refTable; 330 } 331 332 /** Get the column name. */ 333 protected String getColumn() 334 { 335 return _column; 336 } 337 338 /** Get the referenced column name. */ 339 protected String getRefColumn() 340 { 341 return _refColumn; 342 } 343 344 /** Get the referenced table name. */ 345 protected String getRefTable() 346 { 347 return _refTable; 348 } 349 350 /** The column name. */ 351 private String _column; 352 353 /** The referenced column name. */ 354 private String _refColumn; 355 356 /** The referenced table name. */ 357 private String _refTable; 358 } 359 360 //////////////////////////////////////////////////////////////////////// 361 //// private methods 362 363 /** Add a constraint associated with a column. */ 364 private void _addColumnConstraint(String columnName, String constraintName) 365 { 366 _updateMap(_columnConstraintsMap, columnName, constraintName); 367 } 368 369 /** Add a foreign key associated with a column. */ 370 private void _addColumnForeignKey(String columnName, String fkName) 371 { 372 _updateMap(_columnFKsMap, columnName, fkName); 373 } 374 375 /** Update a map of string to hash set. */ 376 private void _updateMap(Map<String,Set<String>> map, String key, 377 String value) 378 { 379 Set<String> valueSet = map.get(key); 380 if(valueSet == null) 381 { 382 valueSet = new HashSet<String>(); 383 map.put(key, valueSet); 384 } 385 valueSet.add(value); 386 } 387 388 //////////////////////////////////////////////////////////////////////// 389 //// private variables 390 391 /** A mapping of column name to a set of its constraints. */ 392 // XXX this is not used. 393 private Map<String,Set<String>> _columnConstraintsMap; 394 395 /** A mapping of columns name to a set of its foreign keys. */ 396 private Map<String,Set<String>> _columnFKsMap; 397 398 /** A mapping of name to column. */ 399 private Map<String,Column> _columnMap; 400 401 /** A mapping of name to constraint. */ 402 private Map<String,ColumnConstraint> _constraintMap; 403 404 /** A mapping of name to foreign keys. */ 405 private Map<String,ForeignKey> _fkMap; 406 407 /** The name of this table. */ 408 private String _tableName; 409 410 /** A mapping of index name to index type. */ 411 private Map<String,IndexType> _indexNameTypeMap = new HashMap<String,IndexType>(); 412 413 /** A mapping of index name to column(s). */ 414 private Map<String,String> _indexNameColumnsMap = new HashMap<String,String>(); 415}