KickJava   Java API By Example, From Geeks To Geeks.

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


1 /**
2  * com.mckoi.database.RawTableInformation 31 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 java.util.Vector JavaDoc;
28 //import com.mckoi.util.Comparable;
29
import com.mckoi.util.SortUtil;
30 import com.mckoi.util.IntegerVector;
31
32 /**
33  * This object represents the lowest level DataTable information of a given
34  * VirtualTable. Since it is possible to make any level of VirtualTable's,
35  * it is useful to be able to resolve an 'n leveled' VirtualTable to a
36  * single level table. This object is used to collect information as the
37  * 'VirtualTable.resolveToRawTable' method is walking throught the
38  * VirtualTable's ancestors.
39  * <p>
40  * @author Tobias Downer
41  */

42
43 final class RawTableInformation {
44
45   /**
46    * A Vector containing a list of DataTables, and 'row index' IntegerVectors
47    * of the given rows in the table.
48    */

49   private Vector JavaDoc raw_info;
50
51   /**
52    * The constructor.
53    */

54   RawTableInformation() {
55     raw_info = new Vector JavaDoc();
56   }
57
58   /**
59    * Adds a new DataTable or ReferenceTable, and IntegerVector row set into
60    * the object. We can not add VirtualTable objects into this object.
61    */

62   void add(RootTable table, IntegerVector row_set) {
63     RawTableElement elem = new RawTableElement();
64     elem.table = table;
65     elem.row_set = row_set;
66     raw_info.addElement(elem);
67   }
68
69   /**
70    * Returns an AbstractDataTable[] array of all the tables that have been
71    * added.
72    */

73   Table[] getTables() {
74     int size = raw_info.size();
75     Table[] list = new Table[size];
76     for (int i = 0; i < size; ++i) {
77       list[i] = (Table) ((RawTableElement) raw_info.elementAt(i)).table;
78     }
79     return list;
80   }
81
82   /**
83    * Returns a IntegerVector[] list of the rows in the table that have been
84    * added.
85    */

86   IntegerVector[] getRows() {
87     int size = raw_info.size();
88     IntegerVector[] list = new IntegerVector[size];
89     for (int i = 0; i < size; ++i) {
90       list[i] = ((RawTableElement) raw_info.elementAt(i)).row_set;
91     }
92     return list;
93   }
94
95   /**
96    * Returns an array of RawTableElement sorted into a consistant order.
97    */

98   protected RawTableElement[] getSortedElements() {
99     RawTableElement[] list = new RawTableElement[raw_info.size()];
100     raw_info.copyInto(list);
101     SortUtil.quickSort(list);
102     return list;
103   }
104
105   /**
106    * Finds the union of this information with the given information.
107    * It does the following:
108    * + Sorts the unioned tables into a consistant order.
109    * + Merges each row in the tables row_set.
110    * + Sorts the resultant merge.
111    * + Makes a new set with the resultant merge minus any duplicates.
112    */

113   void union(RawTableInformation info) {
114
115     // Number of Table 'columns'
116

117     int col_count = raw_info.size();
118
119     // Get the sorted RawTableElement[] from each raw table information object.
120

121     RawTableElement[] merge1 = getSortedElements();
122     RawTableElement[] merge2 = info.getSortedElements();
123
124     // Validates that both tables being merges are of identical type.
125

126     int size1 = -1;
127     int size2 = -1;
128
129     // First check number of tables in each merge is correct.
130

131     if (merge1.length != merge2.length) {
132       throw new Error JavaDoc("Incorrect format in table union");
133     }
134
135     // Check each table in the merge1 set has identical length row_sets
136

137     for (int i = 0; i < merge1.length; ++i) {
138       if (size1 == -1) {
139         size1 = merge1[i].row_set.size();
140       }
141       else {
142         if (size1 != merge1[i].row_set.size()) {
143           throw new Error JavaDoc("Incorrect format in table union");
144         }
145       }
146     }
147
148     // Check each table in the merge2 set has identical length row_sets
149

150     for (int i = 0; i < merge2.length; ++i) {
151
152       // Check the tables in merge2 are identical to the tables in merge1
153
// (Checks the names match, and the validColumns filters are identical
154
// see AbstractDataTable.typeEquals method).
155

156       if (!merge2[i].table.typeEquals(merge1[i].table)) {
157         throw new Error JavaDoc("Incorrect format in table union");
158       }
159
160       if (size2 == -1) {
161         size2 = merge2[i].row_set.size();
162       }
163       else {
164         if (size2 != merge2[i].row_set.size()) {
165           throw new Error JavaDoc("Incorrect format in table union");
166         }
167       }
168     }
169
170     // If size1 or size2 are -1 then we have a corrupt table. (It will be
171
// 0 for an empty table).
172

173     if (size1 == -1 || size2 == -1) {
174       throw new Error JavaDoc("Incorrect format in table union");
175     }
176
177     // We don't need information in 'raw_info' vector anymore so clear it.
178
// This may help garbage collection.
179

180     raw_info.removeAllElements();
181
182     // Merge the two together into a new list of RawRowElement[]
183

184     int merge_size = size1 + size2;
185     RawRowElement[] elems = new RawRowElement[merge_size];
186     int elems_index = 0;
187
188     for (int i = 0; i < size1; ++i) {
189       RawRowElement e = new RawRowElement();
190       e.row_vals = new int[col_count];
191
192       for (int n = 0; n < col_count; ++n) {
193         e.row_vals[n] = merge1[n].row_set.intAt(i);
194       }
195       elems[elems_index] = e;
196       ++elems_index;
197     }
198
199     for (int i = 0; i < size2; ++i) {
200       RawRowElement e = new RawRowElement();
201       e.row_vals = new int[col_count];
202
203       for (int n = 0; n < col_count; ++n) {
204         e.row_vals[n] = merge2[n].row_set.intAt(i);
205       }
206       elems[elems_index] = e;
207       ++elems_index;
208     }
209
210     // Now sort the row elements into order.
211

212     SortUtil.quickSort(elems);
213
214     // Set up the 'raw_info' vector with the new RawTableElement[] removing
215
// any duplicate rows.
216

217     for (int i = 0; i < col_count; ++i) {
218       RawTableElement e = merge1[i];
219       e.row_set.clear();
220     }
221     RawRowElement previous = null;
222     RawRowElement current = null;
223     for (int n = 0; n < merge_size; ++n) {
224       current = elems[n];
225
226       // Check that the current element in the set is not a duplicate of the
227
// previous.
228

229       if (previous == null || previous.compareTo(current) != 0) {
230         for (int i = 0; i < col_count; ++i) {
231           merge1[i].row_set.addInt(current.row_vals[i]);
232         }
233         previous = current;
234       }
235     }
236
237     for (int i = 0; i < col_count; ++i) {
238       raw_info.addElement(merge1[i]);
239     }
240
241   }
242
243   /**
244    * Removes any duplicate rows from this RawTableInformation object.
245    */

246   void removeDuplicates() {
247
248     // If no tables in duplicate then return
249

250     if (raw_info.size() == 0) {
251       return;
252     }
253
254     // Get the length of the first row set in the first table. We assume that
255
// the row set length is identical across each table in the Vector.
256

257     RawTableElement elen = (RawTableElement) raw_info.elementAt(0);
258     int len = elen.row_set.size();
259     if (len == 0) {
260       return;
261     }
262
263     // Create a new row element to sort.
264

265     RawRowElement[] elems = new RawRowElement[len];
266     int width = raw_info.size();
267
268     // Create an array of RawTableElement so we can quickly access the data
269

270     RawTableElement[] rdup = new RawTableElement[width];
271     raw_info.copyInto(rdup);
272
273     // Run through the data building up a new RawTableElement[] array with
274
// the information in every raw span.
275

276     for (int i = 0; i < len; ++i) {
277       RawRowElement e = new RawRowElement();
278       e.row_vals = new int[width];
279       for (int n = 0; n < width; ++n) {
280         e.row_vals[n] = rdup[n].row_set.intAt(i);
281       }
282       elems[i] = e;
283     }
284
285     // Now 'elems' it an array of individual RawRowElement objects which
286
// represent each individual row in the table.
287

288     // Now sort and remove duplicates to make up a new set.
289

290     SortUtil.quickSort(elems);
291
292     // Remove all elements from the raw_info Vector.
293

294     raw_info.removeAllElements();
295
296     // Make a new set of RawTableElement[] objects
297

298     RawTableElement[] table_elements = rdup;
299
300     // Set up the 'raw_info' vector with the new RawTableElement[] removing
301
// any duplicate rows.
302

303     for (int i = 0; i < width; ++i) {
304       table_elements[i].row_set.clear();
305     }
306     RawRowElement previous = null;
307     RawRowElement current = null;
308     for (int n = 0; n < len; ++n) {
309       current = elems[n];
310
311       // Check that the current element in the set is not a duplicate of the
312
// previous.
313

314       if (previous == null || previous.compareTo(current) != 0) {
315         for (int i = 0; i < width; ++i) {
316           table_elements[i].row_set.addInt(current.row_vals[i]);
317         }
318         previous = current;
319       }
320     }
321
322     for (int i = 0; i < width; ++i) {
323       raw_info.addElement(table_elements[i]);
324     }
325
326   }
327
328 }
329
330 /**
331  * A container class to hold the DataTable and IntegerVector row set of a
332  * given table in the list.
333  */

334 final class RawTableElement implements Comparable JavaDoc {
335
336   RootTable table;
337   IntegerVector row_set;
338
339   public int compareTo(Object JavaDoc o) {
340     RawTableElement rte = (RawTableElement) o;
341     return table.hashCode() - rte.table.hashCode();
342   }
343
344 }
345
346 /**
347  * A container class to hold each row of a list of tables.
348  * table_elems is a reference to the merged set the 'row_index' is in.
349  * row_index is the row index of the row this element refers to.
350  */

351 final class RawRowElement implements Comparable JavaDoc {
352
353   int[] row_vals;
354
355   public int compareTo(Object JavaDoc o) {
356     RawRowElement rre = (RawRowElement) o;
357
358     int size = row_vals.length;
359     for (int i = 0; i < size; ++i) {
360       int v1 = row_vals[i];
361       int v2 = rre.row_vals[i];
362       if (v1 != v2) {
363         return v1 - v2;
364       }
365     }
366     return 0;
367   }
368
369 }
370
Popular Tags