001: /*
002: * CreateTableFunctionPanel.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.BorderLayout;
025: import java.awt.Component;
026: import java.awt.GridBagConstraints;
027: import java.awt.GridBagLayout;
028: import java.awt.Insets;
029: import java.awt.event.ItemEvent;
030: import java.awt.event.ItemListener;
031: import java.awt.event.KeyEvent;
032:
033: import java.util.Vector;
034:
035: import javax.swing.BorderFactory;
036: import javax.swing.JComboBox;
037: import javax.swing.JLabel;
038: import javax.swing.JPanel;
039: import javax.swing.JTabbedPane;
040: import javax.swing.JTextField;
041: import javax.swing.event.ChangeEvent;
042: import javax.swing.event.ChangeListener;
043: import org.executequery.GUIUtilities;
044: import org.underworldlabs.swing.DynamicComboBoxModel;
045:
046: import org.executequery.databasemediators.*;
047: import org.executequery.datasource.ConnectionManager;
048: import org.executequery.gui.FocusComponentPanel;
049: import org.executequery.gui.browser.*;
050: import org.executequery.gui.text.TextEditor;
051: import org.executequery.gui.text.SimpleSqlTextPanel;
052: import org.executequery.gui.text.TextEditorContainer;
053: import org.underworldlabs.jdbc.DataSourceException;
054: import org.underworldlabs.swing.GUIUtils;
055: import org.underworldlabs.util.MiscUtils;
056:
057: /* ----------------------------------------------------------
058: * CVS NOTE: Changes to the CVS repository prior to the
059: * release of version 3.0.0beta1 has meant a
060: * resetting of CVS revision numbers.
061: * ----------------------------------------------------------
062: */
063:
064: /**
065: * The Create Table base panel.
066: *
067: * @author Takis Diakoumis
068: * @version $Revision: 1.8 $
069: * @date $Date: 2006/07/16 06:47:12 $
070: */
071: public abstract class CreateTableFunctionPanel extends JPanel implements
072: FocusComponentPanel, ItemListener, ChangeListener,
073: TableModifier, TableConstraintFunction, TextEditorContainer {
074:
075: /** The table name field */
076: protected JTextField nameField;
077:
078: /** The schema combo box */
079: protected JComboBox schemaCombo;
080:
081: /** the schema combo box model */
082: protected DynamicComboBoxModel schemaModel;
083:
084: /** The connection combo selection */
085: protected JComboBox connectionsCombo;
086:
087: /** the schema combo box model */
088: protected DynamicComboBoxModel connectionsModel;
089:
090: /** The table column definition panel */
091: protected NewTablePanel tablePanel;
092:
093: /** The table constraints panel */
094: protected NewTableConstraintsPanel consPanel;
095:
096: /** The text pane showing SQL generated */
097: protected SimpleSqlTextPanel sqlText;
098:
099: /** The tabbed pane containing definition and constraints */
100: private JTabbedPane tableTabs;
101:
102: /** The buffer off all SQL generated */
103: protected StringBuffer sqlBuffer;
104:
105: /** The tool bar */
106: private CreateTableToolBar tools;
107:
108: /** Utility to retrieve database meta data */
109: protected MetaDataValues metaData;
110:
111: /** The base panel */
112: protected JPanel mainPanel;
113:
114: /** <p> Constructs a new instance. */
115: public CreateTableFunctionPanel() {
116: super (new BorderLayout());
117:
118: try {
119: jbInit();
120: } catch (Exception e) {
121: e.printStackTrace();
122: }
123:
124: }
125:
126: /** <p>Initializes the state of this instance. */
127: private void jbInit() throws Exception {
128:
129: nameField = new JTextField();
130: //initialise the schema label
131: metaData = new MetaDataValues(true);
132:
133: // combo boxes
134: Vector connections = ConnectionManager.getActiveConnections();
135: connectionsModel = new DynamicComboBoxModel(connections);
136: connectionsCombo = new JComboBox(connectionsModel);
137: connectionsCombo.addItemListener(this );
138:
139: schemaModel = new DynamicComboBoxModel();
140: schemaCombo = new JComboBox(schemaModel);
141: schemaCombo.addItemListener(this );
142:
143: // create tab pane
144: tableTabs = new JTabbedPane();
145: // create the column definition panel
146: // and add this to the tabbed pane
147: tablePanel = new NewTablePanel(this );
148: tableTabs.add("Columns", tablePanel);
149:
150: // create the constraints table and model
151: JPanel constraintsPanel = new JPanel(new GridBagLayout());
152: consPanel = new NewTableConstraintsPanel(this );
153: consPanel.setData(new Vector(0), true);
154:
155: constraintsPanel.add(consPanel, new GridBagConstraints(1, 1, 1,
156: 1, 1.0, 1.0, GridBagConstraints.SOUTHEAST,
157: GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0));
158:
159: tableTabs.add("Constraints", constraintsPanel);
160:
161: sqlText = new SimpleSqlTextPanel();
162: tools = new CreateTableToolBar(this );
163:
164: mainPanel = new JPanel(new GridBagLayout());
165: mainPanel.setBorder(BorderFactory.createEtchedBorder());
166:
167: GridBagConstraints gbc = new GridBagConstraints();
168: gbc.insets = new Insets(7, 5, 5, 5);
169: gbc.gridy++;
170: gbc.gridx = 0;
171: gbc.gridwidth = 2;
172: gbc.anchor = GridBagConstraints.NORTHWEST;
173: gbc.fill = GridBagConstraints.NONE;
174: mainPanel.add(new JLabel("Connection:"), gbc);
175: gbc.gridx = 2;
176: gbc.weightx = 1.0;
177: gbc.gridwidth = 1;
178: gbc.insets.left = 0;
179: gbc.insets.top = 5;
180: gbc.fill = GridBagConstraints.HORIZONTAL;
181: mainPanel.add(connectionsCombo, gbc);
182: gbc.gridy++;
183: gbc.gridx = 0;
184: gbc.gridwidth = 2;
185: gbc.insets.top = 0;
186: gbc.insets.left = 5;
187: gbc.weightx = 0;
188: gbc.fill = GridBagConstraints.NONE;
189: mainPanel.add(new JLabel("Schema:"), gbc);
190: gbc.gridx = 2;
191: gbc.weightx = 1.0;
192: gbc.gridwidth = 1;
193: gbc.insets.left = 0;
194: gbc.fill = GridBagConstraints.HORIZONTAL;
195: mainPanel.add(schemaCombo, gbc);
196: gbc.gridy++;
197: gbc.gridx = 0;
198: gbc.gridwidth = 2;
199: gbc.insets.left = 5;
200: gbc.weightx = 0;
201: gbc.fill = GridBagConstraints.NONE;
202: mainPanel.add(new JLabel("Table Name:"), gbc);
203: gbc.gridwidth = GridBagConstraints.REMAINDER;
204: gbc.gridx = 2;
205: gbc.weightx = 1.0;
206: gbc.insets.left = 0;
207: gbc.gridwidth = 1;
208: gbc.fill = GridBagConstraints.HORIZONTAL;
209: mainPanel.add(nameField, gbc);
210: gbc.gridwidth = 1;
211: gbc.gridx = 0;
212: gbc.gridy++;
213: gbc.weightx = 0;
214: gbc.insets.right = 0;
215: gbc.insets.left = 5;
216: gbc.insets.top = 20;
217: gbc.fill = GridBagConstraints.VERTICAL;
218: mainPanel.add(tools, gbc);
219: gbc.insets.left = 0;
220: gbc.insets.right = 5;
221: gbc.insets.top = 0;
222: gbc.gridx = 1;
223: gbc.weighty = 0.4;
224: gbc.weightx = 1.0;
225: gbc.fill = GridBagConstraints.BOTH;
226: gbc.gridwidth = GridBagConstraints.REMAINDER;
227: mainPanel.add(tableTabs, gbc);
228: gbc.gridx = 0;
229: gbc.gridy++;
230: gbc.weighty = 0.6;
231: gbc.insets.left = 5;
232: gbc.insets.bottom = 5;
233: gbc.insets.top = 10;
234: mainPanel.add(sqlText, gbc);
235:
236: setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
237: add(mainPanel, BorderLayout.CENTER);
238:
239: tableTabs.addChangeListener(this );
240: nameField.addKeyListener(new java.awt.event.KeyAdapter() {
241: public void keyReleased(KeyEvent e) {
242: setSQLText();
243: }
244: });
245:
246: sqlBuffer = new StringBuffer(CreateTableSQLSyntax.CREATE_TABLE);
247:
248: // check initial values for possible value inits
249: if (connections == null || connections.isEmpty()) {
250: schemaCombo.setEnabled(false);
251: connectionsCombo.setEnabled(false);
252: } else {
253: DatabaseConnection connection = (DatabaseConnection) connections
254: .elementAt(0);
255: metaData.setDatabaseConnection(connection);
256: Vector schemas = metaData.getHostedSchemasVector();
257: if (schemas == null || schemas.size() == 0) {
258: schemas = metaData.getHostedCatalogsVector();
259: }
260: schemaModel.setElements(schemas);
261: schemaCombo.setSelectedIndex(0);
262: tablePanel.setDataTypes(metaData.getDataTypesArray());
263: }
264:
265: }
266:
267: /**
268: * Returns the selected connection from the panel's
269: * connections combo selection box.
270: *
271: * @return the selected connection properties object
272: */
273: public DatabaseConnection getSelectedConnection() {
274: return (DatabaseConnection) connectionsCombo.getSelectedItem();
275: }
276:
277: /**
278: * Returns the table name field.
279: */
280: public Component getDefaultFocusComponent() {
281: return nameField;
282: }
283:
284: /**
285: * Invoked when an item has been selected or deselected by the user.
286: * The code written for this method performs the operations
287: * that need to occur when an item is selected (or deselected).
288: */
289: public void itemStateChanged(ItemEvent event) {
290: // interested in selections only
291: if (event.getStateChange() == ItemEvent.DESELECTED) {
292: return;
293: }
294:
295: final Object source = event.getSource();
296: GUIUtils.startWorker(new Runnable() {
297: public void run() {
298: try {
299: setInProcess(true);
300: if (source == connectionsCombo) {
301: connectionChanged();
302: } else if (source == schemaCombo) {
303: setSQLText();
304: }
305: } finally {
306: setInProcess(false);
307: }
308: }
309: });
310: }
311:
312: private void connectionChanged() {
313: // retrieve connection selection
314: DatabaseConnection connection = (DatabaseConnection) connectionsCombo
315: .getSelectedItem();
316:
317: // reset meta data
318: metaData.setDatabaseConnection(connection);
319:
320: // reset schema values
321: try {
322: Vector schemas = metaData.getHostedSchemasVector();
323: if (schemas == null || schemas.isEmpty()) {
324: // try catalogs (ie. for mysql and others where schema not used)
325: schemas = metaData.getHostedCatalogsVector();
326: }
327: populateSchemaValues(schemas);
328: } catch (DataSourceException e) {
329: GUIUtilities
330: .displayExceptionErrorDialog(
331: "Error retrieving the catalog/schema names for the "
332: + "selected connection.\n\nThe system returned:\n"
333: + e.getExtendedMessage(), e);
334: populateSchemaValues(new Vector<String>(0));
335: }
336:
337: // reset data types
338: try {
339: populateDataTypes(metaData.getDataTypesArray());
340: } catch (DataSourceException e) {
341: GUIUtilities
342: .displayExceptionErrorDialog(
343: "Error retrieving the data types for the "
344: + "selected connection.\n\nThe system returned:\n"
345: + e.getExtendedMessage(), e);
346: populateDataTypes(new String[0]);
347: }
348:
349: }
350:
351: private void populateDataTypes(final String[] dataTypes) {
352: GUIUtils.invokeAndWait(new Runnable() {
353: public void run() {
354: tablePanel.setDataTypes(dataTypes);
355: }
356: });
357: }
358:
359: private void populateSchemaValues(final Vector schemas) {
360: GUIUtils.invokeAndWait(new Runnable() {
361: public void run() {
362: schemaModel.setElements(schemas);
363: schemaCombo.setSelectedIndex(0);
364: schemaCombo.setEnabled(true);
365: }
366: });
367: }
368:
369: public void setFocusComponent() {
370: nameField.requestFocusInWindow();
371: nameField.selectAll();
372: }
373:
374: public void setSQLTextCaretPosition(int position) {
375: sqlText.setCaretPosition(position);
376: }
377:
378: protected void addButtonsPanel(JPanel buttonsPanel) {
379: add(buttonsPanel, BorderLayout.SOUTH);
380: }
381:
382: public void fireEditingStopped() {
383: tablePanel.fireEditingStopped();
384: consPanel.fireEditingStopped();
385: }
386:
387: public void setColumnDataArray(ColumnData[] cda) {
388: tablePanel.setColumnDataArray(cda, null);
389: }
390:
391: public void setColumnConstraintVector(Vector ccv, boolean fillCombos) {
392: consPanel.setData(ccv, fillCombos);
393: }
394:
395: public void setColumnConstraintsArray(ColumnConstraint[] cca,
396: boolean fillCombos) {
397: Vector ccv = new Vector(cca.length);
398: for (int i = 0; i < cca.length; i++) {
399: ccv.add(cca[i]);
400: }
401: consPanel.setData(ccv, fillCombos);
402: }
403:
404: /**
405: * Indicates that a [long-running] process has begun or ended
406: * as specified. This may trigger the glass pane on or off
407: * or set the cursor appropriately.
408: *
409: * @param inProcess - true | false
410: */
411: public void setInProcess(boolean inProcess) {
412: }
413:
414: // -----------------------------------------------
415: // --- TableConstraintFunction implementations ---
416: // -----------------------------------------------
417:
418: public abstract Vector<String> getHostedSchemasVector();
419:
420: public abstract Vector<String> getSchemaTables(String schemaName);
421:
422: public abstract Vector<String> getColumnNamesVector(
423: String tableName, String schemaName);
424:
425: public void resetSQLText() {
426: tablePanel.resetSQLText();
427: consPanel.resetSQLText();
428: }
429:
430: public void setSQLText() {
431: sqlBuffer.setLength(0);
432: sqlBuffer.append(CreateTableSQLSyntax.CREATE_TABLE);
433:
434: // check for a valid schema name
435: if (schemaModel.getSize() > 0) {
436: String schema = schemaCombo.getSelectedItem().toString();
437: if (!MiscUtils.isNull(schema)) {
438: sqlBuffer.append(schemaCombo.getSelectedItem()).append(
439: CreateTableSQLSyntax.DOT);
440:
441: }
442: }
443:
444: sqlBuffer.append(nameField.getText()).append(
445: CreateTableSQLSyntax.SPACE).append(
446: CreateTableSQLSyntax.B_OPEN).append(
447: tablePanel.getSQLText()).append(consPanel.getSQLText());
448:
449: sqlBuffer.append(CreateTableSQLSyntax.B_CLOSE).append(
450: CreateTableSQLSyntax.SEMI_COLON);
451:
452: setSQLText(sqlBuffer.toString());
453: }
454:
455: public void setSQLText(String values, int type) {
456: sqlBuffer.setLength(0);
457: sqlBuffer.append(CreateTableSQLSyntax.CREATE_TABLE);
458:
459: // check for a valid schema name
460: if (schemaModel.getSize() > 0) {
461: String schema = schemaCombo.getSelectedItem().toString();
462: if (!MiscUtils.isNull(schema)) {
463: sqlBuffer.append(schemaCombo.getSelectedItem()).append(
464: CreateTableSQLSyntax.DOT);
465:
466: }
467: }
468:
469: sqlBuffer.append(nameField.getText()).append(
470: CreateTableSQLSyntax.SPACE).append(
471: CreateTableSQLSyntax.B_OPEN);
472:
473: if (type == TableModifier.COLUMN_VALUES) {
474: sqlBuffer.append(values).append(consPanel.getSQLText());
475: } else if (type == TableModifier.CONSTRAINT_VALUES) {
476: sqlBuffer.append(tablePanel.getSQLText()).append(values);
477: }
478:
479: sqlBuffer.append(CreateTableSQLSyntax.B_CLOSE).append(
480: CreateTableSQLSyntax.SEMI_COLON);
481: setSQLText(sqlBuffer.toString());
482: }
483:
484: private void setSQLText(final String text) {
485: GUIUtils.invokeLater(new Runnable() {
486: public void run() {
487: sqlText.setSQLText(text);
488: }
489: });
490: }
491:
492: public String getSQLText() {
493: return sqlText.getSQLText();
494: }
495:
496: public String getTableName() {
497: return nameField.getText();
498: }
499:
500: // -----------------------------------------------
501:
502: // constraints panel only
503: public void updateCellEditor(int col, int row, String value) {
504: }
505:
506: public void columnValuesChanging(int col, int row, String value) {
507: }
508:
509: public Vector getTableColumnDataVector() {
510: return tablePanel.getTableColumnDataVector();
511: }
512:
513: public void stateChanged(ChangeEvent e) {
514: if (tableTabs.getSelectedIndex() == 1) {
515: tools.enableButtons(false);
516:
517: // if (table.isEditing())
518: // table.removeEditor();
519:
520: } else {
521: tools.enableButtons(true);
522: }
523: }
524:
525: /*
526: private void tableTabs_changed() {
527:
528: if (tableTabs.getSelectedIndex() == 1) {
529: tools.enableButtons(false);
530:
531: // if (table.isEditing())
532: // table.removeEditor();
533:
534: }
535: else {
536: tools.enableButtons(true);
537: }
538:
539: }
540: */
541:
542: public ColumnData[] getTableColumnDataAndConstraints() {
543: String tableName = null;
544: ColumnData[] cda = tablePanel.getTableColumnData();
545: ColumnConstraint[] cca = consPanel.getColumnConstraintArray();
546:
547: for (int i = 0; i < cda.length; i++) {
548:
549: // reset the keys
550: cda[i].setPrimaryKey(false);
551: cda[i].setForeignKey(false);
552: cda[i].resetConstraints();
553:
554: tableName = cda[i].getTableName();
555:
556: for (int j = 0; j < cca.length; j++) {
557:
558: if (cca[j].getColumn().equalsIgnoreCase(
559: cda[i].getColumnName())) {
560:
561: if (cca[j].isPrimaryKey()) {
562: cda[i].setPrimaryKey(true);
563: } else if (cca[j].isForeignKey()) {
564: cda[i].setForeignKey(true);
565: }
566:
567: cca[j].setTable(tableName);
568: cca[j].setNewConstraint(true);
569: cda[i].addConstraint(cca[j]);
570: }
571:
572: }
573:
574: }
575:
576: return cda;
577:
578: }
579:
580: public void columnValuesChanging() {
581: }
582:
583: public ColumnData[] getTableColumnData() {
584: return tablePanel.getTableColumnData();
585: }
586:
587: // -----------------------------------------------
588: // -------- TableFunction implementations --------
589: // -----------------------------------------------
590:
591: public void moveColumnUp() {
592: int index = tableTabs.getSelectedIndex();
593: if (index == 0) {
594: tablePanel.moveColumnUp();
595: }
596: }
597:
598: public void moveColumnDown() {
599: int index = tableTabs.getSelectedIndex();
600: if (index == 0) {
601: tablePanel.moveColumnDown();
602: }
603: }
604:
605: public void deleteRow() {
606: if (tableTabs.getSelectedIndex() == 0) {
607: tablePanel.deleteRow();
608: } else if (tableTabs.getSelectedIndex() == 1) {
609: consPanel.deleteSelectedRow();
610: }
611: }
612:
613: public void insertBefore() {
614: tablePanel.insertBefore();
615: }
616:
617: public void insertAfter() {
618: if (tableTabs.getSelectedIndex() == 0) {
619: tablePanel.insertAfter();
620: } else if (tableTabs.getSelectedIndex() == 1) {
621: consPanel.insertRowAfter();
622: }
623: }
624:
625: // -----------------------------------------------
626:
627: public String getDisplayName() {
628: return "";
629: }
630:
631: // ------------------------------------------------
632: // ----- TextEditorContainer implementations ------
633: // ------------------------------------------------
634:
635: /**
636: * Returns the SQL text pane as the TextEditor component
637: * that this container holds.
638: */
639: public TextEditor getTextEditor() {
640: return sqlText;
641: }
642:
643: }
|