KickJava   Java API By Example, From Geeks To Geeks.

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


1 /**
2  * com.mckoi.database.RowData 07 Mar 1998
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 com.mckoi.database.global.Types;
28 import com.mckoi.database.global.StringObject;
29 import java.util.List JavaDoc;
30 import java.util.Arrays JavaDoc;
31 import java.util.Date JavaDoc;
32 import java.io.DataOutput JavaDoc;
33 import java.io.InputStream JavaDoc;
34 import java.io.IOException JavaDoc;
35
36 /**
37  * Represents a row of data to be added into a table. The row data is linked
38  * to a TableField that describes the cell information within a row.
39  * <p>
40  * There are two types of RowData object. Those that are empty and contain
41  * blank data, and those that contain information to either be inserted
42  * into a table, or has be retrieved from a row.
43  * <p>
44  * NOTE: Any RowData objects that need to be set to 'null' should be done so
45  * explicitly.
46  * NOTE: We must call a 'setColumnData' method for _every_ column in the
47  * row to form.
48  * NOTE: This method (or derived classes) must only use safe methods in
49  * DataTable. (ie. getRowCount, etc are out).
50  *
51  * @author Tobias Downer
52  */

53
54 public class RowData implements Types {
55
56   /**
57    * The TransactionSystem this RowData is a context of.
58    */

59   private TransactionSystem system;
60
61   /**
62    * The TableDataSource object that this RowData is in, or is destined to be
63    * in.
64    */

65   private TableDataSource table;
66
67   /**
68    * The definition of the table.
69    */

70   private DataTableDef table_def;
71
72   /**
73    * A list of TObject objects in the table.
74    */

75   private TObject[] data_cell_list;
76
77   /**
78    * The number of columns in the row.
79    */

80   private int col_count;
81
82
83   /**
84    * To create a RowData object without an underlying table. This is for
85    * copying from one table to a different one.
86    */

87   public RowData(TransactionSystem system, int col_count) {
88     this.system = system;
89     this.col_count = col_count;
90     data_cell_list = new TObject[col_count];
91   }
92
93   /**
94    * The Constructor generates a blank row.
95    */

96   public RowData(TableDataSource table) {
97     this.system = table.getSystem();
98     this.table = table;
99     table_def = table.getDataTableDef();
100     col_count = table_def.columnCount();
101     data_cell_list = new TObject[col_count];
102   }
103
104   /**
105    * Populates the RowData object with information from a specific row from
106    * the underlying DataTable.
107    */

108   void setFromRow(int row) {
109     for (int col = 0; col < col_count; ++col) {
110       setColumnData(col, table.getCellContents(col, row));
111     }
112   }
113
114   /**
115    * Returns the table object this row data is assigned to. This is used to
116    * ensure we don't try to use a row data in a different table to what it was
117    * created from.
118    */

119   boolean isSameTable(DataTable tab) {
120     return table == tab;
121   }
122
123   /**
124    * Sets up a column by casting the value from the given TObject to a
125    * type that is compatible with the column. This is useful when we
126    * are copying information from one table to another.
127    */

128   public void setColumnData(int column, TObject cell) {
129     DataTableColumnDef col = table_def.columnAt(column);
130     if (table != null && col.getSQLType() != cell.getTType().getSQLType()) {
131       // Cast the TObject
132
cell = cell.castTo(col.getTType());
133     }
134     setColumnDataFromTObject(column, cell);
135   }
136
137   /**
138    * Sets up a column from an Object.
139    */

140   public void setColumnDataFromObject(int column, Object JavaDoc ob) {
141     DataTableColumnDef col_def = table_def.columnAt(column);
142
143     if (ob instanceof String JavaDoc) {
144       ob = StringObject.fromString((String JavaDoc) ob);
145     }
146     
147     // Create a TObject from the given object to the given type
148
TObject cell = TObject.createAndCastFromObject(col_def.getTType(), ob);
149     setColumnDataFromTObject(column, cell);
150   }
151
152   /**
153    * Sets up a column from a TObject.
154    */

155   public void setColumnDataFromTObject(int column, TObject ob) {
156     data_cell_list[column] = ob;
157   }
158
159   /**
160    * This is a special case situation for setting the column cell to 'null'.
161    */

162   public void setColumnToNull(int column) {
163     DataTableColumnDef col_def = table_def.columnAt(column);
164     setColumnDataFromTObject(column, new TObject(col_def.getTType(), null));
165   }
166
167   /**
168    * Sets the given column number to the default value for this column.
169    */

170   public void setColumnToDefault(int column, QueryContext context) {
171     if (table != null) {
172       DataTableColumnDef column_def = table_def.columnAt(column);
173       Expression exp = column_def.getDefaultExpression(system);
174       if (exp != null) {
175         TObject def_val = evaluate(exp, context);
176         setColumnData(column, def_val);
177         return;
178       }
179     }
180     setColumnToNull(column);
181   }
182
183   /**
184    * Returns the TObject that represents the information in the given column
185    * of the row.
186    */

187   public TObject getCellData(int column) {
188     TObject cell = data_cell_list[column];
189     if (cell == null) {
190       DataTableColumnDef col_def = table_def.columnAt(column);
191       cell = new TObject(col_def.getTType(), null);
192     }
193     return cell;
194   }
195
196   /**
197    * Returns the name of the given column number.
198    */

199   public String JavaDoc getColumnName(int column) {
200     return table_def.columnAt(column).getName();
201   }
202
203   /**
204    * Finds the field in this RowData with the given name.
205    */

206   public int findFieldName(String JavaDoc column_name) {
207     return table_def.findColumnName(column_name);
208   }
209
210   /**
211    * Returns the number of columns (cells) in this row.
212    */

213   public int getColumnCount() {
214     return col_count;
215   }
216
217   /**
218    * Evaluates the expression and returns the object it evaluates to using
219    * the local VariableResolver to resolve variables in the expression.
220    */

221   TObject evaluate(Expression expression, QueryContext context) {
222     boolean ignore_case = system.ignoreIdentifierCase();
223     // Resolve any variables to the table_def for this expression.
224
table_def.resolveColumns(ignore_case, expression);
225     // Get the variable resolver and evaluate over this data.
226
VariableResolver vresolver = getVariableResolver();
227     return expression.evaluate(null, vresolver, context);
228   }
229
230   /**
231    * Evaluates a single assignment on this RowData object. A VariableResolver
232    * is made which resolves to variables only within this RowData context.
233    */

234   void evaluate(Assignment assignment, QueryContext context) {
235
236     // Get the variable resolver and evaluate over this data.
237
VariableResolver vresolver = getVariableResolver();
238     TObject ob = assignment.getExpression().evaluate(null, vresolver, context);
239
240     // Check the variable name is within this row.
241
Variable variable = assignment.getVariable();
242     int column = findFieldName(variable.getName());
243
244     // Set the column to the resolved value.
245
setColumnData(column, ob);
246   }
247
248   /**
249    * Any columns in the row of data that haven't been set yet (they will be
250    * 'null') will be set to the default value during this method. This should
251    * be called after the row data has initially been set with values from some
252    * source.
253    */

254   public void setDefaultForRest(QueryContext context)
255                                                     throws DatabaseException {
256     for (int i = 0; i < col_count; ++i) {
257       if (data_cell_list[i] == null) {
258         setColumnToDefault(i, context);
259       }
260     }
261   }
262
263   /**
264    * Sets up an entire row given the array of assignments. If any columns are
265    * left 'null' then they are filled with the default value.
266    */

267   public void setupEntire(Assignment[] assignments, QueryContext context)
268                                                    throws DatabaseException {
269     for (int i = 0; i < assignments.length; ++i) {
270       evaluate(assignments[i], context);
271     }
272     // Any that are left as 'null', set to default value.
273
setDefaultForRest(context);
274   }
275
276   /**
277    * Sets up an entire row given the list of insert elements and a list of
278    * indices to the columns to set. An insert element is either an expression
279    * that is resolved to a constant, or the string "DEFAULT" which indicates
280    * the value should be set to the default value of the column.
281    */

282   public void setupEntire(int[] col_indices, List JavaDoc insert_elements,
283                           QueryContext context) throws DatabaseException {
284     int elem_size = insert_elements.size();
285     if (col_indices.length != elem_size) {
286       throw new DatabaseException(
287                      "Column indices and expression array sizes don't match");
288     }
289     // Get the variable resolver and evaluate over this data.
290
VariableResolver vresolver = getVariableResolver();
291     for (int i = 0; i < col_indices.length; ++i) {
292       Object JavaDoc element = insert_elements.get(i);
293       if (element instanceof Expression) {
294         // Evaluate to the object to insert
295
TObject ob = ((Expression) element).evaluate(null, vresolver, context);
296         int table_column = col_indices[i];
297         // Cast the object to the type of the column
298
ob = ob.castTo(table_def.columnAt(table_column).getTType());
299         // Set the column to the resolved value.
300
setColumnDataFromTObject(table_column, ob);
301       }
302       else {
303         // The element must be 'DEFAULT'. If it's not throw an error. If it
304
// is, the default value will be set later.
305
if (!element.equals("DEFAULT")) {
306           throw new DatabaseException(
307                                   "Invalid value in 'insert_elements' list.");
308         }
309       }
310     }
311     // Any that are left as 'null', set to default value.
312
setDefaultForRest(context);
313   }
314
315   /**
316    * Sets up an entire row given the array of Expressions and a list of indices
317    * to the columns to set. Any columns that are not set by this method are
318    * set to the default value as defined for the column.
319    */

320   public void setupEntire(int[] col_indices, Expression[] exps,
321                           QueryContext context) throws DatabaseException {
322     setupEntire(col_indices, Arrays.asList(exps), context);
323   }
324
325   /**
326    * Returns a string representation of this row.
327    */

328   public String JavaDoc toString() {
329     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
330     buf.append("[RowData: ");
331     for (int i = 0; i < col_count; ++i) {
332       buf.append(data_cell_list[i].getObject());
333       buf.append(", ");
334     }
335     return new String JavaDoc(buf);
336   }
337
338   /**
339    * Returns a VariableResolver to use within this RowData context.
340    */

341   private VariableResolver getVariableResolver() {
342     if (variable_resolver == null) {
343       variable_resolver = new RDVariableResolver();
344     }
345     else {
346       variable_resolver.nextAssignment();
347     }
348     return variable_resolver;
349
350   }
351
352   private RDVariableResolver variable_resolver = null;
353
354   // ---------- Inner classes ----------
355

356   /**
357    * Variable resolver for this context.
358    */

359   private class RDVariableResolver implements VariableResolver {
360
361     private int assignment_count = 0;
362
363     void nextAssignment() {
364       ++assignment_count;
365     }
366
367     public int setID() {
368       return assignment_count;
369     }
370
371     public TObject resolve(Variable variable) {
372       String JavaDoc col_name = variable.getName();
373
374       int col_index = table_def.findColumnName(col_name);
375       if (col_index == -1) {
376         throw new Error JavaDoc("Can't find column: " + col_name);
377       }
378
379       TObject cell = data_cell_list[col_index];
380
381       if (cell == null) {
382         throw new Error JavaDoc("Column " + col_name + " hasn't been set yet.");
383       }
384
385       return cell;
386     }
387
388     public TType returnTType(Variable variable) {
389       String JavaDoc col_name = variable.getName();
390
391       int col_index = table_def.findColumnName(col_name);
392       if (col_index == -1) {
393         throw new Error JavaDoc("Can't find column: " + col_name);
394       }
395
396       return table_def.columnAt(col_index).getTType();
397     }
398
399   }
400
401 }
402
Popular Tags