001/*
002 * Copyright (c) 2003-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
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.ecoinformatics.seek.querybuilder;
031
032import java.util.Enumeration;
033import java.util.Vector;
034
035import javax.swing.table.AbstractTableModel;
036
037import org.kepler.objectmanager.data.db.DSSchemaIFace;
038import org.kepler.objectmanager.data.db.DSTableFieldIFace;
039import org.kepler.objectmanager.data.db.DSTableIFace;
040
041/**
042 * This classes is the abstract "base" class implementation of the model that is
043 * used in the JTables. Classes are derived from this class so they can show
044 * more or less information for the items that are being displayed.
045 */
046public abstract class DBSelectTableModelBase extends AbstractTableModel {
047        protected Vector mItems;
048        protected DSSchemaIFace mSchema;
049        protected Vector mAvailTableNames = new Vector();
050        protected Vector mAvailFieldNames = new Vector();
051
052        /**
053         * Constructor for Table Model
054         * 
055         * @param aSchema
056         *            the schema
057         */
058        public DBSelectTableModelBase(DSSchemaIFace aSchema) {
059                mSchema = aSchema;
060                mItems = new Vector();
061                add((DBTableField) null, true);
062        }
063
064        /**
065         * Returns the number of columns
066         * 
067         * @return Number of columns
068         */
069        public abstract int getColumnCount();
070
071        /**
072         * Returns the Class object for a column
073         * 
074         * @param aColumn
075         *            the column in question
076         * @return the Class of the column
077         */
078        public abstract Class getColumnClass(int aColumn);
079
080        /**
081         * Indicates if col and row is editable
082         * 
083         * @param aRow
084         *            the row of the cell
085         * @param aColumn
086         *            the column of the cell
087         */
088        public abstract boolean isCellEditable(int aRow, int aColumn);
089
090        /**
091         * Get the column name
092         * 
093         * @param aColumn
094         *            the column of the cell to be gotten
095         */
096        public abstract String getColumnName(int aColumn);
097
098        /**
099         * Gets the value of the row col
100         * 
101         * @param aRow
102         *            the row of the cell to be gotten
103         * @param aColumn
104         *            the column of the cell to be gotten
105         */
106        public abstract Object getValueAt(int aRow, int aColumn);
107
108        /**
109         * Sets a new value into the Model
110         * 
111         * @param aValue
112         *            the value to be set
113         * @param aRow
114         *            the row of the cell to be set
115         * @param aColumn
116         *            the column of the cell to be set
117         */
118        public abstract void setValueAt(Object aValue, int aRow, int aColumn);
119
120        /**
121         * Sets Display attr in UI List cell
122         * 
123         * @param aFieldCell
124         *            the cell item to be changed
125         * @param aFlag
126         *            whether it is to be displayed
127         */
128        protected abstract void setDisplayListCell(
129                        DBSelectTableModelItem aFieldCell, boolean aFlag);
130
131        /**
132         * Returns the Schema object
133         * 
134         * @return the schema
135         */
136        public DSSchemaIFace getSchema() {
137                return mSchema;
138        }
139
140        /**
141         * Returns the number of rows
142         * 
143         * @return Number of rows
144         */
145        public int getRowCount() {
146                return mItems.size();
147        }
148
149        /**
150         * Resturns the items vector
151         * 
152         *       */
153        public Vector getItemVector() {
154                return mItems;
155        }
156
157        /**
158         * Gets the current field for a row
159         * 
160         * @param the
161         *            row of the field to be gotten
162         * @return the row's item, or null if the index is wrong
163         */
164        protected DBSelectTableModelItem getFieldForRow(int aRow) {
165                DBSelectTableModelItem field = null;
166                if (aRow > -1 && aRow < mItems.size()) {
167                        return (DBSelectTableModelItem) mItems.elementAt(aRow);
168                }
169                return null;
170        }
171
172        /**
173         * Checks to see if there is a valid table name in the cell/row
174         * 
175         * @param the
176         *            row of the field to be checked
177         * @return false if the name is ok
178         */
179        protected boolean isTableNameOK(int aRow) {
180                boolean tableNameOK = false;
181                DBSelectTableModelItem field = getFieldForRow(aRow);
182                if (field != null) {
183                        tableNameOK = field != null && field.getTableName().length() > 0
184                                        && !field.getTableName().equals(DBUIUtils.NO_NAME);
185                }
186                return tableNameOK;
187        }
188
189        /**
190         * Sets the Display cell for a row
191         * 
192         * @param aRow
193         *            the row of the field to be updated
194         * @param aFlag
195         *            indicates whether it is displayed or not
196         */
197        public void setIsDisplayed(int aRow, boolean aFlag) {
198                DBTableField fieldCell = null;
199                this.fireTableRowsUpdated(aRow, aRow);
200        }
201
202        /**
203         * Adds a field (Row) to the model
204         * 
205         * @param aField
206         * @param aDoAppend
207         *            indicates whether to append it at the end or one index before
208         *            the end
209         * @return the new item that was added
210         */
211        public DBSelectTableModelItem add(DBTableField aField, boolean aDoAppend) {
212                DBSelectTableModelItem item = new DBSelectTableModelItem(aField);
213                mItems.add(aDoAppend ? mItems.size() : Math.max(mItems.size() - 1, 0),
214                                item);
215                int newRow = mItems.size() - 1;
216                fireTableRowsUpdated(0, newRow);
217                this.fireTableDataChanged();
218                return item;
219        }
220
221        /**
222         * Adds a item (Row) to the model
223         * 
224         * @param aItem
225         *            the item to add
226         * @param aDoAppend
227         *            indicates whether to append it at the end or one index before
228         *            the end
229         * @return the new item that was added
230         */
231        public DBSelectTableModelItem add(DBSelectTableModelItem aItem,
232                        boolean aDoAppend) {
233                DBSelectTableModelItem newItem = new DBSelectTableModelItem(
234                                (DBDisplayItemIFace) aItem);
235                mItems.add(aDoAppend ? mItems.size() : Math.max(mItems.size() - 1, 0),
236                                newItem);
237                int newRow = mItems.size() - 1;
238                fireTableRowsUpdated(0, newRow);
239                this.fireTableDataChanged();
240                return aItem;
241        }
242
243        /**
244         * Sets the table name, if the name is NO_NAME then it deletes the row in
245         * the model
246         * 
247         * @param aField
248         *            object to be updated
249         * @param aRow
250         *            the row to be deleted if necessary
251         * @param aValue
252         *            the new name or NO_NAME
253         */
254        protected void setTableName(DBSelectTableModelItem aField, int aRow,
255                        Object aValue) {
256                if (aValue instanceof String) {
257                        String valStr = (String) aValue;
258                        setDisplayListCell(aField, false);
259                        if (valStr.equals(DBUIUtils.NO_NAME)) {
260                                if (mItems.size() > 1) {
261                                        if (mItems.size() == 2) {
262                                                if (aRow == 0) {
263                                                        aField = (DBSelectTableModelItem) mItems
264                                                                        .elementAt(1);
265                                                        if (aField.getTableName().equals(DBUIUtils.NO_NAME)
266                                                                        || aField.getTableName().equals("")) {
267                                                                mItems.removeElementAt(aRow);
268                                                        }
269                                                }
270                                        } else if (aRow < mItems.size() - 1) {
271                                                mItems.removeElementAt(aRow);
272                                        }
273                                }
274
275                        } else {
276                                aField.setTableName(valStr);
277                                setDisplayListCell(aField, aField.isDisplayed());
278
279                                if (aRow == mItems.size() - 1) {
280                                        add((DBTableField) null, true);
281                                }
282                        }
283                        this.fireTableDataChanged();
284                }
285        }
286
287        /**
288         * Checks to see if the Table Name/Field Name is already in the model
289         * 
290         * @param aTableName
291         *            table name
292         * @param aFieldName
293         *            field name
294         * @return true if in model, false if not.
295         */
296        private boolean isInModelAlready(String aTableName, String aFieldName) {
297                for (Enumeration e = mItems.elements(); e.hasMoreElements();) {
298                        DBSelectTableModelItem item = (DBSelectTableModelItem) e
299                                        .nextElement();
300                        if (aTableName.equals(item.getTableName())
301                                        && aFieldName.equals(item.getName())) {
302                                return true;
303                        }
304                }
305                return false;
306        }
307
308        /**
309         * Sets a field name, and notifies the model of data change
310         * 
311         * @param aField
312         *            a model item to be changed
313         * @param aValue
314         *            the new name
315         */
316        protected void setFieldName(DBSelectTableModelItem aField, Object aValue) {
317                if (aValue instanceof String) {
318
319                        if (!isInModelAlready(aField.getTableName(), aField.getName())) {
320                                setDisplayListCell(aField, false);
321                        }
322
323                        String fieldName = (String) aValue;
324                        aField.setName(fieldName);
325                        if (fieldName.equals("*")) {
326                                aField.setDataType("");
327                                this.fireTableDataChanged();
328                        } else {
329                                DSTableFieldIFace fieldIFace = DBUIUtils.getFieldByName(
330                                                mSchema, aField.getTableName(), fieldName);
331                                if (fieldIFace != null) {
332                                        aField.setDataType(fieldIFace.getDataType());
333                                        this.fireTableDataChanged();
334                                }
335
336                                setDisplayListCell(aField, aField.isDisplayed());
337                        }
338                }
339        }
340
341        /**
342         * Sets the field to be marked as "displayed" and updates the UI
343         * 
344         * @param aField
345         *            the field
346         * @param aValue
347         *            the Boolean value to be set
348         */
349        protected void setDisplay(DBSelectTableModelItem aField, Object aValue) {
350                if (aValue instanceof Boolean) {
351                        boolean val = ((Boolean) aValue).booleanValue();
352                        aField.setDisplayed(val);
353                        setDisplayListCell(aField, val);
354                }
355        }
356
357        /**
358         * Sets the crieria field if it is a string
359         * 
360         * @param aField
361         *            the field object
362         * @param aValue
363         *            the new string value
364         */
365        protected void setCriteria(DBSelectTableModelItem aField, Object aValue) {
366                if (aValue instanceof String)
367                        aField.setCriteria((String) aValue);
368        }
369
370        /**
371         * Returns the available field names for a table
372         * 
373         * @param aTableName
374         *            table name
375         * @return vector of names
376         */
377        public Vector getAvailableFieldNames(String aTableName) {
378                mAvailFieldNames.removeAllElements();
379                mAvailFieldNames.add(DBUIUtils.ALL_FIELDS);
380
381                Vector tables = mSchema.getTables();
382                if (tables != null && tables.size() > 0) {
383                        for (Enumeration et = tables.elements(); et.hasMoreElements();) {
384                                DSTableIFace table = (DSTableIFace) et.nextElement();
385                                if (table.getName().equals(aTableName)) {
386                                        Vector fields = table.getFields();
387                                        for (Enumeration ef = fields.elements(); ef
388                                                        .hasMoreElements();) {
389                                                DSTableFieldIFace field = (DSTableFieldIFace) ef
390                                                                .nextElement();
391                                                if (!field.getName().equals(DBUIUtils.ALL_FIELDS))
392                                                        mAvailFieldNames.add(field.getName());
393                                        }
394                                        break;
395                                }
396                        }
397                }
398                return mAvailFieldNames;
399        }
400
401        /**
402         * Returns a vector of table names and includes the name of the table
403         * identified by the aRow parameter
404         * 
405         * @param aRow
406         *            the row to be included or -1
407         * @return vector of table names
408         */
409        public Vector getAvailableTableNames(int aRow) {
410                mAvailTableNames.removeAllElements();
411                mAvailTableNames.add(DBUIUtils.NO_NAME);
412
413                Vector tables = mSchema.getTables();
414                if (tables != null && tables.size() > 0) {
415                        for (Enumeration et = tables.elements(); et.hasMoreElements();) {
416                                DSTableIFace table = (DSTableIFace) et.nextElement();
417                                getAvailableFieldNames(table.getName());
418                                if (mAvailFieldNames.size() > 0) {
419                                        mAvailTableNames.add(table.getName());
420                                }
421                        }
422                }
423
424                return mAvailTableNames;
425        }
426
427        /**
428         * Notifies the table that it has been completely updated.
429         * 
430         */
431        public void fireTableModelChanged() {
432                fireTableRowsUpdated(0, mItems.size() - 1);
433                fireTableDataChanged();
434        }
435
436}