KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > DataTableDef


1 /**
2  * com.mckoi.database.DataTableDef 27 Jul 2000
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database;
26
27 import java.io.*;
28 import java.util.ArrayList JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.List JavaDoc;
31
32 /**
33  * A definition of a table. Every table in the database has a definition
34  * that describes how it is stored on disk, the column definitions, primary
35  * keys/foreign keys, and any check constraints.
36  *
37  * @author Tobias Downer
38  */

39
40 public class DataTableDef {
41
42   /**
43    * A TableName object that represents this data table def.
44    */

45   private TableName table_name;
46   
47   /**
48    * The type of table this is (this is the class name of the object that
49    * maintains the underlying database files).
50    */

51   private String JavaDoc table_type_class;
52
53   /**
54    * The list of DataTableColumnDef objects that are the definitions of each
55    * column in the table.
56    */

57   private ArrayList JavaDoc column_list;
58
59
60   /**
61    * Set to true if this data table def is immutable.
62    */

63   private boolean immutable;
64
65   /**
66    * Constructs this DataTableDef file.
67    */

68   public DataTableDef() {
69     column_list = new ArrayList JavaDoc();
70     table_type_class = "";
71     immutable = false;
72   }
73
74   /**
75    * Copy constructor.
76    */

77   public DataTableDef(DataTableDef table_def) {
78     table_name = table_def.getTableName();
79     table_type_class = table_def.table_type_class;
80     column_list = (ArrayList JavaDoc) table_def.column_list.clone();
81
82     // Copy is not immutable
83
immutable = false;
84   }
85
86   /**
87    * Sets this DataTableDef to immutable which means nothing is able to
88    * change it.
89    */

90   public void setImmutable() {
91     immutable = true;
92   }
93
94   /**
95    * Returns true if this is immutable.
96    */

97   public boolean immutable() {
98     return immutable;
99   }
100
101   /**
102    * Checks that this object is mutable. If it isn't an exception is thrown.
103    */

104   private void checkMutable() {
105     if (immutable()) {
106       throw new Error JavaDoc("Tried to mutate immutable object.");
107     }
108   }
109
110   /**
111    * Outputs to the PrintStream for debugging.
112    */

113   public void dump(PrintStream out) {
114     for (int i = 0; i < columnCount(); ++i) {
115       columnAt(i).dump(out);
116       out.println();
117     }
118   }
119   
120   /**
121    * Resolves variables in a column so that any unresolved column names point
122    * to this table. Used to resolve columns in the 'check_expression'.
123    */

124   void resolveColumns(boolean ignore_case, Expression exp) {
125
126     // For each variable, determine if the column correctly resolves to a
127
// column in this table. If the database is in identifier case insensitive
128
// mode attempt to resolve the column name to a valid column in this
129
// def.
130
if (exp != null) {
131       List JavaDoc list = exp.allVariables();
132       for (int i = 0; i < list.size(); ++i) {
133         Variable v = (Variable) list.get(i);
134         String JavaDoc col_name = v.getName();
135         // Can we resolve this to a variable in the table?
136
if (ignore_case) {
137           int size = columnCount();
138           for (int n = 0; n < size; ++n) {
139             // If this is a column name (case ignored) then set the variable
140
// to the correct cased name.
141
if (columnAt(n).getName().equalsIgnoreCase(col_name)) {
142               v.setColumnName(columnAt(n).getName());
143             }
144           }
145         }
146       }
147
148     }
149   }
150
151   /**
152    * Resolves a single column name to its correct form. For example, if
153    * the database is in case insensitive mode it'll resolve ID to 'id' if
154    * 'id' is in this table. Throws a database exception if a column couldn't
155    * be resolved (ambiguous or not found).
156    */

157   public String JavaDoc resolveColumnName(String JavaDoc col_name, boolean ignore_case)
158                                                    throws DatabaseException {
159     // Can we resolve this to a column in the table?
160
int size = columnCount();
161     int found = -1;
162     for (int n = 0; n < size; ++n) {
163       // If this is a column name (case ignored) then set the column
164
// to the correct cased name.
165
String JavaDoc this_col_name = columnAt(n).getName();
166       if (ignore_case && this_col_name.equalsIgnoreCase(col_name)) {
167         if (found == -1) {
168           found = n;
169         }
170         else {
171           throw new DatabaseException(
172                       "Ambiguous reference to column '" + col_name + "'");
173         }
174       }
175       else if (!ignore_case && this_col_name.equals(col_name)) {
176         found = n;
177       }
178     }
179     if (found != -1) {
180       return columnAt(found).getName();
181     }
182     else {
183       throw new DatabaseException("Column '" + col_name + "' not found");
184     }
185   }
186
187   /**
188    * Given a list of column names referencing entries in this table, this will
189    * resolve each one to its correct form. Throws a database exception if
190    * a column couldn't be resolved.
191    */

192   public void resolveColumnsInArray(DatabaseConnection connection,
193                                     ArrayList JavaDoc list) throws DatabaseException {
194     boolean ignore_case = connection.isInCaseInsensitiveMode();
195     for (int i = 0; i < list.size(); ++i) {
196       String JavaDoc col_name = (String JavaDoc) list.get(i);
197       list.set(i, resolveColumnName((String JavaDoc) list.get(i), ignore_case));
198     }
199   }
200
201   // ---------- Set methods ----------
202

203   public void setTableName(TableName name) {
204     this.table_name = name;
205   }
206
207   public void setTableClass(String JavaDoc clazz) {
208     checkMutable();
209     if (clazz.equals("com.mckoi.database.VariableSizeDataTableFile")) {
210       table_type_class = clazz;
211     }
212     else {
213       throw new Error JavaDoc("Unrecognised table class: " + clazz);
214     }
215   }
216
217   public void addColumn(DataTableColumnDef col_def) {
218     checkMutable();
219     // Is there already a column with this name in the table def?
220
for (int i = 0; i < column_list.size(); ++i) {
221       DataTableColumnDef cd = (DataTableColumnDef) column_list.get(i);
222       if (cd.getName().equals(col_def.getName())) {
223         throw new Error JavaDoc("Duplicated columns found.");
224       }
225     }
226     column_list.add(col_def);
227   }
228
229   /**
230    * Same as 'addColumn' only this does not perform a check to ensure no
231    * two columns are the same.
232    */

233   public void addVirtualColumn(DataTableColumnDef col_def) {
234     checkMutable();
235     column_list.add(col_def);
236   }
237
238
239   // ---------- Get methods ----------
240

241   public String JavaDoc getSchema() {
242     String JavaDoc schema_name = table_name.getSchema();
243     return schema_name == null ? "" : schema_name;
244   }
245
246   public String JavaDoc getName() {
247     return table_name.getName();
248   }
249
250   public TableName getTableName() {
251     return table_name;
252   }
253
254   public String JavaDoc getTableClass() {
255     return table_type_class;
256   }
257
258   public int columnCount() {
259     return column_list.size();
260   }
261
262   public DataTableColumnDef columnAt(int column) {
263     return (DataTableColumnDef) column_list.get(column);
264   }
265
266   public int findColumnName(String JavaDoc column_name) {
267     int size = columnCount();
268     for (int i = 0; i < size; ++i) {
269       if (columnAt(i).getName().equals(column_name)) {
270         return i;
271       }
272     }
273     return -1;
274   }
275
276   // Stores col name -> col index lookups
277
private transient HashMap JavaDoc col_name_lookup;
278   private transient Object JavaDoc COL_LOOKUP_LOCK = new Object JavaDoc();
279   /**
280    * A faster way to find a column index given a string column name. This
281    * caches column name -> column index in a HashMap.
282    */

283   public final int fastFindColumnName(String JavaDoc col) {
284     synchronized (COL_LOOKUP_LOCK) {
285       if (col_name_lookup == null) {
286         col_name_lookup = new HashMap JavaDoc(30);
287       }
288       Object JavaDoc ob = col_name_lookup.get(col);
289       if (ob == null) {
290         int ci = findColumnName(col);
291         col_name_lookup.put(col, new Integer JavaDoc(ci));
292         return ci;
293       }
294       else {
295         return ((Integer JavaDoc) ob).intValue();
296       }
297     }
298   }
299   
300   
301   /**
302    * Returns a copy of this object, except with no columns or constraints.
303    */

304   public DataTableDef noColumnCopy() {
305     DataTableDef def = new DataTableDef();
306     def.setTableName(getTableName());
307 // def.setSchema(schema);
308
// def.setName(name);
309

310     def.table_type_class = table_type_class;
311
312     return def;
313   }
314
315
316   // ---------- In/Out methods ----------
317

318   /**
319    * Writes this DataTableDef file to the data output stream.
320    */

321   void write(DataOutput out) throws IOException {
322     out.writeInt(2); // Version number
323

324     out.writeUTF(getName());
325     out.writeUTF(getSchema()); // Added in version 2
326
out.writeUTF(table_type_class);
327     out.writeInt(column_list.size());
328     for (int i = 0; i < column_list.size(); ++i) {
329       ((DataTableColumnDef) column_list.get(i)).write(out);
330     }
331
332 // // -- Added in version 2 --
333
// // Write the constraint list.
334
// out.writeInt(constraint_list.size());
335
// for (int i = 0; i < constraint_list.size(); ++i) {
336
// ((DataTableConstraintDef) constraint_list.get(i)).write(out);
337
// }
338

339 // [ this is removed from version 1 ]
340
// if (check_expression != null) {
341
// out.writeBoolean(true);
342
// // Write the text version of the expression to the stream.
343
// out.writeUTF(new String(check_expression.text()));
344
// }
345
// else {
346
// out.writeBoolean(false);
347
// }
348

349   }
350
351   /**
352    * Reads this DataTableDef file from the data input stream.
353    */

354   static DataTableDef read(DataInput in) throws IOException {
355     DataTableDef dtf = new DataTableDef();
356     int ver = in.readInt();
357     if (ver == 1) {
358
359       throw new IOException("Version 1 DataTableDef no longer supported.");
360
361     }
362     else if (ver == 2) {
363
364       String JavaDoc rname = in.readUTF();
365       String JavaDoc rschema = in.readUTF();
366       dtf.setTableName(new TableName(rschema, rname));
367       dtf.table_type_class = in.readUTF();
368       int size = in.readInt();
369       for (int i = 0; i < size; ++i) {
370         DataTableColumnDef col_def = DataTableColumnDef.read(in);
371         dtf.column_list.add(col_def);
372       }
373
374     }
375     else {
376       throw new Error JavaDoc("Unrecognized DataTableDef version (" + ver + ")");
377     }
378
379     dtf.setImmutable();
380     return dtf;
381   }
382
383 }
384
Popular Tags