001: /*
002: * EditTablePanel.java
003: *
004: * Copyright (C) 2002, 2003, 2004, 2005, 2006 Takis Diakoumis
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: */
021:
022: package org.executequery.gui.table;
023:
024: import java.awt.Point;
025: import java.awt.event.MouseAdapter;
026: import java.awt.event.MouseEvent;
027: import java.sql.SQLException;
028: import java.util.Enumeration;
029: import java.util.Hashtable;
030: import javax.swing.DefaultCellEditor;
031:
032: import javax.swing.JOptionPane;
033:
034: import org.executequery.databasemediators.QuerySender;
035: import org.executequery.GUIUtilities;
036: import org.executequery.databasemediators.SqlStatementResult;
037: import org.executequery.gui.browser.ColumnData;
038: import org.underworldlabs.swing.GUIUtils;
039: import org.underworldlabs.util.MiscUtils;
040:
041: /* ----------------------------------------------------------
042: * CVS NOTE: Changes to the CVS repository prior to the
043: * release of version 3.0.0beta1 has meant a
044: * resetting of CVS revision numbers.
045: * ----------------------------------------------------------
046: */
047:
048: /**
049: *
050: * @author Takis Diakoumis
051: * @version $Revision: 1.5 $
052: * @date $Date: 2006/06/09 01:44:37 $
053: */
054: public class EditTablePanel extends TableDefinitionPanel {
055:
056: /** The table creator object - parent to this */
057: private TableModifier creator;
058:
059: /** The buffer off all SQL generated */
060: private StringBuffer sqlText;
061:
062: /** Holds temporary SQL text during modifications */
063: private Hashtable tempSqlText;
064:
065: /** The column descriptions for the current selection before modifications */
066: private ColumnData[] originalData;
067:
068: /** The string literal 'ALTER TABLE ' */
069: private static String DROP_COLUMN_1 = "ALTER TABLE ";
070:
071: /** The string literal ' DROP COLUMN ' */
072: private static String DROP_COLUMN_2 = " DROP COLUMN ";
073:
074: //------------------------------------------------
075: // The following are reuseable String constants
076: // used in the SQL text pane when making table
077: // or other schema modifications.
078: //------------------------------------------------
079:
080: /** The String literal 'ALTER TABLE ' */
081: private static final String ALTER_TABLE = "ALTER TABLE ";
082: /** The String literal ' MODIFY (' */
083: private static final String MODIFY = " MODIFY (";
084: /** The String literal ' NOT NULL' */
085: private static final String NOT_NULL = " NOT NULL";
086: /** The String literal ' NULL' */
087: private static final String NULL = " NULL";
088: /** The String literal ' ADD ' */
089: private static final String ADD = " ADD ";
090:
091: /** The String literal ' DROP ' */
092: private static final String DROP = " DROP ";
093:
094: /** The String literal ')' */
095: private static final String CLOSE_B = ")";
096: /** The character literal '(' */
097: private static final char OPEN_B = '(';
098: /** The String literal ' RENAME COLUMN ' */
099: private static final String RENAME_COLUMN = " RENAME COLUMN ";
100: /** The String literal ' TO ' */
101: private static final String TO = " TO ";
102: /** The character literal ',' */
103: private static final char COMMA = ',';
104: /** The character literal '.' */
105: private static final char DOT = '.';
106: /** The character literal ' ' */
107: private static final char SPACE = ' ';
108: /** An empty String literal */
109: private static final String EMPTY = "";
110: /** A semi-colon followed by a carriage return ';\n' */
111: private static final String NEW_LINE = ";\n";
112:
113: public EditTablePanel(TableModifier creator) {
114: super ();
115: this .creator = creator;
116:
117: sqlText = new StringBuffer(100);
118: tempSqlText = new Hashtable();
119: getTable().addMouseListener(new MouseHandler());
120: }
121:
122: public String getSQLText() {
123: generateSQL();
124: return sqlText.toString();
125: }
126:
127: public void setOriginalData(ColumnData[] cda) {
128: originalData = cda;
129: }
130:
131: /*
132: public void setColumnDataArray(ColumnData[] cda) {
133: _model.setColumnDataArray(cda);
134: }
135: */
136:
137: /** <p>Sets the SQL changes <code>Hashtable</code> to
138: * an existing one as the value passed.
139: *
140: * @param the SQL changes within a <code>Hashtable</code>
141: */
142: public void setSQLChangesHash(Hashtable tempSqlText) {
143: if (tempSqlText != null) {
144: this .tempSqlText = tempSqlText;
145: }
146: }
147:
148: /** <p>Returns the SQL changes within a <code>Hashtable</code>.
149: *
150: * @return the SQL changes
151: */
152: public Hashtable getSQLChangesHash() {
153: return tempSqlText;
154: }
155:
156: public void setOriginalData() {
157:
158: GUIUtils.startWorker(new Runnable() {
159: //SwingUtilities.invokeLater(new Runnable() {
160: public void run() {
161:
162: int v_size = tableVector.size();
163: originalData = new ColumnData[v_size];
164:
165: for (int i = 0; i < v_size; i++) {
166: originalData[i] = new ColumnData();
167: originalData[i].setValues(tableVector.elementAt(i));
168: }
169:
170: }
171: });
172:
173: }
174:
175: /** <p>Drops the currently selected column (table row)
176: * from the database table and applies this change
177: * to the database.
178: *
179: * @param the <code>QuerySender</code> to perform the
180: * operation on the database.
181: */
182: public void deleteRow(QuerySender qs) {
183: int row = getSelectedRow();
184: if (row == -1) {
185: return;
186: }
187:
188: tableEditingStopped(null);
189: if (isEditing()) {
190: removeEditor();
191: }
192:
193: ColumnData cd = tableVector.elementAt(row);
194:
195: int newEditingRow = row == tableVector.size() - 1 ? row - 1
196: : row;
197: setEditingRow(newEditingRow);
198:
199: if (cd.isNewColumn()) {
200: tableVector.removeElementAt(row);
201: _model.fireTableRowsDeleted(row, row);
202: tempSqlText.remove(ADD + row);
203: addColumnLines(-1);
204: return;
205: }
206:
207: int yesNo = GUIUtilities
208: .displayConfirmDialog("Are you sure you want to remove\n"
209: + "the column " + cd.getColumnName() + "?");
210:
211: if (yesNo == JOptionPane.NO_OPTION
212: || yesNo == JOptionPane.CANCEL_OPTION) {
213: return;
214: } else if (yesNo == JOptionPane.YES_OPTION) {
215:
216: try {
217: SqlStatementResult result = qs
218: .updateRecords(DROP_COLUMN_1
219: + creator.getTableName()
220: + DROP_COLUMN_2 + cd.getColumnName());
221:
222: if (result.getUpdateCount() >= 0) {
223: tableVector.removeElementAt(row);
224: _model.fireTableRowsDeleted(row, row);
225: }
226:
227: else {
228: SQLException e = result.getSqlException();
229: if (e != null) {
230: StringBuffer sb = new StringBuffer();
231: sb
232: .append(
233: "An error occurred applying the specified changes.")
234: .append("\n\nThe system returned:\n")
235: .append(MiscUtils.formatSQLError(e));
236: GUIUtilities.displayExceptionErrorDialog(sb
237: .toString(), e);
238: } else {
239: GUIUtilities.displayErrorMessage(result
240: .getErrorMessage());
241: }
242: }
243:
244: } catch (Exception e) {
245: e.printStackTrace();
246: StringBuffer sb = new StringBuffer();
247: sb
248: .append(
249: "An error occurred applying the specified changes.")
250: .append("\n\nThe system returned:\n").append(
251: e.getMessage());
252: GUIUtilities.displayExceptionErrorDialog(sb.toString(),
253: e);
254: }
255:
256: }
257:
258: }
259:
260: /**
261: * <p>Inserts a new column after the selected
262: * column moving the selected column up one row.
263: *
264: * Overrides to mark the column as new.
265: */
266: public void insertAfter() {
267: fireEditingStopped();
268:
269: int selection = getSelectedRow();
270: if (selection == -1) {
271: return;
272: }
273:
274: int newRow = selection + 1;
275: ColumnData cd = new ColumnData(true);
276: cd.setColumnRequired(ColumnData.VALUE_NOT_REQUIRED);
277:
278: if (selection == tableVector.size()) {
279: tableVector.add(cd);
280: } else {
281: tableVector.add(newRow, cd);
282: }
283:
284: _model.fireTableRowsInserted(selection, newRow);
285: setRowSelectionInterval(newRow);
286: setColumnSelectionInterval(1);
287:
288: setEditingRow(newRow);
289: setEditingColumn(1);
290: ((DefaultCellEditor) getCellEditor(newRow, 1)).getComponent()
291: .requestFocus();
292: }
293:
294: /**
295: * Marks the currently selected column (table row)
296: * to be deleted/dropped from this table.
297: */
298: public void markDeleteRow() {
299: int row = getSelectedRow();
300: if (row == -1) {
301: return;
302: }
303:
304: tableEditingStopped(null);
305: if (isEditing()) {
306: removeEditor();
307: }
308:
309: ColumnData cd = tableVector.elementAt(row);
310:
311: // if its already a new row - just remove it
312: if (cd.isNewColumn()) {
313: int newEditingRow = (row == tableVector.size() - 1) ? row - 1
314: : row;
315: setEditingRow(newEditingRow);
316: tableVector.removeElementAt(row);
317: _model.fireTableRowsDeleted(row, row);
318: tempSqlText.remove(ADD + row);
319: addColumnLines(-1);
320: return;
321: }
322:
323: // create the drop statement
324: sqlText.setLength(0);
325: sqlText.append(DROP_COLUMN_1);
326:
327: String schema = cd.getSchema();
328: if (!MiscUtils.isNull(schema)) {
329: sqlText.append(schema.toUpperCase()).append(DOT);
330: }
331:
332: sqlText.append(cd.getTableName());
333: sqlText.append(DROP_COLUMN_2);
334: sqlText.append(cd.getColumnName());
335: sqlText.append(NEW_LINE);
336: tempSqlText.put(DROP + row, sqlText.toString());
337:
338: // mark the column to be dumped
339: cd.setMarkedDeleted(true);
340:
341: // regenerate the SQL
342: generateSQL();
343:
344: // fire the event
345: _model.fireTableRowsUpdated(row, row);
346: }
347:
348: public void reset() {
349: sqlText.setLength(0);
350: tempSqlText.clear();
351: }
352:
353: public void tableChanged(int col, int row, String value) {
354: sqlText.setLength(0);
355: ColumnData cd = (ColumnData) tableVector.get(row);
356:
357: switch (col) {
358:
359: case 1:
360: if (value == null) {
361: return;
362: }
363:
364: if (cd.isNewColumn()) {
365:
366: sqlText.append(ALTER_TABLE);
367:
368: String schema = cd.getSchema();
369: if (!MiscUtils.isNull(schema)) {
370: sqlText.append(schema.toUpperCase()).append(DOT);
371: }
372:
373: sqlText.append(creator.getTableName()).append(ADD)
374: .append(value).append(SPACE);
375:
376: value = cd.getColumnType();
377: if (value != null && value.length() > 0) {
378: sqlText.append(value).append(OPEN_B).append(
379: cd.getColumnSize());
380:
381: int scale = cd.getColumnScale();
382: if (scale != 0) {
383: sqlText.append(COMMA).append(scale);
384: }
385:
386: sqlText.append(CLOSE_B).append(
387: cd.isRequired() ? NOT_NULL : NULL);
388: }
389:
390: sqlText.append(NEW_LINE);
391: tempSqlText.put(ADD + row, sqlText.toString());
392:
393: } else {
394:
395: if (originalData[row].getColumnName().equals(value)) {
396: tempSqlText.remove(RENAME_COLUMN + row);
397: } else {
398: sqlText.append(ALTER_TABLE);
399:
400: String schema = cd.getSchema();
401: if (!MiscUtils.isNull(schema)) {
402: sqlText.append(schema.toUpperCase())
403: .append(DOT);
404: }
405:
406: sqlText.append(originalData[row].getTableName())
407: .append(RENAME_COLUMN).append(
408: originalData[row].getColumnName())
409: .append(TO).append(value).append(NEW_LINE);
410:
411: tempSqlText.put(RENAME_COLUMN + row, sqlText
412: .toString());
413:
414: }
415:
416: }
417: break;
418:
419: case 2:
420: case 3:
421: case 4:
422: case 5:
423: tableChanged(cd, row, col);
424: break;
425:
426: }
427:
428: generateSQL();
429: creator.setSQLText(sqlText.toString(),
430: TableModifier.COLUMN_VALUES);
431: }
432:
433: private void tableChanged(ColumnData cd, int row, int col) {
434: sqlText.setLength(0);
435:
436: int size = cd.getColumnSize();
437: int scale = cd.getColumnScale();
438: String type = cd.getColumnType();
439:
440: /*
441: if (col == 2) {
442: type = (String)comboCell.getCellEditorValue();
443: } else if (col == 3) {
444: size = sizeEditor.getValue();
445: } else if (col == 4) {
446: scale = scaleEditor.getValue();
447: }
448: */
449:
450: if (cd.isNewColumn()) {
451: sqlText.append(ALTER_TABLE);
452:
453: String schema = cd.getSchema();
454: if (!MiscUtils.isNull(schema)) {
455: sqlText.append(schema.toUpperCase()).append(DOT);
456: }
457:
458: sqlText.append(creator.getTableName()).append(ADD).append(
459: cd.getColumnName()).append(SPACE).append(type)
460: .append(OPEN_B).append(size);
461:
462: if (scale != 0) {
463: sqlText.append(COMMA).append(scale);
464: }
465:
466: sqlText.append(CLOSE_B).append(
467: cd.isRequired() ? NOT_NULL : NULL).append(NEW_LINE);
468:
469: tempSqlText.put(ADD + row, sqlText.toString());
470: } else if (originalData[row].getColumnSize() == size
471: && originalData[row].getColumnType().equals(type)
472: && originalData[row].getColumnScale() == scale
473: && originalData[row].isRequired() == cd.isRequired()) {
474:
475: tempSqlText.remove(MODIFY + row);
476:
477: } else {
478: sqlText.append(ALTER_TABLE);
479:
480: String schema = cd.getSchema();
481: if (!MiscUtils.isNull(schema)) {
482: sqlText.append(schema.toUpperCase()).append(DOT);
483: }
484:
485: sqlText.append(originalData[row].getTableName()).append(
486: MODIFY).append(cd.getColumnName()).append(SPACE)
487: .append(type).append(OPEN_B).append(size);
488:
489: if (scale != 0) {
490: sqlText.append(COMMA).append(scale);
491: }
492:
493: sqlText.append(CLOSE_B).append(
494: cd.isRequired() ? NOT_NULL : NULL).append(CLOSE_B)
495: .append(NEW_LINE);
496:
497: tempSqlText.put(MODIFY + row, sqlText.toString());
498: }
499:
500: generateSQL();
501: creator.setSQLText(sqlText.toString(),
502: TableModifier.COLUMN_VALUES);
503: }
504:
505: private void generateSQL() {
506: sqlText.setLength(0);
507:
508: for (Enumeration i = tempSqlText.elements(); i
509: .hasMoreElements();) {
510: sqlText.append((String) i.nextElement());
511: }
512:
513: }
514:
515: /** <p>Adds all the column definition lines to
516: * the SQL text buffer for display.
517: *
518: * @param the current row being edited
519: */
520: public void addColumnLines(int row) {
521: generateSQL();
522: creator.setSQLText(sqlText.toString(),
523: TableModifier.COLUMN_VALUES);
524: }
525:
526: private class MouseHandler extends MouseAdapter {
527: public void mouseClicked(MouseEvent e) {
528: int mouseX = e.getX();
529: int mouseY = e.getY();
530:
531: int col = getTable().columnAtPoint(
532: new Point(mouseX, mouseY));
533: if (col != 0) {
534: return;
535: }
536:
537: ColumnData[] cda = getTableColumnData();
538: int row = getTable().rowAtPoint(new Point(mouseX, mouseY));
539: for (int i = 0; i < cda.length; i++) {
540: if (i == row) {
541: if (cda[i].isMarkedDeleted()) {
542: cda[i].setMarkedDeleted(false);
543: tempSqlText.remove(DROP + row);
544: _model.fireTableRowsUpdated(row, row);
545: generateSQL();
546: creator.setSQLText();
547: }
548: break;
549: }
550: }
551:
552: }
553: }
554:
555: }
|