package org.objectstyle.wolips.eomodeler.actions; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.objectstyle.wolips.baseforplugins.util.StringUtils; import org.objectstyle.wolips.baseforuiplugins.utils.ErrorUtils; import org.objectstyle.wolips.eomodeler.core.model.EODatabaseConfig; import org.objectstyle.wolips.eomodeler.core.model.EOModel; import org.objectstyle.wolips.eomodeler.core.model.IEOClassLoaderFactory; import org.objectstyle.wolips.eomodeler.core.sql.IEOSQLGenerator; import org.objectstyle.wolips.eomodeler.core.sql.IEOSQLGeneratorFactory; import org.objectstyle.wolips.eomodeler.core.utils.SQLUtils; public class GenerateSQLDialog extends Dialog { private Button _dropDatabaseButton; private Button _dropTablesButton; private Button _dropPrimaryKeySupportButton; private Button _dropIndexesButton; private Button _createSelectedEntitiesButton; private Button _createTablesButton; private Button _createPrimaryKeySupportButton; private Button _createPrimaryKeyConstraintsButton; private Button _createForeignKeyConstraintsButton; private Button _createDatabaseButton; private Button _createIndexesButton; private Button _runInEntityModelerButton; private Text _sqlText; private EOModel _model; private List<String> _entityNames; private Set<EODatabaseConfig> _databaseConfigs; private ComboViewer _databaseConfigComboViewer; private ClassLoader _eoModelClassLoader; private FlagChangedHandler _flagChangeHander; private boolean _cancel; private Cursor _waitCursor; private Button _executeSqlButton; private boolean _createOnlySelectedEntities; public GenerateSQLDialog(Shell parentShell, EOModel model, List<String> entityNames) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); _model = model; _entityNames = entityNames; _flagChangeHander = new FlagChangedHandler(); } protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText("SQL Generation"); } protected Control createDialogArea(Composite parent) { Composite control = (Composite) super.createDialogArea(parent); GridLayout layout = new GridLayout(1, true); layout.marginTop = 10; layout.marginLeft = 10; layout.marginRight = 10; layout.numColumns = 2; control.setLayout(layout); _databaseConfigs = _model.getDatabaseConfigs(); if (_databaseConfigs.size() > 1) { _databaseConfigComboViewer = new ComboViewer(control, SWT.READ_ONLY); GridData extraInfoData = new GridData(GridData.FILL_HORIZONTAL); extraInfoData.horizontalSpan = 2; _databaseConfigComboViewer.setContentProvider(new DatabaseConfigContentProvider()); _databaseConfigComboViewer.setLabelProvider(new DatabaseConfigLabelProvider()); _databaseConfigComboViewer.setInput(_databaseConfigs); _databaseConfigComboViewer.getCombo().setLayoutData(extraInfoData); EODatabaseConfig activeDatabaseConfig = _model.getActiveDatabaseConfig(); if (activeDatabaseConfig != null) { _databaseConfigComboViewer.setSelection(new StructuredSelection(activeDatabaseConfig)); } else { _databaseConfigComboViewer.setSelection(new StructuredSelection(_databaseConfigs.iterator().next())); } _databaseConfigComboViewer.addSelectionChangedListener(_flagChangeHander); } _dropDatabaseButton = new Button(control, SWT.CHECK); _dropDatabaseButton.setText("Drop Database"); _dropDatabaseButton.addSelectionListener(_flagChangeHander); _createDatabaseButton = new Button(control, SWT.CHECK); _createDatabaseButton.setText("Create Database"); _createDatabaseButton.addSelectionListener(_flagChangeHander); _dropTablesButton = new Button(control, SWT.CHECK); _dropTablesButton.setText("Drop Tables"); _dropTablesButton.setSelection(true); _dropTablesButton.addSelectionListener(_flagChangeHander); _createTablesButton = new Button(control, SWT.CHECK); _createTablesButton.setText("Create Tables"); _createTablesButton.setSelection(true); _createTablesButton.addSelectionListener(_flagChangeHander); _dropPrimaryKeySupportButton = new Button(control, SWT.CHECK); _dropPrimaryKeySupportButton.setText("Drop Primary Keys"); _dropPrimaryKeySupportButton.setSelection(true); _dropPrimaryKeySupportButton.addSelectionListener(_flagChangeHander); _createPrimaryKeySupportButton = new Button(control, SWT.CHECK); _createPrimaryKeySupportButton.setText("Create Primary Key Support"); _createPrimaryKeySupportButton.setSelection(true); _createPrimaryKeySupportButton.addSelectionListener(_flagChangeHander); _dropIndexesButton = new Button(control, SWT.CHECK); _dropIndexesButton.setText("Drop Indexes"); _dropIndexesButton.setSelection(true); _dropIndexesButton.addSelectionListener(_flagChangeHander); _createIndexesButton = new Button(control, SWT.CHECK); _createIndexesButton.setText("Create Indexes"); _createIndexesButton.setSelection(true); _createIndexesButton.addSelectionListener(_flagChangeHander); int entityCount = (_entityNames != null) ? _entityNames.size() : 0; _createSelectedEntitiesButton = new Button(control, SWT.CHECK); _createSelectedEntitiesButton.setText("Create Only Selected Entities"); _createSelectedEntitiesButton.setSelection(entityCount > 0); _createSelectedEntitiesButton.addSelectionListener(_flagChangeHander); _createSelectedEntitiesButton.setEnabled(entityCount > 0); _createOnlySelectedEntities = (entityCount > 0); _createPrimaryKeyConstraintsButton = new Button(control, SWT.CHECK); _createPrimaryKeyConstraintsButton.setText("Primary Key Constraints"); _createPrimaryKeyConstraintsButton.setSelection(true); _createPrimaryKeyConstraintsButton.addSelectionListener(_flagChangeHander); _runInEntityModelerButton = new Button(control, SWT.CHECK); _runInEntityModelerButton.setText("Single Transaction Compatible"); _runInEntityModelerButton.setSelection(true); _runInEntityModelerButton.addSelectionListener(_flagChangeHander); _createForeignKeyConstraintsButton = new Button(control, SWT.CHECK); _createForeignKeyConstraintsButton.setText("Foreign Key Constraints"); _createForeignKeyConstraintsButton.setSelection(true); _createForeignKeyConstraintsButton.addSelectionListener(_flagChangeHander); new Label(control, SWT.NONE); _sqlText = new Text(control, SWT.BORDER | SWT.MULTI | SWT.READ_ONLY | SWT.V_SCROLL); GridData sqlTextData = new GridData(GridData.FILL_BOTH); sqlTextData.heightHint = 300; sqlTextData.widthHint = 500; sqlTextData.verticalIndent = 10; sqlTextData.horizontalSpan = 2; _sqlText.setLayoutData(sqlTextData); _sqlText.setText("Generating SQL. Please Wait ..."); _waitCursor = new Cursor(getShell().getDisplay(), SWT.CURSOR_WAIT); generateSqlInThread(); return control; } public boolean close() { boolean close = super.close(); if (_waitCursor != null) { _waitCursor.dispose(); _waitCursor = null; } return close; } protected Control createButtonBar(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 3; layout.makeColumnsEqualWidth = true; layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); composite.setLayout(layout); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_CENTER); composite.setLayoutData(data); composite.setFont(parent.getFont()); Button closeButton = new Button(composite, SWT.PUSH); closeButton.setText("Close"); closeButton.addSelectionListener(new CloseHandler()); _executeSqlButton = new Button(composite, SWT.PUSH); _executeSqlButton.setText("Execute SQL"); _executeSqlButton.addSelectionListener(new ExecuteSqlHandler()); getShell().setDefaultButton(closeButton); return composite; } protected String yesNo(Button button) { return (button.getSelection()) ? "YES" : "NO"; } protected Text getSqlText() { return _sqlText; } protected EODatabaseConfig getSelectedDatabaseConfig() { EODatabaseConfig selectedDatabaseConfig = null; if (_databaseConfigComboViewer != null) { IStructuredSelection selection = (IStructuredSelection) _databaseConfigComboViewer.getSelection(); selectedDatabaseConfig = (EODatabaseConfig) selection.getFirstElement(); } else { selectedDatabaseConfig = _model.getActiveDatabaseConfig(); } return selectedDatabaseConfig; } protected ClassLoader getEOModelClassLoader() throws Exception { if (_eoModelClassLoader == null) { _eoModelClassLoader = IEOClassLoaderFactory.Utility.createClassLoader(_model); } return _eoModelClassLoader; } public void generateSqlInThread() { _createOnlySelectedEntities = _createSelectedEntitiesButton.getSelection(); final Map<String, String> flags = new HashMap<String, String>(); flags.put("dropTables", yesNo(_dropTablesButton)); flags.put("dropPrimaryKeySupport", yesNo(_dropPrimaryKeySupportButton)); flags.put("createTables", yesNo(_createTablesButton)); flags.put("createPrimaryKeySupport", yesNo(_createPrimaryKeySupportButton)); flags.put("primaryKeyConstraints", yesNo(_createPrimaryKeyConstraintsButton)); flags.put("foreignKeyConstraints", yesNo(_createForeignKeyConstraintsButton)); flags.put("createDatabase", yesNo(_createDatabaseButton)); flags.put("dropDatabase", yesNo(_dropDatabaseButton)); flags.put("createIndexes", yesNo(_createIndexesButton)); flags.put("dropIndexes", yesNo(_dropIndexesButton)); final EODatabaseConfig selectedDatabaseConfig = getSelectedDatabaseConfig(); final boolean runInEntityModeler = _runInEntityModelerButton.getSelection(); Thread generateSqlThread = new Thread(new Runnable() { public void run() { generateSql(flags, selectedDatabaseConfig, runInEntityModeler); } }, "Generate SQL"); generateSqlThread.start(); } protected Button getExecuteSqlButton() { return _executeSqlButton; } protected synchronized void generateSql(Map flags, EODatabaseConfig selectedDatabaseConfig, boolean runInEntityModeler) { try { Display.getDefault().syncExec(new Runnable() { public void run() { getShell().setCursor(getWaitCursor()); getExecuteSqlButton().setEnabled(false); } }); IEOSQLGenerator sqlGenerator = IEOSQLGeneratorFactory.Utility.sqlGeneratorFactory().sqlGenerator(_model, getEntityNames(), selectedDatabaseConfig, getEOModelClassLoader(), runInEntityModeler); final String sqlScript = sqlGenerator.generateSchemaCreationScript(flags); Display.getDefault().syncExec(new Runnable() { public void run() { getSqlText().setText(sqlScript); getExecuteSqlButton().setEnabled(true); } }); } catch (final Throwable t) { Display.getDefault().syncExec(new Runnable() { public void run() { getSqlText().setText("Generation Failed."); } }); ErrorUtils.openErrorDialog(getShell(), t); } finally { Display.getDefault().syncExec(new Runnable() { public void run() { getShell().setCursor(null); } }); } } protected String getSqlString() { return _sqlText.getText(); } public void executeSqlInThread() { _createOnlySelectedEntities = _createSelectedEntitiesButton.getSelection(); boolean confirmed = MessageDialog.openConfirm(getShell(), "Execute SQL", "Are you sure you want to execute this SQL?"); if (confirmed) { final String sqlString = getSqlString(); final EODatabaseConfig selectedDatabaseConfig = getSelectedDatabaseConfig(); final boolean runInEntityModeler = _runInEntityModelerButton.getSelection(); Thread executeSqlThread = new Thread(new Runnable() { public void run() { executeSql(sqlString, selectedDatabaseConfig, runInEntityModeler); } }, "Execute SQL"); executeSqlThread.start(); } } protected void setCancel(boolean cancel) { _cancel = cancel; } protected Cursor getWaitCursor() { return _waitCursor; } protected List<String> getEntityNames() { return (_createOnlySelectedEntities) ? _entityNames : null; } protected synchronized void executeSql(String allSql, EODatabaseConfig selectedDatabaseConfig, boolean runInEntityModeler) { try { Display.getDefault().syncExec(new Runnable() { public void run() { getShell().setCursor(getWaitCursor()); } }); IEOSQLGenerator sqlGenerator = IEOSQLGeneratorFactory.Utility.sqlGeneratorFactory().sqlGenerator(_model, getEntityNames(), selectedDatabaseConfig, getEOModelClassLoader(), runInEntityModeler); String url = selectedDatabaseConfig.getURL(); char commandSeparatorChar; // yes. This sucks. if (url != null && url.toLowerCase().contains("oracle")) { commandSeparatorChar = '/'; } else { commandSeparatorChar = ';'; } List<String> statements = SQLUtils.splitSQLStatements(allSql, commandSeparatorChar); setCancel(false); for (int statementsNum = 0; !_cancel && statementsNum < statements.size(); statementsNum++) { String statement = statements.get(statementsNum); statement = statement.trim().replaceAll("[\n\r]", " "); if (statement.length() > 0) { try { sqlGenerator.executeSQL(statement); } catch (final Throwable t) { Display.getDefault().syncExec(new Runnable() { public void run() { MessageDialog dialog = new MessageDialog(getShell(), "Error", null, StringUtils.getErrorMessage(t) + "\n\nThere was an error, do you want to cancel the rest of the script?", MessageDialog.QUESTION, new String[] { "Cancel", "Continue" }, 0); int results = dialog.open(); boolean cancel = (results == 0); setCancel(cancel); } }); } } } Display.getDefault().syncExec(new Runnable() { public void run() { MessageDialog.openInformation(getShell(), "Done", "SQL Execution Complete"); } }); } catch (final Throwable t) { ErrorUtils.openErrorDialog(getShell(), t); } finally { Display.getDefault().syncExec(new Runnable() { public void run() { getShell().setCursor(null); } }); } } public class FlagChangedHandler implements SelectionListener, ISelectionChangedListener { public void widgetDefaultSelected(SelectionEvent event) { widgetSelected(event); } public void widgetSelected(SelectionEvent event) { GenerateSQLDialog.this.generateSqlInThread(); } public void selectionChanged(SelectionChangedEvent event) { GenerateSQLDialog.this.generateSqlInThread(); } } public class ExecuteSqlHandler implements SelectionListener { public void widgetDefaultSelected(SelectionEvent event) { widgetSelected(event); } public void widgetSelected(SelectionEvent event) { GenerateSQLDialog.this.executeSqlInThread(); } } public class CloseHandler implements SelectionListener { public void widgetDefaultSelected(SelectionEvent event) { widgetSelected(event); } public void widgetSelected(SelectionEvent event) { GenerateSQLDialog.this.close(); } } public static class DatabaseConfigLabelProvider implements ILabelProvider { public void addListener(ILabelProviderListener listener) { // DO NOTHING } public void dispose() { // DO NOTHING } public Image getImage(Object element) { return null; } public String getText(Object element) { EODatabaseConfig config = (EODatabaseConfig) element; StringBuffer text = new StringBuffer(); text.append(config.getName()); text.append(" ("); text.append(config.getUsername()); text.append(" @ "); text.append(config.getURL()); text.append(")"); return text.toString(); } public boolean isLabelProperty(Object element, String property) { return true; } public void removeListener(ILabelProviderListener listener) { // DO NOTHING } } public static class DatabaseConfigContentProvider implements IStructuredContentProvider { public void dispose() { // DO NOTHING } public Object[] getElements(Object inputElement) { return ((Collection) inputElement).toArray(); } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // DO NOTHING } } }