Index: D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/views/DBTablesViewer.java =================================================================== --- D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/views/DBTablesViewer.java (revision 0) +++ D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/views/DBTablesViewer.java (revision 0) @@ -0,0 +1,302 @@ +/******************************************************************************* + * Copyright (c) 2007-2008 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributor: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.seam.ui.views; + +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.progress.WorkbenchJob; +import org.hibernate.HibernateException; +import org.hibernate.JDBCException; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.JDBCReaderFactory; +import org.hibernate.cfg.Settings; +import org.hibernate.cfg.reveng.dialect.MetaDataDialect; +import org.hibernate.console.ConsoleConfiguration; +import org.hibernate.console.ImageConstants; +import org.hibernate.console.execution.ExecutionContext; +import org.hibernate.eclipse.console.utils.EclipseImages; +import org.hibernate.mapping.Table; +import org.jboss.tools.seam.ui.internal.reveng.JDBCTablesColumnsReader; +import org.jboss.tools.seam.ui.internal.reveng.TablesColumnsCollector; + +/** + * Database tree viewer with three-level structure (till Tables) + * @author Dmitry Geraskov + */ +public class DBTablesViewer extends TreeViewer { + + private String connectionErrorMessage = "Couldn't connect to Database"; //$NON-NLS-1$ + + private Image catalog = EclipseImages.getImageDescriptor(ImageConstants.DATABASE).createImage(); + private Image schema = EclipseImages.getImageDescriptor(ImageConstants.SCHEMA).createImage(); + private Image table = EclipseImages.getImageDescriptor(ImageConstants.TABLE).createImage(); + + public class Element{ + private String name; + protected String defaultLabel; + + Element(String name){ + this.name = name; + } + + public String getName(){ + return name; + } + + public String getLabel(){ + return name == null ? defaultLabel : name; + } + } + + public class Catalog extends Element{ + + public static final String DEF_CATALOG_NAME = ""; //$NON-NLS-1$ + + Catalog(String name){ + super(name); + defaultLabel = DEF_CATALOG_NAME; + } + } + + public class Schema extends Element{ + + public static final String DEF_SCHEMA_NAME = ""; //$NON-NLS-1$ + + private Catalog parent; + + Schema(String name, Catalog parent){ + super(name); + this.parent = parent; + defaultLabel = DEF_SCHEMA_NAME; + } + + public Catalog getParent(){ + return parent; + } + } + + public DBTablesViewer(Tree tree){ + super(tree); + setContentProvider(createContentProvider()); + setLabelProvider(createLabelProvider()); + } + + public DBTablesViewer(Composite parent) { + super(parent); + + } + + /** + * @return ITreeContentProvider + */ + protected ITreeContentProvider createContentProvider() { + return new ITreeContentProvider(){ + + private Configuration cfg = null; + + private Settings buildSettings = null; + + private String placeHolder = "Pending..."; //$NON-NLS-1$ + + private String conErrorItem = '<' + connectionErrorMessage + '>'; + + private final Object[] NO_CHILDREN = new Object[0]; + + private static final int BEGIN_STATE = 0; + + private static final int CHILDREN_FETCHED = 1; + + private static final int CONNECTION_ERROR = 2; + + private static final int LOADING_IN_PROGRESS = 3; + + private int connectionState = BEGIN_STATE; + + private TablesColumnsCollector tablesCollector; + + private Object[] getCatalogs(){ + if (connectionState == LOADING_IN_PROGRESS){ + return new String[]{placeHolder}; + } + if (connectionState == CONNECTION_ERROR){ + return new String[]{connectionErrorMessage}; + } + List catalogNames = tablesCollector.getCatalogNames(); + Element[] catalogs = new Element[catalogNames.size()]; + for (int i = 0; i < catalogs.length; i++) { + String catalogName = (String) catalogNames.get(i); + if (catalogName == null || "".equals(catalogName)) catalogName = null; //$NON-NLS-1$ + catalogs[i] = new Catalog(catalogName); + + } + return catalogs; + } + + private Object[] getSchemas(Catalog catalog){ + List schemaNames = tablesCollector.getMatchingSchemaNames(catalog.getName(), buildSettings.getDefaultSchemaName()); + Element[] schemas = new Element[schemaNames.size()]; + for (int i = 0; i < schemaNames.size(); i++) { + String schemaName = (String) schemaNames.get(i); + if (schemaName == null || "".equals(schemaName)) schemaName = null; //$NON-NLS-1$ + schemas[i] = new Schema( schemaName, catalog); + } + return schemas; + } + + private Object[] getTables(Schema schema){ + List tableNames = tablesCollector.getMatchingTablesNames(schema.getParent().getName(), schema.getName(), ""); //$NON-NLS-1$ + Table[] tables = new Table[tableNames.size()]; + for (int i = 0; i < tables.length; i++) { + tables[i] = new Table((String) tableNames.get(i)); + tables[i].setCatalog(schema.getParent().getName()); + tables[i].setSchema(schema.getName()); + } + return tables; + } + + public Object[] getChildren(Object parent) { + if (parent instanceof Catalog) { + return getSchemas((Catalog)parent); + } + if (parent instanceof Schema) { + Schema schema = (Schema)parent; + return getTables(schema); + } + return NO_CHILDREN; + } + + public Object getParent(Object element) { + if (element instanceof Schema){ + return ((Schema)element).getParent(); + } + return null; + } + + public boolean hasChildren(Object parent) { + return parent instanceof Element; + } + + public Object[] getElements(Object inputElement) { + if (buildSettings == null) return new String[]{conErrorItem}; + + if (connectionState == BEGIN_STATE){ + tablesCollector = new TablesColumnsCollector(true); + if (connectionState == BEGIN_STATE) + connectionState = LOADING_IN_PROGRESS; + WorkbenchJob job = new WorkbenchJob("Fetching database structure") { //$NON-NLS-1$ + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + try{ + MetaDataDialect realMetaData = JDBCReaderFactory.newMetaDataDialect(buildSettings + .getDialect(), cfg.getProperties()); + + JDBCTablesColumnsReader reader = new JDBCTablesColumnsReader(realMetaData, + buildSettings.getConnectionProvider(), buildSettings.getSQLExceptionConverter()); + reader.readDatabaseTables(tablesCollector, buildSettings.getDefaultCatalogName(), buildSettings.getDefaultSchemaName()); + + connectionState = CHILDREN_FETCHED; + } catch (JDBCException e){ + connectionState = CONNECTION_ERROR; + } + DBTablesViewer.this.remove(placeHolder); + DBTablesViewer.this.refresh(); + return Status.OK_STATUS; + }}; + job.schedule(); + } + return getCatalogs(); + } + + public void dispose() {} + + /** + * Supported input types are: + * org.hibernate.console.ConsoleConfiguration, + * org.hibernate.cfg.Settings. + */ + public void inputChanged(Viewer viewer, Object oldInput, + Object newInput) { + if (newInput == oldInput + && connectionState != CONNECTION_ERROR) return; + + if (newInput instanceof ConsoleConfiguration) { + ConsoleConfiguration cc = (ConsoleConfiguration) newInput; + try{ + cc.build(); + cfg = cc.getConfiguration(); + cc.getExecutionContext().execute(new ExecutionContext.Command() { + public Object execute() { + Settings newSettings = cfg.buildSettings(); + if (!newSettings.equals(buildSettings)){ + buildSettings = newSettings; + connectionState = BEGIN_STATE; + } + return null; + }}); + } catch (HibernateException e){ + connectionState = CONNECTION_ERROR; + } + } + } + }; + } + + protected LabelProvider createLabelProvider(){ + return new LabelProvider(){ + + @Override + public void dispose() { + catalog.dispose(); + schema.dispose(); + table.dispose(); + } + + @Override + public Image getImage(Object element) { + if (element instanceof Catalog){ + return catalog; + } + if (element instanceof Schema){ + return schema; + } + if (element instanceof Table){ + return table; + } + return null; + } + + @Override + public String getText(Object element) { + if (element instanceof Element){ + return ((Element)element).getLabel(); + } + if (element instanceof Table){ + return ((Table)element).getName(); + } + return super.getText(element); + } + }; + } + + public void setConnectionErrorMessage(String connectionErrorMessage) { + this.connectionErrorMessage = connectionErrorMessage; + } +} Property changes on: D:\workspaces\RedHat\org.jboss.tools.seam.ui\src\org\jboss\tools\seam\ui\views\DBTablesViewer.java ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Id Revision Date Name: svn:eol-style + native Index: D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/views/DBTableFilterView.java =================================================================== --- D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/views/DBTableFilterView.java (revision 0) +++ D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/views/DBTableFilterView.java (revision 0) @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2007-2008 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributor: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.seam.ui.views; + +import java.util.Iterator; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.widgets.Composite; +import org.hibernate.console.ConsoleConfiguration; +import org.hibernate.console.KnownConfigurations; +import org.hibernate.eclipse.console.model.ITableFilter; +import org.hibernate.eclipse.console.wizards.TableFilterView; +import org.hibernate.mapping.Table; +import org.hibernate.util.StringHelper; +import org.jboss.tools.seam.ui.views.DBTablesViewer.Catalog; +import org.jboss.tools.seam.ui.views.DBTablesViewer.Schema; + +/** + * @author Dmitry Geraskov + * + */ +public abstract class DBTableFilterView extends TableFilterView { + + private DBTablesViewer viewer; + + public DBTableFilterView(Composite parent, int style) { + super( parent, style ); + } + + @Override + protected TreeViewer createTreeViewer() { + if (viewer == null){ + viewer = new DBTablesViewer( tree ); + } + return viewer; + } + + @Override + protected void doRefreshTree() { + ConsoleConfiguration configuration = KnownConfigurations.getInstance() + .find( getConsoleConfigurationName() ); + + if(configuration!=null) { + viewer.setInput( configuration ); + } + } + + @Override + protected void toggle(boolean exclude) { + ISelection selection = viewer.getSelection(); + + if ( !selection.isEmpty() ) { + StructuredSelection ss = (StructuredSelection) selection; + Iterator iterator = ss.iterator(); + while ( iterator.hasNext() ) { + Object sel = iterator.next(); + ITableFilter filter = null; + + if ( sel instanceof Table ) { + Table table = (Table) sel; + filter = revEngDef.createTableFilter(); + if ( StringHelper.isNotEmpty( table.getName() ) ) { + filter.setMatchName( table.getName() ); + } + if ( StringHelper.isNotEmpty( table.getCatalog() ) ) { + filter.setMatchCatalog( table.getCatalog() ); + } + if ( StringHelper.isNotEmpty( table.getSchema() ) ) { + filter.setMatchSchema( table.getSchema() ); + } + filter.setExclude( Boolean.valueOf( exclude ) ); + } else if ( sel instanceof Schema ) { // assume its a schema! + Schema tc = (Schema) sel; + filter = revEngDef.createTableFilter(); + String schema = tc.getName(); + String catalog = tc.getParent().getName(); + if(StringHelper.isNotEmpty(schema)) { + filter.setMatchSchema(schema); + } + if(StringHelper.isNotEmpty(catalog)) { + filter.setMatchCatalog(catalog); + } + filter.setExclude( Boolean.valueOf( exclude ) ); + } else if ( sel instanceof Catalog ) { // assume its a catalog! + Catalog tc = (Catalog) sel; + filter = revEngDef.createTableFilter(); + if(StringHelper.isNotEmpty(tc.getName())) { + filter.setMatchCatalog(tc.getName()); + } + filter.setExclude( Boolean.valueOf( exclude ) ); + } + if ( filter != null ) + revEngDef.addTableFilter( filter ); + } + } else { + ITableFilter filter = revEngDef.createTableFilter(); + filter.setExclude( Boolean.valueOf( exclude ) ); + revEngDef.addTableFilter( filter ); + } + } + +} Property changes on: D:\workspaces\RedHat\org.jboss.tools.seam.ui\src\org\jboss\tools\seam\ui\views\DBTableFilterView.java ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Id Revision Date Name: svn:eol-style + native Index: D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/wizard/SeamGenerateEnitiesWizardPage.java =================================================================== --- D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/wizard/SeamGenerateEnitiesWizardPage.java (revision 7463) +++ D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/wizard/SeamGenerateEnitiesWizardPage.java (working copy) @@ -14,6 +14,7 @@ import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.core.resources.IProject; @@ -21,6 +22,7 @@ import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; @@ -60,7 +62,6 @@ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ public void createControl(Composite parent) { - setPageComplete(true); rootSeamProject = SeamWizardUtils.getCurrentSelectedRootSeamProject(); String projectName = rootSeamProject==null?"":rootSeamProject.getName(); projectEditor = SeamWizardFactory.createSeamProjectSelectionFieldEditor(projectName); @@ -231,8 +232,23 @@ values.put(configEditor.getName(), configEditor.getValueAsString()); String mode = radios.getValue().toString(); values.put(HibernateLaunchConstants.ATTR_REVERSE_ENGINEER, ("reverse".equals(mode) ? "true" : "false")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + IWizardPage page2 = getWizard().getPage(SeamGenerateEntitiesTablesWizardPage.pageName); + if (page2 instanceof SeamGenerateEntitiesTablesWizardPage){ + SeamGenerateEntitiesTablesWizardPage page = (SeamGenerateEntitiesTablesWizardPage)page2; + String filters = page.getFilters(); + if (filters.length() > 0) values.put(HibernateLaunchConstants.ATTR_REVENG_TABLES, filters); + } return values; } return null; } + + @Override + public boolean canFlipToNextPage() { + return "reverse".equals(radios.getValue()) && (getErrorMessage() == null); //$NON-NLS-1$ + } + + public String getConsoleCongigurationName(){ + return configEditor.getValueAsString(); + } } \ No newline at end of file Index: D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/wizard/SeamGenerateEnitiesWizard.java =================================================================== --- D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/wizard/SeamGenerateEnitiesWizard.java (revision 7463) +++ D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/wizard/SeamGenerateEnitiesWizard.java (working copy) @@ -30,6 +30,7 @@ import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.INewWizard; import org.eclipse.ui.PlatformUI; @@ -51,6 +52,9 @@ */ public class SeamGenerateEnitiesWizard extends SeamBaseWizard implements INewWizard { + IWizardPage page1 = new SeamGenerateEnitiesWizardPage(); + IWizardPage page2 = new SeamGenerateEntitiesTablesWizardPage(); + public void createPageControls(Composite pageContainer) { super.createPageControls(pageContainer); PlatformUI.getWorkbench().getHelpSystem().setHelp(pageContainer, ISeamHelpContextIds.GENERATE_SEAM_ENTITIES); @@ -59,10 +63,16 @@ public SeamGenerateEnitiesWizard() { super(GENERATE_SEAM_ENTITIES); setWindowTitle(SeamUIMessages.GENERATE_SEAM_ENTITIES_WIZARD_TITLE); - setDefaultPageImageDescriptor(ImageDescriptor.createFromFile(SeamGenerateEnitiesWizard.class, "SeamWebProjectWizBan.png")); - addPage(new SeamGenerateEnitiesWizardPage()); + setDefaultPageImageDescriptor(ImageDescriptor.createFromFile(SeamGenerateEnitiesWizard.class, "SeamWebProjectWizBan.png")); + addPage(page1); + addPage(page2); } - + + @Override + public boolean canFinish() { + return page1.isPageComplete(); + } + public static final IUndoableOperation GENERATE_SEAM_ENTITIES = new SeamBaseOperation(SeamUIMessages.SEAM_GENERATE_ENTITIES_WIZARD_ACTION_CREATING_OPERATION) { /* @@ -302,7 +312,14 @@ hbmtemplateAttributes.put("for_each", "entity"); //$NON-NLS-1$ //$NON-NLS-2$ hbmtemplateAttributes.put("hibernatetool.util.toolclass","org.hibernate.eclipse.launch.SeamUtil"); //$NON-NLS-1$ //$NON-NLS-2$ wc.setAttribute(HibernateLaunchConstants.ATTR_EXPORTERS + ".hbmtemplate9.properties", hbmtemplateAttributes); //$NON-NLS-1$ + + //save before adding additional attribute wc.doSave(); + + if (params.containsKey(HibernateLaunchConstants.ATTR_REVENG_TABLES)){ + wc.setAttribute(HibernateLaunchConstants.ATTR_REVENG_TABLES, params.get(HibernateLaunchConstants.ATTR_REVENG_TABLES)); + } + launchManager.addLaunch(wc.launch(ILaunchManager.RUN_MODE, monitor)); WebUtils.changeTimeStamp(project); Index: D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/wizard/SeamGenerateEntitiesTablesWizardPage.java =================================================================== --- D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/wizard/SeamGenerateEntitiesTablesWizardPage.java (revision 0) +++ D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/wizard/SeamGenerateEntitiesTablesWizardPage.java (revision 0) @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2007-2008 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributor: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.seam.ui.wizard; + +import org.eclipse.jface.dialogs.IPageChangedListener; +import org.eclipse.jface.dialogs.PageChangedEvent; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.hibernate.eclipse.console.model.IReverseEngineeringDefinition; +import org.hibernate.eclipse.console.model.ITableFilter; +import org.hibernate.eclipse.console.model.impl.ReverseEngineeringDefinitionImpl; +import org.jboss.tools.seam.ui.SeamUIMessages; +import org.jboss.tools.seam.ui.views.DBTableFilterView; + +/** + * The page for selection table filters. + * @author Dmitry Geraskov + */ +public class SeamGenerateEntitiesTablesWizardPage extends WizardPage /*implements ISelectionChangedListener*/ { + + public static final String pageName = "seam.generate.entities.tablesPage"; //$NON-NLS-1$ + + private String cfgName; + + private IReverseEngineeringDefinition model; + + public SeamGenerateEntitiesTablesWizardPage() { + super(pageName, SeamUIMessages.GENERATE_SEAM_ENTITIES_WIZARD_TITLE, null); + setMessage("Select Tables"); //$NON-NLS-1$ + } + + public void createControl(Composite parent) { + setPageComplete(true); + Composite top = new Composite(parent, SWT.NONE); + top.setLayout(new FillLayout()); + final DBTableFilterView tfView = new DBTableFilterView(top, SWT.NONE){ + + @Override + protected String getConsoleConfigurationName() { + return cfgName; + } + }; + + model = new ReverseEngineeringDefinitionImpl(); + + tfView.setModel(model); + + if (getWizard().getContainer() instanceof WizardDialog){ + WizardDialog wd = (WizardDialog) getWizard().getContainer(); + wd.addPageChangedListener(new IPageChangedListener(){ + + //set console configuration as treeViewer input + public void pageChanged(PageChangedEvent event) { + if (event.getSelectedPage() == SeamGenerateEntitiesTablesWizardPage.this){ + SeamGenerateEnitiesWizardPage page1 = (SeamGenerateEnitiesWizardPage)getWizard().getPreviousPage(SeamGenerateEntitiesTablesWizardPage.this); + cfgName = page1.getConsoleCongigurationName(); + } + }}); + } + setControl(top); + } + + /* + * Get filters founded on the selected tables + */ + public String getFilters() { + StringBuilder builder = new StringBuilder(); + if (model != null){ + ITableFilter[] filters = model.getTableFilters(); + if (filters.length == 0) return builder.toString(); + builder.append("\r\n")//$NON-NLS-1$ + .append("\r\n")//$NON-NLS-1$ + .append("\r\n")//$NON-NLS-1$ + .append("\r\n");//$NON-NLS-1$ + for (ITableFilter element : filters) { + builder.append(generateStringForFilter(element)); + } + builder.append("\r\n"); //$NON-NLS-1$ + } + return builder.toString(); + } + + private String generateStringForFilter(ITableFilter filter){ + String filterStr = " 1 && columnName.charAt(0) == '`' + && columnName.charAt(columnName.length() - 1) == '`') { + return columnName; // avoid double quoting + } + return "`" + columnName + "`"; + } + + private void collectTables(TablesColumnsCollector tcc, String catalog, String schema) { + Iterator tableIterator = null; + try { + String tablesMask = null; + tableIterator = metadataDialect.getTables(StringHelper.replace(catalog, ".*", "%"), + StringHelper.replace(schema, ".*", "%"), StringHelper.replace(tablesMask, ".*", + "%")); + while (tableIterator.hasNext()) { + Map tableRs = (Map) tableIterator.next(); + String catalogName = (String) tableRs.get("TABLE_CAT"); +/* + * commented by Dmitry Geraskov to prevent showing catalog name if + * db provider can't found it + * otherwise we'll set it and filter out all tables when will run code generation + * if (null == catalogName) { + * // simple workaround if db provider do not find resources + * // to return right catalog name here + * catalogName = currentCatalog; + * } + */ + String schemaName = (String) tableRs.get("TABLE_SCHEM"); + String tableName = (String) tableRs.get("TABLE_NAME"); + //String comment = (String) tableRs.get("REMARKS"); + String tableType = (String) tableRs.get("TABLE_TYPE"); + if (("TABLE".equals(tableType) || "VIEW".equals(tableType))) { + log.debug("Adding table " + tableName + " of type " + tableType); + tcc.addTableName(catalogName, schemaName, quote(tableName)); + } else { + log.debug("Ignoring table " + tableName + " of type " + tableType); + } + } + } finally { + try { + if (null != tableIterator) { + metadataDialect.close(tableIterator); + } + } catch (Exception ignore) { + } + } + } + + public void readDatabaseTables(TablesColumnsCollector tcc, String catalog, String schema) { + try { + ReverseEngineeringRuntimeInfo info = ReverseEngineeringRuntimeInfo.createInstance(provider, sec, + null); + metadataDialect.configure(info); + tcc.init(); + initCurrentCatalog(info); + collectTables(tcc, catalog, schema); + tcc.adjust(); + } finally { + metadataDialect.close(); + } + } + + private void collectColumns(TablesColumnsCollector tcc, String catalog, String schema) { + Iterator columnIterator = null; + try { + String tablesMask = null; + String columnsMask = null; + columnIterator = metadataDialect.getColumns(StringHelper.replace(catalog, ".*", "%"), + StringHelper.replace(schema, ".*", "%"), StringHelper.replace(tablesMask, ".*", + "%"), StringHelper.replace(columnsMask, ".*", "%")); + while (columnIterator.hasNext()) { + Map columnRs = (Map) columnIterator.next(); + String catalogName = (String) columnRs.get("TABLE_CAT"); + if (null == catalogName) { + // simple workaround if db provider do not find resources + // to return right catalog name here + catalogName = currentCatalog; + } + String schemaName = (String) columnRs.get("TABLE_SCHEM"); + String tableName = (String) columnRs.get("TABLE_NAME"); + String columnName = (String) columnRs.get("COLUMN_NAME"); + //String dataType = (String) tableRs.get("DATA_TYPE"); + log.debug("Adding column " + tableName + "." + columnName); + tcc.addColumnName(catalogName, schemaName, quote(tableName), columnName); + } + } finally { + try { + if (null != columnIterator) { + metadataDialect.close(columnIterator); + } + } catch (Exception ignore) { + } + } + } + + public void readDatabaseColumns(TablesColumnsCollector tcc, String catalog, String schema) { + try { + ReverseEngineeringRuntimeInfo info = ReverseEngineeringRuntimeInfo.createInstance(provider, sec, + null); + metadataDialect.configure(info); + tcc.init(); + initCurrentCatalog(info); + collectColumns(tcc, catalog, schema); + tcc.adjust(); + } finally { + metadataDialect.close(); + } + } + + public void readDatabaseTablesColumns(TablesColumnsCollector tcc, String catalog, String schema) { + try { + ReverseEngineeringRuntimeInfo info = ReverseEngineeringRuntimeInfo.createInstance(provider, sec, + null); + metadataDialect.configure(info); + tcc.init(); + initCurrentCatalog(info); + collectTables(tcc, catalog, schema); + collectColumns(tcc, catalog, schema); + tcc.adjust(); + } finally { + metadataDialect.close(); + } + } + + /** + * init current catalog name + **/ + private void initCurrentCatalog(ReverseEngineeringRuntimeInfo info) { + currentCatalog = null; + try { + currentCatalog = info.getConnectionProvider().getConnection().getCatalog(); + } catch (SQLException ignore) { + } + } +} Property changes on: D:\workspaces\RedHat\org.jboss.tools.seam.ui\src\org\jboss\tools\seam\ui\internal\reveng\JDBCTablesColumnsReader.java ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Id Revision Date Name: svn:eol-style + native Index: D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/internal/reveng/TablesColumnsCollector.java =================================================================== --- D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/internal/reveng/TablesColumnsCollector.java (revision 0) +++ D:/workspaces/RedHat/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/internal/reveng/TablesColumnsCollector.java (revision 0) @@ -0,0 +1,586 @@ +/******************************************************************************* + * Copyright (c) 2008 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.seam.ui.internal.reveng; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * @author Vitali + * + * This is specific efficient storage for names of catalogs, schemas, tables, columns and + * it's relations. + */ +public class TablesColumnsCollector { + + // filter for lower part of long + public static final long LOWER_MASK = 0x00000000FFFFFFFFL; + // filter for upper part of long + public static final long UPPER_MASK = 0xFFFFFFFF00000000L; + + // if true - collect full exact hierarchical structure - full structure info with redundancy + // ---------- (useful to get the tree structure easily) + // ---------- all relations one-to-many + // if false - result structure has no duplicate strings - structure without redundancy + // ---------- (useful for context help) + // ---------- all relations many-to-many + protected boolean fullStructure = false; + // sorted in alphabetic order list of catalogs + protected List catalogs; + // sorted in alphabetic order list of schemas + protected List schemas; + // sorted in alphabetic order list of tables + protected List tables; + // sorted in alphabetic order list of columns + protected List columns; + + /** + * Index relation array-maps. + * Maps which are used to save relations between items in both directions. + * Here is a short description: + * left <-> right; + * left - could be catalogs, schemas, tables; + * right - could be schemas, tables, columns; + * xMap[i] & UPPER_MASK -> this is index in left array; + * xMap[i] & LOWER_MASK -> this is index in right array + **/ + // catalogs <-> schemas index map + protected long[] csMap; + // schemas <-> tables index map + protected long[] stMap; + // tables <-> columns index map + protected long[] tcMap; + + // temporary structures + protected List tempCATList; + protected List tempCSTList; + protected List tempTblList; + protected List tempClnList; + // simple protection of duplicates + protected String strCAT; + protected String strCST; + protected String strTbl; + protected String strCln; + + public TablesColumnsCollector() { + } + + /** + * @param fullStructure + * if true - collect full exact hierarchical structure - (useful to get the tree structure easily) + * if false - result structure has no duplicate strings - (useful for context help) + */ + public TablesColumnsCollector(boolean fullStructure) { + this.fullStructure = fullStructure; + } + + /** + * initialize collection + */ + public void init() { + catalogs = null; + schemas = null; + tables = null; + columns = null; + csMap = null; + stMap = null; + tcMap = null; + tempCATList = new ArrayList(); + tempCSTList = new ArrayList(); + tempTblList = new ArrayList(); + tempClnList = new ArrayList(); + strCAT = "%%%%"; + strCST = "%%%%"; + strTbl = "%%%%"; + strCln = "%%%%"; + } + + public String updateNullValue(String str) { + if (null == str) { + return ""; + } + return str; + } + + public void addCatalogName(String catalogName) { + catalogName = updateNullValue(catalogName); + String strCurr = "" + catalogName; + if (!strCAT.equalsIgnoreCase(strCurr)) { + tempCATList.add(strCurr); + strCAT = strCurr; + } + } + + public void addSchemaName(String catalogName, String schemaName) { + catalogName = updateNullValue(catalogName); + schemaName = updateNullValue(schemaName); + addCatalogName(catalogName); + String strCurr = schemaName + "%" + catalogName; + if (!strCST.equalsIgnoreCase(strCurr)) { + tempCSTList.add(strCurr); + strCST = strCurr; + } + } + + public void addTableName(String catalogName, String schemaName, String tableName) { + catalogName = updateNullValue(catalogName); + schemaName = updateNullValue(schemaName); + tableName = updateNullValue(tableName); + addSchemaName(catalogName, schemaName); + String strCurr = fullStructure ? + tableName + "%" + schemaName + "%" + catalogName : + tableName + "%" + schemaName; + if (!strTbl.equalsIgnoreCase(strCurr)) { + tempTblList.add(strCurr); + strTbl = strCurr; + } + } + + public void addColumnName(String catalogName, String schemaName, String tableName, String columnName) { + catalogName = updateNullValue(catalogName); + schemaName = updateNullValue(schemaName); + tableName = updateNullValue(tableName); + columnName = updateNullValue(columnName); + addTableName(catalogName, schemaName, tableName); + String strCurr = fullStructure ? + columnName + "%" + tableName + "%" + schemaName + "%" + catalogName : + columnName + "%" + tableName; + if (!strCln.equalsIgnoreCase(strCurr)) { + tempClnList.add(strCurr); + strCln = strCurr; + } + } + + protected void copyWithoutDuplicates(List arrTmp, List formList) { + String strPrev = null, strCurr = null; + for (int i = 0; i < arrTmp.size(); i++) { + strCurr = (String)arrTmp.get(i); + if (strPrev == strCurr) { + continue; + } + if (null != strPrev && strPrev.equalsIgnoreCase(strCurr)) { + continue; + } + strPrev = strCurr; + formList.add(strCurr); + } + } + + protected void copyIncludeDuplicates(List arrTmp, List formList) { + for (int i = 0; i < arrTmp.size(); i++) { + String strCurr = (String)arrTmp.get(i); + formList.add(strCurr); + } + } + + /** + * @param tempList - relation description list (with duplicates) + * @param formList + * @return + * size of tempList without duplicates + * in case of fullStructure: tempList.size() == formList.size() & tempList <-> formList by elements + */ + protected int adjustList(List tempList, List formList) { + ArrayList arrTmp = new ArrayList(); + Collections.sort(tempList, String.CASE_INSENSITIVE_ORDER); + String strPrev = null, strCurr = null; + int i, j; + // remove duplicates + for (i = 0, j = 0; i < tempList.size(); i++) { + strCurr = (String)tempList.get(i); + if (strPrev == strCurr) { + continue; + } + if (null != strPrev && strPrev.equalsIgnoreCase(strCurr)) { + continue; + } + strPrev = strCurr; + String[] atc = strCurr.split("%", 2); + tempList.set(j++, strCurr); + arrTmp.add(fullStructure ? strCurr : atc[0]); + } + if (fullStructure) { + copyIncludeDuplicates(arrTmp, formList); + } + else { + Collections.sort(arrTmp, String.CASE_INSENSITIVE_ORDER); + copyWithoutDuplicates(arrTmp, formList); + } + arrTmp = null; + return j; + } + + protected void adjustMap(long[] xMap, List tempList, List formList0, List formList1) { + // in case of fullStructure: + // tempList.size() == formList0.size() & + // tempList <-> formList0 by elements + int i, j = xMap.length; + for (i = 0; i < j; i++) { + String strCurr = (String)tempList.get(i); + String[] atc = strCurr.split("%", 2); + String tmp = atc[1]; + int keyT = Collections.binarySearch(formList1, tmp, String.CASE_INSENSITIVE_ORDER); + if (keyT < 0 || keyT >= formList1.size() || !tmp.equalsIgnoreCase((String)formList1.get(keyT))) { + keyT = Integer.MAX_VALUE; + } + tmp = atc[0]; + int keyC = fullStructure ? + i : Collections.binarySearch(formList0, tmp, String.CASE_INSENSITIVE_ORDER); + tmp = fullStructure ? strCurr : tmp; + if (keyC < 0 || keyC >= formList0.size() || !tmp.equalsIgnoreCase((String)formList0.get(keyC))) { + keyC = Integer.MAX_VALUE; + } + xMap[i] = ( ((long)keyT) << 32 ) | ((long)keyC); + } + Arrays.sort(xMap); + } + + /** + * adjust collected results + */ + public void adjust() { + strCAT = null; + strCST = null; + strTbl = null; + strCln = null; + int size; + catalogs = new ArrayList(); + if (null != tempCATList) { + Collections.sort(tempCATList, String.CASE_INSENSITIVE_ORDER); + copyWithoutDuplicates(tempCATList, catalogs); + tempCATList = null; + } + schemas = new ArrayList(); + csMap = new long[0]; + if (null != tempCSTList) { + size = adjustList(tempCSTList, schemas); + csMap = new long[size]; + adjustMap(csMap, tempCSTList, schemas, catalogs); + tempCSTList = null; + } + tables = new ArrayList(); + stMap = new long[0]; + if (null != tempTblList) { + size = adjustList(tempTblList, tables); + stMap = new long[size]; + adjustMap(stMap, tempTblList, tables, schemas); + tempTblList = null; + } + columns = new ArrayList(); + tcMap = new long[0]; + if (null != tempClnList) { + size = adjustList(tempClnList, columns); + tcMap = new long[size]; + adjustMap(tcMap, tempClnList, columns, tables); + tempClnList = null; + } + } + + public static final class Bounds { + public int nL = 0; + public int nH = 0; + } + + /** + * binaryBoundsSearch is a method to find lower and upper bounds + * in sorted array of strings for some string prefix. + * @param list - search array of strings (should be sorted in ascending case insensitive order); + * @param prefix - matching prefix; + * @param bounds - result interval in the list - all items in interval start from prefix. + * bounds.nL <= interval < bounds.nH + */ + public static final Bounds binaryBoundsSearch(List list, String prefix) { + Bounds bounds = new Bounds(); + if (0 == list.size()) { + bounds.nL = bounds.nH = 0; + return bounds; + } + prefix = prefix.toUpperCase(); + int low = 0; + int high = list.size() - 1; + int mid = (low + high) >> 1; + // looking for mid - some element in the interval, + // which is matched for criteria (has the prefix) + while (low <= high) { + mid = (low + high) >> 1; + String midVal = ((String)list.get(mid)).toUpperCase(); + int cmp = midVal.compareToIgnoreCase(prefix); + cmp = midVal.startsWith(prefix) ? 0 : cmp; + if (cmp < 0) { + low = mid + 1; + } + else if (cmp > 0) { + high = mid - 1; + } + else { + break; + } + } + int low2 = mid; + int high2 = mid; + // looking for low bound - indicates minimal index of element in the interval, + // which is matched for criteria (has the prefix) + while (low <= high2) { + mid = (low + high2) >> 1; + String midVal = ((String)list.get(mid)).toUpperCase(); + int cmp = midVal.compareToIgnoreCase(prefix); + cmp = midVal.startsWith(prefix) ? 0 : cmp; + if (cmp < 0) { + low = mid + 1; + } + else if (cmp >= 0) { + high2 = mid - 1; + } + } + // looking for high bound - indicates maximal index of element in the interval, + // which is matched for criteria (has the prefix) + while (low2 <= high) { + mid = (low2 + high) >> 1; + String midVal = ((String)list.get(mid)).toUpperCase(); + int cmp = midVal.compareToIgnoreCase(prefix); + cmp = midVal.startsWith(prefix) ? 0 : cmp; + if (cmp <= 0) { + low2 = mid + 1; + } + else if (cmp > 0) { + high = mid - 1; + } + } + // adjust low bound + if (low < list.size()) { + while (0 <= low && ((String)list.get(low)).toUpperCase().startsWith(prefix)) { + low--; + } + low++; + } + if (high < low) { + high = low; + } + // adjust high bound + while (high < list.size() && ((String)list.get(high)).toUpperCase().startsWith(prefix)) { + high++; + } + bounds.nL = low; + bounds.nH = high; + return bounds; + } + + + /** + * Clear string from redundant information. + * @param res + */ + protected String correctName(String input) { + if (!fullStructure) { + return input; + } + String[] atc = input.split("%", 2); + return atc[0]; + } + + /** + * Clear list of string from redundant information. + * @param res + */ + protected void correctNames(List res) { + if (!fullStructure) { + return; + } + for (int i = 0; i < res.size(); i++) { + String strCurr = (String)res.get(i); + String[] atc = strCurr.split("%", 2); + res.set(i, atc[0]); + } + } + + protected List getXNames(List xArray, String prefix) { + List res = new ArrayList(); + if (null == xArray) { + return res; + } + if (null != prefix) { + prefix = prefix.toUpperCase(); + } + if (null == prefix) { + res.addAll(xArray); + } + else { + Bounds bounds = binaryBoundsSearch(xArray, prefix); + for (; bounds.nL < bounds.nH; bounds.nL++) { + res.add(xArray.get(bounds.nL)); + } + } + return res; + } + + public List getMatchingCatalogNames(String prefix) { + List res = getXNames(catalogs, prefix); + correctNames(res); + return res; + } + + public List getMatchingSchemaNames(String prefix) { + List res = getXNames(schemas, prefix); + correctNames(res); + return res; + } + + public List getMatchingTableNames(String prefix) { + List res = getXNames(tables, prefix); + correctNames(res); + return res; + } + + public List getMatchingColumnNames(String prefix) { + List res = getXNames(columns, prefix); + correctNames(res); + return res; + } + + /** + * return list of matching strings. + * Here is a short description what is happen here. + * the same schema with left <-> right which was above: + * xArray1 - right; + * xArray2 - left; + * xxMap - <-> index relation array-map; + * name - exactly string in xArray2; + * prefix - prefix string in xArray1. + * Matching criteria: + * list of strings from xArray1 which start from prefix and which is in relation with + * item from xArray2 which is exactly match the name. + **/ + protected List getXNames(List xArray1, long[] xxMap, List xArray2, String name, String prefix) { + List res = new ArrayList(); + if (null == xArray1) { + return res; + } + if (null != name) { + name = name.toUpperCase(); + } + if (null != prefix) { + prefix = prefix.toUpperCase(); + } + if (null == name && null == prefix) { + res.addAll(xArray1); + } + else if (null == name) { + Bounds bounds = binaryBoundsSearch(xArray1, prefix); + for (; bounds.nL < bounds.nH; bounds.nL++) { + res.add(xArray1.get(bounds.nL)); + } + } + else { + if (null == xArray2 || null == xxMap) { + return res; + } + Bounds bounds = binaryBoundsSearch(xArray2, name); + for (; bounds.nL < bounds.nH; bounds.nL++) { + int keyT = bounds.nL; + String itemT = (String)xArray2.get(keyT); + if (fullStructure) { + if (!itemT.toUpperCase().startsWith(name)) { + continue; + } + name = correctName(name); + itemT = correctName(itemT); + } + if (!name.equalsIgnoreCase(itemT)) { + continue; + } + long keyTlong = ((long)keyT) << 32; + int i = Arrays.binarySearch(xxMap, keyTlong); + if (i < 0) { + i = - i - 1; + } + if (null == prefix) { + for ( ; i < xxMap.length; i++) { + if (keyTlong != (xxMap[i] & UPPER_MASK)) { + break; + } + int keyC = (int)(xxMap[i] & LOWER_MASK); + if (0 <= keyC && keyC < xArray1.size()) { + res.add(xArray1.get(keyC)); + } + } + } + else { + for ( ; i < xxMap.length; i++) { + if (keyTlong != (xxMap[i] & UPPER_MASK)) { + break; + } + int keyC = (int)(xxMap[i] & LOWER_MASK); + if (0 <= keyC && keyC < xArray1.size() && ((String)xArray1.get(keyC)).toUpperCase().startsWith(prefix)) { + res.add(xArray1.get(keyC)); + } + } + } + } + } + return res; + } + + public List getCatalogNames() { + List res = new ArrayList(); + if (null != catalogs) { + res.addAll(catalogs); + } + return res; + } + + public List getMatchingSchemaNames(String catalogName, String prefix) { + List res = getXNames(schemas, csMap, catalogs, catalogName, prefix); + correctNames(res); + return res; + } + + public List getMatchingTablesNames(String schemaName, String prefix) { + List res = getXNames(tables, stMap, schemas, schemaName, prefix); + correctNames(res); + return res; + } + + public List getMatchingColumnNames(String tableName, String prefix) { + List res = getXNames(columns, tcMap, tables, tableName, prefix); + correctNames(res); + return res; + } + + public List getMatchingTablesNames(String catalogName, String schemaName, String prefix) { + catalogName = updateNullValue(catalogName); + schemaName = updateNullValue(schemaName); + schemaName = "" + schemaName + "%" + catalogName; + List res = getXNames(tables, stMap, schemas, schemaName, prefix); + correctNames(res); + return res; + } + + public List getMatchingColumnNames(String schemaName, String tableName, String prefix) { + schemaName = updateNullValue(schemaName); + tableName = updateNullValue(tableName); + tableName = "" + tableName + "%" + schemaName; + List res = getXNames(columns, tcMap, tables, tableName, prefix); + correctNames(res); + return res; + } + + public List getMatchingColumnNames(String catalogName, String schemaName, String tableName, String prefix) { + catalogName = updateNullValue(catalogName); + schemaName = updateNullValue(schemaName); + tableName = updateNullValue(tableName); + tableName = "" + tableName + "%" + schemaName + "%" + catalogName; + List res = getXNames(columns, tcMap, tables, tableName, prefix); + correctNames(res); + return res; + } +} Property changes on: D:\workspaces\RedHat\org.jboss.tools.seam.ui\src\org\jboss\tools\seam\ui\internal\reveng\TablesColumnsCollector.java ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Id Revision Date Name: svn:eol-style + native