DBVIEW
|
00001 /* 00002 DbView - Graph Visualization 00003 Copyright (C) 2012 Denis BEURIVE 00004 00005 This program is free software: you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation, either version 3 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 /** 00020 * @author Denis Beurive 00021 */ 00022 00023 package org.dbview.db.structure; 00024 00025 import org.dbview.db.structure.Table; 00026 00027 /** 00028 * This class represents a table's field. 00029 * @author Denis Beurive 00030 */ 00031 public class Field 00032 { 00033 /** 00034 * This constant is used to say that a field is not an index. 00035 */ 00036 final static int NOT_INDEX = 0; 00037 00038 /** 00039 * This constant is used to say that a field is not a key. 00040 */ 00041 final static int NOT_KEY = 0; 00042 00043 /** 00044 * This constant is used to say that a field is a multiple index. 00045 */ 00046 final static int MULTIPLE_INDEX = 1; 00047 00048 /** 00049 * This constant is used to say that a field is a unique index. 00050 */ 00051 final static int UNIQUE_INDEX = 2; 00052 00053 /** 00054 * This constant is used to say that a field is a (hard or soft) foreign key. 00055 */ 00056 final static int KEY_FOREIGN = 1; 00057 00058 /** 00059 * This constant is used to say that a field is a primary index. 00060 */ 00061 final static int KEY_PRIMRY = 2; 00062 00063 /** 00064 * This constant is used to say that a field is a "dead" foreign key. 00065 */ 00066 final static int KEY_DEAD_FOREIGN = 3; 00067 00068 /** 00069 * This constant is used to say that a field can not be null. 00070 */ 00071 final static int NOT_NULL = 0; 00072 00073 /** 00074 * This constant is used to say that a field can be null. 00075 */ 00076 final static int CAN_BE_NULL = 1; 00077 00078 /** Name of the table. */ 00079 private Table __table = null; 00080 00081 /** Name of the field. */ 00082 private String __name = null; 00083 00084 /** Name of the index that uses this field. */ 00085 private String __index_name = null; 00086 00087 /** Is the field a key? */ 00088 private int __key = Field.NOT_KEY; 00089 00090 /** Is the field an index? **/ 00091 private int __index = Field.NOT_INDEX; 00092 00093 /** Can the field be null? **/ 00094 private int __null = Field.NOT_NULL; 00095 00096 /** If the field is a foreign key (type IFieldTypes.FOREIGN_KEY), then his member represents the field's "reference". */ 00097 private Field __reference = null; 00098 00099 /** If this field is a "reference" for a foreign key, then this field represents the foreign key. */ 00100 private Field __fk = null; 00101 00102 /** If the field is a foreign key, then this attribute tells whether the field is a "hard" (as opposed to "soft") foreign key or not. */ 00103 private Boolean __fk_hard = Boolean.TRUE; 00104 00105 /** If the field is a "dead" foreign key (type IFieldTypes.DEAD_FOREIGN_KEY), then his member represents the "dead" field's "reference". */ 00106 private DeadForeignKey __dead_reference = null; 00107 00108 /** 00109 * Assuming that this field is a dead foreign key, then the method returns the dead foreign key's reference. 00110 * @return If this field is a dead foreign key, then the method returns its reference. 00111 */ 00112 public DeadForeignKey getDeadForeignKey() throws org.dbview.db.structure.FieldException 00113 { 00114 if (! this.isDeadForeignKey()) { throw new FieldException("Field " + this.getFullName() + " is not a dead foreing key!"); } 00115 return this.__dead_reference; 00116 } 00117 00118 /** 00119 * This method is used to specify that a foreign key is a soft one. 00120 * @remark A soft foreign key defines a soft join. A soft join is defined by foreign keys' names only. You can find this type of joins in MyIsam (MySql) tables, for example. 00121 */ 00122 public void isASoftForeignKey() 00123 { 00124 this.__fk_hard = Boolean.FALSE; 00125 } 00126 00127 /** 00128 * This method is used to specify that a foreign key is a hard one. 00129 * @remark A hard foreign key defines a hard join. A hard join is defined by the table's constraint. 00130 */ 00131 public void isAHardForeignKey() 00132 { 00133 this.__fk_hard = Boolean.TRUE; 00134 } 00135 00136 /** 00137 * Test if a foreign key is soft. 00138 * @return The method returns the value TRUE if the foreign key is soft. 00139 */ 00140 public Boolean isSoftForeignKey() 00141 { 00142 return ! this.__fk_hard; 00143 } 00144 00145 /** 00146 * Test if a foreign key is hard. 00147 * @return The method returns the value TRUE if the foreign key is hard. 00148 */ 00149 public Boolean isHardForeignKey() 00150 { 00151 return this.__fk_hard; 00152 } 00153 00154 /** 00155 * Set the name of the index that uses this field. 00156 * @param in_index_name Name of the index. 00157 */ 00158 public void setIndexName(String in_index_name) 00159 { 00160 this.__index_name = in_index_name; 00161 } 00162 00163 /** 00164 * Return the name of the index that uses this field. 00165 * @return The method returns the name of the index that uses this field. 00166 */ 00167 public String getIndexName() 00168 { 00169 return this.__index_name; 00170 } 00171 00172 /** 00173 * Create a field, and add the field to a table. 00174 * @param in_table Table that contains <i>this</i> field. 00175 * @param in_name Name of the field. 00176 * @throw org.dbview.db.structure.TableException 00177 */ 00178 public Field(Table in_table, String in_name) throws org.dbview.db.structure.TableException 00179 { 00180 this.__name = in_name; 00181 this.__table = in_table; 00182 in_table.addField(this); 00183 } 00184 00185 /** 00186 * Set the field "can be NULL". 00187 */ 00188 public void isANull() 00189 { 00190 this.__null = Field.CAN_BE_NULL; 00191 } 00192 00193 /** 00194 * Set the field a primary key. 00195 */ 00196 public void isAPrimaryKey() 00197 { 00198 this.__key = Field.KEY_PRIMRY; 00199 } 00200 00201 /** 00202 * Set the field a foreign key. 00203 * @param in_reference "Reference" field. 00204 */ 00205 public void isAforeignKey(Field in_reference) throws org.dbview.db.structure.FieldException 00206 { 00207 // Debug utile: 00208 // if (this.__fk != null) System.out.println(" " + this.getFullName() + ".__fk = " + this.__fk.getFullName() + " reference is " + in_reference.getFullName()); 00209 00210 // We make sure that the field has not already been defined as a foreign key. 00211 if (this.__key == Field.KEY_FOREIGN) // if (null != this.__fk) // BUG !!! 00212 { throw new FieldException("Field " + in_reference.getFullName() + " has already been assigned to a foreign key (" + in_reference.__fk.getFullName() + ")!"); } 00213 00214 // We make sure that the foreign key does not point to its own table. 00215 // Note: A foreign key *CAN* point to its own table. 00216 // if (0 == in_target.getTableName().compareTo(this.getTableName())) 00217 // { throw new FieldException("Field " + this.__name + ": You try to set a foreign key the same table than the foreign key itself!"); } 00218 00219 this.__key = Field.KEY_FOREIGN; 00220 this.__reference = in_reference; 00221 00222 in_reference.__fk = this; 00223 } 00224 00225 /** 00226 * Set the field a "dead" foreign key. 00227 * @param in_reference_table Name of the reference table. 00228 * @param in_reference_field Name of the reference field. 00229 */ 00230 public void isADeadforeignKey(String in_reference_table, String in_reference_field) throws org.dbview.db.structure.FieldException 00231 { 00232 // We make sure that the field has not already been defined as a foreign key. 00233 if (this.__key == Field.KEY_FOREIGN) 00234 { throw new FieldException("Field " + in_reference_field + " has already been assigned to a foreign key!"); } 00235 00236 // We make sure that the field has not already been defined as a dead foreign key. 00237 if (this.__key == Field.KEY_DEAD_FOREIGN) 00238 { throw new FieldException("Field " + in_reference_field + " has already been assigned to a dead foreign key!"); } 00239 00240 this.__key = Field.KEY_DEAD_FOREIGN; 00241 this.__dead_reference = new DeadForeignKey(in_reference_table, in_reference_field); 00242 } 00243 00244 /** 00245 * Set the field a unique index. 00246 */ 00247 public void isAUniqueIndex() 00248 { 00249 this.__index = Field.UNIQUE_INDEX; 00250 } 00251 00252 /** 00253 * Set the field a multiple index. 00254 */ 00255 public void isAMultipleIndex() 00256 { 00257 this.__index = Field.MULTIPLE_INDEX; 00258 } 00259 00260 /** 00261 * If the field is a "reference" for a foreign key, then the method returns the foreign key. 00262 * @return If the field is a "reference" for a foreign key, then the method returns the foreign key. 00263 * Otherwise, the method returns the value null. 00264 */ 00265 public Field getFkToMe() 00266 { 00267 return this.__fk; 00268 } 00269 00270 /** 00271 * Return the name of the field. 00272 * @return The method returns the name of the field. 00273 */ 00274 public String getName() 00275 { 00276 return this.__name; 00277 } 00278 00279 /** 00280 * This method returns the full name of the field. The full name includes the table's name. 00281 * @return The method returns the full name of the field. 00282 */ 00283 public String getFullName() 00284 { 00285 return this.__table.getName() + "." + this.__name; 00286 } 00287 00288 /** 00289 * Return the field's "reference" (if the field is a foreign key). 00290 * @return The method returns the field's "reference". 00291 * @throws org.dbview.db.structure.FieldException 00292 */ 00293 public Field getReference() throws org.dbview.db.structure.FieldException 00294 { 00295 if (Field.KEY_FOREIGN != this.__key) 00296 { throw new FieldException("The field \"" + this.__name + "\" is not a foreign key."); } 00297 return this.__reference; 00298 } 00299 00300 /** 00301 * Return the table that contains <i>this</i> field. 00302 * @return The method returns the table that contains "this" field. 00303 */ 00304 public Table getTable() 00305 { 00306 return this.__table; 00307 } 00308 00309 /** 00310 * This method returns the name of the field's table. 00311 * @return The method returns the name of the field's table. 00312 */ 00313 public String getTableName() 00314 { 00315 return this.__table.getName(); 00316 } 00317 00318 /** 00319 * Test if the field is a primary key. 00320 * @return The method returns the value TRUE if the field is a primary key. 00321 * Otherwise the method returns the value FALSE. 00322 */ 00323 public Boolean isPrimaryKey() 00324 { 00325 return Field.KEY_PRIMRY == this.__key; 00326 } 00327 00328 /** 00329 * Test if the field is a foreign key. 00330 * @return The method returns the value TRUE if the field is a foreign key. 00331 * Otherwise the method returns the value FALSE. 00332 */ 00333 public Boolean isForeignKey() 00334 { 00335 return Field.KEY_FOREIGN == this.__key; 00336 } 00337 00338 /** 00339 * Test if the field is a dead foreign key. 00340 * @return The method returns the value TRUE if the field is a dead foreign key. 00341 * Otherwise the method returns the value FALSE. 00342 */ 00343 public Boolean isDeadForeignKey() 00344 { 00345 return Field.KEY_DEAD_FOREIGN == this.__key; 00346 } 00347 00348 /** 00349 * Test if the field is a key (primary or foreign). 00350 * @return The method returns the value TRUE if the field is a key. 00351 * Otherwise the method returns the value FALSE. 00352 */ 00353 public Boolean isKey() 00354 { 00355 return Field.KEY_FOREIGN == this.__key 00356 || 00357 Field.KEY_PRIMRY == this.__key; 00358 } 00359 00360 /** 00361 * Test if the field is a unique index. 00362 * @return The method returns the value TRUE if the field is a unique index. 00363 * Otherwise the method returns the value FALSE. 00364 */ 00365 public Boolean isUniqueIndex() 00366 { 00367 return Field.UNIQUE_INDEX == this.__index; 00368 } 00369 00370 /** 00371 * Test if the field has a unique constraint. 00372 * @return The method returns the value TRUE if the field is a unique constraint. 00373 * Otherwise the method returns the value FALSE. 00374 */ 00375 public Boolean isUnique() 00376 { 00377 return this.isUniqueIndex(); 00378 } 00379 00380 /** 00381 * Test if the field is a multiple index. 00382 * @return The method returns the value TRUE if the field is a multiple index. 00383 * Otherwise the method returns the value FALSE. 00384 */ 00385 public Boolean isMultipleIndex() 00386 { 00387 return Field.MULTIPLE_INDEX == this.__index; 00388 } 00389 00390 /** 00391 * Test if the field is an index. 00392 * @return The method returns the value TRUE if the field is an index. 00393 * Otherwise the method returns the value FALSE. 00394 */ 00395 public Boolean isIndex() 00396 { 00397 return Field.UNIQUE_INDEX == this.__index 00398 || 00399 Field.MULTIPLE_INDEX == this.__index; 00400 } 00401 00402 /** 00403 * Test if the field can be null. 00404 * @return The method returns the value TRUE if the field can be null. 00405 */ 00406 public Boolean isNull() 00407 { 00408 return this.__null == Field.CAN_BE_NULL; 00409 } 00410 00411 /** 00412 * Create a textual representation of the field. 00413 * @return The method returns a textual representation of the field. 00414 */ 00415 public String toString() 00416 { 00417 String prefix = ""; 00418 String back = ""; 00419 00420 if (null != this.__fk) { back = " <= " + this.__fk.getFullName(); } 00421 00422 if (this.isPrimaryKey()) { return "PK " + this.getFullName() + back; } 00423 00424 if (this.isUniqueIndex()) { prefix = "UI"; } 00425 else if (this.isMultipleIndex()) { prefix = "MI"; } 00426 else { prefix = "ST"; } 00427 00428 if (this.isForeignKey()) { return "FK(" + prefix + ") " + this.getFullName() + " => " + this.__reference.getFullName() + back; } 00429 00430 if (this.isDeadForeignKey()) { return "DFK(" + prefix + ") " + this.getFullName() + " => " + this.__dead_reference.getFullName() + back; } 00431 00432 return prefix + " " + this.getFullName() + back; 00433 } 00434 }