From 1efc03c75342d181eba38eaf9c6722b5f19758f7 Mon Sep 17 00:00:00 2001 From: khartlage Date: Fri, 16 Apr 2004 19:15:53 +0000 Subject: [PATCH 1/1] initial quantum version --- .../.classpath | 9 + .../.cvsignore | 2 + .../.project | 17 + .../net.sourceforge.phpeclipse.quantum.sql/README | 78 +++ .../build.properties | 10 + .../doc/Custom Copy.html | 99 ++++ .../doc/Structure.html | 98 ++++ .../doc/book.css | 1 + .../doc/connect.html | 71 +++ .../doc/developers.html | 301 +++++++++++ .../doc/getting_started_connections.html | 77 +++ .../doc/getting_started_perspective.html | 28 + .../doc/images/logo.gif | Bin 0 -> 9740 bytes .../doc/images/newbookmark_menu.gif | Bin 0 -> 4120 bytes .../doc/images/newbookmark_wizard.gif | Bin 0 -> 8861 bytes .../doc/images/open_perspective.gif | Bin 0 -> 32416 bytes .../doc/images/quantum_perspective.gif | Bin 0 -> 27548 bytes .../doc/images/select_perspective_dialog.gif | Bin 0 -> 8360 bytes .../doc/index.html | 17 + .../doc/structure.gif | Bin 0 -> 3882 bytes .../doc/toc.xml | 9 + .../icons/.xvpics/fulldata-disabled.gif | 5 + .../icons/add.gif | Bin 0 -> 238 bytes .../icons/add_schema.gif | Bin 0 -> 154 bytes .../icons/append.gif | Bin 0 -> 164 bytes .../icons/autocommit.gif | Bin 0 -> 207 bytes .../icons/bigtable.gif | Bin 0 -> 242 bytes .../icons/bookmarkfile.gif | Bin 0 -> 933 bytes .../icons/bookmarks.gif | Bin 0 -> 238 bytes .../icons/clear.gif | Bin 0 -> 162 bytes .../icons/close.gif | Bin 0 -> 155 bytes .../icons/column.gif | Bin 0 -> 219 bytes .../icons/commit.gif | Bin 0 -> 252 bytes .../icons/connect.gif | Bin 0 -> 902 bytes .../icons/connected.gif | Bin 0 -> 152 bytes .../icons/copy.gif | Bin 0 -> 288 bytes .../icons/cut.gif | Bin 0 -> 652 bytes .../icons/delete.gif | Bin 0 -> 143 bytes .../icons/disconnect.gif | Bin 0 -> 919 bytes .../icons/edit.gif | Bin 0 -> 441 bytes .../icons/entitygroup.gif | Bin 0 -> 169 bytes .../icons/export.gif | Bin 0 -> 143 bytes .../icons/filter.gif | Bin 0 -> 159 bytes .../icons/fulldata.gif | Bin 0 -> 111 bytes .../icons/greentable.gif | Bin 0 -> 120 bytes .../icons/grid.gif | Bin 0 -> 152 bytes .../icons/group.gif | Bin 0 -> 217 bytes .../icons/import.gif | Bin 0 -> 141 bytes .../icons/key.gif | Bin 0 -> 156 bytes .../icons/keycolumn.gif | Bin 0 -> 251 bytes .../icons/log.gif | Bin 0 -> 164 bytes .../icons/missingtable.gif | Bin 0 -> 256 bytes .../icons/next.gif | Bin 0 -> 183 bytes .../icons/paste.gif | Bin 0 -> 298 bytes .../icons/play.gif | Bin 0 -> 186 bytes .../icons/previous.gif | Bin 0 -> 183 bytes .../icons/qmodel.gif | Bin 0 -> 941 bytes .../icons/quantum-ng.gif | Bin 0 -> 591 bytes .../icons/refresh.gif | Bin 0 -> 937 bytes .../icons/rollback.gif | Bin 0 -> 201 bytes .../icons/sample.gif | Bin 0 -> 983 bytes .../icons/schema.gif | Bin 0 -> 152 bytes .../icons/script.gif | Bin 0 -> 677 bytes .../icons/sequence.gif | Bin 0 -> 118 bytes .../icons/statement.gif | Bin 0 -> 152 bytes .../icons/stop.gif | Bin 0 -> 254 bytes .../icons/subset.gif | Bin 0 -> 156 bytes .../icons/success.gif | Bin 0 -> 661 bytes .../icons/table.gif | Bin 0 -> 237 bytes .../icons/torque.gif | Bin 0 -> 1044 bytes .../icons/unused/Thumbs.db | Bin 0 -> 9216 bytes .../icons/unused/bluegroup.gif | Bin 0 -> 157 bytes .../icons/unused/green_group.gif | Bin 0 -> 159 bytes .../icons/unused/green_schema.gif | Bin 0 -> 152 bytes .../icons/unused/green_view_group.gif | Bin 0 -> 254 bytes .../icons/unused/key.gif | Bin 0 -> 155 bytes .../icons/unused/key2.gif | Bin 0 -> 153 bytes .../icons/unused/margarita.gif | Bin 0 -> 152 bytes .../icons/unused/quantum.gif | Bin 0 -> 93 bytes .../icons/unused/sequence_group.gif | Bin 0 -> 248 bytes .../icons/unused/subset.gif | Bin 0 -> 621 bytes .../icons/unused/table_group.gif | Bin 0 -> 252 bytes .../icons/unused/view.gif | Bin 0 -> 149 bytes .../icons/unused/view_group.gif | Bin 0 -> 254 bytes .../icons/user.gif | Bin 0 -> 134 bytes .../icons/view.gif | Bin 0 -> 148 bytes .../icons/xml.gif | Bin 0 -> 159 bytes .../install.txt | 24 + .../lib/junit.jar | Bin 0 -> 121070 bytes .../plugin-3.0.xml | 300 +++++++++++ .../plugin.properties | 15 + .../plugin.xml | 303 +++++++++++ .../schema/data.exsd | 107 ++++ .../schema/metadata.exsd | 107 ++++ .../src-test/com/quantum/util/StringUtilTest.java | 71 +++ .../src/com/quantum/IQuantumConstants.java | 26 + .../src/com/quantum/Messages.java | 41 ++ .../src/com/quantum/QuantumPlugin.java | 310 ++++++++++++ .../src/com/quantum/QuantumResources.properties | 286 +++++++++++ .../com/quantum/actions/AddToQuickListAction.java | 56 ++ .../src/com/quantum/actions/BaseSQLAction.java | 25 + .../com/quantum/actions/BaseSequenceAction.java | 53 ++ .../src/com/quantum/actions/CloseTableAction.java | 40 ++ .../src/com/quantum/actions/ConnectAction.java | 115 +++++ .../src/com/quantum/actions/CustomCopyAction.java | 73 +++ .../com/quantum/actions/DeleteAllRowsAction.java | 77 +++ .../com/quantum/actions/DeleteBookmarkAction.java | 59 +++ .../com/quantum/actions/DeleteColumnAction.java | 63 +++ .../com/quantum/actions/DeleteObjectAction.java | 77 +++ .../com/quantum/actions/DeleteSubsetAction.java | 55 ++ .../src/com/quantum/actions/DisconnectAction.java | 81 +++ .../src/com/quantum/actions/ExecuteAction.java | 142 ++++++ .../com/quantum/actions/ExecuteAgainstAction.java | 184 +++++++ .../com/quantum/actions/ExportBookmarksAction.java | 42 ++ .../src/com/quantum/actions/ExportQueryAction.java | 83 +++ .../src/com/quantum/actions/ExportXMLAction.java | 130 +++++ .../com/quantum/actions/ImportBookmarksAction.java | 88 ++++ .../src/com/quantum/actions/ImportQueryAction.java | 80 +++ .../src/com/quantum/actions/NewBookmarkAction.java | 32 ++ .../src/com/quantum/actions/NewSubsetAction.java | 53 ++ .../com/quantum/actions/NextSequenceAction.java | 42 ++ .../src/com/quantum/actions/OpenQueryAction.java | 43 ++ .../com/quantum/actions/PrevSequenceAction.java | 44 ++ .../com/quantum/actions/RefreshBookmarkAction.java | 37 ++ .../com/quantum/actions/RefreshTableAction.java | 40 ++ .../quantum/actions/RemoveFromQuickListAction.java | 56 ++ .../src/com/quantum/actions/ViewTableAction.java | 59 +++ .../quantum/actions/ViewTableDetailsAction.java | 66 +++ .../src/com/quantum/adapters/AdabasDAdapter.java | 11 + .../src/com/quantum/adapters/AdapterFactory.java | 93 ++++ .../src/com/quantum/adapters/DB2AS400Adapter.java | 15 + .../src/com/quantum/adapters/DB2Adapter.java | 21 + .../src/com/quantum/adapters/DatabaseAdapter.java | 198 ++++++++ .../src/com/quantum/adapters/DriverInfo.java | 57 +++ .../com/quantum/adapters/FeatureNotSupported.java | 7 + .../src/com/quantum/adapters/GenericAdapter.java | 20 + .../src/com/quantum/adapters/MySQLAdapter.java | 9 + .../quantum/adapters/NoSuchAdapterException.java | 9 + .../src/com/quantum/adapters/OracleAdapter.java | 67 +++ .../src/com/quantum/adapters/PostgresAdapter.java | 70 +++ .../src/com/quantum/adapters/RedBrickAdapter.java | 23 + .../src/com/quantum/editors/ColorManager.java | 28 + .../editors/NonRuleBasedDamagerRepairer.java | 135 +++++ .../src/com/quantum/editors/SQLColorConstants.java | 13 + .../src/com/quantum/editors/SQLConfiguration.java | 89 ++++ .../com/quantum/editors/SQLDocumentProvider.java | 35 ++ .../src/com/quantum/editors/SQLEditor.java | 59 +++ .../com/quantum/editors/SQLPartitionScanner.java | 225 +++++++++ .../com/quantum/extensions/ExtensionAction.java | 132 +++++ .../src/com/quantum/extensions/IDataExtension.java | 21 + .../com/quantum/extensions/IMetadataExtension.java | 21 + .../com/quantum/extensions/IQuantumExtension.java | 13 + .../quantum/extensions/ProcessServiceMembers.java | 281 +++++++++++ .../src/com/quantum/model/Bookmark.java | 525 ++++++++++++++++++++ .../src/com/quantum/model/BookmarkCollection.java | 312 ++++++++++++ .../src/com/quantum/model/BookmarkHolder.java | 17 + .../src/com/quantum/model/Column.java | 21 + .../src/com/quantum/model/ColumnImpl.java | 148 ++++++ .../src/com/quantum/model/ConnectionException.java | 56 ++ .../src/com/quantum/model/Constraint.java | 8 + .../src/com/quantum/model/Database.java | 214 ++++++++ .../src/com/quantum/model/Entity.java | 40 ++ .../src/com/quantum/model/EntityFactory.java | 36 ++ .../src/com/quantum/model/EntityHolder.java | 8 + .../src/com/quantum/model/EntityImpl.java | 182 +++++++ .../src/com/quantum/model/ForeignKey.java | 15 + .../src/com/quantum/model/HasMetaData.java | 24 + .../src/com/quantum/model/Index.java | 13 + .../src/com/quantum/model/IndexImpl.java | 69 +++ .../com/quantum/model/NotConnectedException.java | 8 + .../src/com/quantum/model/PasswordFinder.java | 15 + .../src/com/quantum/model/Schema.java | 109 ++++ .../src/com/quantum/model/SchemaHolder.java | 8 + .../src/com/quantum/model/Sequence.java | 8 + .../src/com/quantum/model/SequenceImpl.java | 13 + .../src/com/quantum/model/Table.java | 11 + .../src/com/quantum/model/TableImpl.java | 31 ++ .../src/com/quantum/model/View.java | 11 + .../src/com/quantum/model/ViewImpl.java | 25 + .../com/quantum/model/xml/ModelToXMLConverter.java | 150 ++++++ .../src/com/quantum/model/xml/TorqueConverter.java | 90 ++++ .../src/com/quantum/perspective/DBPerspective.java | 30 ++ .../com/quantum/preferences/CopyPreferences.java | 37 ++ .../quantum/preferences/CustomCopyPreferences.java | 46 ++ .../preferences/CustomCopyPreferences2.java | 46 ++ .../preferences/CustomCopyPreferences3.java | 46 ++ .../com/quantum/preferences/GlobalPreferences.java | 49 ++ .../quantum/preferences/SQLEditorPreferences.java | 339 +++++++++++++ .../quantum/properties/BookmarkPropertyPage.java | 284 +++++++++++ .../DatabaseInformationPropertyPage.java | 60 +++ .../com/quantum/properties/EntityPropertyPage.java | 187 +++++++ .../com/quantum/properties/SchemaPropertyPage.java | 256 ++++++++++ .../src/com/quantum/sql/ConnectionEstablisher.java | 19 + .../src/com/quantum/sql/FilterSort.java | 83 +++ .../src/com/quantum/sql/MultiSQLServer.java | 426 ++++++++++++++++ .../src/com/quantum/sql/SQLHelper.java | 73 +++ .../src/com/quantum/sql/SQLParser.java | 62 +++ .../src/com/quantum/sql/SQLResults.java | 139 ++++++ .../src/com/quantum/sql/TableRow.java | 60 +++ .../sql/metadata/MetaDataJDBCInterface.java | 195 ++++++++ .../quantum/sql/metadata/MetaDataXMLInterface.java | 191 +++++++ .../com/quantum/sql/metadata/ObjectMetaData.java | 204 ++++++++ .../src/com/quantum/sql/parser/SQLLexx.java | 166 ++++++ .../src/com/quantum/sql/parser/StringPointer.java | 62 +++ .../src/com/quantum/sql/parser/Token.java | 57 +++ .../quantum/ui/dialog/BookmarkSelectionDialog.java | 110 ++++ .../quantum/ui/dialog/ExceptionDisplayDialog.java | 281 +++++++++++ .../src/com/quantum/ui/dialog/PasswordDialog.java | 122 +++++ .../src/com/quantum/util/NthLevelConverter.java | 145 ++++++ .../src/com/quantum/util/OneLevelConverter.java | 77 +++ .../src/com/quantum/util/QuantumUtil.java | 47 ++ .../src/com/quantum/util/StringMatrix.java | 352 +++++++++++++ .../src/com/quantum/util/StringUtil.java | 33 ++ .../quantum/util/connection/ConnectionUtil.java | 46 ++ .../src/com/quantum/util/io/InputStreamHelper.java | 18 + .../src/com/quantum/util/sql/TypesHelper.java | 59 +++ .../quantum/util/versioning/VersioningHelper.java | 49 ++ .../src/com/quantum/util/xml/XMLHelper.java | 73 +++ .../src/com/quantum/view/CopyAction.java | 40 ++ .../src/com/quantum/view/LogConstants.java | 9 + .../src/com/quantum/view/LogProxy.java | 34 ++ .../src/com/quantum/view/SQLLogView.java | 109 ++++ .../src/com/quantum/view/SQLQueryView.java | 517 +++++++++++++++++++ .../src/com/quantum/view/ViewHelper.java | 101 ++++ .../com/quantum/view/bookmark/AddSchemaAction.java | 58 +++ .../com/quantum/view/bookmark/AddSchemaDialog.java | 86 ++++ .../quantum/view/bookmark/BookmarkClipboard.java | 13 + .../view/bookmark/BookmarkContentProvider.java | 40 ++ .../view/bookmark/BookmarkLabelProvider.java | 74 +++ .../quantum/view/bookmark/BookmarkListNode.java | 120 +++++ .../com/quantum/view/bookmark/BookmarkNode.java | 167 +++++++ .../com/quantum/view/bookmark/BookmarkView.java | 269 ++++++++++ .../view/bookmark/BookmarkViewActionGroup.java | 266 ++++++++++ .../src/com/quantum/view/bookmark/ColumnNode.java | 64 +++ .../src/com/quantum/view/bookmark/CopyAction.java | 109 ++++ .../src/com/quantum/view/bookmark/EntityNode.java | 128 +++++ .../src/com/quantum/view/bookmark/GroupNode.java | 92 ++++ .../view/bookmark/LabelDecorationInstructions.java | 39 ++ .../src/com/quantum/view/bookmark/PasteAction.java | 46 ++ .../com/quantum/view/bookmark/QueryListNode.java | 76 +++ .../src/com/quantum/view/bookmark/QueryNode.java | 64 +++ .../com/quantum/view/bookmark/QuickListNode.java | 98 ++++ .../com/quantum/view/bookmark/RenameAction.java | 52 ++ .../src/com/quantum/view/bookmark/SchemaNode.java | 81 +++ .../src/com/quantum/view/bookmark/TreeNode.java | 124 +++++ .../src/com/quantum/view/subset/EntitySubset.java | 86 ++++ .../src/com/quantum/view/subset/ObjectNode.java | 167 +++++++ .../quantum/view/subset/SubsetContentProvider.java | 158 ++++++ .../quantum/view/subset/SubsetLabelProvider.java | 61 +++ .../src/com/quantum/view/subset/SubsetNode.java | 162 ++++++ .../src/com/quantum/view/subset/SubsetRoot.java | 41 ++ .../src/com/quantum/view/subset/SubsetView.java | 354 +++++++++++++ .../com/quantum/view/tableview/DefaultSizes.java | 6 + .../com/quantum/view/tableview/TableAdapter.java | 269 ++++++++++ .../src/com/quantum/view/tableview/TableView.java | 283 +++++++++++ .../view/tableview/TableViewMenuListener.java | 138 +++++ .../quantum/view/tableview/TableViewToolBar.java | 246 +++++++++ .../src/com/quantum/wizards/BaseSQLPage.java | 49 ++ .../src/com/quantum/wizards/BookmarkWizard.java | 297 +++++++++++ .../src/com/quantum/wizards/DeleteRowPage.java | 139 ++++++ .../com/quantum/wizards/ExportBookmarkWizard.java | 34 ++ .../quantum/wizards/ExportBookmarkWizardPage.java | 283 +++++++++++ .../com/quantum/wizards/ExportTorqueWizard.java | 20 + .../src/com/quantum/wizards/InsertRowPage.java | 120 +++++ .../src/com/quantum/wizards/SQLPage.java | 11 + .../src/com/quantum/wizards/SQLRowWizard.java | 28 + .../src/com/quantum/wizards/SortFilterPage.java | 180 +++++++ .../src/com/quantum/wizards/UpdateRowPage.java | 166 ++++++ 268 files changed, 18929 insertions(+), 0 deletions(-) create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/.classpath create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/.cvsignore create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/.project create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/README create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/build.properties create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/Custom Copy.html create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/Structure.html create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/book.css create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/connect.html create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/developers.html create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/getting_started_connections.html create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/getting_started_perspective.html create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/logo.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/newbookmark_menu.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/newbookmark_wizard.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/open_perspective.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/quantum_perspective.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/select_perspective_dialog.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/index.html create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/structure.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/doc/toc.xml create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/.xvpics/fulldata-disabled.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/add.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/add_schema.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/append.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/autocommit.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/bigtable.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/bookmarkfile.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/bookmarks.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/clear.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/close.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/column.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/commit.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/connect.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/connected.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/copy.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/cut.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/delete.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/disconnect.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/edit.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/entitygroup.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/export.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/filter.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/fulldata.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/greentable.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/grid.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/group.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/import.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/key.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/keycolumn.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/log.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/missingtable.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/next.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/paste.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/play.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/previous.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/qmodel.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/quantum-ng.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/refresh.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/rollback.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/sample.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/schema.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/script.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/sequence.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/statement.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/stop.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/subset.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/success.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/table.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/torque.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/Thumbs.db create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/bluegroup.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/green_group.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/green_schema.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/green_view_group.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/key.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/key2.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/margarita.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/quantum.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/sequence_group.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/subset.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/table_group.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/view.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/view_group.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/user.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/view.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/icons/xml.gif create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/install.txt create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/lib/junit.jar create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/plugin-3.0.xml create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/plugin.properties create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/plugin.xml create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/schema/data.exsd create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/schema/metadata.exsd create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src-test/com/quantum/util/StringUtilTest.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/IQuantumConstants.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/Messages.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/QuantumPlugin.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/QuantumResources.properties create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/AddToQuickListAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/BaseSQLAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/BaseSequenceAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/CloseTableAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ConnectAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/CustomCopyAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteAllRowsAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteBookmarkAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteColumnAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteObjectAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteSubsetAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DisconnectAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExecuteAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExecuteAgainstAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportBookmarksAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportQueryAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportXMLAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ImportBookmarksAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ImportQueryAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NewBookmarkAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NewSubsetAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NextSequenceAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/OpenQueryAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/PrevSequenceAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RefreshBookmarkAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RefreshTableAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RemoveFromQuickListAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ViewTableAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ViewTableDetailsAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/AdabasDAdapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/AdapterFactory.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DB2AS400Adapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DB2Adapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DatabaseAdapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DriverInfo.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/FeatureNotSupported.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/GenericAdapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/MySQLAdapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/NoSuchAdapterException.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/OracleAdapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/PostgresAdapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/RedBrickAdapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/ColorManager.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/NonRuleBasedDamagerRepairer.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLColorConstants.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLConfiguration.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLDocumentProvider.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLEditor.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLPartitionScanner.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/ExtensionAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IDataExtension.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IMetadataExtension.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IQuantumExtension.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/ProcessServiceMembers.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Bookmark.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/BookmarkCollection.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/BookmarkHolder.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Column.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ColumnImpl.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ConnectionException.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Constraint.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Database.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Entity.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityFactory.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityHolder.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityImpl.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ForeignKey.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/HasMetaData.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Index.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/IndexImpl.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/NotConnectedException.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/PasswordFinder.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Schema.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/SchemaHolder.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Sequence.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/SequenceImpl.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Table.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/TableImpl.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/View.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ViewImpl.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/xml/ModelToXMLConverter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/xml/TorqueConverter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/perspective/DBPerspective.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CopyPreferences.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences2.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences3.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/GlobalPreferences.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/SQLEditorPreferences.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/BookmarkPropertyPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/DatabaseInformationPropertyPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/EntityPropertyPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/SchemaPropertyPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/ConnectionEstablisher.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/FilterSort.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/MultiSQLServer.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLHelper.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLParser.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLResults.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/TableRow.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/MetaDataJDBCInterface.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/MetaDataXMLInterface.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/ObjectMetaData.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/SQLLexx.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/StringPointer.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/Token.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/BookmarkSelectionDialog.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/ExceptionDisplayDialog.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/PasswordDialog.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/NthLevelConverter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/OneLevelConverter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/QuantumUtil.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/StringMatrix.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/StringUtil.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/connection/ConnectionUtil.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/io/InputStreamHelper.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/sql/TypesHelper.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/versioning/VersioningHelper.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/xml/XMLHelper.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/CopyAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/LogConstants.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/LogProxy.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/SQLLogView.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/SQLQueryView.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/ViewHelper.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/AddSchemaAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/AddSchemaDialog.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkClipboard.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkContentProvider.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkLabelProvider.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkListNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkView.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkViewActionGroup.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/ColumnNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/CopyAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/EntityNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/GroupNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/LabelDecorationInstructions.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/PasteAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QueryListNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QueryNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QuickListNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/RenameAction.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/SchemaNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/TreeNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/EntitySubset.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/ObjectNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetContentProvider.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetLabelProvider.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetNode.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetRoot.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetView.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/DefaultSizes.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableAdapter.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableView.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableViewMenuListener.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableViewToolBar.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/BaseSQLPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/BookmarkWizard.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/DeleteRowPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportBookmarkWizard.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportBookmarkWizardPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportTorqueWizard.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/InsertRowPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SQLPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SQLRowWizard.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SortFilterPage.java create mode 100644 archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/UpdateRowPage.java diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/.classpath b/archive/net.sourceforge.phpeclipse.quantum.sql/.classpath new file mode 100644 index 0000000..5074f04 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/.cvsignore b/archive/net.sourceforge.phpeclipse.quantum.sql/.cvsignore new file mode 100644 index 0000000..ce087de --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/.cvsignore @@ -0,0 +1,2 @@ +bin +com.quantum diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/.project b/archive/net.sourceforge.phpeclipse.quantum.sql/.project new file mode 100644 index 0000000..68fc1de --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/.project @@ -0,0 +1,17 @@ + + + net.sourceforge.phpeclipse.quantum.sql + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/README b/archive/net.sourceforge.phpeclipse.quantum.sql/README new file mode 100644 index 0000000..7212fda --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/README @@ -0,0 +1,78 @@ +Changes: Changes from 2.2.3 + +Most changes to this version are trivial, and fall +into two main categories: + +- JDK 1.3 should now be supported. + +- Eclipse 3.0 M5/M6 should be supported (although + there's a different jar to install + +In addition: + +- Schema handling has been revised. + + + + + +Changes: Changes from 2.2.2 + +Most of the changes to the code are structural and +won't have an effect on the use of the plug-in. Some +of the changes that you will see include: + +- Better refresh support (Issuing a refresh on the + bookmark list does not collapse any previously-open + selections. + +- Properties available for items in the bookmark list + +- Key mapping (Ctl-Shift-Q) to execute queries in the + Query view + +- Bug fix for mixed-case tables in PostGres + +- Bug fix for SQL Queries on Oracle with column type + of CHAR + +- Added an explicit checkbox to indicate that you want + to be prompted for a password at connection time. + +- When you've selected multiple nodes at the same time, + you can perform the same action on each of them. + +- The status line from the Bookmark View now appears in + the standard status line window area. + +- Queries are persisted so that you can keep a list of + queries. + +Changes: Changes from 2.2.1 + +- Now you can leave blank the password field in the bookmark, + as suggested by Erik Dick in the Forum. You will be asked for + its value when trying to connect. There is a property + (Window->Properties->QuantumDB) to modify in case you use + blank passwords and don't want to be pestered with dialogs. + In this case, change the default (nothing) to a string + (e.g. "") and only when you use that string as bookmark + password you'll be asked for a new password. + +- The Query History View now registers all the queries, even + before being activated, fixing bug #773726. + +- The case sensitivity when using Postgres in Windows should + go now (bug #804353). + +- Fixed bug #811591, the Copy/Paste of bookmarks wasn't properly + initialized. + +- Now if the connection is implicit (created when using the SQL + Editor before opening the bookmark), the bookmark is connected + but the tables and views are not loaded till you try to expand + the node. + +- Fixed (really avoided) the problem with the Oracle jdbc driver + and its bug with getIndexInfo(). Bug reference #819846. + \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/build.properties b/archive/net.sourceforge.phpeclipse.quantum.sql/build.properties new file mode 100644 index 0000000..c1c75db --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/build.properties @@ -0,0 +1,10 @@ +bin.includes = icons/,\ + doc/,\ + *.jar,\ + plugin.xml,\ + plugin.properties,\ + install.txt,\ + .classpath,\ + .project,\ + +source.quantum.jar = src/ diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/Custom Copy.html b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/Custom Copy.html new file mode 100644 index 0000000..e9b8ee4 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/Custom Copy.html @@ -0,0 +1,99 @@ + +

Author: jparrai
+ Date: 26-08-2003
+ Subject: Using the Custom Copy facility
+

+

The "Custom Copy" feature is meant to allow the user to customize the copy + format of tables and columns.

+

How to use : You are in the Bookmarks View, or the Subset View. You + select the tables, views and columns that you want to copy. Be sure that only + tables, views and columns are selected. Then you select "Custom Copy" in the + context menu. By default, a blank sub-menu will appear. You have to customize + it to do something.

+

How to customize : You go to the Window->Preferences , then QuantumDB->Copy->Custom + Copy 1. You can have up to three different templates, that will appear in + the sub-menu with the names you give to them. So you start the Custom Copy 1 + preferences page.

+

There you have some boxes to fill up. The idea is that you will have a list + of tables (from now on, tables will mean "tables and views"). This list of tables + is composed of the directly selected tables plus the implicitely selected (because + a column of it is selected). You choose a general template format, and the formats + of the lists and items. The possible variables you have to play are:

+
+

${schema} The schema of the table or column. Valid in all format specifiers + except Template.

+

${table} The table name, without schema. Valid in all format specifiers + except Template.

+

${qualified} Same as ${schema}.${table} Valid in all format specifiers + except Template.

+

${column} The column name. Only valid for Column specifiers.

+

${column_list} The list of all columns. Only valid for Table specifiers. +

+

${table_list} The list of all tables. Only valid in Template. This + is the only variable that can be used in Template.

+

\n Inserts a new line

+

\t Inserts a tab character

+
+

It's faster to explain by example. Suppose I select the columns ENAME and JOB + from the table BONUS in schema SCOTT, and also the entire table DEPT from same + schema.

+
+

 

+ + + + + + + + + + + + + + + + + + + + + +
BONUS (implicit)ENAME (selected)
 JOB (selected)
DEPT (selected)DEPTO (implicit)
 DNAME (implicit)
 LOC (implicit)
+
+

Now I have the specifiers :

+ +

The result will be:

+
+
+

// Generated code

+

Call_Func(ENAME, JOB)

+

Call_Func(DEPTNO, DNAME, LOC)

+

//End of generated code

+
+
+

If I want only a list of columns, I can set:

+ +

The result will be:

+
+
+

(SCOTT.BONUS.ENAME, SCOTT.BONUS.JOB, SCOTT.DEPT.DEPTNO, SCOTT.DEPT.DNAME, + SCOTT.DEPT.LOC)

+
+
diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/Structure.html b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/Structure.html new file mode 100644 index 0000000..b2f04d1 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/Structure.html @@ -0,0 +1,98 @@ + + + + + + + + + + + +Author: jparrai
+Date: 28-06-2003
+Subject: Highlights of the structure of data in Quantum.
+

Quantum program data structure

+

After loading the Quantum plug-in, the saved-state file (an xml file) is loaded + up. Bookmarks are loaded into the BookmarkContentProvider + and the SubsetContentProvider + classes, where they are stored in the form of a vector of BookmarkNode + and SubsetNode respectively.

+

A SubsetNode has a number of + children, objects of class ObjectNode. + Each ObjectNode has an ObjectMetaData + instance that will hold the metadata (columns names, sizes and that stuff) of + the table or view that it (the ObjectNode) + references. That metadata is loaded from the saved-state file also on load-up + of the plug-in (three hypen-words in a single-sentence, wow! :)

+

A BookmarkNode represents a + connection with a database. It will be displayed by the BookmarView + view. When you double-click on one of the bookmarks, the function MultiSQLServer.connect(current) + willl be called. MultiSQLServer + is a Singleton (a class that will have a single instance), so we can get the + instance of it with MultiSQLServer.getInstance().

+

The connect() function will + use the JDBC driver and connect to the database. After that, the BookmarkNode + will have its con member assigned + (not null). After the connection, the function that is answering your double-clicking + (ConnectAction.run()), will try + to get the tables, views, etc from that connection. To do that, it will call + BookmarkView.refreshBookmarkData(), + that will query the database. As the procedure to get the tables may be different + for each database, the actual querying is delegated to another class SQLHelper, + that will centralize that kind of procedures (the ones that depend on the type + of the database). The called function in this case is getTableList(). + SQLHelper is not a Singleton, + although it could be, but we don't really need an instance because the functions + are all static.

+

The getTableList() will try + to get the tables from the function MultiSQLServer.listTables(), + if the jdbc adapter of the bookmark is generic. listTables will ask the jdbc + driver directly for the list of tables, using the DatabaseMetadata.getTables() + call. If the adapter is not generic, it will use a SQL statement to get + the list of table names. This SQL statement will be of course different in every + database, so it will come from the DatabaseAdapter + class.

+

The DatabaseAdapter class is + the one where you should put all the functions that will be different for each + database. Then for each database, you create an "adapter" class derived + from DatabaseAdapter, and implement + all the necessary abstract functions. So you get a proper adapter using DatabaseAdapter + adapter = AdapterFactory.getInstance().getAdapter(current.getType()), + and the returned adapter will have the proper type (always a derived type from + DatabaseAdapter). Then calls + to the adapter object will be redirected to the proper function.

+

The TableNode objects generated + will have metadata, i.e. columns. That information is saved in an object of + class ObjectMetaData in the TableNode + object. This ObjectMetaData class is part of the metadata package, that has + basically four classes:

+

MetaDataJDBCInterface : Basically + takes care (through static functions) of passing the metadata from the jdbc + driver to the ObjectMetadata class.

+

MetaDataXMLInterface : Handles + interface between an ObjectMetaData and XML storage. It can write an existing + metadata object to XML and generate a new ObjectMetaData from existing XML.

+

ObjectMetaData : The class that + has all the metadata. Rather underdeveloped, one must add functions as needed. + The metadata is saved in the form of StringMatrix objects.

+

StringMatrix : A matrix of strings. + Saves the results from the jdbc driver, usually given as ResultSet objects, + that are very similar in structure but sequential in nature (you access the + records one at a time). The first line of the matrix are the names of the columns, + and the rest hold the values.

+

 

+

+


+

+

 

+ + \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/book.css b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/book.css new file mode 100644 index 0000000..b6da4c8 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/book.css @@ -0,0 +1 @@ +P.Code { display: block; text-align: left; text-indent: 0.00pt; margin-top: 0.000000pt; margin-bottom: 0.000000pt; margin-right: 0.000000pt; margin-left: 15pt; font-size: 10.000000pt; font-weight: medium; font-style: Regular; color: #4444CC; text-decoration: none; vertical-align: baseline; text-transform: none; font-family: "Courier New"; } H6.CaptionFigColumn { display: block; text-align: left; text-indent: 0.000000pt; margin-top: 3.000000pt; margin-bottom: 11.000000pt; margin-right: 0.000000pt; margin-left: 0.000000pt; font-size: 9.000000pt; font-weight: medium; font-style: Italic; color: #000000; text-decoration: none; vertical-align: baseline; text-transform: none; font-family: "Arial"; } P.Note { display: block; text-align: left; text-indent: 0pt; margin-top: 19.500000pt; margin-bottom: 19.500000pt; margin-right: 0.000000pt; margin-left: 30pt; font-size: 11.000000pt; font-weight: medium; font-style: Italic; color: #000000; text-decoration: none; vertical-align: baseline; text-transform: none; font-family: "Arial"; } EM.UILabel { font-weight: Bold; font-style: Regular; text-decoration: none; vertical-align: baseline; text-transform: none; } EM.CodeName { font-weight: Bold; font-style: Regular; text-decoration: none; vertical-align: baseline; text-transform: none; font-family:"Courier New"; } /* following font face declarations need to be removed for DBCS */ body, h1, h2, h3, h4, ,h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font-family: Arial, Helvetica, sans-serif; color: #000000} pre { font-family: Courier, monospace} /* end font face declarations */ /* following font size declarations should be OK for DBCS */ body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font-size: 10pt; } pre { font-size: 10pt} /* end font size declarations */ body { background: #FFFFFF} h1 { font-size: 18pt; margin-top: 5; margin-bottom: 1 } h2 { font-size: 14pt; margin-top: 25; margin-bottom: 3 } h3 { font-size: 11pt; margin-top: 20; margin-bottom: 3 } h4 { font-size: 10pt; margin-top: 20; margin-bottom: 3; font-style: italic } p { margin-top: 10px; margin-bottom: 10px } pre { margin-left: 6; font-size: 9pt } a:link { color: #0000FF } a:hover { color: #000080 } a:visited { text-decoration: underline } ul { margin-top: 0; margin-bottom: 10 } li { margin-top: 0; margin-bottom: 0 } li p { margin-top: 0; margin-bottom: 0 } ol { margin-top: 0; margin-bottom: 10 } dl { margin-top: 0; margin-bottom: 10 } dt { margin-top: 0; margin-bottom: 0; font-weight: bold } dd { margin-top: 0; margin-bottom: 0 } strong { font-weight: bold} em { font-style: italic} var { font-style: italic} div.revision { border-left-style: solid; border-left-width: thin; border-left-color: #7B68EE; padding-left:5 } th { font-weight: bold } \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/connect.html b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/connect.html new file mode 100644 index 0000000..b6b8e63 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/connect.html @@ -0,0 +1,71 @@ + + + + + Making a Quantumdb connexion (bookmark) + + +Author: jparrai
+Date: 28-03-2003
+Subject: Making a Quantumdb connexion
+
+To connect to a database (create a bookmark in quantum) you use the New Bookmark menu item that appears +when right-clicking on the blank space in the Database Bookmarks view.
+
+The data that the form asks of you is:
+
+ +
+Other examples (only as orientation, your particular data may be +different)
+
+For MySql (in Windows):
+
Connect: jdbc:mysql://localhost/test
Driver: com.mysql.jdbc.Driver
Driver Filename: C:\mysql\jdbc\mysql-connector-java-2.0.4-bin.jar

For PostgreSql (in Linux):

Connect: jdbc:postgresql://localhost/emsdevel
Driver: org.postgresql.Driver
driver filename: /opt/postgresql/share/java/postgresql.jar


+
+ + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/developers.html b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/developers.html new file mode 100644 index 0000000..34724ed --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/developers.html @@ -0,0 +1,301 @@ + + + + + Tutorial of developing and changing QuantumDb + + +Author: jparrai
+Date: 28-03-2003
+Subject: Tutorial of developing and changing QuantumDb
+
+To modify the quantumdb plug-in, first you get it to a development +system, usually Eclipse itself.
+

1. Getting the project from CVS.
+

+First you go to Open a Perspective +and open the CVS repository exploring +perspective. It can be in the Others.... +You get a perspective. You right-click on the CVS Repositories view and create a New -> Repository Location...
+The data to access quantum is:
+
+Host: cvs.sourceforge.net
+Repository Path: /cvsroot/quantum
+User: anonymous
+Password:
+
+There is no password for anonymous. +You can substitute the User and Password for you own, if you are +registered in sourcefoge.net. If +you want developer access, remember to use extssh as the connexion type, so as +to be able to update the cvs repository with your changes (that need a +ssh connection in sourceforge)
+
+After that, if you are connected to the Net, you will be able to get +the project files. You will see a HEAD +sub-item, a Branches, and a Versions. You select the HEAD, and then right-click onto quantum-plugin. Then select Check Out As.... You cannot check it +out as a Project, because some files are not present, mainly the .project and .classpath.
+
+

2. Configuring the project.
+

+So you "Check Out As..." and select an Plug-In project, call it as you +wish, (I will use "com.quantum") and then select an Empty Plug In. If +everything goes ok, you should end with a new project and about 1600 +errors. The errors are caused because you have now a default classpath, +and the quantumdb project uses some plug-ins, so these plug-ins +directories must be referenced.
+
+My classpath for Eclipse 2.0 is as follows:
+
+ <?xml version="1.0" +encoding="UTF-8"?>
+ <classpath>
+     +<classpathentry kind="src" path="src"/>
+     +<classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" +sourcepath="JRE_SRC"/>
+     +<classpathentry kind="lib"
+ +        +path="C:/Parsec/eclipse/plugins/org.eclipse.core.boot_2.0.2/boot.jar" +sourcepath="C:/Parsec/eclipse/plugins/org.eclipse.platform.source_2.0.2/src/org.eclipse.core.boot_2.0.2/bootsrc.zip"/>
+     +<classpathentry kind="lib"
+ +        +path="C:/Parsec/eclipse/plugins/org.eclipse.core.runtime_2.0.2/runtime.jar" +sourcepath="C:/Parsec/eclipse/plugins/org.eclipse.platform.source_2.0.2/src/org.eclipse.core.runtime_2.0.2/runtimesrc.zip"/>
+     +<classpathentry kind="lib"
+ +        +path="C:/Parsec/eclipse/plugins/org.eclipse.core.resources_2.0.1/resources.jar" +sourcepath="C:/Parsec/eclipse/plugins/org.eclipse.platform.source_2.0.2/src/org.eclipse.core.resources_2.0.1/resourcessrc.zip"/>
+     +<classpathentry kind="lib"
+ +        +path="C:/Parsec/eclipse/plugins/org.eclipse.swt.win32_2.0.2/ws/win32/swt.jar" +sourcepath="C:/Parsec/eclipse/plugins/org.eclipse.platform.win32.source_2.0.2/src/org.eclipse.swt.win32_2.0.2/ws/win32/swtsrc.zip"/>
+     +<classpathentry kind="lib"
+ +        +path="C:/Parsec/eclipse/plugins/org.eclipse.ui_2.0.2/workbench.jar" +sourcepath="C:/Parsec/eclipse/plugins/org.eclipse.platform.source_2.0.2/src/org.eclipse.ui_2.0.2/workbenchsrc.zip"/>
+     +<classpathentry kind="lib"
+ +        +path="C:/Parsec/eclipse/plugins/org.eclipse.ui.win32_2.0.0/workbenchwin32.jar"
+ +        rootpath="" +sourcepath="C:/Parsec/eclipse/plugins/org.eclipse.platform.win32.source_2.0.2/src/org.eclipse.ui.win32_2.0.0/workbenchwin32src.zip"/>
+     +<classpathentry kind="output" path="bin"/>
+ </classpath>
+
+Where, as you can see, my Eclipse home is C:\Parsec\eclipse. In any case, +you need to reference those plug-ins you see below, from org.eclipse:
+ +


+ Remember after changing manually the .classpath + file that you have to Refresh the project + to take the changes in.
+
+ If you want to reference those plug-ins using the workspace, select Properties from the newly created com.quantum project and go to Java Build Path, then Libraries tab, and select the .jar files the project needs.
+
+ It should now build without errors.
+
+ In Eclipse 2.1 that won't work. Dependencies amongs plug-ins have changed and + instead of redoing all of them again I chose to use the new "classpath container" + facility. When I say that won't work I mean if linking against the 2.1 libraries. + If you link against the 2.0 libraries will work all right.
+

+

The libraries for 2.1 are as follows (I copy my classpath) :

+

<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.core.boot_2.1.0/boot.jar" sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.core.boot_2.1.0/bootsrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.core.runtime_2.1.0/runtime.jar" + sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.core.runtime_2.1.0/runtimesrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.core.resources_2.1.0/resources.jar" + sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.core.resources_2.1.0/resourcessrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.swt.win32_2.1.0/ws/win32/swt.jar" + sourcepath="ORG_ECLIPSE_PLATFORM_WIN32_SOURCE_SRC/org.eclipse.swt.win32_2.1.0/ws/win32/swtsrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.ui_2.1.0/ui.jar" sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.ui_2.1.0/uisrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.text_2.1.0/text.jar" sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.text_2.1.0/textsrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.jface_2.1.0/jface.jar" sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.jface_2.1.0/jfacesrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.jface.text_2.1.0/jfacetext.jar" + sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.jface.text_2.1.0/jfacetextsrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.ui.views_2.1.0/views.jar" sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.ui.views_2.1.0/viewssrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.ui.workbench_2.1.0/workbench.jar" + sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.ui.workbench_2.1.0/workbenchsrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.ui.win32_2.1.0/workbenchwin32.jar" + sourcepath="ORG_ECLIPSE_PLATFORM_WIN32_SOURCE_SRC/org.eclipse.ui.win32_2.1.0/workbenchwin32src.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.ui.workbench.texteditor_2.1.0/texteditor.jar" + sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.ui.workbench.texteditor_2.1.0/texteditorsrc.zip"/>
+ <classpathentry kind="var"
+ path="ECLIPSE_HOME/plugins/org.eclipse.ui.editors_2.1.0/editors.jar" + sourcepath="ORG_ECLIPSE_PLATFORM_SOURCE_SRC/org.eclipse.ui.editors_2.1.0/editorssrc.zip"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+ </classpath>
+
+

+

3. Running the project.
+

+First go to Window -> Preferences +-> Plug-in Development -> Target Platform and to select all +the plug-ins that should be used when running a platform from the +plug-in development. I select all of them not in the workspace because I +don't want to resolve all the cross-references.
+
+Then go to Run -> Run As -> +Run-time Workbench. If all is well, a new workbench should +appear, that has you just-compiled quantum plug-in installed. To check +it, open the quantumdb perspective (Perspective +Button -> Others... ->QuantumDb Perspective), and see if +it appears. This is not
+the usual QuantumDb perspective, but the one you are developing. Of +course, if you have made no change to the standard source, there is no +difference.
+
+

4. Making a small change.
+

+To check that we are really using our modified QuantumDb, and not the +standard, let's make a change. Open the QuantumResources.properties file, +(in the com.quantum package), +and modify the line
+
+ bookmarkview.newBookmark = +New Bookmark...
+
+to
+
+ bookmarkview.newBookmark = +Add New Bookmark...
+
+(for example)
+
+Then Run the testing workbench again, you can now use simply Ctrl+F11 to run the last launched +environment. Now, in the bookmark view, when you right-click on it, it +should show your modified string. So you are now ready to change the +plug-in.
+

5. Creating a .jar file.
+

+

You may simply want to make a .jar + file from some configuration taken from the CVS, so as to have the latest version + available to you. You have to follow the same instructions as before for installation. + When it's installed and built, select the com.quantum + project, right-click on it and select Export.
+
+ In Eclipse 2.0: Select jar File and + then choose a directory. The name of the jar file should be Quantum.jar as that's the name stated in the + plugin.xml file.
+
+ To install this jar file as a plug-in, create a directory called com.quantum in the directory plugins under your local Eclipse installation + directory. Copy the jar file to that directory, and uncompress it (without deleting + it) into that same directory. In fact, I think you only need the icons + directory and the plugin.xlm, but you + can leave the rest of the files so they feel not so alone.
+
+ You close your Eclipse IDE and open it up again, and the QuantumDB perspective + should be available.
+

+

6. Uploading the change to CVS.

+

(I copy directly from the Eclipse Help, so as to have all the info in the same + place)

+

Synchronizing with a CVS repository

+


+ In the CVS team programming environment, there are two distinct processes involved + in synchronizing resources: updating with the latest changes from a branch and + committing to the branch.

+

When you make changes in the Workbench, the resources are saved locally. Eventually + you will want to commit your changes to the branch so others can have access + to them. Meanwhile, others may have committed changes to the branch. You will + want to update your Workbench resources with their changes.

+

Important!: It is preferable to update before committing, in case there are + conflicts with the resources in your Workbench and the resources currently in + the branch.

+

The synchronize view contains filters to control whether you want to view only + incoming changes or outgoing changes. Incoming changes come from the branch. + If accepted, they will update the Workbench resource to the latest version currently + committed into the branch. Outgoing changes come from the Workbench. If committed, + they will change the branch resources to match those currently present in the + Workbench.

+

Regardless of which mode (filter) you select, the Synchronize view always shows + you conflicts that arise when you have locally modified a resource for which + a more recent version is available in the branch. In this situation you can + choose to do one of three things: update the resource from the branch, commit + your version of the resource to the branch ,or merge your work with the changes + in the branch resource. Typically you will want to merge, as the other two options + will result in loss of work.

+

(End of copy from Eclipse Help, there are lots more, just go there and have + a look) Basically to get all the changes since the last time you took the sources, + then accept all the files that have changed in the CVS and you haven't touched. + If there are some that you have touched and are also touched by someone else + at CVS then you have to inspect the changes, see if they conflict with yours, + and merge both until you have a working set. Then you can upload that "working" + set to CVS. That's more or less the idea.

+ + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/getting_started_connections.html b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/getting_started_connections.html new file mode 100644 index 0000000..c14d6aa --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/getting_started_connections.html @@ -0,0 +1,77 @@ + + + + + Creating a QuantumDB Bookmark + + + +

Creating a QuantumDB Bookmark

+

Author: jparrai
+Date: 28-03-2003
+

To connect to a database (create a bookmark in quantum) you use the New Bookmark menu item that appears +when right-clicking on the blank space in the Database Bookmarks view.

+ + + +

Once this menu item is selected, you will see the "New Bookmark" wizard:

+ + + +

The data that the form asks of you is: +

+

Other examples (only as orientation, your particular data may be +different)
+

+For MySql (in Windows):

+
Connect: jdbc:mysql://localhost/test
Driver: com.mysql.jdbc.Driver
Driver Filename: C:\mysql\jdbc\mysql-connector-java-2.0.4-bin.jar
+
+

For PostgreSql (in Linux):

+
+ 
Connect: jdbc:postgresql://localhost/emsdevel
Driver: org.postgresql.Driver
driver filename: /opt/postgresql/share/java/postgresql.jar
+ + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/getting_started_perspective.html b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/getting_started_perspective.html new file mode 100644 index 0000000..442ceb9 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/getting_started_perspective.html @@ -0,0 +1,28 @@ + + + + + + Opening the Quantum DB Perspective + + + + +

Opening the Quantum DB Perspective

+

Typically, the first thing you do with the Quantum plug-in is to open the Quantum DB Perspective. +Go to Window -> Open Perspective -> Other... to get the "Select Perspective" +dialog.

+ + + +

Choose the "Quantum DB Perspective" option from the list:

+ + + +

The Quantum DB Perspective looks like this:

+ + + +

The first time you open the Quantum DB perspective, you won't see any bookmarks defined. + + \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/logo.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..969a593172fa155c90bd65d2e50bc7747e7f3926 GIT binary patch literal 9740 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 literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/newbookmark_menu.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/newbookmark_menu.gif new file mode 100644 index 0000000000000000000000000000000000000000..f6014e299eabb08d44699139e1bf890af4e3c3e2 GIT binary patch literal 4120 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 literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/newbookmark_wizard.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/newbookmark_wizard.gif new file mode 100644 index 0000000000000000000000000000000000000000..30f148a8c2c05a5cc5cb98d4f538a5563c29ba71 GIT binary patch literal 8861 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 literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/open_perspective.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/images/open_perspective.gif new file mode 100644 index 0000000000000000000000000000000000000000..a6a299d47a266a017bce73e38e69ae1e78dc9c13 GIT binary patch literal 32416 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 yg+6qm7v1PbM|#qgzI3KH-RVz + + + + + Quantum DB User's Guide + + + + + +

QuantumDB User's Guide

+

Quantum is a database access plugin for Eclipse. +It can be used to connect to databases, list tables and views, and issue ad-hoc queries. +

The Quantum home page is hosted by Sourceforge. + + \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/structure.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/structure.gif new file mode 100644 index 0000000000000000000000000000000000000000..283ee3e59f74a78c33497a04f826361e53c7dbd4 GIT binary patch literal 3882 zcmV+_57qETNk%w1VeJAT0r3C;@9*yb00960{{R30A^8LW00000EC2ui0PO-H0RRI2 zgpaAq?GK}zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNI&iDQg3<`(DqVb4KDwoWr z^9hYgr_`$Tip^@b+^+Wv4vWX+viXcotJmzd`wfrF=k&V$j?e4&{J#GW7$`VMSZH{N zn5ekO*y#8O87VnQS!sERnW?$S+3EQS8Y((UT55WVnyR|W+UoiW8!J0YTWfoZo2$Fa z+w1!a94tIcTx@)doUFXe-0b`e9WA{VP;GsUovppi-R=Di9v(hTUak-zkgmSY-tPVm zA1^;oUq4@Mo==W$-|znqFrYkq`U*bdCorMHg$xNAe5ec|!-*6tzHrSSV<)ks0E8;jwfv|qTO)2?5ULUkJUt2MG^&)R*JcHvmI zU{S&q3z+WI0Cx+s$_sMo&bdn6dTkt)F=M(^4O<3VBn9yOxxCwd{eNU)#16d$#U&t#A8IlzX>uq`!+p3O-zSZ{y4XiF*z`y7cMdnp;PN zJh|-U*Sp`zu3a^E@8sox4=;Lr`Soqiqt~pSy?iw8-&3wVKYyJ1_Wq^D*AL(q;0^dz zO!a7W;AHgt7hr>0q-9e{nX%N^flgg$piUW1brF6Jen`evC&9ItWF?+-6o)FxwHH&4 zMJD2lk{PItTSj>ZVvYhr78qMJKGxQX7yZ~)TznN7SB4Z4sU(g%KKUSzEc!TCi&RE6 zWRFu;$Rk)sF*O!si>7<$>ap_I{F}P`{Idt0JO__>{>JOxr zTGXkjzN!Otvd&6tt=PbdD-f%)ifOLC@~|tfAi4T$u`L8E{w!(48p|vS$R-OAsLf8x z!L!i%BQ3SsUSRFD_GG(lxDs^h?SjjSi!Qh2h6irC?j}I)y79F8ZoTo!+hM)>YH%;U zyq&vmxWxAB?_dERe1J6$5L|GX2p^p10t`1y@58C4Byq#a0c@sagFU>T~2Wbo+ z%rX#duF<6mT|&-MuYvVdPz%;I2~^*+wFhIPRJIEy2NHHGXMdWu+TOMe!P|A|%3C3H zr(*YedxOxoPH}G#_}^w5e2C$s40=yM5)!JHf^TmA_%F_f&g-~eKx&To3nu5bq=vK! z5wRkQhmvMbnXl**QA@_AwdG-E`On9j3+b@uyiv~D?40*B_zDU?a=IsYy0~bHf)@CA zpite&c=CT%$k+3V6;HU7FuIw|^^RVcsG-kWjeC`QUCun17@|!&CD>~+=#gQa&!zml zvw41!U%Gi`n|B5;JV4=3dqA=uU<@cf0AfHwiW=aY{Fl1UN#lK}fuQsV_##6U%7Ob+ zQ%(qozbfSpZyY=n{X~eq1}0BLT=a^u_!wG=}K<|`i*oJ9WgrZ+tp#t(z&%OCU>RlujPPJCk`4(Ylm zMhkA~gi0hM3t{lN$H3@{uT$UUBv?ZtV&-f2vD~$)2!H`uN{_z)WFrE{E<$E)Zi*b2 zT1?VNUl`JKd?d>xDS${C>h5ZhEMzC$S4sbT5^#)cq2ER+NmLRqls{2r2QrCA78K5v zy||^?KZ>sY$?A#AIJ5o;uAXA>4Jc2d< z`LY}2vpx4Tl??_~$`K&6pGI(JBK~nOP&GJoJLrU0Y4+L3;puapMVM%E*cs6?_-Jyq zD=F^8Q&9wz&X>Ft+Xz+4Q6hLWmnm&PNJCU8)kVvsygO+*Yk;wHBvb@JW$7{-T2M>Y zbYV+n109jal@Tq^O24BX7Ec5|$SLcfnlu1LU5ZC=A~mV4)DbiSw96SqgK$$Xpf!3YEaPOfy1OlYFiD)@YQDazP~fGLp&f+} zUj=u&o<>cYm>6vTmIznZsp+jb9Tq@G1UyFCj5c{aqh+&t#4KXSMCobj1Ol6dr>0Sh z0^}a#a6+amhL1nGj2&c&{wi6qLbPt1anbx9Si;RV)V5)m>1c{OSG=|~vX#^BQ6YNK z^dM9|0;zYC%MPN(rar2$VnN` zutQ8X=oCy`*(y6u$qn`I_=dI>8&sh$1(a!8)W!lHjO!TUhA3csO%$df9J~UwKdaNhUV5NYr zbeaWAXuNrvY)-CkrcKS_Q^gsjV3>56M?J4l+c?o}UUZHZ3hUm9!PQgCb*xM6W?5=l zRle5s7$9ApO&5ELmuB;+gWc?9lls{5n&hg{i|BZMdDuRl0Gq-PveYJ9*w%EJXtRi;o??!EPHU^XWQDJIs|wGLrYTomC#EN z=3o6b$l?AjeDUTBy6n62l5msfdI zSE87mUCJ^Yywf~)c9s`5Mj==1#CvKYstOl`jA}ge7;hq+;yt!Wq!Y}&?s9{Ztb*}8 zI=DAK-jT+=gC=a!)I~q~N@UV*SI-{m;}rF@%3ZB=k812QF>dLC+l1*G?h7j)`OE)F zP`~f2&?QT4et*>N&98#t6CeG5KeYO?e}24MJ#X%V()-;Vez|Hd{{ND{{0Bcj_0tc9 z;QoW{{iGy0{9&{Hg$p+P_g`iH8!aH$rw#pg9RCM^`)7Xy=m_%HN7>hK3WyyBICPT6 ze-KDX5{P~oFi{z3f$8>t9H=e{*nz+yfv|^w?l*!LXn-JS0UJnvDJWAV$buE%f-o3? z82EyRBZ4+a2n?uHIJJX3s7*KsgeWM4Jt%--SA-9Egnp2OPY8w7QGrcJg&l@(Rd|Fo zh=o|FgKNmQPAGn`_Pgh!E-W@u*SgV?r_z~X5hDT6r(j~`hz zEJuVPDUy{&k}JuQ92saYxq>Fyj$7w%u|{0yrG2rZlC9Kl-%@aG_fs+cIVyHCluneC zMCn3Z*H$%FXeMzx5VBj^_k%`xl#A6xiIR7N;XKAiSQzJdaAG}w$0_~+L|Z9wZY5zj zS(I4mSj^);xrcN8qjpo*CwAF;@3$**$yh%WCpc7Aa9Lz}8AH9bIUIySRFamUg_tyn zmRh8Ib!1-freTD+VbN7{Jmi>gM>%XHMPhQ6du5n8@j+2UcUOs-8`hS@r#^F3m2wd% z7#BwCQ%6-dfea@~WD36MpM>w{cuQro>S(3xanjLAJFo~RSG?L3%lg-&{E(x6< zXp`!QlG8R;(J7tINu8s~o!wb$cLtgHw~5b~krz2#>G@CMsc8P>S)Jy2o#&XHqw|y2 z>7L_>X63nl=gExq`D^znpZTeB@JVz-hMxoqWy(o(;l-Q^IyBOk6+Sm$M3-}dv~IQe zlun5@mdSn)Y67j(ZX@cH$Wl*5)oE7AR};b{J*RgA2YKHIqF}X{YPoz9R#kZCTxH3V zTV|nQ^>;fuaey~fIr?$@wU*n1RURjnMQVaGieOs#mr(SSZ^2tT`J=t6oiZsC zyjl^uI*iB)l?w)9$2qJO$)3~{D={{$&=jr6Rji|epaYt%v|60tnV{dQgSEPy<4Uer zx2;j>t?8<+=E|=9IiKXntRD(&LZ__2Sg-oGZ|&-?{PLXQ>aYL0KmjYD@=CD83a>Hv zpb1NZ279gp>#&#vvGGcN`Pz&7dUE}WuoD}C3wy67hq1b-u?NVp7dx-vShAMdlHuvG s6uYhr>#{F9F4sCM7-_T5M6)fJv(u4YJRHUIzs literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/doc/toc.xml b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/toc.xml new file mode 100644 index 0000000..5af310f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/doc/toc.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/.xvpics/fulldata-disabled.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/.xvpics/fulldata-disabled.gif new file mode 100644 index 0000000..ac825ff --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/.xvpics/fulldata-disabled.gif @@ -0,0 +1,5 @@ +P7 332 +#IMGINFO:16x16 Greyscale (883 bytes) +#END_OF_COMMENTS +16 16 255 +I$IIÛ¶¶¶IH%IÛ¶¶ÚI$IIÛ¶¶¶IH%IÛ¶¶ÚI$IImIIIIHJl%Û¶¶I$II¶’’¶‘’¶’$Û¶ÛÛ¶¶H“H%H%IH“HI$IÛ¶¶H“µ’’¶’’‘II$IÛ¶¶H“H%H%IH“HI$IÛ¶¶H“µ’’¶’’‘II$II$II¶%H%H%I¶$Û¶ÛI$II¶’’¶‘’¶’$Û¶ÛI$II¶%H%H%I¶$Û¶ÛI$II¶’’¶‘’¶’$Û¶ÛÛ¶¶H“H%H%IH“HI$IÛ¶¶H“µ’’¶’’‘II$IÛ¶¶HI%IHÛ¶·¶H%IHÛ¶¶¶I$IIÛ¶¶Ú%H%I \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/add.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/add.gif new file mode 100644 index 0000000000000000000000000000000000000000..0fc47e193cf88cea7e6718e602e71f560cfad5cd GIT binary patch literal 238 zcmZ?wbhEHb6krfw*!-X2|NsBbp8bFN6o~$vIrIO_nWtN}oY}nj%!=g)mn}Qc-Myr{ zYjH!vOa=yq0|yQONyVQmj0_BX3_3tI&;$Vn2NsVDCq1=u7c5DrI3Sv4&~`~6fuo}1 z@}Bps=clP?NquKpb$x5ERD#Erk69j~g)@RC7Ie;KW&Uc~JKK+4^OMiIb&(es5AaN$ zlFY)O_|M-tzo4=xGd-h3!N|bCKq0A8A-FV8!8bFxD8IO}xFj{VSVzG#FIi8)F(*eM m2&AxBAt<#twWusLMUR)u%g0T@JxC!ewMfBG&w!VU!5RS7JYcT? literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/add_schema.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/add_schema.gif new file mode 100644 index 0000000000000000000000000000000000000000..dbbb9cf9d12173169650b52a838ef22c229783f0 GIT binary patch literal 154 zcmZ?wbhEHb6krfw*vtR||NsBLb?5GdOP3EEI&2$c=aOJ%>a4fs*0j(HXP^{V34&1k z$->CMz{Q{g5(1gQz~UZo(o@^lBD-ed{{$tUPFKmt%hcK&H8?etPkub~Eak?eYya%$ rJ#o;H;%|-4pW1y^gx&jOiA0Ez{fdoB5*2H^8qdyN9CG?82ZJ>L+TAx- literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/append.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/append.gif new file mode 100644 index 0000000000000000000000000000000000000000..2dbb07370b4403f107b44de031079c9ba3982659 GIT binary patch literal 164 zcmZ?wbhEHb6krfw*vtR||Ns9tFi5nu&6_y!(7bu)ck=SC;^qA#Dth|l$t#yHzk2lw zr~s@GL@54bVPs(7VbB3_KxQzo1Wq{VsqK0qtL^N%8-^UonjR6e*ccD;aW7xy7O=tT zjD%adjA=MSnPZ2?iHVC|XnJr=Iyi|b#X-`qEy2n%asEY@qb_0{+TB}{=6bBL|F9!Q In32I60Jj4>5C8xG literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/autocommit.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/autocommit.gif new file mode 100644 index 0000000000000000000000000000000000000000..32b77eee23246aea9b62b83c954d325b0fcc14b2 GIT binary patch literal 207 zcmZ?wbhEHb6krfwSoELa|NsAI&YVe0o0*oD#=yXE;J^VO2?UBiSr{1@SQ&Ic9FSTD zX2*zKcdP`2jw;SgSU;E1LI-S4U18C|$f9L#y%A(Blj1mPS0|Ntvq)LV0(mVy<%;ci{;>zNZ z)ZAhn1<$->Jq5>{9EBi|!eWJ>)Z)~lveXnkUM?>mHwE_~g|O5j1w%apUM>b}0RJ^a A3IG5A literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/bigtable.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/bigtable.gif new file mode 100644 index 0000000000000000000000000000000000000000..b90c043b856311e3a5aad26a4fbf5dc63d66544d GIT binary patch literal 242 zcmZ?wbhEHb6krfwXl4L`|Ns9R7$n--=1rVfta-~d<>g$OUTRQ$=p z%)r3Np!hGqIlrK?C^J2yM8U|wz(66XQX#lBPr)}cxhTK5vbZEQw^&EPGcQ?B!7(RC zAqb?fSRp92IJKxOHARn?%ge`2!97SJEVW3%P|tvui-AE0WEsd^3@qLTCp=fnFugu= zT;#lSi>rklQ_)1V-#l3t&PKmsZ3*$HWbkH^_1D;ZF=L}b-wp5B8As;lI6uA7)_C{Q Y^p>>7V_K$S4l~Zb*qrLy$-rO@0P&Dd8~^|S literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/bookmarkfile.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/bookmarkfile.gif new file mode 100644 index 0000000000000000000000000000000000000000..0684ffb91062132cd8c087c4d03fb8ea5d5060ec GIT binary patch literal 933 zcmZ?wbhEHb6krfwXlDR{sHmu*;wT1&27CMc3=IEUfM8C`93a>_XYbyxlf-y{r~?TtZ$SU4S^va0*XIbfPVPTpab#=C{HkOG%+Z1h-5G{G&Xav zYxM*OG&nIciV2mx2vA^R7i4F;!NG8-xr>XbBjkmE6APO>yV;2q9~r%-h=%Lwyx6qN zc_x!(-WpEf^mDB2EDR4g4?I7=z`1%;4?}_@(*h@Rw+|~PCo?cJg$qd>n7XiOeZoOE aoefhLp4gmWEGD6_ajgSWo+uj&gEatg|4_C7 literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/bookmarks.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/bookmarks.gif new file mode 100644 index 0000000000000000000000000000000000000000..137b3ca6c0de8741b010c454c28b4397306a849c GIT binary patch literal 238 zcmZ?wbhEHb6krfw*!-UX2>$>7A6^{UFsG?`UhAx_bCw@kx%2AoV~z4jcd~R{Y7r$iTqIpaaqgGJ}D|cPe| z-X=UfB*je|NsB*2eRhRZ)j)$vN3_;PZmZ7 z27U$|1|R^L!NB7G;iTtkQ>E95OBGx_cs$a17J8J$TX7w4-L)iftCkMGjlRORQ|%56 w3~Y@NPhCv->KspPsPH*8%l$=eLP^y2y*wK}^UPrGn2}g(q2M*Qf`!2v0Iirzp#T5? literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/close.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/close.gif new file mode 100644 index 0000000000000000000000000000000000000000..fed9c3baf7e637fc77f82a7fa9337d13b6082212 GIT binary patch literal 155 zcmV;M0A&A1Nk%w1VGsZi0OJ4vx3{xw-%U|NsC0EC2ui01yBW000C~5Xebu03z$XuLxi$dgNf9C`J-Q!Llx) zszzZO^*w*bVgH5RE`TTki-=)j30x+I3I)&>9WH*0t8Fo4FbZBTm@#aa&*)ucz2mqu Jqj)?506R42Nvr?> literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/column.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/column.gif new file mode 100644 index 0000000000000000000000000000000000000000..1c1e2d4dd081627b1cd93787ef5f583282400fca GIT binary patch literal 219 zcmZ?wbhEHb6krfwXl4L`|Ns9R7$n--=1rVfta-~dnxOn}rtK?8&0 zPZnkd21W+Oe*w<<1(ija=@}&oMg|533Q3g;!KHZ$zM08I`NfsRC8@c^Itre7$$AQo zIXMbJAce&WL8-;5MP;cedc0g-K5h!`K?-51MGA&`2E1Gh3_2iNK<;8-F)=vdxq5BV zlj!5sOox0AnRg^F$b6yUk-o}n;ha=m^9w(}uChJ7YTB=(LAx0)Zsm#+2uRmrVz34P DWNJqK literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/commit.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/commit.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d31c8b2ccd48d32acf35dccf6c5689a38a04a36 GIT binary patch literal 252 zcmZ?wbhEHb6krfw*!-UX2>$>7|LN1G^XJbWI&>&6FE24Mk(ZbEz<~oGISioqlZBCi zfrCK@Bm**ofhA1fq-VA*!)u*&8cq`!8w*M{0EOIEKL7v# literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/connect.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/connect.gif new file mode 100644 index 0000000000000000000000000000000000000000..41ca0bc9b1ceca98ebbc9f48a2018f531130b641 GIT binary patch literal 902 zcmZ?wbhEHb6krfwXlG#H;o%7l4J|J(Pn$V&+O%mi&zw2)|Nn#gj~Pb6Xb6me5K#Qd z!py+H&Y%PGD=1Gea3nKuvsgH6Sm4+U%pEo-CL|nc<>j|y5m=CPgqewn#~@)r!+~xF zE*=R>A%`OqRM>5DIyNn7oG8G}q%djJA5KU}sV6X-Nm%}vF literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/connected.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/connected.gif new file mode 100644 index 0000000000000000000000000000000000000000..f97ce626da0dedbba3daaf6850090956c2e0d3a7 GIT binary patch literal 152 zcmZ?wbhEHb6krfwXl7vG;NS=^u?Zkf|EXX~7$$JXw>w)fccb3pJP8&Leo!oa}r zpFsym0!POe#dY}KkGD^?s@x^&;7MZ4!O*g13N zCI$wE0|yQONeEE<$->CMAj6;o;)3jSVD(Z^?@O`FYiQOAS&*l?Dz_xJi=knc$F&7Z zX1!H&iVf(MWENu%DC4`%SaCXX?U6Sxz4j^wUVCSzkbIHBchlvkLfpZ7ly9ljWOphu zDE{+z&M&Ae%1qBFQ7|$vFi=RUR0uB3Q}E49F3K;iEG|jSE!I)+%uCi&aLmb32m&cA jRtQQhPAw`+P0{1!^73(0a1T-lOD$3`)HC4aVz34PxRisX literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/cut.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/cut.gif new file mode 100644 index 0000000000000000000000000000000000000000..14b73a8577fa6d300ddf6ea8b1f999ee214f822f GIT binary patch literal 652 zcmZ?wbhEHb6krfw*!-UX2>$>7f8f9Y1A~bb6<0oe`ZRs|^scThUS3|190pMQ$->CM zz{H>fk^z~)z~U2d!c&`dMF30F*_kX^q2&@m*CU&xW@yZoJbt3Z&fz(Z7ByO z1ey5?m=t(8wA4#99k?d#JZO4kirf6vC%rW#+BF*w8TmflsKj9X_S)5#ckjHvdGqFy zB};HQ1MV(}dl-@2!&Z8rp}<3jFZ;xjO<`*;&by$#m`%aTP~GRvR43on?ovL-E~bPm zT0eDJ=hhh23GT9KxkigapE`?M>1(Q~D2mC}GMe&qb$5rjdr$DGW0*2^8be+}Q#C{^ez5 ze}4ad_xA0+y?cQn{QLLsZ{NNFgZJ*;yX)7lcX4rncn#uy1|;{hPiv@eYHn#|s4wRi z?CR<6>!=qLnJgkOb*ccrz=ZO=n&AB0vV7Juc2<@NRrw2Q%IfQut;n9Uc73^0-RA05 z`Rh8Al%?vjt5=qH?B8)nUaXGAWz}{iIjOUf;&ppYlrO12BX;9f>8hn$uHURKy?CcA zo0Yx((JPnARqxr4ZunB^G-ugSJ^{rI>*VD;T7~#_F+b=#+%BNZ#>Alb&)+$}pt2}4 zJ)=ay$iTorA*oU!xHM0}H#4~?zqqovBsI5KN5L~MSx><+Cr2R&q_9{aD784Xs4O)_ ZkC)5K$4$XKNFgk>NWoCgfR~HG8UX#k=(GR; literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/delete.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/delete.gif new file mode 100644 index 0000000000000000000000000000000000000000..7f506218aef6a12446aded5188db5c782cb61e05 GIT binary patch literal 143 zcmZ?wbhEHb6krfwXl7t&VPKeJX}Qw9(9B5?Z z=Vr19Sdi?_ASs;lC4wR4#6)?{7Lk{N42;a$ybKyYH!Wabmf+vj;u+A;)S|}w$>)J_ t;_*5B-AWlVFETJL_K`pJ#KY)?<4hH9h1wq?4cA+korNT<%aR=!tN}KeJwgBg literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/edit.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..f56a27e18cb6b099a14306d402269b5fe080e49a GIT binary patch literal 441 zcmV;q0Y?5uNk%w1VGsZi0M-8h00030|NpT;RK8AOz`(%T*Zj)J?9R;a&CBo1%I@3Q z{n^+1$HnT)$?n$F`PbF@ySm}U#O%k$?ZLq2zrN(Yz2n5g>BGY3&(8GJ)A-WS_Rr7% zuCCUyve~h**uTH$!NKUm!|Kq`_Mf22p`y&Gs?@c%;Iy^gva{T;u-CY`;g^}iqNL5J zs?){BM$*$$xs6TPudU|1y7Kb!!^6Y2wziLtkBf_oC@3f!8ygJ`4FCWD0000000000 z00000A^8LW000C4EC2ui01yBW000JqK!R{cED8ZSq*7O-<#4xvP&W%ytAIca7sJht zfmLgS0&DrSsf7+8V!t& zY=jaM83_u2cY|OT4hWwwp+!^=2L%k5k3?Aq3l^|es!M=5HdRJeRyb={Mntj2$i+bb zA^uN8Z*X~XX=iA3ATls8Fd$-iAX9a2AWdmwa&L2ab97~Gb1Wc9ZeuPWL2PUwQfX&s jbaNn5Wpib6c4cHP4GKz3Mj%I0AXa5^ATcg54GI7|8{5iM literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/entitygroup.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/entitygroup.gif new file mode 100644 index 0000000000000000000000000000000000000000..8bfe5933f4c3f35913b6c76381df7057b1b45518 GIT binary patch literal 169 zcmZ?wbhEHb6krfwXl7tAG)%U%%nmA!ii)xX;+7VMDN~NknNvMy&bhsFEbr~L{C{uG z|NlS)1&Tje7#JA-Gw1+Gpa}vD3@l+API_kZGQ8%=&}>jpSft1%ywSi>bCT0_k=KWE zXN4GO-;xk&adCTmvc?e`U)EDY8FAcRN& literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/export.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/export.gif new file mode 100644 index 0000000000000000000000000000000000000000..c501e517774083e6f7de72163e008ff5ac843a3d GIT binary patch literal 143 zcmZ?wbhEHb6krfwXl4L{7E8-HmQiyotM^*Y*}M1N-v4-k;!hT41_m|;9gtR#84N5o z7fyJt-g~2o*XZfI5T57=j-ctHjjDUrc6hB9;9wElEVAx#M7#h1 literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/filter.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/filter.gif new file mode 100644 index 0000000000000000000000000000000000000000..1492b4efae265051c43c5f2870c1f71f97c899e3 GIT binary patch literal 159 zcmZ?wbhEHb6krfw*v!CSZy#S@Z~y=Q{QLL!|G#g4f4+Tvy#4+Q8p}12WsEYxhqZ46z5UO4 xC{IX5qW?tG!t@NQxhzk8CmDO_&kQNvl+j$RV9uyFP1Eu=fc2X4FC}0Hs=5U literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/fulldata.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/fulldata.gif new file mode 100644 index 0000000000000000000000000000000000000000..3d1c062dfcf4c8a5408d29245e3d9ab910fce173 GIT binary patch literal 111 zcmZ?wbhEHb6krfwSj50!A75`@KmY&#{|yZd@$vCM1_Kx<{$ycfU|?m?0r5a;8JJBX zcHQ}xf5Ng;TIqF;G@kTUdp?UMphZjfw2LlEM2F0H&j0_BH3_3tIP^AC^ z1G8<$t~>t>_A#tjdw|i2O*|&RTb!dTv41gEpJy Ve8<_M(yc2>v{pu~?`C1J1^~LkD@*_Y literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/grid.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/grid.gif new file mode 100644 index 0000000000000000000000000000000000000000..10b0d034e4ad380335c6a20ad3dec1a6dec72b83 GIT binary patch literal 152 zcmZ?wbhEHb6krfw*vtR||Ns9tFi5nu&6_y!(7bu)PoF$_+R#l(Mep;RJ(!GAx14jRm(BENX9xGEFLs)=RRnv*5b9 h!K%lio6VZzh~s)|mKWa}4m=nCSFhL9tfI(Z4FD7vOr-z- literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/import.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/import.gif new file mode 100644 index 0000000000000000000000000000000000000000..2191d137185daf69bc228709faa765cfe339a6a6 GIT binary patch literal 141 zcmZ?wbhEHb6krfwXl4L{7E8-HmQiyotM^*Y*}M1N-v4-k;!hT41_m|;9gtR#84N5| z7fyJt-Ww)TbNJa*wy=91oepXo2Td4OZrsG=xJ5|jdb#X_U9k(wnSa)}J<2($a%)~d PM#Ih5EYPI!8FG&D5i0ArIhbN~PV literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/keycolumn.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/keycolumn.gif new file mode 100644 index 0000000000000000000000000000000000000000..65564f8d900bf089ff2726e50cf03a397dcd5fe7 GIT binary patch literal 251 zcmZ?wbhEHb6krfwXl4L`|Ns9R7$n--=1rVfta-~dnxOn}rtK?8&0 zPZnkd21W+Oe*w<<1(ija=@}&oMg|533Q3g;!KHZ$zM08I`NfsRC8@c^Itre7$$AQo zIXMbJAce&WL8-;5MP;cedc0g-K5h!`K?-51MGA&`2E1Gh3_2iNK<;8-2{B*^&QdhW zZvM=BNFdEEv*_Rl8z!Z>YHDkmtq-oyxRv2{Vv^L!PoADpvz!)iT)L^^_3Xiqm?-0> k1k+odtrOu1rbDYF=o;(BkZ3Nly&0C-(fmH+?% literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/log.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/log.gif new file mode 100644 index 0000000000000000000000000000000000000000..07fdb5afb6c4d004bbd366a4710e7e48ebc91e2a GIT binary patch literal 164 zcmZ?wbhEHb6krfwnE0RJ|Ns9C3=9Vj8~~DvKUo+V7?>DzfNY?w0FbRTrGMq>hy2Y< zTcR2k&HJ9lTNwMbvCkr@{pW(@%w4k1*S#4T6#w}<=ND8KWu|A8C>R+S7$_uFDg>A2 zDfnh47v&dM7MG;v7V9W@<|XSXIOgOi1c4M5D+Hw$rxul^rs(lKX8IF<1itb$>Nd literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/missingtable.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/missingtable.gif new file mode 100644 index 0000000000000000000000000000000000000000..f9cce7151f542953e397a92ea6a1b27a90436cdb GIT binary patch literal 256 zcmZ?wbhEHb6krfwXl7tAG)%U%%nmBHthThAGUeFPrPuaaTJDXCI(F>Xy}f(?Gcf$G zuKte%6#oS{=ND8KWu|A8C>R+S7$_uFDg>A2Dfnh47v&dM7MG;v7V9W@<|XSXIOgOi z1c4M5D+Hw$rxul^rs(lKX8IF)-*b00GE73@nKgPI|89VR(J! zFiVp|i>n0}L(xPvZ5FM|XQSU3wuE?CGJ7+~`fF^yn6auQai`Cl0*9%M8v}GC+U|W$ v-yyf6d2z@`TMf4Ja?{Tk@NWrRBfjUN$I39Br1STUr!Y6Naf%5GGFSrux>930 literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/next.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/next.gif new file mode 100644 index 0000000000000000000000000000000000000000..d25a3f956f88b2044da971544cb110250a9aed9f GIT binary patch literal 183 zcmZ?wbhEHb6krfwSoELa|NsAI&itP_^9%z6!+`?_fFuMc{$ycfU|?a;0dYZU8JIOa zcHQxNyjO5hObAEy!h3U#YVMe3EiGwEYhZdSoxkDLrH2+*Eam?>I59CO{_}UvFQ_ca zOwTA$FfuSOP)Mp&2rkW2@Xbsv$}g@gE=kQT)=}`xOV(3x%*jy*0x2w32udwZEha@(Dg+pZkic;(QBGeEFs^_kskPVZTBc)M&EOD8uhozyV5r+Q9L^_14KzJ{W-w6tVH!#HDO1_p)$2Mz#9G@$sC zg^__ll0gR~4zkmMH6%f;FU2#d!AMr{V?;w|SVQ84X)_nDyTHOTL(iF+LF;gA*P8J;WME*RkW{GQdq1I hlv#QVz;|l4QFS5>n!?y>au8bK$sWMfPenZ z`303lnduoN3PuJ71`0`)3c;m$3ci`iMft^*#U-h^#X1U}dC7VTjyX9BK_G?23PGvG esYPX}DSEtIUOsLL?m-G+sYMEgdIr2)4Auan9z4|m literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/previous.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/previous.gif new file mode 100644 index 0000000000000000000000000000000000000000..f48362d71c2820bfd6d39acf401b88fb604b3c9c GIT binary patch literal 183 zcmZ?wbhEHb6krfwSoELa|NsAI&itP_^9%z6!+`?_fFuMc{$ycfU|?a;0dYZU8JIOa zcHKGmc(351m=F%_&ur7p8)6sqF8mpLYC&$!@1ln?!tW|~zwo=~5XQuy_|M-tzo4=x zGd-h3!N|bCKq0A8A-FV8!8bFxD8IO}xFj{VSVzG#FIi8)F(*eM2&AxBAt<#twWusL aMUR)u%g0T@JxC!ewMfBG&w!VU!5RQ4a6W+m literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/qmodel.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/qmodel.gif new file mode 100644 index 0000000000000000000000000000000000000000..52ab6dbd0511aeac0bec5c7d07fca294f5c19e4b GIT binary patch literal 941 zcmZ?wbhEHb6krfwXlDQcMn*;^CMGsEHhzA7QBhF?gG5`~y!iO|@Z!jXgoNbe5I&902gty3RSPbxynawz;ZvvpWB?)x{ZSHv6(})@gUhA8g?4E+GedfpOPpb!w}vAm4g%(B&?a(u8WObcDtk4 z-wm~fAz1;H#T?d3*s!@uv%K5=+3S^l{5G9E+uTV(L`9OoD{5=6(d}*3yRy@f%T0^X zG*%H6Q?)z1)nJP@4U~j<1&Nkm^F~E4)=i_8WQ7FK0x&4aRCs$wXzOZKDB2`N*PzG) zBLR*8RbljPRQkr%OwrQB6359jkS#EhKsUiakT5{#{kI_T*S`y*e=|*FvQqB(i+tX- zFYDgl=jlH%aB%RD_wW&4=BRh**zoZae*ehm$y28Zm-o!sv4Qb(6M?|_3!aO_C5B6z?G{r*T9u=&t9Jng>T%PBX7-1x2LE(pC%UW(u+&E$$OD#$iEbe#g`MgmDT&v zN$V1Po%%jx0y#9gj8+;ukHlJ=d`pd%1Fji>$}gMyAz@{1&MS4Gc|<@$6en48)R7&B{x^ M)zf_?*MY$r0I;n>?*IS* literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/rollback.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/rollback.gif new file mode 100644 index 0000000000000000000000000000000000000000..8fdd814c2f412a1d3de25534f056137fc26f8f1e GIT binary patch literal 201 zcmZ?wbhEHb6krfwSj52a|Ns9pXa3Ked4_?3;lP0dKoSBJf3h$#Ft9M_fVd#F49wOZ zyYAe3d{R(#p-Br@`!%N%nsEa2lv226a2U+vX1KyVySetI_nD}@qHUi()CTc!bsbH< z(02A%4%Zqr1_s4{{?7RYl|`B986^rv1_lNSNtFu0rFjaznaM@@#g)Y+sky~E3Z8k% sdJ2v?ISN4_g~bX%sl};9WvMB8yj)&BZVK)}3Sp^53Wj{0H3u&+5i9m literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/sample.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/sample.gif new file mode 100644 index 0000000000000000000000000000000000000000..34fb3c9d8cb7d489681b7f7aee4bdcd7eaf53610 GIT binary patch literal 983 zcmZ?wbhEHb6krfw_|CxKYUg-n!?izO{@9*?jxd%4aX0yzy`dymabz zw#(eg=y~&N&n)dZv2xzduG}5lraiApo3(c4*{Ylg5#|$JO_EEZ<^|a2`Z*=9ns7DV zy=TR&gYw*7f%auV?ip3tvjRPmcdoho{K?x$_vR?C#t5&<;~V}S*>OMCr>h}%%bLZ9 zmo3`hYEwTICo-TTCZwgTsC&VjZRgJ1eE#fBa^%9R zmmfWS@;bnyJ27HWY}kxYzv(Hl>yu;FCPlAEh+34Muq-8Rb6C)<8qA3{r2e5 z`$vyngh#H=FWlqqvnapfc5%(!sQ4v?r7J61-&eJNEN^;KTK}T7{#i-gJh%G*9vcYdwv_*~xdw!Gz4Va?T!sXyyF@8?w<>X`X=#j%uHV4GRvj@+tE@ zQ%F!a)GKcn^~8abN>4la1UNXVL;{ZWi)lEwyeatDu%Lr6;aASiLrXXW zQm#H|%L^t(99R>iC{eMurC^4ap1%@$>7f8fA@34PlaFFZGO^6rNERrPhtr%gT5*1CSy%;OXK zceS;ynK$>;)G7OWd$#s;Z=N=F|DuKGCQsV6VE(E3^G?p0ePrg00~04~+rI7TvZWX1 z%s#wg`Nd^R&(E8CbmNBG>(<^_wes?^rRSC`KD}t+$=S0GY}$Bx?V77wx7=H^`ttT| z_gAhsw|m#)O&f3Q+5LFk+Dkik+&^{lLwozy>guH}EgSm#_jY&hm^g8NN5`hAQxA1_ zZ*6biFk!;3o}R7q=bxE5^T>=Dhv&>WK6UE8<;$-uSa5pQtRssSot-!D#PsR=dwMob zo3?kwic8CuU0AZ@?5b5)_Uw7Ne*MkWtFIh8_GRCuwZcJ zO)%lJatFo%$%OY2Sjf$+DV%ppGyhzJo>tkk? z(C`dma$XkA)T4T9g@>@BA)`YVPv^x6CmkCZ7!?2cJLeZv7Gr%@o#UnC*B%^NjsP->pTQK2imx$_?CCjEA QzB`L8e#(*$stgR)0M05bwg3PC literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/statement.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/statement.gif new file mode 100644 index 0000000000000000000000000000000000000000..1c65a3b1a7182f1461315032faa66b360bb361e0 GIT binary patch literal 152 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 DM5-^g literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/bluegroup.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/bluegroup.gif new file mode 100644 index 0000000000000000000000000000000000000000..105d9373d737c341a884de916d978d7ae86ca299 GIT binary patch literal 157 zcmZ?wbhEHb6krfw*vtR||NsBLb?5GdOP3EEI_#5IYY`Y@Qrw$6Z*$l2heDysCywm{ zDgY}45sE)q7#SFN7<51!kQodtUK37wuHL&nqcQ!X_jgs5#hGo6qA9P{mVH0Rny$1t znrBksleMw$8xB0>v1xnnpkr0Yc4&gjI(pM%o1W`um%7w CuRsU@ literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/green_group.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/green_group.gif new file mode 100644 index 0000000000000000000000000000000000000000..67f2f04af91c3ae19f1d556a69b1e4c6ebff58b6 GIT binary patch literal 159 zcmZ?wbhEHb6krfw*vtR||NsBLb?5GdOP3EEIxG~b?2=%X(hyd^D6e~C<(ga5LMxn4 z9NPy}16IqR_>+Z^fq|Dn2gC)L!NB6P;iTv4z2%vW&p-Km*GyTQ+2*L5@>*-z_jBCo zYMXcSOlo|h%e+3(LZ!em@qK}V%zXFO#tkV^>pNDu6nItcWqlQ9pfQ~@qa^+8G8YC0 FYXA;1Kt})o literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/green_schema.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/green_schema.gif new file mode 100644 index 0000000000000000000000000000000000000000..621f5000daf9f4deb4052d4f7aa518d53406bcb4 GIT binary patch literal 152 zcmZ?wbhEHb6krfw*vtR||NsBLb?5GdOP3EEI&2$c=aOJ%>a4fs*0j(HXP^{V34&1k z$->CMz{Q{g5(1gQz~UNk(o@^lBD-ed{{$tUPFKmt%hcK&H8?etPkub~Eak?eYya%$ pJ#o;H;%|-4U;6Tl9cQZM@`8y52i62BN>uD^DVX7<=dZ+I4FGtGHMRf% literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/green_view_group.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/green_view_group.gif new file mode 100644 index 0000000000000000000000000000000000000000..c3fcef0a19af268b722238af0dae08c7a1098a2c GIT binary patch literal 254 zcmZ?wbhEHb6krfwIKlt||Ns9tFi5nu&AWBy?uAR24;(tY?8K>)A3yK7dw=KE-NzoC zsGnSY;@G~E({;|xF+4g!YhJG4p&qq0DI$BbW%>E}f!e{wU?&uRvM@3*h%xAZq(OEv zuvRZn?Mtz=>wheu_A`Pb$u zQlMnFw@V9yr-~LAWAa%E4TeWfmC-+|SRZ;gE;3~nYv2~;G_0zr_3>s%;}m3TXRqy< f+{a=sEG#%{_AF*LF_wj_ix;ykTW+>ek--`O#{XBS literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/key.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/key.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ab7f3481a184cc9b9bef1773ada217f290d37c7 GIT binary patch literal 155 zcmZ?wbhEHb6krfw*v!DtFsEtO);T+`?mqVDL_+| zz`((v1Cj!n!NB4n;F%mS(c--2x^tn15_hL}J`R}GsxaYI6h5EYPBb($my933+@+gGjPZmZ7 z22KVYkSNFu1{ODilb+eG8j{tjO483WkBE1%1+Ge;x=yPwB0omtmCx006L+tQK4*Tx mx2A>ZlYs;W!&KGFng&4~K8~SNW@N3Mb9j0+>ttO)25SI->@t1; literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/margarita.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/margarita.gif new file mode 100644 index 0000000000000000000000000000000000000000..77cd2a3f5c9e9411cdfd5966181cb253ba3ccb73 GIT binary patch literal 152 zcmZ?wbhEHb6krfw*vtR||NsC0x%2j7??sKa4L^7O`1ki8Gcz+#5G;vKDE?$&WMJT6 z&;dz+%wS+~6*%d+dhN4QHoltE6(we>b4>pr`h4ZqHwTpt2W)lMyRt`j<*GXk20B4D kZOkj5&z=*ZeUJBsQ{;;M*Gg4??pPMQI?ZRF3j>2S051MFJOBUy literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/quantum.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/quantum.gif new file mode 100644 index 0000000000000000000000000000000000000000..e964a2fd7aa3f316e6a7221241ca9cdaa289963f GIT binary patch literal 93 zcmZ?wbhEHb6k!lySjYeZdl{UvGuLKkZq)(tK;jHcW-W%xPrucj$5QB|x@oD}YuU=F ss(sM{H36NAmhR-q-5_~*?zIzZ{l4G5`G?PdU0|`dU6<*yO$-dy017c6e*gdg literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/sequence_group.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/sequence_group.gif new file mode 100644 index 0000000000000000000000000000000000000000..16b07bb143cb4ec318a8e55d49cf77805b077a94 GIT binary patch literal 248 zcmZ?wbhEHb6krfwIKlt||NsBDwavSA=kA3|mk%5|oY|cdUL5)F&&=PSdjGv^`S+yc z#Ib$fF6aEYm~?Ww&bc{;M<-~_%N0D-qqZhRWN)@CP&?Qd?1bV^7DfgJF$NuwG{{Z{ z*3t#4eJPes7e4c-aYlM3x%y=9_2`QTj{hqvs3K-8!*^tcs)deJ|4EnB4*^H|jysn8 ziV)b?vLZzwQ-HmB!wiAK8N%luZB$hBxx;+;^Md2o-t+QCuroI^3$ZpdCNvdyFgu8d Z2u+zfg^5)xBa>w=3+sY~W{VXWtN|A$TnhjI literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/subset.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/subset.gif new file mode 100644 index 0000000000000000000000000000000000000000..ae12ef235046b75550c60684ce077994b81edc53 GIT binary patch literal 621 zcmb7>>q}E%0LEWUGKkP5N+<}s5#)8kBJ66uE^sIC8?hlhvXm*@HNoGp}!a}~)T8AJe> z^043Mml)b@GWjhQ-elrzHfr3AG(+^zFg2Q3|$M<)EvczA&a0837|zc zzd#EMv>(Ii8J3Sgp1{aF!(+&YAun)VA3Hrm3sFW<>riwGL9Y*DqQhi_5FJ7~5(9`a zB*cjj42780RlKsy;4maehhw(zAw~#B0e+ifek^mLAWIO$h!H{*AEYAD@c=#hm71U9 z2;%r4x3awS=bym;DD7858~_aO**Q5GS6ZJp ziN*POCl4Pwt$HacC@eg8wYXSb)h8048aQ83Sy`cY)Y_b@Eh@Vvlh@w4AE!KW^!SP5 zn$nB1I?sbMn-Z!eHzk*9E|g#Q)J^T*r#x`%Vae_K`Wu&br=@Pd%7f|mq<3#g<2NU5 z+xU|=mnp!+tDVWet9s>qc6Cz9jy>*dg)KgDSCLqT8}l1mwwI=ZycD~7-PY81)t#t7 b`a-q7RzAw^ZRu8RdE7f&ZZAn`1VHi^WEWog literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/table_group.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/table_group.gif new file mode 100644 index 0000000000000000000000000000000000000000..0a852e085c02cc6c08bf590c79e2fcf95d2d8e52 GIT binary patch literal 252 zcmZ?wbhEHb6krfwIKlt||Ns9tFi5nu&6_y!(7bu)Z{4|j;nL*;hYp7qNB;XW^Y^FT zfA3oUJt;YHY~Q!bIe#uDot&<7ZjRy630m`V1rPP8tw|Btn=K181Z)^Oq4<-9k%2*i zK?fuOvXgFzv2^J+;x(g4j*;ckYmK!-K}^i zKuxG6`ytm^Sa91?8v*%vP4ShCb?xgvu#08+DHE&u=k literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/view.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/unused/view.gif new file mode 100644 index 0000000000000000000000000000000000000000..649207f2ec78aa50ce544e89e9c7a3ccbae105c6 GIT binary patch literal 149 zcmZ?wbhEHb6krfw*v!CSV325Qo451o?qiQm)K9Md^Xu3D|Nj{n7$78&fd&+RvM@3* za4_hA#6e~-us8{v^jy8y;8frVDnH2#h)yU z3=EPCIv`PyoeZqi32J>QmTrP9f@+efU6VZhXYVbX6S(JT^dgTuj}V4d%QLPk&qQ)e zc=*)8HepV{u_Q}@lHF%H9WO;B@HMqq8E(*0WBnxd`775UR)EXEv(^v-Z~e*Qd9} uD>PhIpOLX@ZTjurG~Mj4TE`>zecpLMf7#&zD}#p+|z`((v z1Cjul!NB4uaME-2UW?bd{T~-Jc3w@aJ*=?ejr&X{#q-QbER!wHY;KU*!KZXg`AVL! ef7VfvnkLKB3j-$9t(*5s^}t&v%LE@525SJ7f-pV+ literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/icons/xml.gif b/archive/net.sourceforge.phpeclipse.quantum.sql/icons/xml.gif new file mode 100644 index 0000000000000000000000000000000000000000..1dff5505c85ed0f0619887499c8699a8c2080677 GIT binary patch literal 159 zcmZ?wbhEHb6krfw*v!B%Z{GP8D{k)D^LD|JRa$Oe)Sp!k!8k%57SK?lSInZdx~Ght(ER;-ctmP!9Pml;k^n)S#d&gnJR%WW(r zvB$+1ym#0W+q&R_dz4JyiN)`eGOVU|Pv_2B{m5dE?8Qw2RSR1-MAXFcoO^Nb+M#s@ HN(|Njq(Vp( literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/install.txt b/archive/net.sourceforge.phpeclipse.quantum.sql/install.txt new file mode 100644 index 0000000..b05046b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/install.txt @@ -0,0 +1,24 @@ +Quick and Dirty Install Instructions: +1. Download and unpack eclipse 2.1.1 into a directory [e.g. C:\Test\eclipse] +2. Download Quantum +3. Unzip quantum into the parent directory of eclipse [e.g. C:\Test]. The zip file has the relative path + eclipse/plugins/com.quantum.Quantum_2.2.0 So if you have called the eclipse directory by any other + name you should unzip into a temporary directory, take the com.quantum.Quantum_2.2.0 directory, + and copy it into your plugins directory. +4. Launch eclipse. You need java 1.4 or higher to run Quantum. So if you don't have it installed, + you can install it to use only with Eclipse. Install it into some directory, and run eclipse with + the -vm parameter: + + Eclipse.exe -d C:\Test\workspace -vm C:\java\jre1.4.2\bin\javaw.exe + + or + + Eclipse.exe -d /home/panic/workspace -vm /usr/java/bin/ + +5. Open the Quantum DB Perspective [Go to Windows -> Open Perspective -> Other and select Quantum DB Perspective] +6. Right click any where on the Bookmark view and select "New Bookmark..." +7. If you need more instructions, check the documentation (/doc directory under com.quantum.Quantum_2.2.0), and + the online documentation in the sourceforge page (http://sourceforge.net/docman/?group_id=7746). + +8. If you update to Quantum 2.2.3 from a previous version, you may get warnings about not being able + to restore some views. Close your Quantum perspective and re-open it. \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/lib/junit.jar b/archive/net.sourceforge.phpeclipse.quantum.sql/lib/junit.jar new file mode 100644 index 0000000000000000000000000000000000000000..674d71e89ea154dbe2e3cd032821c22b39e8fd68 GIT binary patch literal 121070 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 F`9DH82$KK+ literal 0 HcmV?d00001 diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/plugin-3.0.xml b/archive/net.sourceforge.phpeclipse.quantum.sql/plugin-3.0.xml new file mode 100644 index 0000000..213fbe7 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/plugin-3.0.xml @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A wizard that exports the list of database bookmarks to a Quantum bookmark file. + + + + + A wizard that exports the database structure to a Torque-compatible XML file. + + + + + + + + + + + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/plugin.properties b/archive/net.sourceforge.phpeclipse.quantum.sql/plugin.properties new file mode 100644 index 0000000..b67550a --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/plugin.properties @@ -0,0 +1,15 @@ +quantum.name = Quantum DB Utility +perspective.name = Quantum DB Perspective +sqllogview.name = Quantum SQL Log +tableview.name = Quantum Table View +sqlqueryview.name = Quantum SQL Query Editor +bookmarkview.name = Database Bookmarks +bookmarkview.importboomarks = Import Bookmarks +bookmarkview.exportbookmarks = Export Bookmarks +subsetview.name = Subsets +category.name = QuantumDB +category.description = Quantum Database Tools +scope.name = Quantum UI Scope +scope.description = Quantum UI Scope +command.execute.name = Execute SQL +command.execute.description = Execute the SQL statements against a database bookmark diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/plugin.xml b/archive/net.sourceforge.phpeclipse.quantum.sql/plugin.xml new file mode 100644 index 0000000..e8df2c8 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/plugin.xml @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A wizard that exports the list of database bookmarks to a Quantum bookmark file. + + + + + A wizard that exports the database structure to a Torque-compatible XML file. + + + + + + + + + + + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/schema/data.exsd b/archive/net.sourceforge.phpeclipse.quantum.sql/schema/data.exsd new file mode 100644 index 0000000..765ec41 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/schema/data.exsd @@ -0,0 +1,107 @@ + + + + + + + + + This extension point allow other plug-ins to act on data information extracted by Quantum. +For each registered extension, Quantum will add a menu entry in the context menu of the Table View. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The label of the dataActor. Will be used to appear in the context menu. + + + + + + + The class acting on the data. Will be supplied by the external plug-in, not by Quantum. + + + + + + + + + + + + 2.3 + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + + + + + + + + + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/schema/metadata.exsd b/archive/net.sourceforge.phpeclipse.quantum.sql/schema/metadata.exsd new file mode 100644 index 0000000..25ea75f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/schema/metadata.exsd @@ -0,0 +1,107 @@ + + + + + + + + + This extension point allow other plug-ins to act on metadata information extracted by Quantum. +For each registered extension, Quantum will add a menu entry in the context menu of the Bookmarks View. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The label of the metadataActor. Will be used to appear in the context menu. + + + + + + + The class acting on the metadata. Will be supplied by the external plug-in, not by Quantum. + + + + + + + + + + + + 2.3 + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + + + + + + + + + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src-test/com/quantum/util/StringUtilTest.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src-test/com/quantum/util/StringUtilTest.java new file mode 100644 index 0000000..8e9670f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src-test/com/quantum/util/StringUtilTest.java @@ -0,0 +1,71 @@ +/* Created on Jan 19, 2004 */ +package com.quantum.util; + +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +/** + * @author holmesbc + */ +public class StringUtilTest extends TestCase { + public void testSubstituteString() throws Exception { + + String sample = "This is a test of ${variable} substitution."; + String replaceAll = replaceAll(sample, "\\$\\{variable\\}", "parameter"); + + assertEquals("replaceAll", "This is a test of parameter substitution.", replaceAll); + System.out.println(StringUtil.substituteString(sample, "${variable}", "parameter")); + assertEquals("substitute String", replaceAll, StringUtil.substituteString(sample, "${variable}", "parameter")); + } + + public void testSubstituteStringAtEnd() throws Exception { + + String sample = "Substitute ${variable}"; + String replaceAll = replaceAll(sample, "\\$\\{variable\\}", "parameter"); + + System.out.println(StringUtil.substituteString(sample, "${variable}", "parameter")); + assertEquals("substitute String", replaceAll, StringUtil.substituteString(sample, "${variable}", "parameter")); + } + + public void testSubstituteStringAtBeginning() throws Exception { + + String sample = "${variable} substitution"; + String replaceAll = replaceAll(sample, "\\$\\{variable\\}", "parameter"); + + System.out.println(StringUtil.substituteString(sample, "${variable}", "parameter")); + assertEquals("substitute String", replaceAll, StringUtil.substituteString(sample, "${variable}", "parameter")); + } + + public void testSubstituteStringMultipleTokens() throws Exception { + + String sample = "${variable}${variable}"; + String replaceAll = replaceAll(sample, "\\$\\{variable\\}", "parameter"); + + System.out.println(StringUtil.substituteString(sample, "${variable}", "parameter")); + assertEquals("substitute String", replaceAll, StringUtil.substituteString(sample, "${variable}", "parameter")); + } + + public void testSubstituteStringZeroLength() throws Exception { + + String sample = "This is a test of ${variable} substitution."; + String replaceAll = replaceAll(sample, "\\$\\{variable\\}", ""); + + System.out.println(StringUtil.substituteString(sample, "${variable}", "")); + assertEquals("substitute String", replaceAll, StringUtil.substituteString(sample, "${variable}", "")); + } + + public void testSubstituteStringSpecialChars() throws Exception { + + String sample = "This is a test of \r substitution."; + String replaceAll = replaceAll(sample, "\r", ""); + + System.out.println(StringUtil.substituteString(sample, "\r", "")); + assertEquals("substitute String", replaceAll, StringUtil.substituteString(sample, "\r", "")); + } + + private String replaceAll(String original, String regex, String newValue) throws Exception { + Method method = String.class.getMethod("replaceAll", new Class[] { String.class, String.class } ); + return (String) method.invoke(original, new Object[] { regex, newValue } ); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/IQuantumConstants.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/IQuantumConstants.java new file mode 100644 index 0000000..3f5dc51 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/IQuantumConstants.java @@ -0,0 +1,26 @@ +/* + * Created on 12-jul-2003 + * + */ +package com.quantum; + +/** + * @author panic + * + * Constants for general use in the quantum plug-in + */ +public interface IQuantumConstants { + public static final String PLUGIN_ID ="com.quantum"; //$NON-NLS-1$ + public static final String PREFIX = PLUGIN_ID+"."; //$NON-NLS-1$ + + public static final String ADD_SCHEMA_DIALOG_CONTEXT = PREFIX+"add_schema_dialog_context"; //$NON-NLS-1$ + + //Constants for specifying Tables, Views and Sequences to the JDBC driver + public static final String Table = "TABLE"; + public static final String View = "VIEW"; + public static final String Sequence = "SEQUENCE"; + + public static final String autoCommitTrue = "Always True"; + public static final String autoCommitFalse = "Always False"; + public static final String autoCommitSaved = "Last Saved"; +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/Messages.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/Messages.java new file mode 100644 index 0000000..ed81afc --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/Messages.java @@ -0,0 +1,41 @@ +package com.quantum; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class Messages { + + private static final String BUNDLE_NAME = "com.quantum.QuantumResources"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME); + + private Messages() { + } + + public static String getString(Class resourceClass, String key) { + return getString( + createKey(resourceClass, key)); + } + + private static String createKey(Class resourceClass, String key) { + return resourceClass.getName() + (key.startsWith(".") ? key : "." + key); + } + + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + public static String getString(Class resourceClass, String key, Object[] arguments) { + return getString(createKey(resourceClass, key), arguments); + } + + public static String getString(String key, Object[] arguments) { + String string = getString(key); + return MessageFormat.format(string, arguments); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/QuantumPlugin.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/QuantumPlugin.java new file mode 100644 index 0000000..154604a --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/QuantumPlugin.java @@ -0,0 +1,310 @@ +package com.quantum; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import com.quantum.model.BookmarkCollection; +import com.quantum.util.xml.XMLHelper; +import com.quantum.view.subset.SubsetContentProvider; + +import org.eclipse.core.resources.ISaveContext; +import org.eclipse.core.resources.ISaveParticipant; +import org.eclipse.core.resources.ISavedState; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IPluginDescriptor; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * @author root + * Main class of the quantum plugin, sets defaults, saves and recovers state. + */ +public class QuantumPlugin extends AbstractUIPlugin { + + private static QuantumPlugin plugin; + private Clipboard sysClip; + + + public QuantumPlugin(IPluginDescriptor descriptor) { + super(descriptor); + plugin = this; + } + + public static QuantumPlugin getDefault() { + return plugin; + } + /** + * Reads the Quantum Plugin state from a file. The file has been created with writeImportantState + * @param target + */ + protected void readStateFrom(File target) { + String fileName = target.getName(); + if (!fileName.endsWith(Messages.getString("QuantumPlugin.saveFileExtension"))){ //$NON-NLS-1$ + try { + // It's the 2.0 format for preferences + BookmarkCollection.getInstance().load(target); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + //It's the 2.1 format for preferences and subsets + FileInputStream source = null; + try { + source = new FileInputStream(target); + } catch (FileNotFoundException e1) { + e1.printStackTrace(); + return; + } + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder parser; + try { + parser = factory.newDocumentBuilder(); + Document doc = parser.parse(source); + + Element root = doc.getDocumentElement(); + BookmarkCollection.getInstance().importXML(root); + BookmarkCollection.getInstance().setChanged(false); + SubsetContentProvider.getInstance().importXML(root); + + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.Plugin#startup() + */ + public void startup() throws CoreException { + super.startup(); + ISaveParticipant saveParticipant = new QuantumSaveParticipant(); + ISavedState lastState = + ResourcesPlugin.getWorkspace().addSaveParticipant( + this, + saveParticipant); + if (lastState != null) { + IPath location = lastState.lookup(new Path(Messages.getString("QuantumPlugin.saveDir"))); //$NON-NLS-1$ + if (location != null) { + // the plugin instance should read any important state from the file. + File f = getStateLocation().append(location).toFile(); + readStateFrom(f); + + } + } + sysClip = new Clipboard(null); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.Plugin#shutdown() + */ + public void shutdown() throws CoreException { + super.shutdown(); + sysClip.dispose(); + } + + /** + * Write the bookmarks and subsets to a file, saving them for next use of the quantum plugin + * @param target + */ + protected void writeImportantState(File target) { + try { + Document document = XMLHelper.createEmptyDocument(); + + Element root = (Element) document.appendChild( + document.createElement(Messages.getString("ExportXMLAction.SavedData"))); //$NON-NLS-1$ + + BookmarkCollection.getInstance().exportXML(root); + SubsetContentProvider.getInstance().exportXML(root); + + FileWriter writer = new FileWriter(target); + try { + XMLHelper.createDOMSerializer(writer).serialize(document); + } finally { + writer.close(); + } + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Gets an image descriptof from a file in the icons directory + * @param name of the file to get + * @return ImageDescriptor or null if not found + */ + public static ImageDescriptor getImageDescriptor(String name) { + ImageDescriptor descriptor = null; + try { + URL installURL = + QuantumPlugin.getDefault().getDescriptor().getInstallURL(); + URL url = new URL(installURL, Messages.getString("QuantumPlugin.iconsDir") + name); //$NON-NLS-1$ + descriptor = ImageDescriptor.createFromURL(url); + } catch (Exception e) { + e.printStackTrace(); + } + return descriptor; + } + public static Image getImage(String name) { + ImageDescriptor imageDescriptor = getImageDescriptor(name); + return imageDescriptor == null ? null : imageDescriptor.createImage(); + } + + protected void initializeDefaultPluginPreferences() { + RGB BACKGROUND = new RGB(255, 255, 255); + RGB COMMENT = new RGB(88, 148, 64); + RGB KEYWORD = new RGB(126, 0, 75); + RGB STRING = new RGB(0, 0, 255); + RGB NUMERIC = new RGB(255, 0, 0); + RGB DEFAULT = new RGB(0, 0, 0); + IPreferenceStore store = getPreferenceStore(); + PreferenceConverter.setDefault(store, + "quantum.background.color", BACKGROUND); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.text.color", DEFAULT); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.keyword.color", KEYWORD); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.comment.color", COMMENT); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.string.color", STRING); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.numeric.color", NUMERIC); //$NON-NLS-1$ + getPreferenceStore().setDefault("quantum.text.bold", false); //$NON-NLS-1$ + getPreferenceStore().setDefault("quantum.keyword.bold", true); //$NON-NLS-1$ + getPreferenceStore().setDefault("quantum.string.bold", false); //$NON-NLS-1$ + getPreferenceStore().setDefault("quantum.comment.bold", false); //$NON-NLS-1$ + getPreferenceStore().setDefault("quantum.numeric.bold", false); //$NON-NLS-1$ + PreferenceConverter.setDefault(getPreferenceStore(), "quantum.font", (FontData) null); //$NON-NLS-1$ + getPreferenceStore().setDefault("com.quantum.model.Bookmark.queryHistorySize", 20); //$NON-NLS-1$ + } + // Returns the active page + public IWorkbenchPage getActivePage() + { + IWorkbench workbench = getWorkbench(); + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + if (window == null) return null; + IWorkbenchPage page = window.getActivePage(); + return page; + } + /** + * returns a view in the active page, creating it if needed + * @param view, the name of the view (e.g com.quantum.view.tableview) + * @return true if successful, false if not + */ + public IViewPart getView(String view) + { + IViewPart tableView = null; + try { + IWorkbenchPage page = QuantumPlugin.getDefault().getActivePage(); + tableView = page.findView(view); + if (tableView == null){ + // showView will give focus to the created view, we don't want that + // so we save the active part + IWorkbenchPart part = page.getActivePart(); + tableView = page.showView(view); + // and return the focus to it + page.activate(part); + } + } catch (PartInitException e) { + e.printStackTrace(); + } + return tableView; + } + + + + class QuantumSaveParticipant implements ISaveParticipant { + /** + * @see org.eclipse.core.resources.ISaveParticipant#doneSaving(ISaveContext) + */ + public void doneSaving(ISaveContext context) { + } + /** + * @see org.eclipse.core.resources.ISaveParticipant#prepareToSave(ISaveContext) + */ + public void prepareToSave(ISaveContext context) throws CoreException { + } + + /** + * @see org.eclipse.core.resources.ISaveParticipant#rollback(ISaveContext) + */ + public void rollback(ISaveContext context) { + } + + /** + * @see org.eclipse.core.resources.ISaveParticipant#saving(ISaveContext) + */ + public void saving(ISaveContext context) throws CoreException { + switch (context.getKind()) { + case ISaveContext.FULL_SAVE : + QuantumPlugin quantumPluginInstance = QuantumPlugin.getDefault(); + // save the plug in state + if (BookmarkCollection.getInstance().isAnythingChanged() + || SubsetContentProvider.getInstance().hasChanged()) { + + int saveNumber = context.getSaveNumber(); + String saveFileName = Messages.getString("QuantumPlugin.saveDir") + "-" + Integer.toString(saveNumber) + Messages.getString("QuantumPlugin.saveFileExtension"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + File f = quantumPluginInstance.getStateLocation().append(saveFileName).toFile(); + + // if we fail to write, an exception is thrown and we do not update the path + quantumPluginInstance.writeImportantState(f); + + context.map(new Path(Messages.getString("QuantumPlugin.saveDir")), new Path(saveFileName)); //$NON-NLS-1$ + context.needSaveNumber(); + + } else { + System.out.println("Not saving unchanged bookmarks"); //$NON-NLS-1$ + } + break; + case ISaveContext.PROJECT_SAVE : + // get the project related to this save operation + //IProject project = context.getProject(); + // save its information, if necessary + break; + case ISaveContext.SNAPSHOT : + // This operation needs to be really fast because + // snapshots can be requested frequently by the + // workspace. + break; + } + } + } + /** + * @return + */ + public Clipboard getSysClip() { + return sysClip; + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/QuantumResources.properties b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/QuantumResources.properties new file mode 100644 index 0000000..d0a7e30 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/QuantumResources.properties @@ -0,0 +1,286 @@ +bookmarkview.done = Done +bookmarkview.editBookmark = Edit Bookmark... +bookmarkview.refresh = Refresh +bookmarkview.viewTableDetails = View Table Details +bookmarkview.exportXML = Export XML +bookmarkview.noSequence = Database type does not support sequences +bookmarkview.noViews = Database type does not support views +bookmarkview.noTables = Database type does not support tables +bookmarkview.retrieveDbElementData = Retrieving data of type +bookmarkview.retrieveEntities = Retrieving table/view/sequence information +bookmarkview.done = Done +bookmarkview.metaDataError = Error while retrieving metadata +bookmarkview.confirm = Are you sure you want to delete bookmark +bookmarkview.disconnect = Disconnecting from +bookmarkview.deleteAllRows = Delete all rows from +bookmarkview.deleteRowsAction = Delete all rows +bookmarkview.customCopyAction = Custom Copy +bookmarkview.confirmDeleteAllRows = Are you sure you want to delete all the rows from this table? +sqlqueryview.executeQuery = Execute Query (Ctrl+Shift+Q) +sqlqueryview.importQuery = Import Query +sqlqueryview.exportQuery = Export Query +sqlqueryview.clear = Clear +sqlqueryview.copy = Copy +sqlqueryview.paste = Paste +sqlqueryview.done = Done +tableview.refresh = Refresh Table +tableview.copy = Copy Table Selection To Clipboard +tableview.selectAll = Select All Table Rows +tableview.close = Close Table +tableview.update = Update... +tableview.insert = Insert... +tableview.delete = Delete... +tableview.filterSort = Sort or Filter Table... +tableview.showAll = Toggle Show All Table Rows +tableview.defaultEncoding = Set Default Encoding +tableview.UTF8Encoding = Set UTF-8 +tableview.UTF16Encoding = Set UTF-16 +tableview.QuantumTableViewName=Quantum Table View +tableview.ViewNameFinalDecoration=) +tableview.BookmarkSeparator=: +tableview.ViewNameInitialDecoration=\ ( +filedialog.preferences = Preferences (*.ini) +filedialog.allfiles = All Files (*.*) +filedialog.sqlFiles = SQL query (*.sql) +filedialog.ddlFiles = SQL query (*.ddl) +filedialog.exportxml.name = XML files (*.xml) +filedialog.exportxml.filter = *.xml +filedialog.exportxml.name = XML files (*.xml) +filedialog.exportxml.filter = *.xml +filedialog.exportxml.name = XML files (*.xml) +filedialog.exportxml.filter = *.xml +filedialog.allfiles.name = All Files (*.*) +filedialog.allfiles.filter = *.* +filedialog.message.CannotOpenFileTitle=Cannot open file +filedialog.message.CannotOpenFileMessage=Cannot open file to write : +filedialog.message.CannotOpenFileExplain=\n\nProbably is\'t read-only or used by another process. +filedialog.options.ConfirmOverwrite = y +filedialog.message.ConfirmOverwriteTitle = Confirm Overwrite +filedialog.message.ConfirmOverwriteMessage = This file already exists : +filedialog.message.ConfirmOverwriteQuestion= \n\nDo you want to overwrite it? +adapters.generic = Generic JDBC +adapters.oracle = Oracle +adapters.postgres = Postgres +adapters.mysql = MySQL +adapters.db2 = DB2 +adapters.db2as400 = DB2 for AS400 +adapters.adabasd = Adabas-D +adapters.informix = Informix +adapters.redbrick = Red Brick +adapters.sybase = Sybase +QuantumPlugin.save_2=save +QuantumPlugin.icons_3=icons/ +QuantumPlugin.quantum.keyword.color_6=quantum.keyword.color +QuantumPlugin.quantum.string.bold_12=quantum.string.bold +QuantumPlugin.save_espace=save +QuantumPlugin.Not_saving_unchanged_bookmarks_18=Not saving unchanged bookmarks +QuantumPlugin.iconsDir=icons/ +QuantumPlugin.saveDir=save +QuantumPlugin.saveFileExtension=.xml +ExecuteAction.Executing_Query3=Executing Query... +ExecuteAction.Executing_Query2=Executing Query.. +ExecuteAction.Parsing_sql_script3=Parsing sql script... +ExecuteAction.QueriesExecuted=\ queries executed, +ExecuteAction.RowsUpdated=\ rows updated, +ExecuteAction.Errors=\ errors, +ExecutAction.TimeExec=\ seconds +ExecuteAction.Done=Done +ExecuteAction.RowUpdated=\ rows updated, +ExecuteAction.ResultsDisplayed=\ results displayed, +ExportXMLAction.XMLExporting=XML struct: Exporting to file: +ExportXMLAction.Metadata=Metadata +ExportXMLAction.Author=Author +ExportXMLAction.Quantum=Quantum +ExportXMLAction.Version=Version +ExportXMLAction.XMLVersionNumber=0.4 +ExportXMLAction.Table=TABLE +ExportXMLAction.View=VIEV +ExportXMLAction.TableName=NAME +ExportXMLAction.SchemaName=SCHEMA +ExportXMLAction.OtherSchemas=Other_Schemas +ExportXMLAction.BookmarkName=BOOKMARK +ExportXMLAction.Subsets=SUBSETS +ExportXMLAction.Subset=SUBSET +ExportXMLAction.SubsetName=NAME +ExportXMLAction.SavedData=SAVED_DATA +ExportXMLAction.TableColumn=COLUMN +ExportXMLAction.ColumnName=NAME +ExportXMLAction.UNKNOWN=UNKNOWN +ExportXMLAction.NO=NO +ExportXMLAction.YES=YES +ExportXMLAction.ColumnNullable=Nullable +ExportXMLAction.ColumnAutoIncrement=Auto_Increment +ExportXMLAction.PrimaryKey=Primary_Key +ExportXMLAction.PKName=Name +ExportXMLAction.PKColumn=Column +ExportXMLAction.PKColumnName=Name +ExportXMLAction.PKSequence=Sequence +ExportXMLAction.ForeignKey=Foreign_Key +ExportXMLAction.FKName=Name +ExportXMLAction.FKType=Type +ExportXMLAction.FKImported=Imported +ExportXMLAction.FKExported=Exported +ExportXMLAction.FKCascadeUpdate=Cascade_Update +ExportXMLAction.FKCascadeDelete=Cascade_Delete +ExportXMLAction.FKColumn=Column +ExportXMLAction.FKSequence=Sequence +ExportXMLAction.FKPrimarySchema=Primary_Schema +ExportXMLAction.FKPrimaryTable=Primary_Table +ExportXMLAction.FKPrimaryColumn=Primary_Column +ExportXMLAction.FKForeignSchema=Foreign_Schema +ExportXMLAction.FKForeignTable=Foreign_Table +ExportXMLAction.FKForeignColumn=Foreign_Column +SetSchemaAction.SetSchema=Set Schema +SetSchemaAction.PleaseEnterName=Please enter the name of new schema: +MetaDataKey=METADATA +MetaDataKeySeparator=: +NoFeature.Views=Views +NoFeature.Sequences=Sequences +Error.NoDatabase=Database not supported: +PreferencesPage.PickFont=Pick Font +PreferencesPage.DefaultFont=Default Font +PreferencesPage.BackgroundColor=Background Color +PreferencesPage.DefaultTextColor=Default Text Color +PreferencesPage.quantum.keyword.color_26=quantum.keyword.color +PreferencesPage.KeywordTextColor=Keyword Text Color +PreferencesPage.Bold=Bold +PreferencesPage.CommentTextColor=Comment Text Color +PreferencesPage.StringTextColor=String Text Color +PreferencesPage.NumericTextColor=Numeric Text Color +PreferencesPage.Font_Default=Font: default +PreferencesPage.regular=regular +PreferencesPage.bold=bold +PreferencesPage.italic=italic +PreferencesPage.boldItalic=bold italic +PreferencesPage.FontPrompt=Font: +BookmarkLabelProvider.TablePrefix= +BookmarkLabelProvider.ViewPrefix= +BookmarkLabelProvider.SequencePrefix= +DeleteColumnAction.DeleteColumns=Delete Columns... +DeleteColumnAction.ConfirmDeleteColumns=Are you sure you want to delete the selected columns? +DeleteObjectAction.DeleteSubset=Delete Subset... +DeleteObjectAction.ConfirmDeleteSubset=Are you sure you want to delete the selected subset ? +DeleteObjectAction.DeleteItems=Delete items... +DeleteObjectAction.ConfirmDeleteItems=Are you sure you want to delete the selected tables/views? +DeleteSubsetAction.DeleteSubset=Delete Subset... +DeleteSubsetAction.ConfirmDeleteSubset=Are you sure you want to delete the selected subset? +NewSubsetAction.CreatingNewSubset=Creating new subset.. +NewSubsetAction.NameOfNewSubset=Name of the new Subset +NewSubsetAction.PleaseEnterName=Please enter name +OracleAdapter.._3=. +BookmarkView.ShowTableSizes=Show Table Sizes +BookmarkView.ShowDatabaseData=Show Database Info +BookmarkView.Paste=Paste +BookmarkView.Copy=Copy +BookmarkView.CopyOf=Copy of +SQLLogView.ClearLog=Clear Log +SQLQueryView.Commit=Commit +SQLQueryView.RollBack=RollBack +SQLQueryView.AutoCommit=AutoCommit +SubsetView.Paste=Paste +SubsetView.Delete=Delete +SubsetView.CreatesANewEmptySubset=Creates a new empty subset +SubsetView.DeletesTheSelectedColumns=Deletes the selected column +SubsetView.DeletesTheSelectedObject=Deletes the selected object +SubsetView.DeletesTheSelectedSubset=Deletes the selected subset +TableView.FilterAndSort=Filter and Sort +TableView.UpdateRow=Update Row +TableView.InsertRow=Insert Row +TableView.DeleteRow=Delete Row +TableAdapter.to=\ to +TableAdapter.of=\ of +TableAdapter.full=\ (FULL) +BookmarkWizard.NewBookmark=New Bookmark +BookmarkWizard.Testing=Testing... +BookmarkWizard.JarFiles=Jar Files (*.jar) +BookmarkWizard.ZipFiles=Zip Files (*.zip) +BookmarkWizard.AllFiles=All Files (*.*) +BookmarkWizard.BookmarkNameAst=*Bookmark Name +BookmarkWizard.UsernameAst=*Username +BookmarkWizard.PasswordAst=Password +BookmarkWizard.Schema=Schema (optional) +BookmarkWizard.ConnectAst=*JDBC URL +BookmarkWizard.DriverAst=*Driver +BookmarkWizard.TypeAst=*Type +BookmarkWizard.Prompt=Prompt for password +BookmarkWizard.DriverFilenameAst=*Driver Filename +BookmarkWizard.Browse=Browse... +DeleteRowPage.ColumnName=Column Name +DeleteRowPage.Value=Value +DeleteRowPage.IncludeIn=Include in? +DeleteRowPage.WhereClause=Where clause +DeleteRowPage.UpdatingQuery=Updating query +DeleteRowPage.WarningNoWhere=Warning: no \"where clause\" columns selected, all rows will be deleted +InsertRowPage.ColumnName=Column Name +InsertRowPage.Value=Value +UpdateRowPage.ColumnName=Column Name +UpdateRowPage.OldValue=Old Value +UpdateRowPage.NewValue=New Value +UpdateRowPage._13= +UpdateRowPage.SetValue=Set Value +ConnectAction.ConnectingTo=Connecting to +ConnectAction.ErrorConnecting=Error while connecting to +BookmarkView.SetExtraSchemas=Set Extra Schemas +BookmarkView.CopyColumnSeparator=\ +MultiSQLServer.Enter_Password=Enter Password +MultiSQLServer.PasswordNotProvided=Password not provided in Bookmark +BookmarkSelectionDialog.text=Select a bookmark +BookmarkSelectionDialog.title=Bookmark Selection +ExecuteAgainstAction.IOException=An I/O Exception was encountered while \ntrying to read the input file. +ExecuteAgainstAction.SQLException=A database error was encountered while \ntrying to execute the SQL statements. +ExecuteAgainstAction.title=Problem Encountered +ExceptionDisplayDialog.stackTrace=Stack trace: + +# Actions +com.quantum.actions.AddToQuickListAction.text=Add to Quick List +com.quantum.actions.RemoveFromQuickListAction.text=Remove from Quick List +com.quantum.actions.ConnectAction.text = Connect +com.quantum.actions.ConnectAction.singleSuccessMessage = Connected to {0} +com.quantum.actions.ConnectAction.singleFailureMessage = Could not connect to {0} +com.quantum.actions.ConnectAction.multiSuccessMessage = {0} databases successfully connected. +com.quantum.actions.ConnectAction.multiFailureMessage = {0} database(s) successfully connected. {1} error(s). +com.quantum.actions.DisconnectAction.text = Disconnect +com.quantum.actions.DisconnectAction.message = Disconnected +com.quantum.actions.ViewTableAction.text = View Table +com.quantum.actions.OpenQueryAction.text = Open +com.quantum.actions.DeleteBookmarkAction.text = Delete +com.quantum.actions.RefreshBookmarkAction.text = Refresh +com.quantum.actions.NextSequenceAction.text = Increment Sequence Value +com.quantum.actions.PrevSequenceAction.text = Current Sequence Value +com.quantum.actions.NewBookmarkAction.text = New Bookmark... +com.quantum.actions.NewBookmarkAction.toolTip = Create a new bookmark +com.quantum.actions.DeleteAllRowsAction.text = Delete All Rows +com.quantum.actions.DeleteAllRowsAction.confirmTitle = Warning +com.quantum.actions.DeleteAllRowsAction.confirmText = Are you sure you want to delete all the rows from the table {0}? +com.quantum.actions.ViewTableDetailsAction.text = View Table Details + +com.quantum.util.connection.ConnectionUtil.title = Connection Not Established +com.quantum.util.connection.ConnectionUtil.message = The bookmark could not be connected. + +com.quantum.view.bookmark.CopyAction.text = Copy +com.quantum.view.bookmark.PasteAction.text = Paste +com.quantum.view.bookmark.RenameAction.text = Rename +com.quantum.view.bookmark.QuickListNode.labelName=Quick List +com.quantum.view.bookmark.QueryListNode.labelName=Recent SQL Statements +com.quantum.view.bookmark.GroupNode.TABLE=Tables +com.quantum.view.bookmark.GroupNode.VIEW=Views +com.quantum.view.bookmark.GroupNode.SEQUENCE=Sequences + +com.quantum.preferences.GlobalPreferences.com.quantum.model.Bookmark.queryHistorySize=Maximum size of query history: + +com.quantum.wizards.ExportBookmarkWizardPage.title = Export Bookmark List +com.quantum.wizards.ExportBookmarkWizardPage.selectAll = Select All +com.quantum.wizards.ExportBookmarkWizardPage.deselectAll = Deselect All +com.quantum.wizards.ExportBookmarkWizardPage.fileName = File name: +com.quantum.wizards.ExportBookmarkWizardPage.browse = Browse +com.quantum.wizards.ExportBookmarkWizardPage.error.IOException.title = I/O Exception +com.quantum.wizards.ExportBookmarkWizardPage.error.IOException.message = A problem was encountered with the file: "{0}" + + +# Exception Dialog +com.quantum.ui.dialog.ExceptionDisplayDialog.java.sql.IOException.title=I/O Exception +com.quantum.ui.dialog.ExceptionDisplayDialog.java.sql.IOException.message=A problem was encountered while trying to access the file. +com.quantum.ui.dialog.ExceptionDisplayDialog.java.sql.SQLException.title=SQL Exception +com.quantum.ui.dialog.ExceptionDisplayDialog.java.sql.SQLException.message=An SQL Exception was encountered while trying to process your request. +BookmarkWizard.Error=Error +BookmarkWizard.bookmarkAlreadyExists=The selected bookmark name already exists. diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/AddToQuickListAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/AddToQuickListAction.java new file mode 100644 index 0000000..e773620 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/AddToQuickListAction.java @@ -0,0 +1,56 @@ +package com.quantum.actions; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import com.quantum.Messages; +import com.quantum.view.bookmark.EntityNode; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + *

This action takes an EntityNode and adds a copy of it to the quicklist + * of a bookmark.

+ * + * @author bcholmes + */ +public class AddToQuickListAction extends SelectionListenerAction { + private IViewPart view; + private List entities = Collections.synchronizedList(new ArrayList()); + + public AddToQuickListAction(IViewPart view) { + super(Messages.getString(AddToQuickListAction.class.getName() + ".text")); + this.view = view; + } + + public void run() { + for (Iterator i = this.entities.iterator(); i.hasNext(); ) { + EntityNode entityNode = (EntityNode) i.next(); + entityNode.getBookmark().addQuickListEntry(entityNode.getEntity()); + } + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + this.entities.clear(); + for (Iterator i = selection.iterator(); enabled && i.hasNext(); ) { + Object object = i.next(); + if (object != null && object instanceof EntityNode) { + EntityNode node = (EntityNode) object; + enabled &= !(node.getBookmark().isInQuickList(node.getEntity())); + this.entities.add(node); + } else { + enabled = false; + } + } + + return enabled; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/BaseSQLAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/BaseSQLAction.java new file mode 100644 index 0000000..e651640 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/BaseSQLAction.java @@ -0,0 +1,25 @@ +package com.quantum.actions; + +import java.sql.Connection; + +import com.quantum.model.Bookmark; +import com.quantum.util.connection.ConnectionUtil; + +import org.eclipse.jface.action.Action; +import org.eclipse.swt.widgets.Shell; + +/** + * @author BC + */ +public abstract class BaseSQLAction extends Action { + + private ConnectionUtil connectionUtil = new ConnectionUtil(); + + protected abstract Shell getShell(); + + protected abstract Bookmark getBookmark(); + + protected Connection getConnection() { + return this.connectionUtil.getConnection(getBookmark(), getShell()); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/BaseSequenceAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/BaseSequenceAction.java new file mode 100644 index 0000000..0e967c4 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/BaseSequenceAction.java @@ -0,0 +1,53 @@ +package com.quantum.actions; + +import java.sql.Connection; +import java.util.List; + +import com.quantum.model.Bookmark; +import com.quantum.util.connection.ConnectionUtil; +import com.quantum.view.bookmark.EntityNode; +import com.quantum.view.bookmark.TreeNode; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + * @author BC + */ +public abstract class BaseSequenceAction extends SelectionListenerAction { + + protected IViewPart view; + private ConnectionUtil connectionUtil = new ConnectionUtil(); + + protected BaseSequenceAction(String text, IViewPart view) { + super(text); + + } + + protected Bookmark getBookmark() { + TreeNode node = getEntityNode(); + return node.getBookmark(); + } + + protected Connection getConnection() { + return connectionUtil.getConnection(getBookmark(), getShell()); + } + + protected EntityNode getEntityNode() { + List list = getSelectedNonResources(); + return (EntityNode) list.get(0); + } + + protected Shell getShell() { + return this.view.getViewSite().getShell(); + } + + protected boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + return enabled && selection.size() == 1 + && (selection.getFirstElement() instanceof EntityNode) + && ((EntityNode) selection.getFirstElement()).isSequence(); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/CloseTableAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/CloseTableAction.java new file mode 100644 index 0000000..dc99395 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/CloseTableAction.java @@ -0,0 +1,40 @@ +package com.quantum.actions; + +import com.quantum.view.tableview.TableView; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * @author root + * + */ +public class CloseTableAction extends Action implements IViewActionDelegate { + TableView view; + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = (TableView) view; + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + public void run() { + view.closeCurrent(); + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ConnectAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ConnectAction.java new file mode 100644 index 0000000..05eeed9 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ConnectAction.java @@ -0,0 +1,115 @@ +package com.quantum.actions; + +import java.sql.Connection; +import java.util.Iterator; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.util.connection.ConnectionUtil; +import com.quantum.view.bookmark.BookmarkNode; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +public class ConnectAction extends SelectionListenerAction { + /** + * @param text + */ + public ConnectAction(IViewPart view) { + super(Messages.getString(ConnectAction.class.getName() + ".text")); + this.view = view; + setImageDescriptor( + QuantumPlugin.getImageDescriptor("connect.gif")); //$NON-NLS-1$ + } + + private IViewPart view; + private ConnectionUtil connectionUtil = new ConnectionUtil(); + + /** + * @see IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = view; + } + + /** + * @see org.eclipse.jface.action.IAction#run() + */ + public void run() { + + int bookmarks = 0; + int errors = 0; + String lastBookmarkName = null; + for (Iterator i = getSelectedNonResources().iterator(); i.hasNext();) { + Bookmark bookmark = ((BookmarkNode) i.next()).getBookmark(); + Connection connection = this.connectionUtil.connect(bookmark, getShell()); + if (connection == null) { + errors++; + } + bookmarks++; + lastBookmarkName = bookmark.getName(); + } + + if (bookmarks == 1 && errors == 0) { + updateStatusLine(getMessage("singleSuccessMessage", + new Object[] {lastBookmarkName})); + } else if (bookmarks == 1 && errors == 1) { + updateStatusLine(getMessage("singleFailureMessage", + new Object[] {lastBookmarkName})); + } else if (bookmarks > 1 && errors == 0) { + updateStatusLine(getMessage("multiSuccessMessage", + new Object[] {String.valueOf(bookmarks)})); + } else if (bookmarks > 1 && errors > 0) { + updateStatusLine(getMessage("multiFailureMessage", + new Object[] {String.valueOf(bookmarks - errors), + String.valueOf(errors)})); + } + } + + private String getMessage(String key, Object[] arguments) { + return Messages.getString(getClass().getName() + "." + key, arguments); + } + + /** + * Updates the message shown in the status line. + * + * @param message the message to display + */ + protected void updateStatusLine(String message) { + this.view.getViewSite().getActionBars().getStatusLineManager().setMessage(message); + } + + protected Shell getShell() { + return this.view.getSite().getShell(); + } + + /** + * + */ + protected boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + for (Iterator i = selection.iterator(); + enabled && i.hasNext(); + ) { + Object object = i.next(); + if (object instanceof BookmarkNode) { + BookmarkNode node = (BookmarkNode) object; + enabled &= !node.getBookmark().isConnected(); + } else { + enabled = false; + } + } + return enabled; + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/CustomCopyAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/CustomCopyAction.java new file mode 100644 index 0000000..24ea456 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/CustomCopyAction.java @@ -0,0 +1,73 @@ +/* + * Created on 11/08/2003 + * + */ +package com.quantum.actions; + +import java.util.Iterator; + +import com.quantum.QuantumPlugin; +import com.quantum.model.Column; +import com.quantum.model.EntityHolder; +import com.quantum.util.NthLevelConverter; +import com.quantum.util.QuantumUtil; +import com.quantum.util.StringUtil; +import com.quantum.view.bookmark.ColumnNode; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + + +public class CustomCopyAction extends SelectionListenerAction { + private final IViewPart view; + private final int ind; + /** + * @param BookmarkView + */ + public CustomCopyAction(IViewPart view, int ind) { + super(null); + this.view = view; + this.ind = ind; + } + public void run() { + String copyText = ""; + Iterator iter = getSelectedNonResources().iterator(); + NthLevelConverter converter = new NthLevelConverter(); + // Fill up the converter. We iterate the selection items + while (iter.hasNext()) { + Object current = iter.next(); + if (current instanceof ColumnNode) { + ColumnNode column = (ColumnNode) current; + if (column != null) { + converter.add(column.getColumn().getName(), + column.getColumn().getParentEntity().getCondQualifiedName(), 0); + } + } else if (current instanceof EntityHolder) { + EntityHolder currentSelec = (EntityHolder) current; + converter.add(currentSelec.getEntity().getCondQualifiedName(), null, 1); + Column[] columns = currentSelec.getEntity().getColumns(); + for (int i = 0, length = (columns == null) ? 0 : columns.length; + i < length; + i++) { + converter.add(columns[i].getName(), + currentSelec.getEntity().getCondQualifiedName(), 0); + } + } + } + IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore(); + + + converter.convert(Integer.toString(ind)); + + String template = QuantumUtil.trasposeEscape(store.getString("customCopyTemplate" + Integer.toString(ind))); + copyText = StringUtil.substituteString(template, "${table_list}", converter.getTableList()); + + + QuantumPlugin.getDefault().getSysClip().setContents( + new Object[] { copyText }, + new Transfer[] { TextTransfer.getInstance()}); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteAllRowsAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteAllRowsAction.java new file mode 100644 index 0000000..09f67bd --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteAllRowsAction.java @@ -0,0 +1,77 @@ +package com.quantum.actions; + +import java.sql.SQLException; + +import com.quantum.Messages; +import com.quantum.model.ConnectionException; +import com.quantum.model.Table; +import com.quantum.ui.dialog.ExceptionDisplayDialog; +import com.quantum.view.bookmark.EntityNode; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + * @author root + * + */ +public class DeleteAllRowsAction extends SelectionListenerAction { + private IViewPart view; + + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public DeleteAllRowsAction(IViewPart view) { + super(Messages.getString(DeleteAllRowsAction.class.getName() + ".text")); + this.view = view; + } + + public void run() { + try { + Table table = getTable(); + if (table != null) { + boolean flag = MessageDialog.openConfirm( + view.getSite().getShell(), + Messages.getString(DeleteAllRowsAction.class.getName() + ".confirmTitle"), + Messages.getString(DeleteAllRowsAction.class.getName() + ".confirmText", + new Object[] { table.getCondQualifiedName() })); + if (flag) { + table.deleteAllRows(); + } + } + } catch (SQLException e) { + ExceptionDisplayDialog.openError(getShell(), + Messages.getString("ExecuteAgainstAction.title"), + Messages.getString("ExecuteAgainstAction.ConnectionException"), e); + } catch (ConnectionException e) { + ExceptionDisplayDialog.openError(getShell(), + Messages.getString("ExecuteAgainstAction.title"), + Messages.getString("ExecuteAgainstAction.ConnectionException"), e); + } + } + + private Table getTable() { + EntityNode node = (EntityNode) getSelectedNonResources().get(0); + return node == null ? null : (Table) node.getEntity(); + } + + + + protected Shell getShell() { + return this.view.getViewSite().getShell(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.actions.SelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) + */ + protected boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + return enabled && selection.size() == 1 && + (selection.getFirstElement() instanceof EntityNode) && + ((EntityNode) selection.getFirstElement()).isTable(); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteBookmarkAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteBookmarkAction.java new file mode 100644 index 0000000..a00c028 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteBookmarkAction.java @@ -0,0 +1,59 @@ +package com.quantum.actions; + +import java.util.Iterator; +import java.util.List; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.BookmarkCollection; +import com.quantum.view.bookmark.BookmarkNode; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + * @author root + * + */ +public class DeleteBookmarkAction extends SelectionListenerAction { + + private IViewPart view; + + public DeleteBookmarkAction(IViewPart view) { + super(Messages.getString(DeleteBookmarkAction.class.getName() + ".text")); + setImageDescriptor(QuantumPlugin.getImageDescriptor("delete.gif")); + this.view = view; + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + + public void run() { + List bookmarkNodes = getSelectedNonResources(); + boolean flag = MessageDialog.openConfirm(view.getSite().getShell(), Messages.getString("bookmarkview.deleteBookmark"), Messages.getString("bookmarkview.confirm")); //$NON-NLS-1$ //$NON-NLS-2$ + + for (Iterator i = bookmarkNodes.iterator(); flag && i.hasNext();) { + BookmarkNode bookmarkNode = (BookmarkNode) i.next(); + if (bookmarkNode != null) { + BookmarkCollection.getInstance().removeBookmark(bookmarkNode.getBookmark()); + } + } + } + + public boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + for (Iterator i = selection.iterator(); enabled && i.hasNext(); ) { + enabled &= (i.next() instanceof BookmarkNode); + } + + return enabled; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteColumnAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteColumnAction.java new file mode 100644 index 0000000..37e38ff --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteColumnAction.java @@ -0,0 +1,63 @@ +package com.quantum.actions; + +import java.util.Iterator; + +import com.quantum.Messages; +import com.quantum.view.bookmark.ColumnNode; +import com.quantum.view.subset.SubsetView; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * Deletes the selected columns from the Subset items (Tables) + * @author root + * + */ +public class DeleteColumnAction extends Action implements IViewActionDelegate { + SubsetView view; + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = (SubsetView) view; + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + + public void run() { + StructuredSelection selection = view.getSelection(); + Iterator iter = selection.iterator(); + if (! MessageDialog.openConfirm(view.getSite().getShell(), + Messages.getString("DeleteColumnAction.DeleteColumns"), //$NON-NLS-1$ + Messages.getString("DeleteColumnAction.ConfirmDeleteColumns") )) //$NON-NLS-1$ + return; + + while (iter.hasNext()) { + Object current = iter.next(); + if (current instanceof ColumnNode) { + ColumnNode column = (ColumnNode) current; + if (column != null) { + view.deleteColumn(column); + } + } + } + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteObjectAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteObjectAction.java new file mode 100644 index 0000000..4d83cee --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteObjectAction.java @@ -0,0 +1,77 @@ +package com.quantum.actions; + +import java.util.Iterator; + +import com.quantum.Messages; +import com.quantum.view.subset.ObjectNode; +import com.quantum.view.subset.SubsetNode; +import com.quantum.view.subset.SubsetView; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * Deletes an entire object (Table) from the SubsetView + * @author root + * + */ +public class DeleteObjectAction extends Action implements IViewActionDelegate { + SubsetView view; + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = (SubsetView) view; + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + + public void run() { + Object selection = view.getCurrent(); + if (selection instanceof SubsetNode) { + SubsetNode node = (SubsetNode) selection; + if (node != null) { + boolean flag = MessageDialog.openConfirm(view.getSite().getShell(), + Messages.getString("DeleteObjectAction.DeleteSubset"), //$NON-NLS-1$ + Messages.getString("DeleteObjectAction.ConfirmDeleteSubset") + node.getName()); //$NON-NLS-1$ + if (flag) { + view.deleteCurrent(); + } + } + } else if (selection instanceof ObjectNode) { + StructuredSelection allSelected = view.getSelection(); + Iterator iter = allSelected.iterator(); + if (! MessageDialog.openConfirm(view.getSite().getShell(), + Messages.getString("DeleteObjectAction.DeleteItems"), //$NON-NLS-1$ + Messages.getString("DeleteObjectAction.ConfirmDeleteItems") )) //$NON-NLS-1$ + return; + + while (iter.hasNext()) { + Object current = iter.next(); + if (current instanceof ObjectNode) { + ObjectNode node = (ObjectNode) current; + if (node != null) { + view.deleteObject(node); + } + } + } + } + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteSubsetAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteSubsetAction.java new file mode 100644 index 0000000..086d543 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DeleteSubsetAction.java @@ -0,0 +1,55 @@ +package com.quantum.actions; + +import com.quantum.Messages; +import com.quantum.view.subset.SubsetNode; +import com.quantum.view.subset.SubsetView; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * @author root + * Deletes a complete subset from the subset view + */ +public class DeleteSubsetAction extends Action implements IViewActionDelegate { + SubsetView view; + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = (SubsetView) view; + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + + public void run() { + Object selection = view.getCurrent(); + if (selection instanceof SubsetNode) { + SubsetNode node = (SubsetNode) selection; + if (node != null) { + boolean flag = MessageDialog.openConfirm(view.getSite().getShell(), + Messages.getString("DeleteSubsetAction.DeleteSubset"), //$NON-NLS-1$ + Messages.getString("DeleteSubsetAction.ConfirmDeleteSubset") + node.getName()); //$NON-NLS-1$ + if (flag) { + view.deleteCurrent(); + } + } + } + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DisconnectAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DisconnectAction.java new file mode 100644 index 0000000..7966a08 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/DisconnectAction.java @@ -0,0 +1,81 @@ +package com.quantum.actions; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.model.ConnectionException; +import com.quantum.view.bookmark.BookmarkNode; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + * Disconnects from the database + * + * @author root + */ +public class DisconnectAction extends SelectionListenerAction { + private IViewPart view; + private List selections = new Vector(); + + /** + * @param text + */ + public DisconnectAction(IViewPart view) { + super(Messages.getString(DisconnectAction.class.getName() + ".text")); + this.view = view; + setImageDescriptor( + QuantumPlugin.getImageDescriptor("disconnect.gif")); //$NON-NLS-1$ + } + + + public void run() { + for (Iterator i = this.selections.iterator(); i.hasNext();) { + Bookmark bookmark = (Bookmark) i.next(); + try { + bookmark.disconnect(); + } catch (ConnectionException e) { + e.printStackTrace(); + } + } + updateStatusLine(getMessage("message")); + } + + private String getMessage(String key) { + return Messages.getString(getClass().getName() + "." + key); + } + + /** + * Updates the message shown in the status line. + * + * @param message the message to display + */ + protected void updateStatusLine(String message) { + this.view.getViewSite().getActionBars().getStatusLineManager().setMessage(message); + } + + + /** + * + */ + public boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + this.selections.clear(); + for (Iterator i = selection.iterator(); enabled && i.hasNext(); ) { + Object object = i.next(); + if (object instanceof BookmarkNode) { + BookmarkNode node = (BookmarkNode) object; + this.selections.add(node.getBookmark()); + enabled &= node.getBookmark().isConnected(); + } else { + enabled = false; + } + } + return enabled; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExecuteAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExecuteAction.java new file mode 100644 index 0000000..f8c4418 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExecuteAction.java @@ -0,0 +1,142 @@ +package com.quantum.actions; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Vector; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.sql.MultiSQLServer; +import com.quantum.sql.SQLParser; +import com.quantum.sql.SQLResults; +import com.quantum.view.LogProxy; +import com.quantum.view.SQLQueryView; +import com.quantum.view.bookmark.BookmarkNode; +import com.quantum.view.bookmark.BookmarkView; +import com.quantum.view.tableview.DefaultSizes; +import com.quantum.view.tableview.TableView; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * @author panic + * + * Executes a query from the QueryView + */ +public class ExecuteAction extends BaseSQLAction implements IViewActionDelegate { + SQLQueryView view; + boolean flag = false; + String execute1 = Messages.getString("ExecuteAction.Executing_Query3"); //$NON-NLS-1$ + String execute2 = Messages.getString("ExecuteAction.Executing_Query2"); //$NON-NLS-1$ + + public ExecuteAction() { + setActionDefinitionId("com.quantum.actions.ExecuteAction"); + } + + public void init(IViewPart view) { + this.view = (SQLQueryView) view; + } + + public void run(IAction action) { + run(); + } + + public void run() { + BookmarkNode current = BookmarkView.getInstance().getCurrentBookmark(); + if (current == null) + { + MessageDialog.openInformation( + view.getSite().getShell(),"Sorry","Please select a bookmark to use as connection."); + return; + } + Connection con = getConnection(); + view.setStatus(execute1); + MultiSQLServer server = MultiSQLServer.getInstance(); + view.setStatus(Messages.getString("ExecuteAction.Parsing_sql_script3")); //$NON-NLS-1$ + Vector queries = new Vector(); + String viewQuery = view.getQuery(); + // We parse the executable units to send to the JDBC driver + queries = SQLParser.parse(viewQuery); + for (int i = 0; i < queries.size(); i++) { + String query = (String) queries.elementAt(i); + System.out.println(query); + } + int resultCount = 0; + int resultUpdateCount = 0; + int errorCount = 0; + int resultsDisplayed = 0; + double startTime = 0.0; // stores the time when query is started + double queryDuration= 0.0; // stores query's execution time + + for (int i = 0; i < queries.size(); i++) { + if (flag) { + view.setStatus(execute1); + } else { + view.setStatus(execute2); + } + + String query = (String) queries.elementAt(i); + System.out.println(">" + query + "<"); //$NON-NLS-1$ //$NON-NLS-2$ + if (con != null && !query.equals("")) { //$NON-NLS-1$ + + SQLResults results; + try { + startTime = System.currentTimeMillis(); // Start the measure of execution time + results = server.execute(con, query, 1, DefaultSizes.PAGE_SIZE, DefaultSizes.MAX_COLUMN_SIZE); + queryDuration = (System.currentTimeMillis() - startTime)/1000; // calculate the execution time (in seconds) + current.getBookmark().addQuery(query); + } catch (SQLException e) { + errorCount++; + LogProxy log = LogProxy.getInstance(); + log.addText( + LogProxy.ERROR, + "Error Executing: " + query + ":" + e.toString(), e); //$NON-NLS-1$ //$NON-NLS-2$ + MessageDialog.openConfirm(view.getSite().getShell(), "Database returned error", e.getLocalizedMessage()); //$NON-NLS-1$ + continue; + } + resultCount++; + if (results.isResultSet()) { + TableView.getInstance().loadQuery(current.getBookmark(), results); + resultsDisplayed++; + } else { + int count = results.getUpdateCount(); + if (count > 0) { + resultUpdateCount += results.getUpdateCount(); + } + } + } + flag = !flag; + view.setProgress(i + 1, queries.size()); + } + Image statImage = QuantumPlugin.getImage((errorCount > 0) ? "stop.gif" : "success.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + view.setStatus(statImage, Messages.getString("ExecuteAction.Done") + "(" + //$NON-NLS-1$ //$NON-NLS-2$ + resultCount + Messages.getString("ExecuteAction.QueriesExecuted") + //$NON-NLS-1$ + resultUpdateCount + Messages.getString("ExecuteAction.RowsUpdated") + //$NON-NLS-1$ + resultsDisplayed + Messages.getString("ExecuteAction.ResultsDisplayed") + //$NON-NLS-1$ + errorCount + Messages.getString("ExecuteAction.Errors") + //$NON-NLS-1$ + queryDuration + Messages.getString("ExecutAction.TimeExec") + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + view.setProgress(0, 1); + } + + public void selectionChanged(IAction action, ISelection selection) { + } + protected Bookmark getBookmark() { + BookmarkNode current = BookmarkView.getInstance().getCurrentBookmark(); + return current.getBookmark(); + } + + /* (non-Javadoc) + * @see com.quantum.actions.BaseSQLAction#getShell() + */ + protected Shell getShell() { + return this.view.getViewSite().getShell(); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExecuteAgainstAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExecuteAgainstAction.java new file mode 100644 index 0000000..c1e2486 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExecuteAgainstAction.java @@ -0,0 +1,184 @@ +package com.quantum.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import com.quantum.Messages; +import com.quantum.model.Bookmark; +import com.quantum.model.BookmarkCollection; +import com.quantum.model.ConnectionException; +import com.quantum.sql.MultiSQLServer; +import com.quantum.sql.SQLParser; +import com.quantum.sql.SQLResults; +import com.quantum.ui.dialog.BookmarkSelectionDialog; +import com.quantum.ui.dialog.ExceptionDisplayDialog; +import com.quantum.util.io.InputStreamHelper; +import com.quantum.view.tableview.DefaultSizes; +import com.quantum.view.tableview.TableView; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +/** + * This action can be executed against any .sql file, regardless of + * whether or not the Quantum perspective is open. + * + * @author BC + */ +public class ExecuteAgainstAction extends BaseSQLAction + implements IObjectActionDelegate, PropertyChangeListener { + + private String selectedBookmark = null; + private IFile[] files = null; + + private IWorkbenchPart workbenchPart; + + /** + * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart) + */ + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + this.workbenchPart = targetPart; + } + + protected Shell getShell() { + return this.workbenchPart.getSite().getShell(); + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) + */ + public void run(IAction action) { + + BookmarkSelectionDialog dialog = new BookmarkSelectionDialog(getShell()); + dialog.addPropertyChangeListener(this); + int result = dialog.open(); + + if (result == Window.OK) { + try { + executeAgainstBookmark(); + } catch (SQLException e) { + ExceptionDisplayDialog.openError(getShell(), + null, + null, e); + } catch (IOException e) { + ExceptionDisplayDialog.openError(getShell(), + Messages.getString("ExecuteAgainstAction.title"), + Messages.getString("ExecuteAgainstAction.IOException"), e); + } catch (ConnectionException e) { + ExceptionDisplayDialog.openError(getShell(), + null, + null, e); + } catch (CoreException e) { + ErrorDialog.openError(getShell(), null, null, e.getStatus()); + } + } + } + + protected Bookmark getBookmark() { + return BookmarkCollection.getInstance().find(this.selectedBookmark); + } + + private void executeAgainstBookmark() + throws SQLException, IOException, CoreException, ConnectionException { + Bookmark bookmark = getBookmark(); + if (bookmark != null) { + boolean alreadyConnected = bookmark.isConnected(); + Connection connection = getConnection(); + try { + for (int i = 0, + length = (this.files == null) ? 0 : this.files.length; + connection != null && i < length; + i++) { + executeAgainstBookmark(bookmark, connection, this.files[i]); + } + } finally { + if (!alreadyConnected && connection != null) { + bookmark.disconnect(); + } + } + } + } + + private void executeAgainstBookmark( + Bookmark bookmark, + Connection connection, + IFile file) + throws SQLException, IOException, CoreException { + executeAgainstBookmark( + bookmark, + connection, + InputStreamHelper.readIntoString(file.getContents())); + } + + private void executeAgainstBookmark( + Bookmark bookmark, + Connection connection, + String queries) + throws SQLException { + List queryList = SQLParser.parse(queries); + MultiSQLServer server = MultiSQLServer.getInstance(); + + for (Iterator i = queryList.iterator(); i.hasNext();) { + String query = (String) i.next(); + SQLResults results = + server.execute( + connection, + query, + 1, + DefaultSizes.PAGE_SIZE, + DefaultSizes.MAX_COLUMN_SIZE); + if (results.isResultSet()) { + TableView view = TableView.getInstance(); + if (view != null) { + view.loadQuery(bookmark, results); + } + } + } + } + + /** + * This method is called with a new selection has been made on one + * of the views. + * + * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + if (selection instanceof IStructuredSelection) { + IStructuredSelection structuredSelection = + (IStructuredSelection) selection; + List list = new ArrayList(); + + for (Iterator i = structuredSelection.iterator(); i.hasNext();) { + Object temp = i.next(); + if (temp != null && temp instanceof IFile) { + System.out.println(((IFile) temp).getName()); + list.add(temp); + } + } + this.files = (IFile[]) list.toArray(new IFile[list.size()]); + } + } + + /** + * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + if ("selection".equals(event.getPropertyName())) { + this.selectedBookmark = (String) event.getNewValue(); + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportBookmarksAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportBookmarksAction.java new file mode 100644 index 0000000..06be066 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportBookmarksAction.java @@ -0,0 +1,42 @@ +package com.quantum.actions; + +import com.quantum.wizards.ExportBookmarkWizard; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * @author root + * Asks the user for a file name and saves there the bookmarks in xml format + */ +public class ExportBookmarksAction implements IViewActionDelegate { + + private IViewPart view; + + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = view; + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + + ExportBookmarkWizard wizard = new ExportBookmarkWizard(); + WizardDialog dialog = + new WizardDialog(this.view.getSite().getShell(), wizard); + dialog.open(); + } + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportQueryAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportQueryAction.java new file mode 100644 index 0000000..081897e --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportQueryAction.java @@ -0,0 +1,83 @@ +package com.quantum.actions; + +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.StringTokenizer; + +import com.quantum.Messages; +import com.quantum.util.StringUtil; +import com.quantum.view.LogProxy; +import com.quantum.view.SQLLogView; +import com.quantum.view.SQLQueryView; +import com.quantum.view.ViewHelper; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +public class ExportQueryAction extends Action implements IViewActionDelegate { + SQLQueryView view; + + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = (SQLQueryView) view; + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + + public void run() { + FileOutputStream out = ViewHelper.askSaveFile("exportquery", view.getSite().getShell(), + new String[]{"*.sql", "*.ddl", "*.*"}, + new String[]{ + Messages.getString("filedialog.sqlFiles"), + Messages.getString("filedialog.ddlFiles"), + Messages.getString("filedialog.allfiles") + }); + if (out == null) + return; + + try { + FileWriter fileWriter = new FileWriter(out.getFD()); + PrintWriter writer = new PrintWriter(fileWriter); + String output = view.getQuery(); + output = StringUtil.substituteString(output, "\r", ""); + StringTokenizer tokenizer = new StringTokenizer(output, "\n", true); //$NON-NLS-1$ + String prevToken = ""; + while (tokenizer.hasMoreElements()) { + String token = (String) tokenizer.nextElement(); + // If it's a normal line end, we won't write it, because the println() will + // adapting it to the OS (have to test that). But if it's a line end after + // another, then it's a blank line. + if (token.equals("\n")) + if (prevToken.equals("\n")) + writer.println(); // Two consecutives "\n", means a separate line + else + ; // Do nothing, the end of line is already written + else + writer.println(token); //Normal line + prevToken = token; + } + writer.close(); + } catch (IOException e) { + LogProxy.getInstance().addText(SQLLogView.ERROR, e.toString()); + e.printStackTrace(); + } + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportXMLAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportXMLAction.java new file mode 100644 index 0000000..2dbd6ae --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ExportXMLAction.java @@ -0,0 +1,130 @@ +package com.quantum.actions; + + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Iterator; + +import javax.xml.parsers.ParserConfigurationException; + +import com.quantum.Messages; +import com.quantum.model.xml.ModelToXMLConverter; +import com.quantum.sql.metadata.MetaDataXMLInterface; +import com.quantum.util.xml.XMLHelper; +import com.quantum.view.ViewHelper; +import com.quantum.view.bookmark.BookmarkView; +import com.quantum.view.bookmark.EntityNode; +import com.quantum.view.bookmark.TreeNode; +import com.quantum.view.subset.SubsetView; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * @author root + */ +public class ExportXMLAction extends Action implements IViewActionDelegate { + + IViewPart view; + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = view; + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + + public void run() { + + FileOutputStream out = ViewHelper.askSaveFile("exportxml", view.getSite().getShell()); + if (out == null) + return; + StructuredSelection selection = null; + if (view instanceof BookmarkView){ + BookmarkView bookmarkView = (BookmarkView) view; + selection = bookmarkView.getSelection(); + } else if (view instanceof SubsetView){ + SubsetView subsetView = (SubsetView) view; + selection = subsetView.getSelection(); + } + + try { + Document doc = XMLHelper.createEmptyDocument(); + exportXMLSelection(doc, selection); + try { + XMLHelper.write(out, doc); + } finally { + out.close(); + } + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + + } + + /** + * Exports to an XmlDocument the items selected in a StructuredSelection. + * @param doc + * @param selection + */ + public void exportXMLSelection(Document doc, StructuredSelection selection) { + Element root = (Element) doc.appendChild(doc.createElement(Messages.getString("ExportXMLAction.Metadata"))); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(root, Messages.getString("ExportXMLAction.Author"), //$NON-NLS-1$ + Messages.getString("ExportXMLAction.Quantum")); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(root, Messages.getString("ExportXMLAction.Version"), //$NON-NLS-1$ + Messages.getString("ExportXMLAction.XMLVersionNumber")); //$NON-NLS-1$ + Iterator iter = selection.iterator(); + while (iter.hasNext()) { + TreeNode current = (TreeNode) iter.next(); +// TODO: reinstate this +// if (current instanceof SubsetNode){ +// SubsetNode subset = (SubsetNode) current; +// MetaDataXMLInterface.createElementText(root, Messages.getString("ExportXMLAction.Subset"), //$NON-NLS-1$ +// subset.getName()); //$NON-NLS-1$ +// Object[] children = subset.getChildren(); +// for (int i = 0; i < children.length; i++) { +// TreeNode objectNode = (TreeNode) children[i]; +// if (objectNode instanceof SelectableNode) +// ExportXMLAction.exportObject(root, (SelectableNode)objectNode); +// } +// } else { + exportObject(root, current); +// } + } + + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + + /** + * Exports a TreeNode metadata representation to an XmlDocument, based on a an already-created root Element + * @param doc The XmlDocument to receive the metadata representation + * @param node The node with the metadata to export + * @param root The root element (already present in the XmlDocument) that will hold the metadata + */ + public void exportObject(Element root, TreeNode node) { + if (node instanceof EntityNode) { + EntityNode entityNode = (EntityNode) node; + ModelToXMLConverter.getInstance().convert(root, entityNode.getEntity()); + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ImportBookmarksAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ImportBookmarksAction.java new file mode 100644 index 0000000..9477bdd --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ImportBookmarksAction.java @@ -0,0 +1,88 @@ +package com.quantum.actions; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +import javax.xml.parsers.ParserConfigurationException; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.BookmarkCollection; +import com.quantum.util.xml.XMLHelper; +import com.quantum.view.bookmark.BookmarkView; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * @author root + * + * To change this generated comment edit the template variable "typecomment": + * Window>Preferences>Java>Templates. + * To enable and disable the creation of type comments go to + * Window>Preferences>Java>Code Generation. + */ +public class ImportBookmarksAction implements IViewActionDelegate { + BookmarkView view; + FileDialog dialog; + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = (BookmarkView) view; + dialog = new FileDialog(view.getSite().getShell(), SWT.OPEN); + dialog.setFilterExtensions(new String[]{"*.xml","*.*"}); //$NON-NLS-1$ //$NON-NLS-2$ + dialog.setFilterNames(new String[]{Messages.getString("filedialog.xmlFiles"),Messages.getString("filedialog.xmlFiles")}); //$NON-NLS-1$ //$NON-NLS-2$ + + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + dialog.setFilterPath(QuantumPlugin.getDefault().getPreferenceStore().getString("quantum.dialogs.importbookmark.path")); + String filename = dialog.open(); + if (filename != null) { + QuantumPlugin.getDefault().getPreferenceStore().setValue("quantum.dialogs.importbookmark.path", filename); + File importFile = new File(filename); + + FileInputStream source = null; + try { + source = new FileInputStream(importFile); + } catch (FileNotFoundException e1) { + e1.printStackTrace(); + return; + } + try { + Document doc = XMLHelper.createFromInputStream(source); + Element root = doc.getDocumentElement(); + BookmarkCollection.getInstance().importXML(root); + + view.refresh(); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ImportQueryAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ImportQueryAction.java new file mode 100644 index 0000000..6d9654b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ImportQueryAction.java @@ -0,0 +1,80 @@ +package com.quantum.actions; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.view.LogProxy; +import com.quantum.view.SQLLogView; +import com.quantum.view.SQLQueryView; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * @author root + * + */ +public class ImportQueryAction extends Action implements IViewActionDelegate { + SQLQueryView view; + FileDialog dialog; + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = (SQLQueryView) view; + dialog = new FileDialog(view.getSite().getShell(), SWT.OPEN); + dialog.setFilterExtensions(new String[]{"*.sql", "*.ddl", "*.*"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + dialog.setFilterNames(new String[]{Messages.getString("filedialog.sqlFiles"), //$NON-NLS-1$ + Messages.getString("filedialog.ddlFiles"), Messages.getString("filedialog.allfiles")}); //$NON-NLS-1$ //$NON-NLS-2$ + + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + + public void run() { + dialog.setFilterPath(QuantumPlugin.getDefault().getPreferenceStore().getString("quantum.dialogs.importquery.path")); + String filename = dialog.open(); + if (filename != null) { + QuantumPlugin.getDefault().getPreferenceStore().setValue("quantum.dialogs.importquery.path", filename); + + try { + File importFile = new File(filename); + FileReader fileReader = new FileReader(importFile); + BufferedReader reader = new BufferedReader(fileReader); + String line; + StringBuffer buffer = new StringBuffer(); + + while ((line = reader.readLine()) != null) { + buffer.append(line); + buffer.append('\n'); + } + view.setQuery(buffer.toString()); + reader.close(); + } catch (IOException e) { + LogProxy.getInstance().addText(SQLLogView.ERROR, e.toString()); + e.printStackTrace(); + } + } + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NewBookmarkAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NewBookmarkAction.java new file mode 100644 index 0000000..b3dbd19 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NewBookmarkAction.java @@ -0,0 +1,32 @@ +package com.quantum.actions; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.wizards.BookmarkWizard; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.IViewPart; + +/** + * @author root + * + */ +public class NewBookmarkAction extends Action { + private IViewPart view; + + public NewBookmarkAction(IViewPart view) { + this.view = view; + setText(Messages.getString(getClass().getName() + ".text")); //$NON-NLS-1$ + setToolTipText(Messages.getString(getClass().getName() + ".text")); //$NON-NLS-1$ + setImageDescriptor(QuantumPlugin.getImageDescriptor("bookmarks.gif")); //$NON-NLS-1$ + } + + public void run() { + BookmarkWizard wizard = new BookmarkWizard(); + wizard.init(); + WizardDialog dialog = + new WizardDialog(view.getSite().getShell(), wizard); + dialog.open(); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NewSubsetAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NewSubsetAction.java new file mode 100644 index 0000000..8732413 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NewSubsetAction.java @@ -0,0 +1,53 @@ +package com.quantum.actions; + +import com.quantum.Messages; +import com.quantum.view.subset.SubsetNode; +import com.quantum.view.subset.SubsetView; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * @author root + * + */ +public class NewSubsetAction extends Action implements IViewActionDelegate { + IViewPart view; + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = view; + + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + public void run() { + System.out.println(Messages.getString("NewSubsetAction.CreatingNewSubset")); //$NON-NLS-1$ + InputDialog dialog = new InputDialog(view.getSite().getShell(), + Messages.getString("NewSubsetAction.NameOfNewSubset"), Messages.getString("NewSubsetAction.PleaseEnterName"), null, null); //$NON-NLS-1$ //$NON-NLS-2$ + dialog.open(); + String value = dialog.getValue(); + if (value != null) { + SubsetNode subset = new SubsetNode(value); + ((SubsetView) view).addNewSubset(subset); + } + + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NextSequenceAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NextSequenceAction.java new file mode 100644 index 0000000..88331d8 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/NextSequenceAction.java @@ -0,0 +1,42 @@ +package com.quantum.actions; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.model.Bookmark; +import com.quantum.sql.SQLResults; +import com.quantum.view.ViewHelper; +import com.quantum.view.bookmark.EntityNode; +import com.quantum.view.tableview.TableView; + +import org.eclipse.ui.IViewPart; + +public class NextSequenceAction extends BaseSequenceAction { + + /** + * @param text + * @param view + */ + public NextSequenceAction(IViewPart view) { + super(Messages.getString(NextSequenceAction.class.getName() + ".text"), view); + setImageDescriptor(QuantumPlugin.getImageDescriptor("append.gif")); + } + + public void run() { + EntityNode node = getEntityNode(); + String name = null; + if (node.isSequence()) { + EntityNode sequence = (EntityNode) node; + Bookmark bookmark = sequence.getBookmark(); + DatabaseAdapter adapter = AdapterFactory.getInstance().getAdapter(bookmark.getType()); + if (adapter == null) return; + name = sequence.getName(); + String query = adapter.getNextValue(name, sequence.getEntity().getSchema()); + + SQLResults results = ViewHelper.tryGetResults(view, getConnection(), query); + if (results != null && ! results.isError()) + TableView.getInstance().loadQuery(bookmark, results); + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/OpenQueryAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/OpenQueryAction.java new file mode 100644 index 0000000..8a78c6e --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/OpenQueryAction.java @@ -0,0 +1,43 @@ +package com.quantum.actions; + +import com.quantum.Messages; +import com.quantum.view.SQLQueryView; +import com.quantum.view.bookmark.QueryNode; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + * @author BC + */ +public class OpenQueryAction extends SelectionListenerAction { + + /** + * @param text + */ + public OpenQueryAction(IViewPart viewPart) { + super(Messages.getString(OpenQueryAction.class.getName() + ".text")); + } + + protected boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + enabled &= (selection.size() == 1 && + selection.getFirstElement() instanceof QueryNode); + return enabled; + } + public void run() { + SQLQueryView queryView = SQLQueryView.getInstance(); + if (queryView != null) { + queryView.setQuery(getQuery()); + } + } + private String getQuery() { + if (isEnabled()) { + QueryNode node = (QueryNode) getSelectedNonResources().get(0); + return node.getQuery(); + } else { + return null; + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/PrevSequenceAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/PrevSequenceAction.java new file mode 100644 index 0000000..875df6d --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/PrevSequenceAction.java @@ -0,0 +1,44 @@ +/* + * Created on 22-jul-2003 + * + */ +package com.quantum.actions; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.model.Bookmark; +import com.quantum.sql.SQLResults; +import com.quantum.view.ViewHelper; +import com.quantum.view.bookmark.EntityNode; +import com.quantum.view.tableview.TableView; + +import org.eclipse.ui.IViewPart; + +public class PrevSequenceAction extends BaseSequenceAction { + /** + * @param text + * @param view + */ + public PrevSequenceAction(IViewPart view) { + super(Messages.getString(PrevSequenceAction.class.getName() + ".text"), view); + setImageDescriptor(QuantumPlugin.getImageDescriptor("grid.gif")); + } + + public void run() { + EntityNode node = getEntityNode(); + if (((EntityNode) node).isSequence()) { + EntityNode sequence = (EntityNode) node; + Bookmark bookmark = sequence.getBookmark(); + DatabaseAdapter adapter = AdapterFactory.getInstance().getAdapter( + bookmark.getType()); + if (adapter == null) return; + String name = sequence.getName(); + String query = adapter.getPrevValue(name, sequence.getEntity().getSchema()); + SQLResults results = ViewHelper.tryGetResults(view, getConnection(), query); + if (results != null && ! results.isError()) + TableView.getInstance().loadQuery(bookmark, results); + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RefreshBookmarkAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RefreshBookmarkAction.java new file mode 100644 index 0000000..525503f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RefreshBookmarkAction.java @@ -0,0 +1,37 @@ +package com.quantum.actions; + +import java.util.Iterator; +import java.util.List; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.sql.SQLHelper; +import com.quantum.view.bookmark.BookmarkView; +import com.quantum.view.bookmark.TreeNode; + +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + * @author root + */ +public class RefreshBookmarkAction extends SelectionListenerAction { + SQLHelper helper = new SQLHelper(); + + BookmarkView view; + public RefreshBookmarkAction(IViewPart view) { + super(Messages.getString(RefreshBookmarkAction.class.getName() + ".text")); + this.view = (BookmarkView) view; + setImageDescriptor(QuantumPlugin.getImageDescriptor("refresh.gif")); + } + + public void run() { + List list = getSelectedNonResources(); + for (Iterator i = list.iterator(); i.hasNext(); ) { + Object object = i.next(); + if (object != null && object instanceof TreeNode) { + ((TreeNode) object).reload(); + } + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RefreshTableAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RefreshTableAction.java new file mode 100644 index 0000000..d987d8a --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RefreshTableAction.java @@ -0,0 +1,40 @@ +package com.quantum.actions; + +import com.quantum.view.tableview.TableView; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * @author root + * Implements the "Refresh Table" action for the TableView view + */ +public class RefreshTableAction extends Action implements IViewActionDelegate { + TableView view; + /** + * @see org.eclipse.ui.IViewActionDelegate#init(IViewPart) + */ + public void init(IViewPart view) { + this.view = (TableView) view; + } + + /** + * @see org.eclipse.ui.IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + public void run() { + view.refreshCurrent(); + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RemoveFromQuickListAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RemoveFromQuickListAction.java new file mode 100644 index 0000000..a677733 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/RemoveFromQuickListAction.java @@ -0,0 +1,56 @@ +package com.quantum.actions; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import com.quantum.Messages; +import com.quantum.view.bookmark.EntityNode; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + *

This action takes an EntityNode and adds a copy of it to the quicklist + * of a bookmark.

+ * + * @author bcholmes + */ +public class RemoveFromQuickListAction extends SelectionListenerAction { + private IViewPart view; + private List entities = Collections.synchronizedList(new ArrayList()); + + public RemoveFromQuickListAction(IViewPart view) { + super(Messages.getString(RemoveFromQuickListAction.class.getName() + ".text")); + this.view = view; + } + + public void run() { + for (Iterator i = this.entities.iterator(); i.hasNext(); ) { + EntityNode entityNode = (EntityNode) i.next(); + entityNode.getBookmark().removeQuickListEntry(entityNode.getEntity()); + } + } + + /** + * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection) + */ + public boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + this.entities.clear(); + for (Iterator i = selection.iterator(); enabled && i.hasNext(); ) { + Object object = i.next(); + if (object != null && object instanceof EntityNode) { + EntityNode node = (EntityNode) object; + enabled &= node.getBookmark().isInQuickList(node.getEntity()); + this.entities.add(node); + } else { + enabled = false; + } + } + + return enabled; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ViewTableAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ViewTableAction.java new file mode 100644 index 0000000..6da4e9f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ViewTableAction.java @@ -0,0 +1,59 @@ +package com.quantum.actions; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.Entity; +import com.quantum.view.bookmark.EntityNode; +import com.quantum.view.tableview.TableView; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + * @author root + * Implements action for "View Table" +*/ +public class ViewTableAction extends SelectionListenerAction { + private IViewPart view; + private Entity entity; + + public ViewTableAction(IViewPart view) { + super(Messages.getString(ViewTableAction.class.getName() + ".text")); + this.view = view; + setImageDescriptor( + QuantumPlugin.getImageDescriptor("table.gif")); //$NON-NLS-1$ + } + + public void run() { + TableView.getInstance().loadTable(this.entity); + // TODO: reinstate this +// } else if (view instanceof SubsetView){ +// SubsetView subsetView = (SubsetView) view; +// node = (TreeNode) subsetView.getCurrent(); +// if (!(node instanceof ObjectNode)) return; +// ObjectNode objectNode = (ObjectNode) node; +// +// String query = objectNode.getQuery(); +// +// SQLResults results = ViewHelper.tryGetResults(view, objectNode.getConnection(), query); +// if (results != null && ! results.isError()) +// TableView.getInstance().loadQuery(bookmark.getBookmark(), results); +// + } + + public boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + enabled &= (selection.size() == 1); + + if (enabled) { + Object object = selection.getFirstElement(); + if (object != null && object instanceof EntityNode) { + EntityNode entityNode = (EntityNode) object; + this.entity = entityNode.getEntity(); + enabled &= (entityNode.isTable() || entityNode.isView()); + } + } + return enabled; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ViewTableDetailsAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ViewTableDetailsAction.java new file mode 100644 index 0000000..5215912 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/actions/ViewTableDetailsAction.java @@ -0,0 +1,66 @@ +package com.quantum.actions; + +import java.sql.Connection; +import java.util.List; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.model.Entity; +import com.quantum.sql.SQLResults; +import com.quantum.util.connection.ConnectionUtil; +import com.quantum.view.ViewHelper; +import com.quantum.view.bookmark.EntityNode; +import com.quantum.view.tableview.TableView; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +public class ViewTableDetailsAction extends SelectionListenerAction { + private IViewPart view; + private ConnectionUtil connectionUtil = new ConnectionUtil(); + + public ViewTableDetailsAction(IViewPart view) { + super(Messages.getString(ViewTableDetailsAction.class, "text")); + setImageDescriptor(QuantumPlugin.getImageDescriptor("table.gif")); //$NON-NLS-1$ + this.view = view; + } + + public void run() { + Entity entity = getEntity(); + StringBuffer query = new StringBuffer(); + query.append(Messages.getString("MetaDataKey")+Messages.getString("MetaDataKeySeparator")); //$NON-NLS-1$ //$NON-NLS-2$ + query.append(entity.getQuotedTableName()); + Connection connection = connectionUtil.getConnection(getBookmark(), getShell()); + if (connection != null) { + SQLResults results = ViewHelper.tryGetResults(view, connection, query.toString()); + if (results != null && ! results.isError()) + TableView.getInstance().loadQuery(entity.getBookmark(), results); + } + } + public void selectionChanged(IAction action, ISelection selection) { + } + protected Bookmark getBookmark() { + return getEntity().getBookmark(); + } + protected Shell getShell() { + return this.view.getViewSite().getShell(); + } + protected Entity getEntity() { + List list = getSelectedNonResources(); + return ((EntityNode) list.get(0)).getEntity(); + } + + /** + * @see org.eclipse.ui.actions.SelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) + */ + protected boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + return enabled && selection.size() == 1; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/AdabasDAdapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/AdabasDAdapter.java new file mode 100644 index 0000000..42c403a --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/AdabasDAdapter.java @@ -0,0 +1,11 @@ +package com.quantum.adapters; + + +public class AdabasDAdapter extends DatabaseAdapter { + public String getShowTableQuery(String qualifier, boolean isDefault) { + return "SELECT OWNER, TABLENAME FROM TABLES WHERE OWNER = '" + qualifier.toUpperCase() + "'"; //$NON-NLS-1$ + } + public String getShowViewQuery(String qualifier, boolean isDefault) { + return "SELECT OWNER, VIEWNAME FROM VIEWS WHERE OWNER = '" + qualifier.toUpperCase() + "'"; //$NON-NLS-1$ + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/AdapterFactory.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/AdapterFactory.java new file mode 100644 index 0000000..f26b278 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/AdapterFactory.java @@ -0,0 +1,93 @@ +package com.quantum.adapters; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.quantum.Messages; + +/** + * @author root + * Basically this Factory is a Singleton that is used to return the proper adapter + */ +public class AdapterFactory { + public static final String GENERIC = "GENERIC"; //$NON-NLS-1$ + public static final String ORACLE = "ORACLE"; //$NON-NLS-1$ + public static final String POSTGRES = "POSTGRES"; //$NON-NLS-1$ + public static final String MYSQL = "MYSQL"; //$NON-NLS-1$ + public static final String DB2 = "DB2"; //$NON-NLS-1$ + public static final String DB2AS400 = "DB2AS400"; //$NON-NLS-1$ + public static final String ADABASD = "ADABASD"; //$NON-NLS-1$ + public static final String INFORMIX = "INFORMIX"; //$NON-NLS-1$ + public static final String REDBRICK = "REDBRICK"; //$NON-NLS-1$ + public static final String SYBASE = "SYBASE"; //$NON-NLS-1$ + + private static AdapterFactory instance; + + private ArrayList drivers; + + private AdapterFactory() { + loadDrivers(); + } + public static synchronized AdapterFactory getInstance() { + if (instance == null) { + instance = new AdapterFactory(); + } + return instance; + } + + /** + * Master list of supported drivers + */ + private void loadDrivers() { + drivers = new ArrayList(); + + DriverInfo generic = new DriverInfo(GENERIC, Messages.getString("adapters.generic"), new GenericAdapter()); //$NON-NLS-1$ + DriverInfo oracle = new DriverInfo(ORACLE, Messages.getString("adapters.oracle"), new OracleAdapter()); //$NON-NLS-1$ + DriverInfo db2 = new DriverInfo(DB2, Messages.getString("adapters.db2"), new DB2Adapter()); //$NON-NLS-1$ + DriverInfo db2as400 = new DriverInfo(DB2AS400, Messages.getString("adapters.db2as400"), new DB2AS400Adapter()); //$NON-NLS-1$ + DriverInfo postgres = new DriverInfo(POSTGRES, Messages.getString("adapters.postgres"), new PostgresAdapter()); //$NON-NLS-1$ + DriverInfo mysql = new DriverInfo(MYSQL, Messages.getString("adapters.mysql"), new GenericAdapter()); //$NON-NLS-1$ + DriverInfo adabasd = new DriverInfo(ADABASD, Messages.getString("adapters.adabasd"), new AdabasDAdapter()); //$NON-NLS-1$ + DriverInfo informix = new DriverInfo(INFORMIX, Messages.getString("adapters.informix"), new GenericAdapter()); //$NON-NLS-1$ + DriverInfo redbrick = new DriverInfo(REDBRICK, Messages.getString("adapters.redbrick"), new RedBrickAdapter()); //$NON-NLS-1$ + DriverInfo sybase = new DriverInfo(SYBASE, Messages.getString("adapters.sybase"), new GenericAdapter()); //$NON-NLS-1$ + + drivers.add(generic); + drivers.add(oracle); + drivers.add(db2); + drivers.add(db2as400); + drivers.add(postgres); + drivers.add(mysql); + drivers.add(adabasd); + drivers.add(informix); + drivers.add(redbrick); + drivers.add(sybase); + } + + public synchronized DatabaseAdapter getAdapter(String type){ + if (drivers == null) { + loadDrivers(); + } + for (int i = 0; i < drivers.size(); i++) { + DriverInfo info = (DriverInfo) drivers.get(i); + if (type.equals(info.getDriverType())) { + return info.getAdapter(); + } + } + // If its not a recognized driver, we return the generic one + for (int i = 0; i < drivers.size(); i++) { + DriverInfo info = (DriverInfo) drivers.get(i); + if (type.equals(GENERIC)) { + return info.getAdapter(); + } + } + return null; + } + + public synchronized DriverInfo[] getDriverList() { + List list = new ArrayList(this.drivers); + Collections.sort(list); + return (DriverInfo[]) list.toArray(new DriverInfo[list.size()]); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DB2AS400Adapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DB2AS400Adapter.java new file mode 100644 index 0000000..ff6bf2e --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DB2AS400Adapter.java @@ -0,0 +1,15 @@ +package com.quantum.adapters; + + +public class DB2AS400Adapter extends DatabaseAdapter { + public String getShowTableQuery(String qualifier, boolean isDefault) { + return "SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE table_schema = '" + + qualifier.toUpperCase() + + "' AND TABLE_TYPE IN ('T', 'P') AND SYSTEM_TABLE= 'N'"; //$NON-NLS-1$ //$NON-NLS-2$ + } + public String getShowViewQuery(String qualifier, boolean isDefault) { + return "SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE table_schema = '" + + qualifier.toUpperCase() + + "' AND TABLE_TYPE IN ('V', 'L') AND SYSTEM_TABLE= 'N'"; //$NON-NLS-1$ //$NON-NLS-2$ + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DB2Adapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DB2Adapter.java new file mode 100644 index 0000000..ca5dd76 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DB2Adapter.java @@ -0,0 +1,21 @@ +package com.quantum.adapters; + +import com.quantum.sql.SQLHelper; + +public class DB2Adapter extends DatabaseAdapter { + public String getShowTableQuery(String qualifier, boolean isDefault) { + return "SELECT TABNAME FROM syscat.tables WHERE tabschema = '" + qualifier.toUpperCase() + "' AND TYPE='T'"; //$NON-NLS-1$ //$NON-NLS-2$ + } + public String getShowViewQuery(String qualifier, boolean isDefault) { + return "SELECT TABNAME FROM syscat.tables WHERE tabschema = '" + qualifier.toUpperCase() + "' AND TYPE='V'"; //$NON-NLS-1$ //$NON-NLS-2$ + } + public String getShowSequenceQuery(String qualifier, boolean isDefault) { + return "SELECT SEQNAME FROM sysibm.syssequences WHERE seqschema = '" + qualifier.toUpperCase() + "'"; //$NON-NLS-1$ //$NON-NLS-2$ + } + public String getNextValue(String sequence, String owner) { + return "VALUES NEXTVAL FOR " + SQLHelper.getQualifiedName(owner, sequence); //$NON-NLS-1$ + } + public String getPrevValue(String sequence, String owner) { + return "VALUES PREVVAL FOR " + SQLHelper.getQualifiedName(owner, sequence); //$NON-NLS-1$ + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DatabaseAdapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DatabaseAdapter.java new file mode 100644 index 0000000..d17e8b0 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DatabaseAdapter.java @@ -0,0 +1,198 @@ +package com.quantum.adapters; + +import com.quantum.sql.SQLHelper; +import com.quantum.util.StringUtil; + +/** + * Abstract base class for all the adapter classes. Most functions can be redefined in + * the adapters for the different databases. If the functions is not redefined, the base + * implementation (usually a direct call to the JDBC driver) is used. + * + * @author root + */ +public abstract class DatabaseAdapter { + + /** + * Returns the SQL Query to get a list of the tables for the current user (schema) + * @param info + * @return - A String with the SQL query + */ + public String getShowTableQuery(String schema, boolean isDefault) { + return null; + } + /** + * Returns the SQL Query to get a list of the queries for the current user (schema) + * @param info + * @return - A String with the SQL query + */ + public String getShowViewQuery(String schema, boolean isDefault) { + return null; + } + /** + * Returns the SQL Query to get a list of the sequences for the current user (schema) + * @param info + * @return - A String with the SQL query + */ + public String getShowSequenceQuery(String schema, boolean isDefault) { + return null; + } + + /** Returns the SQL Query to access all the columns of a table (SELECT) + * @param info + * @param table + * @return - A String with the SQL query + */ + public String getTableQuery( String table) { + return "SELECT * FROM " + filterTableName(table); //$NON-NLS-1$ + } + + /** + * Gets the SQL query to get the next value of a sequence, (incrementing it). + * @param sequence - The name of the sequence + * @param owner - The owner (schema) of it + * @return - A string with the SQL query + */ + public String getNextValue(String sequence, String owner) { + return null; + } + /** + * Gets the SQL query to get the actual value (previously used) of a sequence, (the sequence is not altered). + * @param sequence - The name of the sequence + * @param owner - The owner (schema) of it + * @return - A string with the SQL query + */ + public String getPrevValue(String sequence, String owner) { + return null; + } + /** + * Returns a query to get the comments on the columns of a table. + * Should return a query to generate a recordset with one row where + * the first and only column is the comment + * @param tableName - The full name of the table qualified with schema if applicable + * @param columnName - The name of the column + */ + public String getCommentsQuery(String tableName, String columnName) { + return null; + } + + /** + * @param table + * @return : A query to get an empty ResultSet (null if failed) for that table or view. + * Subclassed if needed by the different database adapters + */ + public String getEmptySetQuery(String table){ + return "SELECT * FROM " + filterTableName(table) + " WHERE (1 = 0)"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Quotes a string according to the type of the column + * @param string to be quoted + * @param type according to java.sql.Types + * @return + */ + public String quote(String string, int type, String typeString) { + if (isTextType(type, typeString)) { + return "'" + StringUtil.substituteString(string, "'", "''") + "'"; + } else if (type == java.sql.Types.DATE || type == java.sql.Types.TIMESTAMP){ + string = string.trim(); + //Check if we have to strip the millisecods + String sub = string.substring(string.length() - 2, string.length() - 1); + if (string.length() > 1 && sub.equals(".")) //$NON-NLS-1$ + string = string.substring(0, string.length() - 2); // strip the milliseconds + + return "'" + string + "'"; //$NON-NLS-1$ //$NON-NLS-2$ + + } + return string; + } + + /** + * Indicates whether or not a particular type should be quoted in + * SQL statements. Some databases support non-standard types such as + * TEXT that aren't normally recognized as quoted types. + * + * @param type according to java.sql.Types + * @param typeString if the type is "Other". + * @return + */ + protected boolean isTextType(int type, String typeString) { + return SQLHelper.isText(type); + } + + + /** + * Makes an SQL insert string with the given table, names of columns and values + * @param string + * @param namesClause + * @param valuesClause + * @return + */ + public String getInsert(String tableName, String namesClause, String valuesClause) { + String query = "INSERT INTO " + filterTableName(tableName); + if (namesClause != "") { + query += " (" + namesClause + ")"; + query += " VALUES " + "(" + valuesClause; //$NON-NLS-1$ + query += " )"; //$NON-NLS-1$ + } + return query; + } + /** + * Changes the name of the table, usually to allow for lowercase situations. + * The parent implementation does nothing to the tableName, simply returns it. + * @param tableName + * @return + */ + public String filterTableName(String tableName) { + return tableName; + } + /** + * Returns a query to get the number of registers from a table + * @param tableName + * @return + */ + public String getCountQuery(String tableName) { + return "SELECT COUNT(*) FROM " + filterTableName(tableName); + } + /** + * @param string + * @param string2 + * @param whereClause + * @param string3 + */ + public void getUpdate(String tableName, String string2, StringBuffer whereClause, String string3) { + // TODO Auto-generated method stub + + } + /** + * Returns an SQL UPDATE statement + * @param string + * @param string2 + * @param string3 + */ + public String getUpdate(String tableName, String setClause, String whereClause) { + String query = "UPDATE " + filterTableName(tableName); //$NON-NLS-1$ + query += " SET " + setClause; //$NON-NLS-1$ + if (!whereClause.equals("")) query += " WHERE " + whereClause; //$NON-NLS-1$ + return query; + } + /** + * Returns an SQL DELETE statement + * @param string + * @param string2 + * @return + */ + public String getDelete(String tableName, String whereClause) { + String query = "DELETE FROM " + filterTableName(tableName); //$NON-NLS-1$ + if (!whereClause.equals("")) { + query += " WHERE " + whereClause; //$NON-NLS-1$ + } + return query; + } + /** + * @param userid - the userid used to connect to the database + * @return the default schema for the database + */ + public String getDefaultSchema(String userid) { + return userid; + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DriverInfo.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DriverInfo.java new file mode 100644 index 0000000..6b13c1d --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/DriverInfo.java @@ -0,0 +1,57 @@ +package com.quantum.adapters; + +import java.util.Vector; + +public class DriverInfo implements Comparable { + private String driverType; + private String displayName; + private Vector driverNames = new Vector(); + private DatabaseAdapter adapter; + public DriverInfo(String driverType, String displayName, DatabaseAdapter adapter) { + this.driverType = driverType; + this.displayName = displayName; + this.adapter = adapter; + } + + public String getDriverType() { + return driverType; + } + + public void setDriverType(String driverType) { + this.driverType = driverType; + } + + public void addDriverName(String driverName) { + driverNames.addElement(driverName); + } + + public String[] getDriverNames() { + String retVal[] = new String[driverNames.size()]; + for (int i = 0; i < driverNames.size(); i++) { + retVal[i] = (String) driverNames.elementAt(i); + } + return retVal; + } + + public DatabaseAdapter getAdapter() { + return adapter; + } + + public void setAdapter(DatabaseAdapter adapter) { + this.adapter = adapter; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public int compareTo(Object o) { + DriverInfo that = (DriverInfo) o; + return this.getDisplayName().compareTo(that.getDisplayName()); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/FeatureNotSupported.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/FeatureNotSupported.java new file mode 100644 index 0000000..f80aa56 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/FeatureNotSupported.java @@ -0,0 +1,7 @@ +package com.quantum.adapters; + +public class FeatureNotSupported extends Error { + public FeatureNotSupported(String error) { + super(error); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/GenericAdapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/GenericAdapter.java new file mode 100644 index 0000000..bb4eb6b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/GenericAdapter.java @@ -0,0 +1,20 @@ +package com.quantum.adapters; + + + + +public class GenericAdapter extends DatabaseAdapter { + + public String getShowTableQuery(String qualifier, boolean isDefault) { + return null; + } + public String getShowViewQuery(String qualifier, boolean isDefault) { + return null; + } + + public String getShowSequenceQuery(String qualifier, boolean isDefault) { + return null; + } + + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/MySQLAdapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/MySQLAdapter.java new file mode 100644 index 0000000..d764095 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/MySQLAdapter.java @@ -0,0 +1,9 @@ +package com.quantum.adapters; + + + +public class MySQLAdapter extends DatabaseAdapter { + public String getShowTableQuery(String qualifier, boolean isDefault) { + return "SHOW TABLES"; //$NON-NLS-1$ + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/NoSuchAdapterException.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/NoSuchAdapterException.java new file mode 100644 index 0000000..ec71a00 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/NoSuchAdapterException.java @@ -0,0 +1,9 @@ +package com.quantum.adapters; + +import com.quantum.Messages; + +public class NoSuchAdapterException extends Exception { + public NoSuchAdapterException(String driverName) { + super(Messages.getString("Error.NoDatabase") + driverName + Messages.getString("NoSuchAdapterException.<-_2")); //$NON-NLS-1$ //$NON-NLS-2$ + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/OracleAdapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/OracleAdapter.java new file mode 100644 index 0000000..a7fc544 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/OracleAdapter.java @@ -0,0 +1,67 @@ +package com.quantum.adapters; + +import com.quantum.Messages; +import com.quantum.sql.SQLHelper; +import com.quantum.util.QuantumUtil; + + + +public class OracleAdapter extends DatabaseAdapter { + public String getShowSequenceQuery(String qualifier, boolean isDefault) { + return "SELECT SEQUENCE_OWNER, SEQUENCE_NAME FROM ALL_SEQUENCES WHERE SEQUENCE_OWNER = '" + qualifier + "'"; //$NON-NLS-1$ + } + public String getPrevValue(String sequence, String owner) { + return "SELECT LAST_NUMBER FROM ALL_SEQUENCES WHERE SEQUENCE_OWNER = '" + owner + "' AND SEQUENCE_NAME = '" + sequence + "'"; //$NON-NLS-1$ //$NON-NLS-2$ + } + public String getNextValue(String sequence, String owner) { + return "SELECT " + SQLHelper.getQualifiedName(owner, sequence) + ".NEXTVAL FROM DUAL"; + } + public String getCommentsQuery(String tableName, String column) { + String query = "SELECT COMMENTS FROM ALL_COL_COMMENTS WHERE TABLE_NAME = '"; + query += QuantumUtil.getTableName(tableName) + "' AND COLUMN_NAME = '" + column + "'" ; + if (!(QuantumUtil.getSchemaName(tableName).equals(""))) + query += " AND OWNER = '" + QuantumUtil.getSchemaName(tableName) + "'"; + return query; + } + /** + * Quotes a string according to the type of the column + * @param string to be quoted + * @param type according to java.sql.Types + * @return + */ + public String quote(String string, int type, String typeString) { + if (type == java.sql.Types.DATE || type == java.sql.Types.TIMESTAMP) { + string = string.trim(); + String sub = string.substring(string.length()-2, string.length()-1); + if (string.length() > 1 && sub.equals(Messages.getString("OracleAdapter.._3"))) //$NON-NLS-1$ + string = string.substring(0,string.length()-2); + return "TO_DATE('" + string + "','yyyy-mm-dd hh24:mi:ss')"; //$NON-NLS-1$ //$NON-NLS-2$ + } + // use the default (upper type) + return super.quote(string, type, typeString); + } + + /* (non-Javadoc) + * @see com.quantum.adapters.DatabaseAdapter#filterTableName(java.lang.String) + */ + public String filterTableName(String tableName) { + // If there is no mixed case, better not quote, it's prettier on display + if (tableName.equals(tableName.toUpperCase())) return tableName; + // We quote the table name (and only the table name) because it has mixed case + if (QuantumUtil.getSchemaName(tableName).equals("")) + return "\"" + tableName +"\""; //$NON-NLS-1$ + else + return QuantumUtil.getSchemaName(tableName) + ".\"" + + QuantumUtil.getTableName(tableName) + "\""; +} + + /** + * The default schema for Oracle is the upper-case userid. + * @see com.quantum.adapters.DatabaseAdapter#getDefaultSchema(java.lang.String) + */ + public String getDefaultSchema(String userid) { + return super.getDefaultSchema(userid).toUpperCase(); + } + + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/PostgresAdapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/PostgresAdapter.java new file mode 100644 index 0000000..8389bf1 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/PostgresAdapter.java @@ -0,0 +1,70 @@ +package com.quantum.adapters; + +import com.quantum.sql.SQLHelper; +import com.quantum.util.QuantumUtil; +import com.quantum.util.sql.TypesHelper; + + +public class PostgresAdapter extends DatabaseAdapter { + public String getShowTableQuery(String qualifier, boolean isDefault) { + return "SELECT SCHEMANAME, TABLENAME FROM PG_TABLES WHERE SCHEMANAME = '" + + qualifier + "'"; + } + public String getShowViewQuery(String qualifier, boolean isDefault) { + return "SELECT SCHEMANAME, VIEWNAME FROM PG_VIEWS WHERE SCHEMANAME = '" + + qualifier + "'"; + } + public String getShowSequenceQuery(String qualifier, boolean isDefault) { + return "SELECT SCHEMANAME, relname FROM pg_class WHERE relkind = 'S'" + + "AND SCHEMANAME = '" + qualifier + "'"; + } + public String getNextValue(String sequence, String owner) { + return "SELECT NEXTVAL('" + SQLHelper.getQualifiedName(owner, sequence) + "')"; + } + public String getPrevValue(String sequence, String owner) { + return "SELECT * FROM " + SQLHelper.getQualifiedName(owner, sequence); + } + + /** + * Quotes a string according to the type of the column + * @param string to be quoted + * @param type according to java.sql.Types + * @return + */ + public String quote(String string, int type, String typeString) { + // Booleans in PostgreSQL are queried "t" or "f", but require "true" or "false" when inputed. + if (type == TypesHelper.BIT || type == TypesHelper.BOOLEAN ) // Postgresql seems to identify booleans as BITs + { + if (string.indexOf('t') >= 0 || string.indexOf('T') >= 0 ) + return "true"; + else if (string.indexOf('f') >= 0 || string.indexOf('F') >= 0 ) + return "false"; + else + return string; + } + // use the default (upper type) + return super.quote(string, type, typeString); + } + + /** + * @see com.quantum.adapters.DatabaseAdapter#filterTableName(java.lang.String) + */ + public String filterTableName(String tableName) { + // If there is no mixed case, better not quote, it's prettier on display + if (tableName.equals(tableName.toUpperCase())) return tableName; + // We quote the table name (and only the table name) because it has mixed case + if (QuantumUtil.getSchemaName(tableName).equals("")) { + return "\"" + tableName +"\""; //$NON-NLS-1$ + } else { + return QuantumUtil.getSchemaName(tableName) + ".\"" + + QuantumUtil.getTableName(tableName) + "\""; + } + } + /** + * @see com.quantum.adapters.DatabaseAdapter#getDefaultSchema(java.lang.String) + */ + public String getDefaultSchema(String userid) { + return "public"; + } + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/RedBrickAdapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/RedBrickAdapter.java new file mode 100644 index 0000000..623c3be --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/adapters/RedBrickAdapter.java @@ -0,0 +1,23 @@ +package com.quantum.adapters; + + +/** + * @author bcholmes + */ +public class RedBrickAdapter extends DatabaseAdapter { + + public String getShowTableQuery(String qualifier, boolean isDefault) { + return "select name from rbw_tables where type = 'TABLE'"; + } + + public String getShowViewQuery(String qualifier, boolean isDefault) { + return "select name from rbw_tables where type = 'VIEW'"; + } + /** + * @see com.quantum.adapters.DatabaseAdapter#getDefaultSchema(java.lang.String) + */ + public String getDefaultSchema(String userid) { + return null; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/ColorManager.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/ColorManager.java new file mode 100644 index 0000000..a7a662c --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/ColorManager.java @@ -0,0 +1,28 @@ +package com.quantum.editors; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +public class ColorManager { + + protected Map fColorTable = new HashMap(10); + + public void dispose() { + Iterator e= fColorTable.values().iterator(); + while (e.hasNext()) + ((Color) e.next()).dispose(); + } + public Color getColor(RGB rgb) { + Color color= (Color) fColorTable.get(rgb); + if (color == null) { + color= new Color(Display.getCurrent(), rgb); + fColorTable.put(rgb, color); + } + return color; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/NonRuleBasedDamagerRepairer.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/NonRuleBasedDamagerRepairer.java new file mode 100644 index 0000000..6829684 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/NonRuleBasedDamagerRepairer.java @@ -0,0 +1,135 @@ +package com.quantum.editors; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.presentation.IPresentationDamager; +import org.eclipse.jface.text.presentation.IPresentationRepairer; +import org.eclipse.jface.util.Assert; +import org.eclipse.swt.custom.StyleRange; + +public class NonRuleBasedDamagerRepairer + implements IPresentationDamager, IPresentationRepairer { + + /** The document this object works on */ + protected IDocument fDocument; + /** The default text attribute if non is returned as data by the current token */ + protected TextAttribute fDefaultTextAttribute; + + /** + * Constructor for NonRuleBasedDamagerRepairer. + */ + public NonRuleBasedDamagerRepairer(TextAttribute defaultTextAttribute) { + Assert.isNotNull(defaultTextAttribute); + + fDefaultTextAttribute = defaultTextAttribute; + } + + /** + * @see IPresentationRepairer#setDocument(IDocument) + */ + public void setDocument(IDocument document) { + fDocument = document; + } + + public void setTextAttribute(TextAttribute attr) { + fDefaultTextAttribute = attr; + } + + /** + * Returns the end offset of the line that contains the specified offset or + * if the offset is inside a line delimiter, the end offset of the next line. + * + * @param offset the offset whose line end offset must be computed + * @return the line end offset for the given offset + * @exception BadLocationException if offset is invalid in the current document + */ + protected int endOfLineOf(int offset) throws BadLocationException { + + IRegion info = fDocument.getLineInformationOfOffset(offset); + if (offset <= info.getOffset() + info.getLength()) + return info.getOffset() + info.getLength(); + + int line = fDocument.getLineOfOffset(offset); + try { + info = fDocument.getLineInformation(line + 1); + return info.getOffset() + info.getLength(); + } catch (BadLocationException x) { + return fDocument.getLength(); + } + } + + /** + * @see IPresentationDamager#getDamageRegion(ITypedRegion, DocumentEvent, boolean) + */ + public IRegion getDamageRegion( + ITypedRegion partition, + DocumentEvent event, + boolean documentPartitioningChanged) { + if (!documentPartitioningChanged) { + try { + + IRegion info = fDocument.getLineInformationOfOffset(event.getOffset()); + int start = Math.max(partition.getOffset(), info.getOffset()); + + int end = + event.getOffset() + + (event.getText() == null ? event.getLength() : event.getText().length()); + + if (info.getOffset() <= end && end <= info.getOffset() + info.getLength()) { + // optimize the case of the same line + end = info.getOffset() + info.getLength(); + } else + end = endOfLineOf(end); + + end = Math.min(partition.getOffset() + partition.getLength(), end); + return new Region(start, end - start); + + } catch (BadLocationException x) { + } + } + + return partition; + } + + /** + * @see IPresentationRepairer#createPresentation(TextPresentation, ITypedRegion) + */ + public void createPresentation( + TextPresentation presentation, + ITypedRegion region) { + addRange( + presentation, + region.getOffset(), + region.getLength(), + fDefaultTextAttribute); + } + + /** + * Adds style information to the given text presentation. + * + * @param presentation the text presentation to be extended + * @param offset the offset of the range to be styled + * @param length the length of the range to be styled + * @param attr the attribute describing the style of the range to be styled + */ + protected void addRange( + TextPresentation presentation, + int offset, + int length, + TextAttribute attr) { + if (attr != null) + presentation.addStyleRange( + new StyleRange( + offset, + length, + attr.getForeground(), + attr.getBackground(), + attr.getStyle())); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLColorConstants.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLColorConstants.java new file mode 100644 index 0000000..ae519bf --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLColorConstants.java @@ -0,0 +1,13 @@ +package com.quantum.editors; + +import org.eclipse.swt.graphics.RGB; + +public class SQLColorConstants { + public static RGB BACKGROUND = new RGB(255, 0, 255); + public static RGB COMMENT = new RGB(88, 148, 64); + public static RGB IDENTIFIER = new RGB(0, 0, 0); + public static RGB KEYWORD = new RGB(126, 0, 75); + public static RGB STRING = new RGB(0, 0, 255); + public static RGB NUMERIC = new RGB(255, 0, 0); + public static RGB DEFAULT = new RGB(0, 0, 0); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLConfiguration.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLConfiguration.java new file mode 100644 index 0000000..985c0d8 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLConfiguration.java @@ -0,0 +1,89 @@ +package com.quantum.editors; + +import java.util.HashMap; + +import com.quantum.QuantumPlugin; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; + +public class SQLConfiguration extends SourceViewerConfiguration { + private PresentationReconciler reconciler = new PresentationReconciler(); + private ColorManager colorManager; + private HashMap cache = new HashMap(); + private boolean textBold = false; + private boolean keywordBold = true; + private boolean stringBold = false; + private boolean commentBold = false; + private boolean numericBold = false; + public SQLConfiguration(ColorManager colorManager) { + this.colorManager = colorManager; + } + public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { + return new String[] { + IDocument.DEFAULT_CONTENT_TYPE, + SQLPartitionScanner.SQL_COMMENT, + SQLPartitionScanner.SQL_KEYWORD, + SQLPartitionScanner.SQL_IDENTIFIER}; + } + + public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { + initializeColors(); + return reconciler; + } + public void loadPrefs() { + IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore(); + textBold = store.getBoolean("quantum.text.bold"); //$NON-NLS-1$ + keywordBold = store.getBoolean("quantum.keyword.bold"); //$NON-NLS-1$ + stringBold = store.getBoolean("quantum.string.bold"); //$NON-NLS-1$ + commentBold = store.getBoolean("quantum.comment.bold"); //$NON-NLS-1$ + numericBold = store.getBoolean("quantum.numeric.bold"); //$NON-NLS-1$ + SQLColorConstants.BACKGROUND = PreferenceConverter.getColor(store, "quantum.background.color"); //$NON-NLS-1$ + SQLColorConstants.DEFAULT = PreferenceConverter.getColor(store, "quantum.text.color"); //$NON-NLS-1$ + SQLColorConstants.IDENTIFIER = PreferenceConverter.getColor(store, "quantum.text.color"); //$NON-NLS-1$ + SQLColorConstants.KEYWORD = PreferenceConverter.getColor(store, "quantum.keyword.color"); //$NON-NLS-1$ + SQLColorConstants.STRING = PreferenceConverter.getColor(store, "quantum.string.color"); //$NON-NLS-1$ + SQLColorConstants.COMMENT = PreferenceConverter.getColor(store, "quantum.comment.color"); //$NON-NLS-1$ + SQLColorConstants.NUMERIC = PreferenceConverter.getColor(store, "quantum.numeric.color"); //$NON-NLS-1$ + } + public void initializeColors() { + setDamageRepairer(getAttr(SQLColorConstants.KEYWORD, keywordBold), SQLPartitionScanner.SQL_KEYWORD); + setDamageRepairer(getAttr(SQLColorConstants.COMMENT, commentBold), SQLPartitionScanner.SQL_COMMENT); + setDamageRepairer(getAttr(SQLColorConstants.STRING, stringBold), SQLPartitionScanner.SQL_STRING); + setDamageRepairer(getAttr(SQLColorConstants.DEFAULT, textBold), IDocument.DEFAULT_CONTENT_TYPE); + setDamageRepairer(getAttr(SQLColorConstants.DEFAULT, textBold), SQLPartitionScanner.SQL_SYMBOL); + setDamageRepairer(getAttr(SQLColorConstants.DEFAULT, textBold), SQLPartitionScanner.SQL_IDENTIFIER); + setDamageRepairer(getAttr(SQLColorConstants.DEFAULT, textBold), SQLPartitionScanner.SQL_SEPARATOR); + setDamageRepairer(getAttr(SQLColorConstants.NUMERIC, numericBold), SQLPartitionScanner.SQL_NUMERIC); + } + public TextAttribute getAttr(RGB color, boolean bold) { + colorManager.getColor(SQLColorConstants.BACKGROUND); + Color foreground = colorManager.getColor(color); + TextAttribute attr = new TextAttribute(foreground); + if (bold) { + return new TextAttribute(foreground, attr.getBackground(), SWT.BOLD); + } + return attr; + } + public void setDamageRepairer(TextAttribute attr, String token) { + NonRuleBasedDamagerRepairer ndr = (NonRuleBasedDamagerRepairer) cache.get(token); + if (ndr == null) { + ndr = + new NonRuleBasedDamagerRepairer(attr); + reconciler.setDamager(ndr, token); + reconciler.setRepairer(ndr, token); + cache.put(token, ndr); + } else { + ndr.setTextAttribute(attr); + } + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLDocumentProvider.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLDocumentProvider.java new file mode 100644 index 0000000..1fab1c3 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLDocumentProvider.java @@ -0,0 +1,35 @@ +package com.quantum.editors; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.rules.DefaultPartitioner; +import org.eclipse.ui.editors.text.FileDocumentProvider; + +public class SQLDocumentProvider extends FileDocumentProvider { + + public SQLDocumentProvider() { + super(); + } + + protected IDocument createDocument(Object element) throws CoreException { + IDocument document = super.createDocument(element); + if (document != null) { + IDocumentPartitioner partitioner = + new DefaultPartitioner( + new SQLPartitionScanner(), + new String[] { + IDocument.DEFAULT_CONTENT_TYPE, + SQLPartitionScanner.SQL_KEYWORD, + SQLPartitionScanner.SQL_COMMENT, + SQLPartitionScanner.SQL_IDENTIFIER, + SQLPartitionScanner.SQL_STRING, + SQLPartitionScanner.SQL_SEPARATOR, + SQLPartitionScanner.SQL_SYMBOL, + SQLPartitionScanner.SQL_NUMERIC }); + partitioner.connect(document); + document.setDocumentPartitioner(partitioner); + } + return document; + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLEditor.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLEditor.java new file mode 100644 index 0000000..1ceab17 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLEditor.java @@ -0,0 +1,59 @@ +package com.quantum.editors; + +import com.quantum.QuantumPlugin; + +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.editors.text.TextEditor; + +public class SQLEditor extends TextEditor { + SQLConfiguration config; + private ColorManager colorManager; + /** + * An editor capable of editing SQL scripts + */ + public SQLEditor() { + super(); + colorManager = new ColorManager(); + config = new SQLConfiguration(colorManager); + config.loadPrefs(); + + setPreferenceStore(QuantumPlugin.getDefault().getPreferenceStore()); + IPropertyChangeListener preferenceListener = new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + config.loadPrefs(); + config.initializeColors(); + getSourceViewer().invalidateTextPresentation(); + StyledText widget = getSourceViewer().getTextWidget(); + FontData font = PreferenceConverter.getFontData(getPreferenceStore(), "quantum.font"); //$NON-NLS-1$ + widget.setFont(new Font(Display.getCurrent(), font)); + Color background = colorManager.getColor(SQLColorConstants.BACKGROUND); + widget.setBackground(background); + } + }; + getPreferenceStore(). + addPropertyChangeListener(preferenceListener); + + setSourceViewerConfiguration(config); + setDocumentProvider(new SQLDocumentProvider()); + } + public void dispose() { + colorManager.dispose(); + super.dispose(); + } + public void createPartControl(Composite arg0) { + super.createPartControl(arg0); + StyledText widget = getSourceViewer().getTextWidget(); + FontData font = PreferenceConverter.getFontData(getPreferenceStore(), "quantum.font"); //$NON-NLS-1$ + widget.setFont(new Font(Display.getCurrent(), font)); + Color background = colorManager.getColor(SQLColorConstants.BACKGROUND); + widget.setBackground(background); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLPartitionScanner.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLPartitionScanner.java new file mode 100644 index 0000000..01898d1 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/editors/SQLPartitionScanner.java @@ -0,0 +1,225 @@ +package com.quantum.editors; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IPredicateRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWhitespaceDetector; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; + +public class SQLPartitionScanner extends RuleBasedPartitionScanner { + public final static String SQL_COMMENT = "__sql_comment"; //$NON-NLS-1$ + public final static String SQL_IDENTIFIER = "__sql_word"; //$NON-NLS-1$ + public final static String SQL_STRING = "__sql_string"; //$NON-NLS-1$ + public final static String SQL_KEYWORD = "__sql_keyword"; //$NON-NLS-1$ + public final static String SQL_SYMBOL = "__sql_symbol"; //$NON-NLS-1$ + public final static String SQL_SEPARATOR = "__sql_separator"; //$NON-NLS-1$ + public final static String SQL_NUMERIC = "__sql_numeric"; //$NON-NLS-1$ + + private final static String[] KEYWORDS = { + "ALTER", //$NON-NLS-1$ + "AND", //$NON-NLS-1$ + "BY", //$NON-NLS-1$ + "COLUMN", //$NON-NLS-1$ + "CREATE", //$NON-NLS-1$ + "DELETE", //$NON-NLS-1$ + "DROP", //$NON-NLS-1$ + "FROM", //$NON-NLS-1$ + "GROUP", //$NON-NLS-1$ + "INSERT", //$NON-NLS-1$ + "INTO", //$NON-NLS-1$ + "NOT", //$NON-NLS-1$ + "NULL", //$NON-NLS-1$ + "OR", //$NON-NLS-1$ + "ORDER", //$NON-NLS-1$ + "SELECT", //$NON-NLS-1$ + "SEQUENCE", //$NON-NLS-1$ + "SET", //$NON-NLS-1$ + "TABLE", //$NON-NLS-1$ + "UNION", //$NON-NLS-1$ + "UNIQUE", //$NON-NLS-1$ + "UPDATE", //$NON-NLS-1$ + "USING", //$NON-NLS-1$ + "VALUES", //$NON-NLS-1$ + "VIEW", //$NON-NLS-1$ + "WHEN", //$NON-NLS-1$ + "WHERE" //$NON-NLS-1$ + }; + + public SQLPartitionScanner() { + + List rules = new ArrayList(); + + IToken comment = new Token(SQL_COMMENT); + IToken string = new Token(SQL_STRING); + IToken identifier = new Token(SQL_IDENTIFIER); + IToken keyword = new Token(SQL_KEYWORD); + IToken separator = new Token(SQL_SEPARATOR); + IToken symbol = new Token(SQL_SYMBOL); + IToken whitespace = new Token(IDocument.DEFAULT_CONTENT_TYPE); + IToken numeric = new Token(SQL_NUMERIC); + + rules.add(new PredicateRuleAdapter(new WhitespaceRule(new WhitespaceDetector()), whitespace)); + rules.add(new MultiLineRule("/*", "*/", comment)); //$NON-NLS-1$ //$NON-NLS-2$ + rules.add(new EndOfLineRule("--", comment)); //$NON-NLS-1$ + rules.add(new SingleLineRule("'", "'", string)); //$NON-NLS-1$ //$NON-NLS-2$ + rules.add(new PredicateRuleAdapter(new SQLNumberRule(numeric), numeric)); + SQLWordRule wordRule = new SQLWordRule(identifier); + for (int i = 0; i < KEYWORDS.length; i++) { + wordRule.addKeyword(KEYWORDS[i], keyword); + } + rules.add(new PredicateRuleAdapter(wordRule, keyword)); + rules.add(new PredicateRuleAdapter(wordRule, identifier)); + rules.add(new PredicateRuleAdapter(new SQLSeparatorRule(separator), separator)); + rules.add(new PredicateRuleAdapter(new SymbolRule(symbol), symbol)); + + IPredicateRule[] result= new IPredicateRule[rules.size()]; + rules.toArray(result); + setPredicateRules(result); + } +} + +class PredicateRuleAdapter implements IPredicateRule { + IRule rule; + IToken token; + public PredicateRuleAdapter(IRule rule, IToken token) { + this.rule = rule; + this.token = token; + } + + public IToken evaluate(ICharacterScanner scanner, boolean resume) { + return rule.evaluate(scanner); + } + + public IToken getSuccessToken() { + return token; + } + + public IToken evaluate(ICharacterScanner scanner) { + return rule.evaluate(scanner); + } + +} + +class SQLSeparatorRule implements IRule { + IToken token; + public SQLSeparatorRule(IToken token) { + this.token = token; + } + public IToken evaluate(ICharacterScanner scanner) { + char c = (char) scanner.read(); + if (c == ';') { + return token; + } + scanner.unread(); + return Token.UNDEFINED; + } + +} + +class SymbolRule implements IRule { + IToken token; + public SymbolRule(IToken token) { + this.token = token; + } + public IToken evaluate(ICharacterScanner scanner) { + int val = scanner.read(); + if (val != ICharacterScanner.EOF) { + char c = (char) val; + if (!Character.isWhitespace(c) && !Character.isLetterOrDigit(c) && c != '_') { + return token; + } + } + scanner.unread(); + return Token.UNDEFINED; + } + +} + +class WhitespaceDetector implements IWhitespaceDetector { + + public boolean isWhitespace(char c) { + return Character.isWhitespace(c); + } +} + +class SQLNumberRule implements IRule { + private IToken token; + + public SQLNumberRule(IToken token) { + this.token = token; + } + + public IToken evaluate(ICharacterScanner scanner) { + char c = (char) scanner.read(); + if (Character.isDigit(c)) { + // postive numbers and zero + do { + c= (char) scanner.read(); + } while (Character.isDigit(c) || c == '.'); + scanner.unread(); + return token; + } else if (c == '-') { + // negative numbers + c = (char) scanner.read(); + if (Character.isDigit(c)) { + do { + c= (char) scanner.read(); + } while (Character.isDigit(c) || c == '.'); + scanner.unread(); + return token; + } else { + scanner.unread(); + scanner.unread(); + return Token.UNDEFINED; + } + } else { + scanner.unread(); + return Token.UNDEFINED; + } + } +} + +class SQLWordRule implements IRule { + private IToken token; + private HashMap keywords = new HashMap(); + + public SQLWordRule(IToken token) { + this.token = token; + } + + public void addKeyword(String word, IToken token) { + keywords.put(word.toUpperCase(), token); + } + + public IToken evaluate(ICharacterScanner scanner) { + char c = (char) scanner.read(); + if (Character.isLetter(c) || c == '_') { + StringBuffer value = new StringBuffer(); + do { + value.append(c); + c= (char) scanner.read(); + } while (Character.isLetterOrDigit(c) || c == '_'); + scanner.unread(); + IToken retVal = (IToken) keywords.get(value.toString().toUpperCase()); + if (retVal != null) { + return retVal; + } else { + return token; + } + } else { + scanner.unread(); + return Token.UNDEFINED; + } + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/ExtensionAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/ExtensionAction.java new file mode 100644 index 0000000..50a35db --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/ExtensionAction.java @@ -0,0 +1,132 @@ +/* + * Created on 17/02/2004 + * + */ +package com.quantum.extensions; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Iterator; + +import javax.xml.parsers.ParserConfigurationException; + +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.xml.ModelToXMLConverter; +import com.quantum.sql.TableRow; +import com.quantum.sql.metadata.MetaDataXMLInterface; +import com.quantum.util.xml.XMLHelper; +import com.quantum.view.bookmark.BookmarkView; +import com.quantum.view.bookmark.EntityNode; +import com.quantum.view.bookmark.TreeNode; +import com.quantum.view.tableview.TableView; + +/** + * @author panic + * + * Defines an Action Class to implement extension Actions. + * An external plug-in that wants to extend quantum will + * generate one ExtensionAction object for each action it + * wants to perform. + */ +public class ExtensionAction extends SelectionListenerAction { + private IViewPart view; + private IQuantumExtension extension; + private TableRow tableRow; + + public ExtensionAction(IViewPart view, String label, String toolTip, IQuantumExtension extension) { + super(label); + this.view = view; + this.extension = extension; + + setText(label); + setToolTipText(toolTip); //$NON-NLS-1$ + tableRow = null; + } + + public void run() { + if (extension instanceof IMetadataExtension && view instanceof BookmarkView) + runMetadataExtension(); + else if (extension instanceof IDataExtension && view instanceof TableView) + runDataExtension(); + } + + /** + * + */ + private void runDataExtension() { + IDataExtension dataExtension = (IDataExtension) extension; + if (tableRow == null) return; + Document doc; + try { + doc = XMLHelper.createEmptyDocument(); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + return; + } + Element root = (Element) doc.appendChild(doc.createElement(Messages.getString("ExportXMLAction.Metadata"))); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(root, Messages.getString("ExportXMLAction.Author"), //$NON-NLS-1$ + Messages.getString("ExportXMLAction.Quantum")); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(root, Messages.getString("ExportXMLAction.Version"), //$NON-NLS-1$ + Messages.getString("ExportXMLAction.XMLVersionNumber")); //$NON-NLS-1$ + ModelToXMLConverter.getInstance().convert(root, tableRow.getEntity() ); + MetaDataXMLInterface.stringMatrixToXML(tableRow.getRowTableData(), doc, root, "DataRow"); //$NON-NLS-1$ + + dataExtension.run(doc); + } + + private void runMetadataExtension() { + IMetadataExtension metadataExtension = (IMetadataExtension) extension; + BookmarkView bookmarkView = (BookmarkView) view; + StructuredSelection selection = bookmarkView.getSelection(); + if (selection == null) return; + Document doc; + try { + doc = XMLHelper.createEmptyDocument(); + } catch (ParserConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } + Element root = (Element) doc.appendChild(doc.createElement(Messages.getString("ExportXMLAction.Metadata"))); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(root, Messages.getString("ExportXMLAction.Author"), //$NON-NLS-1$ + Messages.getString("ExportXMLAction.Quantum")); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(root, Messages.getString("ExportXMLAction.Version"), //$NON-NLS-1$ + Messages.getString("ExportXMLAction.XMLVersionNumber")); //$NON-NLS-1$ + Iterator iter = selection.iterator(); + while (iter.hasNext()) { + TreeNode current = (TreeNode) iter.next(); + EntityNode entityNode = (EntityNode) current; + ModelToXMLConverter.getInstance().convert(root, entityNode.getEntity() ); + } + + StringWriter text = new StringWriter(); + try { + XMLHelper.createDOMSerializer(text).serialize(doc); + } catch (IOException e) { + e.printStackTrace(); + } + String textXml = new String(text.getBuffer()); + QuantumPlugin.getDefault().getSysClip().setContents( + new Object[] { textXml }, + new Transfer[] { TextTransfer.getInstance()}); + + metadataExtension.run(doc); + } + + /** + * @param row + */ + public void addRowData(TableRow row) { + tableRow = row; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IDataExtension.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IDataExtension.java new file mode 100644 index 0000000..9149235 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IDataExtension.java @@ -0,0 +1,21 @@ +/* + * Created on 21/03/2004 + * + */ +package com.quantum.extensions; + +import org.w3c.dom.Document; + +/** + * @author panic + * + */ +public interface IDataExtension extends IQuantumExtension { + /** + * Callback method for data export + * + * @param doc. An org.w3c.dom.Document with the XML data on the selected items + */ + public void run(Document doc); + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IMetadataExtension.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IMetadataExtension.java new file mode 100644 index 0000000..34298c7 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IMetadataExtension.java @@ -0,0 +1,21 @@ +/* + * Created on 15/02/2004 + * + */ +package com.quantum.extensions; + +import org.w3c.dom.Document; + +/** + * @author panic + * + */ +public interface IMetadataExtension extends IQuantumExtension{ + /** + * Callback method for metadata export + * + * @param doc. An org.w3c.dom.Document with the XML data on the selected items + */ + public void run(Document doc); + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IQuantumExtension.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IQuantumExtension.java new file mode 100644 index 0000000..e9806c3 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/IQuantumExtension.java @@ -0,0 +1,13 @@ +/* + * Created on 17/02/2004 + * + */ +package com.quantum.extensions; + +/** + * @author panic + * A commom parent for the Quantum Extensions + */ +public interface IQuantumExtension { + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/ProcessServiceMembers.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/ProcessServiceMembers.java new file mode 100644 index 0000000..30ca7f2 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/extensions/ProcessServiceMembers.java @@ -0,0 +1,281 @@ + +/* + * Created on 16-feb-2004 + * + */ +package com.quantum.extensions; +import java.util.Vector; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IPluginRegistry; +import org.eclipse.core.runtime.Platform; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.WorkbenchException; +import org.w3c.dom.Document; + +import com.quantum.view.bookmark.BookmarkView; +import com.quantum.view.tableview.TableView; + +/** + * Extension processing logic for the functions extension-point. + * Extract specific information about each function. Create callback + * function object when required. + * + * @author panic + * + */ +public class ProcessServiceMembers { + + /** + * The fully-qualified name of the functions extension-point for this plug-in. + */ + private static final String EXTENSION_POINT_METADATA = + "com.quantum.Quantum.metadata"; + private static final String EXTENSION_POINT_DATA = + "com.quantum.Quantum.data"; + + /** + * Name of the XML attribute designating a metadata actor label. + */ + private static final String FUNCTION_NAME_ATTRIBUTE = "label"; + + /** + * Name of the XML attribute designating the fully-qualified name + * of the implementation class of a function. + */ + private static final String CLASS_ATTRIBUTE = "class"; + + /** + * Perform initial extension processing for the members of the + * functions extension-point. Make calls to the user interface + * module to add the functions of an extension to the UI functions grid. + * For each function, a virtual proxy callback object is created and handed + * to the user interface module. The proxy class is a nested top-level + * class and is therefore known at compile time. The actual (real) callback + * objects configured into extensions are instantiated and initialized in + * a lazy fashion by the proxy callback objects. + * + * @param grid The UI functions grid exposing the functions configured + * into functions extensions. + * + */ + public static void process(IViewPart view, Vector extensionActions) throws WorkbenchException { + + extensionActions.clear(); + + IPluginRegistry registry = Platform.getPluginRegistry(); + String extPointId; + // We have two different extension points, we choose the needed one based + // on the view that calls this function. + // Our two extension points have the same attributes, so the only change is the name + // If the implementation differed more, we should probably make two different functions + if (view instanceof BookmarkView) + extPointId = EXTENSION_POINT_METADATA; + else if (view instanceof TableView) + extPointId = EXTENSION_POINT_DATA; + else + return; + + IExtensionPoint extensionPoint = + registry.getExtensionPoint(extPointId); + if (extensionPoint == null) { + throw new WorkbenchException( + "unable to resolve extension-point: " + extPointId); + } + IConfigurationElement[] members = + extensionPoint.getConfigurationElements(); + + // For each service: + for (int m = 0; m < members.length; m++) { + IConfigurationElement member = members[m]; + // Get the label of the extender plugin and the ID of the extension. + IExtension extension = member.getDeclaringExtension(); + String pluginLabel = + extension.getDeclaringPluginDescriptor().getLabel(); + if (pluginLabel == null) { + pluginLabel = "[unnamed plugin]"; + } + // Get the name of the operation implemented by the service. + // The operation name is a service attribute in the extension's XML specification. + String functionName = member.getAttribute(FUNCTION_NAME_ATTRIBUTE); + if (functionName == null) { + functionName = "[unnamed function]"; + } + String label = pluginLabel + "/" + functionName; + // Add a row to support this operation to the UI grid. + IQuantumExtension proxy = null; + if (view instanceof BookmarkView) + proxy = (IMetadataExtension) new MetadataFunctionProxy(member); + else if (view instanceof TableView) + proxy = (IDataExtension) new DataFunctionProxy(member); + //grid.addFunction(proxy, functionName, label); + extensionActions.add(new ExtensionAction(view, label, label, proxy)); + } + } + + /** + * Virtual proxy class for function invokation. + * Members of this class support lazy processing by fronting the real + * implementations of arithmetic functions configured into extensions. + */ + private static class MetadataFunctionProxy implements IMetadataExtension { + // The "real" implementation of the function. + private IMetadataExtension delegate = null; + // The configured state of the extension element representing this arithmetic function. + private IConfigurationElement element; + // Whether this function has been invoked before. + // Used for lazy evaluation of the service. + private boolean invoked = false; + + /** + * Construct a virtual proxy to stand in place of an extension function. + * The constructor simply keeps track of an arithmetic function's configured state + * without at this time instantiating the implementation of the function. + * + * @param element The configuration of this arithmetic function. + */ + public MetadataFunctionProxy(IConfigurationElement element) { + this.element = element; + } + + /** + * Compute the function value. + * The proxy computation first instantiates the implementation + * of the function, if this is the first time the function is called, + * and then delegates to that implementation. The instantiation and + * initialization of the delegate implementation uses the standard + * callback object instantiation and initialization methods of Eclipse. + * + * @see com.bolour.sample.eclipse.service.ui.IFunction#compute(long) + */ + public final void run(Document doc) { + try { + getDelegate().run(doc); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Instantiate and initialize the implementation of the function if + * this is the first time the proxy has been called. + * + * @return The implementation delegate (same as the instance variable delegate. + * @throws Exception If the callback object is misconfigured. + */ + private final IMetadataExtension getDelegate() throws Exception { + if (invoked) { + return delegate; + } + invoked = true; + try { + Object callback = + element.createExecutableExtension(CLASS_ATTRIBUTE); + if (!(callback instanceof IMetadataExtension)) { + String message = + "callback class '" + + callback.getClass().getName() + + "' is not an IFunction"; + System.err.println(message); + throw new ClassCastException(message); + } + delegate = (IMetadataExtension) callback; + } catch (CoreException ex) { + System.err.println(ex.getMessage()); + ex.printStackTrace(); + throw ex; + } catch (Error err) { + System.err.println(err.getMessage()); + err.printStackTrace(); + throw err; + } + return delegate; + } + } + /** + * Virtual proxy class for function invokation. + * Members of this class support lazy processing by fronting the real + * implementations of arithmetic functions configured into extensions. + */ + private static class DataFunctionProxy implements IDataExtension { + // The "real" implementation of the function. + private IDataExtension delegate = null; + // The configured state of the extension element representing this arithmetic function. + private IConfigurationElement element; + // Whether this function has been invoked before. + // Used for lazy evaluation of the service. + private boolean invoked = false; + + /** + * Construct a virtual proxy to stand in place of an extension function. + * The constructor simply keeps track of an arithmetic function's configured state + * without at this time instantiating the implementation of the function. + * + * @param element The configuration of this arithmetic function. + */ + public DataFunctionProxy(IConfigurationElement element) { + this.element = element; + } + + /** + * Compute the function value. + * The proxy computation first instantiates the implementation + * of the function, if this is the first time the function is called, + * and then delegates to that implementation. The instantiation and + * initialization of the delegate implementation uses the standard + * callback object instantiation and initialization methods of Eclipse. + * + * @see com.bolour.sample.eclipse.service.ui.IFunction#compute(long) + */ + public final void run(Document doc) { + try { + getDelegate().run(doc); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Instantiate and initialize the implementation of the function if + * this is the first time the proxy has been called. + * + * @return The implementation delegate (same as the instance variable delegate. + * @throws Exception If the callback object is misconfigured. + */ + private final IDataExtension getDelegate() throws Exception { + if (invoked) { + return delegate; + } + invoked = true; + try { + Object callback = + element.createExecutableExtension(CLASS_ATTRIBUTE); + if (!(callback instanceof IDataExtension)) { + String message = + "callback class '" + + callback.getClass().getName() + + "' is not an IFunction"; + System.err.println(message); + throw new ClassCastException(message); + } + delegate = (IDataExtension) callback; + } catch (CoreException ex) { + System.err.println(ex.getMessage()); + ex.printStackTrace(); + throw ex; + } catch (Error err) { + System.err.println(err.getMessage()); + err.printStackTrace(); + throw err; + } + return delegate; + } + } + +} + diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Bookmark.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Bookmark.java new file mode 100644 index 0000000..d2dff2b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Bookmark.java @@ -0,0 +1,525 @@ +package com.quantum.model; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.quantum.IQuantumConstants; +import com.quantum.QuantumPlugin; +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.sql.ConnectionEstablisher; +import com.quantum.sql.MultiSQLServer; + +import org.eclipse.jface.preference.IPreferenceStore; + +/** + * Class Bookmark holds the "static" information of a bookmark, that is the data that + * is saved and loaded from the external file and describes a bookmark. This info will + * be filled up by the end user. + * + * @author root + */ +public class Bookmark { + + private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); + private String name = ""; //$NON-NLS-1$ + private String username = ""; //$NON-NLS-1$ + private String password = ""; //$NON-NLS-1$ + private String connect = ""; //$NON-NLS-1$ + private String driver = ""; //$NON-NLS-1$ + private String type = ""; //$NON-NLS-1$ + private String driverFile = ""; //$NON-NLS-1$ + + /** + * A quick list is a list of favourite tables that a person might want to view + * without having to look at the entire list of tables. + */ + private Map quickList = new Hashtable(); + private Set schemas = new HashSet(); + private Connection connection = null; + private ConnectionEstablisher connectionEstablisher; + private boolean changed = true; + private List queries = Collections.synchronizedList(new ArrayList()); + private boolean promptForPassword = false; + private boolean autoCommit = true; + private String autoCommitPreference = IQuantumConstants.autoCommitTrue; + + public Bookmark() { + this(MultiSQLServer.getInstance()); + } + + public Bookmark(ConnectionEstablisher connectionEstablisher) { + this.connectionEstablisher = connectionEstablisher; + } + + public Bookmark(Bookmark data) { + this(); + setName(data.getName()); + setUsername(data.getUsername()); + setPassword(data.getPassword()); + setConnect(data.getConnect()); + setDriver(data.getDriver()); + setType(data.getType()); + setDriverFile(data.getDriverFile()); + setPromptForPassword(data.getPromptForPassword()); + setAutoCommit(data.isAutoCommit()); + setAutoCommitPreference(data.getAutoCommitPreference()); + + this.schemas.addAll(data.schemas); + this.quickList = new Hashtable(data.quickList); + } + + /** + * Returns the JDBC URL. + * @return String + */ + public String getConnect() { + return connect; + } + + /** + * Returns the driver. + * @return String + */ + public String getDriver() { + return driver; + } + + /** + * Returns the driverFile. + * @return String + */ + public String getDriverFile() { + return driverFile; + } + + /** + * Returns the password. + * @return String + */ + public String getPassword() { + return password; + } + + /** + * Returns the username. + * @return String + */ + public String getUsername() { + return username; + } + + /** + * Sets the connect. + * @param connect The connect to set + */ + public void setConnect(String connect) { + if (connect == null) { + connect = ""; //$NON-NLS-1$ + } + this.connect = connect; + } + + /** + * Sets the driver. + * @param driver The driver to set + */ + public void setDriver(String driver) { + if (driver == null) { + driver = ""; //$NON-NLS-1$ + } + this.driver = driver; + } + + /** + * Sets the driverFile. + * @param driverFile The driverFile to set + */ + public void setDriverFile(String driverFile) { + if (driverFile == null) { + driverFile = ""; //$NON-NLS-1$ + } + this.driverFile = driverFile; + } + + /** + * Sets the password. + * @param password The password to set + */ + public void setPassword(String password) { + if (password == null) { + password = ""; //$NON-NLS-1$ + } + this.password = password; + } + + /** + * Sets the username. + * @param username The username to set + */ + public void setUsername(String username) { + if (username == null) { + username = ""; //$NON-NLS-1$ + } + this.username = username; + } + + /** + * Returns the name. + * @return String + */ + public String getName() { + return name; + } + + /** + * Sets the name. + * @param name The name to set + */ + public void setName(String name) { + if (name == null) { + name = ""; //$NON-NLS-1$ + } + if (!name.equals(this.name)) { + + String oldName = this.name; + this.name = name; + this.propertyChangeSupport.firePropertyChange("name", oldName, this.name); + this.changed = true; + } + } + + public boolean isEmpty() { + if (name.equals("") && //$NON-NLS-1$ + username.equals("") && //$NON-NLS-1$ + password.equals("") && //$NON-NLS-1$ + connect.equals("") && //$NON-NLS-1$ + driver.equals("") && //$NON-NLS-1$ + type.equals("") && //$NON-NLS-1$ + driverFile.equals("")) { //$NON-NLS-1$ + return true; + } + return false; + } + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("["); //$NON-NLS-1$ + buffer.append("name="); //$NON-NLS-1$ + buffer.append(name); + buffer.append(", "); //$NON-NLS-1$ + buffer.append("username="); //$NON-NLS-1$ + buffer.append(username); + buffer.append(", "); //$NON-NLS-1$ + buffer.append("password=****"); //$NON-NLS-1$ + buffer.append(", "); //$NON-NLS-1$ + buffer.append("connect="); //$NON-NLS-1$ + buffer.append(connect); + buffer.append(", "); //$NON-NLS-1$ + buffer.append("driver="); //$NON-NLS-1$ + buffer.append(driver); + buffer.append(", "); //$NON-NLS-1$ + buffer.append("type="); //$NON-NLS-1$ + buffer.append(type); + buffer.append(", "); //$NON-NLS-1$ + buffer.append("driverFile="); //$NON-NLS-1$ + buffer.append(driverFile); + buffer.append("]"); //$NON-NLS-1$ + return buffer.toString(); + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Connection connect(PasswordFinder passwordFinder) throws ConnectionException { + boolean isConnected = isConnected(); + if (this.connection == null) { + this.connection = this.connectionEstablisher.connect(this, passwordFinder); + } + + if (isConnected() != isConnected) { + this.propertyChangeSupport.firePropertyChange( + "connected", isConnected, isConnected()); + } + return this.connection; + } + + /** + * Returns the connection object. + * @return the Connection object associated with the current JDBC source. + * + */ + public Connection getConnection() throws NotConnectedException { + if (this.connection == null) { + throw new NotConnectedException(); + } + return this.connection; + } + + /** + * @return true if the BookmarkNode is connected to a JDBC source + */ + public boolean isConnected() { + return (connection != null); + } + + /** + * Sets the connection member. From that moment on the BookmarkNode is "connected" (open) + * @param connection : a valid connection to a JDBC source + */ + public void setConnection(Connection connection) { + this.connection = connection; + } + + public void disconnect() throws ConnectionException { + boolean isConnected = isConnected(); + try { + if (this.connection != null) { + this.connectionEstablisher.disconnect(this.connection); + } + } finally { + this.connection = null; + if (isConnected() != isConnected) { + this.propertyChangeSupport.firePropertyChange( + "connected", isConnected, isConnected()); + } + } + } + public void addSchema(String schema) { + if (schema != null && schema.trim().length() > 0) { + addSchema(new Schema(schema)); + } + } + + public void addSchema(Schema qualifier) { + if (qualifier != null) { + this.schemas.add(qualifier); + this.changed = true; + this.propertyChangeSupport.firePropertyChange("schemas", null, null); + } + } + + public void setSchemas(Schema[] schemas) { + this.schemas.clear(); + for (int i = 0, length = (schemas == null) ? 0 : schemas.length; + i < length; + i++) { + this.schemas.add(schemas[i]); + + } + this.changed = true; + this.propertyChangeSupport.firePropertyChange("schemas", null, null); + } + + /** + * @return a list of all the schemas that have been set up. + */ + public Schema[] getSchemas() { + Set set = new HashSet(); + set.addAll(this.schemas); + if (set.isEmpty()) { + set.add(new Schema(getAdapter().getDefaultSchema(this.username), + this.username, true)); + } + List list = new ArrayList(set); + Collections.sort(list); + return (Schema[]) list.toArray(new Schema[list.size()]); + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (!(obj instanceof Bookmark)) return false; + String name = ((Bookmark)obj).getName(); + if (name.equals(this.getName())) return true; + return false; + } + + /** + * @param listener + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + this.propertyChangeSupport.addPropertyChangeListener(listener); + } + + /** + * @param listener + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + this.propertyChangeSupport.removePropertyChangeListener(listener); + } + + public void addQuickListEntry(String type, String schemaName, String name) { + Entity entity = EntityFactory.getInstance().create(this, schemaName, name, type); + this.quickList.put(entity.getCondQualifiedName(), entity); + this.propertyChangeSupport.firePropertyChange("quickList", null, null); + this.changed = true; + } + + public void addQuickListEntry(Entity entity) { + addQuickListEntry(entity.getType(), entity.getSchema(), entity.getName()); + } + + public void removeQuickListEntry(Entity entity) { + if (entity != null && this.quickList.containsKey(entity.getCondQualifiedName())) { + this.quickList.remove(entity.getCondQualifiedName()); + this.propertyChangeSupport.firePropertyChange("quickList", null, null); + this.changed = true; + } + } + + public Entity[] getQuickListEntries() { + return (Entity[]) this.quickList.values().toArray(new Entity[this.quickList.size()]); + } + + public boolean hasQuickList() { + return !this.quickList.isEmpty(); + } + /** + * @return + */ + public boolean isChanged() { + return changed; + } + + /** + * @param b + */ + public void setChanged(boolean b) { + changed = b; + } + + public Database getDatabase() throws NotConnectedException { + if (!isConnected()) { + throw new NotConnectedException(); + } + return new Database(this); + } + + public DatabaseAdapter getAdapter() { + return AdapterFactory.getInstance().getAdapter(getType()); + } + + public Entity[] getEntitiesForSchema(Schema schema, String type) throws SQLException { + try { + Entity[] entities = getDatabase().getEntities(this, schema, type); + return entities; + } catch (NotConnectedException e) { + return new Entity[0]; + } + } + + public Entity getEntity(Schema schema, String name) throws SQLException { + Entity result = null; + if (schema != null && name != null) { + Entity[] entities = getEntitiesForSchema(schema, null); + for (int i = 0, length = (entities == null) ? 0 : entities.length; + result == null && i < length; + i++) { + if (schema.equals(entities[i].getSchema()) && + name.equals(entities[i].getName())) { + result = entities[i]; + } + } + } + return result; + } + + public boolean isInQuickList(Entity entity) { + return this.quickList.containsKey(entity.getCondQualifiedName()); + } + + /** + * + * @param queryString + */ + public void addQuery(String queryString) { + if (this.queries.contains(queryString)) { + this.queries.remove(queryString); + } + this.queries.add(queryString); + + int size = getQueryHistorySize(); + + while (this.queries.size() > size) { + this.queries.remove(0); + } + this.propertyChangeSupport.firePropertyChange("queries", null, null); + this.changed = true; + } + + public String[] getQueries() { + return (String[]) this.queries.toArray(new String[this.queries.size()]); + } + + private int getQueryHistorySize() { + IPreferenceStore store = + QuantumPlugin.getDefault().getPreferenceStore(); + return store.getInt(getClass().getName() + ".queryHistorySize"); //$NON-NLS-1$ + } + /** + * @return + */ + public boolean getPromptForPassword() { + return promptForPassword; + } + + /** + * @param b + */ + public void setPromptForPassword(boolean b) { + promptForPassword = b; + } + + /** + * @return + */ + public boolean isAutoCommit() { + return autoCommit; + } + + /** + * @return + */ + public String getAutoCommitPreference() { + return autoCommitPreference; + } + + /** + * @param b + */ + public void setAutoCommit(boolean b) { + autoCommit = b; + } + + /** + * @param string + */ + public void setAutoCommitPreference(String string) { + autoCommitPreference = string; + } + + // Returns true or false indicating whether this bookmark must be set to AutoCommit on connection or not + public boolean getDefaultAutoCommit(){ + if (autoCommitPreference.equals(IQuantumConstants.autoCommitTrue)) return true; + else if (autoCommitPreference.equals(IQuantumConstants.autoCommitFalse)) return false; + else if (autoCommitPreference.equals(IQuantumConstants.autoCommitSaved)) return autoCommit; + + return true; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/BookmarkCollection.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/BookmarkCollection.java new file mode 100644 index 0000000..58a854e --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/BookmarkCollection.java @@ -0,0 +1,312 @@ +package com.quantum.model; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Vector; + +import com.quantum.IQuantumConstants; +import com.quantum.Messages; +import com.quantum.model.xml.ModelToXMLConverter; +import com.quantum.sql.metadata.MetaDataXMLInterface; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * The collection of database bookmarks that the Quantum plug-in knows about. + * This collection is loaded by the QuantumPlugin class before any Quantum plugin + * extension is invoked. + * + * @author BC + */ +public class BookmarkCollection { + + private static BookmarkCollection instance = new BookmarkCollection(); + private List bookmarks = new Vector(); + private boolean changed = false; + private PropertyChangeSupport support = new PropertyChangeSupport(this); + + private BookmarkCollection() { + } + + /** + * Singleton accessor + */ + public static BookmarkCollection getInstance() { + return BookmarkCollection.instance; + } + + /** + * Imports the bookmars from a properties file. This load method is + * provided for backwards compatability only; we no longer persist + * bookmarks as properties files. + * @param file + */ + public void load(File file) throws IOException { + Properties props = new Properties(); + FileInputStream in = new FileInputStream(file); + props.load(in); + in.close(); + fromProperties(true, props); + } + + private void fromProperties(boolean overwrite, Properties props) { + List newBookmarks = new Vector(); + int i = 0; + while (true) { + Bookmark bookmark = new Bookmark(); + String name = props.getProperty(i + ".name"); //$NON-NLS-1$ + if (name == null) { + break; + } + bookmark.setName(name); + bookmark.setUsername(props.getProperty(i + ".username")); //$NON-NLS-1$ + bookmark.setPassword(props.getProperty(i + ".password")); //$NON-NLS-1$ + bookmark.setConnect(props.getProperty(i + ".connect")); //$NON-NLS-1$ + bookmark.setDriver(props.getProperty(i + ".driver")); //$NON-NLS-1$ + String schema = props.getProperty(i + ".schema"); //$NON-NLS-1$ + if (schema != null) { + bookmark.addSchema(schema); + } + String type = props.getProperty(i + ".type"); //$NON-NLS-1$ + if (type != null) { + bookmark.setType(type); + } else { + bookmark.setType(""); //$NON-NLS-1$ + } + String driverFile = props.getProperty(i + ".driverLocation"); //$NON-NLS-1$ + if (driverFile != null) { + bookmark.setDriverFile(driverFile); + } else { + bookmark.setDriverFile(""); //$NON-NLS-1$ + } + System.out.println(bookmark.toString()); + if (!bookmark.isEmpty()) { + newBookmarks.add(bookmark); + } + i++; + } + if (overwrite) { + this.bookmarks = newBookmarks; + } else { + this.bookmarks.addAll(newBookmarks); + } + } + /** + * Finds a Bookmark with the specified name. + * + * @param name + * @return the bookmark with the specified name, or null if no bookmark can be found + */ + public Bookmark find(String name){ + Bookmark result = null; + if (name != null) { + for (Iterator i = this.bookmarks.iterator(); result == null && i.hasNext(); ) { + Bookmark temp = (Bookmark) i.next(); + if (name.equals(temp.getName())) { + result = temp; + } + } + } + return result; + } + + /** + * Exports a Bookmark data to an XMLDocument Element + * The complementary function is importXML() + * @param root The Element to fill up with the bookmark info + */ + public void exportXML(Element root) { + System.out.println("Bookmarks: Saving to Element"); //$NON-NLS-1$ + Element bookmarkRoot = MetaDataXMLInterface.createElementText(root,"bookmarks", ""); //$NON-NLS-1$ //$NON-NLS-2$ + for (int i = 0; i < bookmarks.size(); i++) { + Bookmark b = (Bookmark) bookmarks.get(i); + ModelToXMLConverter.getInstance().convert(bookmarkRoot, b); + } + } + + /** + * Imports a Bookmark data from an XMLDocument Element + * The complementary function is exportXML() + * @param root The Element from which to load + */ + public void importXML(Element root) { + this.changed = true; + System.out.println("Bookmarks: Loading from Element"); //$NON-NLS-1$ + Vector newBookmarks = new Vector(); + NodeList nodes = root.getElementsByTagName("bookmark"); //$NON-NLS-1$ + for (int i = 0; i < nodes.getLength(); i++) { + Bookmark bookmark = new Bookmark(); + Element column = (Element) nodes.item(i); + + String name = MetaDataXMLInterface.getElementText(column,"name"); //$NON-NLS-1$ + if (name == null) break; + bookmark.setName(name); + + MetaDataXMLInterface.getElementText(column,"name"); //$NON-NLS-1$ + bookmark.setUsername(MetaDataXMLInterface.getElementText(column,"username")); //$NON-NLS-1$ + bookmark.setPassword(MetaDataXMLInterface.getElementText(column,"password")); //$NON-NLS-1$ + bookmark.setPromptForPassword(Boolean.TRUE.toString().equalsIgnoreCase( + MetaDataXMLInterface.getElementText(column,"prompt"))); //$NON-NLS-1$ + bookmark.setConnect(MetaDataXMLInterface.getElementText(column,"connect")); //$NON-NLS-1$ + bookmark.setAutoCommit(Boolean.TRUE.toString().equalsIgnoreCase( + MetaDataXMLInterface.getElementText(column,"autoCommit", "True"))); //$NON-NLS-1$ + bookmark.setAutoCommitPreference(MetaDataXMLInterface.getElementText(column,"autoCommitPreference", IQuantumConstants.autoCommitTrue)); //$NON-NLS-1$ + bookmark.setDriver(MetaDataXMLInterface.getElementText(column,"driver")); //$NON-NLS-1$ + bookmark.addSchema(MetaDataXMLInterface.getElementText(column,"schema")); //$NON-NLS-1$ + bookmark.setType(MetaDataXMLInterface.getElementText(column,"type")); //$NON-NLS-1$ + bookmark.setDriverFile(MetaDataXMLInterface.getElementText(column,"driverLocation")); //$NON-NLS-1$ + NodeList children = column.getElementsByTagName(Messages.getString("ExportXMLAction.OtherSchemas")); + if (children.getLength() > 0) { + importSchemas((Element) children.item(0), bookmark); + } + System.out.println(bookmark.toString()); + if (!bookmark.isEmpty()) { + newBookmarks.addElement(bookmark); + } + importQuickList(bookmark, column); + importQueryList(bookmark, column); + } + this.bookmarks.addAll(newBookmarks); + this.support.firePropertyChange("bookmarks", null, null); + } + + private void importSchemas(Element otherSchemas, Bookmark bookmark) { + Vector vector = MetaDataXMLInterface.getVectorText(otherSchemas, Messages.getString("ExportXMLAction.SchemaName")); + List list = new ArrayList(); + for (Iterator i = vector.iterator(); i.hasNext();) { + String schemaName = (String) i.next(); + list.add(new Schema(schemaName)); + } + bookmark.setSchemas((Schema[]) list.toArray(new Schema[list.size()])); + } + + private void importQuickList(Bookmark bookmark, Element bookmarkElement) { + NodeList quickList = bookmarkElement.getElementsByTagName("quickList"); + for (int j = 0, + length = (quickList == null) ? 0 : quickList.getLength(); + j < length; + j++) { + + Element element = (Element) quickList.item(j); + NodeList childNodes = element.getChildNodes(); + + for (int k = 0, + length2 = (childNodes == null) ? 0 : childNodes.getLength(); + k < length2; + k++) { + if (Node.ELEMENT_NODE == childNodes.item(k).getNodeType()) { + Element entity = (Element) childNodes.item(k); + bookmark.addQuickListEntry(entity.getTagName(), + entity.getAttribute("schema"), entity.getAttribute("name")); + } + } + } + } + + private void importQueryList(Bookmark bookmark, Element bookmarkElement) { + NodeList queryList = bookmarkElement.getElementsByTagName("queryList"); + for (int i = 0, + length = (queryList == null) ? 0 : queryList.getLength(); + i < length; + i++) { + + Element element = (Element) queryList.item(i); + NodeList childNodes = element.getElementsByTagName("query"); + + for (int k = 0, + length2 = (childNodes == null) ? 0 : childNodes.getLength(); + k < length2; + k++) { + + Element query = (Element) childNodes.item(k); + bookmark.addQuery(MetaDataXMLInterface.getElementText(query,"queryString")); + + } + } + } + + public void addBookmark(Bookmark b) { + this.changed = true; + if (!bookmarks.contains(b)) { + Bookmark[] original = getBookmarks(); + bookmarks.add(b); + this.support.firePropertyChange("bookmarks", original, getBookmarks()); + } + } + public void removeBookmark(Bookmark b) { + this.changed = true; + if (bookmarks.contains(b)) { + Bookmark[] original = getBookmarks(); + bookmarks.remove(b); + this.support.firePropertyChange("bookmarks", original, getBookmarks()); + } + } + + public Bookmark[] getBookmarks() { + return (Bookmark[]) this.bookmarks.toArray(new Bookmark[this.bookmarks.size()]); + } + /** + * @return + */ + public boolean isAnythingChanged() { + boolean anythingChanged = this.changed; + for (Iterator i = this.bookmarks.iterator(); !anythingChanged && i.hasNext();) { + Bookmark bookmark = (Bookmark) i.next(); + anythingChanged |= bookmark.isChanged(); + } + return anythingChanged; + } + + public boolean isChanged() { + return this.changed; + } + + /** + * @param b + */ + public void setChanged(boolean changed) { + this.changed = changed; + } + + /** + * @param listener + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + this.support.addPropertyChangeListener(listener); + } + + /** + * @param listener + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + this.support.removePropertyChangeListener(listener); + } + + /** + * @param string + * @return + */ + public String getCopyName(String name) { + + String copyName = Messages.getString("BookmarkView.CopyOf") + name; + int i = 1; + while (find(copyName) != null) + { + copyName = Messages.getString("BookmarkView.CopyOf") + name + "(" + String.valueOf(i) + ")"; + i++; + } + + return copyName; + } + + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/BookmarkHolder.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/BookmarkHolder.java new file mode 100644 index 0000000..1f4a35c --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/BookmarkHolder.java @@ -0,0 +1,17 @@ +/* + * Created on 22-jul-2003 + * + */ +package com.quantum.model; + + +/** + * User interface components that can provide a connection to the database they + * relate to implement this interface. Such components must know how to obtain a + * password, as required. + * + * @author panic + */ +public interface BookmarkHolder { + public Bookmark getBookmark(); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Column.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Column.java new file mode 100644 index 0000000..53923e4 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Column.java @@ -0,0 +1,21 @@ +package com.quantum.model; + +/** + * + * @author bcholmes + */ +public interface Column { + public int getSize(); + public int getPrimaryKeyOrder(); + public boolean isPrimaryKey(); + public String getName(); + public int getNumberOfFractionalDigits(); + public String getTypeName(); + public boolean isReal(); + public boolean isNullable(); + public boolean isNumeric(); + public int getType(); + public Entity getParentEntity(); + public String getQualifiedTableName(); + public String getRemarks(); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ColumnImpl.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ColumnImpl.java new file mode 100644 index 0000000..eb4e6cb --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ColumnImpl.java @@ -0,0 +1,148 @@ +package com.quantum.model; + +import com.quantum.sql.SQLHelper; + +/** + * @author BC + */ +class ColumnImpl implements Column, Comparable { + + private int size; + private boolean nullable; + private int primaryKeyOrder; + private String name; + private Entity entity; + private int numberOfFractionalDigits; + private String typeName; + private int type; + private int position; + private String remarks; + + ColumnImpl(Entity entity, String name, String typeName, int type, + int size, int numberOfFractionalDigits, boolean nullable, int position, + String remarks) { + + this.entity = entity; + this.name = name; + this.typeName = typeName; + this.type = type; + this.size = size; + this.numberOfFractionalDigits = numberOfFractionalDigits; + this.nullable = nullable; + this.position = position; + this.remarks = remarks; + } + + /** + * @see com.quantum.model.Column#getPrimaryKeyOrder() + */ + public int getPrimaryKeyOrder() { + return this.primaryKeyOrder; + } + + /** + * @see com.quantum.model.Column#isPrimaryKey() + */ + public boolean isPrimaryKey() { + return getPrimaryKeyOrder() > 0; + } + + /** + * @see com.quantum.model.Column#getName() + */ + public String getName() { + return this.name; + } + + /** + * @see com.quantum.model.Column#getTypeName() + */ + public String getTypeName() { + return this.typeName; + } + + /** + * @see com.quantum.model.Column#isReal() + */ + public boolean isReal() { + return false; + } + + /** + * @see com.quantum.model.Column#isNullable() + */ + public boolean isNullable() { + return this.nullable; + } + + /** + * @see com.quantum.model.Column#isNumeric() + */ + public boolean isNumeric() { + return SQLHelper.isNumeric(this.type); + } + + /** + * @see com.quantum.model.Column#getType() + */ + public int getType() { + return this.type; + } + + /** + * @see com.quantum.model.Column#getParentEntity() + */ + public Entity getParentEntity() { + return this.entity; + } + + /** + * @see com.quantum.model.Column#getQualifiedTableName() + */ + public String getQualifiedTableName() { + return this.entity.getCondQualifiedName(); + } + /** + * @param i + */ + void setPrimaryKeyOrder(int i) { + this.primaryKeyOrder = i; + } + + /** + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(Object o) { + ColumnImpl that = (ColumnImpl) o; + if (this.isPrimaryKey() && that.isPrimaryKey()) { + return this.primaryKeyOrder - that.primaryKeyOrder; + } else if (this.isPrimaryKey()) { + return -1; + } else if (that.isPrimaryKey()) { + return 1; + } else { + return this.position - that.position; + } + } + /** + * @return + */ + public int getSize() { + return size; + } + + /** + * @return + */ + public int getNumberOfFractionalDigits() { + return numberOfFractionalDigits; + } + + /** + * @return + */ + public String getRemarks() { + return this.remarks == null ? "" : this.remarks; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ConnectionException.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ConnectionException.java new file mode 100644 index 0000000..f1da0bf --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ConnectionException.java @@ -0,0 +1,56 @@ +package com.quantum.model; + +/** + * @author BC + */ +public class ConnectionException extends Exception { + + private Throwable cause = null; + + /** + * + */ + public ConnectionException() { + super(); + } + + /** + * @param message + */ + public ConnectionException(String message) { + super(message); + } + + /** + * @param message + * @param cause + */ + public ConnectionException(String message, Throwable cause) { + super(message); + this.cause = cause; + } + + /** + * @param cause + */ + public ConnectionException(Throwable cause) { + super(cause.getMessage()); + this.cause = cause; + } + + public Throwable getCause() { + return this.cause; + } + + public String toString() { + String base = super.toString(); + if (this.cause != null) { + base += System.getProperty("line.separator") + + "Root cause:" + + System.getProperty("line.separator") + + this.cause.toString(); + } + return base; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Constraint.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Constraint.java new file mode 100644 index 0000000..f927ffc --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Constraint.java @@ -0,0 +1,8 @@ +package com.quantum.model; + +/** + * @author BC + */ +public interface Constraint { + public Entity getEntity(); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Database.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Database.java new file mode 100644 index 0000000..b6dee05 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Database.java @@ -0,0 +1,214 @@ +package com.quantum.model; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.quantum.IQuantumConstants; +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.sql.MultiSQLServer; +import com.quantum.sql.SQLResults; + +/** + * @author BC + */ +public class Database { + + private DatabaseAdapter databaseAdapter; + private Bookmark bookmark; + + public Database(Bookmark bookmark) { + this.bookmark = bookmark; + this.databaseAdapter = bookmark.getAdapter(); + } + + private static final String[] ALL_TYPES = { + IQuantumConstants.Table, + IQuantumConstants.View, + IQuantumConstants.Sequence }; + + private static final List STANDARD_TABLE_TYPES = + Collections.synchronizedList(new ArrayList()); + + static { + for (int i = 0, length = (ALL_TYPES == null) ? 0 : ALL_TYPES.length; + i < length; + i++) { + STANDARD_TABLE_TYPES.add(ALL_TYPES[i]); + } + } + + public String[] getEntityTypes() + throws NotConnectedException, SQLException { + return getEntityTypes(this.bookmark.getConnection(), this.bookmark.getSchemas()[0]); + } + + + /** + *

This method returns a list of entity types supported by the database + * adapter. This list will always be limited to Tables, Views and + * Sequences.

+ * + *

Not all databases support all types. MySQL only supports + * Tables. Informix supports Tables and Views. Oracle and DB2 support + * Tables, Views and Sequences.

+ * + * @param connection + * @param schema - + * This parameter is somewhat bogus. It is used to determine if the + * adapter defines an SQL statement for finding entities of a + * particular types. + * @return + * @throws SQLException + */ + public String[] getEntityTypes(Connection connection, Schema schema) + throws SQLException { + + Set set = new HashSet(); + if (this.databaseAdapter.getShowTableQuery(schema.getName(), false) != null) { + set.add(IQuantumConstants.Table); + } else if (this.databaseAdapter.getShowViewQuery(schema.getName(), false) != null) { + set.add(IQuantumConstants.View); + } else if (this.databaseAdapter.getShowSequenceQuery(schema.getName(), false) != null) { + set.add(IQuantumConstants.Sequence); + } + + DatabaseMetaData metaData = connection.getMetaData(); + ResultSet resultSet = metaData.getTableTypes(); + while (resultSet.next()) { + String type = resultSet.getString("TABLE_TYPE"); + if (type != null) { + type = type.trim(); + } + if (STANDARD_TABLE_TYPES.contains(type)) { + set.add(type); + } + } + + return (String[]) set.toArray(new String[set.size()]); + } + + public String getInformation() throws SQLException { + try { + Connection connection = this.bookmark.getConnection(); + DatabaseMetaData metaData = connection.getMetaData(); + + return metaData == null ? null : metaData.getDatabaseProductName() + " " + + metaData.getDatabaseProductVersion(); + } catch (NotConnectedException e) { + // TODO: think about this... + return ""; + } + } + + /** + * Get a list of entities (tables, views, sequences) for a particular + * bookmark. This function is usually not redefined because it gives + * an external interface. You will usually redefine the getShowTableQuery(), + * getShowViewQuery(), etc. + * + * @param bookmark - + * the bookmark that describes the database that is being accessed. + * @param passwordFinder - + * a utility class that knows how to obtain a password, if required + * @param schema - + * the schema from which to extract + * @param type - + * the type ("VIEW", "TABLE", etc.) of entities to extract or null + * if all entity types should be extracted + * @return + * an array of entity objects representing the tables, views and sequences. + * @throws SQLException + */ + public Entity[] getEntities(Bookmark bookmark, Schema schema, String type) + throws SQLException, NotConnectedException { + Connection connection = bookmark.getConnection(); + Entity[] result = getEntities(bookmark, connection, schema, type); + return (result == null) ? new Entity[0] : result; + } + + protected Entity[] getEntities(Bookmark bookmark, Connection connection, Schema schema, String type) + throws SQLException { + + List list = new ArrayList(); + String[] types = (type == null) ? ALL_TYPES : new String[] { type }; + + for (int i = 0; i < types.length; i++) { + list.addAll(getEntitiesList(bookmark, connection, types[i], schema)); + } + + return (Entity[]) list.toArray(new Entity[list.size()]); + } + + protected List getEntitiesList(Bookmark bookmark, Connection connection, String type, Schema schema) + throws SQLException { + + String sql = getSQL(bookmark, type, schema); + List list = new ArrayList(); + SQLResults results = null; + if (sql != null) { + results = MultiSQLServer.getInstance().execute(connection, sql); + for (int i = 1, size = (results == null) ? 0 : results.getRowCount(); i <= size; i++) { + String schemaName = results.getColumnCount() == 1 + ? schema.getName() : results.getElement(1, i).toString(); + String tableName = results.getColumnCount() == 1 + ? results.getElement(1, i).toString() + : results.getElement(2, i).toString(); + if (tableName != null && tableName.length() > 0) { + Entity entity = EntityFactory.getInstance().create( + bookmark, schemaName, tableName, type); + if (entity != null) { + list.add(entity); + } + } + } + } + // If we have some results, we go back + if (results != null) return list; + // Else, we try the JDBC driver + DatabaseMetaData metaData = connection.getMetaData(); + // getTables needs a null schema to get all the schemas. So we don't pass a "" schema, but a null one + ResultSet set = null; + if (metaData.supportsSchemasInTableDefinitions()) + set = metaData.getTables(null, (schema != null) ? schema.getName() : null, "%", new String[] { type }); + else + set = metaData.getTables(null, null, "%", new String[] { type }); + + while (set.next()) { + String tempSchema = set.getString("TABLE_SCHEM"); + tempSchema = (tempSchema == null) ? "" : tempSchema.trim(); + String tableName = set.getString("TABLE_NAME"); + tableName = (tableName == null) ? "" : tableName.trim(); + + if (tableName != null && tableName.length() > 0) { + Entity entity = EntityFactory.getInstance().create(bookmark, tempSchema, tableName, type); + if (entity != null) { + list.add(entity); + } + } + } + set.close(); + return list; + } + + + private String getSQL(Bookmark bookmark, String type, Schema schema) { + if (Entity.TABLE_TYPE.equals(type)) { + return this.databaseAdapter.getShowTableQuery(schema.getName(), schema.isDefault()); + } else if (Entity.VIEW_TYPE.equals(type)) { + return this.databaseAdapter.getShowViewQuery(schema.getName(), schema.isDefault()); + } else if (Entity.SEQUENCE_TYPE.equals(type)) { + return this.databaseAdapter.getShowSequenceQuery(schema.getName(), schema.isDefault()); + } else { + return null; + } + } + + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Entity.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Entity.java new file mode 100644 index 0000000..845c751 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Entity.java @@ -0,0 +1,40 @@ +package com.quantum.model; + +import com.quantum.IQuantumConstants; + +/** + * @author BC + */ +public interface Entity extends BookmarkHolder { + + public static final String TABLE_TYPE = IQuantumConstants.Table; + public static final String VIEW_TYPE = IQuantumConstants.View; + public static final String SEQUENCE_TYPE = IQuantumConstants.Sequence; + + public String getName(); + public String getSchema(); + public String getType(); + public Column[] getColumns(); + public Index[] getIndexes(); + public Column getColumn(String columnName); + /** + * Returns a String with the qualified name of the Entity. + * That is, "schema.name". The difference with getQualifiedName() + * is that the schema may be absent if it's not defined in the bookmark + */ + public String getCondQualifiedName(); + + /** + * @return - TRUE if the entity exists in the database
+ * - FALSE if the entity does not exist in the database
+ * - null if it's not known whether or not the + * entity exists in the database. + */ + public Boolean exists(); + /** + * Some databases support mixed-case table names. Queries issued + * against these tables must be quoted. + * @return + */ + public String getQuotedTableName(); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityFactory.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityFactory.java new file mode 100644 index 0000000..de48c0f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityFactory.java @@ -0,0 +1,36 @@ +package com.quantum.model; + + +/** + * + * + * @author BC + */ +public class EntityFactory { + + private static EntityFactory instance = new EntityFactory(); + + private EntityFactory() { + } + + public static EntityFactory getInstance() { + return EntityFactory.instance; + } + + public Entity create(Bookmark bookmark, String schema, String name, String type) { + if (type != null) { + type = type.toUpperCase().trim(); + } + + if (Entity.TABLE_TYPE.equals(type)) { + return new TableImpl(bookmark, schema, name); + } else if (Entity.VIEW_TYPE.equals(type)) { + return new ViewImpl(bookmark, schema, name); + } else if (Entity.SEQUENCE_TYPE.equals(type)) { + return new SequenceImpl(bookmark, schema, name); + } else { + return null; +// throw new IllegalArgumentException("Unknown type: " + type); + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityHolder.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityHolder.java new file mode 100644 index 0000000..897c82b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityHolder.java @@ -0,0 +1,8 @@ +package com.quantum.model; + +/** + * @author BC + */ +public interface EntityHolder { + public Entity getEntity(); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityImpl.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityImpl.java new file mode 100644 index 0000000..a960fbb --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/EntityImpl.java @@ -0,0 +1,182 @@ + package com.quantum.model; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DatabaseAdapter; + +/** + * This class models a table or view. + * + * @author bcholmes + */ +abstract class EntityImpl implements Entity { + private String schema; + private String name; + private String type; + private Bookmark bookmark; + private Boolean exists = Boolean.TRUE; + + public EntityImpl(Bookmark bookmark, String schema, String name, String type) { + this.schema = schema; + this.name = name; + this.type = type; + this.bookmark = bookmark; + } + public Bookmark getBookmark() { + return this.bookmark; + } + public String getName() { + return this.name; + } + public String getSchema() { + return this.schema; + } + public String getType() { + return this.type; + } + public String getCondQualifiedName() { + return (this.schema == null || this.schema.length() == 0) ? + this.name : this.schema + "." + this.name; + } + public Column getColumn(String columnName) { + Column column = null; + Column[] columns = getColumns(); + for (int i = 0, length = (columns == null) ? 0 : columns.length; + column == null && i < length; + i++) { + if (columnName != null && columnName.equals(columns[i].getName())) { + column = columns[i]; + } + } + return column; + } + public Column[] getColumns() { + + Column[] columns = new Column[0]; + try { + // TODO: Some DBs (like DB2) don't support metadata + Map temp = new HashMap(); + Connection connection = this.bookmark.getConnection(); + DatabaseMetaData metaData = connection.getMetaData(); + ResultSet resultSet = metaData.getColumns(null, getSchema(), getName(), null); + + while (resultSet.next()) { + ColumnImpl column = new ColumnImpl( + this, + resultSet.getString("COLUMN_NAME"), + resultSet.getString("TYPE_NAME"), + resultSet.getInt("DATA_TYPE"), + resultSet.getInt("COLUMN_SIZE"), + resultSet.getInt("DECIMAL_DIGITS"), + "YES".equalsIgnoreCase(resultSet.getString("IS_NULLABLE")), + resultSet.getInt("ORDINAL_POSITION"), + getComments(resultSet.getString("REMARKS"),getCondQualifiedName(), resultSet.getString("COLUMN_NAME")) + ); + temp.put(column.getName(), column); + } + resultSet.close(); + + resultSet = metaData.getPrimaryKeys(null, getSchema(), getName()); + while (resultSet.next()) { + String name = resultSet.getString("COLUMN_NAME"); + short keySequence = resultSet.getShort("KEY_SEQ"); + ColumnImpl column = (ColumnImpl) temp.get(name); + if (column != null) { + column.setPrimaryKeyOrder(keySequence); + } + } + resultSet.close(); + + List columnList = Collections.synchronizedList( + new ArrayList(temp.values())); + Collections.sort(columnList); + columns = (Column[]) columnList.toArray(new Column[columnList.size()]); + + } catch (NotConnectedException e) { + } catch (SQLException e) { + } + return columns; + } + + /** + * Some JDBC drivers (Oracle for example) won't return the comments + * We recheck with a custom query, if it's defined + * @param iniComment The already got comment + * @param tableName The fully qualified table name + * @param columnName The column name + */ + private String getComments( String iniComment, String tableName, String columnName) { + if (iniComment != null && iniComment.length() > 0) + return iniComment; + String comment = ""; + try { + Connection con = this.bookmark.getConnection(); + Statement stmt = con.createStatement(); + DatabaseAdapter adapter = AdapterFactory.getInstance().getAdapter(this.bookmark.getType()); + if (adapter != null && stmt != null && adapter.getCommentsQuery(tableName, columnName) != null) { + + stmt.execute(adapter.getCommentsQuery(tableName, columnName)); + ResultSet set = stmt.getResultSet(); + if (set.next()) + comment = set.getString(1); + } + } catch (NotConnectedException e) { + } catch (SQLException e) { + } + + return comment; + } + public Index[] getIndexes() { + + List indexList = new ArrayList(); + Map temp = new HashMap(); + try { + Connection connection = this.bookmark.getConnection(); + DatabaseMetaData metaData = connection.getMetaData(); + ResultSet resultSet = metaData.getIndexInfo(null, getSchema(), getName(), false, false); + + while (resultSet.next()) { + String indexName = resultSet.getString("INDEX_NAME"); + IndexImpl index = (IndexImpl) temp.get(indexName); + if (index == null) { + index = new IndexImpl(this, indexName); + temp.put(indexName, index); + } + String columnName = resultSet.getString("COLUMN_NAME"); + String ascending = resultSet.getString("ASC_OR_DESC"); + index.addColumn(columnName, ascending == null + ? null : (ascending.toUpperCase().startsWith("A") + ? Boolean.TRUE : Boolean.FALSE)); + } + resultSet.close(); + indexList.addAll(temp.values()); + + } catch (NotConnectedException e) { + } catch (SQLException e) { + } + return (Index[]) indexList.toArray(new Index[indexList.size()]); + } + + public Boolean exists() { + return this.exists; + } + + + /** + * @see com.quantum.model.Entity#getQuotedTableName() + */ + public String getQuotedTableName() { + return getBookmark().getAdapter().filterTableName(getCondQualifiedName()); + } + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ForeignKey.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ForeignKey.java new file mode 100644 index 0000000..6a39917 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ForeignKey.java @@ -0,0 +1,15 @@ +package com.quantum.model; + +/** + * @author BC + */ +public interface ForeignKey extends Constraint { + public String getName(); + public Entity getForeignEntity(); + public String getForeignEntityName(); + public String getForeignEntitySchema(); + public int getNumberOfColumns(); + public String getLocalColumnName(int index); + public String getForeignColumnName(int index); + public int getDeleteRule(); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/HasMetaData.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/HasMetaData.java new file mode 100644 index 0000000..6d1ab1f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/HasMetaData.java @@ -0,0 +1,24 @@ +/* + * Created on 22-jul-2003 + * + */ +package com.quantum.model; + +import com.quantum.sql.metadata.ObjectMetaData; + +/** + * Interface for objects that offer metadata support + * @author panic + * + */ +public interface HasMetaData { + public ObjectMetaData getMetaData() throws NotConnectedException; + /** + * Returns a String with the qualified name of the Entity. + * That is, "schema.name". The difference with getConQualifiedName() + * is that the schema is always present if the database supports schemas. + * @return + */ + public String getQualifiedName(); + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Index.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Index.java new file mode 100644 index 0000000..3aa5cf5 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Index.java @@ -0,0 +1,13 @@ +package com.quantum.model; + +/** + * @author BC + */ +public interface Index { + public String getName(); + public int getNumberOfColumns(); + public String getColumnName(int ordinalPosition); + public Entity getParentEntity(); + public boolean isAscending(int ordinalPosition); + public boolean isDescending(int ordinalPosition); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/IndexImpl.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/IndexImpl.java new file mode 100644 index 0000000..2bda513 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/IndexImpl.java @@ -0,0 +1,69 @@ +package com.quantum.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author BC + */ +/*package*/ class IndexImpl implements Index { + + private String name; + private List columnNames = Collections.synchronizedList(new ArrayList()); + private Entity entity; + private List ascending = Collections.synchronizedList(new ArrayList()); + + IndexImpl(Entity entity, String name) { + + this.name = name; + this.entity = entity; + } + + void addColumn(String columnName, Boolean ascending) { + this.columnNames.add(columnName); + this.ascending.add(ascending); + } + + public String getName() { + return this.name; + } + + /** + * @see com.quantum.model.Index#getNumberOfColumns() + */ + public int getNumberOfColumns() { + return this.columnNames.size(); + } + + /** + * @see com.quantum.model.Index#getColumnName(int) + */ + public String getColumnName(int ordinalPosition) { + return (String) this.columnNames.get(ordinalPosition); + } + + /** + * @see com.quantum.model.Index#getParentEntity() + */ + public Entity getParentEntity() { + return this.entity; + } + + /** + * @see com.quantum.model.Index#isAscending() + */ + public boolean isAscending(int ordinalPosition) { + Boolean ascending = (Boolean) this.ascending.get(ordinalPosition); + return Boolean.TRUE.equals(ascending); + } + + /** + * @see com.quantum.model.Index#isDescending() + */ + public boolean isDescending(int ordinalPosition) { + Boolean ascending = (Boolean) this.ascending.get(ordinalPosition); + return Boolean.FALSE.equals(ascending); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/NotConnectedException.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/NotConnectedException.java new file mode 100644 index 0000000..0f4ee12 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/NotConnectedException.java @@ -0,0 +1,8 @@ +package com.quantum.model; + +/** + * @author BC + */ +public class NotConnectedException extends ConnectionException { + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/PasswordFinder.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/PasswordFinder.java new file mode 100644 index 0000000..4ba0e1d --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/PasswordFinder.java @@ -0,0 +1,15 @@ +package com.quantum.model; + +/** + * When a bookmark doesn't have a saved password, an + * implementation of a password finder class can be called + * to obtain one. + * + * @author BC + */ +public interface PasswordFinder { + + public String getPassword(); + public boolean isPasswordMeantToBeSaved(); + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Schema.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Schema.java new file mode 100644 index 0000000..154e15b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Schema.java @@ -0,0 +1,109 @@ +package com.quantum.model; + +/** + * @author BC + */ +public class Schema implements Comparable { + + private String name; + private String displayName; + private boolean isDefault; + + + public Schema() { + } + + public Schema(String name, String displayName, boolean isDefault) { + this.name = name; + this.displayName = displayName; + this.isDefault = isDefault; + } + + public Schema(String name) { + this(name, name, false); + } + + /** + * @return + */ + public String getName() { + return name; + } + + /** + * @param string + */ + public void setName(String string) { + name = string; + } + + /** + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(Object o) { + Schema that = (Schema) o; + if (that.isDefault() == this.isDefault()) { + return this.getDisplayName().compareTo(that.getDisplayName()); + } else { + return that.isDefault() ? 1 : -1; + } + } + public boolean equals(Object obj) { + if (getClass() != obj.getClass()) { + return false; + } else { + Schema that = (Schema) obj; + if (this.name == null && !(that.name == null)) { + return false; + } else if (this.name != null && !this.name.equals(that.name)) { + return false; + } else if (this.displayName == null && !(that.displayName == null)) { + return false; + } else if (this.displayName == null && !this.displayName.equals(that.displayName)) { + return false; + } else { + return true; + } + } + } + public int hashCode() { + int hashCode = super.hashCode(); + if (this.name != null) { + hashCode ^= this.name.hashCode(); + } + if (this.displayName != null) { + hashCode ^= this.displayName.hashCode(); + } + + return hashCode; + } + + /** + * @return + */ + public boolean isDefault() { + return isDefault; + } + + /** + * @param b + */ + public void setDefault(boolean isDefault) { + this.isDefault = isDefault; + } + + /** + * @return + */ + public String getDisplayName() { + return displayName; + } + + /** + * @param string + */ + public void setDisplayName(String string) { + displayName = string; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/SchemaHolder.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/SchemaHolder.java new file mode 100644 index 0000000..7961492 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/SchemaHolder.java @@ -0,0 +1,8 @@ +package com.quantum.model; + +/** + * @author BC + */ +public interface SchemaHolder { + public Schema getSchema(); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Sequence.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Sequence.java new file mode 100644 index 0000000..374af35 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Sequence.java @@ -0,0 +1,8 @@ +package com.quantum.model; + +/** + * @author BC + */ +public interface Sequence extends Entity { + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/SequenceImpl.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/SequenceImpl.java new file mode 100644 index 0000000..0443906 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/SequenceImpl.java @@ -0,0 +1,13 @@ +package com.quantum.model; + +class SequenceImpl extends EntityImpl implements Sequence { + public SequenceImpl(Bookmark bookmark, String schema, String name) { + super(bookmark, schema, name, SEQUENCE_TYPE); + } + public Column[] getColumns() { + return new Column[0]; + } + public Column getColumn(String columnName) { + return null; + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Table.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Table.java new file mode 100644 index 0000000..91bbc31 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/Table.java @@ -0,0 +1,11 @@ +package com.quantum.model; + +import java.sql.SQLException; + +/** + * @author BC + */ +public interface Table extends Entity { + public Integer getSize(); + public void deleteAllRows() throws SQLException, ConnectionException; +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/TableImpl.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/TableImpl.java new file mode 100644 index 0000000..161ab0f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/TableImpl.java @@ -0,0 +1,31 @@ +package com.quantum.model; + +import java.sql.SQLException; + +import com.quantum.adapters.AdapterFactory; +import com.quantum.sql.MultiSQLServer; +import com.quantum.sql.SQLHelper; + + +class TableImpl extends EntityImpl implements Table { + public TableImpl(Bookmark bookmark, String schema, String name) { + super(bookmark, schema, name, TABLE_TYPE); + } + + public Integer getSize() { + Integer size = null; + try { + size = new Integer(SQLHelper.getSize( + getBookmark().getConnection(), getCondQualifiedName(), + AdapterFactory.getInstance().getAdapter(getBookmark().getType()))); + } catch (SQLException e) { + } catch (ConnectionException e) { + } + return size; + } + + public void deleteAllRows() throws SQLException, ConnectionException { + String sql = "DELETE FROM " + getCondQualifiedName(); + MultiSQLServer.getInstance().execute(getBookmark().getConnection(), sql); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/View.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/View.java new file mode 100644 index 0000000..2078bf4 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/View.java @@ -0,0 +1,11 @@ +package com.quantum.model; + + +/** + * @author BC + */ +public interface View extends Entity { + + public Integer getSize(); + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ViewImpl.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ViewImpl.java new file mode 100644 index 0000000..7a49d86 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/ViewImpl.java @@ -0,0 +1,25 @@ +package com.quantum.model; + +import java.sql.SQLException; + +import com.quantum.adapters.AdapterFactory; +import com.quantum.sql.SQLHelper; + + +class ViewImpl extends EntityImpl implements View { + public ViewImpl(Bookmark bookmark, String schema, String name) { + super(bookmark, schema, name, VIEW_TYPE); + } + + public Integer getSize() { + Integer size = null; + try { + size = new Integer(SQLHelper.getSize( + getBookmark().getConnection(), getCondQualifiedName(), + AdapterFactory.getInstance().getAdapter(getBookmark().getType()))); + } catch (SQLException e) { + } catch (ConnectionException e) { + } + return size; + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/xml/ModelToXMLConverter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/xml/ModelToXMLConverter.java new file mode 100644 index 0000000..908b239 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/xml/ModelToXMLConverter.java @@ -0,0 +1,150 @@ +package com.quantum.model.xml; + +import com.quantum.Messages; +import com.quantum.model.Bookmark; +import com.quantum.model.Column; +import com.quantum.model.Entity; +import com.quantum.model.Schema; +import com.quantum.sql.metadata.MetaDataXMLInterface; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Text; + +/** + * @author BC + */ +public class ModelToXMLConverter { + + private static final ModelToXMLConverter instance = new ModelToXMLConverter(); + + private ModelToXMLConverter() { + } + + public static ModelToXMLConverter getInstance() { + return ModelToXMLConverter.instance; + } + + public void createRoot(Document document) { + document.appendChild(document.createElement("SAVED_DATA")); + } + + public void convert(Element bookmarkRoot, Bookmark b) { + Document document = bookmarkRoot.getOwnerDocument(); + Element bookmark = MetaDataXMLInterface.createElementText(bookmarkRoot,"bookmark", ""); //$NON-NLS-1$ //$NON-NLS-2$ + MetaDataXMLInterface.createElementText(bookmark,"name", b.getName()); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(bookmark,"username", b.getUsername()); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(bookmark,"password", b.getPassword()); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(bookmark,"prompt", b.getPromptForPassword() ? "true" : "false"); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(bookmark,"connect", b.getConnect()); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(bookmark,"autoCommit", b.isAutoCommit() ? "true" : "false"); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(bookmark,"autoCommitPreference", b.getAutoCommitPreference()); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(bookmark,"driver", b.getDriver()); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(bookmark,"type", b.getType()); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(bookmark,"driverLocation", b.getDriverFile()); //$NON-NLS-1$ + Element otherSchemas = (Element) bookmark.appendChild(document.createElement(Messages.getString("ExportXMLAction.OtherSchemas"))); //$NON-NLS-1$ + Schema[] schemas = b.getSchemas(); + for (int i = 0, length = (schemas == null) ? 0 : schemas.length; + i < length; + i++) { + if (!schemas[i].isDefault()) { + MetaDataXMLInterface.createElementText( + otherSchemas,Messages.getString("ExportXMLAction.SchemaName"), schemas[i].getName()); //$NON-NLS-1$ + } + } + Entity[] quickList = b.getQuickListEntries(); + Element quickListEntity = document.createElement("quickList"); + for (int j = 0, length = (quickList == null) ? 0 : quickList.length; + j < length; + j++) { + ModelToXMLConverter.getInstance().convert(quickListEntity, quickList[j]); + } + bookmark.appendChild(quickListEntity); + convertQueryList(b, bookmark); + } + + + public void convert(Element parent, Entity entity) { + convert(parent, entity, true); + } + public void convert(Element parent, Entity entity, boolean recurse) { + Document document = parent.getOwnerDocument(); + Element element = document.createElement(getEntityDOMNodeName(entity)); + element.setAttribute("name", entity.getName()); + if (entity.getSchema() != null) { + element.setAttribute("schema", entity.getSchema()); + } + if (recurse) { + convert(element, entity.getColumns()); + } + parent.appendChild(element); + } + + public void convert(Element element, Column[] columns) { + for (int i = 0, length = (columns == null) ? 0 : columns.length; + i < length; + i++) { + convert(element, columns[i]); + } + } + + public void convert(Element parent, Column column) { + Document document = parent.getOwnerDocument(); + Element element = document.createElement("column"); + element.setAttribute("name", column.getName()); + element.setAttribute("type", column.getTypeName()); + element.setAttribute("primaryKey", column.isPrimaryKey() ? "true" : "false"); + element.setAttribute("nullable", column.isNullable() ? "true" : "false"); + if (column.isNumeric()) { + if (column.getSize() > 0) { + element.setAttribute("size", String.valueOf(column.getSize())); + } + if (column.getNumberOfFractionalDigits() > 0) { + element.setAttribute("numberOfFractionalDigits", String.valueOf(column.getNumberOfFractionalDigits())); + } + } else { + if (column.getSize() > 0) { + element.setAttribute("size", String.valueOf(column.getSize())); + } + } + if (column.getRemarks().length() > 0) + MetaDataXMLInterface.createElementText(element, "remarks", column.getRemarks()); + parent.appendChild(element); + } + + + public String getEntityDOMNodeName(Entity entity) { + if (Entity.TABLE_TYPE.equals(entity.getType())) { + return "table"; + } else if (Entity.VIEW_TYPE.equals(entity.getType())) { + return "view"; + } else if (Entity.SEQUENCE_TYPE.equals(entity.getType())) { + return "sequence"; + } else { + return "unknown"; + } + } + + public void convertQueryList( + Bookmark bookmark, + Element parent) { + + Document document = parent.getOwnerDocument(); + String[] queryList = bookmark.getQueries(); + Element queryListEntity = document.createElement("queryList"); + for (int j = 0, length = (queryList == null) ? 0 : queryList.length; + j < length; + j++) { + Element query = document.createElement("query"); + + // will have more possibilities later + Element queryString = document.createElement("queryString"); + Text queryText = document.createTextNode(queryList[j]); + queryString.appendChild(queryText); + query.appendChild(queryString); + queryListEntity.appendChild(query); + } + parent.appendChild(queryListEntity); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/xml/TorqueConverter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/xml/TorqueConverter.java new file mode 100644 index 0000000..15c3c57 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/model/xml/TorqueConverter.java @@ -0,0 +1,90 @@ +package com.quantum.model.xml; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.sql.SQLException; +import java.sql.Types; + +import com.quantum.model.Bookmark; +import com.quantum.model.Column; +import com.quantum.model.Entity; +import com.quantum.model.Schema; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * @author BC + */ +public class TorqueConverter { + public void createRoot(Document document) { + Element root = document.createElement("database"); + document.appendChild(root); + } + public void convert(Element root, Bookmark bookmark, Schema schema) { + try { + Entity[] tables = bookmark.getEntitiesForSchema( + schema, Entity.TABLE_TYPE); + + for (int i = 0, length = (tables == null) ? 0 : tables.length; + i < length; + i++) { + convert(root, tables[i]); + } + } catch (SQLException e) { + } + } + + public void convert(Element root, Entity entity) { + Element table = root.getOwnerDocument().createElement("table"); + table.setAttribute("name", entity.getName()); + + Column[] columns = entity.getColumns(); + for (int i = 0, length = (columns == null) ? 0 : columns.length; + i < length; + i++) { + convert(table, columns[i]); + } + + root.appendChild(table); + } + + public void convert(Element root, Column column) { + Element element = root.getOwnerDocument().createElement("column"); + element.setAttribute("name", column.getName()); + if (column.isPrimaryKey()) { + element.setAttribute("primaryKey", "true"); + } + element.setAttribute("required", column.isNullable() ? "false" : "true"); + if (column.isNumeric() && column.getNumberOfFractionalDigits() > 0) { + element.setAttribute("size", String.valueOf(column.getSize()) + + "," + String.valueOf(column.getNumberOfFractionalDigits())); + } else if (column.getSize() >= 0) { + element.setAttribute("size", String.valueOf(column.getSize())); + } + element.setAttribute("type", getStandardType(column.getType())); + + root.appendChild(element); + } + + private String getStandardType(int type) { + String result = null; + try { + Field[] fields = Types.class.getFields(); + for (int i = 0, length = (fields == null) ? 0 : fields.length; + result == null & i < length; + i++) { + if (fields[i].getDeclaringClass() == Integer.TYPE && + Modifier.isStatic(fields[i].getModifiers()) && + Modifier.isPublic(fields[i].getModifiers()) && + type == fields[i].getLong(null)) { + + result = fields[i].getName(); + } + } + } catch (IllegalAccessException e) { + // shouldn't happen + } + return result; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/perspective/DBPerspective.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/perspective/DBPerspective.java new file mode 100644 index 0000000..c47f2ce --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/perspective/DBPerspective.java @@ -0,0 +1,30 @@ +package com.quantum.perspective; + +import org.eclipse.ui.IFolderLayout; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +/** + * @author root + */ +public class DBPerspective implements IPerspectiveFactory { + public void createInitialLayout(IPageLayout layout) { + layout.setEditorAreaVisible(false); + IFolderLayout side = + layout.createFolder( + "side", //$NON-NLS-1$ + IPageLayout.LEFT, + 0.33F, + layout.getEditorArea()); + side.addView("com.quantum.view.bookmarkview"); //$NON-NLS-1$ + layout.addView("com.quantum.view.sqlqueryview", IPageLayout.BOTTOM, 0.33F, layout.getEditorArea()); //$NON-NLS-1$ + IFolderLayout bottomRight = + layout.createFolder( + "bottomRight", //$NON-NLS-1$ + IPageLayout.BOTTOM, + 0.33F, + "com.quantum.view.sqlqueryview"); + bottomRight.addView("com.quantum.view.tableview.TableView"); //$NON-NLS-1$ + bottomRight.addView("com.quantum.view.logview"); //$NON-NLS-1$ + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CopyPreferences.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CopyPreferences.java new file mode 100644 index 0000000..51df2dc --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CopyPreferences.java @@ -0,0 +1,37 @@ +package com.quantum.preferences; + + +import com.quantum.QuantumPlugin; + +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +public class CopyPreferences + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public CopyPreferences() { + super(FieldEditorPreferencePage.GRID); + + // Set the preference store for the preference page. + IPreferenceStore store = + QuantumPlugin.getDefault().getPreferenceStore(); + setPreferenceStore(store); + } + + public void init(IWorkbench workbench) { + this.workbench = workbench; + } + + IWorkbench workbench; + + protected void createFieldEditors() { + StringFieldEditor copyColumnSeparator = new StringFieldEditor("copyColumnSeparator", "&Normal Copy Separator:", getFieldEditorParent()); + this. + addField(copyColumnSeparator); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences.java new file mode 100644 index 0000000..065fbb3 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences.java @@ -0,0 +1,46 @@ +package com.quantum.preferences; + + +import com.quantum.QuantumPlugin; + +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +public class CustomCopyPreferences + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public CustomCopyPreferences() { + super(FieldEditorPreferencePage.GRID); + + // Set the preference store for the preference page. + IPreferenceStore store = + QuantumPlugin.getDefault().getPreferenceStore(); + setPreferenceStore(store); + } + + public void init(IWorkbench workbench) { + this.workbench = workbench; + } + + IWorkbench workbench; + + protected void createFieldEditors() { + StringFieldEditor customCopyName = new StringFieldEditor("customCopyName1", "&Name:", getFieldEditorParent()); + addField(customCopyName); + StringFieldEditor customCopyTableItem = new StringFieldEditor("customCopyTableItem1", "&Table Item:", getFieldEditorParent()); + addField(customCopyTableItem); + StringFieldEditor customCopyTableSeparator = new StringFieldEditor("customCopyTableSeparator1", "&Table Separator:", getFieldEditorParent()); + addField(customCopyTableSeparator); + StringFieldEditor customCopyColumnItem = new StringFieldEditor("customCopyColumnItem1", "&Column Item:", getFieldEditorParent()); + addField(customCopyColumnItem); + StringFieldEditor customCopyColumnSeparator = new StringFieldEditor("customCopyColumnSeparator1", "&Column Separator:", getFieldEditorParent()); + addField(customCopyColumnSeparator); + StringFieldEditor customCopyTemplate = new StringFieldEditor("customCopyTemplate1", "&Template:", getFieldEditorParent()); + addField(customCopyTemplate); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences2.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences2.java new file mode 100644 index 0000000..ad0fbf4 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences2.java @@ -0,0 +1,46 @@ +package com.quantum.preferences; + + +import com.quantum.QuantumPlugin; + +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +public class CustomCopyPreferences2 + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public CustomCopyPreferences2() { + super(FieldEditorPreferencePage.GRID); + + // Set the preference store for the preference page. + IPreferenceStore store = + QuantumPlugin.getDefault().getPreferenceStore(); + setPreferenceStore(store); + } + + public void init(IWorkbench workbench) { + this.workbench = workbench; + } + + IWorkbench workbench; + + protected void createFieldEditors() { + StringFieldEditor customCopyName = new StringFieldEditor("customCopyName2", "&Name:", getFieldEditorParent()); + addField(customCopyName); + StringFieldEditor customCopyTableItem = new StringFieldEditor("customCopyTableItem2", "&Table Item:", getFieldEditorParent()); + addField(customCopyTableItem); + StringFieldEditor customCopyTableSeparator = new StringFieldEditor("customCopyTableSeparator2", "&Table Separator:", getFieldEditorParent()); + addField(customCopyTableSeparator); + StringFieldEditor customCopyColumnItem = new StringFieldEditor("customCopyColumnItem2", "&Column Item:", getFieldEditorParent()); + addField(customCopyColumnItem); + StringFieldEditor customCopyColumnSeparator = new StringFieldEditor("customCopyColumnSeparator2", "&Column Separator:", getFieldEditorParent()); + addField(customCopyColumnSeparator); + StringFieldEditor customCopyTemplate = new StringFieldEditor("customCopyTemplate2", "&Template:", getFieldEditorParent()); + addField(customCopyTemplate); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences3.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences3.java new file mode 100644 index 0000000..2b3cf1b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/CustomCopyPreferences3.java @@ -0,0 +1,46 @@ +package com.quantum.preferences; + + +import com.quantum.QuantumPlugin; + +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +public class CustomCopyPreferences3 + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public CustomCopyPreferences3() { + super(FieldEditorPreferencePage.GRID); + + // Set the preference store for the preference page. + IPreferenceStore store = + QuantumPlugin.getDefault().getPreferenceStore(); + setPreferenceStore(store); + } + + public void init(IWorkbench workbench) { + this.workbench = workbench; + } + + IWorkbench workbench; + + protected void createFieldEditors() { + StringFieldEditor customCopyName = new StringFieldEditor("customCopyName3", "&Name:", getFieldEditorParent()); + addField(customCopyName); + StringFieldEditor customCopyTableItem = new StringFieldEditor("customCopyTableItem3", "&Table Item:", getFieldEditorParent()); + addField(customCopyTableItem); + StringFieldEditor customCopyTableSeparator = new StringFieldEditor("customCopyTableSeparator3", "&Table Separator:", getFieldEditorParent()); + addField(customCopyTableSeparator); + StringFieldEditor customCopyColumnItem = new StringFieldEditor("customCopyColumnItem3", "&Column Item:", getFieldEditorParent()); + addField(customCopyColumnItem); + StringFieldEditor customCopyColumnSeparator = new StringFieldEditor("customCopyColumnSeparator3", "&Column Separator:", getFieldEditorParent()); + addField(customCopyColumnSeparator); + StringFieldEditor customCopyTemplate = new StringFieldEditor("customCopyTemplate3", "&Template:", getFieldEditorParent()); + addField(customCopyTemplate); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/GlobalPreferences.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/GlobalPreferences.java new file mode 100644 index 0000000..05156eb --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/GlobalPreferences.java @@ -0,0 +1,49 @@ +package com.quantum.preferences; + + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; + +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.IntegerFieldEditor; +import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +/** + * PreferencePage for the global options on QuantumDB + * @author panic + * + */ +public class GlobalPreferences +extends FieldEditorPreferencePage +implements IWorkbenchPreferencePage { + + public GlobalPreferences() { + super(FieldEditorPreferencePage.GRID); + + // Set the preference store for the preference page. + IPreferenceStore store = + QuantumPlugin.getDefault().getPreferenceStore(); + setPreferenceStore(store); + } + + public void init(IWorkbench workbench) { + this.workbench = workbench; + } + + IWorkbench workbench; + + protected void createFieldEditors() { + IntegerFieldEditor queryHistorySize = new IntegerFieldEditor( + "com.quantum.model.Bookmark.queryHistorySize", + Messages.getString(getClass().getName() + "." + + "com.quantum.model.Bookmark.queryHistorySize"), + getFieldEditorParent()); + queryHistorySize.setValidRange(0, Integer.MAX_VALUE); + this.addField(queryHistorySize); + StringFieldEditor askPasswordString = new StringFieldEditor("askPasswordString", "&Ask for password string:", getFieldEditorParent()); + this.addField(askPasswordString); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/SQLEditorPreferences.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/SQLEditorPreferences.java new file mode 100644 index 0000000..b1697ba --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/preferences/SQLEditorPreferences.java @@ -0,0 +1,339 @@ +package com.quantum.preferences; + + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.editors.ColorManager; +import com.quantum.editors.SQLColorConstants; +import com.quantum.util.versioning.VersioningHelper; + +import org.eclipse.jface.preference.ColorFieldEditor; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.RGB; +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.FontDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +public class SQLEditorPreferences extends PreferencePage + implements IWorkbenchPreferencePage { + FontDialog fontDialog; + ColorFieldEditor backgroundColorEditor; + + ColorFieldEditor textColorEditor; + boolean textFlag; + ColorFieldEditor keywordColorEditor; + boolean keywordFlag; + ColorFieldEditor stringColorEditor; + boolean stringFlag; + ColorFieldEditor numericColorEditor; + boolean numericFlag; + ColorFieldEditor commentColorEditor; + boolean commentFlag; + + Button boldText; + Button boldKeyword; + Button boldString; + Button boldNumeric; + Button boldComment; + + IWorkbench workbench; + FontData fontData; + Label fontDisplay; + public void init(IWorkbench workbench) { + //Initialize the preference store + this.workbench = workbench; + setPreferenceStore(QuantumPlugin.getDefault().getPreferenceStore()); + initializeColorDefaults(getPreferenceStore()); + } + + private void initializeColorDefaults(IPreferenceStore store) { + RGB BACKGROUND = new RGB(255, 255, 255); + RGB COMMENT = new RGB(88, 148, 64); + RGB KEYWORD = new RGB(126, 0, 75); + RGB STRING = new RGB(0, 0, 255); + RGB NUMERIC = new RGB(255, 0, 0); + RGB DEFAULT = new RGB(0, 0, 0); + PreferenceConverter.setDefault(store, + "quantum.background.color", BACKGROUND); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.text.color", DEFAULT); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.keyword.color", KEYWORD); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.comment.color", COMMENT); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.string.color", STRING); //$NON-NLS-1$ + PreferenceConverter.setDefault(store, + "quantum.numeric.color", NUMERIC); //$NON-NLS-1$ + } + + protected void performDefaults() { + fontData = null; + updateFontDisplay(); + textFlag = false; + keywordFlag = true; + stringFlag = false; + numericFlag = false; + commentFlag = false; + updateFlags(); + backgroundColorEditor.loadDefault(); + textColorEditor.loadDefault(); + keywordColorEditor.loadDefault(); + stringColorEditor.loadDefault(); + commentColorEditor.loadDefault(); + numericColorEditor.loadDefault(); + } + /** + * Save the preferences to the preference store. + */ + public boolean performOk() { + PreferenceConverter.setValue(getPreferenceStore(), "quantum.font", fontData); //$NON-NLS-1$ + getPreferenceStore().setValue("quantum.text.bold", textFlag); //$NON-NLS-1$ + getPreferenceStore().setValue("quantum.keyword.bold", keywordFlag); //$NON-NLS-1$ + getPreferenceStore().setValue("quantum.string.bold", stringFlag); //$NON-NLS-1$ + getPreferenceStore().setValue("quantum.comment.bold", commentFlag); //$NON-NLS-1$ + getPreferenceStore().setValue("quantum.numeric.bold", numericFlag); //$NON-NLS-1$ + backgroundColorEditor.store(); + textColorEditor.store(); + keywordColorEditor.store(); + stringColorEditor.store(); + commentColorEditor.store(); + numericColorEditor.store(); + return super.performOk(); + } + protected Control createContents(Composite parent) { + Composite main = new Composite(parent, SWT.NULL); + + GridLayout innerLayout = new GridLayout(); + innerLayout.numColumns = 4; + main.setLayout(innerLayout); + + fontData = PreferenceConverter.getFontData(getPreferenceStore(), "quantum.font"); //$NON-NLS-1$ + textFlag = getPreferenceStore().getBoolean("quantum.text.bold"); //$NON-NLS-1$ + keywordFlag = getPreferenceStore().getBoolean("quantum.keyword.bold"); //$NON-NLS-1$ + stringFlag = getPreferenceStore().getBoolean("quantum.string.bold"); //$NON-NLS-1$ + commentFlag = getPreferenceStore().getBoolean("quantum.comment.bold"); //$NON-NLS-1$ + numericFlag = getPreferenceStore().getBoolean("quantum.numeric.bold"); //$NON-NLS-1$ + + fontDialog = new FontDialog(workbench.getActiveWorkbenchWindow().getShell()); + Button fontButton = new Button(main, SWT.PUSH); + fontButton.setText(Messages.getString("PreferencesPage.PickFont")); //$NON-NLS-1$ + fontButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + if (fontData != null) { + VersioningHelper.setFont(fontDialog, new FontData[] { fontData} ); + } + FontData data = fontDialog.open(); + if (data != null) { + fontData = data; + updateFontDisplay(); + } + } + }); + Button defaultButton = new Button(main, SWT.PUSH); + defaultButton.setText(Messages.getString("PreferencesPage.DefaultFont")); //$NON-NLS-1$ + defaultButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + fontData = null; + updateFontDisplay(); + } + }); + + fontDisplay = new Label(main, SWT.NULL); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.grabExcessHorizontalSpace = true; + fontDisplay.setLayoutData(data); + updateFontDisplay(); + + ColorManager manager = new ColorManager(); + + Composite comp = new Composite(main, SWT.NULL); + GridData layoutData = new GridData(); + layoutData.horizontalSpan = 2; + comp.setLayoutData(layoutData); + + manager.getColor(SQLColorConstants.DEFAULT); + backgroundColorEditor = + new ColorFieldEditor( + "quantum.background.color", //$NON-NLS-1$ + Messages.getString("PreferencesPage.BackgroundColor"), //$NON-NLS-1$ + comp); + + Composite temp = new Composite(main, SWT.NULL); + temp.setSize(0, 0); + + comp = new Composite(main, SWT.NULL); + layoutData = new GridData(); + layoutData.horizontalSpan = 2; + comp.setLayoutData(layoutData); + + textColorEditor = + new ColorFieldEditor( + "quantum.text.color", //$NON-NLS-1$ + Messages.getString("PreferencesPage.DefaultTextColor"), //$NON-NLS-1$ + comp); + + boldText = new Button(main, SWT.CHECK); + boldText.setSelection(textFlag); + boldText.setText(Messages.getString("PreferencesPage.Bold")); //$NON-NLS-1$ + boldText.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + textFlag = boldText.getSelection(); + } + }); + + comp = new Composite(main, SWT.NULL); + layoutData = new GridData(); + layoutData.horizontalSpan = 2; + comp.setLayoutData(layoutData); + + keywordColorEditor = + new ColorFieldEditor( + Messages.getString("PreferencesPage.quantum.keyword.color_26"), //$NON-NLS-1$ + Messages.getString("PreferencesPage.KeywordTextColor"), //$NON-NLS-1$ + comp); + + boldKeyword = new Button(main, SWT.CHECK); + boldKeyword.setSelection(keywordFlag); + boldKeyword.setText(Messages.getString("PreferencesPage.Bold")); //$NON-NLS-1$ + boldKeyword.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + keywordFlag = boldKeyword.getSelection(); + } + }); + + comp = new Composite(main, SWT.NULL); + layoutData = new GridData(); + layoutData.horizontalSpan = 2; + comp.setLayoutData(layoutData); + + commentColorEditor = + new ColorFieldEditor( + "quantum.comment.color", //$NON-NLS-1$ + Messages.getString("PreferencesPage.CommentTextColor"), //$NON-NLS-1$ + comp); + + boldComment = new Button(main, SWT.CHECK); + boldComment.setSelection(commentFlag); + boldComment.setText(Messages.getString("PreferencesPage.Bold")); //$NON-NLS-1$ + boldComment.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + commentFlag = boldComment.getSelection(); + } + }); + + comp = new Composite(main, SWT.NULL); + layoutData = new GridData(); + layoutData.horizontalSpan = 2; + comp.setLayoutData(layoutData); + + stringColorEditor = + new ColorFieldEditor( + "quantum.string.color", //$NON-NLS-1$ + Messages.getString("PreferencesPage.StringTextColor"), //$NON-NLS-1$ + comp); + + boldString = new Button(main, SWT.CHECK); + boldString.setSelection(stringFlag); + boldString.setText(Messages.getString("PreferencesPage.Bold")); //$NON-NLS-1$ + boldString.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + stringFlag = boldString.getSelection(); + } + }); + + comp = new Composite(main, SWT.NULL); + layoutData = new GridData(); + layoutData.horizontalSpan = 2; + comp.setLayoutData(layoutData); + + numericColorEditor = + new ColorFieldEditor( + "quantum.numeric.color", //$NON-NLS-1$ + Messages.getString("PreferencesPage.NumericTextColor"), //$NON-NLS-1$ + comp); + + boldNumeric = new Button(main, SWT.CHECK); + boldNumeric.setSelection(numericFlag); + boldNumeric.setText(Messages.getString("PreferencesPage.Bold")); //$NON-NLS-1$ + boldNumeric.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + numericFlag = boldNumeric.getSelection(); + } + }); + + backgroundColorEditor.setPreferencePage(this); + backgroundColorEditor.setPreferenceStore(getPreferenceStore()); + backgroundColorEditor.load(); + + textColorEditor.setPreferencePage(this); + textColorEditor.setPreferenceStore(getPreferenceStore()); + textColorEditor.load(); + + keywordColorEditor.setPreferencePage(this); + keywordColorEditor.setPreferenceStore(getPreferenceStore()); + keywordColorEditor.load(); + + commentColorEditor.setPreferencePage(this); + commentColorEditor.setPreferenceStore(getPreferenceStore()); + commentColorEditor.load(); + + stringColorEditor.setPreferencePage(this); + stringColorEditor.setPreferenceStore(getPreferenceStore()); + stringColorEditor.load(); + + numericColorEditor.setPreferencePage(this); + numericColorEditor.setPreferenceStore(getPreferenceStore()); + numericColorEditor.load(); + + return main; + } + public void updateFontDisplay() { + if (fontData == null) { + fontDisplay.setText(Messages.getString("PreferencesPage.Font_Default")); //$NON-NLS-1$ + } else { + String style = Messages.getString("PreferencesPage.regular"); //$NON-NLS-1$ + if (fontData.getStyle() == SWT.BOLD) { + style = Messages.getString("PreferencesPage.bold"); //$NON-NLS-1$ + } else if (fontData.getStyle() == SWT.ITALIC) { + style = Messages.getString("PreferencesPage.italic"); //$NON-NLS-1$ + } else if (fontData.getStyle() == (SWT.BOLD | SWT.ITALIC)) { + style = Messages.getString("PreferencesPage.boldItalic"); //$NON-NLS-1$ + } + fontDisplay.setText(Messages.getString("PreferencesPage.FontPrompt") + fontData.getName() + '-' + style + '-' + fontData.getHeight()); //$NON-NLS-1$ + } + } + public void updateFlags() { + boldText.setSelection(textFlag); + boldKeyword.setSelection(keywordFlag); + boldString.setSelection(stringFlag); + boldNumeric.setSelection(numericFlag); + boldComment.setSelection(commentFlag); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/BookmarkPropertyPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/BookmarkPropertyPage.java new file mode 100644 index 0000000..42c4065 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/BookmarkPropertyPage.java @@ -0,0 +1,284 @@ +package com.quantum.properties; + +import com.quantum.IQuantumConstants; +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DriverInfo; +import com.quantum.model.Bookmark; +import com.quantum.view.bookmark.TreeNode; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.dialogs.PropertyPage; + +public class BookmarkPropertyPage extends PropertyPage { + + private Text password; + private Text userid; + private Button prompt; + + private Text jdbcURL; + private Text driverName; + private Text driverPath; + + private Combo type; + private Combo autoCommit; + private DriverInfo[] adapters = AdapterFactory.getInstance().getDriverList(); + + protected Control createContents(Composite parent) { + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout(layout); + GridData data = new GridData(GridData.FILL); + data.grabExcessHorizontalSpace = true; + composite.setLayoutData(data); + + Label nameLabel = new Label(composite, SWT.NONE); + nameLabel.setText("Name:"); + + Label name = new Label(composite, SWT.NONE); + + Bookmark bookmark = getBookmark(); + String description = bookmark.getName(); + name.setText(description); + + TabFolder tabFolder = new TabFolder(parent, SWT.NONE); + layout = new GridLayout(); + tabFolder.setLayout(layout); + data = new GridData(GridData.FILL_BOTH); + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + data.verticalAlignment = GridData.FILL; + data.horizontalSpan = 2; + data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + tabFolder.setLayoutData(data); + + createUserTab(tabFolder); + createDriverTab(tabFolder); + createOptionsTab(tabFolder); + + performDefaults(); + return composite; + } + + private Bookmark getBookmark() { + Bookmark bookmark = + ((TreeNode) getElement()).getBookmark(); + return bookmark; + } + + private void createDriverTab(TabFolder tabFolder) { + TabItem driverTab = new TabItem(tabFolder, SWT.NONE); + driverTab.setText("JDBC Driver"); + + Composite composite = new Composite(tabFolder, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout(layout); + GridData data = new GridData(GridData.FILL); + data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + data.grabExcessHorizontalSpace = true; + composite.setLayoutData(data); + + Label label = new Label(composite, SWT.NONE); + label.setText("Connection URL:"); + + this.jdbcURL = new Text(composite, SWT.BORDER); + data = new GridData(GridData.FILL); + data.horizontalAlignment = GridData.FILL; + data.grabExcessHorizontalSpace = true; + data.grabExcessHorizontalSpace = true; + this.jdbcURL.setLayoutData(data); + + label = new Label(composite, SWT.NONE); + label.setText("Driver Name:"); + + this.driverName = new Text(composite, SWT.BORDER); + data = new GridData(GridData.FILL); + data.horizontalAlignment = GridData.FILL; + data.grabExcessHorizontalSpace = true; + this.driverName.setLayoutData(data); + + label = new Label(composite, SWT.NONE); + label.setText("Driver Location:"); + + this.driverPath = new Text(composite, SWT.BORDER); + data = new GridData(GridData.FILL); + data.horizontalAlignment = GridData.FILL; + data.grabExcessHorizontalSpace = true; + this.driverPath.setLayoutData(data); + + label = new Label(composite, SWT.NULL); + label.setText("Type:"); + this.type = new Combo(composite, SWT.SIMPLE | SWT.DROP_DOWN | SWT.READ_ONLY); + String adapterNames[] = new String[adapters.length]; + for (int i = 0; i < adapters.length; i++) { + adapterNames[i] = adapters[i].getDisplayName(); + } + this.type.setItems(adapterNames); + + data = new GridData(); + data.horizontalAlignment = GridData.FILL; + this.type.setLayoutData(data); + + driverTab.setControl(composite); + } + + private void createUserTab(TabFolder tabFolder) { + TabItem userTab = new TabItem(tabFolder, SWT.NONE); + userTab.setText("User"); + + Composite composite = new Composite(tabFolder, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout(layout); + GridData data = new GridData(GridData.FILL); + data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + data.grabExcessHorizontalSpace = true; + composite.setLayoutData(data); + + Label useridLabel = new Label(composite, SWT.NONE); + useridLabel.setText("Userid:"); + + this.userid = new Text(composite, SWT.BORDER); + data = new GridData(GridData.FILL); + data.horizontalAlignment = GridData.FILL; + data.grabExcessHorizontalSpace = true; + data.grabExcessHorizontalSpace = true; + this.userid.setLayoutData(data); + + Label passworLabel = new Label(composite, SWT.NONE); + passworLabel.setText("Password:"); + + this.password = new Text(composite, SWT.BORDER); + this.password.setEchoChar('*'); + data = new GridData(GridData.FILL); + data.horizontalAlignment = GridData.FILL; + data.grabExcessHorizontalSpace = true; + this.password.setLayoutData(data); + + this.prompt = new Button(composite, SWT.CHECK); + this.prompt.setText("Prompt for password"); + data = new GridData(GridData.FILL); + data.horizontalSpan = 2; + data.horizontalAlignment = GridData.FILL; + data.grabExcessHorizontalSpace = true; + this.prompt.setLayoutData(data); + + this.prompt.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + password.setEditable(!((Button) event.getSource()).getSelection()); + } + }); + + userTab.setControl(composite); + } + + /** + * @param tabFolder + */ + private void createOptionsTab(TabFolder tabFolder) { + TabItem optionsTab = new TabItem(tabFolder, SWT.NONE); + optionsTab.setText("Options"); + + Composite composite = new Composite(tabFolder, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout(layout); + GridData data = new GridData(GridData.FILL); + data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + data.grabExcessHorizontalSpace = true; + composite.setLayoutData(data); + + Label label; + + label = new Label(composite, SWT.NULL); + label.setText("On connection, Auto-Commit should be:"); + this.autoCommit = new Combo(composite, SWT.SIMPLE | SWT.DROP_DOWN | SWT.READ_ONLY); + String autoCommitTypes[] = new String[] { + IQuantumConstants.autoCommitTrue, + IQuantumConstants.autoCommitFalse, + IQuantumConstants.autoCommitSaved + }; + this.autoCommit.setItems(autoCommitTypes); + + data = new GridData(); + data.horizontalAlignment = GridData.FILL; + this.autoCommit.setLayoutData(data); + + optionsTab.setControl(composite); + + } + + + + /** + * @see org.eclipse.jface.preference.PreferencePage#performApply() + */ + public boolean performOk() { + Bookmark bookmark = getBookmark(); + bookmark.setUsername(this.userid.getText()); + bookmark.setPromptForPassword(this.prompt.getSelection()); + if (this.prompt.getSelection()) { + bookmark.setPassword(""); + } else { + bookmark.setPassword(this.password.getText()); + } + + int index = this.type.getSelectionIndex(); + bookmark.setType(this.adapters[index].getDriverType()); + bookmark.setConnect(this.jdbcURL.getText()); + bookmark.setDriver(this.driverName.getText()); + bookmark.setDriverFile(this.driverPath.getText()); + if (this.autoCommit.getSelectionIndex() >= 0) + bookmark.setAutoCommitPreference(this.autoCommit.getItem(this.autoCommit.getSelectionIndex())); + return super.performOk(); + } + /* (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#performDefaults() + */ + protected void performDefaults() { + super.performDefaults(); + Bookmark bookmark = getBookmark(); + + this.prompt.setSelection(bookmark.getPromptForPassword()); + this.password.setEditable(!bookmark.getPromptForPassword()); + this.password.setText(bookmark.getPassword()); + this.userid.setText(bookmark.getUsername()); + + this.type.select(0); + boolean done = false; + for (int i = 0, + length = (adapters == null) ? 0 : adapters.length; + !done && i < length; + i++) { + if (bookmark.getType() != null && + bookmark.getType().equals(adapters[i].getDriverType())) { + this.type.select(i); + done = true; + } + } + if (bookmark.getAutoCommitPreference().equals(IQuantumConstants.autoCommitTrue)) + this.autoCommit.select(0); + else if (bookmark.getAutoCommitPreference().equals(IQuantumConstants.autoCommitFalse)) + this.autoCommit.select(1); + else if (bookmark.getAutoCommitPreference().equals(IQuantumConstants.autoCommitSaved)) + this.autoCommit.select(2); + + this.driverName.setText(bookmark.getDriver()); + this.jdbcURL.setText(bookmark.getConnect()); + this.driverPath.setText(bookmark.getDriverFile()); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/DatabaseInformationPropertyPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/DatabaseInformationPropertyPage.java new file mode 100644 index 0000000..e1a0606 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/DatabaseInformationPropertyPage.java @@ -0,0 +1,60 @@ +package com.quantum.properties; + +import java.sql.SQLException; + +import com.quantum.model.Bookmark; +import com.quantum.model.NotConnectedException; +import com.quantum.view.bookmark.TreeNode; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.dialogs.PropertyPage; + +public class DatabaseInformationPropertyPage extends PropertyPage { + + public DatabaseInformationPropertyPage() { + super(); + } + + protected Control createContents(Composite parent) { + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout(layout); + GridData data = new GridData(GridData.FILL); + data.grabExcessHorizontalSpace = true; + composite.setLayoutData(data); + + Label productLabel = new Label(composite, SWT.NONE); + productLabel.setText("Product:"); + + Label productDescriptionLabel = new Label(composite, SWT.NONE); + + Bookmark bookmark = + ((TreeNode) getElement()).getBookmark(); + String description = null; + try { + description = bookmark.getDatabase().getInformation(); + } catch (NotConnectedException e) { + } catch (SQLException e) { + } + if (description == null) { + description = ""; + } + productDescriptionLabel.setText(description); + return composite; + } + + protected void performDefaults() { + } + + public boolean performOk() { + return true; + } + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/EntityPropertyPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/EntityPropertyPage.java new file mode 100644 index 0000000..6937c1b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/EntityPropertyPage.java @@ -0,0 +1,187 @@ +package com.quantum.properties; + +import com.quantum.model.Column; +import com.quantum.model.Entity; +import com.quantum.model.Index; +import com.quantum.view.bookmark.EntityNode; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.ui.dialogs.PropertyPage; + +public class EntityPropertyPage extends PropertyPage { + + protected Control createContents(Composite parent) { + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout(layout); + GridData data = new GridData(GridData.FILL); + data.grabExcessHorizontalSpace = true; + composite.setLayoutData(data); + + Label label = new Label(composite, SWT.NONE); + label.setText("Name:"); + + Entity entity = getEntity(); + + Label name = new Label(composite, SWT.NONE); + name.setText(entity.getName()); + + label = new Label(composite, SWT.NONE); + label.setText("Schema:"); + + Label schema = new Label(composite, SWT.NONE); + schema.setText(entity.getSchema()); + + if (!Entity.SEQUENCE_TYPE.equals(getEntity().getType())) { + TabFolder tabFolder = new TabFolder(parent, SWT.NONE); + layout = new GridLayout(); + tabFolder.setLayout(layout); + data = new GridData(GridData.FILL_BOTH); + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + data.verticalAlignment = GridData.FILL; + data.horizontalSpan = 2; + data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + tabFolder.setLayoutData(data); + + createColumnsTab(tabFolder); + createIndexesTab(tabFolder); + } + + return composite; + } + + private Entity getEntity() { + Entity entity = + ((EntityNode) getElement()).getEntity(); + return entity; + } + + private void createColumnsTab(TabFolder tabFolder) { + TabItem columnsTab = new TabItem(tabFolder, SWT.NONE); + columnsTab.setText("Columns"); + + Table table = new Table(tabFolder, SWT.FULL_SELECTION | SWT.MULTI); + table.setLinesVisible(true); + table.setHeaderVisible(true); + + GridLayout layout = new GridLayout(); + layout.marginWidth = 5; + layout.marginHeight = 5; + table.setLayout(layout); + GridData data = new GridData(GridData.FILL); + data.horizontalAlignment = GridData.FILL_HORIZONTAL; + data.verticalAlignment = GridData.FILL_VERTICAL; + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + table.setLayoutData(data); + + String[] columnNames = { "Name", "Type", "Size", "Digits", + "Primary Key", "Nullable", "Remarks" }; + + for (int i = 0, length = columnNames.length; i < length; i++) { + TableColumn column = new TableColumn(table, SWT.NONE); + column.setText(columnNames[i]); + } + for (int i = 0, length = columnNames.length; i < length; i++) { + table.getColumn(i).pack(); + } + + Column[] columns = getEntity().getColumns(); + for (int i = 0, length = columns.length; i < length; i++) { + TableItem item = new TableItem(table, SWT.NONE); + item.setText(new String[] { + columns[i].getName(), + columns[i].getTypeName(), + String.valueOf(columns[i].getSize()), + columns[i].getNumberOfFractionalDigits() == 0 ? "" : + String.valueOf(columns[i].getNumberOfFractionalDigits()), + columns[i].isPrimaryKey() ? "Yes" : "No", + columns[i].isNullable() ? "Yes" : "No", + columns[i].getRemarks() }); + } + + for (int i = 0, length = columnNames.length; i < length; i++) { + table.getColumn(i).pack(); + } + + data = new GridData(GridData.FILL); + data.horizontalAlignment = GridData.FILL_HORIZONTAL; + data.verticalAlignment = GridData.FILL_VERTICAL; + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + table.setLayoutData(data); + + columnsTab.setControl(table); + } + + private void createIndexesTab(TabFolder tabFolder) { + TabItem indexesTab = new TabItem(tabFolder, SWT.NONE); + indexesTab.setText("Indexes"); + + Table table = new Table(tabFolder, SWT.FULL_SELECTION | SWT.MULTI); + table.setLinesVisible(true); + table.setHeaderVisible(true); + + GridLayout layout = new GridLayout(); + layout.marginWidth = 5; + layout.marginHeight = 5; + table.setLayout(layout); + GridData data = new GridData(GridData.FILL); + data.horizontalAlignment = GridData.FILL_HORIZONTAL; + data.verticalAlignment = GridData.FILL_VERTICAL; + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + table.setLayoutData(data); + + String[] columnNames = { "Name", "Column", "Ascending" }; + + for (int i = 0, length = columnNames.length; i < length; i++) { + TableColumn column = new TableColumn(table, SWT.NONE); + column.setText(columnNames[i]); + } + for (int i = 0, length = columnNames.length; i < length; i++) { + table.getColumn(i).pack(); + } + + Index[] indexes = getEntity().getIndexes(); + for (int i = 0, length = indexes.length; i < length; i++) { + for (int j = 0, numberOfColumns = indexes[i].getNumberOfColumns(); + j < numberOfColumns; j++) { + + TableItem item = new TableItem(table, SWT.NONE); + item.setText(new String[] { + j == 0 ? indexes[i].getName() : "", + indexes[i].getColumnName(j), + indexes[i].isAscending(j) ? "Yes" + : (indexes[i].isDescending(j)) ? "No" : "" }); + } + } + + for (int i = 0, length = columnNames.length; i < length; i++) { + table.getColumn(i).pack(); + } + + data = new GridData(GridData.FILL); + data.horizontalAlignment = GridData.FILL_HORIZONTAL; + data.verticalAlignment = GridData.FILL_VERTICAL; + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + table.setLayoutData(data); + + indexesTab.setControl(table); + } + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/SchemaPropertyPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/SchemaPropertyPage.java new file mode 100644 index 0000000..d812f59 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/properties/SchemaPropertyPage.java @@ -0,0 +1,256 @@ +package com.quantum.properties; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.Vector; + +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.model.BookmarkHolder; +import com.quantum.model.ConnectionException; +import com.quantum.model.Schema; +import com.quantum.sql.SQLHelper; +import com.quantum.ui.dialog.ExceptionDisplayDialog; +import com.quantum.util.connection.ConnectionUtil; +import com.quantum.view.bookmark.AddSchemaDialog; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +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.ui.dialogs.PropertyPage; + +public class SchemaPropertyPage extends PropertyPage { + + class ContentProviderImpl implements IStructuredContentProvider { + public Object[] getElements(Object inputElement) { + List list = new ArrayList((Collection) inputElement); + Collections.sort(list); + return list.toArray(); + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + } + + class LabelProviderImpl implements ITableLabelProvider { + + public Image getColumnImage(Object element, int columnIndex) { + if (columnIndex == 0) { + return QuantumPlugin.getImage("schema.gif"); + } else { + return null; + } + } + + public String getColumnText(Object element, int columnIndex) { + if (columnIndex == 0) { + return ((Schema) element).getDisplayName(); + } else { + return null; + } + } + + public void addListener(ILabelProviderListener listener) { + } + + public void dispose() { + } + + public boolean isLabelProperty(Object element, String property) { + return "displayName".equals(property); + } + + public void removeListener(ILabelProviderListener listener) { + } + } + + private Set schemas = Collections.synchronizedSet(new HashSet()); + private TableViewer schemaTable; + private Button addButton; + private Button removeButton; + + private ConnectionUtil connectionUtil = new ConnectionUtil(); + + protected Control createContents(Composite parent) { + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout(layout); + GridData data = new GridData(); + composite.setLayoutData(data); + + this.schemaTable = new TableViewer(composite, + SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER); + + layout = new GridLayout(); + layout.marginWidth = 5; + layout.marginHeight = 5; + + this.schemaTable.getTable().setLayout(layout); + data = new GridData(); + data.heightHint = 200; + data.widthHint = 200; +// data.verticalSpan = 2; + this.schemaTable.getTable().setLayoutData(data); + this.schemaTable.setLabelProvider(new LabelProviderImpl()); + this.schemaTable.setContentProvider(new ContentProviderImpl()); + this.schemaTable.setInput(this.schemas); + + createButtonArea(composite); + + performDefaults(); + return composite; + } + + private void createButtonArea(Composite composite) { + GridLayout layout; + GridData data; + Composite buttonArea = new Composite(composite, SWT.NONE); + layout = new GridLayout(); + layout.numColumns = 1; + buttonArea.setLayout(layout); + data = new GridData(); + data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + buttonArea.setLayoutData(data); + + this.addButton = new Button(buttonArea, SWT.NULL); + this.addButton.setText("Add"); + data = new GridData(); + data.horizontalAlignment = GridData.FILL_HORIZONTAL; + data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + data.widthHint = 60; + this.addButton.setLayoutData(data); + this.addButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + addSchema(); + } + }); + + this.removeButton = new Button(buttonArea, SWT.NULL); + this.removeButton.setText("Remove"); + this.removeButton.setEnabled(false); + data = new GridData(); + data.horizontalAlignment = GridData.FILL_HORIZONTAL; + data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + data.widthHint = 60; + this.removeButton.setLayoutData(data); + this.removeButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + removeSchema(SchemaPropertyPage.this.schemaTable.getSelection()); + } + }); + + this.schemaTable.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + SchemaPropertyPage.this.removeButton.setEnabled( + !event.getSelection().isEmpty()); + } + }); + } + + private void addSchema() { + Bookmark bookmark = getBookmark(); + boolean isAlreadyConnected = bookmark.isConnected(); + + if (!isAlreadyConnected) { + boolean confirmed = MessageDialog.openConfirm(getShell(), "Connect Required", + "We must connect to the database to retrieve schemas."); + if (confirmed) { + this.connectionUtil.connect(bookmark, getShell()); + } + } + + try { + if (bookmark.isConnected()) { + Vector schemas = SQLHelper.getSchemas(bookmark.getConnection()); + AddSchemaDialog dialog = new AddSchemaDialog(getShell(), schemas); + dialog.open(); + if (dialog.getSelectedSchemas() != null) { + Collection temp = dialog.getSelectedSchemas(); + for (Iterator i = temp.iterator(); i.hasNext();) { + String name = (String) i.next(); + this.schemas.add(new Schema(name)); + } + refreshTable(); + } + + if (!isAlreadyConnected) { + bookmark.disconnect(); + } + } + } catch (ConnectionException e) { + ExceptionDisplayDialog.openError(getShell(), null, null, e); + } + } + + private void removeSchema(ISelection selection) { + IStructuredSelection structuredSelection = (IStructuredSelection) selection; + for (Iterator i = structuredSelection.iterator(); i.hasNext();) { + Schema element = (Schema) i.next(); + this.schemas.remove(element); + } + refreshTable(); + } + + private Bookmark getBookmark() { + Bookmark bookmark = + ((BookmarkHolder) getElement()).getBookmark(); + return bookmark; + } + + /** + * @see org.eclipse.jface.preference.PreferencePage#performApply() + */ + public boolean performOk() { + getBookmark().setSchemas((Schema[]) this.schemas.toArray( + new Schema[this.schemas.size()])); + return true; + } + /* (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#performDefaults() + */ + protected void performDefaults() { + super.performDefaults(); + Bookmark bookmark = getBookmark(); + + this.schemas.clear(); + Schema[] schemas = bookmark.getSchemas(); + for (int i = 0, length = (schemas == null) ? 0 : schemas.length; + i < length; + i++) { + if (!schemas[i].isDefault()) { + this.schemas.add(schemas[i]); + } + } + refreshTable(); + } + + private void refreshTable() { + this.schemaTable.refresh(); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/ConnectionEstablisher.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/ConnectionEstablisher.java new file mode 100644 index 0000000..75d9363 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/ConnectionEstablisher.java @@ -0,0 +1,19 @@ +package com.quantum.sql; + +import java.sql.Connection; + +import com.quantum.model.Bookmark; +import com.quantum.model.ConnectionException; +import com.quantum.model.PasswordFinder; + +/** + * @author BC + */ +public interface ConnectionEstablisher { + + public Connection connect(Bookmark bookmark, PasswordFinder passwordFinder) + throws ConnectionException; + public void disconnect(Connection connection) + throws ConnectionException; + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/FilterSort.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/FilterSort.java new file mode 100644 index 0000000..844e6de --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/FilterSort.java @@ -0,0 +1,83 @@ +package com.quantum.sql; + +import java.util.ArrayList; + +public class FilterSort { + private ArrayList filterList = new ArrayList(); + private ArrayList sortList = new ArrayList(); + private ArrayList ascDescList = new ArrayList(); + public void addFilter(String column, String operator, String value, boolean isString) { + FilterRow row = new FilterRow(); + row.column = column; + row.operator = operator; + row.value = value; + row.isString = isString; + filterList.add(row); + } + public void clearFilters() { + filterList.clear(); + } + public void addSort(String column, String ascDesc) { + int ind = sortList.indexOf(column); + if (ind < 0) { + sortList.add(column); + ascDescList.add(ascDesc); + return; + } + if (ind < ascDescList.size()) { + ascDescList.remove(ind); + } + ascDescList.add(ind, ascDesc); + } + public void removeSort(String column) { + int ind = sortList.indexOf(column); + if (ind < 0) return; + sortList.remove(ind); + ascDescList.remove(ind); + } + public String toString() { + StringBuffer text = new StringBuffer(); + if (filterList.size() > 0) { + text.append(" WHERE "); //$NON-NLS-1$ + for (int i = 0; i < filterList.size(); i++) { + FilterRow row = (FilterRow) filterList.get(i); + text.append(row.column); + text.append(" "); //$NON-NLS-1$ + text.append(row.operator); + text.append(" "); //$NON-NLS-1$ + if (row.isString) { + text.append(escape(row.value)); + } else { + text.append(row.value); + } + text.append(" "); //$NON-NLS-1$ + if (i < filterList.size() - 1) { + text.append("AND "); //$NON-NLS-1$ + } + } + } + if (sortList.size() > 0) { + text.append(" ORDER BY "); //$NON-NLS-1$ + for (int i = 0; i < sortList.size(); i++) { + String value = (String) sortList.get(i); + text.append(value); + text.append(" "); + text.append(ascDescList.get(i)); + if (i < sortList.size() - 1) { + text.append(", "); //$NON-NLS-1$ + } + } + } + return text.toString(); + } + public static String escape(String original) { + return '\'' + original + '\''; + } +} + +class FilterRow { + public String column; + public String operator; + public String value; + public boolean isString; +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/MultiSQLServer.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/MultiSQLServer.java new file mode 100644 index 0000000..843d57f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/MultiSQLServer.java @@ -0,0 +1,426 @@ +package com.quantum.sql; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.InputStream; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.Driver; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Hashtable; +import java.util.Properties; +import java.util.Vector; + +import com.quantum.model.Bookmark; +import com.quantum.model.ConnectionException; +import com.quantum.model.Entity; +import com.quantum.model.PasswordFinder; +import com.quantum.sql.metadata.MetaDataJDBCInterface; +import com.quantum.sql.metadata.ObjectMetaData; +import com.quantum.view.LogProxy; +import com.quantum.view.bookmark.EntityNode; +import com.quantum.view.bookmark.TreeNode; + + +/** + * MultiSQLServer is a Singleton, used as a interface with the sql drivers. + * Use MultiSQLServer.getInstance() to get the object. + */ +public class MultiSQLServer implements ConnectionEstablisher { + private static final int STREAM = 1024 * 2; + public static final String USERNAME = "user"; //$NON-NLS-1$ + public static final String PASSWORD = "password"; //$NON-NLS-1$ + private static MultiSQLServer instance = null; + private Hashtable classLoaderCache = new Hashtable(); + boolean running = true; + + public MultiSQLServer() { + //start(); + } + public synchronized static MultiSQLServer getInstance() { + if (instance == null) { + instance = new MultiSQLServer(); + } + return instance; + } + + public void commit(Connection con) { + LogProxy log = LogProxy.getInstance(); + try { + con.commit(); + } catch (SQLException e) { + log.addText(LogProxy.ERROR, "Error commiting: " + e, e); //$NON-NLS-1$ + } + } + + public void rollback(Connection con) { + LogProxy log = LogProxy.getInstance(); + try { + con.rollback(); + } catch (SQLException e) { + log.addText(LogProxy.ERROR, "Error rolling back: " + e, e); //$NON-NLS-1$ + } + } + + public void setAutoCommit(Connection con, boolean enabled) { + LogProxy log = LogProxy.getInstance(); + try { + if (con != null) { + con.setAutoCommit(enabled); + } else { + log.addText(LogProxy.ERROR, "Please connect before setting autocommit"); //$NON-NLS-1$ + } + } catch (SQLException e) { + log.addText(LogProxy.ERROR, "Error setting autocommit: " + e, e); //$NON-NLS-1$ + } + } + + public void disconnect(Connection connection) throws ConnectionException { + try { + if (connection != null) { + connection.close(); + } + } catch (SQLException e) { + throw new ConnectionException(e); + } + } + + public Vector getSchemas(Connection con) { + ResultSet set; + Vector schemaList = new Vector(); + try { + DatabaseMetaData meta = con.getMetaData(); + set = meta.getSchemas(); + while (set.next()) { + schemaList.add(set.getString("TABLE_SCHEM")); //$NON-NLS-1$ + } + set.close(); + } catch (SQLException e) { + LogProxy log = LogProxy.getInstance(); + log.addText(LogProxy.ERROR, e); + } + return schemaList; + } + /** + * Makes a connection to a JDBC driver based on the data from a bookmark + * @param bookmark - + * The Bookmark with the data needed to make the connection + * @param passwordFinder - + * A utility class that can be invoked if the bookmark does not + * include a password + * @return The Connection object if everything went OK + */ + public Connection connect(Bookmark bookmark, PasswordFinder passwordFinder) + throws ConnectionException { + + String password = bookmark.getPassword(); + if (bookmark.getPromptForPassword()) { + password = passwordFinder.getPassword(); + if (passwordFinder.isPasswordMeantToBeSaved()) { + bookmark.setPassword(password); + } + } + Connection con; + if (password != null) { + con = connect(bookmark, password); + } else { + return null; + } + // Set the autoCommit state of the bookmark to the default on new connections + bookmark.setAutoCommit(bookmark.getDefaultAutoCommit()); + // Set the autoCommit state of the JDBC connection to the bookmark autoCommit statec + setAutoCommit(con, bookmark.isAutoCommit()); + return con; + + } + private Connection connect(Bookmark bookmark, String password) + throws ConnectionException { + LogProxy log = LogProxy.getInstance(); + log.addText(LogProxy.QUERY, "Connecting to: " + bookmark.getName()); //$NON-NLS-1$ + URL urls[] = new URL[1]; + try { + String driverFile = bookmark.getDriverFile(); + URLClassLoader loader = + (URLClassLoader) classLoaderCache.get(driverFile); + if (loader == null) { + urls[0] = new File(driverFile).toURL(); + loader = new URLClassLoader(urls); + classLoaderCache.put(driverFile, loader); + System.out.println("Creating new classloader"); //$NON-NLS-1$ + } else { + System.out.println("Using classloader in cache"); //$NON-NLS-1$ + } + Class driverClass = loader.loadClass(bookmark.getDriver()); + Driver driver = (Driver) driverClass.newInstance(); + Properties props = new Properties(); + props.put(USERNAME, bookmark.getUsername()); + props.put(PASSWORD, password); + Connection connection = + driver.connect(bookmark.getConnect(), props); + if (connection == null) { + throw new ConnectionException("Error: Driver returned a null connection: " + bookmark.toString()); //$NON-NLS-1$ + } + log.addText(LogProxy.RESULTS, "Connected to: " + bookmark.getName()); //$NON-NLS-1$ + System.out.println("Connected"); //$NON-NLS-1$ + return connection; + } catch (SQLException e) { + throw new ConnectionException(e); + } catch (MalformedURLException e) { + throw new ConnectionException(e); + } catch (ClassNotFoundException e) { + throw new ConnectionException(e); + } catch (InstantiationException e) { + throw new ConnectionException(e); + } catch (IllegalAccessException e) { + throw new ConnectionException(e); + } + } + public SQLResults execute(Connection con, String s) throws SQLException { + return execute(con, s, -1, -1); + } + public SQLResults execute(Connection con, String s, int startRow, int endRow) throws SQLException { + return execute(con, s, -1, -1, Integer.MAX_VALUE); + } + + public SQLResults execute(Connection con, String s, int startRow, int endRow, int maxLength) throws SQLException { + return execute(con, s, startRow, endRow, maxLength, ""); //$NON-NLS-1$ + } + + public SQLResults execute( + Connection con, + String s, + int startRow, + int endRow, + int maxLength, + String encoding) + throws SQLException { + + SQLResults results = new SQLResults(); + + System.out.println("Executing"); //$NON-NLS-1$ + LogProxy log = LogProxy.getInstance(); + log.addText(LogProxy.QUERY, "Executing Request [" + s + "]"); //$NON-NLS-1$ //$NON-NLS-2$ + boolean metadata = false; + if (s.startsWith("METADATA")) { //$NON-NLS-1$ + metadata = true; + } + if (metadata) { + results.setQuery(s); + String table = s.substring(s.indexOf(':') + 1); + String query = "SELECT * FROM " + table + " WHERE (1 = 0)"; //$NON-NLS-1$ //$NON-NLS-2$ + s = query; + log.addText(LogProxy.QUERY, "Metadata Request [" + s + "]"); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + results.setQuery(s); + } + + Statement stmt = con.createStatement(); + boolean flag = stmt.execute(s); + results.setResultSet(flag); + if (metadata) { + genMetadataResultSet(results, stmt); + return results; + } + if (!flag) { + int updates = stmt.getUpdateCount(); + results.setUpdateCount(updates); + log.addText(LogProxy.RESULTS, "Success: " + updates + " records updated"); //$NON-NLS-1$ //$NON-NLS-2$ + + } else { + ResultSet set = stmt.getResultSet(); + ResultSetMetaData metaData = set.getMetaData(); + int columnCount = metaData.getColumnCount(); + Vector columnNames = new Vector(); + for (int i = 1; i <= columnCount; i++) { + columnNames.addElement(metaData.getColumnName(i)); + } + results.setColumnNames(columnNames); + Vector columnTypes = new Vector(); + for (int i = 1; i <= columnCount; i++) { + columnTypes.addElement(metaData.getColumnTypeName(i)); + } + results.setColumnTypes(columnTypes); + int columnSizes[] = new int[columnCount]; + for (int i = 1; i <= columnCount; i++) { + columnSizes[i - 1] = metaData.getColumnDisplaySize(i); + } + int rowCount = 1; + boolean exitEarly = false; + while (set.next()) { + boolean disable = startRow < 1 || endRow < 1; + boolean start = rowCount >= startRow; + boolean end = rowCount <= endRow; + if (disable || (start && end)) { + Vector row = new Vector(); + for (int i = 1; i <= columnCount; i++) { + String value; + if (columnSizes[i - 1] < STREAM + && columnSizes[i - 1] < maxLength) { + if (encoding.equals("")) { //$NON-NLS-1$ + value = set.getString(i); + } else { + try { + value = + new String(set.getBytes(i), encoding); + } catch (UnsupportedEncodingException e) { + log.addText(LogProxy.ERROR, "Error Unsupported encoding " + encoding.toString() + ":" + e.toString(), e); //$NON-NLS-1$ //$NON-NLS-2$ + value = new String(set.getBytes(i)); + } + } + } else { + try { + if (encoding.equals("")) { //$NON-NLS-1$ + Reader reader = set.getCharacterStream(i); + StringBuffer buffer = new StringBuffer(); + if (reader != null) { + int retVal = reader.read(); + int count = 0; + while (retVal >= 0) { + buffer.append((char) retVal); + retVal = reader.read(); + count++; + if (count > maxLength) { + buffer.append("...>>>"); //$NON-NLS-1$ + break; + } + } + reader.close(); + } + value = buffer.toString(); + } else { + InputStream binaryStream = + set.getBinaryStream(i); + ByteArrayOutputStream baos = + new ByteArrayOutputStream(); + if (binaryStream != null) { + int retVal = binaryStream.read(); + int count = 0; + while (retVal >= 0) { + baos.write(retVal); + retVal = binaryStream.read(); + count++; + if (count > maxLength) { + break; + } + } + binaryStream.close(); + } + value = + new String( + baos.toByteArray(), + encoding); + } + } catch (Throwable e) { + // hack for mysql which doesn't implement + // character streams + value = set.getString(i); + } + } + if (set.wasNull()) { + row.addElement(""); //$NON-NLS-1$ + } else { + row.addElement(value); + } + } + results.addRow(row); + } + rowCount++; + if (!disable && (rowCount > endRow)) { + exitEarly = true; + break; + } + } + if (exitEarly) { + results.setHasMore(set.next()); + } else { + results.setMaxSize(rowCount); + results.setHasMore(false); + } + set.close(); + } + log.addText(LogProxy.RESULTS, "Success: result set displayed"); //$NON-NLS-1$ + stmt.close(); + System.out.println("Executed"); //$NON-NLS-1$ + System.out.println(); + return results; + } + private void genMetadataResultSet(SQLResults results, Statement stmt) + throws SQLException { + ResultSet set = stmt.getResultSet(); + ResultSetMetaData metaData = set.getMetaData(); + int columnCount = metaData.getColumnCount(); + Vector columnNames = new Vector(); + columnNames.addElement("ColumnName"); //$NON-NLS-1$ + columnNames.addElement("Type"); //$NON-NLS-1$ + columnNames.addElement("Size"); //$NON-NLS-1$ + columnNames.addElement("Nullable"); //$NON-NLS-1$ + columnNames.addElement("AutoIncrement"); //$NON-NLS-1$ + results.setColumnNames(columnNames); + for (int i = 1; i <= columnCount; i++) { + Vector row = new Vector(); + row.addElement(metaData.getColumnName(i)); + row.addElement(metaData.getColumnTypeName(i)); + int textSize = metaData.getColumnDisplaySize(i); + int precision = metaData.getPrecision(i); + int scale = metaData.getScale(i); + if (scale == 0 && precision == 0) { + row.addElement(Integer.toString(precision)); + } else { + row.addElement(textSize + ", " + precision + ", " + scale); //$NON-NLS-1$ //$NON-NLS-2$ + } + int nullable = metaData.isNullable(i); + if (nullable == ResultSetMetaData.columnNoNulls) { + row.addElement("Not Null"); //$NON-NLS-1$ + } else if (nullable == ResultSetMetaData.columnNullable) { + row.addElement("Nullable"); //$NON-NLS-1$ + } else if ( + nullable == ResultSetMetaData.columnNullableUnknown) { + row.addElement("Nullable"); //$NON-NLS-1$ + } else { + row.addElement(""); //$NON-NLS-1$ + } + row.addElement( + (metaData.isAutoIncrement(i) + ? Boolean.TRUE + : Boolean.FALSE) + .toString()); + results.addRow(row); + } + results.setHasMore(false); + set.close(); + } + + /** + * Returns an ObjectMetadata object got from the connection 'con' using the name and schema of the node. + * @param con + * @param node + * @return + * @throws SQLException + */ + public ObjectMetaData getObjectMetadata(Connection con, TreeNode node) throws SQLException { + ObjectMetaData metadata = new ObjectMetaData(); + if (!(node instanceof Entity)) return metadata; + + String schema = ((Entity)node).getSchema(); + String tableName = node.getName(); + + if (schema.length() == 0) schema = null; + metadata.setColumns(MetaDataJDBCInterface.getColumns(con, schema, tableName)); + if (node instanceof EntityNode && ((EntityNode) node).isTable()) { + metadata.setPrimaryKeys(MetaDataJDBCInterface.getPrimaryKeys(con, schema, tableName)); + metadata.setForeignKeys(MetaDataJDBCInterface.getForeignKeys(con, schema, tableName, true)); + metadata.setIndexInfo(MetaDataJDBCInterface.getIndexInfo(con, schema, tableName)); + metadata.setBestRowId(MetaDataJDBCInterface.getBestRowId(con, schema, tableName)); + } + return metadata; + } + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLHelper.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLHelper.java new file mode 100644 index 0000000..7a050d1 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLHelper.java @@ -0,0 +1,73 @@ +package com.quantum.sql; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Vector; + +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.view.LogProxy; + +public class SQLHelper { + + public static Vector getSchemas(Connection connection) { + return MultiSQLServer.getInstance().getSchemas(connection); + } + public static int getSize(Connection connection, String tableName, DatabaseAdapter adapter) throws SQLException { + SQLResults results = MultiSQLServer.getInstance().execute( + connection, adapter.getCountQuery(tableName)); + if (results.getRowCount() > 0 && results.getColumnCount() > 0) { + return Integer.parseInt(results.getElement(1, 1).toString()); + } else { + return -1; + } + } + + public static SQLResults getResults(Connection connection, String query, int start, int end, int maxLength, String encoding) { + try { + return MultiSQLServer.getInstance().execute(connection, + query, start, end, maxLength, encoding); + } catch (SQLException e) { + LogProxy log = LogProxy.getInstance(); + log.addText( + LogProxy.ERROR, + "Error Executing: " + query + ":" + e.toString(), e); //$NON-NLS-1$ //$NON-NLS-2$ + } + SQLResults results = new SQLResults(); + results.setIsError(true); + return results; + } + + /** + * True if the type is Real (numeric and with decimal part) according to java.sql.Types + * @param type + * @return + */ + public static boolean isReal(int type) { + return (type == java.sql.Types.DECIMAL || type == java.sql.Types.DOUBLE || type ==java.sql.Types.FLOAT || + type == java.sql.Types.NUMERIC || type == java.sql.Types.REAL ); + } + + /** + * True if the type is Numeric according to java.sql.Types + * @param type + * @return + */ + public static boolean isNumeric(int type) { + return (type == java.sql.Types.DECIMAL || type == java.sql.Types.DOUBLE || type ==java.sql.Types.FLOAT || + type == java.sql.Types.NUMERIC || type == java.sql.Types.REAL || type == java.sql.Types.BIGINT || + type == java.sql.Types.TINYINT || type == java.sql.Types.SMALLINT || type == java.sql.Types.INTEGER ); + } + /** + * True if the type is textual according to java.sql.Types + * @param type + * @return + */ + public static boolean isText(int type) { + return (type == java.sql.Types.CLOB || type == java.sql.Types.VARBINARY || type ==java.sql.Types.VARCHAR + || type == java.sql.Types.CHAR || type == java.sql.Types.LONGVARCHAR ); + } + + public static String getQualifiedName(String schema, String name) { + return (schema != null && schema.length() > 0) ? schema + "." + name : name; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLParser.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLParser.java new file mode 100644 index 0000000..c2dc2cb --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLParser.java @@ -0,0 +1,62 @@ +package com.quantum.sql; + +import java.util.Vector; + +import com.quantum.sql.parser.SQLLexx; +import com.quantum.sql.parser.Token; + +public class SQLParser { + + /** + * Parses a query string into executable units. + * @param query + * @return a Vector of Strings, with the individual executable units. + */ + public static Vector parse(String query) { + Vector commands = new Vector(); + Vector groups = new Vector(); + try { + Vector tokens = SQLLexx.parse(query); + StringBuffer buffer = new StringBuffer(); + StringBuffer groupBuffer = new StringBuffer(); + for (int i = 0; i < tokens.size(); i++) { + Token t = (Token) tokens.elementAt(i); + if (t.getType() == Token.COMMENT) { + // ignore comments + } else if (t.getType() == Token.SEPARATOR) { + groupBuffer.append(t.getValue()); + String newCommand = buffer.toString().trim(); + if (!newCommand.equals("")) { //$NON-NLS-1$ + commands.addElement(newCommand); + } + buffer = new StringBuffer(); + } else if (t.getType() == Token.GROUP) { + // We don't append the group token because it may be misinterpreted + //groupBuffer.append(t.getValue()); + String newGroup = groupBuffer.toString().trim(); + if (!newGroup.equals("")) { //$NON-NLS-1$ + groups.addElement(newGroup); + //Groups have precedence over commands, so the preceding commands are erased + commands.clear(); + } + groupBuffer = new StringBuffer(); + } else { + // We append the tokens to the buffer until it's a separator or group. + buffer.append(t.getValue()); + groupBuffer.append(t.getValue()); + } + } + String newCommand = buffer.toString().trim(); + if (!newCommand.equals("")) { //$NON-NLS-1$ + commands.addElement(newCommand); + } + } catch (Throwable e) { + e.printStackTrace(); + } + System.out.println("Returning"); //$NON-NLS-1$ + Vector result = new Vector(); + result.addAll(groups); + result.addAll(commands); + return result; + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLResults.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLResults.java new file mode 100644 index 0000000..3abc2b9 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/SQLResults.java @@ -0,0 +1,139 @@ +package com.quantum.sql; + +import java.util.ArrayList; +import java.util.Vector; + +/** + * com.quantum project + * @author root + * +*/ +public class SQLResults { + private String query; + private String table; + private ArrayList rows = new ArrayList(); + private Vector columns; + private Vector columnTypes; + private int[] columnSizes; + private int updateCount = 0; + private boolean resultSet = false; + private boolean hasMore = false; + private boolean isError = false; + private int maxSize = -1; + + public void setColumnNames(Vector columns) { + this.columns = columns; + } + public String getColumnName(int column) { + if (columns.size() < column) return ""; //$NON-NLS-1$ + return columns.elementAt(column - 1).toString(); + + } + public void setColumnTypes(Vector columnsTypes) { + this.columnTypes = columnsTypes; + } + public String getColumnType(int column) { + if (columnTypes.size() < column) return ""; //$NON-NLS-1$ + return columnTypes.elementAt(column - 1).toString(); + } + public void setColumnSizes(int[] columnSizes) { + this.columnSizes = columnSizes; + } + public int getColumnSize(int column) { + if (columnSizes.length < column) return 0; + return columnSizes[column - 1]; + } + public void addRow(Vector row) { + rows.add(row); + } + public Object getElement(int column, int row) { + return ((Vector) rows.get(row - 1)).elementAt(column - 1); + } + public int getColumnCount() { + if (columns.size() > 0) { + return columns.size(); + } + return 0; + } + public int getRowCount() { + return rows.size(); + } + /** + * Returns the query. + * @return String + */ + public String getQuery() { + return query; + } + + /** + * Sets the query. + * @param query The query to set + */ + public void setQuery(String query) { + this.query = query; + } + + /** + * Returns the resultSet. + * @return boolean + */ + public boolean isResultSet() { + return resultSet; + } + + /** + * Sets the resultSet. + * @param resultSet The resultSet to set + */ + public void setResultSet(boolean resultSet) { + this.resultSet = resultSet; + } + + public int getUpdateCount() { + return updateCount; + } + + public void setUpdateCount(int updateCount) { + this.updateCount = updateCount; + } + + public String getTable() { + return table; + } + + public void setTable(String table) { + this.table = table; + } + + public boolean hasMore() { + return hasMore; + } + + public void setHasMore(boolean hasMore) { + this.hasMore = hasMore; + } + + public int getMaxSize() { + return maxSize; + } + + public void setMaxSize(int maxSize) { + this.maxSize = maxSize; + } + + public boolean isError() { + return isError; + } + + public void setIsError(boolean isError) { + this.isError = isError; + } + /** + * + */ + public Object[] getRows() { + return rows.toArray(); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/TableRow.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/TableRow.java new file mode 100644 index 0000000..e263d49 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/TableRow.java @@ -0,0 +1,60 @@ +package com.quantum.sql; + +import com.quantum.model.Bookmark; +import com.quantum.model.Entity; +import com.quantum.util.StringMatrix; + +public class TableRow { + private String[] columnNames; + private Bookmark bookmark; + private String table; + private Entity entity; + private StringMatrix fullTableData; + + public TableRow(Entity entity, Bookmark bookmark, String table, StringMatrix tableData) { + this.entity = entity; + this.table = table; + // tableData will contain the first row of the tableData, for compatibility reasons with older code + // TODO: refactor the older code to allow for multiple selections + this.columnNames = tableData.getHeader(); + this.bookmark = bookmark; + this.fullTableData = tableData; + } + + public int getColumnCount() { + return columnNames.length; + } + + public String[] getColumnNames() { + return columnNames; + } + + public String getTable() { + return table; + } + + public Bookmark getBookmark() { + return this.bookmark; + } + + public Entity getEntity() { + return this.entity; + } + + public void setColumnNames(String[] columnNames) { + this.columnNames = columnNames; + } + + public String[] getTableData() { + return getTableRow(0); + } + + public String[] getTableRow(int i) { + return fullTableData.getRow(i); + } + + public StringMatrix getRowTableData() { + return fullTableData; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/MetaDataJDBCInterface.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/MetaDataJDBCInterface.java new file mode 100644 index 0000000..b754964 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/MetaDataJDBCInterface.java @@ -0,0 +1,195 @@ +/* + * Created on 8/04/2003 + * + */ +package com.quantum.sql.metadata; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; + +import com.quantum.util.StringMatrix; + +/** + * Groups functions that allow extracting data from a JDBC connection + * in the form of StringMatrix objects + * + * @author panic + * + */ +public class MetaDataJDBCInterface { + + /** + * @param con : A valid (open) connection to an JDBC database + * @param schema : Schema of the table. Must be null if not given + * @param table : Name of the table. + * @return a StringMatrix with the info of the columns' metadata, null if error + */ + public static StringMatrix getColumns(Connection con, String schema, String table) + throws SQLException { + + DatabaseMetaData meta = con.getMetaData(); + ResultSet set = null; + StringMatrix columns = null; + try { + set = meta.getColumns(null, schema, table, null); + columns = fillMatrix(set); + set.close(); + + } catch (SQLException e) { + } + if (columns == null) { + columns = new StringMatrix(); + String query = "SELECT * FROM \"" + table + "\" WHERE (1 = 0)"; //$NON-NLS-1$ //$NON-NLS-2$ + Statement stmt = con.createStatement(); + stmt.execute(query); + ResultSet rset = stmt.getResultSet(); + ResultSetMetaData rsMetaData = rset.getMetaData(); + int columnCount = rsMetaData.getColumnCount(); + String headMatrix[] = {"TABLE_CAT","TABLE_SCHEM","TABLE_NAME","COLUMN_NAME","DATA_TYPE","TYPE_NAME","COLUMN_SIZE", + "BUFFER_LENGTH","DECIMAL_DIGITS","NUM_PREC_RADIX","NULLABLE","REMARKS", + "COLUMN_DEF","SQL_DATA_TYPE","SQL_DATETIME_SUB","CHAR_OCTET_LENGTH", + "ORDINAL_POSITION","IS_NULLABLE","SCOPE_CATLOG","SCOPE_SCHEMA","SCOPE_TABLE","SOURCE_DATA_TYPE"}; + columns.addMatrixHeader(headMatrix); + for (int i = 0; i < columnCount; i++) { + columns.add(null, i); /* TABLE_CAT */ + columns.add(schema, i); /* TABLE_SCHEM */ + columns.add(table, i); /* TABLE_NAME */ + columns.add(rsMetaData.getColumnName(i+1), i); /* COLUMN_NAME */ + columns.add(String.valueOf(rsMetaData.getColumnType(i+1)), i); /* DATA_TYPE */ + columns.add(rsMetaData.getColumnTypeName(i+1), i); /* TYPE_NAME */ + columns.add(String.valueOf(rsMetaData.getPrecision(i+1)), i); /* COLUMN_SIZE */ + columns.add(null, i); /* BUFFER_LENGTH */ + columns.add(String.valueOf(rsMetaData.getScale(i+1)), i); /* DECIMAL_DIGITS */ + columns.add(null, i); /* NUM_PREC_RADIX */ + int isNullable = rsMetaData.isNullable(i+1); + columns.add(String.valueOf(isNullable), i); /* NULLABLE */ + columns.add(null, i); /* REMARKS */ + columns.add(null, i); /* COLUMN_DEF */ + columns.add(null, i); /* SQL_DATA_TYPE */ + columns.add(null, i); /* SQL_DATETIME_SUB */ + columns.add(String.valueOf(rsMetaData.getColumnDisplaySize(i+1)), i); /* CHAR_OCTET_LENGTH */ + columns.add(String.valueOf(i+1), i); /* ORDINAL_POSITION */ + columns.add(isNullable == DatabaseMetaData.columnNullable ? "YES" : "NO", i ); + columns.add(null, i); /* SCOPE_CATLOG */ + columns.add(null, i); /* SCOPE_SCHEMA */ + columns.add(null, i); /* SCOPE_TABLE */ + columns.add(null, i); /* SOURCE_DATA_TYPE */ + } + } + return columns; + } + + /** + * @param con : A valid (open) connection to an JDBC database + * @param schema : Schema of the table. Must be null if not given + * @param table : Name of the table. + * @return a StringMatrix with the info of the primary keys + */ + public static StringMatrix getPrimaryKeys(Connection con, String schema, String table) { + + StringMatrix keys = new StringMatrix(); + try { + DatabaseMetaData meta = con.getMetaData(); + ResultSet set = meta.getPrimaryKeys(null, schema, table); + keys = fillMatrix(set); + set.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + return keys; + } + + /** + * @param con : A valid (open) connection to an JDBC database + * @param schema : Schema of the table. Must be null if not given + * @param table : Name of the table. + * @param imported : Determines if the foreign keys are the imported or exported ones + * @return a StringMatrix with the info of the foreign keys + */ + public static StringMatrix getForeignKeys(Connection con, String schema, String table, boolean imported ) { + + ResultSet set = null; + StringMatrix keys = new StringMatrix(); + try { + DatabaseMetaData meta = con.getMetaData(); + if (imported){ + set = meta.getImportedKeys(null, schema, table); + } else { + set = meta.getExportedKeys(null, schema, table); + } + keys = fillMatrix(set); + set.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + return keys; + } + + /** + * @param con : A valid (open) connection to an JDBC database + * @param schema : Schema of the table. Must be null if not given + * @param table : Name of the table. + * @return a StringMatrix with the info of the indexes on that table + */ + public static StringMatrix getIndexInfo(Connection con, String schema, String table) { + + ResultSet set = null; + DatabaseMetaData meta; + StringMatrix keys = new StringMatrix(); + try { + meta = con.getMetaData(); + set = meta.getIndexInfo(null, schema, table, false, false); + keys = fillMatrix(set); + set.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + return keys; + } + + + /** + * + * @param set + * @return a filled StringMatrix with the set results + * @throws SQLException + */ + public static StringMatrix fillMatrix(ResultSet set) throws SQLException { + int columnCount = set.getMetaData().getColumnCount(); + StringMatrix keys = new StringMatrix(); + for (int i = 1; i <= columnCount; i++) { + keys.addHeader(set.getMetaData().getColumnName(i)); + } + int row = 0; + while (set.next()) { + for (int i = 1; i <= columnCount; i++) { + keys.add(set.getString(i), row); + } + row++; + } + return keys; + } + + /** + * @param con + * @param schema + * @param tableName + */ + public static StringMatrix getBestRowId(Connection con, String schema, String table) + throws SQLException { + + ResultSet set = null; + DatabaseMetaData meta = con.getMetaData(); + set = meta.getBestRowIdentifier(null, schema, table, DatabaseMetaData.bestRowSession, true); + StringMatrix keys = fillMatrix(set); + set.close(); + return keys; + + } + + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/MetaDataXMLInterface.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/MetaDataXMLInterface.java new file mode 100644 index 0000000..03cc5e4 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/MetaDataXMLInterface.java @@ -0,0 +1,191 @@ +/* + * Created on 15/04/2003 + * + */ +package com.quantum.sql.metadata; + +import java.util.Vector; + +import com.quantum.util.StringMatrix; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + + +/** + * @author panic + * Handles interface between an ObjectMetaData and XML storage. + * It can write an existing metadata object to XML and generate + * a new ObjectMetaData from existing XML. + */ +public class MetaDataXMLInterface { + + /** + * Exports an ObjectMetaData to an XML document, under a root Element + * @param metadata The ObjectMetaData to export + * @param doc A valid XML document to receive the export + * @param root The Element under which all the XML data will be written + */ + public static void metaDataToXML(ObjectMetaData metadata, Document doc, Element root) { + StringMatrix columns = metadata.getColumns(); + if (columns != null) + stringMatrixToXML(columns, doc, root, "COLUMN"); //$NON-NLS-1$ + StringMatrix primaryKeys = metadata.getPrimaryKeys(); + if (primaryKeys != null) + stringMatrixToXML(primaryKeys, doc, root, "PRIMARY_KEY_ITEM"); //$NON-NLS-1$ + StringMatrix foreignKeys = metadata.getForeignKeys(); + if (foreignKeys != null) + stringMatrixToXML(foreignKeys, doc, root, "FOREIGN_KEY_ITEM"); //$NON-NLS-1$ + StringMatrix indexInfo = metadata.getIndexInfo(); + if (indexInfo != null) + stringMatrixToXML(indexInfo, doc, root, "INDEX_ITEM"); //$NON-NLS-1$ + } + + /** + * Imports an XML element to an ObjectMetaData. The format has to be the same as extracted by + * the MetaDataToXML function. + * @param metadata The ObjectMetaData to fill up. Usually empty. + * @param root The Element having all the XML data + */ + public static void xmlToMetaData(ObjectMetaData metadata, Element root) { + StringMatrix columns = new StringMatrix(); + MetaDataXMLInterface.xmlToStringMatrix(columns, root, "COLUMN"); //$NON-NLS-1$ + metadata.setColumns(columns); + StringMatrix primaryKeys = new StringMatrix(); + MetaDataXMLInterface.xmlToStringMatrix(primaryKeys, root, "PRIMARY_KEY_ITEM"); //$NON-NLS-1$ + metadata.setPrimaryKeys(primaryKeys); + StringMatrix foreignKeys = new StringMatrix(); + MetaDataXMLInterface.xmlToStringMatrix(foreignKeys, root, "FOREIGN_KEY_ITEM"); //$NON-NLS-1$ + metadata.setForeignKeys(foreignKeys); + StringMatrix indexInfo = new StringMatrix(); + MetaDataXMLInterface.xmlToStringMatrix(indexInfo, root, "INDEX_ITEM"); //$NON-NLS-1$ + metadata.setIndexInfo(indexInfo); + } + + /** + * Adds a StringMatrix to an XML document + * @param matrix The StringMatrix to add + * @param doc The XmlDocument to which it will be added + * @param root An element of the previous document under which the info will be added + * @param sub A key under which each row of the StringMatrix will be added + */ + public static void stringMatrixToXML(StringMatrix matrix, Document doc, Element root, String sub) { + for (int i = 0; i < matrix.size(); i++) { + Element localRoot = (Element) root.appendChild(doc.createElement(sub)); + for (int j = 0; j < matrix.getNumColumns(); j++) { + String key = matrix.getHeaderColumn(j); + Element tableName = (Element) localRoot.appendChild(doc.createElement(key)); + String value = matrix.get(key, i); + if (value != null) + tableName.appendChild(doc.createTextNode(value)); + } + } + } + + /** + * Fills a StringMatrix with the data from XML, usually extracted with the StringMatrixToXML function + * @param matrix The matrix to fill up, usually empty. + * @param root The Element with all the data in XML DOM + * @param sub The String to select the Nodes which interest us. Only the selected nodes will be added + * to the StringMatrix. + */ + private static void xmlToStringMatrix(StringMatrix matrix, Element root, String sub) { + NodeList columns = root.getElementsByTagName(sub); + for (int i = 0; i < columns.getLength(); i++) { + Node column = columns.item(i); + NodeList columnList = column.getChildNodes(); + for (int j = 0; j < columnList.getLength(); j++) { + Node node = columnList.item(j); + String header = node.getNodeName(); + if (header.equals("#text")) //$NON-NLS-1$ + continue; + String value = null; + if (node != null && node.hasChildNodes()) { + Node valueNode = node.getFirstChild(); + if (valueNode instanceof Text) { + value = valueNode.getNodeValue(); + } + } + if (!matrix.contains(header)) + matrix.addHeader(header); + matrix.addAt(header, value, i); + } + } + } + /** + * Creates a new Element with a text value + * @param root + * @param key + * @param value + * @return + */ + public static Element createElementText(Element root, String key, String value){ + // get the XmlDocument for use as a factory + Document doc = root.getOwnerDocument(); + Element newElement = doc.createElement(key); + + root.appendChild(newElement); + if (value != null && value.length() > 0) + { + Text valueText = doc.createTextNode(value); + newElement.appendChild(valueText); + } + return newElement; + } + + public static String getElementText(Element root, String key){ + return getElementText(root, key, ""); + } + /** + * gets the text value from an element or a child of it + * @param root element root + * @param key key to search + * @param defValue default string value if not found + * @return + */ + public static String getElementText(Element root, String key, String defValue){ + // get the XmlDocument for use as a factory + String value = defValue; + if (root.getNodeName().equals(key)){ + value = extractText(root, defValue); + } else { + NodeList children = root.getElementsByTagName(key); + if (children.getLength() > 0) { + Element column = (Element) children.item(0); + value = extractText(column, defValue); + } + } + return value; + } + + private static String extractText(Element node, String defValue){ + String value = defValue; + if (node != null && node.hasChildNodes()) { + Node valueNode = node.getFirstChild(); + if (valueNode instanceof Text) { + value = valueNode.getNodeValue(); + } + } + return value; + } + + /** + * Gets a Vector with the String values of the keys + * that are children of 'root' and that match 'key' + * @param root + * @param key + * @return + */ + public static Vector getVectorText(Element root, String key) { + Vector result = new Vector(); + NodeList children = root.getElementsByTagName(key); + for (int i = 0; i < children.getLength(); i++) { + Element column = (Element) children.item(i); + result.add(extractText(column, "")); + } + return result; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/ObjectMetaData.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/ObjectMetaData.java new file mode 100644 index 0000000..3858253 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/metadata/ObjectMetaData.java @@ -0,0 +1,204 @@ +/* + * Created on 8/04/2003 + * + */ +package com.quantum.sql.metadata; + +import java.util.Vector; + +import com.quantum.util.StringMatrix; + + +/** + * Class to hold the Metadata of a database element + * @author panic + */ +public class ObjectMetaData { + private StringMatrix columns = new StringMatrix(); + private StringMatrix primaryKeys = new StringMatrix(); + private StringMatrix foreignKeys = new StringMatrix(); + private StringMatrix indexInfo = new StringMatrix(); + private StringMatrix bestRowId = new StringMatrix(); + + + /** + * Gives the order of the column in the primary key + * @param column + * @return the order of the column in the primary key, 0 if it's not part of it. + */ + public int getPrimaryKeyOrder(String column){ + if (primaryKeys.size() == 0) return 0; + StringMatrix keyColumns = primaryKeys.select("COLUMN_NAME", column); //$NON-NLS-1$ + if (keyColumns != null && keyColumns.size() > 0) { + String index = keyColumns.get("KEY_SEQ", 0); // We suppose there is only a primary key //$NON-NLS-1$ + if (index != null ) return Integer.parseInt(index); + } + return 0; + } + + /** + * Gives the type of the column + * @param column + * @return the type of the column using the values defined in java.sql.Types + */ + public int getColumnType(String column){ + StringMatrix selectCol = columns.select("COLUMN_NAME", column); //$NON-NLS-1$ + if (selectCol != null && selectCol.size() > 0) { + String type = selectCol.get("DATA_TYPE", 0); // It should be only one column //$NON-NLS-1$ + if (type != null ) return Integer.parseInt(type); + } + return 0; + + } + + /** + * Returns a String with the names of the columns, separated by commas + */ + public String getColumnsString() { + String result = ""; //$NON-NLS-1$ + Vector columnNames = columns.getColumn("COLUMN_NAME"); //$NON-NLS-1$ + for (int i = 0; i < columnNames.size(); i++) { + if (i > 0) result += ", "; //$NON-NLS-1$ + result += (String) columnNames.get(i); + } + return result; + } + + /** + * Returns a vector of Strings with the names of the columns + */ + public Vector getColumnNamesVector() { + Vector result = new Vector(); + Vector columnNames = columns.getColumn("COLUMN_NAME"); //$NON-NLS-1$ + for (int i = 0; i < columnNames.size(); i++) { + result.add((String) columnNames.get(i)); + } + return result; + } + + // Inmediate getters and setters + + /** + * @param matrix + */ + public void setColumns(StringMatrix matrix) { + columns = matrix; + } + /** + * @param matrix + */ + public void setForeignKeys(StringMatrix matrix) { + foreignKeys = matrix; + } + + /** + * @param matrix + */ + public void setPrimaryKeys(StringMatrix matrix) { + primaryKeys = matrix; + } + /** + * @param matrix + */ + public void setBestRowId(StringMatrix matrix) { + bestRowId = matrix; + } + + /** + * @param matrix + */ + public void setIndexInfo(StringMatrix matrix) { + indexInfo = matrix; + } + + /** + * @return + */ + public StringMatrix getColumns() { + return columns; + } + + /** + * @return + */ + public StringMatrix getForeignKeys() { + return foreignKeys; + } + + /** + * @return + */ + public StringMatrix getPrimaryKeys() { + return primaryKeys; + } + + + /** + * @return + */ + public StringMatrix getIndexInfo() { + return indexInfo; + } + /** + * @return + */ + public StringMatrix getBestRowId() { + return bestRowId; + } + + + /** + * @param column + */ + public void dropColumn(String columnName) { + columns.dropMatching("COLUMN_NAME", columnName); //$NON-NLS-1$ + } + + // Common Object interface + + /* (non-Javadoc) + * @see java.lang.Object#clone() + */ + public Object clone() { + ObjectMetaData result = new ObjectMetaData(); + result.columns = (StringMatrix) columns.clone(); + result.primaryKeys = (StringMatrix) primaryKeys.clone(); + result.indexInfo = (StringMatrix) indexInfo.clone(); + result.foreignKeys = (StringMatrix) foreignKeys.clone(); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (!(obj instanceof ObjectMetaData)) return false; + ObjectMetaData obMd = (ObjectMetaData) obj; + return (columns.equals(obMd.columns) && + primaryKeys.equals(obMd.primaryKeys) && + indexInfo.equals(obMd.indexInfo) && + foreignKeys.equals(obMd.foreignKeys) ); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return ( columns.toString() + + foreignKeys.toString() + + indexInfo.toString() + + primaryKeys.toString()); + } + + public String getQualifiedTableName(){ + if (columns.size() < 1) return ""; + String result = columns.get("TABLE_NAME", 0); + String schema = columns.get("TABLE_SCHEM", 0); + if (schema != null && schema.length() > 0) + result = schema + "." + result; + return result; + + } + + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/SQLLexx.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/SQLLexx.java new file mode 100644 index 0000000..e901266 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/SQLLexx.java @@ -0,0 +1,166 @@ +package com.quantum.sql.parser; + +import java.util.Vector; + +public class SQLLexx { + private static String endline = ";"; //$NON-NLS-1$ + private static String dash = "-"; //$NON-NLS-1$ + private static String group = "/"; //$NON-NLS-1$ + /** + * Parses a SQL text into tokens. + * @param text + * @return a vector of Token objects. + */ + public static Vector parse(String text) { + Vector tokens = new Vector(); + StringPointer p = new StringPointer(text); + try { + while (!p.isDone()) { + int offset = p.getOffset(); + char c = p.getNext(); + // Adds END_OF_LINE token + if (c == '\n') { + tokens.addElement(new Token(Token.END_OF_LINE, "\n", offset, offset + 1)); + } + // Adds WHITESPACE token; + else if (Character.isWhitespace(c)) { + StringBuffer value = new StringBuffer(); + while (Character.isWhitespace(c) && !p.isDone()) { + value.append(c); + c = p.getNext(); + } + // done because of is done + if (Character.isWhitespace(c)) { + value.append(c); + } else if (!p.isDone()){ + p.back(); + } + tokens.addElement(new Token(Token.WHITESPACE, value.toString(), offset, offset + value.length())); + // Adds IDENTIFIER token (can be reserved SQL word or not); + } else if (Character.isLetter(c) || c == '_' || c == '$') { + StringBuffer value = new StringBuffer(); + while ((Character.isLetterOrDigit(c) || c == '_' || c == '$') && !p.isDone()) { + value.append(c); + c = p.getNext(); + } + if ((Character.isLetterOrDigit(c) || c == '_')) { + value.append(c); + } else if (!p.isDone()){ + p.back(); + } + tokens.addElement(new Token(Token.IDENTIFIER, value.toString(), offset, offset + value.length())); + // Adds LITERAL token; + } else if (c == '\'') { + StringBuffer value = new StringBuffer(); + value.append(c); + if (!p.isDone()) { + c = p.getNext(); + while (c != '\'' && c != '\n' && !p.isDone()) { + value.append(c); + c = p.getNext(); + } + if (c == '\'' || p.isDone()) { + value.append(c); + } else if (!p.isDone()){ + p.back(); + } + } + tokens.addElement(new Token(Token.LITERAL, value.toString(), offset, offset + value.length())); + // Adds COMMENT token (or SYMBOL (dash) if only one dash); + } else if (c == '-') { + p.mark(); + if (p.isDone()) { + tokens.addElement(new Token(Token.SYMBOL, dash, offset, offset + 1)); + } else { + char next = p.getNext(); + if (next == '-') { + StringBuffer value = new StringBuffer("--"); //$NON-NLS-1$ + if (!p.isDone()) { + c = p.getNext(); + while (c != '\n' && !p.isDone()) { + value.append(c); + c = p.getNext(); + } + if (p.isDone()) { + value.append(c); + } else { + p.back(); + } + } + tokens.addElement(new Token(Token.COMMENT, value.toString(), offset, offset + value.length())); + } else { + tokens.addElement(new Token(Token.SYMBOL, dash, offset, offset + 1)); + p.reset(); + } + } + // Adds SEPARATOR token (;), considers the rest of the line as COMMENT token; + } else if (c == ';') { + tokens.addElement(new Token(Token.SEPARATOR, endline, offset, offset + 1)); + StringBuffer value = new StringBuffer(); + if (!p.isDone()) { + c = p.getNext(); + while (c != '\n' && !p.isDone()) { + value.append(c); + c = p.getNext(); + } + if (p.isDone()) { + value.append(c); + } else { + p.back(); + } + // We add to the offset so as to skip the initial ';' + offset++; + tokens.addElement(new Token(Token.COMMENT, value.toString(), offset, offset + value.length())); + } + // Adds NUMERIC token; + } else if (Character.isDigit(c)) { + StringBuffer value = new StringBuffer(); + while ((Character.isDigit(c) || c == '.') && !p.isDone()) { + value.append(c); + c = p.getNext(); + } + if ((Character.isDigit(c) || c == '.')) { + value.append(c); + } else { + p.back(); + } + tokens.addElement(new Token(Token.NUMERIC, value.toString(), offset, offset + value.length())); + // Adds COMMENT token (or GROUP (slash) if only one slash); + } else if (c == '/') { + p.mark(); + // If we have '/*', it's a comment till '*/' found or eof + if (p.peek() == '*') { + StringBuffer value = new StringBuffer(); + c = p.getNext(); + value.append('/'); + while (!( c == '*' && p.peek() == '/' ) && !p.isDone()) { + value.append(c); + c = p.getNext(); + } + if (!p.isDone()){ + value.append(c); + c = p.getNext(); + value.append(c); + } + tokens.addElement(new Token(Token.COMMENT, value.toString(), offset, offset + value.length())); + } else { + // It's not '/*' , so it's a group token + tokens.addElement(new Token(Token.GROUP, group, offset, offset + 1)); + p.reset(); + } + // Adds SYMBOL token; + } else { + tokens.addElement(new Token(Token.SYMBOL, new String(new char[] {c}), offset, offset + 1)); + } + } + } catch (RuntimeException e) { + e.printStackTrace(); + } + +// System.out.println("-------------------"); +// for (int i = 0; i < tokens.size(); i++) { +// System.out.println((Token) tokens.elementAt(i)); +// } + return tokens; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/StringPointer.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/StringPointer.java new file mode 100644 index 0000000..846da29 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/StringPointer.java @@ -0,0 +1,62 @@ +package com.quantum.sql.parser; + +public class StringPointer { + char[] value; + int offset = 0; + int mark = 0; + public StringPointer(String s) { + value = s.toCharArray(); + } + /** + * Returns the next character. Will return 0 if at end of file, but that's not + * checkeable because it can be a valid character. You should check with isDone(); + * @return + */ + public char getNext() { + char retVal = (offset < value.length) ? value[offset] : 0; + offset++; + return retVal; + } + /** + * Returns the next character, without advancing the pointer. + * Will return 0 if at end of file, but that's not + * checkeable because it can be a valid character. You should check with isDone(); + * @return + */ + public char peek() { + char retVal = (offset < value.length) ? value[offset] : 0; + return retVal; + } + /** + * Marks a poing of the stream to come back later (using reset()); + */ + public void mark() { + mark = offset; + } + /** + * Returns to a previously marked (with mark()) place. + */ + public void reset() { + offset = mark; + } + /** + * Sets the pointer back a character, in fact 'pop'ing it back to the stream; + */ + public void back() { + if (offset > 0) offset--; + } + + public int getOffset() { + return offset; + } + /** + * @return true if the stream is at an end + */ + public boolean isDone() { + return offset >= value.length; + } + + public int getLength() { + return value.length; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/Token.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/Token.java new file mode 100644 index 0000000..438ce5c --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/sql/parser/Token.java @@ -0,0 +1,57 @@ +package com.quantum.sql.parser; + +public class Token { + public static final char SEPARATOR = 'S'; + public static final char SYMBOL = 'Y'; + public static final char LITERAL = 'L'; + public static final char IDENTIFIER = 'I'; + public static final char COMMENT = 'C'; + public static final char WHITESPACE = 'W'; + public static final char NUMERIC = 'N'; + public static final char GROUP = 'G'; + public static final char END_OF_LINE = 'E'; + private char type; + private int start; + private int end; + private String value; + public Token(char type, String value, int start, int end) { + this.type = type; + this.value = value; + this.start = start; + this.end = end; + } + public int getEnd() { + return end; + } + + public int getStart() { + return start; + } + + public int getType() { + return type; + } + + public String getValue() { + return value; + } + + public void setEnd(int end) { + this.end = end; + } + + public void setStart(int start) { + this.start = start; + } + + public void setType(char type) { + this.type = type; + } + + public void setValue(String value) { + this.value = value; + } + public String toString() { + return type + " ->" + value + "<- [" + start + ", " + end + "]"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/BookmarkSelectionDialog.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/BookmarkSelectionDialog.java new file mode 100644 index 0000000..6707429 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/BookmarkSelectionDialog.java @@ -0,0 +1,110 @@ +package com.quantum.ui.dialog; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +import com.quantum.Messages; +import com.quantum.model.Bookmark; +import com.quantum.model.BookmarkCollection; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; + +/** + * @author BC + */ +public class BookmarkSelectionDialog extends Dialog { + + private List list; + private String selection = null; + private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); + + /** + * @param parentShell + */ + public BookmarkSelectionDialog(Shell parentShell) { + super(parentShell); + int style = getShellStyle() | SWT.TITLE; + setShellStyle(style); + } + + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText(Messages.getString("BookmarkSelectionDialog.title")); + } + + /** + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + protected Control createDialogArea(Composite parent) { + + Composite composite = new Composite(parent, 0); + GridLayout layout = new GridLayout(); + composite.setLayout(layout); + layout.numColumns = 1; + layout.verticalSpacing = 1; + + Label label = new Label(composite, SWT.NULL); + label.setText(Messages.getString("BookmarkSelectionDialog.text")); + + this.list = new List(composite, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL); + Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks(); + + for (int i = 0, length = (bookmarks == null) ? 0 : bookmarks.length; i < length; i++) { + this.list.add(bookmarks[i].getName()); + if (i == 0) { + this.list.select(i); + setSelection(bookmarks[i].getName()); + } + } + + final List list = this.list; + list.addListener(SWT.Selection, new Listener() { + public void handleEvent (Event event) { + String[] selections = list.getSelection(); + if (selections != null && selections.length > 0) { + BookmarkSelectionDialog.this.setSelection(selections[0]); + } + } + }); + + GridData full = new GridData(); + full.horizontalAlignment = GridData.FILL; + full.verticalAlignment = GridData.FILL; + full.heightHint = convertHeightInCharsToPixels(3); + this.list.setLayoutData(full); + + return composite; + } + + /** + * @param listener + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + this.propertyChangeSupport.addPropertyChangeListener(listener); + } + + /** + * @param listener + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + this.propertyChangeSupport.removePropertyChangeListener(listener); + } + + private void setSelection(String selection) { + String original = this.selection; + if (this.selection == null || !this.selection.equals(selection)) { + this.selection = selection; + this.propertyChangeSupport.firePropertyChange("selection", original, this.selection); + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/ExceptionDisplayDialog.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/ExceptionDisplayDialog.java new file mode 100644 index 0000000..7917a07 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/ExceptionDisplayDialog.java @@ -0,0 +1,281 @@ +package com.quantum.ui.dialog; + +import com.quantum.Messages; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +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.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * @author BC + */ +public class ExceptionDisplayDialog extends Dialog { + + private Control detailsArea; + private Throwable throwable; + private String message; + + /** + * @param parentShell + */ + public ExceptionDisplayDialog(Shell parentShell, Throwable throwable) { + super(parentShell); + this.throwable = throwable; + } + + /** + * The Details button. + */ + private Button detailsButton; + + /** + * The title of the dialog. + */ + private String title; + + /** + * Indicates whether the error details viewer is currently created. + */ + private boolean detailsShown = false; + + /** + * Creates an error dialog. + * Note that the dialog will have no visual representation (no widgets) + * until it is told to open. + *

+ * Normally one should use openError to create and open one of these. + * This constructor is useful only if the error object being displayed contains child + * items and you need to specify a mask which will be used to filter the + * displaying of these children. + *

+ * + * @param parentShell the shell under which to create this dialog + * @param dialogTitle the title to use for this dialog, + * or null to indicate that the default title should be used + * @param message the message to show in this dialog, + * or null to indicate that the error's message should be shown + * as the primary message + * @param status the error to show to the user + * @param displayMask the mask to use to filter the displaying of child items, + * as per IStatus.matches + * @see org.eclipse.core.runtime.IStatus#matches(int) + */ + public ExceptionDisplayDialog( + Shell parentShell, + String dialogTitle, + String message, + Throwable throwable) { + super(parentShell); + + this.title = dialogTitle; + this.message = message; + this.throwable = throwable; + + setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL); + } + + /* (non-Javadoc) + * Method declared on Dialog. + * Handles the pressing of the Ok or Details button in this dialog. + * If the Ok button was pressed then close this dialog. If the Details + * button was pressed then toggle the displaying of the error details area. + * Note that the Details button will only be visible if the error being + * displayed specifies child details. + */ + protected void buttonPressed(int id) { + if (id == IDialogConstants.DETAILS_ID) { + // was the details button pressed? + toggleDetailsArea(); + } else { + super.buttonPressed(id); + } + } + /* (non-Javadoc) + * Method declared in Window. + */ + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText(title); + } + /* (non-Javadoc) + * Method declared on Dialog. + */ + protected void createButtonsForButtonBar(Composite parent) { + // create OK and Details buttons + createButton( + parent, + IDialogConstants.OK_ID, + IDialogConstants.OK_LABEL, + true); + this.detailsButton = + createButton( + parent, + IDialogConstants.DETAILS_ID, + IDialogConstants.SHOW_DETAILS_LABEL, + false); + } + + protected Control createDialogArea(Composite parent) { + + // create a composite with standard margins and spacing + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = + convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + layout.marginWidth = + convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + layout.verticalSpacing = + convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + layout.horizontalSpacing = + convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + composite.setLayout(layout); + GridData childData = new GridData(GridData.FILL_BOTH); + childData.horizontalSpan = 2; + composite.setLayoutData(childData); + composite.setFont(parent.getFont()); + + Label label = new Label(composite, 0); + label.setText(this.message); + label.setFont(parent.getFont()); + + + GridData full = new GridData(); + full.horizontalAlignment = GridData.FILL; + full.verticalAlignment = GridData.FILL; + full.heightHint = convertHeightInCharsToPixels(3); + full.widthHint = convertWidthInCharsToPixels(60); + label.setLayoutData(full); + + return composite; + + } + + /** + * Create the expandable details arae. + * + * @param parent the parent composite + * @return the details text control + */ + protected Control createDetailsArea(Composite parent) { + + // create a composite with standard margins and spacing + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = + convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + layout.marginWidth = + convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + layout.verticalSpacing = + convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + layout.horizontalSpacing = + convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + composite.setLayout(layout); + GridData childData = new GridData(GridData.FILL_BOTH); + childData.horizontalSpan = 2; + composite.setLayoutData(childData); + composite.setFont(parent.getFont()); + + Label label = new Label(composite, 0); + label.setText(Messages.getString("ExceptionDisplayDialog.stackTrace")); + label.setFont(parent.getFont()); + + GridData full = new GridData(); + full.horizontalAlignment = GridData.FILL; + full.verticalAlignment = GridData.FILL; + full.heightHint = convertHeightInCharsToPixels(3); + full.widthHint = convertWidthInCharsToPixels(60); + label.setLayoutData(full); + + Text text = + new Text( + composite, + SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI); + + text.setText(this.throwable.getMessage()); + + GridData data = + new GridData( + GridData.HORIZONTAL_ALIGN_FILL + | GridData.GRAB_HORIZONTAL + | GridData.VERTICAL_ALIGN_FILL + | GridData.GRAB_VERTICAL); + data.heightHint = convertHeightInCharsToPixels(8); + text.setLayoutData(data); + text.setFont(parent.getFont()); + + this.detailsShown = true; + return composite; + } + /** + * Opens an error dialog to display the given error. Use this method if the + * error object being displayed contains child items and you wish to + * specify a mask which will be used to filter the displaying of these + * children. The error dialog will only be displayed if there is at + * least one child status matching the mask. + * + * @param parentShell - + * the parent shell of the dialog, or null if none + * @param dialogTitle the title to use for this dialog, + * or null to indicate that the default title should be used + * @param message the message to show in this dialog, + * or null to indicate that the error's message should be shown + * as the primary message + * as per IStatus.matches + * @return the code of the button that was pressed that resulted in this dialog + * closing. This will be Dialog.OK if the OK button was + * pressed, or Dialog.CANCEL if this dialog's close window + * decoration or the ESC key was used. + * @see org.eclipse.core.runtime.IStatus#matches(int) + */ + public static int openError( + Shell parentShell, + String title, + String message, + Throwable throwable) { + + if (title == null) { + title = Messages.getString(ExceptionDisplayDialog.class.getName() + + "." + throwable.getClass().getName() + ".title"); + } + if (message == null) { + message = Messages.getString(ExceptionDisplayDialog.class.getName() + + "." + throwable.getClass().getName() + ".message"); + } + ExceptionDisplayDialog dialog = + new ExceptionDisplayDialog(parentShell, title, message, throwable); + return dialog.open(); + } + + /** + * Toggles the unfolding of the details area. This is triggered by + * the user pressing the details button. + */ + private void toggleDetailsArea() { + Point windowSize = getShell().getSize(); + Point oldSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); + + if (this.detailsShown) { + this.detailsArea.dispose(); + this.detailsShown = false; + detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL); + } else { + this.detailsArea = createDetailsArea((Composite) getContents()); + detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL); + } + + Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); + + getShell().setSize( + new Point(windowSize.x, windowSize.y + (newSize.y - oldSize.y))); + + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/PasswordDialog.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/PasswordDialog.java new file mode 100644 index 0000000..8e5d5bf --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/ui/dialog/PasswordDialog.java @@ -0,0 +1,122 @@ +/* + * Created on 28-ago-2003 + * + */ +package com.quantum.ui.dialog; + +import com.quantum.Messages; +import com.quantum.model.PasswordFinder; + +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * @author panic + * + */ +public class PasswordDialog extends InputDialog { + + static class PasswordFinderImpl implements PasswordFinder { + private boolean passwordMeantToBeSaved = false; + private String password; + private boolean prompted = false; + private Shell shell; + + PasswordFinderImpl(Shell shell) { + this.shell = shell; + } + + protected void prompt() { + PasswordDialog dialog = + new PasswordDialog( + this.shell, + Messages.getString("MultiSQLServer.PasswordNotProvided"), + Messages.getString("MultiSQLServer.Enter_Password"), + "", + this); + dialog.open(); + this.prompted = true; + } + + /** + * @return + */ + public String getPassword() { + if (!this.prompted) { + prompt(); + } + return password; + } + + /** + * @return + */ + public boolean isPasswordMeantToBeSaved() { + if (!this.prompted) { + prompt(); + } + return passwordMeantToBeSaved; + } + + /** + * @param string + */ + public void setPassword(String string) { + password = string; + } + + /** + * @param b + */ + public void setPasswordMeantToBeSaved(boolean b) { + passwordMeantToBeSaved = b; + } + + } + + private PasswordFinderImpl passwordFinderImpl; + + /** + * @param parentShell + * @param dialogTitle + * @param dialogMessage + * @param initialValue + * @param validator + */ + protected PasswordDialog( + Shell parentShell, + String dialogTitle, + String dialogMessage, + String initialValue, + PasswordFinderImpl passwordFinderImpl) { + super(parentShell, dialogTitle, dialogMessage, initialValue, null); + this.passwordFinderImpl = passwordFinderImpl; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + protected Control createDialogArea(Composite parent) { + + Control control = super.createDialogArea(parent); + Text text = getText(); + text.setEchoChar('*'); + return control; + } + + public static PasswordFinder createPasswordFinder(Shell parentShell) { + PasswordFinderImpl passwordFinder = new PasswordFinderImpl(parentShell); + return passwordFinder; + } + /** + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + */ + protected void okPressed() { + this.passwordFinderImpl.setPassword(getText().getText()); + super.okPressed(); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/NthLevelConverter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/NthLevelConverter.java new file mode 100644 index 0000000..09352f0 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/NthLevelConverter.java @@ -0,0 +1,145 @@ +/* + * Created on 11/08/2003 + * + */ +package com.quantum.util; + +import java.util.Iterator; +import java.util.Vector; + +import com.quantum.QuantumPlugin; + +import org.eclipse.jface.preference.IPreferenceStore; + +/** + * Class to clasify two levels of strings. It's called Nth Level but in fact it has only two levels :o) + * @author panic + * + */ +public class NthLevelConverter { + private final int DEFAULT_COLUMNS = 10; + private final int DEFAULT_INCREMENT = 10; + + private Vector upper = new Vector(DEFAULT_COLUMNS,DEFAULT_INCREMENT); + + public void add(String id, String parentId, int level) { + OneLevelConverter upperLine = new OneLevelConverter(id); + if (level == 1) { // If it's an upper leaf + if (!upper.contains(upperLine)) + this.upper.add(upperLine); + } + else if (level == 0) { // It's a lower leaf + if (parentId == null) return; // No parent, what shall we do. + OneLevelConverter upperFinder = new OneLevelConverter(parentId); + // Search if its parent is already present in the upper level + int ind = upper.indexOf(upperFinder); + // If not, addIt and find its index + if (ind < 0) { + this.upper.add(upperFinder); + ind = upper.indexOf(upperFinder); + } + OneLevelConverter upperItem = (OneLevelConverter) upper.get(ind); + // If it has no children, we create a new Vector for the children + if (upperItem.getLower() == null) + upperItem.setLower(new Vector(DEFAULT_COLUMNS,DEFAULT_INCREMENT)); + Vector children = upperItem.getLower(); + // Is the item already present in the children of its parent? + int indChildren = children.indexOf(id); + // If it's not, we add it + if (indChildren < 0) { + OneLevelConverter leaf = new OneLevelConverter(id); + children.add(leaf); + } + } + + } + + + /** + * @return + */ + public Vector getUpper() { + return upper; + } + + public Vector getLevel(String id, int level){ + if (level == 1) + return upper; + else if (level == 0){ + if (id == null) return null; + OneLevelConverter upperFinder = new OneLevelConverter(id); + int ind = upper.indexOf(upperFinder); + if (ind < 0) + return null; + else { + OneLevelConverter upperItem = (OneLevelConverter) upper.get(ind); + return upperItem.getLower(); + } + } + return null; + } + + public void convert(String ind){ + IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore(); + + String tableItem = QuantumUtil.trasposeEscape(store.getString("customCopyTableItem" + ind)); + String tableSeparator = QuantumUtil.trasposeEscape(store.getString("customCopyTableSeparator" + ind)); + String columnItem = QuantumUtil.trasposeEscape(store.getString("customCopyColumnItem" + ind)); + String columnSeparator = QuantumUtil.trasposeEscape(store.getString("customCopyColumnSeparator" + ind)); + + for (Iterator iter = upper.iterator(); iter.hasNext();) { + OneLevelConverter oneLevel = (OneLevelConverter) iter.next(); + String upperId = oneLevel.getId(); + Vector lower = oneLevel.getLower(); + if (lower != null) { + for (Iterator iterator = lower.iterator(); iterator.hasNext();) { + OneLevelConverter element = (OneLevelConverter) iterator.next(); + String convLeaf = columnItem + (iterator.hasNext() ? columnSeparator : ""); + + convLeaf = StringUtil.substituteString(convLeaf, "${schema}", QuantumUtil.getSchemaName(upperId)); + convLeaf = StringUtil.substituteString(convLeaf, "${qualified}", upperId); + convLeaf = StringUtil.substituteString(convLeaf, "${table}", QuantumUtil.getTableName(upperId)); + convLeaf = StringUtil.substituteString(convLeaf, "${column}", element.getId()); + + element.setResult(convLeaf); + } + } + // We have all the leafs converted, we calculate the parent conversion + String convUpper = tableItem + (iter.hasNext() ? tableSeparator : ""); + convUpper = StringUtil.substituteString(convUpper, "${schema}", QuantumUtil.getSchemaName(upperId)); + convUpper = StringUtil.substituteString(convUpper, "${qualified}", upperId); + convUpper = StringUtil.substituteString(convUpper, "${table}", QuantumUtil.getTableName(upperId)); + convUpper = StringUtil.substituteString(convUpper, "${column_list}", getColumnList(oneLevel)); + + oneLevel.setResult(convUpper); + } + } + + + /** + * Calculates the list of columns for an upper level converter. Has to be already converted. + * @param oneLevel + * @return + */ + private String getColumnList(OneLevelConverter oneLevel) { + + String result = ""; + Vector lower = oneLevel.getLower(); + if (lower != null) { + for (Iterator iterator = lower.iterator(); iterator.hasNext();) { + OneLevelConverter element = (OneLevelConverter) iterator.next(); + result += element.getResult(); + } + } + return result; + } + + public String getTableList() { + String result = ""; + for (Iterator iter = upper.iterator(); iter.hasNext();) { + OneLevelConverter oneLevel = (OneLevelConverter) iter.next(); + result += oneLevel.getResult(); + } + return result; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/OneLevelConverter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/OneLevelConverter.java new file mode 100644 index 0000000..8763cd5 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/OneLevelConverter.java @@ -0,0 +1,77 @@ +/* + * Created on 11/08/2003 + * + */ +package com.quantum.util; + +import java.util.Vector; + +/** + * "record" class that holds an identifier and the resulting + * string. This string comes from applying rules to the identifier + * Also, can have a vector of lower-level classifiers. + * + * @author panic + * + */ +public class OneLevelConverter { + private String id = ""; + private String result = ""; + private Vector lower = null; + + OneLevelConverter(String id) { + this.id = id; + } + + // Getters and setters + /** + * @return + */ + public String getId() { + return id; + } + + /** + * @return + */ + public Vector getLower() { + return lower; + } + + /** + * @return + */ + public String getResult() { + return result; + } + + /** + * @param string + */ + public void setId(String string) { + id = string; + } + + /** + * @param vector + */ + public void setLower(Vector vector) { + lower = vector; + } + + /** + * @param string + */ + public void setResult(String string) { + result = string; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (!(obj instanceof OneLevelConverter)) return false; + return this.id.equals(((OneLevelConverter)obj).id); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/QuantumUtil.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/QuantumUtil.java new file mode 100644 index 0000000..c789923 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/QuantumUtil.java @@ -0,0 +1,47 @@ +/* + * Created on 24/08/2003 + * + */ +package com.quantum.util; + +import java.util.StringTokenizer; + +/** + * @author panic + * + */ +public class QuantumUtil { + /** + * Gets the first string in a string with the structure XXXX.XXXX + * @param qualifiedName + * @return The schema name if present, else an empty string ("") + */ + public static String getSchemaName(String qualifiedName) { + StringTokenizer st = new StringTokenizer(qualifiedName, "."); //$NON-NLS-1$ + if (st.countTokens() > 1) { + return st.nextToken(); + } else + return ""; + } + + /** + * Gets the second string in a string with the structure XXXX.XXXX + * @param qualifiedName + * @return The table name if present, else the received parameter + */ + public static String getTableName(String qualifiedName) { + StringTokenizer st = new StringTokenizer(qualifiedName, "."); //$NON-NLS-1$ + if (st.countTokens() > 1) { + st.nextToken(); + return st.nextToken(); + } else + return qualifiedName; + } + + public static String trasposeEscape(String untrans){ + String trasposed = StringUtil.substituteString(untrans, "\\n", "\n"); + trasposed = StringUtil.substituteString(trasposed, "\\t", "\t"); + + return trasposed; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/StringMatrix.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/StringMatrix.java new file mode 100644 index 0000000..f87f14d --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/StringMatrix.java @@ -0,0 +1,352 @@ +/* + * Created on 8/04/2003 + * + */ +package com.quantum.util; + +import java.util.Vector; + +/** + * @author jparrai + * Generic class to hold a Matrix of Strings, that is a Vector of Vectors of Strings. + * The first Vector "line" is supposed to have headers to the values of the rest. + * Those headers will always be case insensitive + */ +public class StringMatrix { + private final int DEFAULT_COLUMNS = 10; + private final int DEFAULT_ROWS = 10; + private final int DEFAULT_INCREMENT = 10; + + private Vector header = new Vector(DEFAULT_COLUMNS,DEFAULT_INCREMENT); + private Vector matrix = new Vector(DEFAULT_ROWS,DEFAULT_INCREMENT); + + /** + * Adds a String to the end of the header keys + * @param header : The string to be added + */ + public void addHeader(String header) { + this.header.add(header); + } + /** + * Adds a whole vector to the header + * @param header + */ + private void addVectorHeader(Vector header){ + this.header.addAll(header); + for (int i = 0; i < this.header.size(); i++) { + String element = (String) this.header.get(i); + this.header.setElementAt(element, i); + } + } + /** + * Adds a whole matrix to the header + * @param header + */ + public void addMatrixHeader(String header[]){ + for (int i = 0; i < header.length; i++) { + String element = (String) header[i]; + this.header.add(element); + } + } + /** + * Adds a String to the end of the row indicated + * @param value : The string to be added + * @param row : The row to + */ + public void add(String value, int row) { + grow(row); + Vector rowVector = (Vector) matrix.get(row); + rowVector.add(value); + } + /** + * Adds a StringMatrix to the end of the row indicated + * @param value : The string to be added + * @param row : The row to + */ + public void add(StringMatrix value) { + int row = matrix.size(); + for (int i = 0; i < value.size(); i++){ + grow(row); + for (int j = 0; j < value.getNumColumns(); j++){ + String header = value.getHeaderColumn(j); + addAt(header, value.get(header,i), row); + } + row++; + } + Vector rowVector = (Vector) matrix.get(row); + rowVector.add(value); + } + + /** + * Converts the StringMatrix into a copy of the given + * @param origin - The StringMatrix to be copied + */ + public void copy(StringMatrix origin) { + clear(); + add(origin); + } + + /** + * Clears (emtpies) the StringMatrix + */ + public void clear(){ + header.clear(); + matrix.clear(); + } + /** + * Adds a String to the row indicated, to the column that matches the key + * @param value : The string to be added + * @param row : The row to + */ + public void addAt(String key, String value, int row) { + grow(row); + Vector rowVector = (Vector) matrix.get(row); + int ind = header.indexOf(key); + if (ind < 0) return; + if (rowVector.size() < ind+1) rowVector.setSize(ind); + rowVector.add(ind, value); + } + /** + * Adds a whole vector to the end of the row indicated + * @param value : The vector to be added + * @param row : The row to + */ + private void addVector(Vector value, int row){ + grow(row); + Vector rowVector = (Vector) matrix.get(row); + rowVector.addAll(value); + } + + /** + * Tells if you have that particular key in your StringMatrix + * @param key + * @return + */ + public boolean contains(String key){ + return (findKey(key) >= 0); + } + /** + * Gets a String value from the row indicated, from the column that matches the key + * @param key + * @param row + * @return + */ + public String get(String key, int row){ + if (matrix.size() <= row) return null; + int col = findKey(key); + if (col < 0) return null; + Vector rowVector = (Vector) matrix.get(row); + if (rowVector == null) return null; + return (String) rowVector.get(col); + } + /** + * Finds the key in the header + * @param key + * @return + */ + private int findKey(String key) { + for (int i = 0; i < header.size(); i++) { + String element = (String) header.get(i); + if (element.equalsIgnoreCase(key)) return i; + } + return -1; + } + /** + * @param key: selects the column + * @return a Vector with all the values in the selected column; null if empty + */ + public Vector getColumn(String key){ + if (size() < 1 ) return null; + Vector result = new Vector(size(),1); + for (int i = 0; i < size(); i++){ + result.add(get(key, i)); + } + return result; + } + /** + * @param key: selects the column + * @return a Vector with all the values in the selected column, dropping duplicates; null if empty + */ + public Vector getUniqueColumn(String key){ + if (size() < 1 ) return null; + Vector result = new Vector(size(),1); + for (int i = 0; i < size(); i++){ + if (!result.contains(get(key, i))) result.add(get(key, i)); + } + return result; + } + /** + * @param key: selects the column + * @return a Vector of Integers with all the indexes of the rows + * matching the selected column, dropping duplicates; null if empty + */ + public Vector getIndexes(String key, String value){ + Vector result = new Vector(); + for (int i = 0; i < size(); i++){ + if (get(key, i).equals(value)) + result.add(new Integer(i)); + } + return result; + } + /** + * Deletes all the rows that matches the value for the key + * @param key: selects the column + */ + public void dropMatching(String key, String value){ + for (int i = 0; i < size(); i++){ + if (get(key, i).equals(value)) deleteRow(i); + } + } + /** + * Returns a StringMatrix with all the complete rows that match the key - value pair + * @param key The column key + * @param value The value to match + * @return a StringMatrix with only the rows where the key equals the value + */ + public StringMatrix select(String key, String value){ + StringMatrix result = new StringMatrix(); + result.addVectorHeader(header); + int j = 0; + for (int i = 0; i < size(); i++){ + if (get(key, i).equals(value)) { + result.addVector((Vector)matrix.get(i), j); + j++; + } + } + return result; + } + + // Private functions + /** + * Grows the StringMatrix till it's able to hold "row" rows. + * @param row : The number of rows that must hold + */ + private void grow(int row) { + if (matrix.size() <= row) + for (int i = matrix.size(); i <= row; i++) { + matrix.add(new Vector(header.size(), 1)); + } + } + /** + * Gets a String value from the row indicated , from the column number + * @param col : 0-index column + * @param row : 0-index column + * @return + */ + private String get(int col, int row){ + if (col < 0 || row < 0) return null; + Vector rowVector = (Vector) matrix.get(row); + if (rowVector == null) return null; + return (String) rowVector.get(col); + } + + // Generic interfaces + /** + * @param i + * @return : a StringMatrix with only one row, the selected by i + */ + public StringMatrix rowMatrix(int i){ + StringMatrix result = new StringMatrix(); + result.addVectorHeader(header); + result.addVector((Vector)matrix.get(i),0); + return result; + } + + /** + * Resturns a String[] with the selected row + * @param i The index of the row + * @return + */ + public String[] getRow(int i) { + if (i < matrix.size()) { + String[] result = new String[header.size()]; + Vector resVector = (Vector)matrix.get(i); + resVector.toArray(result); + return result; + } + return null; + + } + + + /** + * @return the number of rows + */ + public int size() { + return matrix.size(); + } + public int getNumColumns() { + return header.size(); + } + public String getHeaderColumn(int i){ + return (String) header.get(i); + } + public void deleteRow(int i){ + matrix.remove(i); + } + + + // Common Object interface + /* (non-Javadoc) + * @see java.lang.Object#clone() + */ + public Object clone() { + // Deep clone + StringMatrix matrix = new StringMatrix(); + matrix.copy(this); + return matrix; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + String result = ""; + for (int j = 0; j < header.size(); j++){ + result += (String) header.get(j); + result += "\t"; + } + result += "\n"; + // Write the lines + for (int i = 0; i < matrix.size(); i++){ + for (int j = 0; j < header.size(); j++){ + result += get(j,i); + result += "\t"; + } + result += "\n"; + } + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (!(obj instanceof StringMatrix)) return false; + StringMatrix sm = (StringMatrix) obj; + if (!header.equals(sm.header)) return false; + if (matrix.size() != sm.matrix.size()) return false; + for (int i = 0; i < matrix.size(); i++){ + Vector row = (Vector) matrix.get(i); + Vector smRow = (Vector) sm.matrix.get(i); + if (!(row.equals(smRow))) return false; + } + return true; + } + + /** + * @return + */ + public Vector getMatrix() { + return matrix; + } + /** + * @return + */ + public String[] getHeader() { + String[] result = new String[header.size()]; + header.toArray(result); + return result; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/StringUtil.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/StringUtil.java new file mode 100644 index 0000000..3ec3d3d --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/StringUtil.java @@ -0,0 +1,33 @@ +/* Created on Jan 19, 2004 */ +package com.quantum.util; + +import java.util.Arrays; + +/** + * @author holmesbc + */ +public class StringUtil { + + public static String substituteString(String original, String placeHolder, String replacementValue) { + StringBuffer buffer = new StringBuffer(); + char[] originalChars = original == null ? new char[0] : original.toCharArray(); + char[] placeHolderChars = placeHolder.toCharArray(); + char[] placeHolderComparisonArray = new char[placeHolderChars.length]; + + for (int i = 0, length = originalChars.length; i < length; i++) { + if (i <= length - placeHolderChars.length) { + System.arraycopy(originalChars, i, placeHolderComparisonArray, 0, placeHolderComparisonArray.length); + if (Arrays.equals(placeHolderComparisonArray, placeHolderChars)) { + i += placeHolderComparisonArray.length - 1; + buffer.append(replacementValue); + } else { + buffer.append(originalChars[i]); + } + } else { + buffer.append(originalChars[i]); + } + } + + return original == null ? null : buffer.toString(); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/connection/ConnectionUtil.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/connection/ConnectionUtil.java new file mode 100644 index 0000000..ecfe620 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/connection/ConnectionUtil.java @@ -0,0 +1,46 @@ +package com.quantum.util.connection; + +import java.sql.Connection; + +import com.quantum.Messages; +import com.quantum.model.Bookmark; +import com.quantum.model.ConnectionException; +import com.quantum.model.NotConnectedException; +import com.quantum.ui.dialog.ExceptionDisplayDialog; +import com.quantum.ui.dialog.PasswordDialog; + +import org.eclipse.swt.widgets.Shell; + +/** + *

This utility gets a connection from a bookmark, and handles any UI-specific + * interactions such as providing messages to the user and/or prompting for a + * password. + * + * @author BC + */ +public class ConnectionUtil { + + public Connection getConnection(Bookmark bookmark, Shell shell) { + Connection connection = null; + try { + connection = bookmark.getConnection(); + } catch (NotConnectedException e) { + connection = connect(bookmark, shell); + } + return connection; + } + + public Connection connect(Bookmark bookmark, Shell shell) { + Connection connection = null; + try { + connection = bookmark.connect(PasswordDialog.createPasswordFinder(shell)); + } catch (ConnectionException e) { + ExceptionDisplayDialog.openError(shell, + Messages.getString(getClass().getName() + ".title"), + Messages.getString(getClass().getName() + ".message") + + " (Bookmark:"+bookmark.getName()+")", e); + } + return connection; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/io/InputStreamHelper.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/io/InputStreamHelper.java new file mode 100644 index 0000000..33d4416 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/io/InputStreamHelper.java @@ -0,0 +1,18 @@ +package com.quantum.util.io; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author BC + */ +public class InputStreamHelper { + public static String readIntoString(InputStream inputStream) throws IOException { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + for (int b = inputStream.read(); b >= 0; b = inputStream.read()) { + outputStream.write((byte) b); + } + return new String(outputStream.toByteArray()); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/sql/TypesHelper.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/sql/TypesHelper.java new file mode 100644 index 0000000..e8b87f6 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/sql/TypesHelper.java @@ -0,0 +1,59 @@ +/* Created on Jan 9, 2004 */ +package com.quantum.util.sql; + +import java.lang.reflect.Field; +import java.sql.Types; + +/** + * @author holmesbc + */ +public class TypesHelper { + + public static final int BIT = Types.BIT; + public static final int TINYINT = Types.TINYINT; + public static final int SMALLINT = Types.SMALLINT; + public static final int INTEGER = Types.INTEGER; + public static final int BIGINT = Types.BIGINT; + public static final int FLOAT = Types.FLOAT; + public static final int REAL = Types.REAL; + public static final int DOUBLE = Types.DOUBLE; + public static final int NUMERIC = Types.NUMERIC; + public static final int DECIMAL = Types.DECIMAL; + public static final int CHAR = Types.CHAR; + public static final int VARCHAR = Types.VARCHAR; + public static final int LONGVARCHAR = Types.LONGVARCHAR; + public static final int DATE = Types.DATE; + public static final int TIME = Types.TIME; + public static final int TIMESTAMP = Types.TIMESTAMP; + public static final int BINARY = Types.BINARY; + public static final int VARBINARY = Types.VARBINARY; + public static final int LONGVARBINARY = Types.LONGVARBINARY; + public static final int NULL = Types.NULL; + public static final int OTHER = Types.OTHER; + public static final int JAVA_OBJECT = Types.JAVA_OBJECT; + public static final int DISTINCT = Types.DISTINCT; + public static final int STRUCT = Types.STRUCT; + public static final int ARRAY = Types.ARRAY; + public static final int BLOB = Types.BLOB; + public static final int CLOB = Types.CLOB; + public static final int REF = Types.REF; + public static final int DATALINK; + public static final int BOOLEAN; + + static { + // These fields only exist in the JDK 1.4 version of the Types class. + BOOLEAN = getType("BOOLEAN", 16); + DATALINK = getType("DATALINK", 70); + } + + private static int getType(String typeName, int defaultValue) { + try { + Field field = Types.class.getField(typeName); + defaultValue = field.getInt(null); + } catch (NoSuchFieldException e) { + } catch (IllegalAccessException e) { + } + return defaultValue; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/versioning/VersioningHelper.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/versioning/VersioningHelper.java new file mode 100644 index 0000000..1f3bacf --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/versioning/VersioningHelper.java @@ -0,0 +1,49 @@ +package com.quantum.util.versioning; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.widgets.FontDialog; + +/** + * This class provides backward compatibility between versions of Eclipse for + * known differences. + * + * @author BC + */ +public class VersioningHelper { + + public static final int ECLIPSE_VERSION_2_1_1 = 2135; + + /** + * Set the font in a FontDialog. In Eclipse 2.1.1, the + * setFontData() method was deprecated and an alternative + * method, setFontList() was suggested in its place. + * + * @param fontDialog + * @param fontData + */ + public static void setFont(FontDialog fontDialog, FontData[] fontData) { + try { + if (SWT.getVersion() >= ECLIPSE_VERSION_2_1_1) { + Method method = fontDialog.getClass().getMethod( + "setFontList", new Class[] { fontData.getClass()}); + method.invoke(fontDialog, new Object[] {fontData}); + } else if (fontData.length > 0) { + Method method = fontDialog.getClass().getMethod( + "setFontData", new Class[] { FontData.class }); + method.invoke(fontDialog, new Object[] { fontData[0] }); + } + } catch (NoSuchMethodException e) { + // should not happen + } catch (IllegalArgumentException e) { + // should not happen + } catch (IllegalAccessException e) { + // should not happen + } catch (InvocationTargetException e) { + // should not happen + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/xml/XMLHelper.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/xml/XMLHelper.java new file mode 100644 index 0000000..bf16296 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/util/xml/XMLHelper.java @@ -0,0 +1,73 @@ +package com.quantum.util.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Writer; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.xml.serialize.DOMSerializer; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.XMLSerializer; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + + +/** + *

This class constructs a pretty-printing XML Serializer + * + * @author BC + */ +public class XMLHelper { + + private XMLHelper() {} + + public static DOMSerializer createDOMSerializer(Writer writer) + throws IOException { + XMLSerializer serializer = new XMLSerializer(writer, createOutputFormat()); + return serializer.asDOMSerializer(); + } + + public static DOMSerializer createDOMSerializer(OutputStream stream) + throws IOException { + XMLSerializer serializer = new XMLSerializer(stream, createOutputFormat()); + return serializer.asDOMSerializer(); + } + private static OutputFormat createOutputFormat() { + OutputFormat format = new OutputFormat(); + format.setIndenting(true); + format.setLineWidth(80); + return format; + } + + public static Document createEmptyDocument() throws ParserConfigurationException { + DocumentBuilder builder = createDocumentBuilder(); + return builder.newDocument(); + } + + public static Document createFromInputStream(InputStream stream) + throws IOException, SAXException, ParserConfigurationException { + DocumentBuilder builder = createDocumentBuilder(); + return builder.parse(stream); + } + + private static DocumentBuilder createDocumentBuilder() + throws FactoryConfigurationError, ParserConfigurationException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + return factory.newDocumentBuilder(); + } + + public static void write(Writer writer, Document document) + throws IOException { + createDOMSerializer(writer).serialize(document); + } + + public static void write(OutputStream stream, Document document) + throws IOException { + createDOMSerializer(stream).serialize(document); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/CopyAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/CopyAction.java new file mode 100644 index 0000000..27fe957 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/CopyAction.java @@ -0,0 +1,40 @@ +/* + * Created on 28-jul-2003 + * + */ +package com.quantum.view; + +import com.quantum.QuantumPlugin; +import com.quantum.view.tableview.TableView; + +import org.eclipse.jface.action.Action; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; + + +public final class CopyAction extends Action { + private final TableView view; + private final Table table; + public CopyAction(TableView view, Table table) { + super(); + this.view = view; + this.table = table; + } + public void run() { + TableItem items[] = table.getSelection(); + StringBuffer text = new StringBuffer(); + for (int i = 0; i < items.length; i++) { + int columns = table.getColumnCount(); + for (int col = 0; col < columns; col++) { + text.append(items[i].getText(col)); + text.append('\t'); + } + text.append('\n'); + } + QuantumPlugin.getDefault().getSysClip().setContents( + new Object[] { text.toString()}, + new Transfer[] { TextTransfer.getInstance()}); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/LogConstants.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/LogConstants.java new file mode 100644 index 0000000..38e6b0e --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/LogConstants.java @@ -0,0 +1,9 @@ +package com.quantum.view; + +public interface LogConstants { + public int QUERY = 1; + public int ERROR = 2; + public int RESULTS = 3; + public int WARNING = 4; + public int DEFAULT = 5; +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/LogProxy.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/LogProxy.java new file mode 100644 index 0000000..2c592c1 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/LogProxy.java @@ -0,0 +1,34 @@ +package com.quantum.view; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class LogProxy implements LogConstants { + private static LogProxy instance = null; + private SQLLogView log = null; + private LogProxy() { + } + public synchronized static LogProxy getInstance() { + if (instance == null) { + instance = new LogProxy(); + } + return instance; + } + public void addText(int type, String text) { + log = SQLLogView.getInstance(); + if (log != null) { + log.addText(type, text); + } + } + + public void addText(int type, String text, Exception e) { + addText(type, text); + StringWriter writer = new StringWriter(); + e.printStackTrace(new PrintWriter(writer)); + addText(type, writer.toString()); + } + + public void addText(int type, Exception e) { + addText(type, "Error occured: " + e, e); //$NON-NLS-1$ + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/SQLLogView.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/SQLLogView.java new file mode 100644 index 0000000..dfd7465 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/SQLLogView.java @@ -0,0 +1,109 @@ +package com.quantum.view; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.custom.StyledTextContent; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.part.ViewPart; + +public class SQLLogView extends ViewPart implements LogConstants { + private Color QUERY_COLOR; + private Color WARNING_COLOR; + private Color DEFAULT_COLOR; + private Color ERROR_COLOR; + private Color RESULTS_COLOR; + private StyledText widget; + private static SQLLogView instance = null; + private static final String newLine = "\n"; //$NON-NLS-1$ + public static SQLLogView getInstance() { + return instance; + } + + public void createPartControl(Composite parent) { + instance = this; + QUERY_COLOR = new Color(parent.getShell().getDisplay(), 0, 255, 0); + ERROR_COLOR = new Color(parent.getShell().getDisplay(), 255, 0, 0); + RESULTS_COLOR = new Color(parent.getShell().getDisplay(), 0, 0, 255); + DEFAULT_COLOR = new Color(parent.getShell().getDisplay(), 0, 0, 0); + WARNING_COLOR = new Color(parent.getShell().getDisplay(), 255, 127, 0); + widget = new StyledText(parent, SWT.H_SCROLL | SWT.V_SCROLL); + IActionBars bars = this.getViewSite().getActionBars(); + bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction); + bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction); + + IToolBarManager toolBar = getViewSite().getActionBars().getToolBarManager(); + clearAction.setImageDescriptor(QuantumPlugin.getImageDescriptor("clear.gif")); //$NON-NLS-1$ + clearAction.setToolTipText(Messages.getString("SQLLogView.ClearLog")); //$NON-NLS-1$ + toolBar.add(clearAction); + + widget.setEditable(false); + + widget.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + instance = null; + } + }); + } + + public void addText(int style, String text) { + text = text + newLine; + int start = widget.getText().length(); + StyleRange styleRange = new StyleRange(); + styleRange.start = start; + styleRange.length = text.length(); + if (style == QUERY) { + styleRange.foreground = QUERY_COLOR; + } else if (style == ERROR) { + styleRange.foreground = ERROR_COLOR; + } else if (style == RESULTS) { + styleRange.foreground = RESULTS_COLOR; + } else if (style == WARNING) { + styleRange.foreground = WARNING_COLOR; + } else { + styleRange.foreground = DEFAULT_COLOR; + } + widget.append(text); + widget.setStyleRange(styleRange); + revealEndOfDocument(); + } + + protected void revealEndOfDocument() { + StyledTextContent doc= widget.getContent(); + int docLength= doc.getCharCount(); + if (docLength > 0) { + widget.setCaretOffset(docLength); + widget.showSelection(); + } + } + + public void setFocus() { + widget.setFocus(); + } + + private Action copyAction = new Action() { + public void run() { + widget.copy(); + } + }; + private Action selectAllAction = new Action() { + public void run() { + widget.selectAll(); + } + }; + private Action clearAction = new Action() { + public void run() { + widget.setText(""); //$NON-NLS-1$ + } + }; +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/SQLQueryView.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/SQLQueryView.java new file mode 100644 index 0000000..a8469e7 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/SQLQueryView.java @@ -0,0 +1,517 @@ +package com.quantum.view; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.LinkedList; +import java.util.NoSuchElementException; +import java.util.Vector; + +import org.eclipse.jface.action.Action; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ExtendedModifyEvent; +import org.eclipse.swt.custom.ExtendedModifyListener; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IKeyBindingService; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.part.ViewPart; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.actions.ExecuteAction; +import com.quantum.actions.ExportQueryAction; +import com.quantum.actions.ImportQueryAction; +import com.quantum.model.Bookmark; +import com.quantum.model.NotConnectedException; +import com.quantum.sql.MultiSQLServer; +import com.quantum.sql.parser.SQLLexx; +import com.quantum.sql.parser.Token; +import com.quantum.view.bookmark.BookmarkNode; +import com.quantum.view.bookmark.BookmarkView; + +public class SQLQueryView extends ViewPart { + private ExecuteAction executeAction; + private ImportQueryAction importQueryAction; + private ExportQueryAction exportQueryAction; + private Label statusImage; + private Label status; + private ProgressBar progress; + private StyledText widget; + private ToolItem autoCommitItem; + private ToolItem commitItem; + private ToolItem rollbackItem; + private Color STRING_LITERAL; + private Color KEYWORD; + private Color COMMENT; + private Color NUMERIC; + private Color DEFAULT; + private long parseTime = 0; + private long fullTime = 0; + public SQLQueryView() { + super(); + } + public void setFocus() { + + String title = "Quantum SQL Query Editor"; + BookmarkNode bookmarkNode = null; + Bookmark bookmark = null; + Connection con = null; + if (BookmarkView.getInstance() != null ) { + bookmarkNode = BookmarkView.getInstance().getCurrentBookmark(); + } + if (bookmarkNode != null) + bookmark = bookmarkNode.getBookmark(); + if (bookmark != null) { + title = bookmark.getName() + " (" + title + ")"; + setTitle( title ); + try { + con = bookmark.getConnection(); + } catch (NotConnectedException e) { + // Doesn't matter, "con" remains null + } + } + + updateAutoCommitState(bookmark, con); + + widget.setFocus(); + + } + public static SQLQueryView getInstance() { + return (SQLQueryView) QuantumPlugin.getDefault().getView("com.quantum.view.sqlqueryview"); + + } + + public void createPartControl(org.eclipse.swt.widgets.Composite parent) { + initActions(); + KEYWORD = new Color(parent.getShell().getDisplay(), 126, 0, 75); + STRING_LITERAL = new Color(parent.getShell().getDisplay(), 0, 0, 255); + COMMENT = new Color(parent.getShell().getDisplay(), 88, 148, 64); + NUMERIC = new Color(parent.getShell().getDisplay(), 255, 0, 0); + DEFAULT = new Color(parent.getShell().getDisplay(), 0, 0, 0); + Composite main = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + main.setLayout(layout); + ToolBar toolbar = new ToolBar(main, SWT.HORIZONTAL); + ToolItem item = new ToolItem(toolbar, SWT.PUSH); + item.setImage(QuantumPlugin.getImage("play.gif")); //$NON-NLS-1$ + item.setToolTipText(Messages.getString("sqlqueryview.executeQuery")); //$NON-NLS-1$ + item.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + executeAction.run(); + } + }); + item = new ToolItem(toolbar, SWT.SEPARATOR); + item = new ToolItem(toolbar, SWT.PUSH); + item.setImage(QuantumPlugin.getImage("import.gif")); //$NON-NLS-1$ + item.setToolTipText(Messages.getString("sqlqueryview.importQuery")); //$NON-NLS-1$ + item.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + importQueryAction.run(); + } + }); + item = new ToolItem(toolbar, SWT.PUSH); + item.setImage(QuantumPlugin.getImage("export.gif")); //$NON-NLS-1$ + item.setToolTipText(Messages.getString("sqlqueryview.exportQuery")); //$NON-NLS-1$ + item.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + exportQueryAction.run(); + } + }); + item = new ToolItem(toolbar, SWT.PUSH); + item.setImage(QuantumPlugin.getImage("clear.gif")); //$NON-NLS-1$ + item.setToolTipText(Messages.getString("sqlqueryview.clear")); //$NON-NLS-1$ + item.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + setQuery(""); //$NON-NLS-1$ + } + }); + + item = new ToolItem(toolbar, SWT.SEPARATOR); + + commitItem = new ToolItem(toolbar, SWT.PUSH); + commitItem.setImage(QuantumPlugin.getImage("commit.gif")); //$NON-NLS-1$ + commitItem.setToolTipText(Messages.getString("SQLQueryView.Commit")); //$NON-NLS-1$ + commitItem.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent event) { + try { + BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark(); + if (node != null) MultiSQLServer.getInstance().commit( + node.getBookmark().getConnection()); + } catch (NotConnectedException e) { + e.printStackTrace(); + } + } + }); + + rollbackItem = new ToolItem(toolbar, SWT.PUSH); + rollbackItem.setImage(QuantumPlugin.getImage("rollback.gif")); //$NON-NLS-1$ + rollbackItem.setToolTipText(Messages.getString("SQLQueryView.RollBack")); //$NON-NLS-1$ + rollbackItem.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent event) { + } + public void widgetSelected(SelectionEvent event) { + try { + BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark(); + if (node != null) MultiSQLServer.getInstance().rollback( + node.getBookmark().getConnection()); + } catch (NotConnectedException e) { + e.printStackTrace(); + } + } + }); + + autoCommitItem = new ToolItem(toolbar, SWT.CHECK); + autoCommitItem.setImage(QuantumPlugin.getImage("autocommit.gif")); //$NON-NLS-1$ + autoCommitItem.setToolTipText(Messages.getString("SQLQueryView.AutoCommit")); //$NON-NLS-1$ + autoCommitItem.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent event) { + BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark(); + if (node == null) return; + Connection con = null; + try { + // Get the connection + con = node.getBookmark().getConnection(); + // If connected (else will throw exception and jump out) switchs the state of the + // autoCommit option of the JDBC driver + MultiSQLServer.getInstance().setAutoCommit( con, autoCommitItem.getSelection()); + } catch (NotConnectedException e) { + //Doesn't matter + } + // Update the bookmark and the buttons + updateAutoCommitState(node.getBookmark(), con); + + } + }); + BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark(); + if (node == null) autoCommitItem.setSelection(true); + else autoCommitItem.setSelection(node.getBookmark().isAutoCommit()); + if (autoCommitItem.getSelection()) { + commitItem.setEnabled(false); + rollbackItem.setEnabled(false); + } else { + commitItem.setEnabled(true); + rollbackItem.setEnabled(true); + } + widget = new StyledText(main, SWT.H_SCROLL | SWT.V_SCROLL); + + IActionBars bars = this.getViewSite().getActionBars(); + bars.setGlobalActionHandler(IWorkbenchActionConstants.CUT, cutAction); + bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction); + bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction); + bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction); + + widget.setEditable(true); + widget.addExtendedModifyListener(modifyListener); + + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + gridData.verticalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + widget.setLayoutData(gridData); + + Composite bottomStatus = new Composite(main, SWT.NONE); + gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + bottomStatus.setLayoutData(gridData); + + GridLayout horizontal = new GridLayout(3, false); + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + layout.marginHeight = 0; + layout.marginWidth = 0; + bottomStatus.setLayout(horizontal); + + statusImage = new Label(bottomStatus, SWT.NONE); + status = new Label(bottomStatus, SWT.NONE); + gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + status.setLayoutData(gridData); + + progress = new ProgressBar(bottomStatus, SWT.HORIZONTAL); + + status.setText(Messages.getString("sqlqueryview.done")); //$NON-NLS-1$ + statusImage.setImage(QuantumPlugin.getImage("success.gif")); //$NON-NLS-1$ + progress.setMinimum(0); + + IKeyBindingService keyBindingService = getSite().getKeyBindingService(); + // TODO: check the version numbers for this method + keyBindingService.setScopes(new String[] { + "org.eclipse.ui.globalScope", + "com.quantum.view.sql" + }); + keyBindingService.registerAction(this.executeAction); + } + + /** + * Sets the state of the "Commit", "Rollback" and "autoCommit" buttons + * to reflect the situation in the connection + */ + protected void updateAutoCommitState(Bookmark bookmark, Connection con) { + boolean autoCommit = true; + // Calculate the state of the autoCommit option + if (con != null) + { + // If we have a connection, the autoCommit state is that of the connection + try { + autoCommit = con.getAutoCommit(); + } catch (SQLException e) { + // Doesn't matter, we take default + } + } else { + // if no connection, we try the autoCommit of the bookmark, or else the default + if (bookmark != null) autoCommit = bookmark.isAutoCommit(); + } + // Set the autoCommit state of the bookmark to the calculated + if (bookmark != null) bookmark.setAutoCommit(autoCommit); + // Set the state of the buttons to the correct autoCommit state + autoCommitItem.setSelection(autoCommit); + if (autoCommitItem.getSelection()) { + commitItem.setEnabled(false); + rollbackItem.setEnabled(false); + } else { + commitItem.setEnabled(true); + rollbackItem.setEnabled(true); + } + } + public void setProgress(int increment, int max) { + progress.setMaximum(max); + progress.setSelection(increment); + } + + private void initActions() { + executeAction = new ExecuteAction(); + executeAction.init(this); + importQueryAction = new ImportQueryAction(); + importQueryAction.init(this); + exportQueryAction = new ExportQueryAction(); + exportQueryAction.init(this); + } + + public void setStatus(String text) { + statusImage.setImage(null); + status.setText(text); + } + + public void setStatus(Image img, String text) { + statusImage.setImage(img); + status.setText(text); + } + + public String getQuery() { + return widget.getText(); + } + + public void setQuery(String text) { + widget.setText(text); + } + + private String[] keywords = { + "ADD", "ALL", "ALTER", "AND", "ANY", + "AS", "ASC", "AUTOINCREMENT", "AVA", "BETWEEN", + "BINARY", "BIT", "BOOLEAN", "BY", "CREATE", + "BYTE", "CHAR", "CHARACTER", "COLUMN", "CONSTRAINT", + "COUNT", "COUNTER", "CURRENCY", "DATABASE", "DATE", + "DATETIME", "DELETE", "DESC", "DISALLOW", "DISTINCT", + "DISTINCTROW", "DOUBLE", "DROP", "EXISTS", "FROM", + "FLOAT", "FLOAT4", "FLOAT8", "FOREIGN", "GENERAL", + "GROUP", "GUID", "HAVING", "INNER", "INSERT", + "IGNORE", "IMP", "IN", "INDEX", "INT", + "INTEGER", "INTEGER1", "INTEGER2", "INTEGER4", "INTO", + "IS", "JOIN", "KEY", "LEFT", "LEVEL", + "LIKE", "LOGICAL", "LONG", "LONGBINARY", "LONGTEXT", + "MAX", "MEMO", "MIN", "MOD", "MONEY", + "NOT", "NULL", "NUMBER", "NUMERIC", "OLEOBJECT", + "ON", "PIVOT", "OPTION", "PRIMARY", "ORDER", + "OUTER", "OWNERACCESS", "PARAMETERS", "PERCENT", "REAL", + "REFERENCES", "RIGHT", "SELECT", "SET", "SHORT", + "SINGLE", "SMALLINT", "SOME", "STDEV", "STDEVP", + "STRING", "SUM", "TABLE", "TABLEID", "TEXT", + "TIME", "TIMESTAMP", "TOP", "TRANSFORM", "UNION", + "UNIQUE", "UPDATE", "VALUE", "VALUES", "VAR", + "VARBINARY", "VARCHAR", "VARP", "WHERE", "WITH", + "YESNO" }; + + SyntaxHighlighter textUpdater = new SyntaxHighlighter(); + + private class UpdateRequest { + public UpdateRequest(String text, int start, int length) { + this.text = text; + this.start = start; + this.length = length; + } + public String text; + public int start; + public int length; + } + + private class SyntaxHighlighter extends Thread { + private boolean running = true; + private LinkedList requests = new LinkedList(); + public SyntaxHighlighter() { + super(); + setPriority(Thread.MIN_PRIORITY); + start(); + } + public synchronized void updateText(String text, int start, int length) { + requests.add(new UpdateRequest(text, start, length)); + notify(); + } + public synchronized void shutdown() { + running = false; + interrupt(); + } + public void run() { + while (running) { + try { + synchronized (this) { + if (requests.size() <= 0) { + wait(); + } else { + Thread.sleep(10); + } + } + UpdateRequest request = (UpdateRequest) requests.removeFirst(); + String text = request.text.toUpperCase(); + //int dirtyStart = request.start; + //int dirtyEnd = request.start + request.length; + StyleRange styleRange; + long startTime = System.currentTimeMillis(); + Vector tokens = SQLLexx.parse(text); + long subTime = System.currentTimeMillis(); + Vector styles = new Vector(); + int min = Integer.MAX_VALUE; + int max = 0; + for (int i = 0; i < tokens.size(); i++) { + Token t = (Token) tokens.elementAt(i); + String value = t.getValue(); + int start = t.getStart(); + int length = t.getEnd() - t.getStart(); + styleRange = new StyleRange(); + styleRange.start = start; + styleRange.length = value.length(); + styleRange.fontStyle = SWT.NULL; + styleRange.foreground = DEFAULT; + //boolean upper = start <= dirtyEnd && start >= dirtyStart; + //boolean lower = ((start + length) >= dirtyStart && (start + length) <= dirtyEnd); + //boolean both = (start <= dirtyStart && (start + length) >= dirtyEnd); + //if (upper || lower || both) { + if (true) { // Let's update the whole text, as some comment changes can alter everything + min = Math.min(start, min); + max = Math.max(max, start + length); + if (t.getType() == Token.IDENTIFIER) { + boolean keyword = false; + for (int index = 0; index < keywords.length; index++) { + if (value.equals(keywords[index])) { + keyword = true; + } + } + if (keyword) { + styleRange.fontStyle = SWT.BOLD; + styleRange.foreground = KEYWORD; + } else { + styleRange.foreground = DEFAULT; + } + styles.addElement(styleRange); + } else if (t.getType() == Token.COMMENT) { + styleRange.foreground = COMMENT; + styles.addElement(styleRange); + } else if (t.getType() == Token.LITERAL) { + styleRange.foreground = STRING_LITERAL; + styles.addElement(styleRange); + } else if (t.getType() == Token.NUMERIC) { + styleRange.foreground = NUMERIC; + styles.addElement(styleRange); + } else { + styles.addElement(styleRange); + } + } + } + StyleRange[] ranges = new StyleRange[styles.size()]; + for (int k = 0; k < ranges.length; k++) { + ranges[k] = (StyleRange) styles.elementAt(k); + } + if (max >= 0 && ranges.length > 0) { + setStyles(ranges, min, max - min); + } + long endTime = System.currentTimeMillis(); + parseTime = subTime - startTime; + fullTime = endTime - startTime; + } catch (NoSuchElementException e) { + // ignore a missing request + } catch (InterruptedException e) { + // ignore any interruptions + } + } + } + } + public void setStyles(final StyleRange[] styles, final int start, final int length) { + getViewSite().getShell().getDisplay().asyncExec(new Runnable() { + public void run() { + try { + for (int i = 0; i < styles.length; i++) { + widget.setStyleRange(styles[i]); + } + } catch (Throwable t) { + System.out.println("Error with styles: " + t.getClass().toString()); //$NON-NLS-1$ + // ignore any errors + } + } + }); + } + + ExtendedModifyListener modifyListener = new ExtendedModifyListener() { + public void modifyText(ExtendedModifyEvent event) { + textUpdater.updateText(getQuery(), event.start, event.length); + } + }; + + private Action cutAction = new Action() { + public void run() { + widget.cut(); + } + }; + private Action copyAction = new Action() { + public void run() { + widget.copy(); + } + }; + private Action pasteAction = new Action() { + public void run() { + widget.paste(); + } + }; + private Action selectAllAction = new Action() { + public void run() { + widget.selectAll(); + } + }; +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/ViewHelper.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/ViewHelper.java new file mode 100644 index 0000000..e460e44 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/ViewHelper.java @@ -0,0 +1,101 @@ +/* + * Created on 22-jul-2003 + * + */ +package com.quantum.view; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.sql.Connection; +import java.sql.SQLException; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.sql.MultiSQLServer; +import com.quantum.sql.SQLResults; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IViewPart; + +/** + * @author panic + * + */ +public class ViewHelper { + + public static SQLResults tryGetResults(IViewPart view, Connection con, String query) { + return tryGetResults(view.getSite().getShell(), con, query); + } + + public static SQLResults tryGetResults(Shell shell, Connection con, String query) { + SQLResults results = null; + MultiSQLServer server = MultiSQLServer.getInstance(); + try { + results = server.execute(con, query); + } catch (SQLException e) { + LogProxy log = LogProxy.getInstance(); + log.addText(LogProxy.ERROR, e.getLocalizedMessage(), e); //$NON-NLS-1$ //$NON-NLS-2$ + results = new SQLResults(); + results.setIsError(true); + MessageDialog.openConfirm(shell, "Database returned error", e.getLocalizedMessage()); //$NON-NLS-1$ + } + return results; + } + + public static FileOutputStream askSaveFile(String key, Shell shell) { + return askSaveFile(key, shell, null, null); + } + /** + * Asks the user for a file to be saved. Uses a key to get the preferences and save the path. + * The preferences should be defined in the Messages file. + * @param key + * @param shell + * @param filterExt + * @param filterNames + * @return - An already opened FileOutputStream, or NULL if nothing selected, dialog canceled or some error. + */ + public static FileOutputStream askSaveFile(String key, Shell shell, String[] filterExt, String[] filterNames) { + + FileDialog dialog = new FileDialog(shell, SWT.SAVE); + + if (filterExt == null) { + dialog.setFilterExtensions(new String[]{Messages.getString("filedialog."+key+".filter"), + Messages.getString("filedialog.allfiles.filter")}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + dialog.setFilterNames(new String[]{ Messages.getString("filedialog."+key+".name"), + Messages.getString("filedialog.allfiles.name")}); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + dialog.setFilterExtensions(filterExt); + dialog.setFilterNames(filterNames); + } + + dialog.setFilterPath(QuantumPlugin.getDefault().getPreferenceStore().getString("quantum.dialogs."+ key + ".path")); + String filename = dialog.open(); + if (filename == null) return null; + // We save the used path + QuantumPlugin.getDefault().getPreferenceStore().setValue("quantum.dialogs."+ key + ".path", filename); + + FileOutputStream out = null; + File target = new File(filename); + if (target.exists() && Messages.getString("filedialog.options.ConfirmOverwrite").equals("y")) { + boolean confirmOverwrite = + MessageDialog.openConfirm(shell, Messages.getString("filedialog.message.ConfirmOverwriteTitle"), //$NON-NLS-1$ + Messages.getString("filedialog.message.ConfirmOverwriteMessage") + target.getName() + //$NON-NLS-1$ + Messages.getString("filedialog.message.ConfirmOverwriteQuestion")); //$NON-NLS-1$ + if (!confirmOverwrite) return null; + } + + try { + out = new FileOutputStream(target); + } catch (FileNotFoundException e) { + MessageDialog.openConfirm(shell, Messages.getString("filedialog.message.CannotOpenFileTitle"), //$NON-NLS-1$ + Messages.getString("filedialog.message.CannotOpenFileMessage") + filename+ //$NON-NLS-1$ + Messages.getString("filedialog.message.CannotOpenFileExplain")); //$NON-NLS-1$ + + } + return out; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/AddSchemaAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/AddSchemaAction.java new file mode 100644 index 0000000..9713922 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/AddSchemaAction.java @@ -0,0 +1,58 @@ +package com.quantum.view.bookmark; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.model.NotConnectedException; +import com.quantum.sql.SQLHelper; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + + +final class AddSchemaAction extends SelectionListenerAction { + private final IViewPart view; + /** + * @param BookmarkView + */ + public AddSchemaAction(IViewPart view) { + super(Messages.getString("BookmarkView.SetExtraSchemas")); //$NON-NLS-1$ + setImageDescriptor( + QuantumPlugin.getImageDescriptor("add_schema.gif")); //$NON-NLS-1$ + this.view = view; + } + + public void run() { + Bookmark bookmark = getBookmark(); + if (bookmark != null) { + try { + Vector schemas = SQLHelper.getSchemas(bookmark.getConnection()); + AddSchemaDialog dialog = new AddSchemaDialog(this.view.getSite().getShell(), schemas); + dialog.open(); + if (dialog.getSelectedSchemas() != null) { + for (Iterator i = dialog.getSelectedSchemas().iterator(); i.hasNext();) { + bookmark.addSchema((String) i.next()); + } + } + } catch (NotConnectedException e) { + } + } + } + + protected Bookmark getBookmark() { + List list = getSelectedNonResources(); + return (list.size() > 0) ? ((BookmarkNode) list.get(0)).getBookmark() : null; + } + + protected boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection) & + selection.size() == 1 & + (selection.getFirstElement() instanceof BookmarkNode); + return enabled & getBookmark().isConnected(); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/AddSchemaDialog.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/AddSchemaDialog.java new file mode 100644 index 0000000..ce2819e --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/AddSchemaDialog.java @@ -0,0 +1,86 @@ +/* + * Created on 12-jul-2003 + * + */ +package com.quantum.view.bookmark; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.Vector; + +import com.quantum.IQuantumConstants; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.help.WorkbenchHelp; + +/** + * @author panic + * + */ +public class AddSchemaDialog extends Dialog { + + protected Vector input; + protected List list; + private Vector selection; + /** + * Creates a new AddSchemaDialog. + */ + public AddSchemaDialog(Shell parentShell, Vector input) { + super(parentShell); + this.input = input; + this.list = null; + selection = null; + } + /* (non-Javadoc) + * Method declared on Window. + */ + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Set Schemas"); + WorkbenchHelp.setHelp( + newShell, + IQuantumConstants.ADD_SCHEMA_DIALOG_CONTEXT); + } + /* (non-Javadoc) + * Method declared on Dialog + */ + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + + list = new List(composite, SWT.BORDER | SWT.V_SCROLL | SWT.MULTI); + GridData data = new GridData(GridData.FILL_BOTH); + list.setLayoutData(data); + for (Iterator iter = input.iterator(); iter.hasNext();) { + String element = (String) iter.next(); + list.add(element); + } + return composite; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + */ + protected void okPressed() { + // If it's OK, then the selection is not null. Null is used to signal a canceled dialog. + selection = new Vector(); + if (list != null) { + String selecStr[] = list.getSelection(); + for (int i = 0; i < selecStr.length; i++) { + String string = selecStr[i]; + selection.add(string); + } + } + super.okPressed(); + } + + public Collection getSelectedSchemas() { + return this.selection == null ? null : new ArrayList(this.selection); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkClipboard.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkClipboard.java new file mode 100644 index 0000000..665e50b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkClipboard.java @@ -0,0 +1,13 @@ +package com.quantum.view.bookmark; + +import com.quantum.model.Bookmark; + +/** + * + * TODO: There must be a better way to do this... + * @author BC + */ +public interface BookmarkClipboard { + public void setBookmark(Bookmark bookmark); + public Bookmark getBookmark(); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkContentProvider.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkContentProvider.java new file mode 100644 index 0000000..2335110 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkContentProvider.java @@ -0,0 +1,40 @@ +package com.quantum.view.bookmark; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +public class BookmarkContentProvider implements ITreeContentProvider { + + public Object[] getChildren(Object element) { + if (element instanceof TreeNode) { + TreeNode node = (TreeNode) element; + return node.getChildren(); + } + return BookmarkListNode.EMPTY_ARRAY; + } + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + public Object getParent(Object element) { + if (element instanceof TreeNode) { + TreeNode node = (TreeNode) element; + return node.getParent(); + } + return null; + } + + public boolean hasChildren(Object element) { + if (element instanceof TreeNode) { + TreeNode node = (TreeNode) element; + return node.hasChildren(); + } + return false; + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public void dispose() { + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkLabelProvider.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkLabelProvider.java new file mode 100644 index 0000000..71fec68 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkLabelProvider.java @@ -0,0 +1,74 @@ +package com.quantum.view.bookmark; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.swt.graphics.Image; + +/** + * @author root + * + * Implements the ILabelProvider for the Bookmarks. + */ +public class BookmarkLabelProvider implements ILabelProvider { + + private LabelDecorationInstructions labelDecorationInstructions = new LabelDecorationInstructions(); + + /** + * @see org.eclipse.jface.viewers.ILabelProvider#getImage(Object) + */ + public Image getImage(Object element) { + if (element != null && element instanceof TreeNode) { + return ((TreeNode) element).getImage(); + } else { + return null; + } + } + + /** + * @see org.eclipse.jface.viewers.ILabelProvider#getText(Object) + */ + public String getText(Object element) { + if (element != null && element instanceof TreeNode) { + String labelName = ((TreeNode) element).getLabelName(); + String decorations = ((TreeNode) element).getLabelDecorations( + this.labelDecorationInstructions); + if (decorations != null && decorations.trim().length() > 0) { + labelName += " " + decorations; + } + return labelName; + } else { + return element == null ? "<>" : element.toString(); + } + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(ILabelProviderListener) + */ + public void addListener(ILabelProviderListener listener) { + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() + */ + public void dispose() { + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(Object, String) + */ + public boolean isLabelProperty(Object element, String property) { + return false; + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(ILabelProviderListener) + */ + public void removeListener(ILabelProviderListener listener) { + } + /** + * @return + */ + public LabelDecorationInstructions getLabelDecorationInstructions() { + return labelDecorationInstructions; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkListNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkListNode.java new file mode 100644 index 0000000..37adfc6 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkListNode.java @@ -0,0 +1,120 @@ +package com.quantum.view.bookmark; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Arrays; +import java.util.Collections; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; + +import com.quantum.model.Bookmark; +import com.quantum.model.BookmarkCollection; + + +/** + * @author root + */ +public final class BookmarkListNode extends TreeNode implements PropertyChangeListener { + final static BookmarkListNode instance = new BookmarkListNode(); + final static TreeNode[] EMPTY_ARRAY = new TreeNode[0]; + private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); + private boolean initialized = false; + + private BookmarkListNode() { + super(null); + } + + public static BookmarkListNode getInstance() { + return BookmarkListNode.instance; + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getChildren() + */ + public Object[] getChildren() { + if (!initialized) { + initializeChildren(); + BookmarkCollection.getInstance().addPropertyChangeListener(this); + } + BookmarkNode[] nodes = (BookmarkNode[]) this.children.toArray( + new BookmarkNode[this.children.size()]); + Arrays.sort(nodes); + return nodes; + } + + /** + * @see com.quantum.view.bookmark.TreeNode#hasChildren() + */ + public boolean hasChildren() { + return true; + } + + public String getName() { + return "ROOT"; //$NON-NLS-1$ + } + protected String getImageName() { + return null; + } + /** + * @param listener + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + this.propertyChangeSupport.addPropertyChangeListener(listener); + } + + /** + * @param listener + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + this.propertyChangeSupport.removePropertyChangeListener(listener); + } + protected void firePropertyChange(PropertyChangeEvent event) { + this.propertyChangeSupport.firePropertyChange(event); + } + + protected synchronized void initializeChildren() { + boolean changed = false; + Map temp = new Hashtable(); + for (Iterator i = this.children.iterator(); i.hasNext();) { + BookmarkNode bookmark = (BookmarkNode) i.next(); + temp.put(bookmark.getName(), bookmark); + } + + this.children.clear(); + + Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks(); + for (int i = 0, length = (bookmarks == null) ? 0 : bookmarks.length; i < length; i++) { + + BookmarkNode node = (BookmarkNode) temp.remove(bookmarks[i].getName()); + if (node == null) { + this.children.add(new BookmarkNode(this, bookmarks[i])); + changed = true; + } else { + this.children.add(node); + } + } + + for (Iterator i = temp.values().iterator(); i.hasNext(); ) { + ((TreeNode) i.next()).dispose(); + changed = true; + } + + Collections.sort(this.children); + this.initialized = true; + + if (changed) { + firePropertyChange("bookmarks", null, null); + } + } + + /** + * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + if ("bookmarks".equals(event.getPropertyName())) { + initializeChildren(); + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkNode.java new file mode 100644 index 0000000..c74c555 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkNode.java @@ -0,0 +1,167 @@ +package com.quantum.view.bookmark; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.quantum.model.Bookmark; +import com.quantum.model.ConnectionException; +import com.quantum.model.NotConnectedException; +import com.quantum.model.Schema; + +public class BookmarkNode extends TreeNode implements PropertyChangeListener { + private Bookmark bookmark; + + private QuickListNode quickListNode; + private QueryListNode queryListNode; + + public BookmarkNode(TreeNode parent, Bookmark bookmark) { + super(parent); + this.bookmark = bookmark; + this.bookmark.addPropertyChangeListener(this); + } + + public Object[] getChildren() { + if (bookmark.isConnected() && this.children.isEmpty()) { + initializeChildren(); + } + if (this.bookmark.isConnected()) { + return (TreeNode[]) this.children.toArray(new TreeNode[this.children.size()]); + } else { + return BookmarkListNode.EMPTY_ARRAY; + } + } + + protected void initializeChildren() { + boolean changed = false; + Map temp = new HashMap(); + for (Iterator i = this.children.iterator(); i.hasNext(); ) { + TreeNode node = (TreeNode) i.next(); + if (node instanceof SchemaNode) { + temp.put(node.getName(), node); + } + } + + this.children.clear(); + if (this.quickListNode == null) { + this.quickListNode = new QuickListNode(this); + } + if (this.queryListNode == null) { + this.queryListNode = new QueryListNode(this); + } + this.children.add(this.quickListNode); + this.children.add(this.queryListNode); + Bookmark bookmark = getBookmark(); + + Schema[] schemas = bookmark.getSchemas(); + for (int i = 0, length = (schemas == null) ? 0 : schemas.length; + i < length; + i++) { + SchemaNode node = (SchemaNode) temp.remove(schemas[i].getDisplayName()); + if (node == null) { + this.children.add(new SchemaNode(this, schemas[i])); + } else { + changed = true; + this.children.add(node); + } + } + + for (Iterator i = temp.values().iterator(); i.hasNext(); ) { + ((TreeNode) i.next()).dispose(); + changed = true; + } + + if (changed) { + firePropertyChange("children", null, null); + } + } + + public boolean hasChildren() { + // If the bookmark is connected but hasn't loaded the tables and views, we suppose it may have some + if (bookmark.isConnected() && this.children.isEmpty()) { + return true; + } else if (!bookmark.isConnected()) { + return false; + } else if (children != null && children.size() > 0) { + return true; + } + return false; + } + + protected void dispose() { + try { + this.bookmark.removePropertyChangeListener(this); + if (this.bookmark.isConnected()) { + this.bookmark.disconnect(); + } + } catch (ConnectionException e) { + } + } + + /** + * @see com.quantum.model.TreeNode#getName() + */ + public String getName() { + return this.bookmark == null ? "<>" : this.bookmark.getName(); + } + + /** + * @return + */ + public Bookmark getBookmark() { + return this.bookmark; + } + + protected String getImageName() { + return this.bookmark.isConnected() ? "connected.gif" : "bookmarks.gif"; + } + + /* (non-Javadoc) + * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + if ("connected".equals(event.getPropertyName())) { + if (Boolean.FALSE.equals(event.getNewValue())) { + removeAllChildren(); + } + firePropertyChange("connected", event.getOldValue(), event.getNewValue()); + } else if ("schemas".equals(event.getPropertyName())) { + initializeChildren(); + firePropertyChange("children", event.getOldValue(), event.getNewValue()); + } else if ("name".equals(event.getPropertyName())) { + firePropertyChange("name", event.getOldValue(), event.getNewValue()); + } + } + + protected void removeAllChildren() { + if (this.quickListNode != null) { + this.quickListNode.dispose(); + this.quickListNode = null; + } + if (this.queryListNode != null) { + this.queryListNode.dispose(); + this.queryListNode = null; + } + super.removeAllChildren(); + + } + public String getLabelDecorations(LabelDecorationInstructions labelDecorationInstructions) { + if (!labelDecorationInstructions.isDatabaseDataVisible()) { + return null; + } else if (!this.bookmark.isConnected()) { + return null; + } else { + try { + String decoration = this.bookmark.getDatabase().getInformation(); + return decoration == null ? null : "[" + decoration + "]"; + } catch (NotConnectedException e) { + return null; + } catch (SQLException e) { + return null; + } + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkView.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkView.java new file mode 100644 index 0000000..efc055f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkView.java @@ -0,0 +1,269 @@ +package com.quantum.view.bookmark; + + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Vector; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.viewers.IOpenListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.OpenEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.actions.ActionContext; +import org.eclipse.ui.part.ViewPart; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.actions.CustomCopyAction; +import com.quantum.extensions.ExtensionAction; +import com.quantum.extensions.ProcessServiceMembers; + +public class BookmarkView extends ViewPart implements PropertyChangeListener { + private CustomCopyAction customCopyAction1; + private CustomCopyAction customCopyAction2; + private CustomCopyAction customCopyAction3; + private Vector extensionVector; + + private BookmarkViewActionGroup actionGroup; + + private TreeViewer treeViewer; + private BookmarkLabelProvider labelProvider = new BookmarkLabelProvider(); + + /** + * @return - + * The instance of the BookmarkView. There is no guarantee of it being a singleton + * due to the workspace creating a new one (does the workspace call getInstance() ? ). + * It seems to work. + */ + public synchronized static BookmarkView getInstance() { + return (BookmarkView) QuantumPlugin.getDefault().getView("com.quantum.view.bookmarkview"); + } + /** + * Returns the current selected object in the tree. If it's a multiple selection, return the first. + * @return + */ + public Object getCurrent() { + if (treeViewer == null) return null; + return ((StructuredSelection) treeViewer.getSelection()) + .getFirstElement(); + } + /** + * Returns the current selected objects in the tree, in the form of a StructuredSelection. + * @return + */ + public StructuredSelection getSelection() { + if (treeViewer == null) return null; + return ((StructuredSelection) treeViewer.getSelection()); + } + + /** + * Navigates the tree to get the current bookmark (root) of the selected element. + * If it's a multiple selection, it takes the first one. + * @return + */ + public BookmarkNode getCurrentBookmark() { + TreeNode current = (TreeNode) getCurrent(); + return getRoot(current); + } + + private static BookmarkNode getRoot(TreeNode node){ + if (node == null) return null; + if (! (node instanceof TreeNode)) return null; + while (!( node instanceof BookmarkNode)) + { + node = (TreeNode) node.getParent(); + } + if (node instanceof BookmarkNode) return (BookmarkNode) node; + else return null; + + } + public void refresh() { + treeViewer.refresh(); + } + public void createPartControl(org.eclipse.swt.widgets.Composite parent) { + + treeViewer = new TreeViewer( + parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + treeViewer.setContentProvider(new BookmarkContentProvider()); + treeViewer.setLabelProvider(this.labelProvider); + BookmarkListNode input = BookmarkListNode.getInstance(); + treeViewer.setInput(input); + initActions(); + + input.addPropertyChangeListener(this); + + initializePopUpMenu(); + fillActionBars(); + + treeViewer.addOpenListener(new IOpenListener() { + public void open(OpenEvent event) { + ActionContext context = new ActionContext( + getSelection()); + BookmarkView.this.actionGroup.setContext(context); + IAction action = actionGroup.getOpenAction(); + if (action != null) { + action.run(); + } + } + }); + + } + private void fillActionBars() { + Action enableTableSizes = new Action() { + public void run() { + labelProvider.getLabelDecorationInstructions().setSizeVisible(isChecked()); + treeViewer.refresh(); + } + }; + enableTableSizes.setText(Messages.getString("BookmarkView.ShowTableSizes")); //$NON-NLS-1$ + enableTableSizes.setChecked(false); + + IActionBars actionBars = getViewSite().getActionBars(); + actionBars.getMenuManager().add(enableTableSizes); + + Action showDatabaseData = new Action() { + public void run() { + labelProvider.getLabelDecorationInstructions().setDatabaseDataVisible(isChecked()); + treeViewer.refresh(); + } + }; + showDatabaseData.setText(Messages.getString("BookmarkView.ShowDatabaseData")); //$NON-NLS-1$ + showDatabaseData.setChecked(false); + actionBars.getMenuManager().add(showDatabaseData); + + this.actionGroup.fillActionBars(actionBars); + } + + private void initializePopUpMenu() { + MenuManager manager = new MenuManager(); + manager.setRemoveAllWhenShown(true); + manager.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager mgr) { + fillContextMenu(mgr); + } + }); + Menu fTextContextMenu = + manager.createContextMenu(treeViewer.getControl()); + treeViewer.getControl().setMenu(fTextContextMenu); + // register the menu to the site so that we can allow + // actions to be plugged in + getSite().registerContextMenu(manager, this.treeViewer); + } + public void initActions() { + + this.actionGroup = new BookmarkViewActionGroup(this, this.treeViewer); + +// openDataEditorAction = new OpenDataEditorAction(); +// openDataEditorAction.setText("Edit Data"); +// openDataEditorAction.setImageDescriptor( +// QuantumPlugin.getImageDescriptor("greentable.gif")); //$NON-NLS-1$ +// openDataEditorAction.init(this); + + IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore(); + this.customCopyAction1 = new CustomCopyAction(this,1); // 1 is unused, just in case more custom copies are defined + this.customCopyAction1.setText(store.getString("customCopyName1")); //$NON-NLS-1$ + this.customCopyAction1.setImageDescriptor( + QuantumPlugin.getImageDescriptor("copy.gif")); //$NON-NLS-1$ + this.customCopyAction2 = new CustomCopyAction(this,2); // 1 is unused, just in case more custom copies are defined + this.customCopyAction2.setText(store.getString("customCopyName2")); //$NON-NLS-1$ + this.customCopyAction2.setImageDescriptor( + QuantumPlugin.getImageDescriptor("copy.gif")); //$NON-NLS-1$ + this.customCopyAction3 = new CustomCopyAction(this,3); // 1 is unused, just in case more custom copies are defined + this.customCopyAction3.setText(store.getString("customCopyName3")); //$NON-NLS-1$ + this.customCopyAction3.setImageDescriptor( + QuantumPlugin.getImageDescriptor("copy.gif")); //$NON-NLS-1$ + + extensionVector = new Vector(); + try { + ProcessServiceMembers.process(this, extensionVector); + } catch (WorkbenchException e) { + e.printStackTrace(); + } + + } + + public void dispose(){ + super.dispose(); + BookmarkListNode.getInstance().removePropertyChangeListener(this); + } + + public Shell getShell() { + return getSite().getShell(); + } + + /** + * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + if ("bookmarks".equals(event.getPropertyName())) { + refresh(); + } else if ("name".equals(event.getPropertyName()) && + event.getSource() instanceof BookmarkNode) { + refresh(); + } else if ("connected".equals(event.getPropertyName())) { + treeViewer.refresh(event.getSource()); + if (Boolean.TRUE.equals(event.getNewValue())) { + treeViewer.setExpandedState(event.getSource(), true); + } + } else { + treeViewer.refresh(event.getSource()); + } + } + + private void fillContextMenu(IMenuManager mgr) { + // TODO: this method is pretty barfy... make it cleaner + + IStructuredSelection selection = getSelection(); + ActionContext context = new ActionContext(selection); + this.actionGroup.setContext(context); + this.actionGroup.fillContextMenu(mgr); + + Object sel = getCurrent(); + // If selection is a BookmarkNode + if (sel instanceof EntityNode) { + EntityNode entityNode = (EntityNode) sel; + if (!entityNode.isSequence()) { + mgr.add(new Separator()); + MenuManager subMenu = new MenuManager(Messages.getString("bookmarkview.customCopyAction")); + subMenu.add(customCopyAction1); + subMenu.add(customCopyAction2); + subMenu.add(customCopyAction3); + mgr.add(subMenu); + + MenuManager subMenuExtension = new MenuManager("Extensions"); + for (int i = 0; i < extensionVector.size(); i++) { + ExtensionAction extensionAction = (ExtensionAction) extensionVector.get(i); + subMenuExtension.add(extensionAction); + } + if (extensionVector.size() > 0) mgr.add(subMenuExtension); + } + } else if (sel instanceof ColumnNode) { + MenuManager subMenu = new MenuManager(Messages.getString("bookmarkview.customCopyAction")); + subMenu.add(customCopyAction1); + subMenu.add(customCopyAction2); + subMenu.add(customCopyAction3); + mgr.add(subMenu); + + } + } + /** + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + public void setFocus() { + } + + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkViewActionGroup.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkViewActionGroup.java new file mode 100644 index 0000000..9293770 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/BookmarkViewActionGroup.java @@ -0,0 +1,266 @@ +package com.quantum.view.bookmark; + +import java.util.Iterator; + +import com.quantum.QuantumPlugin; +import com.quantum.actions.AddToQuickListAction; +import com.quantum.actions.ConnectAction; +import com.quantum.actions.DeleteAllRowsAction; +import com.quantum.actions.DeleteBookmarkAction; +import com.quantum.actions.DisconnectAction; +import com.quantum.actions.NewBookmarkAction; +import com.quantum.actions.NextSequenceAction; +import com.quantum.actions.OpenQueryAction; +import com.quantum.actions.PrevSequenceAction; +import com.quantum.actions.RefreshBookmarkAction; +import com.quantum.actions.RemoveFromQuickListAction; +import com.quantum.actions.ViewTableAction; +import com.quantum.actions.ViewTableDetailsAction; +import com.quantum.model.Bookmark; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.actions.ActionGroup; +import org.eclipse.ui.actions.ExportResourcesAction; +import org.eclipse.ui.actions.SelectionListenerAction; +import org.eclipse.ui.actions.SelectionProviderAction; +import org.eclipse.ui.dialogs.PropertyDialogAction; + +/** + * @author BC + */ +public class BookmarkViewActionGroup extends ActionGroup + implements BookmarkClipboard { + + private Bookmark bookmarkClipboard; + + private Action newBookmarkAction; + + // bookmark node actions + private SelectionListenerAction connectAction; + private SelectionListenerAction disconnectAction; + private SelectionListenerAction deleteBookmarkAction; + + // Query node actions + private SelectionListenerAction openQueryAction; + + // Entity node actions + private SelectionListenerAction addToQuickListAction; + private SelectionListenerAction removeFromQuickListAction; + private SelectionListenerAction viewTableAction; + private SelectionListenerAction addSchemaAction; + private SelectionListenerAction viewTableDetailsAction; + + private SelectionListenerAction nextSequenceAction; + private SelectionListenerAction previousSequenceAction; + + + // other actions + private SelectionListenerAction refreshAction; + private SelectionListenerAction renameAction; + + private ExportResourcesAction exportAction; + + + private SelectionProviderAction propertiesAction; + + private SelectionListenerAction copyAction; + private SelectionListenerAction pasteAction; + private SelectionListenerAction deleteAllRowsAction; + + private IViewPart viewPart; + + public BookmarkViewActionGroup( + IViewPart viewPart, ISelectionProvider selectionProvider) { + this.viewPart = viewPart; + + this.newBookmarkAction = new NewBookmarkAction(this.viewPart); + + // bookmark actions + this.connectAction = new ConnectAction(this.viewPart); + this.disconnectAction = new DisconnectAction(this.viewPart); + this.deleteBookmarkAction = new DeleteBookmarkAction(this.viewPart); + + // entity actions + this.previousSequenceAction = new PrevSequenceAction(this.viewPart); + this.nextSequenceAction = new NextSequenceAction(this.viewPart); + this.addToQuickListAction = new AddToQuickListAction(this.viewPart); + this.removeFromQuickListAction = new RemoveFromQuickListAction(this.viewPart); + this.deleteAllRowsAction = new DeleteAllRowsAction(this.viewPart); + this.viewTableDetailsAction = new ViewTableDetailsAction(this.viewPart); + + this.openQueryAction = new OpenQueryAction(this.viewPart); + + this.viewTableAction = new ViewTableAction(this.viewPart); + this.addSchemaAction = new AddSchemaAction(this.viewPart); + this.refreshAction = new RefreshBookmarkAction(this.viewPart); + this.renameAction = new RenameAction(this.viewPart); + this.copyAction = new CopyAction(this.viewPart, this, selectionProvider); + this.pasteAction = new PasteAction(this.viewPart, this, selectionProvider); + this.exportAction = new ExportResourcesAction( + this.viewPart.getViewSite().getWorkbenchWindow()); + this.exportAction.setImageDescriptor(QuantumPlugin.getImageDescriptor("export.gif")); + + this.propertiesAction = new PropertyDialogAction( + this.viewPart.getSite().getShell(), selectionProvider); + } + + + /** + * @see org.eclipse.ui.actions.ActionGroup#fillContextMenu(org.eclipse.jface.action.IMenuManager) + */ + public void fillContextMenu(IMenuManager menu) { + + menu.add(this.newBookmarkAction); + menu.add(new Separator()); + + if (getStructuredSelection().size() > 0 && + isEverySelectionInstanceof(BookmarkNode.class)) { + + addToMenu(menu, this.connectAction); + addToMenu(menu, this.disconnectAction); + } + + menu.add(new Separator()); + menu.add(this.copyAction); + // TODO: paste needs to change enablement whenever something is added + // to the clipboard + addToMenu(menu, this.pasteAction); + addToMenu(menu, this.deleteBookmarkAction); + + if (getStructuredSelection().size() == 1 && + isEverySelectionInstanceof(BookmarkNode.class)) { + + addToMenu(menu, this.renameAction); + } + + menu.add(new Separator()); + + // NOTE: In Eclipse 3.0.0 M6, Export is no longer a sub-class of + // SelectionListenerAction. + this.exportAction.selectionChanged(getStructuredSelection()); + menu.add(this.exportAction); + + if (getStructuredSelection().size() == 1 && + isEverySelectionInstanceof(BookmarkNode.class)) { + + menu.add(new Separator()); + addToMenu(menu, this.addSchemaAction); + } + + if (isEverySelectionInstanceof(QueryNode.class)) { + if (getStructuredSelection().size() == 1) { + addToMenu(menu, this.openQueryAction); + } + } + + if (getStructuredSelection().size() > 0 && + isEverySelectionInstanceof(EntityNode.class)) { + + menu.add(new Separator()); + + if (getStructuredSelection().size() == 1) { + if (((EntityNode) getStructuredSelection().getFirstElement()).isSequence()) { + addToMenu(menu, this.nextSequenceAction); + addToMenu(menu, this.previousSequenceAction); + } else { + addToMenu(menu, this.viewTableAction); + addToMenu(menu, this.deleteAllRowsAction); + addToMenu(menu, this.viewTableDetailsAction); + } + } + + addToMenu(menu, this.addToQuickListAction); + addToMenu(menu, this.removeFromQuickListAction); + } + + if (getStructuredSelection().size() == 1) { + menu.add(new Separator()); + addToMenu(menu, this.refreshAction); + } + + createMarkerForActionsProvidedByOtherPlugins(menu); + + if (getStructuredSelection().size() == 1) { + addToMenu(menu, this.propertiesAction); + } + + } + + private void addToMenu(IMenuManager menu, SelectionListenerAction action) { + action.selectionChanged(getStructuredSelection()); + menu.add(action); + } + + private void addToMenu(IMenuManager menu, SelectionProviderAction action) { + action.selectionChanged(getStructuredSelection()); + menu.add(action); + } + + + private IStructuredSelection getStructuredSelection() { + return (IStructuredSelection) getContext().getSelection(); + } + + private boolean isEverySelectionInstanceof(Class selectedClass) { + boolean result = true; + IStructuredSelection selection = getStructuredSelection(); + for (Iterator i = selection.iterator(); result && i.hasNext(); ) { + Object object = i.next(); + result &= selectedClass.isAssignableFrom(object.getClass()); + } + + return result; + } + + public IAction getOpenAction() { + if (isEverySelectionInstanceof(BookmarkNode.class)) { + this.connectAction.selectionChanged(getStructuredSelection()); + return this.connectAction.isEnabled() ? this.connectAction : null; + } else if (isEverySelectionInstanceof(EntityNode.class)) { + this.viewTableAction.selectionChanged(getStructuredSelection()); + return this.viewTableAction.isEnabled() ? this.viewTableAction : null; + } else if (isEverySelectionInstanceof(QueryNode.class)) { + this.openQueryAction.selectionChanged(getStructuredSelection()); + return this.openQueryAction.isEnabled() ? this.openQueryAction : null; + } else { + return null; + } + } + + private void createMarkerForActionsProvidedByOtherPlugins(IMenuManager mgr) { + mgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + mgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS + "-end")); //$NON-NLS-1$ + mgr.add(new Separator()); + } + public void fillActionBars(IActionBars actionBars) { + IToolBarManager toolBar = actionBars.getToolBarManager(); + toolBar.add(this.newBookmarkAction); + + actionBars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, this.copyAction); + } + + + /* (non-Javadoc) + * @see com.quantum.view.bookmark.BookmarkClipboard#setBookmark(com.quantum.model.Bookmark) + */ + public void setBookmark(Bookmark bookmark) { + this.bookmarkClipboard = bookmark; + } + + + /* (non-Javadoc) + * @see com.quantum.view.bookmark.BookmarkClipboard#getBookmark() + */ + public Bookmark getBookmark() { + return this.bookmarkClipboard; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/ColumnNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/ColumnNode.java new file mode 100644 index 0000000..2894c03 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/ColumnNode.java @@ -0,0 +1,64 @@ +package com.quantum.view.bookmark; + +import com.quantum.model.Column; + +/** + * @author BC + */ +public class ColumnNode extends TreeNode { + + private Column column; + + public ColumnNode(TreeNode parent, Column column) { + super(parent); + this.column = column; + } + + public Object[] getChildren() { + return BookmarkListNode.EMPTY_ARRAY; + } + + public boolean hasChildren() { + return false; + } + + public String getName() { + return this.column.getName(); + } + + protected String getImageName() { + return this.column.isPrimaryKey() ? "keycolumn.gif" : "column.gif"; + } + + public String getLabelName() { + String label = getName() + " : " + this.column.getTypeName(); //$NON-NLS-1$ + if (this.column.isNumeric()) { + if (this.column.getSize() > 0 || this.column.getNumberOfFractionalDigits() > 0) { + label += "(" + Integer.toString(this.column.getSize()); //$NON-NLS-1$ + if (this.column.getNumberOfFractionalDigits() > 0) { + label += "," + Integer.toString(this.column.getNumberOfFractionalDigits()); //$NON-NLS-1$ + } + label += ")"; //$NON-NLS-1$ + } + } else if (this.column.getSize() > 0) { + label += "(" + Integer.toString(this.column.getSize()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } + return label; + } + /* (non-Javadoc) + * @see com.quantum.view.bookmark.TreeNode#initializeChildren() + */ + protected void initializeChildren() { + } + protected boolean isInitialized() { + return true; + } + + /** + * @return + */ + public Column getColumn() { + return column; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/CopyAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/CopyAction.java new file mode 100644 index 0000000..5978426 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/CopyAction.java @@ -0,0 +1,109 @@ +/* + * Created on 11/08/2003 + * + */ +package com.quantum.view.bookmark; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Iterator; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.model.xml.ModelToXMLConverter; +import com.quantum.util.QuantumUtil; +import com.quantum.util.xml.XMLHelper; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + + +final class CopyAction extends SelectionListenerAction { + private IViewPart view; + private BookmarkClipboard bookmarkClipboard; + + /** + * @param BookmarkView + */ + public CopyAction(IViewPart view, BookmarkClipboard bookmarkClipboard, + ISelectionProvider selectionProvider) { + super(Messages.getString(CopyAction.class.getName() + ".text")); + setImageDescriptor(QuantumPlugin.getImageDescriptor("copy.gif")); + this.view = view; + this.bookmarkClipboard = bookmarkClipboard; + selectionProvider.addSelectionChangedListener(this); + } + public void run() { + + List list = getSelectedNonResources(); + Object selection = list.get(0); + + if (selection instanceof BookmarkNode) { + Bookmark bookmark = ((BookmarkNode) selection).getBookmark(); + this.bookmarkClipboard.setBookmark(bookmark); + QuantumPlugin.getDefault().getSysClip().setContents( + new Object[] { bookmark.getName()}, + new Transfer[] { TextTransfer.getInstance()}); + + } else if (selection instanceof EntityNode) { + try { + Document doc = XMLHelper.createEmptyDocument(); + Element root = doc.createElement("metadata"); + doc.appendChild(root); + ModelToXMLConverter.getInstance().convert(root, ((EntityNode) selection).getEntity()); + StringWriter text = new StringWriter(); + try { + XMLHelper.createDOMSerializer(text).serialize(doc); + } catch (IOException e) { + e.printStackTrace(); + } + String textXml = new String(text.getBuffer()); + QuantumPlugin.getDefault().getSysClip().setContents( + new Object[] { textXml }, + new Transfer[] { TextTransfer.getInstance()}); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } + } else if (selection instanceof ColumnNode) { + String copyText = ""; //$NON-NLS-1$ + Iterator iter = list.iterator(); + IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore(); + + while (iter.hasNext()) { + Object current = iter.next(); + if (current instanceof ColumnNode) { + ColumnNode column = (ColumnNode) current; + if (column != null) { + copyText += column.getName(); + if (iter.hasNext()) copyText += QuantumUtil.trasposeEscape(store.getString("copyColumnSeparator")); //$NON-NLS-1$ + } + } + } + + QuantumPlugin.getDefault().getSysClip().setContents( + new Object[] { copyText }, + new Transfer[] { TextTransfer.getInstance()}); + } + + } + /* (non-Javadoc) + * @see org.eclipse.ui.actions.SelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) + */ + protected boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + + return enabled; + } + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/EntityNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/EntityNode.java new file mode 100644 index 0000000..6d5adbe --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/EntityNode.java @@ -0,0 +1,128 @@ +package com.quantum.view.bookmark; + +import com.quantum.model.Column; +import com.quantum.model.Entity; +import com.quantum.model.EntityHolder; +import com.quantum.model.SchemaHolder; +import com.quantum.model.Table; +import com.quantum.model.View; + +/** + * @author BC + */ +public class EntityNode extends TreeNode implements EntityHolder { + + private Entity entity; + private boolean longFormName; + + public EntityNode(TreeNode parent, Entity entity) { + this(parent, entity, false); + } + public EntityNode(TreeNode parent, Entity entity, boolean longFormName) { + super(parent); + this.entity = entity; + this.longFormName = longFormName; + + if (parent instanceof SchemaHolder) { + SchemaHolder schemaHolder = (SchemaHolder) parent; + if (!schemaHolder.getSchema().getDisplayName().equals(entity.getSchema())) { + this.longFormName = true; + } + } + } + + public Object[] getChildren() { + initializeChildren(); + if (this.children.size() > 0) { + return (ColumnNode[]) this.children.toArray(new ColumnNode[this.children.size()]); + } else { + return BookmarkListNode.EMPTY_ARRAY; + } + } + + protected synchronized void initializeChildren() { + this.children.clear(); + Column[] columns = this.entity.getColumns(); + for (int i = 0, length = (columns == null) ? 0 : columns.length; + i < length; + i++) { + this.children.add(new ColumnNode(this, columns[i])); + } + // TODO: fire property change event + } + + public boolean hasChildren() { + if (!isSequence()) { + return true; + } else { + return false; + } + } + + public Entity getEntity() { + return this.entity; + } + + public String getName() { + return this.entity.getName(); + } + + public String getLabelName() { + return (this.longFormName) ? this.entity.getCondQualifiedName() : this.entity.getName(); + } + + public boolean isTable() { + return Entity.TABLE_TYPE.equals(this.entity.getType()); + } + + public boolean isView() { + return Entity.VIEW_TYPE.equals(this.entity.getType()); + } + + public boolean isSequence() { + return Entity.SEQUENCE_TYPE.equals(this.entity.getType()); + } + + protected String getImageName() { + if (isSequence()) { + return "sequence.gif"; + } else if (isView()) { + return "view.gif"; + } else { + return (this.entity.exists() == null || this.entity.exists().booleanValue()) + ? "bigtable.gif" : "missingtable.gif"; + } + } + + public String getLabelDecorations(LabelDecorationInstructions instructions) { + String decoration = null; + if (instructions.isSizeVisible()) { + Integer size = getSize(); + if (size != null) { + decoration = ((decoration == null) ? "" : decoration) + + "[" + size + "]"; + } + } + return decoration; + } + + private Integer getSize() { + if (isTable()) { + return ((Table) this.entity).getSize(); + } else if (isView()) { + return ((View) this.entity).getSize(); + } else { + return null; + } + } + + public int compareTo(Object o) { + if (o instanceof EntityNode) { + EntityNode that = (EntityNode) o; + return this.entity.getCondQualifiedName().compareTo( + that.entity.getCondQualifiedName()); + } else { + return super.compareTo(o); + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/GroupNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/GroupNode.java new file mode 100644 index 0000000..1064faa --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/GroupNode.java @@ -0,0 +1,92 @@ +/* + * Created on 27/06/2003 + * + */ +package com.quantum.view.bookmark; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.quantum.Messages; +import com.quantum.model.Bookmark; +import com.quantum.model.Entity; +import com.quantum.model.Schema; +import com.quantum.model.SchemaHolder; + +/** + * GroupNode represents a level of grouping in the BookmarkView hierarchy + * It will have categories like "TABLE", "VIEW" and so on, usually gotten from + * the JDBC driver. + * + * @author panic + */ +public class GroupNode extends TreeNode implements Comparable, SchemaHolder { + private String type = null; + private Schema schema = null; + + public GroupNode(TreeNode parent, Schema schema, String type) { + super(parent); + this.schema = schema; + this.type = type; + } + public boolean hasChildren() { + if (!isInitialized()) { + return true; + } else { + return !this.children.isEmpty(); + } + } + public Object[] getChildren() { + if (!isInitialized() && getBookmark().isConnected()) { + initializeChildren(); + } + return (TreeNode[]) this.children.toArray(new TreeNode[this.children.size()]); + } + protected void initializeChildren() { + try { + boolean firstTimeInitialization = !isInitialized(); + boolean changed = false; + Map temp = new HashMap(); + for (Iterator i = this.children.iterator(); i.hasNext();) { + TreeNode treeNode = (TreeNode) i.next(); + temp.put(treeNode.getName(), treeNode); + } + this.children.clear(); + + Bookmark bookmark = getBookmark(); + Entity[] entities = bookmark.getEntitiesForSchema(schema, type); + for (int i = 0, + length = (entities == null) ? 0 : entities.length; + i < length; + i++) { + + String name = entities[i].getName(); + EntityNode entityNode = (EntityNode) temp.remove(name); + if (entityNode == null) { + this.children.add(new EntityNode(this, entities[i])); + changed = true; + } else { + this.children.add(entityNode); + } + } + if (changed && !firstTimeInitialization) { + firePropertyChange("children", null, null); + } + } catch (SQLException e) { + } + } + public String getName() { + return Messages.getString(getClass().getName() + "." + this.type); + } + protected String getImageName() { + return "entitygroup.gif"; //$NON-NLS-1$ + } + /** + * @return + */ + public Schema getSchema() { + return schema; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/LabelDecorationInstructions.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/LabelDecorationInstructions.java new file mode 100644 index 0000000..c82df4b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/LabelDecorationInstructions.java @@ -0,0 +1,39 @@ +package com.quantum.view.bookmark; + +/** + *

Label decorations are specified for the entire view

. + * + * @author BC + */ +public class LabelDecorationInstructions { + private boolean sizeVisible = false; + private boolean databaseDataVisible = false; + /** + * @return + */ + public boolean isSizeVisible() { + return sizeVisible; + } + + /** + * @param b + */ + public void setSizeVisible(boolean b) { + sizeVisible = b; + } + + /** + * @return + */ + public boolean isDatabaseDataVisible() { + return databaseDataVisible; + } + + /** + * @param b + */ + public void setDatabaseDataVisible(boolean b) { + databaseDataVisible = b; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/PasteAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/PasteAction.java new file mode 100644 index 0000000..a7bf476 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/PasteAction.java @@ -0,0 +1,46 @@ +package com.quantum.view.bookmark; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.model.BookmarkCollection; + +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + + +final class PasteAction extends SelectionListenerAction { + private IViewPart view; + private BookmarkClipboard bookmarkClipboard; + /** + * @param BookmarkView + */ + public PasteAction(IViewPart view, BookmarkClipboard bookmarkClipboard, + ISelectionProvider selectionProvider) { + super(Messages.getString(PasteAction.class.getName() + ".text")); + setImageDescriptor(QuantumPlugin.getImageDescriptor("paste.gif")); + this.view = view; + selectionProvider.addSelectionChangedListener(this); + this.bookmarkClipboard = bookmarkClipboard; + } + public void run() { + if (this.bookmarkClipboard.getBookmark() != null) { + Bookmark bookmark = new Bookmark(this.bookmarkClipboard.getBookmark()); + String copyName = BookmarkCollection.getInstance().getCopyName(bookmark.getName()); + bookmark.setName(copyName); //$NON-NLS-1$ + BookmarkCollection.getInstance().addBookmark(bookmark); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.actions.SelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) + */ + protected boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + enabled &= this.bookmarkClipboard.getBookmark() != null; + return enabled; + } + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QueryListNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QueryListNode.java new file mode 100644 index 0000000..eb8b173 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QueryListNode.java @@ -0,0 +1,76 @@ +package com.quantum.view.bookmark; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import com.quantum.Messages; + +/** + * @author BC + */ +public class QueryListNode extends TreeNode implements PropertyChangeListener { + + /** + * @param parent + */ + public QueryListNode(TreeNode parent) { + super(parent); + getBookmark().addPropertyChangeListener(this); + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getChildren() + */ + public Object[] getChildren() { + initializeChildren(); + return (TreeNode[]) this.children.toArray(new TreeNode[this.children.size()]); + } + + protected void initializeChildren() { + this.children.clear(); + String[] queries = getBookmark().getQueries(); + for (int i = 0, length = (queries == null) ? 0 : queries.length; + i < length; + i++) { + this.children.add(new QueryNode(this, queries[i])); + } + } + + /** + * @see com.quantum.view.bookmark.TreeNode#hasChildren() + */ + public boolean hasChildren() { + return getBookmark().getQueries().length > 0; + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getName() + */ + public String getName() { + return Messages.getString(getClass().getName() + ".labelName"); + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getImageName() + */ + protected String getImageName() { + return "group.gif"; + } + + /** + * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + if ("queries".equals(event.getPropertyName())) { + firePropertyChange("queries", null, null); + } + } + /** + * @see com.quantum.view.bookmark.TreeNode#dispose() + */ + protected void dispose() { + getBookmark().removePropertyChangeListener(this); + super.dispose(); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QueryNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QueryNode.java new file mode 100644 index 0000000..4826003 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QueryNode.java @@ -0,0 +1,64 @@ +package com.quantum.view.bookmark; + +import com.quantum.sql.metadata.ObjectMetaData; + +public class QueryNode extends TreeNode { + + private String query; + private static final int MAX_SIZE = 30; + + public QueryNode(TreeNode parent, String query) { + super(parent); + this.query = query; + } + + public ObjectMetaData getMetaData() { + return null; //no metadata implementation for now + } + + public String getQuery() { + return this.query; + } + + public String getName() { + String name = this.query.trim(); + boolean trimmed = false; + name = name.replace('\n', ' '); + + if (name.length() > MAX_SIZE) { + name = name.substring(0, MAX_SIZE); + trimmed = true; + } + if (trimmed) { + name += "...->"; //$NON-NLS-1$ + } + return name; + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getChildren() + */ + public Object[] getChildren() { + return BookmarkListNode.EMPTY_ARRAY; + } + + /** + * @see com.quantum.view.bookmark.TreeNode#hasChildren() + */ + public boolean hasChildren() { + return false; + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getImageName() + */ + protected String getImageName() { + return "script.gif"; + } + + /* (non-Javadoc) + * @see com.quantum.view.bookmark.TreeNode#initializeChildren() + */ + protected void initializeChildren() { + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QuickListNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QuickListNode.java new file mode 100644 index 0000000..9e74ef5 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/QuickListNode.java @@ -0,0 +1,98 @@ +package com.quantum.view.bookmark; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import com.quantum.Messages; +import com.quantum.model.Bookmark; +import com.quantum.model.Entity; + +/** + *

A "quick list" is a set of favourite entities that a user may want + * to work with without having to sift through the (somtimes lengthy) longer + * list of tables.

+ * + * @author bcholmes + */ +public class QuickListNode extends TreeNode implements PropertyChangeListener { + + private Map children = new Hashtable(); + + /** + * @param parent + */ + public QuickListNode(BookmarkNode parent) { + super(parent); + + Bookmark bookmark = getBookmark(); + bookmark.addPropertyChangeListener(this); + } + + /** + * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + if ("quickList".equals(event.getPropertyName())) { + initializeChildren(); + firePropertyChange("quickList", null, null); + } + } + + /** + * @see com.quantum.view.bookmark.TreeNode#hasChildren() + */ + public boolean hasChildren() { + return getBookmark().hasQuickList(); + } + /** + * @see com.quantum.view.bookmark.TreeNode#getImageName() + */ + protected String getImageName() { + return "group.gif"; + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getChildren() + */ + public Object[] getChildren() { + Bookmark bookmark = getBookmark(); + if (children.isEmpty() && bookmark.hasQuickList()) { + initializeChildren(); + } + List list = new ArrayList(this.children.values()); + Collections.sort(list); + + return (TreeNode[]) list.toArray(new TreeNode[list.size()]); + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getName() + */ + public String getName() { + return Messages.getString(QuickListNode.class.getName() + ".labelName"); + } + + protected synchronized void initializeChildren() { + this.children.clear(); + Entity[] entities = getBookmark().getQuickListEntries(); + for (int i = 0, length = (entities == null) ? 0 : entities.length; + i < length; + i++) { + + this.children.put(entities[i].getCondQualifiedName(), + new EntityNode(this, entities[i], true)); + } + } + /* (non-Javadoc) + * @see com.quantum.view.bookmark.TreeNode#isInitialized() + */ + protected boolean isInitialized() { + return true; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/RenameAction.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/RenameAction.java new file mode 100644 index 0000000..175c68a --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/RenameAction.java @@ -0,0 +1,52 @@ +package com.quantum.view.bookmark; + +import com.quantum.Messages; +import com.quantum.model.Bookmark; + +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + * @author BC + */ +public class RenameAction extends SelectionListenerAction { + + private IViewPart viewPart; + + /** + * @param text + */ + protected RenameAction(IViewPart viewPart) { + super(Messages.getString(RenameAction.class.getName() + ".text")); + this.viewPart = viewPart; + } + + + + /** + * @see org.eclipse.ui.actions.SelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) + */ + protected boolean updateSelection(IStructuredSelection selection) { + boolean enabled = super.updateSelection(selection); + return enabled & selection.size() == 1 & + selection.getFirstElement() instanceof BookmarkNode; + } + + private Bookmark getBookmark() { + return ((BookmarkNode) getSelectedNonResources().get(0)).getBookmark(); + } + + /** + * @see org.eclipse.jface.action.IAction#run() + */ + public void run() { + InputDialog dialog = new InputDialog(this.viewPart.getSite().getShell(), "Select a new name", + "Name: ", getBookmark().getName(), null); + int result = dialog.open(); + if (result == InputDialog.OK) { + getBookmark().setName(dialog.getValue()); + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/SchemaNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/SchemaNode.java new file mode 100644 index 0000000..6b44cda --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/SchemaNode.java @@ -0,0 +1,81 @@ +package com.quantum.view.bookmark; + +import java.sql.SQLException; + +import com.quantum.model.Bookmark; +import com.quantum.model.NotConnectedException; +import com.quantum.model.Schema; +import com.quantum.model.SchemaHolder; + +/** + * @author BC + */ +public class SchemaNode extends TreeNode implements SchemaHolder { + + private Schema schema; + /** + * @param parent + */ + public SchemaNode(TreeNode parent, Schema schema) { + super(parent); + this.schema = schema; + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getChildren() + */ + public Object[] getChildren() { + Bookmark bookmark = getBookmark(); + if (!bookmark.isConnected()) { + return BookmarkListNode.EMPTY_ARRAY; + } else { + if (this.children.isEmpty()) { + initializeChildren(); + } + } + return (TreeNode[]) this.children.toArray(new TreeNode[this.children.size()]); + } + + protected void initializeChildren() { + this.children.clear(); + Bookmark bookmark = getBookmark(); + try { + String[] types = bookmark.getDatabase().getEntityTypes(); + for (int i = 0, length = (types == null) ? 0 : types.length; + i < length; + i++) { + this.children.add(new GroupNode(this, this.schema, types[i])); + } + } catch (NotConnectedException e) { + } catch (SQLException e) { + } + } + + /** + * @see com.quantum.view.bookmark.TreeNode#hasChildren() + */ + public boolean hasChildren() { + return getBookmark().isConnected(); + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getName() + */ + public String getName() { + return this.schema.getDisplayName(); + } + + /** + * @see com.quantum.view.bookmark.TreeNode#getImageName() + */ + protected String getImageName() { + return this.schema.isDefault() ? "user.gif" : "schema.gif"; + } + + /** + * @see com.quantum.model.SchemaHolder#getSchema() + */ + public Schema getSchema() { + return this.schema; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/TreeNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/TreeNode.java new file mode 100644 index 0000000..1d18d38 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/bookmark/TreeNode.java @@ -0,0 +1,124 @@ +package com.quantum.view.bookmark; + +import java.beans.PropertyChangeEvent; +import java.util.Iterator; +import java.util.Vector; + +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.model.BookmarkHolder; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.swt.graphics.Image; + +/** + * Base class for all nodes of the internal tree of data. Basically allows navigation. + * @author root + */ +public abstract class TreeNode + implements BookmarkHolder, Comparable, IAdaptable { + + private TreeNode parent = null; + protected Vector children = new Vector(); + private boolean disposed = false; + + public TreeNode(TreeNode parent) { + this.parent = parent; + } + + public abstract Object[] getChildren(); + public TreeNode getParent() { + return this.parent; + } + public abstract boolean hasChildren(); + public abstract String getName(); + + public Bookmark getBookmark() { + return getParent().getBookmark(); + } + + public String getLabelName() { + return getName(); + } + + /** + * @return an Image object to appear in the view, null if not found + */ + public Image getImage() { + return QuantumPlugin.getImage(getImageName()); + } + + /** + * @return + */ + protected abstract String getImageName(); + + + /** + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(Object object) { + TreeNode that = (TreeNode) object; + return this.getLabelName().compareTo(that.getLabelName()); + } + + public String toString() { + return getLabelName(); + } + + public String getLabelDecorations(LabelDecorationInstructions labelDecorationInstructions) { + return null; + } + /** + * @param propertyName + * @param oldValue + * @param newValue + */ + protected void firePropertyChange( + String propertyName, + Object oldValue, + Object newValue) { + + firePropertyChange(new PropertyChangeEvent(this, propertyName, oldValue, newValue)); + } + + /** + * @param propertyName + * @param oldValue + * @param newValue + */ + protected void firePropertyChange(PropertyChangeEvent event) { + TreeNode parent = getParent(); + if (parent != null && !this.disposed) { + parent.firePropertyChange(event); + } + } + + protected void dispose() { + this.disposed = true; + removeAllChildren(); + } + protected void removeAllChildren() { + for (Iterator i = this.children.iterator(); i.hasNext();) { + TreeNode element = (TreeNode) i.next(); + element.dispose(); + } + } + + protected boolean isInitialized() { + return !this.children.isEmpty(); + } + + public Object getAdapter(Class adapter) { + return null; + } + protected abstract void initializeChildren(); + public void reload() { + if (isInitialized()) { + initializeChildren(); + for (Iterator i = this.children.iterator(); i.hasNext(); ) { + ((TreeNode) i.next()).reload(); + } + } + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/EntitySubset.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/EntitySubset.java new file mode 100644 index 0000000..0b70c9d --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/EntitySubset.java @@ -0,0 +1,86 @@ +package com.quantum.view.subset; + +import java.sql.SQLException; + +import com.quantum.model.Bookmark; +import com.quantum.model.BookmarkCollection; +import com.quantum.model.Column; +import com.quantum.model.Entity; +import com.quantum.model.Index; +import com.quantum.model.Schema; + +/** + * @author BC + */ +public class EntitySubset implements Entity { + + private String name; + private String schema; + private String bookmarkName; + + public EntitySubset(String name, String schema, String bookmarkName) { + this.name = name; + this.schema = schema; + this.bookmarkName = bookmarkName; + } + + public String getName() { + return this.name; + } + + public String getSchema() { + return schema; + } + + public String getType() { + return null; + } + + public Column[] getColumns() { + // TODO: limit the columns + Entity relatedEntity = getEntityFromBookmark(); + if (relatedEntity != null) { + Column[] columns = relatedEntity.getColumns(); + return columns; + } else { + return null; + } + } + + public Index[] getIndexes() { + return new Index[0]; + } + + public Column getColumn(String columnName) { + Entity relatedEntity = getEntityFromBookmark(); + return relatedEntity == null + ? null : relatedEntity.getColumn(columnName); + } + + public String getCondQualifiedName() { + return this.schema + "." + this.name; + } + + public Boolean exists() { + return null; + } + + public Bookmark getBookmark() { + return BookmarkCollection.getInstance().find(this.bookmarkName); + } + + private Entity getEntityFromBookmark() { + try { + return getBookmark().getEntity( + new Schema(schema), name); + } catch (SQLException e) { + return null; + } + } + /** + * @see com.quantum.model.Entity#getQuotedTableName() + */ + public String getQuotedTableName() { + return getBookmark().getAdapter().filterTableName(getCondQualifiedName()); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/ObjectNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/ObjectNode.java new file mode 100644 index 0000000..149135f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/ObjectNode.java @@ -0,0 +1,167 @@ +package com.quantum.view.subset; + +import com.quantum.IQuantumConstants; +import com.quantum.Messages; +import com.quantum.model.Entity; +import com.quantum.model.EntityHolder; +import com.quantum.sql.metadata.MetaDataXMLInterface; +import com.quantum.sql.metadata.ObjectMetaData; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Defines a node for the Subset. It contains an editable ObjectMetaData + * where you can erase columns you are not interested in. + * @author jparrai + * + */ +public class ObjectNode implements Comparable, EntityHolder { + private SubsetNode parent = null; + private ObjectMetaData metadata = null; + private int order = 0; + private Entity entity; + + public ObjectNode(SubsetNode parent, ObjectMetaData metadata, String bookmark, String name, String schema) { + this.parent = parent; + this.metadata = metadata; + this.entity = new EntitySubset(name, schema, bookmark); + } + + public ObjectNode(){ + } + public String getType(){ + return IQuantumConstants.View; + } + + /* (non-Javadoc) + * @see com.quantum.view.bookmark.TreeNode#getChildren() + * We consider the columns of the metadata to be the children. + */ + public Object[] getChildren() { +// if (metadata != null && ColumnMetaData.getColumnsMetaDataNode(metadata, this) != null) { +// return ColumnMetaData.getColumnsMetaDataNode(metadata, this).toArray(); +// } else { + return SubsetRoot.EMPTY_ARRAY; +// } + } + + public Object getParent() { + return parent; + } + + public boolean hasChildren() { +// if (metadata == null) return false; +// return (ColumnMetaData.getColumnsMetaDataNode(metadata, this) != null && +// ColumnMetaData.getColumnsMetaDataNode(metadata, this).size() > 0); + return false; + } + + public String getName() { + return this.entity.getName(); + } + + public String toString() { + return getName(); + } + + public int compareTo(Object o) { + if (o instanceof ObjectNode) { + ObjectNode node = (ObjectNode) o; + if (node.getOrder() > getOrder()) return -1; + if (node.getOrder() < getOrder()) return 1; + // If the order is the same, we use alphabetical order + return getEntity().getCondQualifiedName().compareTo( + node.getEntity().getCondQualifiedName()); + } else throw new ClassCastException(); + } + + public void setObjectMetadata(ObjectMetaData metadata) { + this.metadata = metadata; + } + /** + * @return + */ + public ObjectMetaData getMetaData() { + return metadata; + } + + /** + * @return The order of this ObjectNode inside the SubsetNode + */ + public int getOrder() { + return order; + } + /** + * Sets an ordering (inside the SubsetNode) to the ObjectNode + * @param i + */ + public void setOrder(int i) { + order = i; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (!(obj instanceof ObjectNode)) return false; + return (getEntity().getCondQualifiedName().equals( + ((ObjectNode) obj).getEntity().getCondQualifiedName())); + } + + /** + * Imports one ObjectNode from an XMLDocument. There must be a tag for the Table Name, another for the Bookmark + * name and other for the metadata. The complement function is exportXML() + * @param root Document to get the data from + * @param parent The SubsetNode to which to add the new ObjectNode + * @return The newly created ObjectNode, or null if some error. + */ + public static ObjectNode importXML(Element root, SubsetNode parent){ + // Get the name tag value into objName + String objName = MetaDataXMLInterface.getElementText(root, Messages.getString("ExportXMLAction.TableName")); //$NON-NLS-1$ + String objSchema = MetaDataXMLInterface.getElementText(root, Messages.getString("ExportXMLAction.SchemaName")); //$NON-NLS-1$ + if (objName == "") return null; //$NON-NLS-1$ + // Get the bookmark tag value into objName + String bookmarkName = MetaDataXMLInterface.getElementText(root, Messages.getString("ExportXMLAction.BookmarkName")); //$NON-NLS-1$ + if (bookmarkName == "") return null; //$NON-NLS-1$ + ObjectMetaData metadata = new ObjectMetaData(); + // The rest of the tags go to be the metadata + MetaDataXMLInterface.xmlToMetaData(metadata, root); + // We can finally create the new ObjectNode with the collected data + ObjectNode objectNode = new ObjectNode(parent, metadata, bookmarkName, objName, objSchema); + return objectNode; + } + + /** + * Exports an ObjectNode to an XMLDocument. The complement function is importXML() + * @param root Document to write the XML tags to + */ + public void exportXML(Element root){ + Document doc = root.getOwnerDocument(); + Element sub = (Element) root.appendChild(doc.createElement(Messages.getString("ExportXMLAction.Table"))); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(sub,Messages.getString("ExportXMLAction.TableName"), getEntity().getName()); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(sub,Messages.getString("ExportXMLAction.SchemaName"), getEntity().getSchema()); //$NON-NLS-1$ + MetaDataXMLInterface.createElementText(sub,Messages.getString("ExportXMLAction.BookmarkName"), getEntity().getBookmark().getName()); //$NON-NLS-1$ + if (this.metadata != null) + MetaDataXMLInterface.metaDataToXML(this.metadata, doc, sub); + } + + /** + * Generates a query with all the columns in the metadata of the ObjectNode. + * "SELECT *" would not be valid because you can have less columns in the ObjectNode than in the table or view. + * @return String with the Query + */ + public String getQuery() { + String result = new String(""); //$NON-NLS-1$ + result = "SELECT " + metadata.getColumnsString() + " FROM " + getEntity().getCondQualifiedName(); //$NON-NLS-1$ //$NON-NLS-2$ + return result; + } + + /** + * @see com.quantum.model.EntityHolder#getEntity() + */ + public Entity getEntity() { + return this.entity; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetContentProvider.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetContentProvider.java new file mode 100644 index 0000000..dd8133b --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetContentProvider.java @@ -0,0 +1,158 @@ +package com.quantum.view.subset; + +import java.util.Vector; + +import com.quantum.Messages; +import com.quantum.sql.metadata.MetaDataXMLInterface; +import com.quantum.view.bookmark.ColumnNode; +import com.quantum.view.bookmark.TreeNode; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class SubsetContentProvider implements ITreeContentProvider { + private Vector subsets = new Vector(); + private static SubsetContentProvider instance = null; + private boolean hasChanged = false; + + /** + * Singleton accessor + */ + public static synchronized SubsetContentProvider getInstance() { + if (instance == null) { + instance = new SubsetContentProvider(); + } + return instance; + } + + private SubsetContentProvider() { + } + + public void exportXML(Element root) { + System.out.println("Subsets: Saving to Element"); //$NON-NLS-1$ + Element subsetRoot = MetaDataXMLInterface.createElementText(root,Messages.getString("ExportXMLAction.Subsets"), ""); //$NON-NLS-1$ //$NON-NLS-2$ + for (int i = 0; i < subsets.size(); i++) { + SubsetNode current = (SubsetNode) subsets.get(i); + current.exportXML(subsetRoot); + } + } + + /** + * Imports the data from an XML file to the tree. Does not set the tree to + * changed because it's usually invoked from the initial import routine. + * @param root + */ + public void importXML(Element root){ + System.out.println("Bookmarks: Loading from Element"); //$NON-NLS-1$ + Vector newSubsets = new Vector(); + NodeList nodes = root.getElementsByTagName(Messages.getString("ExportXMLAction.Subset")); //$NON-NLS-1$ + for (int i = 0; i < nodes.getLength(); i++) { + SubsetNode subset = new SubsetNode(); + Element node = (Element) nodes.item(i); + subset.importXML(node,true); + newSubsets.add(subset); + } + subsets = newSubsets; + } + + + public Object[] getChildren(Object parentElement) { + if (parentElement.equals(SubsetRoot.ROOT)) { + return subsets.toArray(); + } else if (parentElement instanceof TreeNode) { + TreeNode node = (TreeNode) parentElement; + return node.getChildren(); + } + return SubsetRoot.EMPTY_ARRAY; + } + + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + public Object getParent(Object element) { + if (element.equals(SubsetRoot.ROOT)) { + return null; + } else if (element instanceof TreeNode) { + TreeNode node = (TreeNode) element; + return node.getParent(); + } + return null; + } + + public boolean hasChildren(Object element) { + if (element.equals(SubsetRoot.ROOT)) { + return true; + } else if (element instanceof TreeNode) { + TreeNode node = (TreeNode) element; + return node.hasChildren(); + } + return false; + } + + public void setChildren(SubsetNode b, Vector tables) { + b.setChildren(tables); + } + + public void addSubset(SubsetNode b) { + hasChanged = true; + if (!subsets.contains(b)) { + subsets.addElement(b); + } + } + public void removeSubset(SubsetNode b) { + hasChanged = true; + if (subsets.contains(b)) { + subsets.removeElement(b); + } + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public void dispose() { + } + + public boolean hasChanged() { + return hasChanged; + } + + public int getSize() { + return subsets.size(); + } + + /** + * @param b + */ + public void setHasChanged(boolean b) { + hasChanged = b; + } + + /** + * @param column + */ + public void deleteColumn(ColumnNode column) { + // TODO: reinstate this +// TreeNode node = (TreeNode) column.getParent(); +// if (!(node instanceof HasMetaData)) return; +// ObjectMetaData metadata = ((HasMetaData)node).getMetaData(); +// if (metadata == null) return; +// metadata.dropColumn(column.getName()); +// setHasChanged(true); +// + } + + /** + * @param object + */ + public void deleteObject(ObjectNode object) { + SubsetNode node = (SubsetNode) object.getParent(); + if (!(node instanceof SubsetNode)) return; + node.remove(object); + setHasChanged(true); + + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetLabelProvider.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetLabelProvider.java new file mode 100644 index 0000000..2f64f53 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetLabelProvider.java @@ -0,0 +1,61 @@ +package com.quantum.view.subset; + +import com.quantum.view.bookmark.TreeNode; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.swt.graphics.Image; + +/** + * @author root + * + * Implements the ILabelProvider for the Bookmarks. + */ +public class SubsetLabelProvider implements ILabelProvider { + /** + * @see org.eclipse.jface.viewers.ILabelProvider#getImage(Object) + */ + public Image getImage(Object element) { + if (element instanceof TreeNode) { + return ((TreeNode) element).getImage(); + } else { + return null; + } + } + + /** + * @see org.eclipse.jface.viewers.ILabelProvider#getText(Object) + */ + public String getText(Object element) { + if (element instanceof TreeNode) { + return ((TreeNode) element).getLabelName(); + } else { + return element.toString(); + } + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(ILabelProviderListener) + */ + public void addListener(ILabelProviderListener listener) { + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() + */ + public void dispose() { + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(Object, String) + */ + public boolean isLabelProperty(Object element, String property) { + return false; + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(ILabelProviderListener) + */ + public void removeListener(ILabelProviderListener listener) { + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetNode.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetNode.java new file mode 100644 index 0000000..8f6c5cf --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetNode.java @@ -0,0 +1,162 @@ +package com.quantum.view.subset; + +import java.util.Collections; +import java.util.Vector; + +import com.quantum.Messages; +import com.quantum.sql.metadata.MetaDataXMLInterface; +import com.quantum.view.bookmark.TreeNode; + +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class SubsetNode extends TreeNode { + private String name = null; + private Vector children = new Vector(); + + public SubsetNode(SubsetNode param) { + super(param.getParent()); + name = param.name; + children.addAll(param.children); + } + + public SubsetNode() { + super(SubsetRoot.ROOT); + } + + public SubsetNode(String name) { + super(SubsetRoot.ROOT); + this.name = name; + } + + public void setName(String name) { + this.name = name; + } + + public String getName(){ + return name; + } + + public Object[] getChildren() { + return children.toArray(); + } + + public boolean hasChildren() { + if (children != null && children.size() > 0) { + return true; + } + return false; + } + + public void setChildren(Vector children) { + for (int i = 0; i < children.size(); i++) { + Object obj = children.elementAt(i); + isValid(obj); + } + Collections.sort(children); + this.children = children; + } + + public void isValid(Object child) { + boolean valid = false; + if (child instanceof ObjectNode ) { + valid = true; + } + if (!valid) { + throw new RuntimeException("Invalid SubsetNode child: " + child.getClass().getName()); //$NON-NLS-1$ + } + } + + + /** + * Finds a child of the SubsetNode with the said name + * @param name + * @return the TreeNode found. null if none + */ + public TreeNode find(String name){ + for (int i = 0; i < children.size(); i++) { + Object obj = children.elementAt(i); + if (obj instanceof TreeNode){ + TreeNode node = (TreeNode) obj; + if (name.equals(node.getName())) return node; + } + } + return null; + } + + public boolean add(ObjectNode object){ + if (children.indexOf(object) >= 0) return false; + children.add(object); + return true; + } + + public boolean addReplace(ObjectNode object){ + children.remove(object); + return add(object); + } + + public boolean remove(ObjectNode object){ + return children.remove(object); + } + + public void exportXML(Element root) { + Element sub = MetaDataXMLInterface.createElementText(root,Messages.getString("ExportXMLAction.Subset"), ""); //$NON-NLS-1$ //$NON-NLS-2$ + MetaDataXMLInterface.createElementText(sub,Messages.getString("ExportXMLAction.SubsetName"), getName()); //$NON-NLS-1$ + for (int i = 0; i < children.size(); i++) { + Object obj = children.elementAt(i); + if (obj instanceof ObjectNode){ + ((ObjectNode) obj).exportXML(sub); + } + } + + } + + /** + * Imports a set of XML tags (parsed into a XMLDocument) into a Subset + * @param root Document to get the data from + * @param replace True if you want to replace already-existing elements with the same name, false if not + */ + public void importXML(Element root, boolean replace) { + if (replace) { + String name = MetaDataXMLInterface.getElementText(root, Messages.getString("ExportXMLAction.SubsetName")); //$NON-NLS-1$ + if (name == "") return; //$NON-NLS-1$ + setName(name); + } + importElementXML(root, replace, Messages.getString("ExportXMLAction.Table")); //$NON-NLS-1$ + importElementXML(root, replace, Messages.getString("ExportXMLAction.View")); //$NON-NLS-1$ + + } + + + /** + * + * Imports one type of element from a XMLDocument (possibly a part of one) into a Subset + * @param root Document to get the data from + * @param replace True if you want to replace already-existing elements with the same name, false if not + * @param type The type of element to import, has to correspond with the XML tag + */ + private void importElementXML(Element root, boolean replace, String type) { + // We get all the tags named as the type + NodeList tables = root.getElementsByTagName(type); + for (int i = 0; i < tables.getLength(); i++) { + Element table = (Element) tables.item(i); + ObjectNode objectNode = ObjectNode.importXML(table, this); + if (replace)addReplace(objectNode); + else add(objectNode); + } + } + + /* (non-Javadoc) + * @see com.quantum.view.bookmark.TreeNode#getImageName() + */ + protected String getImageName() { + return "subset.gif"; + } + + /* (non-Javadoc) + * @see com.quantum.view.bookmark.TreeNode#initializeChildren() + */ + protected void initializeChildren() { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetRoot.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetRoot.java new file mode 100644 index 0000000..3e893f6 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetRoot.java @@ -0,0 +1,41 @@ +package com.quantum.view.subset; + +import com.quantum.view.bookmark.TreeNode; + + +/** + * @author root + */ +public final class SubsetRoot extends TreeNode { + public final static SubsetRoot ROOT = new SubsetRoot(); + public final static TreeNode[] EMPTY_ARRAY = new TreeNode[0]; + + private SubsetRoot() { + super(null); + } + /** + * @see com.quantum.view.bookmark.TreeNode#getChildren() + */ + public Object[] getChildren() { + return EMPTY_ARRAY; + } + + /** + * @see com.quantum.view.bookmark.TreeNode#hasChildren() + */ + public boolean hasChildren() { + return true; + } + + public String getName() { + return "ROOT"; //$NON-NLS-1$ + } + protected String getImageName() { + return null; + } + /* (non-Javadoc) + * @see com.quantum.view.bookmark.TreeNode#initializeChildren() + */ + protected void initializeChildren() { + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetView.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetView.java new file mode 100644 index 0000000..448ff51 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/subset/SubsetView.java @@ -0,0 +1,354 @@ +package com.quantum.view.subset; + +import java.io.IOException; +import java.io.StringReader; +import java.util.Vector; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.actions.CustomCopyAction; +import com.quantum.actions.DeleteColumnAction; +import com.quantum.actions.DeleteObjectAction; +import com.quantum.actions.DeleteSubsetAction; +import com.quantum.actions.ExportXMLAction; +import com.quantum.actions.NewSubsetAction; +import com.quantum.actions.ViewTableAction; +import com.quantum.view.bookmark.ColumnNode; +import com.quantum.view.bookmark.TreeNode; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.part.ViewPart; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * @author panic + * + * View for subsets + * */ +public class SubsetView extends ViewPart { + + private SubsetContentProvider provider = SubsetContentProvider.getInstance(); + private NewSubsetAction newSubsetAction; + private DeleteSubsetAction deleteSubsetAction; + private DeleteObjectAction deleteObjectAction; + private DeleteColumnAction deleteColumnAction; + private CustomCopyAction customCopyAction; + + private ViewTableAction viewTableAction; + private ExportXMLAction exportXMLAction; + private static SubsetView instance = null; + private TreeViewer treeViewer; + private Label status; + public synchronized static SubsetView getInstance() { + return instance; + } + /** + * Returns the current selected object in the tree. If it's a multiple selection, return the first. + * @return + */ + public Object getCurrent() { + if (treeViewer == null) return null; + return ((StructuredSelection) treeViewer.getSelection()) + .getFirstElement(); + } + /** + * Returns the current selected objects in the tree, in the form of a StructuredSelection. + * @return + */ + public StructuredSelection getSelection() { + if (treeViewer == null) return null; + return ((StructuredSelection) treeViewer.getSelection()); + } + + /** + * Navigates the tree to get the current subset (root) of the selected element. + * If it's a multiple selection, it takes the first one. + * @return + */ + public SubsetNode getCurrentSubset() { + TreeNode current = (TreeNode) getCurrent(); + + return getRoot(current); + } + + /** + * Navigates a given TreeNode till finds a SubsetNode + * @param node + * @return + */ + private static SubsetNode getRoot(TreeNode node){ + while (!( node instanceof SubsetNode)) + { + node = (TreeNode) node.getParent(); + } + return (SubsetNode) node; + + } + + + /** + * Deletes the current node (first selected) in the tree + */ + public void deleteCurrent() { + provider.removeSubset(getCurrentSubset()); + treeViewer.refresh(); + } + + public void refreshSubsetData(){ + //if (treeViewer == null) return; + //SubsetContentProvider provider = (SubsetContentProvider) treeViewer.getContentProvider(); + //Object[] objects = provider.getElements(Root.ROOT); + //for (int i = 0; i < objects.length; i++) { + //SubsetNode current = (SubsetNode) objects[i]; + + //} + } + + public void expandCurrent(SubsetNode node) { + treeViewer.setExpandedState(node, true); + treeViewer.refresh(node, false); + } + public void refresh() { + treeViewer.refresh(); + } + public void disconnect() { + } + + public void createPartControl(org.eclipse.swt.widgets.Composite parent) { + instance = this; + initActions(); + Composite main = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + main.setLayout(layout); + + + treeViewer = new TreeViewer(main); + treeViewer.setContentProvider(provider); + treeViewer.setLabelProvider(new SubsetLabelProvider()); + treeViewer.setInput(SubsetRoot.ROOT); + MenuManager manager = new MenuManager(); + manager.setRemoveAllWhenShown(true); + Menu fTextContextMenu = + manager.createContextMenu(treeViewer.getControl()); + treeViewer.getControl().setMenu(fTextContextMenu); + treeViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + Object sel = getCurrent(); + if (sel instanceof ObjectNode) { + viewTableAction.run(); + } + } + }); + + manager.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager mgr) { + Object sel = getCurrent(); + if (sel instanceof SubsetNode) { + mgr.add(deleteSubsetAction); + deleteSubsetAction.setText(Messages.getString("SubsetView.Delete")); //$NON-NLS-1$ + deleteSubsetAction.setImageDescriptor( + QuantumPlugin.getImageDescriptor("delete.gif")); //$NON-NLS-1$ + mgr.add(pasteAction); + pasteAction.setText(Messages.getString("SubsetView.Paste")); //$NON-NLS-1$ + pasteAction.setImageDescriptor(QuantumPlugin.getImageDescriptor("paste.gif")); //$NON-NLS-1$ + mgr.add(exportXMLAction); + exportXMLAction.setText(Messages.getString("bookmarkview.exportXML")); //$NON-NLS-1$ + exportXMLAction.setImageDescriptor(QuantumPlugin.getImageDescriptor("xml.gif")); //$NON-NLS-1$ + + } else if (sel instanceof ObjectNode) { + mgr.add(deleteObjectAction); + deleteObjectAction.setText(Messages.getString("SubsetView.Delete")); //$NON-NLS-1$ + deleteObjectAction.setImageDescriptor(QuantumPlugin.getImageDescriptor("delete.gif")); //$NON-NLS-1$ + mgr.add(viewTableAction); + viewTableAction.setText(Messages.getString("bookmarkview.viewTable")); //$NON-NLS-1$ + viewTableAction.setImageDescriptor(QuantumPlugin.getImageDescriptor("table.gif")); //$NON-NLS-1$ + mgr.add(exportXMLAction); + exportXMLAction.setText(Messages.getString("bookmarkview.exportXML")); //$NON-NLS-1$ + exportXMLAction.setImageDescriptor(QuantumPlugin.getImageDescriptor("xml.gif")); //$NON-NLS-1$ + customCopyAction.selectionChanged( + (IStructuredSelection) treeViewer.getSelection()); + mgr.add(customCopyAction); + } else if (sel instanceof ColumnNode){ + mgr.add(deleteColumnAction); + deleteColumnAction.setText(Messages.getString("SubsetView.Delete")); //$NON-NLS-1$ + deleteColumnAction.setImageDescriptor(QuantumPlugin.getImageDescriptor("delete.gif")); //$NON-NLS-1$ + customCopyAction.selectionChanged( + (IStructuredSelection) treeViewer.getSelection()); + mgr.add(customCopyAction); + + } else { + mgr.add(newSubsetAction); + } + } + }); + + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + gridData.verticalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + treeViewer.getControl().setLayoutData(gridData); + status = new Label(main, SWT.NONE); + gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + status.setLayoutData(gridData); + + IActionBars bars = getViewSite().getActionBars(); + bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction); + bars.setGlobalActionHandler(IWorkbenchActionConstants.DELETE, deleteSubsetAction); + + IToolBarManager toolBar = getViewSite().getActionBars().getToolBarManager(); + toolBar.add(newSubsetAction); + + status.setText(Messages.getString("bookmarkview.done")); //$NON-NLS-1$ + } + public void initActions() { + newSubsetAction = new NewSubsetAction(); + newSubsetAction.setText("New Subset"); //$NON-NLS-1$ + newSubsetAction.setToolTipText(Messages.getString("SubsetView.CreatesANewEmptySubset")); //$NON-NLS-1$ + newSubsetAction.setImageDescriptor( + QuantumPlugin.getImageDescriptor("subset.gif")); //$NON-NLS-1$ + newSubsetAction.init(this); + deleteColumnAction = new DeleteColumnAction(); + deleteColumnAction.setText("Delete Column"); //$NON-NLS-1$ + deleteColumnAction.setToolTipText(Messages.getString("SubsetView.DeletesTheSelectedColumns")); //$NON-NLS-1$ + deleteColumnAction.setImageDescriptor( + QuantumPlugin.getImageDescriptor("delete.gif")); //$NON-NLS-1$ + deleteColumnAction.init(this); + deleteObjectAction = new DeleteObjectAction(); + deleteObjectAction.setText("Delete Object"); //$NON-NLS-1$ + deleteObjectAction.setToolTipText(Messages.getString("SubsetView.DeletesTheSelectedObject")); //$NON-NLS-1$ + deleteObjectAction.setImageDescriptor( + QuantumPlugin.getImageDescriptor("delete.gif")); //$NON-NLS-1$ + deleteObjectAction.init(this); + deleteSubsetAction = new DeleteSubsetAction(); + deleteSubsetAction.setText("Delete Subset"); //$NON-NLS-1$ + deleteSubsetAction.setToolTipText(Messages.getString("SubsetView.DeletesTheSelectedSubset")); //$NON-NLS-1$ + deleteSubsetAction.setImageDescriptor( + QuantumPlugin.getImageDescriptor("delete.gif")); //$NON-NLS-1$ + deleteSubsetAction.init(this); +// viewTableAction = new ViewTableAction(); +// viewTableAction.setText(Messages.getString("bookmarkview.viewTable")); //$NON-NLS-1$ +// viewTableAction.setImageDescriptor( +// QuantumPlugin.getImageDescriptor("table.gif")); //$NON-NLS-1$ +// viewTableAction.init(this); + exportXMLAction = new ExportXMLAction(); + exportXMLAction.setText(Messages.getString("bookmarkview.exportXML")); //$NON-NLS-1$ + exportXMLAction.setImageDescriptor( + QuantumPlugin.getImageDescriptor("table.gif")); //$NON-NLS-1$ + exportXMLAction.init(this); + + this.customCopyAction = new CustomCopyAction(this,1); // 1 is unused, just in case more custom copies are defined + this.customCopyAction.setText(Messages.getString("bookmarkview.customCopyAction")); //$NON-NLS-1$ + this.customCopyAction.setImageDescriptor( + QuantumPlugin.getImageDescriptor("copy.gif")); //$NON-NLS-1$ + + + + } + public void setFocus() { + } + + private Action pasteAction = new Action() { + public void run() { + Object sel = getCurrent(); + if (sel == null) return; + if (!(sel instanceof SubsetNode)) return; + + SubsetNode subset = (SubsetNode) sel; + + TextTransfer transfer = TextTransfer.getInstance(); + String xmlMetaData = (String) QuantumPlugin.getDefault().getSysClip().getContents(transfer); + StringReader text = new StringReader(xmlMetaData); + InputSource source = new InputSource(text); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder parser; + Document doc; + try { + parser = factory.newDocumentBuilder(); + doc = parser.parse(source); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + return; + } catch (SAXException e) { + e.printStackTrace(); + return; + } catch (IOException e) { + e.printStackTrace(); + return; + } + Element root = doc.getDocumentElement(); + subset.importXML(root, false); + treeViewer.refresh(); + provider.setHasChanged(true); + + } + }; + + public void addNewSubset(SubsetNode subset) { + provider.addSubset(subset); + treeViewer.refresh(); + } + public void setStatus(String text) { + status.setText(text); + } + public void dispose(){ + super.dispose(); + } + + /** + * Returs a Vector with all the elements of the treeViewer + * @return + */ + public Vector getElements(){ + Vector result = new Vector(); + if (treeViewer == null) return result; + SubsetContentProvider provider = (SubsetContentProvider) treeViewer.getContentProvider(); + Object[] objects = provider.getElements(SubsetRoot.ROOT); + for (int i = 0; i < objects.length; i++) { + SubsetNode current = (SubsetNode) objects[i]; + result.add(current); + } + return result; + } + + public void deleteColumn (ColumnNode column){ + provider.deleteColumn(column); + treeViewer.refresh(); + } + + public void deleteObject (ObjectNode object){ + provider.deleteObject(object); + treeViewer.refresh(); + } + + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/DefaultSizes.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/DefaultSizes.java new file mode 100644 index 0000000..aa53489 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/DefaultSizes.java @@ -0,0 +1,6 @@ +package com.quantum.view.tableview; + +public class DefaultSizes { + public static int PAGE_SIZE = 200; + public static int MAX_COLUMN_SIZE = 1024 * 2; +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableAdapter.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableAdapter.java new file mode 100644 index 0000000..17d7b29 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableAdapter.java @@ -0,0 +1,269 @@ +package com.quantum.view.tableview; + +import java.sql.SQLException; +import java.util.Vector; + +import com.quantum.Messages; +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.model.Bookmark; +import com.quantum.model.Entity; +import com.quantum.model.NotConnectedException; +import com.quantum.sql.FilterSort; +import com.quantum.sql.SQLHelper; +import com.quantum.sql.SQLResults; + +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; + +public class TableAdapter { + + private Table table = null; + + public static final String DEFAULT = ""; //$NON-NLS-1$ + public static final String UTF_8 = "UTF-8"; //$NON-NLS-1$ + public static final String UTF_16 = "UTF-16"; //$NON-NLS-1$ + + private int pageSize = DefaultSizes.PAGE_SIZE; + private int maxColumnSize = DefaultSizes.MAX_COLUMN_SIZE; + private FilterSort extra = new FilterSort(); + private int offset = 1; + private int totalSize = -1; + private Vector rows = new Vector(); + private Vector columnNames = new Vector(); + private boolean hasMore = false; + + private Bookmark bookmark = null; + private Entity entity = null; + private String query; + + private String encoding = ""; //$NON-NLS-1$ + + private TableAdapter(Entity entity) { + this.entity = entity; + this.bookmark = entity.getBookmark(); + } + private TableAdapter(Bookmark bookmark) { + this.bookmark = bookmark; + } + public void fullMode() { + offset = 1; + pageSize = Integer.MAX_VALUE; + } + public void resetMode() { + offset = 1; + pageSize = DefaultSizes.PAGE_SIZE; + } + public static TableAdapter createFromQuery(Bookmark bookmark, SQLResults results) throws NotConnectedException { + TableAdapter retVal = new TableAdapter(bookmark); + retVal.setQuery(results.getQuery()); + retVal.setData(results); + return retVal; + } + public static TableAdapter createFromTable(Entity entity) { + TableAdapter retVal = new TableAdapter(entity); + return retVal; + } + private void loadSize() { + try { + if (entity != null) { + totalSize = SQLHelper.getSize( + bookmark.getConnection(), entity.getCondQualifiedName(), + AdapterFactory.getInstance().getAdapter(bookmark.getType())); + } + } catch (SQLException e) { + e.printStackTrace(); + } catch (NotConnectedException e) { + e.printStackTrace(); + } + } + public int getStartIndex() { + if (totalSize == 0) { + return 0; + } + return offset; + } + public int getEndIndex() { + return offset + rows.size() - 1; + } + public int getTotalSize() { + return totalSize; + } + public void nextPage() { + loadSize(); + offset = offset + pageSize; + if (totalSize >= 0 && offset > totalSize) { + offset = offset - pageSize; + } + } + public void previousPage() { + offset = offset - pageSize; + if (offset < 1) { + offset = 1; + } + } + public boolean hasNextPage() { + if (entity != null) { + if (offset + pageSize <= totalSize) { + return true; + } + return false; + } + return hasMore; + } + public boolean hasPreviousPage() { + if (offset > 1) { + return true; + } + return false; + } + + public String getQuery() { + if (entity != null) { + DatabaseAdapter adapter = AdapterFactory.getInstance().getAdapter(bookmark.getType()); + if (adapter == null) throw new RuntimeException(); + else return adapter.getTableQuery((entity).getCondQualifiedName()) + extra.toString(); + } + return query; + } + public void loadData() throws NotConnectedException { + loadSize(); + if (entity != null) { + if (offset > totalSize) { + offset = 1; + } + } + String query = getQuery(); + System.out.println(offset + Messages.getString("TableAdapter.to") + (offset + pageSize - 1)); //$NON-NLS-1$ + SQLResults results = SQLHelper.getResults(bookmark.getConnection(), query, offset, offset + pageSize - 1, maxColumnSize, encoding); + setData(results); + } + public void resetOffset() { + offset = 1; + } + public void setData(SQLResults results) throws NotConnectedException { + if (results.isError()) return; + int rowCount = results.getRowCount(); + int columnCount = results.getColumnCount(); + rows = new Vector(); + columnNames = new Vector(); + for (int col = 1; col <= columnCount; col++) { + columnNames.addElement(results.getColumnName(col)); + } + for (int row = 1; row <= rowCount; row++) { + String rowData[] = new String[columnCount]; + for (int col = 1; col <= columnCount; col++) { + rowData[col - 1] = results.getElement(col, row).toString(); + } + rows.addElement(rowData); + } + hasMore = results.hasMore(); + if (entity == null && results.getMaxSize() >= 0) { + if (offset > results.getMaxSize()) { + offset = 1; + loadData(); + } + } + } + public void loadTable(Table table) { + this.table = table; + table.setHeaderVisible(true); + for (int i = 0; i < columnNames.size(); i++) { + TableColumn column = new TableColumn(table, SWT.NONE); + column.setText(columnNames.elementAt(i).toString()); + } + for (int i = 0; i < columnNames.size(); i++) { + table.getColumn(i).pack(); + } + for (int row = 0; row < rows.size(); row++) { + TableItem item = new TableItem(table, SWT.NONE); + String itemData[] = (String[]) rows.elementAt(row); + item.setText(itemData); + } + for (int i = 0; i < columnNames.size(); i++) { + table.getColumn(i).pack(); + } + } + + public TableViewer addTableViewer(Table table) { + TableViewer tableViewer = new TableViewer(table); + tableViewer.setUseHashlookup(true); + String[] colNams = new String[columnNames.size()]; + for (int i = 0; i < columnNames.size(); i++) { + colNams[i] = (String) columnNames.get(i); + } + tableViewer.setColumnProperties(colNams); + + // Create the cell editors + CellEditor[] editors = new CellEditor[columnNames.size()]; + for (int i = 0; i < columnNames.size(); i++) { + TextCellEditor textEditor = new TextCellEditor(table); + ((Text) textEditor.getControl()).setTextLimit(60); + editors[i] = textEditor; + } + // Assign the cell editors to the viewer + tableViewer.setCellEditors(editors); + // Set the cell modifier for the viewer + //tableViewer.setCellModifier(new MetaDataModifier(this)); + // Set the default sorter for the viewer + //tableViewer.setSorter(new ExampleTaskSorter(ExampleTaskSorter.DESCRIPTION)); + + return tableViewer; + } + + public int getPageSize() { + return pageSize; + } + + public void setFilterSort(FilterSort extra) { + this.extra = extra; + } + public String getTable() { + return (entity != null) ? entity.getCondQualifiedName() : null; + } + + public void setQuery(String query) { + this.query = query; + } + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + public String getStatusString() { + String status = getStartIndex() + Messages.getString("TableAdapter.to") + getEndIndex() + Messages.getString("TableAdapter.of") + //$NON-NLS-1$ //$NON-NLS-2$ + getTotalSize(); + if (!encoding.equals(DEFAULT)) { + status += " (" + encoding + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } + String filterText = extra.toString(); + if (!filterText.equals("")) { //$NON-NLS-1$ + status += " (" + filterText + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (pageSize == Integer.MAX_VALUE) { + status += Messages.getString("TableAdapter.full"); //$NON-NLS-1$ + } + return status; + } + /** + * @return + */ + public Bookmark getBookmark() { + return this.bookmark; + } + /** + * @return + */ + public Entity getEntity() { + return entity; + } + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableView.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableView.java new file mode 100644 index 0000000..dc41455 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableView.java @@ -0,0 +1,283 @@ +package com.quantum.view.tableview; + +import java.util.Vector; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.part.ViewPart; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.extensions.ProcessServiceMembers; +import com.quantum.model.Bookmark; +import com.quantum.model.Entity; +import com.quantum.model.NotConnectedException; +import com.quantum.sql.SQLResults; +import com.quantum.ui.dialog.ExceptionDisplayDialog; +import com.quantum.view.LogProxy; + +/** + * The Table View. Displays tables and Queries. + */ +public class TableView extends ViewPart implements ISelectionListener { + + private class DefaultEncodingAction extends Action { + private final TableAdapter ta; + private DefaultEncodingAction(TableAdapter ta) { + super(); + this.ta = ta; + } + public void run() { + ta.setEncoding(TableAdapter.DEFAULT); + } + } + private static TableView instance = null; + private TabFolder tabs = null; + private Composite parent; + private Vector extensionVector; + + /** + * Generic contructor + */ + public TableView() { + } + + + public void setFocus() { + setQualifiedTitle(); + } + + /** + * Gets the instance of the TableView. This view can appear on multiple + * perspectives, but tabs within the view are shared no matter which perspective + * is open. + * + * @return the TableView instance. + */ + public static TableView getInstance() { + return (TableView) QuantumPlugin.getDefault().getView("com.quantum.view.tableview.TableView"); + } + + /** + * Close the current tab, disposing of it + */ + public void closeCurrent() { + if (tabs == null) return; + + if (tabs.getSelectionIndex() >= 0) { + try { + TabItem item = tabs.getItem(tabs.getSelectionIndex()); + item.dispose(); + } catch (Throwable e) { + LogProxy.getInstance().addText(LogProxy.ERROR, "Error Closing Current: " + e.toString()); //$NON-NLS-1$ + e.printStackTrace(); + } + } + if (tabs.getItemCount() == 0) { + setTitle(Messages.getString("tableview.QuantumTableViewName")); //$NON-NLS-1$ + } + } + + /** + * Reload table or query data into the selected tab + */ + public void refreshCurrent() { + TabItem item = tabs.getItem(tabs.getSelectionIndex()); + TableAdapter adapter = (TableAdapter) item.getData(); + Bookmark bookmark = adapter.getBookmark(); + String table = adapter.getTable(); + if (table == null) { + loadTable(bookmark, item, null, null, true, true); + } else { + loadTable(bookmark, item, null, null, true, true); + } + String title = Messages.getString("tableview.QuantumTableViewName"); //$NON-NLS-1$ + if (bookmark != null) + title = bookmark.getName() + Messages.getString("tableview.ViewNameInitialDecoration") + title + Messages.getString("tableview.ViewNameFinalDecoration"); //$NON-NLS-1$ //$NON-NLS-2$ + setTitle(title); + } + + public void loadQuery(Bookmark bookmark, SQLResults results) { + loadTable(bookmark, null, null, results, true, false); + } + public void loadTable(Entity entity) { + loadTable(entity.getBookmark(), null, entity, null, false, true); + } + public void loadTable(Bookmark bookmark, TabItem tabItem, Entity entity, SQLResults results, boolean query, boolean reload) { + try { + TableAdapter adapter; + // If no TabItem is given we have to create a new one, with the info of the table or view. + if (tabItem == null) { + tabItem = new TabItem(tabs, SWT.NONE); + // Data is stored in a TableAdapter object + if (query) { + adapter = TableAdapter.createFromQuery(bookmark, results); + } else { + adapter = TableAdapter.createFromTable(entity); + } + // That is stored in the tabItem, so it won't get lost + tabItem.setData(adapter); + // This does not really belong here, but it'll fail if done before the creation of the + // first TabItem, so it remains here till a better place found. + // We set a function to change the Title of the window depending on the selected tab. + tabs.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + setQualifiedTitle(); + } + }); + } else { + // If there is already a TabItem, we take its TableAdapter object + adapter = (TableAdapter) tabItem.getData(); + } + + // We create a Composite widget (main) to display our data, with a GridLayout + Composite main = new Composite(tabs, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + main.setLayout(layout); + + + // load widgets, the order of loading them determines the appearance in screen + ToolBar widgetToolBar = new ToolBar(main, SWT.HORIZONTAL); + // We fill up our Composite widget, the main table display, etc. + final Table table = new Table(main, SWT.FULL_SELECTION | SWT.MULTI); + final Label label = new Label(main, SWT.NULL); + TableViewToolBar toolBar = new TableViewToolBar(this, widgetToolBar, table, adapter, label); + + + // load table + if (reload) { + adapter.resetOffset(); + adapter.loadData(); + } + // Load the table data from the adapter into the widget + adapter.loadTable(table); + // Experimental, won't make it into 2.2 + // final TableViewer viewer = adapter.addTableViewer(table); + + String tableName = adapter.getTable(); + if (tableName != null) { + tabItem.setText(bookmark.getName() + ":" + tableName); + } else { + tabItem.setText(bookmark.getName() + ":" + adapter.getQuery()); + } + + toolBar.getPrevious().setEnabled(adapter.hasPreviousPage()); + toolBar.getNext().setEnabled(adapter.hasNextPage()); + label.setText(adapter.getStatusString()); + + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + gridData.verticalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + table.setLayoutData(gridData); + + gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + label.setLayoutData(gridData); + + + toolBar.setColumns(this, adapter, table); + final TableAdapter ta = adapter; + final Action defaultEncodingAction = new DefaultEncodingAction(ta); + defaultEncodingAction.setText(Messages.getString("tableview.defaultEncoding")); //$NON-NLS-1$ + final Action UTF8EncodingAction = new Action() { + public void run() { + ta.setEncoding(TableAdapter.UTF_8); + } + }; + UTF8EncodingAction.setText(Messages.getString("tableview.UTF8Encoding")); //$NON-NLS-1$ + final Action UTF16EncodingAction = new Action() { + public void run() { + ta.setEncoding(TableAdapter.UTF_16); + } + }; + UTF16EncodingAction.setText(Messages.getString("tableview.UTF16Encoding")); //$NON-NLS-1$ + + IMenuListener menuListener = new TableViewMenuListener(this, table, UTF16EncodingAction, ta, defaultEncodingAction, UTF8EncodingAction, extensionVector); + + // final setup + MenuManager manager = new MenuManager(); + manager.setRemoveAllWhenShown(true); + Menu fTextContextMenu = manager.createContextMenu(table); + table.setMenu(fTextContextMenu); + table.setLinesVisible(true); + manager.addMenuListener(menuListener); + + tabItem.setControl(main); + tabs.setSelection(tabs.indexOf(tabItem)); + + setQualifiedTitle(); + } catch (NotConnectedException e) { + e.printStackTrace(); + handleException(e); + } catch (Exception e) { + e.printStackTrace(); + } + } + + protected void handleException(Exception e) { + ExceptionDisplayDialog.openError(getSite().getShell(), null, null, e); + } + + /** + * @return + */ + /** + * Sets the title of the window to the text of the selected tab + */ + private void setQualifiedTitle() { + if (tabs.getSelectionIndex() < 0) return; + TabItem item = tabs.getItem(tabs.getSelectionIndex()); + String defTitle = Messages.getString("tableview.QuantumTableViewName"); //$NON-NLS-1$ + String title = item.getText(); + int ind = title.indexOf(Messages.getString("tableview.BookmarkSeparator")); //$NON-NLS-1$ + if (ind > 0) defTitle = title.substring(0,ind) + + Messages.getString("tableview.ViewNameInitialDecoration") //$NON-NLS-1$ + + defTitle + + Messages.getString("tableview.ViewNameFinalDecoration"); //$NON-NLS-1$ + setTitle(defTitle); + } + + public void createPartControl(Composite parent) { + instance = this; + this.parent = parent; + initActions(); + tabs = new TabFolder(parent, SWT.NONE); + } + + public void initActions() { + extensionVector = new Vector(); + try { + ProcessServiceMembers.process(this, extensionVector); + } catch (WorkbenchException e) { + e.printStackTrace(); + } + + } + + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableViewMenuListener.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableViewMenuListener.java new file mode 100644 index 0000000..09da28f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableViewMenuListener.java @@ -0,0 +1,138 @@ +/* + * Created on 28-jul-2003 + * + */ +package com.quantum.view.tableview; + +import java.util.Vector; + +import com.quantum.Messages; +import com.quantum.extensions.ExtensionAction; +import com.quantum.sql.TableRow; +import com.quantum.util.StringMatrix; +import com.quantum.wizards.DeleteRowPage; +import com.quantum.wizards.InsertRowPage; +import com.quantum.wizards.SQLRowWizard; +import com.quantum.wizards.UpdateRowPage; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; + + +public final class TableViewMenuListener implements IMenuListener { + private final TableView tableView; + private final Table table; + private final Action UTF16EncodingAction; + private final TableAdapter ta; + private final Action defaultEncodingAction; + private final Action UTF8EncodingAction; + private final Vector extensionVector; + + public TableViewMenuListener( + TableView view, + Table table, + Action UTF16EncodingAction, + TableAdapter ta, + Action defaultEncodingAction, + Action UTF8EncodingAction, + Vector extensionVector ) { + + super(); + this.tableView = view; + this.table = table; + this.UTF16EncodingAction = UTF16EncodingAction; + this.ta = ta; + this.defaultEncodingAction = defaultEncodingAction; + this.UTF8EncodingAction = UTF8EncodingAction; + this.extensionVector = extensionVector; + } + public void menuAboutToShow(IMenuManager mgr) { + if (ta.getTable() != null) { + TableItem[] selection = table.getSelection(); + TableColumn[] columns = table.getColumns(); + // Copy in columnNames the names of the columns of the selected rows + String columnNames[] = new String[columns.length]; + for (int i = 0; i < columns.length; i++) { + columnNames[i] = columns[i].getText(); + } + // Copy in data the values of the data columns of the selected rows + StringMatrix data = new StringMatrix(); + data.addMatrixHeader(columnNames); + if (selection != null && selection.length > 0) { + for (int iRow = 0; iRow < selection.length; iRow++) { + TableItem sel = selection[iRow]; + for (int i = 0; i < columns.length; i++) { + data.addAt(columnNames[i], sel.getText(i), iRow ); + } + } + } else { + // Create dummy values in case nothing selected + for (int i = 0; i < columns.length; i++) { + data.addAt(columnNames[i], "", 0); //$NON-NLS-1$ + } + } + final TableRow row = + new TableRow(ta.getEntity(), ta.getBookmark(), ta.getTable(), data); + Action updateAction = new Action() { + public void run() { + UpdateRowPage page = new UpdateRowPage(""); //$NON-NLS-1$ + SQLRowWizard wizard = new SQLRowWizard(); + wizard.init(Messages.getString("TableView.UpdateRow"), page, row, ta); //$NON-NLS-1$ + WizardDialog dialog = + new WizardDialog( + tableView.getSite().getShell(), + wizard); + dialog.open(); + } + }; + updateAction.setText(Messages.getString("tableview.update")); //$NON-NLS-1$ + Action insertAction = new Action() { + public void run() { + InsertRowPage page = new InsertRowPage(""); //$NON-NLS-1$ + SQLRowWizard wizard = new SQLRowWizard(); + wizard.init(Messages.getString("TableView.InsertRow"), page, row, ta); //$NON-NLS-1$ + WizardDialog dialog = + new WizardDialog( + tableView.getSite().getShell(), + wizard); + dialog.open(); + } + }; + insertAction.setText(Messages.getString("tableview.insert")); //$NON-NLS-1$ + Action deleteAction = new Action() { + public void run() { + DeleteRowPage page = new DeleteRowPage(""); //$NON-NLS-1$ + SQLRowWizard wizard = new SQLRowWizard(); + wizard.init(Messages.getString("TableView.DeleteRow"), page, row, ta); //$NON-NLS-1$ + WizardDialog dialog = + new WizardDialog( + tableView.getSite().getShell(), + wizard); + dialog.open(); + } + }; + deleteAction.setText(Messages.getString("tableview.delete")); //$NON-NLS-1$ + mgr.add(insertAction); + mgr.add(updateAction); + mgr.add(deleteAction); + + MenuManager subMenuExtension = new MenuManager("Extensions"); + for (int i = 0; i < extensionVector.size(); i++) { + ExtensionAction extensionAction = (ExtensionAction) extensionVector.get(i); + extensionAction.addRowData(row); + subMenuExtension.add(extensionAction); + } + if (extensionVector.size() > 0) mgr.add(subMenuExtension); + + } + mgr.add(defaultEncodingAction); + mgr.add(UTF8EncodingAction); + mgr.add(UTF16EncodingAction); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableViewToolBar.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableViewToolBar.java new file mode 100644 index 0000000..cb06fbd --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/view/tableview/TableViewToolBar.java @@ -0,0 +1,246 @@ +/* + * Created on 28-jul-2003 + * + */ +package com.quantum.view.tableview; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.actions.CloseTableAction; +import com.quantum.actions.RefreshTableAction; +import com.quantum.model.NotConnectedException; +import com.quantum.sql.TableRow; +import com.quantum.util.StringMatrix; +import com.quantum.view.CopyAction; +import com.quantum.wizards.SQLRowWizard; +import com.quantum.wizards.SortFilterPage; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; + +/** + * @author panic + * + */ +public class TableViewToolBar { + + private ToolBar toolBar; + private RefreshTableAction refreshTableAction; + private CloseTableAction closeTableAction; + private ToolItem previous; + private ToolItem next; + + ToolItem filter; + + public TableViewToolBar( + final TableView view, + final ToolBar toolBar, + final Table table, + final TableAdapter ta, + final Label label) { + + this.toolBar = toolBar; + + refreshTableAction = new RefreshTableAction(); + refreshTableAction.setText(Messages.getString("tableview.refresh")); //$NON-NLS-1$ + refreshTableAction.setImageDescriptor( + QuantumPlugin.getImageDescriptor("refresh.gif")); //$NON-NLS-1$ + refreshTableAction.init(view); + closeTableAction = new CloseTableAction(); + closeTableAction.setText(Messages.getString("tableview.close")); //$NON-NLS-1$ + closeTableAction.setImageDescriptor( + QuantumPlugin.getImageDescriptor("close.gif")); //$NON-NLS-1$ + closeTableAction.init(view); + + ToolItem toolItem = new ToolItem(toolBar, SWT.PUSH); + toolItem.setImage(QuantumPlugin.getImage("refresh.gif")); //$NON-NLS-1$ + toolItem.setToolTipText(Messages.getString("tableview.refresh")); //$NON-NLS-1$ + toolItem.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + refreshTableAction.run(); + } + }); + + final Action copyAction = new CopyAction(view, table); + final Action selectAllAction = new Action() { + public void run() { + table.selectAll(); + } + }; + toolItem = new ToolItem(toolBar, SWT.PUSH); + toolItem.setImage(QuantumPlugin.getImage("copy.gif")); //$NON-NLS-1$ + toolItem.setToolTipText(Messages.getString("tableview.copy")); //$NON-NLS-1$ + toolItem.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + copyAction.run(); + } + }); + toolItem = new ToolItem(toolBar, SWT.PUSH); + toolItem.setImage(QuantumPlugin.getImage("table.gif")); //$NON-NLS-1$ + toolItem.setToolTipText(Messages.getString("tableview.selectAll")); //$NON-NLS-1$ + toolItem.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + selectAllAction.run(); + } + }); + + filter = new ToolItem(toolBar, SWT.PUSH); + filter.setImage(QuantumPlugin.getImage("filter.gif")); //$NON-NLS-1$ + filter.setToolTipText(Messages.getString("tableview.filterSort")); //$NON-NLS-1$ + + toolItem = new ToolItem(toolBar, SWT.SEPARATOR); + + final ToolItem fullMode = new ToolItem(toolBar, SWT.PUSH | SWT.CHECK); + + previous = new ToolItem(toolBar, SWT.PUSH); + next = new ToolItem(toolBar, SWT.PUSH); + + fullMode.setImage(QuantumPlugin.getImage("fulldata.gif")); //$NON-NLS-1$ + fullMode.setToolTipText(Messages.getString("tableview.showAll")); //$NON-NLS-1$ + fullMode.setSelection(false); + fullMode.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent event) { + try { + if (ta.getPageSize() == Integer.MAX_VALUE) { + ta.resetMode(); + } else { + ta.fullMode(); + } + ta.loadData(); + table.removeAll(); + for (int i = table.getColumnCount() - 1; i >= 0; i--) { + table.getColumn(i).dispose(); + } + ta.loadTable(table); + label.setText(ta.getStatusString()); + previous.setEnabled(ta.hasPreviousPage()); + next.setEnabled(ta.hasNextPage()); + } catch (NotConnectedException e) { + view.handleException(e); + } + } + }); + previous.setImage(QuantumPlugin.getImage("previous.gif")); //$NON-NLS-1$ + previous.setToolTipText("Previous"); //$NON-NLS-1$ + previous.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent event) { + try { + ta.previousPage(); + ta.loadData(); + table.removeAll(); + for (int i = table.getColumnCount() - 1; i >= 0; i--) { + table.getColumn(i).dispose(); + } + ta.loadTable(table); + label.setText(ta.getStatusString()); + previous.setEnabled(ta.hasPreviousPage()); + next.setEnabled(ta.hasNextPage()); + } catch (NotConnectedException e) { + view.handleException(e); + } + } + }); + next.setImage(QuantumPlugin.getImage("next.gif")); //$NON-NLS-1$ + next.setToolTipText("Next"); //$NON-NLS-1$ + next.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent event) { + try { + ta.nextPage(); + ta.loadData(); + table.removeAll(); + for (int i = table.getColumnCount() - 1; i >= 0; i--) { + table.getColumn(i).dispose(); + } + ta.loadTable(table); + label.setText(ta.getStatusString()); + previous.setEnabled(ta.hasPreviousPage()); + next.setEnabled(ta.hasNextPage()); + } catch (NotConnectedException e) { + view.handleException(e); + } + } + }); + + toolItem = new ToolItem(toolBar, SWT.SEPARATOR); + + toolItem = new ToolItem(toolBar, SWT.PUSH); + toolItem.setImage(QuantumPlugin.getImage("close.gif")); //$NON-NLS-1$ + toolItem.setToolTipText(Messages.getString("tableview.close")); //$NON-NLS-1$ + toolItem.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + closeTableAction.run(); + } + }); + + } + + public void setColumns( final TableView view, final TableAdapter ta, Table table) { + + // We create a matrix of TableColumn (columns in the Table widget) with + // the columns in the table object + TableColumn[] columns = table.getColumns(); + String columnNames[] = new String[columns.length]; + for (int i = 0; i < columns.length; i++) { + columnNames[i] = columns[i].getText(); + } + // Copy in data the values of the data columns of the selected rows + StringMatrix data = new StringMatrix(); + data.addMatrixHeader(columnNames); + // Create dummy values in case nothing selected + for (int i = 0; i < columns.length; i++) { + data.addAt(columnNames[i], "", 0); //$NON-NLS-1$ + } + final TableRow emptyRow = new TableRow(ta.getEntity(), ta.getBookmark(), ta.getTable(), data); + + filter.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + SortFilterPage page = new SortFilterPage(""); //$NON-NLS-1$ + SQLRowWizard wizard = new SQLRowWizard(); + wizard.init(Messages.getString("TableView.FilterAndSort"), page, emptyRow, ta); //$NON-NLS-1$ + WizardDialog dialog = new WizardDialog(view.getSite().getShell(), wizard); + dialog.open(); + } + }); + } + + + + /** + * @return + */ + public ToolItem getNext() { + return next; + } + + /** + * @return + */ + public ToolItem getPrevious() { + return previous; + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/BaseSQLPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/BaseSQLPage.java new file mode 100644 index 0000000..459a949 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/BaseSQLPage.java @@ -0,0 +1,49 @@ +package com.quantum.wizards; + +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.model.Bookmark; +import com.quantum.model.Column; +import com.quantum.model.ConnectionException; +import com.quantum.model.Entity; +import com.quantum.sql.TableRow; +import com.quantum.view.ViewHelper; +import com.quantum.view.tableview.TableAdapter; + +import org.eclipse.jface.wizard.WizardPage; + +/** + * @author BC + */ +public abstract class BaseSQLPage extends WizardPage implements SQLPage { + + protected TableRow row; + protected TableAdapter adapter; + + public BaseSQLPage(String pageName) { + super(pageName); + } + public boolean performFinish() { + try { + Bookmark bookmark = this.adapter.getBookmark(); + bookmark.addQuery(getQueryText()); + ViewHelper.tryGetResults(getShell(), bookmark.getConnection(), getQueryText()); + } catch (ConnectionException e) { + e.printStackTrace(); + } + return true; + } + protected abstract String getQueryText(); + protected void appendColumn(StringBuffer whereClause, Entity entity, String columnName, DatabaseAdapter adapter, String value) { + + if (adapter != null && entity != null && entity.getColumn(columnName) != null) { + Column column = entity.getColumn(columnName); + whereClause.append(adapter.quote(value, column.getType(), column.getTypeName())); + } else { + whereClause.append(value); + } + } + public void init(TableRow row, TableAdapter adapter) { + this.row = row; + this.adapter = adapter; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/BookmarkWizard.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/BookmarkWizard.java new file mode 100644 index 0000000..da768ff --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/BookmarkWizard.java @@ -0,0 +1,297 @@ +package com.quantum.wizards; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DriverInfo; +import com.quantum.model.Bookmark; +import com.quantum.model.BookmarkCollection; +import com.quantum.view.bookmark.BookmarkNode; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class BookmarkWizard extends Wizard { + BookmarkPage mainPage; + + private Bookmark current; + + public void init(BookmarkNode selection) { + System.out.println("Initing workbench"); //$NON-NLS-1$ + this.current = selection.getBookmark(); + setWindowTitle(Messages.getString("BookmarkWizard.NewBookmark")); //$NON-NLS-1$ + } + public void init() { + System.out.println("Initing workbench"); //$NON-NLS-1$ + current = null; + setWindowTitle(Messages.getString("BookmarkWizard.NewBookmark")); //$NON-NLS-1$ + } + public boolean performFinish() { + System.out.println("perform finish workbench"); //$NON-NLS-1$ + String bookmarkName = mainPage.name.getText(); + if ( BookmarkCollection.getInstance().find(bookmarkName) != null){ + MessageDialog.openInformation( + this.getShell(),Messages.getString("BookmarkWizard.Error"),Messages.getString("BookmarkWizard.bookmarkAlreadyExists")); //$NON-NLS-1$ //$NON-NLS-2$ + return false; + } + + mainPage.performFinish(); + return true; + } + public void addPages() { + System.out.println("adding pages"); //$NON-NLS-1$ + if (current != null) { + mainPage = new BookmarkPage(Messages.getString("BookmarkWizard.Testing"), current); //$NON-NLS-1$ + } else { + mainPage = new BookmarkPage(Messages.getString("BookmarkWizard.Testing")); //$NON-NLS-1$ + } + addPage(mainPage); + System.out.println("adding pages"); //$NON-NLS-1$ + } +} + +class BookmarkPage extends WizardPage { + public static final String ADD = "ADD"; //$NON-NLS-1$ + String action = ADD; + Text name; + Text username; + Text password; + Text schema; + Text connect; + Text driver; + //List driverList; + Combo type; + Text driverFile; + Button prompt; + + Bookmark initialData = null; + + FileDialog dialog; + + DriverInfo[] drivers = AdapterFactory.getInstance().getDriverList(); + /** + * Constructor for BookmarkPage. + * @param pageName + */ + public BookmarkPage(String pageName) { + super(pageName); + initialData = null; + } + /** + * Constructor for BookmarkPage. + * @param pageName + */ + public BookmarkPage(String pageName, Bookmark bookmark) { + super(pageName); + this.initialData = bookmark; + } + + public void createControl(Composite parent) { + System.out.println("page create control"); //$NON-NLS-1$ + dialog = new FileDialog(getContainer().getShell(), SWT.OPEN); + dialog.setFilterExtensions(new String[]{"*.jar", "*.zip","*.*"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + dialog.setFilterNames(new String[]{Messages.getString("BookmarkWizard.JarFiles"),Messages.getString("BookmarkWizard.ZipFiles"), Messages.getString("BookmarkWizard.AllFiles")}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + Composite container = new Composite(parent, SWT.NULL); + GridLayout layout = new GridLayout(); + container.setLayout(layout); + layout.numColumns = 2; + layout.verticalSpacing = 9; + + + Label label = new Label(container, SWT.NULL); + label.setText(Messages.getString("BookmarkWizard.BookmarkNameAst")); //$NON-NLS-1$ + name = new Text(container, SWT.BORDER | SWT.SINGLE); + GridData fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + name.setLayoutData(fullHorizontal); + + label = new Label(container, SWT.NULL); + label.setText(Messages.getString("BookmarkWizard.UsernameAst")); //$NON-NLS-1$ + username = new Text(container, SWT.BORDER | SWT.SINGLE); + fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + username.setLayoutData(fullHorizontal); + + label = new Label(container, SWT.NULL); + label.setText(Messages.getString("BookmarkWizard.PasswordAst")); //$NON-NLS-1$ + password = new Text(container, SWT.BORDER | SWT.SINGLE); + password.setEchoChar('*'); + fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + password.setLayoutData(fullHorizontal); + + this.prompt = new Button(container, SWT.CHECK); + this.prompt.setText(Messages.getString("BookmarkWizard.Prompt")); //$NON-NLS-1$ + fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + fullHorizontal.horizontalSpan = 2; + this.prompt.setLayoutData(fullHorizontal); + + label = new Label(container, SWT.NULL); + label.setText(Messages.getString("BookmarkWizard.Schema")); //$NON-NLS-1$ + schema = new Text(container, SWT.BORDER | SWT.SINGLE); + fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + schema.setLayoutData(fullHorizontal); + + label = new Label(container, SWT.NULL); + label.setText(Messages.getString("BookmarkWizard.ConnectAst")); //$NON-NLS-1$ + connect = new Text(container, SWT.BORDER | SWT.SINGLE); + fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + connect.setLayoutData(fullHorizontal); + + label = new Label(container, SWT.NULL); + label.setText(Messages.getString("BookmarkWizard.DriverAst")); //$NON-NLS-1$ + driver = new Text(container, SWT.BORDER | SWT.SINGLE); + fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + driver.setLayoutData(fullHorizontal); + + //label = new Label(container, SWT.NULL); + //fullHorizontal = new GridData(); + //fullHorizontal.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + //fullHorizontal.verticalSpan = 3; + //label.setLayoutData(fullHorizontal); + //label.setText("(Drivers Found in File)"); + /*driverList = new List(container, SWT.SINGLE); + fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + fullHorizontal.verticalAlignment = GridData.FILL; + fullHorizontal.verticalSpan = 3; + driverList.setLayoutData(fullHorizontal); + driverList.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + String[] selection = driverList.getSelection(); + if (selection != null && selection.length > 0) { + driver.setText(selection[0]); + } + } + });*/ + + label = new Label(container, SWT.NULL); + label.setText(Messages.getString("BookmarkWizard.TypeAst")); //$NON-NLS-1$ + type = new Combo(container, SWT.SIMPLE | SWT.DROP_DOWN | SWT.READ_ONLY); + String driverNames[] = new String[drivers.length]; + for (int i = 0; i < drivers.length; i++) { + driverNames[i] = drivers[i].getDisplayName(); + } + type.setItems(driverNames); + type.select(0); + fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + type.setLayoutData(fullHorizontal); + + label = new Label(container, SWT.NULL); + label.setText(Messages.getString("BookmarkWizard.DriverFilenameAst")); //$NON-NLS-1$ + driverFile = new Text(container, SWT.BORDER | SWT.SINGLE); + fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + driverFile.setLayoutData(fullHorizontal); + + Button button = new Button(container, SWT.PUSH); + button.setText(Messages.getString("BookmarkWizard.Browse")); //$NON-NLS-1$ + + button.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + // We retrieve the last saved path + dialog.setFilterPath(QuantumPlugin.getDefault().getPreferenceStore().getString("quantum.dialogs.bookmarkwizard.path")); //$NON-NLS-1$ + String filename = dialog.open(); + if (filename != null) { + driverFile.setText(filename); + // We save the used path + QuantumPlugin.getDefault().getPreferenceStore().setValue("quantum.dialogs.bookmarkwizard.path", filename); //$NON-NLS-1$ + + } + } + }); + +// if (initialData != null) { +// name.setText(initialData.getName()); +// username.setText(initialData.getUsername()); +// if (initialData.getPromptForPassword()) { +// this.password.setEditable(false); +// } else { +// password.setText(initialData.getPassword()); +// } +// connect.setText(initialData.getConnect()); +// driver.setText(initialData.getDriver()); +// String typeData = initialData.getType(); +// this.prompt.setSelection(initialData.getPromptForPassword()); +// int selectedIndex = 0; +// for (int i = 0; i < drivers.length; i++) { +// if (typeData.equals(drivers[i].getDriverType())) { +// selectedIndex = i; +// } +// } +// type.select(selectedIndex); +// driverFile.setText(initialData.getDriverFile()); +// updateDriverList(); +// } + + prompt.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + BookmarkPage.this.password.setEditable(!prompt.getSelection()); + } + }); + + setControl(container); + + setPageComplete(true); + } + public void updateDriverList() { + /*try { + JarFile file = new JarFile(driverFile.getText()); + Enumeration enum = file.entries(); + while (enum.hasMoreElements()) { + JarEntry entry = (JarEntry) enum.nextElement(); + String className = entry.getName().replace('/', '.'); + if (className.endsWith("Driver.class")) { + className = className.substring(0, className.lastIndexOf('.')); + //driverList.add(className); + } + } + } catch (IOException ex) { + //driverList.removeAll(); + }*/ + } + public void performFinish() { + if (initialData == null) { + initialData = new Bookmark(); + } + initialData.setName(name.getText()); + initialData.setUsername(username.getText()); + initialData.setPromptForPassword(this.prompt.getSelection()); + if (initialData.getPromptForPassword()) { + initialData.setPassword(""); //$NON-NLS-1$ + } else { + initialData.setPassword(password.getText()); + } + initialData.addSchema(schema.getText()); + initialData.setConnect(connect.getText()); + initialData.setDriver(driver.getText()); + int selection = type.getSelectionIndex(); + if (selection >= 0) { + initialData.setType(drivers[selection].getDriverType()); + } + initialData.setDriverFile(driverFile.getText()); + BookmarkCollection.getInstance().addBookmark(initialData); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/DeleteRowPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/DeleteRowPage.java new file mode 100644 index 0000000..dc90a00 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/DeleteRowPage.java @@ -0,0 +1,139 @@ +package com.quantum.wizards; + +import com.quantum.Messages; +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.model.Bookmark; +import com.quantum.model.Entity; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +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.Label; +import org.eclipse.swt.widgets.Text; + +public class DeleteRowPage extends BaseSQLPage implements SQLPage { + String[] columnNames; + Text[] values; + Button[] whereValues; + Text query; + + public DeleteRowPage(String pageName) { + super(pageName); + } + + public void createControl(Composite parent) { + System.out.println("page create control"); //$NON-NLS-1$ + Composite container = new Composite(parent, SWT.NULL); + GridLayout layout = new GridLayout(); + container.setLayout(layout); + layout.numColumns = 3; + + if (row == null) { + System.out.println("Row is null"); //$NON-NLS-1$ + } + if (row.getColumnNames() == null) { + System.out.println("Columns are null"); //$NON-NLS-1$ + } + if (row.getTableData() == null) { + System.out.println("Data is null"); //$NON-NLS-1$ + } + Entity entity = row.getEntity(); + columnNames = row.getColumnNames(); + String[] data = row.getTableData(); + for (int i = 0; i < row.getColumnCount(); i++) { + System.out.println("data = " + i + "=" + data[i]); //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println("column = " + i + "=" + columnNames[i]); //$NON-NLS-1$ //$NON-NLS-2$ + } + values = new Text[row.getColumnCount()]; + whereValues = new Button[row.getColumnCount()]; + new Label(container, SWT.NULL).setText(Messages.getString("DeleteRowPage.ColumnName")); //$NON-NLS-1$ + new Label(container, SWT.NULL).setText(Messages.getString("DeleteRowPage.Value")); //$NON-NLS-1$ + new Label(container, SWT.NULL).setText(Messages.getString("DeleteRowPage.IncludeIn")); //$NON-NLS-1$ + for (int i = 0; i < row.getColumnCount(); i++) { + Label label = new Label(container, SWT.NULL); + label.setText(columnNames[i]); + values[i] = new Text(container, SWT.BORDER | SWT.SINGLE); + GridData fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + values[i].setLayoutData(fullHorizontal); + values[i].setText(data[i]); + + values[i].addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateQuery(); + } + }); + + whereValues[i] = new Button(container, SWT.CHECK); + whereValues[i].setText(Messages.getString("DeleteRowPage.WhereClause")); //$NON-NLS-1$ + // we check if it's a primary key to select it in the WHERE clause + if (entity != null && entity.getColumn(columnNames[i]).isPrimaryKey()) { + whereValues[i].setSelection(true); + } else { + whereValues[i].setSelection(false); + } + whereValues[i].addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + updateQuery(); + } + }); + } + query = new Text(container, SWT.MULTI | SWT.READ_ONLY | SWT.WRAP); + GridData gridData = new GridData(); + gridData.horizontalSpan = layout.numColumns; + gridData.verticalSpan = 3; + gridData.horizontalAlignment = GridData.FILL; + gridData.verticalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + query.setLayoutData(gridData); + + setControl(container); + updateQuery(); + + setPageComplete(true); + } + public void updateQuery() { + System.out.println(Messages.getString("DeleteRowPage.UpdatingQuery")); //$NON-NLS-1$ + StringBuffer whereClause = new StringBuffer(); + Bookmark bookmark = row.getBookmark(); + Entity entity = row.getEntity(); + DatabaseAdapter adapter = AdapterFactory.getInstance().getAdapter(bookmark.getType()); + + int numSelected = 0; + for (int i = 0; i < columnNames.length; i++) { + if (whereValues[i].getSelection()) { + if (numSelected > 0) whereClause.append(" AND "); //$NON-NLS-1$ + numSelected++; + whereClause.append("("); //$NON-NLS-1$ + whereClause.append(columnNames[i]); + whereClause.append(" = "); //$NON-NLS-1$ + appendColumn(whereClause, entity, columnNames[i], adapter, values[i].getText()); + whereClause.append(")"); //$NON-NLS-1$ + } + } + String query = "DELETE FROM " + row.getTable(); //$NON-NLS-1$ + if (numSelected > 0) { + query += " WHERE " + whereClause.toString(); //$NON-NLS-1$ + } + if (numSelected > 0) { + setMessage(""); //$NON-NLS-1$ + } else { + setMessage(Messages.getString("DeleteRowPage.WarningNoWhere")); //$NON-NLS-1$ + } + this.query.setText(query); + } + + protected String getQueryText() { + return query.getText(); + } +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportBookmarkWizard.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportBookmarkWizard.java new file mode 100644 index 0000000..3689fd6 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportBookmarkWizard.java @@ -0,0 +1,34 @@ +package com.quantum.wizards; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.ui.IExportWizard; +import org.eclipse.ui.IWorkbench; + +/** + * @author BC + */ +public class ExportBookmarkWizard extends Wizard implements IExportWizard { + + private ExportBookmarkWizardPage page = new ExportBookmarkWizardPage(); + + public ExportBookmarkWizard() { + setWindowTitle("Export Bookmarks"); + } + + public boolean performFinish() { + return this.page.finish(); + } + + public void init(IWorkbench workbench, IStructuredSelection selection) { + } + + /** + * @see org.eclipse.jface.wizard.IWizard#addPages() + */ + public void addPages() { + super.addPages(); + addPage(this.page); + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportBookmarkWizardPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportBookmarkWizardPage.java new file mode 100644 index 0000000..3feed8f --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportBookmarkWizardPage.java @@ -0,0 +1,283 @@ +package com.quantum.wizards; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import javax.xml.parsers.ParserConfigurationException; + +import com.quantum.Messages; +import com.quantum.QuantumPlugin; +import com.quantum.model.Bookmark; +import com.quantum.model.BookmarkCollection; +import com.quantum.model.xml.ModelToXMLConverter; +import com.quantum.ui.dialog.ExceptionDisplayDialog; +import com.quantum.util.xml.XMLHelper; + +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +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.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.w3c.dom.Document; + +/** + * @author BC + */ +public class ExportBookmarkWizardPage extends WizardPage { + + public class ContentProvider implements ITreeContentProvider { + + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof BookmarkCollection) { + return ((BookmarkCollection) parentElement).getBookmarks(); + } else { + return new Object[0]; + } + } + public Object getParent(Object element) { + if (element instanceof Bookmark) { + return BookmarkCollection.getInstance(); + } else { + return null; + } + } + public boolean hasChildren(Object element) { + if (element instanceof BookmarkCollection) { + return ((BookmarkCollection) element).getBookmarks().length > 0; + } else { + return false; + } + } + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + public void dispose() { + } + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + } + + public class LabelProvider implements ILabelProvider { + + public Image getImage(Object element) { + if (element instanceof Bookmark) { + return QuantumPlugin.getImage("bookmarks.gif"); + } else { + return null; + } + } + + public String getText(Object element) { + + if (element instanceof Bookmark) { + return ((Bookmark) element).getName(); + } else { + return element.toString(); + } + } + + public void addListener(ILabelProviderListener listener) { + } + + public void dispose() { + } + + public boolean isLabelProperty(Object element, String property) { + return false; + } + + public void removeListener(ILabelProviderListener listener) { + } + } + + private CheckboxTreeViewer treeViewer; + private Text fileNameText; + + private boolean sourceIsSelected = false; + private boolean destinationIsSelected = false; + + /** + * @param pageName + */ + protected ExportBookmarkWizardPage() { + super("page1"); + setTitle(Messages.getString(getClass(), "title")); + } + + public void createControl(Composite pageContainer) { + this.sourceIsSelected = false; + this.destinationIsSelected = false; + + Composite composite = new Composite(pageContainer, SWT.NULL); + composite.setLayout(new GridLayout()); + composite.setLayoutData( + new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL)); + + this.treeViewer = new CheckboxTreeViewer(composite, + SWT.CHECK | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + this.treeViewer.setContentProvider(new ContentProvider()); + this.treeViewer.setLabelProvider(new LabelProvider()); + this.treeViewer.setInput(BookmarkCollection.getInstance()); + selectAll(); + + this.treeViewer.addCheckStateListener(new ICheckStateListener() { + public void checkStateChanged(CheckStateChangedEvent event) { + setSourceIsSelected( + ExportBookmarkWizardPage.this.treeViewer.getCheckedElements().length > 0); + } + }); + + GridData data = new GridData(); + data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_FILL; + data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; + data.grabExcessHorizontalSpace = true; + data.heightHint = 200; + data.widthHint = 400; + this.treeViewer.getControl().setLayoutData(data); + + Composite buttons = new Composite(composite, SWT.NULL); + buttons.setLayout(new GridLayout(2, false)); + buttons.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + + Button selectAll = new Button(buttons, SWT.NONE); + selectAll.setText(Messages.getString(getClass(), "selectAll")); + selectAll.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + selectAll(); + } + }); + + Button deselectAll = new Button(buttons, SWT.NONE); + deselectAll.setText(Messages.getString(getClass(), "deselectAll")); + deselectAll.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + deselectAll(); + } + }); + + createDestinationArea(composite); + + setControl(composite); + } + + private void createDestinationArea(Composite composite) { + GridData data; + Composite fileArea = new Composite(composite, SWT.NULL); + fileArea.setLayout(new GridLayout(3, false)); + fileArea.setLayoutData( + new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL)); + Label label = new Label(fileArea, SWT.NONE); + label.setText("File name:"); + + this.fileNameText = new Text(fileArea, SWT.BORDER); + data = new GridData(); + data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_FILL; + data.widthHint = 300; + this.fileNameText.setLayoutData(data); + this.fileNameText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent event) { + String text = ((Text) event.getSource()).getText(); + setDestinationIsSelected(text != null && text.trim().length() > 0); + } + }); + + Button button = new Button(fileArea, SWT.NONE); + button.setText("Browse"); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + promptForFile(); + } + }); + } + + private void setSourceIsSelected(boolean selected) { + this.sourceIsSelected = selected; + setPageComplete(selected & this.destinationIsSelected); + } + + private void setDestinationIsSelected(boolean selected) { + this.destinationIsSelected = selected; + setPageComplete(selected & this.sourceIsSelected); + } + + protected void promptForFile() { + + FileDialog dialog = new FileDialog(getShell(), SWT.SAVE); + dialog.setFilterExtensions(new String[] { "xml" }); + dialog.setFilterNames(new String[] { "XML Files (*.xml)"}); + String filename = dialog.open(); + if (filename != null) { + this.fileNameText.setText(filename); + } + } + protected void deselectAll() { + this.treeViewer.setCheckedElements(new Object[0]); + setSourceIsSelected(false); + } + + protected void selectAll() { + Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks(); + this.treeViewer.setCheckedElements(bookmarks); + setSourceIsSelected(bookmarks.length > 0); + } + + public boolean finish() { + + String fileName = this.fileNameText.getText(); + File file = new File(fileName); + if (file.exists()) { + // prompt for overwrite + } else if (!file.getParentFile().exists()) { + // do what? + } + + try { + Object[] bookmarks = this.treeViewer.getCheckedElements(); + Document document = XMLHelper.createEmptyDocument(); + ModelToXMLConverter.getInstance().createRoot(document); + + for (int i = 0, length = (bookmarks == null) ? 0 : bookmarks.length; + i < length; + i++) { + ModelToXMLConverter.getInstance().convert( + document.getDocumentElement(), (Bookmark) bookmarks[i]); + } + + FileWriter writer = new FileWriter(file); + try { + XMLHelper.write(writer, document); + } finally { + writer.close(); + } + } catch (IOException e) { + ExceptionDisplayDialog.openError(getShell(), + Messages.getString(getClass(), "error.IOException.title"), + Messages.getString(getClass(), "error.IOException.message", + new Object[] { fileName }), e); + } catch (ParserConfigurationException e) { + ExceptionDisplayDialog.openError(getShell(), + Messages.getString(getClass(), "error.IOException.title"), + Messages.getString(getClass(), "error.IOException.message", + new Object[] { fileName }), e); + } + + return true; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportTorqueWizard.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportTorqueWizard.java new file mode 100644 index 0000000..7b05084 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/ExportTorqueWizard.java @@ -0,0 +1,20 @@ +package com.quantum.wizards; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.ui.IExportWizard; +import org.eclipse.ui.IWorkbench; + +/** + * @author BC + */ +public class ExportTorqueWizard extends Wizard implements IExportWizard { + + public boolean performFinish() { + return false; + } + + public void init(IWorkbench workbench, IStructuredSelection selection) { + } + +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/InsertRowPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/InsertRowPage.java new file mode 100644 index 0000000..cbf7ff1 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/InsertRowPage.java @@ -0,0 +1,120 @@ +package com.quantum.wizards; + +import com.quantum.Messages; +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.model.Bookmark; +import com.quantum.model.Entity; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class InsertRowPage extends BaseSQLPage implements SQLPage { + String[] columnNames; + Text[] values; + Label query; + int numColumns = 0; + + public InsertRowPage(String pageName) { + super(pageName); + } + + public void createControl(Composite parent) { + System.out.println("page create control"); //$NON-NLS-1$ + Composite container = new Composite(parent, SWT.NULL); + GridLayout layout = new GridLayout(); + container.setLayout(layout); + layout.numColumns = 2; + + if (row == null) { + System.out.println("Row is null"); //$NON-NLS-1$ + } + if (row.getColumnNames() == null) { + System.out.println("Columns are null"); //$NON-NLS-1$ + } + if (row.getTableData() == null) { + System.out.println("Data is null"); //$NON-NLS-1$ + } + columnNames = row.getColumnNames(); + String[] data = row.getTableData(); + for (int i = 0; i < row.getColumnCount(); i++) { + System.out.println("data = " + i + "=" + data[i]); //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println("column = " + i + "=" + columnNames[i]); //$NON-NLS-1$ //$NON-NLS-2$ + } + values = new Text[row.getColumnCount()]; + new Label(container, SWT.NULL).setText(Messages.getString("InsertRowPage.ColumnName")); //$NON-NLS-1$ + new Label(container, SWT.NULL).setText(Messages.getString("InsertRowPage.Value")); //$NON-NLS-1$ + for (int i = 0; i < row.getColumnCount(); i++) { + Label label = new Label(container, SWT.NULL); + label.setText(columnNames[i]); + values[i] = new Text(container, SWT.BORDER | SWT.SINGLE); + GridData fullHorizontal = new GridData(); + fullHorizontal.horizontalAlignment = GridData.FILL; + values[i].setLayoutData(fullHorizontal); + + //values[i].setText(data[i]); + values[i].addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateQuery(); + } + }); + } + query = new Label(container, SWT.WRAP); + GridData gridData = new GridData(); + gridData.horizontalSpan = layout.numColumns; + gridData.horizontalAlignment = GridData.FILL; + gridData.verticalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + query.setLayoutData(gridData); + + setControl(container); + updateQuery(); + + setPageComplete(true); + } + public void updateQuery() { + System.out.println("Updating query"); //$NON-NLS-1$ + StringBuffer valuesClause = new StringBuffer(); + StringBuffer namesClause = new StringBuffer(); + Bookmark bookmark = row.getBookmark(); + Entity entity = row.getEntity(); + DatabaseAdapter adapter = AdapterFactory.getInstance().getAdapter(bookmark.getType()); + + numColumns = 0; + for (int i = 0; i < columnNames.length; i++) { + String name = columnNames[i]; + String value = values[i].getText(); + if (value.length() > 0) { + if (numColumns > 0) { + valuesClause.append(", "); //$NON-NLS-1$ + namesClause.append(", "); + } + appendColumn(valuesClause, entity, name, adapter, value); + namesClause.append(name); + numColumns++; + } + } + + String query = "INSERT INTO " + row.getTable(); //$NON-NLS-1$ + if (numColumns > 0) { + query += " (" + namesClause + ")"; + query += " VALUES " + "(" + valuesClause; //$NON-NLS-1$ + query += " )"; //$NON-NLS-1$ + } + this.query.setText(query); + } + /* (non-Javadoc) + * @see com.quantum.wizards.BaseSQLPage#getQueryText() + */ + protected String getQueryText() { + return this.query.getText(); + } + +} \ No newline at end of file diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SQLPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SQLPage.java new file mode 100644 index 0000000..32b4322 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SQLPage.java @@ -0,0 +1,11 @@ +package com.quantum.wizards; + +import com.quantum.sql.TableRow; +import com.quantum.view.tableview.TableAdapter; + +import org.eclipse.jface.wizard.IWizardPage; + +public interface SQLPage extends IWizardPage { + public void init(TableRow row, TableAdapter adapter); + public boolean performFinish(); +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SQLRowWizard.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SQLRowWizard.java new file mode 100644 index 0000000..bc37001 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SQLRowWizard.java @@ -0,0 +1,28 @@ +package com.quantum.wizards; + +import com.quantum.sql.TableRow; +import com.quantum.view.tableview.TableAdapter; + +import org.eclipse.jface.wizard.Wizard; + +public class SQLRowWizard extends Wizard { + SQLPage page; + TableRow row; + TableAdapter adapter; + public void init(String title, SQLPage page, TableRow row, TableAdapter adapter) { + System.out.println("Init SQL row wizard"); //$NON-NLS-1$ + this.row = row; + this.adapter = adapter; + this.page = page; + setWindowTitle(title); + } + public boolean performFinish() { + System.out.println("Perform SQL row wizard finish"); //$NON-NLS-1$ + return page.performFinish(); + } + public void addPages() { + System.out.println("QL row wizard adding pages"); //$NON-NLS-1$ + page.init(row, adapter); + addPage(page); + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SortFilterPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SortFilterPage.java new file mode 100644 index 0000000..c23d03e --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/SortFilterPage.java @@ -0,0 +1,180 @@ +package com.quantum.wizards; + +import com.quantum.sql.FilterSort; +import com.quantum.sql.TableRow; +import com.quantum.view.tableview.TableAdapter; +import com.quantum.view.tableview.TableView; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class SortFilterPage extends WizardPage implements SQLPage { + TableRow row; + TableAdapter adapter; + Button[] filter; + Combo[] operator; + Text[] filterValues; + Button[] stringFlags; + Button[] sort; + Combo[] ascDesc; + + String columnNames[]; + Label query; + FilterSort filterSort = new FilterSort(); + public SortFilterPage(String pageName) { + super(pageName); + } + + public void init(TableRow row, TableAdapter adapter) { + this.row = row; + this.adapter = adapter; + } + + public void createControl(Composite parent) { + System.out.println("page create control"); //$NON-NLS-1$ + + Composite container = new Composite(parent, SWT.NULL); + GridLayout layout = new GridLayout(); + container.setLayout(layout); + int layoutColumns = 6; + layout.numColumns = layoutColumns; + + if (row == null) { + System.out.println("Row is null"); //$NON-NLS-1$ + } + if (row.getColumnNames() == null) { + System.out.println("Columns are null"); //$NON-NLS-1$ + } + if (row.getTableData() == null) { + System.out.println("Data is null"); //$NON-NLS-1$ + } + + columnNames = row.getColumnNames(); + String[] data = row.getTableData(); + for (int i = 0; i < row.getColumnCount(); i++) { + System.out.println("data = " + i + "=" + data[i]); //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println("column = " + i + "=" + columnNames[i]); //$NON-NLS-1$ //$NON-NLS-2$ + } + int size = row.getColumnCount(); + filter = new Button[size]; + operator = new Combo[size]; + filterValues = new Text[size]; + stringFlags = new Button[size]; + sort = new Button[size]; + ascDesc = new Combo[size]; + for (int i = 0; i < row.getColumnCount(); i++) { + filter[i] = new Button(container, SWT.CHECK); + filter[i].setText(columnNames[i]); + filter[i].addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + updateQuery(); + } + }); + + operator[i] = new Combo(container, SWT.SINGLE | SWT.READ_ONLY); + operator[i].add("="); //$NON-NLS-1$ + operator[i].add("<>"); //$NON-NLS-1$ + operator[i].add("<"); //$NON-NLS-1$ + operator[i].add(">"); //$NON-NLS-1$ + operator[i].addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + updateQuery(); + } + }); + + filterValues[i] = new Text(container, SWT.BORDER); + filterValues[i].setText(data[i]); + filterValues[i].addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateQuery(); + } + }); + + stringFlags[i] = new Button(container, SWT.CHECK); + stringFlags[i].setText("String"); //$NON-NLS-1$ + stringFlags[i].addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + updateQuery(); + } + }); + + final int index = i; + sort[i] = new Button(container, SWT.CHECK); + sort[i].setText(columnNames[i]); + sort[i].addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + if (sort[index].getSelection()) { + filterSort.addSort(columnNames[index], ascDesc[index].getText()); + } else { + filterSort.removeSort(columnNames[index]); + } + updateQuery(); + } + }); + + ascDesc[i] = new Combo(container, SWT.SINGLE | SWT.READ_ONLY); + ascDesc[i].add(""); //$NON-NLS-1$ + ascDesc[i].add("ASC"); //$NON-NLS-1$ + ascDesc[i].add("DESC"); //$NON-NLS-1$ + ascDesc[i].addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + if (sort[index].getSelection()) { + filterSort.addSort(columnNames[index], ascDesc[index].getText()); + } else { + filterSort.removeSort(columnNames[index]); + } + updateQuery(); + } + }); + } + query = new Label(container, SWT.WRAP); + GridData gridData = new GridData(); + gridData.horizontalSpan = layoutColumns; + gridData.horizontalAlignment = GridData.FILL; + gridData.verticalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + query.setLayoutData(gridData); + + setControl(container); + + setPageComplete(true); + } + + public void updateQuery() { + filterSort.clearFilters(); + for (int i = 0; i < filter.length; i++) { + if (filter[i].getSelection()) { + filterSort.addFilter(filter[i].getText(), operator[i].getText(), filterValues[i].getText(), stringFlags[i].getSelection()); + } + } + query.setText(filterSort.toString()); + } + + public boolean performFinish() { + adapter.setFilterSort(filterSort); + TableView.getInstance().refreshCurrent(); + return true; + } +} diff --git a/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/UpdateRowPage.java b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/UpdateRowPage.java new file mode 100644 index 0000000..b057d59 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.quantum.sql/src/com/quantum/wizards/UpdateRowPage.java @@ -0,0 +1,166 @@ +package com.quantum.wizards; + +import com.quantum.Messages; +import com.quantum.adapters.AdapterFactory; +import com.quantum.adapters.DatabaseAdapter; +import com.quantum.model.Bookmark; +import com.quantum.model.Entity; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +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.Label; +import org.eclipse.swt.widgets.Text; + +public class UpdateRowPage extends BaseSQLPage implements SQLPage { + String[] columnNames; + Text[] oldValues; + Text[] newValues; + Button[] primaryKeys; + Button[] setValues; + Label query; + public UpdateRowPage(String pageName) { + super(pageName); + } + + public void createControl(Composite parent) { + System.out.println("page create control"); //$NON-NLS-1$ + Composite container = new Composite(parent, SWT.V_SCROLL); + GridLayout layout = new GridLayout(); + container.setLayout(layout); + Entity entity = row.getEntity(); + + int layoutColumns = 5; + layout.numColumns = layoutColumns; + + if (row == null) { + System.out.println("Row is null"); //$NON-NLS-1$ + } + if (row.getColumnNames() == null) { + System.out.println("Columns are null"); //$NON-NLS-1$ + } + if (row.getTableData() == null) { + System.out.println("Data is null"); //$NON-NLS-1$ + } + columnNames = row.getColumnNames(); + String[] data = row.getTableData(); + for (int i = 0; i < row.getColumnCount(); i++) { + System.out.println("data = " + i + "=" + data[i]); //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println("column = " + i + "=" + columnNames[i]); //$NON-NLS-1$ //$NON-NLS-2$ + } + oldValues = new Text[row.getColumnCount()]; + newValues = new Text[row.getColumnCount()]; + primaryKeys = new Button[row.getColumnCount()]; + setValues = new Button[row.getColumnCount()]; + Label temp = new Label(container, SWT.NULL); + temp.setText(Messages.getString("UpdateRowPage.ColumnName")); //$NON-NLS-1$ + temp = new Label(container, SWT.NULL); + temp.setText(Messages.getString("UpdateRowPage.OldValue")); //$NON-NLS-1$ + temp = new Label(container, SWT.NULL); + temp.setText(""); //$NON-NLS-1$ + temp = new Label(container, SWT.NULL); + temp.setText(Messages.getString("UpdateRowPage.NewValue")); //$NON-NLS-1$ + temp = new Label(container, SWT.NULL); + temp.setText(Messages.getString("UpdateRowPage._13")); //$NON-NLS-1$ + for (int i = 0; i < row.getColumnCount(); i++) { + Label label = new Label(container, SWT.NULL); + label.setText(columnNames[i]); + oldValues[i] = new Text(container, SWT.BORDER | SWT.SINGLE); + oldValues[i].setText(data[i]); + oldValues[i].addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateQuery(); + } + }); + primaryKeys[i] = new Button(container, SWT.CHECK); + primaryKeys[i].setText("Where"); //$NON-NLS-1$ + if (entity != null && entity.getColumn(columnNames[i]).isPrimaryKey()) + primaryKeys[i].setSelection(true); + primaryKeys[i].addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + updateQuery(); + } + }); + newValues[i] = new Text(container, SWT.BORDER | SWT.SINGLE); + newValues[i].setText(data[i]); + newValues[i].addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateQuery(); + } + }); + setValues[i] = new Button(container, SWT.CHECK); + setValues[i].setText(Messages.getString("UpdateRowPage.SetValue")); //$NON-NLS-1$ + setValues[i].addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + updateQuery(); + } + }); + } + query = new Label(container, SWT.WRAP | SWT.V_SCROLL); + GridData gridData = new GridData(); + gridData.horizontalSpan = layoutColumns; + gridData.horizontalAlignment = GridData.FILL; + gridData.verticalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + query.setLayoutData(gridData); + + setControl(container); + updateQuery(); + + setPageComplete(true); + } + public void updateQuery() { + System.out.println("Updating query"); //$NON-NLS-1$ + StringBuffer setClause = new StringBuffer(); + StringBuffer whereClause = new StringBuffer(); + Bookmark bookmark = row.getBookmark(); + Entity entity = row.getEntity(); + DatabaseAdapter adapter = AdapterFactory.getInstance().getAdapter(bookmark.getType()); + + int numValuesSet = 0; + int numValuesWhere = 0; + for (int i = 0; i < columnNames.length; i++) { + if (primaryKeys[i].getSelection()) { + String value = oldValues[i].getText(); + if (numValuesWhere > 0) whereClause.append(" AND "); //$NON-NLS-1$ + whereClause.append("("); //$NON-NLS-1$ + whereClause.append(columnNames[i]); + whereClause.append(" = "); //$NON-NLS-1$ + appendColumn(whereClause, entity, columnNames[i], adapter, value); + whereClause.append(")"); //$NON-NLS-1$ + numValuesWhere++; + } + if (setValues[i].getSelection()) { + String value = newValues[i].getText(); + if (numValuesSet > 0) setClause.append(", "); //$NON-NLS-1$ + setClause.append(columnNames[i]); + setClause.append(" = "); //$NON-NLS-1$ + appendColumn(setClause, entity, columnNames[i], adapter, value); + numValuesSet++; + } + } + String query = "UPDATE " + row.getTable(); //$NON-NLS-1$ + query += " SET " + setClause.toString(); //$NON-NLS-1$ + query += " WHERE " + whereClause.toString(); //$NON-NLS-1$ + this.query.setText(query); + } + + /* (non-Javadoc) + * @see com.quantum.wizards.BaseSQLPage#getQueryText() + */ + protected String getQueryText() { + return query.getText(); + } + +} \ No newline at end of file -- 1.7.1