p2izing the editor
[taxeditor.git] / eclipseprojects / eu.etaxonomy.taxeditor / src / eu / etaxonomy / taxeditor / datasource / CdmDataSourceDialog.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.taxeditor.datasource;
11
12 import java.util.ArrayList;
13
14 import org.apache.log4j.Logger;
15 import org.eclipse.jface.action.MenuManager;
16 import org.eclipse.jface.dialogs.Dialog;
17 import org.eclipse.jface.dialogs.IDialogConstants;
18 import org.eclipse.jface.dialogs.MessageDialog;
19 import org.eclipse.jface.viewers.ArrayContentProvider;
20 import org.eclipse.jface.viewers.DoubleClickEvent;
21 import org.eclipse.jface.viewers.IDoubleClickListener;
22 import org.eclipse.jface.viewers.IStructuredSelection;
23 import org.eclipse.jface.viewers.LabelProvider;
24 import org.eclipse.jface.viewers.TableViewer;
25 import org.eclipse.swt.SWT;
26 import org.eclipse.swt.custom.CCombo;
27 import org.eclipse.swt.events.ModifyEvent;
28 import org.eclipse.swt.events.ModifyListener;
29 import org.eclipse.swt.events.MouseAdapter;
30 import org.eclipse.swt.events.MouseEvent;
31 import org.eclipse.swt.events.SelectionAdapter;
32 import org.eclipse.swt.events.SelectionEvent;
33 import org.eclipse.swt.graphics.Point;
34 import org.eclipse.swt.layout.GridData;
35 import org.eclipse.swt.layout.GridLayout;
36 import org.eclipse.swt.widgets.Button;
37 import org.eclipse.swt.widgets.Composite;
38 import org.eclipse.swt.widgets.Control;
39 import org.eclipse.swt.widgets.Group;
40 import org.eclipse.swt.widgets.Label;
41 import org.eclipse.swt.widgets.Menu;
42 import org.eclipse.swt.widgets.Shell;
43 import org.eclipse.swt.widgets.Table;
44 import org.eclipse.swt.widgets.Text;
45
46 import eu.etaxonomy.cdm.common.CdmUtils;
47 import eu.etaxonomy.cdm.database.CdmDataSource;
48 import eu.etaxonomy.cdm.database.CdmPersistentDataSource;
49 import eu.etaxonomy.cdm.database.DatabaseTypeEnum;
50 import eu.etaxonomy.cdm.database.ICdmDataSource;
51 import eu.etaxonomy.taxeditor.controller.GlobalController;
52 /**
53 * List of database types comes from {@link eu.etaxonomy.cdm.database.DatabaseTypeEnum}.
54 *
55 * @author p.ciardelli
56 * @created 11.12.2008
57 * @version 1.0
58 */
59 public class CdmDataSourceDialog extends Dialog {
60 private static final Logger logger = Logger.getLogger(CdmDataSourceDialog.class);
61
62 private Text portText;
63 private Text serverText;
64 private Text passwordText;
65 private Text databaseNameText;
66 private Text datasourceNameText;
67 private CCombo databaseTypeCombo;
68 private Text usernameText;
69
70 private Composite container;
71 private Composite editDatasourceComposite;
72 private Group authenticationGroup;
73 private Group locationGroup;
74 private Button saveButton;
75 private Composite dbConfigComposite;
76
77 private ArrayList<DatabaseTypeEnum> databaseTypes;
78 private ICdmDataSource dataSource = null;
79
80 private TableViewer dataSourceViewer;
81
82 private Button btnEdit;
83
84 private Button btnRemove;
85
86 private ICdmDataSource selectedDataSource;
87
88 private Shell parentShell;
89
90 /**
91 * Any time user modifies datasource properties, force a save or a cancel
92 */
93 ModifyListener modifyListener = new ModifyListener() {
94 public void modifyText(ModifyEvent e) {
95 forceUserToSave(true);
96 }
97 };
98
99 /**
100 * Create the dialog
101 * @param parentShell
102 */
103 public CdmDataSourceDialog(Shell parentShell) {
104 super(parentShell);
105 this.parentShell = parentShell;
106 }
107
108 protected void configureShell(Shell shell) {
109 super.configureShell(shell);
110 shell.setText("Edit Data Sources");
111 }
112
113 /**
114 * Create contents of the dialog
115 * @param parent
116 */
117 @Override
118 protected Control createDialogArea(Composite parent) {
119
120 // Create top-level composite
121 container = (Composite) super.createDialogArea(parent);
122 GridLayout gridLayout = new GridLayout();
123 gridLayout.numColumns = 5;
124 container.setLayout(gridLayout);
125
126 // Create buttons to edit list
127 btnEdit = new Button(container, SWT.NONE);
128 btnEdit.setText("Edit ...");
129 btnEdit.setEnabled(false);
130 btnEdit.addSelectionListener(new SelectionAdapter() {
131 public void widgetSelected(SelectionEvent e) {
132 // if (getSelectedTypeDesignation() != null) {
133 // createTypeDesignationWizard(getSelectedTypeDesignation());
134 // }
135 if (getSelectedDataSource() != null) {
136 showDatasource(getSelectedDataSource());
137 }
138 }
139 });
140
141 btnRemove = new Button(container, SWT.NONE);
142 btnRemove.setText("Remove");
143 btnRemove.setEnabled(false);
144 btnRemove.addSelectionListener(new SelectionAdapter() {
145 public void widgetSelected(SelectionEvent e) {
146 if (getSelectedDataSource() != null) {
147 removeDataSource(getSelectedDataSource());
148 setSelectedDataSource(null);
149 }
150 }
151 });
152
153 final Button btnAdd = new Button(container, SWT.NONE);
154 final GridData gd_btnAdd = new GridData(SWT.RIGHT, SWT.CENTER, true,
155 false);
156 btnAdd.setLayoutData(gd_btnAdd);
157 btnAdd.setText("Add ...");
158 btnAdd.addSelectionListener(new SelectionAdapter() {
159 public void widgetSelected(SelectionEvent e) {
160 showNewDatasource();
161 }
162 });
163
164 // Create viewer for datasource list
165 dataSourceViewer = new TableViewer(container, SWT.BORDER);
166 GridData viewerLayout = new GridData(SWT.LEFT, SWT.FILL, false, true, 3, 1);
167 viewerLayout.widthHint = 162;
168 dataSourceViewer.getTable().setLayoutData(viewerLayout);
169
170 // Set providers for datasource list
171 dataSourceViewer.setContentProvider(new ArrayContentProvider());
172 dataSourceViewer.setLabelProvider(new LabelProvider() {
173 public String getText(Object element) {
174 if (element instanceof ICdmDataSource) {
175 return ((ICdmDataSource) element).getName();
176 }
177 return super.getText(element);
178 }
179 });
180
181 // Add data sources to viewer
182 refreshDataSourceViewer();
183
184 // Double-clicking on a dataSource in the viewer puts it in the editable area
185 dataSourceViewer.addDoubleClickListener(new IDoubleClickListener() {
186 public void doubleClick(DoubleClickEvent event) {
187
188 Object dataSource =
189 ((IStructuredSelection) event.getSelection()).
190 getFirstElement();
191
192 if (dataSource instanceof ICdmDataSource) {
193
194 // Existing datasource
195 showDatasource((ICdmDataSource) dataSource);
196 } else {
197
198 // New datasource
199 showDatasource(null);
200 }
201 }
202 });
203
204 // Create "remove datasource" rt-click menu
205 Table dataSourceControl = dataSourceViewer.getTable();
206 final MenuManager manager = new MenuManager();
207 final Menu menu = manager.createContextMenu(dataSourceControl);
208 dataSourceControl.setMenu(menu);
209
210 // Add right-click menu to delete datasources
211 dataSourceControl.addSelectionListener(new SelectionAdapter() {
212 public void widgetSelected(SelectionEvent e) {
213
214 setEnableTypeDesignationButtons(true);
215
216 // Get content of widget's data field
217 if (e.item.getData() instanceof ICdmDataSource) {
218 setSelectedDataSource((ICdmDataSource) e.item.getData());
219 }
220
221
222 // Clear menu
223 // manager.removeAll();
224
225 // Only persistent data sources can be removed -
226 // H2 database and "New datasource" entry remain untouched
227 // if (data instanceof CdmPersistentDataSource) {
228 // manager.add(new RemoveDataSourceAction((CdmPersistentDataSource) data));
229 // }
230 }
231 });
232
233 // Create editDatasourceComposite to display a dataSource's name and type
234 editDatasourceComposite = new Composite(container, SWT.NONE);
235 GridData datasourceGridData = new GridData(SWT.FILL, SWT.TOP, true, true);
236 editDatasourceComposite.setLayoutData(datasourceGridData);
237 GridLayout datasourceLayout = new GridLayout();
238 datasourceLayout.numColumns = 2;
239 editDatasourceComposite.setLayout(datasourceLayout);
240
241 // Create label and input for dataSource name
242 Label datasourceNameLabel = new Label(editDatasourceComposite, SWT.NONE);
243 datasourceNameLabel.setText("Datasource Name:");
244 datasourceNameText = new Text(editDatasourceComposite, SWT.BORDER);
245 datasourceNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
246
247 // Create label and dropdown for database type
248 Label databaseTypeLabel = new Label(editDatasourceComposite, SWT.NONE);
249 databaseTypeLabel.setText("Database Type:");
250 databaseTypeCombo = new CCombo(editDatasourceComposite, SWT.BORDER);
251 GridData comboLayout = new GridData(SWT.FILL, SWT.CENTER, false, false);
252 databaseTypeCombo.setLayoutData(comboLayout);
253 populateComboBoxItems();
254
255 // Create listener to display database type-specific config options
256 databaseTypeCombo.addSelectionListener(new SelectionAdapter() {
257 public void widgetSelected(SelectionEvent e) {
258
259 // Get database type at the selected index
260 DatabaseTypeEnum type = databaseTypes.get(databaseTypeCombo.getSelectionIndex());
261
262 // Display type-specific input fields
263 showDatabaseConfig(dataSource, type);
264 }
265 });
266
267 // Hide editable fields until a dataSource is chosen
268 editDatasourceComposite.setVisible(false);
269
270 return container;
271 }
272
273 /**
274 *
275 */
276 protected void showNewDatasource() {
277 showDatasource(null);
278 }
279
280 /**
281 * @param selectedDataSource
282 */
283 protected void removeDataSource(ICdmDataSource dataSource) {
284
285 if (dataSource instanceof CdmPersistentDataSource) {
286
287 // Delete from persistent data sources
288 CdmDataSourceRepository.getDefault().delete((CdmPersistentDataSource) dataSource);
289
290 // Refresh list of data sources to reflect changes
291 refreshDataSourceViewer();
292
293 } else {
294 MessageDialog.openInformation(parentShell, "Data source not persistent",
295 "This data source cannot be removed. Only persistent data sources can be removed.");
296 }
297 }
298
299 /**
300 * @return
301 */
302 protected ICdmDataSource getSelectedDataSource() {
303 return selectedDataSource;
304 }
305
306 /**
307 *
308 */
309 protected void setSelectedDataSource(ICdmDataSource selectedDataSource) {
310 this.selectedDataSource = selectedDataSource;
311 }
312
313 /**
314 * @param enabled
315 */
316 protected void setEnableTypeDesignationButtons(boolean enabled) {
317 btnEdit.setEnabled(enabled);
318 btnRemove.setEnabled(enabled);
319 }
320
321 private void showDatasource(ICdmDataSource dataSource) {
322
323 // Put dataSource in field
324 this.dataSource = dataSource;
325
326 // Make editable fields visible
327 editDatasourceComposite.setVisible(true);
328
329 // Remove any existing db config data
330 removeDbConfigFields();
331
332 // Populate name and database type if this is a non-null dataSource
333 if (dataSource != null) {
334 datasourceNameText.setText(dataSource.getName());
335 datasourceNameText.setEnabled(false);
336 selectDatabaseType(dataSource.getDatabaseType());
337 databaseTypeCombo.setEnabled(false);
338 } else {
339 datasourceNameText.setText("");
340 datasourceNameText.setEnabled(true);
341 databaseTypeCombo.setText(""); // for some reason, .deselectAll and .clearSelection don't work as advertised
342 databaseTypeCombo.setEnabled(true);
343 }
344
345 }
346
347 private void showDatabaseConfig(ICdmDataSource dataSource, DatabaseTypeEnum type) {
348 if (type.equals(DatabaseTypeEnum.MySQL)) {
349 createMySqlForm(dataSource);
350 } else {
351 // TODO Intrusive - change to text
352 MessageDialog.openInformation(GlobalController.getShell(), "Database not yet implemented",
353 "Creation or editing of datasources using a(n) '" + type.getName() + "' database not yet implemented.");
354 }
355 }
356
357 private void selectDatabaseType(DatabaseTypeEnum type) {
358
359 int i = 0;
360
361 // Go through types list until match is found
362 for (DatabaseTypeEnum typeInList : databaseTypes ) {
363 if (typeInList.equals(type)) {
364
365 // Set combo to the type
366 databaseTypeCombo.select(i);
367 break;
368 }
369 i++;
370 }
371
372 // Display type-specific input fields
373 showDatabaseConfig(dataSource, type);
374
375 // // If we're this far, database type was not in the list
376 // MessageDialog.openInformation(UiUtil.getShell(), "Database not yet implemented",
377 // "This dataSource expects a database type '" + type.getName() +
378 // "', which is not in the Taxonomic Editor's list of expected databases.");
379 }
380
381 private void populateComboBoxItems() {
382
383 // Init DB types
384 if (databaseTypes == null) {
385 databaseTypes = new ArrayList<DatabaseTypeEnum>();
386 }
387
388 // Add types to the type drop-down and to the types collection
389 for (DatabaseTypeEnum type : DatabaseTypeEnum.getAllTypes()) {
390 databaseTypeCombo.add(type.getName());
391 databaseTypes.add(type);
392 }
393 }
394
395 /**
396 * Create contents of the button bar
397 * @param parent
398 */
399 @Override
400 protected void createButtonsForButtonBar(Composite parent) {
401 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
402 true);
403 createButton(parent, IDialogConstants.CANCEL_ID,
404 IDialogConstants.CANCEL_LABEL, false);
405 }
406
407 /**
408 * Return the initial size of the dialog
409 */
410 @Override
411 protected Point getInitialSize() {
412 return new Point(500, 375);
413 }
414
415 private void removeDbConfigFields() {
416 // Init db config area by removing all children
417 if (dbConfigComposite != null) {
418 for (Control child : dbConfigComposite.getChildren()) {
419 child.dispose();
420 }
421 }
422 }
423
424 private void createH2Form() {
425
426 }
427
428 private void createMySqlForm(final ICdmDataSource dataSource) {
429
430 // Create composite for db config as necessary
431 if (dbConfigComposite == null) {
432 dbConfigComposite = new Composite(editDatasourceComposite, SWT.NONE);
433 dbConfigComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
434 GridLayout formLayout = new GridLayout();
435 formLayout.numColumns = 2;
436 dbConfigComposite.setLayout(formLayout);
437 }
438
439 // Create group composite for authentication data
440 authenticationGroup = new Group(dbConfigComposite, SWT.NONE);
441 authenticationGroup.setText("Authentication");
442 authenticationGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
443 GridLayout authenticationLayout = new GridLayout();
444 authenticationLayout.numColumns = 2;
445 authenticationGroup.setLayout(authenticationLayout);
446
447 // Create database name label
448 Label databaseNameLabel = new Label(authenticationGroup, SWT.NONE);
449 databaseNameLabel.setText("Database Name:");
450
451 // Create database name input
452 databaseNameText = new Text(authenticationGroup, SWT.BORDER);
453 databaseNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
454
455 // Create username label
456 Label usernameLabel = new Label(authenticationGroup, SWT.NONE);
457 usernameLabel.setText("User Name:");
458
459 // Create username input
460 usernameText = new Text(authenticationGroup, SWT.BORDER);
461 usernameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
462
463 // Create password label
464 Label passwordLabel = new Label(authenticationGroup, SWT.NONE);
465 passwordLabel.setText("Password:");
466
467 // Create password input
468 passwordText = new Text(authenticationGroup, SWT.BORDER);
469 passwordText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
470
471 // // Create save password label
472 // Label savePasswordLabel = new Label(authenticationGroup, SWT.NONE);
473 // savePasswordLabel.setText("Save password:");
474 //
475 // // Create save password checkbox
476 // Button button = new Button(authenticationGroup, SWT.CHECK);
477
478 // Create group composite for location data
479 locationGroup = new Group(dbConfigComposite, SWT.NONE);
480 locationGroup.setText("Location");
481 locationGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
482 GridLayout locationLayout = new GridLayout();
483 locationLayout.numColumns = 2;
484 locationGroup.setLayout(locationLayout);
485
486 // Create host label
487 Label serverLabel = new Label(locationGroup, SWT.NONE);
488 serverLabel.setText("Host:");
489
490 // Create host input
491 serverText = new Text(locationGroup, SWT.BORDER);
492 serverText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
493
494 // Create port label
495 Label portLabel = new Label(locationGroup, SWT.NONE);
496 portLabel.setText("Port:");
497
498 // Create port input
499 portText = new Text(locationGroup, SWT.BORDER);
500 portText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
501
502 // Create composite for buttons
503 Composite buttonComposite = new Composite(dbConfigComposite, SWT.NONE);
504 buttonComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
505 GridLayout buttonLayout = new GridLayout();
506 buttonLayout.numColumns = 2;
507 buttonComposite.setLayout(buttonLayout);
508
509 // Create test connection button
510 Button testButton = new Button(buttonComposite, SWT.NONE);
511 testButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
512 testButton.setText("Test connection");
513
514 // Test connection when button is pressed
515 testButton.addMouseListener(new MouseAdapter() {
516 public void mouseUp(MouseEvent e) {
517 testDbConfig();
518 }
519 });
520
521 // Create save button
522 saveButton = new Button(buttonComposite, SWT.NONE);
523 GridData saveButtonLayout = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
524 saveButtonLayout.widthHint = 76;
525 saveButton.setLayoutData(saveButtonLayout);
526 saveButton.setText("Save");
527 saveButton.setEnabled(false);
528
529 // Save data to datasource on mouse click
530 saveButton.addMouseListener(new MouseAdapter() {
531 public void mouseUp(MouseEvent e) {
532 saveDbConfig();
533 }
534 });
535
536 // Populate fields with datasource data
537 if (dataSource != null) {
538 databaseNameText.setText(CdmUtils.Nz(dataSource.getDatabase()));
539 passwordText.setText(CdmUtils.Nz(dataSource.getPassword()));
540 usernameText.setText(CdmUtils.Nz(dataSource.getUsername()));
541 serverText.setText(CdmUtils.Nz(dataSource.getServer()));
542 portText.setText(String.valueOf(dataSource.getPort()));
543 }
544
545 // Listen for changes to any input fields in order to toggle Save / OK
546 databaseNameText.addModifyListener(modifyListener);
547 usernameText.addModifyListener(modifyListener);
548 passwordText.addModifyListener(modifyListener);
549 serverText.addModifyListener(modifyListener);
550 portText.addModifyListener(modifyListener);
551 forceUserToSave(false);
552
553 // Redraw
554 container.layout(true, true);
555 }
556
557 /**
558 * @param mustSave
559 */
560 private void forceUserToSave(boolean mustSave) {
561 saveButton.setEnabled(mustSave);
562 getButton(IDialogConstants.OK_ID).setEnabled(!mustSave);
563 }
564
565 private void testDbConfig() {
566
567 ICdmDataSource dataSource = CdmDataSource.NewMySqlInstance(
568 serverText.getText(),
569 databaseNameText.getText(),
570 getPort(),
571 usernameText.getText(),
572 passwordText.getText());
573 if (dataSource.testConnection()) {
574 MessageDialog.openConfirm(GlobalController.getShell(), "Test successful", "Test successful");
575 } else {
576 MessageDialog.openWarning(GlobalController.getShell(), "Test unsuccessful", "Test unsuccessful");
577 }
578 }
579
580 /**
581 * @return
582 */
583 private int getPort() {
584 try {
585 return Integer.valueOf(portText.getText());
586 } catch (NumberFormatException e) {
587 portText.setText("");
588 return -1;
589 }
590 }
591
592 private void saveDbConfig() {
593
594 // Get field values
595 DatabaseTypeEnum databaseType = databaseTypes.get(databaseTypeCombo.getSelectionIndex());
596 String dataSourceName = datasourceNameText.getText();
597 String server = serverText.getText();
598 String database = databaseNameText.getText();
599 String username = usernameText.getText();
600 String password = passwordText.getText();
601 Integer port = getPort(); // new Integer(portText.getText());
602
603 // Remove data source in case it already exists
604 if (dataSource != null) {
605 removeDataSource(dataSource);
606 }
607
608 if (port > 0) {
609 // Save with port
610 CdmDataSourceRepository.getDefault().save (
611 dataSourceName,
612 databaseType,
613 server,
614 database,
615 port,
616 username,
617 password);
618 } else {
619 // Save without port
620 CdmDataSourceRepository.getDefault().save (
621 dataSourceName,
622 databaseType,
623 server,
624 database,
625 username,
626 password);
627 }
628
629 // Refresh list of data sources to reflect changes
630 refreshDataSourceViewer();
631 forceUserToSave(false);
632 }
633
634 private void refreshDataSourceViewer() {
635
636 // Populate the list with saved datasources and an entry for "new dataSource"
637 dataSourceViewer.setInput(
638 CdmDataSourceRepository.getDefault().getAll());
639 }
640
641 public boolean close() {
642 return super.close();
643 }
644 }