Compare commits

...

169 Commits

Author SHA1 Message Date
Wisser acd0ec4f17 update UI asynchronously 2018-10-05 14:21:42 +02:00
Wisser a4ef8ac522 open table only if tree node is selected 2018-10-05 13:32:01 +02:00
Wisser 0bb4e9f649 Increased responsiveness and performance of the data browser GUI 2018-10-05 08:57:27 +02:00
Wisser da1e4ccd2a performance optimization 2018-10-05 07:53:07 +02:00
Wisser cecf7d33b8 disabled FPS logging 2018-10-04 12:50:34 +02:00
Wisser 95951cf824 performance optimization 2018-10-04 12:47:04 +02:00
Wisser e1c7f5074f release notes update 2018-10-04 09:25:32 +02:00
Wisser 408ecfc5fc minor GUI improvements 2018-10-04 09:21:11 +02:00
Wisser 971a870e51 new option "Set foreign key columns to null" 2018-10-02 10:47:04 +02:00
Wisser 25cedf87d0 disable workingTableSchemaComboBox if scope is "local" 2018-10-02 09:20:13 +02:00
Wisser b750d45050 release notes update 2018-09-19 16:46:07 +02:00
Wisser 97b435aa1b create new base folder 2018-09-19 16:45:00 +02:00
Wisser 40aa392935 release notes update 2018-09-19 16:19:19 +02:00
Wisser 0046ef0f2d set VERSION to 8 2018-09-19 16:17:45 +02:00
Wisser 5eb5677799 prevent the data model from being loaded twice 2018-09-19 16:16:43 +02:00
Wisser 03a2bf820e resetTableTableModel after table edition 2018-09-18 19:28:46 +02:00
Wisser 6592f0f86f don't share progressListenerRegistry 2018-09-18 19:25:14 +02:00
Wisser efd799b217 create new ExecutionContext for each EMF 2018-09-18 19:22:39 +02:00
Wisser 7c0ce25871 PathFinder improvements 2018-09-18 19:05:22 +02:00
Wisser d0b1465177 PathFinder improvements 2018-09-17 18:50:08 +02:00
Wisser e7e9634768 release notes update 2018-09-15 10:13:04 +02:00
Wisser 3a95e5e86c PathFinder history 2018-09-15 10:11:57 +02:00
Wisser 40b56a2f0f removed obsolete menu items 2018-09-12 11:49:05 +02:00
Wisser 9ae5037037 fixed NPE 2018-09-12 09:53:41 +02:00
Wisser b217529023 organized imports 2018-09-12 09:33:38 +02:00
Wisser 108791f0b4 PathFinder integration 2018-09-12 09:21:31 +02:00
Wisser 3934482984 reduced EXPAND_SINGLE_TABLE_LIMIT 2018-09-11 14:32:44 +02:00
Wisser 7efa9721c9 reordering column is not allowed 2018-09-11 09:34:42 +02:00
Wisser 78977fde51 restore view position after reload 2018-09-11 09:31:38 +02:00
Wisser 40d80f6ae1 release notes update 2018-09-11 09:06:13 +02:00
Wisser 0bf59e8340 increased version 2018-09-11 09:01:53 +02:00
Wisser 1099d41e68 select all tables on path 2018-09-11 09:01:25 +02:00
Wisser cf52be38ec new image 2018-09-11 07:06:59 +02:00
Wisser a0db0e8387 new feature "PathFinder" 2018-09-11 07:05:30 +02:00
Wisser a48b4faba1 release notes update 2018-09-05 15:34:25 +02:00
Wisser 75e2b1164c release note 2018-09-05 15:30:59 +02:00
Wisser 253032ba92 convertChildrenToRoots if single table is closed 2018-09-05 14:41:09 +02:00
Wisser 20da29b810 prefer exact match 2018-09-05 14:33:16 +02:00
Wisser 7b12c5df99 updated JSqlParser 2018-08-31 13:44:58 +02:00
Wisser 2e487cd77a update 2018-08-31 13:44:12 +02:00
Wisser c0d097e8ea release notes update 2018-08-31 12:32:03 +02:00
Wisser 42c7f60ac6 Merge branch 'master' of https://github.com/Wisser/Jailer.git 2018-08-31 12:29:40 +02:00
Wisser 3683debe1e new popup menu item "Exclude all" 2018-08-31 08:54:01 +02:00
Wisser 1026bab646 lazy init of Condition Editor 2018-08-31 08:53:03 +02:00
Wisser 8a0ef29cda set version to 7.11 2018-08-30 16:25:42 +02:00
Wisser 029459a9d5 set version 2018-08-30 16:17:02 +02:00
Wisser 9bd30aef3e don't change tooltip delay 2018-08-30 08:05:58 +02:00
Wisser 17161ed441 don't change tooltip delay 2018-08-30 08:05:30 +02:00
Wisser 0a1c74b8d0 release notes update 2018-08-30 07:41:00 +02:00
Wisser 67a0f71a31 set version to 7.11 2018-08-30 07:40:41 +02:00
Wisser a72e7fdb20 new PrivilegedSessionProviderDialog 2018-08-30 07:40:19 +02:00
Wisser ae60ccd0fc Database analysis finds PKs and FKs for views and synonyms too 2018-08-30 06:24:44 +02:00
Wisser d9ff02d0d9 added viewTextOrDDLQuery for DB2 2018-08-28 14:51:47 +02:00
Wisser 09be36cade added viewTextQuery for MySQL 2018-08-28 14:19:03 +02:00
Wisser e50d88ddfe release notes update 2018-08-28 13:14:17 +02:00
Wisser 7146e61013 Database analysis finds PKs and FKs for views and synonyms 2018-08-28 13:13:15 +02:00
Wisser 67e552a7a1 release notes update 2018-08-23 16:18:27 +02:00
Wisser 5a48e73bc1 "close table" option pane is a QUESTION_MESSAGE 2018-08-23 16:17:23 +02:00
Wisser cd838a2858 release notes update 2018-08-23 15:48:54 +02:00
Wisser 5a2ce2eac8 do not logFPS 2018-08-23 15:47:26 +02:00
Wisser 68ddf0a175 release notes update 2018-08-23 11:56:11 +02:00
Wisser e389c53861 animation performance optimization and table filter for data model
editor
2018-08-23 11:52:54 +02:00
Wisser 9ee90fc714 release notes update 2018-08-22 14:41:36 +02:00
Wisser c2c04ab1fb reduced MAX_RETENDION 2018-08-22 14:40:48 +02:00
Wisser e3093b9593 wait-cursor management 2018-08-22 09:20:09 +02:00
Wisser 971613186f Improved row-link performance 2018-08-22 08:32:56 +02:00
Wisser 3463fb4766 wait-cursor management 2018-08-21 12:39:04 +02:00
Wisser 282c1cd180 wait-cursor management 2018-08-21 12:38:28 +02:00
Wisser 3a1f98c7bd New layout feature: "align horizontally with predecessor" 2018-08-20 13:56:55 +02:00
Wisser e1b0c23404 introduced DesktopAnchorManager 2018-08-20 13:51:12 +02:00
Wisser 07f25822d5 call getPreciseWheelRotation without reflection 2018-08-14 13:31:50 +02:00
Wisser 3d03b1227a increase rescale end only if rescaleFactorHasChanged 2018-08-14 13:05:33 +02:00
Wisser 1d7806f96d increased rescale-mode duration 2018-08-14 08:37:58 +02:00
Wisser dc5992e0e5 Zoom in / out using the mouse wheel in the data browser 2018-08-14 08:23:14 +02:00
Wisser c9f53810d1 added JAXB libs 2018-08-10 15:40:52 +02:00
Wisser 051d24e1b1 stop scrolling on mouse dragged event 2018-08-10 15:39:54 +02:00
Wisser 7ae893da24 release notes update 2018-08-10 12:11:11 +02:00
Wisser ed913077c7 minor bug fixes 2018-08-10 12:09:43 +02:00
Wisser f35c5b0329 repaint rows-closure immediately 2018-08-10 08:01:39 +02:00
Wisser 33262683f1 minor improvements 2018-08-10 06:59:46 +02:00
Wisser 40a6d7d853 set version to 7.10.6 2018-08-09 12:14:09 +02:00
Wisser aded0c6529 added tool tips 2018-08-09 12:13:29 +02:00
Wisser db972ee841 checkDesktopSize during animation 2018-08-08 14:34:10 +02:00
Wisser 1f3e0182c9 Fixed self assignment of field 2018-08-08 13:21:27 +02:00
Wisser aaaa07b381 reduced animation latency 2018-08-08 09:37:16 +02:00
Wisser d26423bf9f increased animation latency when the pop-up menu is visible 2018-08-08 08:08:58 +02:00
Wisser 09bc381a4e use sigmoid-function to control the animation 2018-08-07 08:16:43 +02:00
Wisser 8f5147f870 increased duration 2018-08-06 13:06:48 +02:00
Wisser e367fc6062 improved default sort column definition 2018-08-06 08:47:20 +02:00
Wisser 395b447f86 reduced duration 2018-08-06 08:46:07 +02:00
Wisser 0ed829c065 release notes update 2018-08-03 10:37:39 +02:00
Wisser 9c85f3955e deferred animation 2018-08-03 10:35:55 +02:00
Wisser 2a379b8543 release notes update 2018-08-02 09:59:13 +02:00
Wisser d00acf3881 improved row-link rendering and performance 2018-08-02 09:58:34 +02:00
Wisser ce3c3192e9 increased BROWSERTABLE_DEFAULT_DISTANCE 2018-08-01 14:20:47 +02:00
Wisser 29cbd7dcf9 improved animation performance 2018-08-01 14:05:27 +02:00
Wisser f92e7d6f13 stop scrolling when location has changed externally 2018-08-01 12:33:50 +02:00
Wisser 6c55ea8092 layout on internalFrameClosed 2018-08-01 12:32:34 +02:00
Wisser b2ce10891f release note update 2018-08-01 10:21:51 +02:00
Wisser d86866758b added documentation 2018-08-01 10:21:25 +02:00
Wisser f3224ad625 Animated desktop layout in the data browser 2018-08-01 10:20:17 +02:00
Wisser 5b391b85b7 introduced "DesktopAnimation" 2018-08-01 08:12:39 +02:00
Wisser 8a8cd325b1 set version to 7.10.5 2018-07-30 07:20:58 +02:00
Wisser c1a885f220 disable button 2018-07-30 07:20:07 +02:00
Wisser 2fa811b6c6 release notes update 2018-07-27 14:52:15 +02:00
Wisser 3bfc6aa51d don't show "estimated row count" for views 2018-07-27 14:51:19 +02:00
Wisser 322c830054 release notes update 2018-07-27 14:16:27 +02:00
Wisser 29e460f79f changed color of "estimated row count" label 2018-07-27 14:15:54 +02:00
Wisser 0254c26e09 Updated H2 DBMS from version 1.3.160 to 1.3.175 2018-07-27 13:09:27 +02:00
Wisser c37064be01 added "ANALYZE TABLE" statements 2018-07-27 10:05:06 +02:00
Wisser 92bc5b3ef9 release notes update 2018-07-27 08:44:23 +02:00
Wisser 6a99fd76a6 The estimated number of rows of the tables is displayed 2018-07-27 08:43:57 +02:00
Wisser a584fa787b release notes update 2018-07-20 10:37:45 +02:00
Wisser 8e08a70e21 verify version number 2018-07-20 07:22:06 +02:00
Wisser b72802c67c release notes update 2018-07-06 10:18:29 +02:00
Wisser 04a5df43e8 don't set java.net.useSystemProxies 2018-07-06 10:18:08 +02:00
Wisser 1518e02736 release notes update 2018-07-06 09:38:06 +02:00
Wisser 9e2a04abd1 reset system property 2018-07-06 09:36:43 +02:00
Wisser d8bf797c16 Added context menu to columns view of results table 2018-07-05 08:01:59 +02:00
Wisser 2778b8d843 Added context menu to columns view of results table 2018-07-04 10:05:24 +02:00
Wisser 5bc07beffa release notes update 2018-06-20 16:57:48 +02:00
Wisser c85fddde8e release notes update 2018-06-20 16:49:48 +02:00
Wisser 2a2b0fbe60 preparing release 7.10 2018-06-20 16:29:11 +02:00
Wisser 7b7bfc289a changed color of "rowsCount" label 2018-06-18 15:35:54 +02:00
Wisser 830a37f55e more detailed error message 2018-06-18 11:45:16 +02:00
Wisser b2ae7d6d79 set font style of row number label to bold 2018-06-18 11:27:20 +02:00
Wisser 384411c2eb improved row limit rendering 2018-06-18 10:39:28 +02:00
Wisser fff9e21a2b propagate "isClosureLimitExceeded" 2018-06-18 10:06:02 +02:00
Wisser d663e19099 added "Row Limit" menu. 2018-06-18 09:28:29 +02:00
Wisser 92956ee4bd moved "related rows" button to north east 2018-06-18 07:02:08 +02:00
Wisser 08d12c7b6f allow "insert child" for associations too 2018-06-15 12:15:08 +02:00
Wisser 9462a21513 prefer table name from datamodel 2018-06-15 09:08:13 +02:00
Wisser c40fb7c739 new item in "Create SQL" menu: "insert child" 2018-06-15 08:38:39 +02:00
Wisser 4b57dcc48a reduced alpha factor 2018-06-14 16:02:37 +02:00
Wisser a6b65a2981 new icon navigation.png 2018-06-14 15:33:57 +02:00
Wisser 82d4f7778f new icon "navigation.png" 2018-06-14 14:56:51 +02:00
Wisser 277afba7e7 performance optimization 2018-06-14 09:53:46 +02:00
Wisser 528c3f83c6 performance optimization 2018-06-14 08:02:29 +02:00
Wisser edb946cd81 show WAIT_CURSOR while closing subtree 2018-06-14 07:13:25 +02:00
Wisser bf414de46b inserted some rows into BONUS 2018-06-14 07:01:04 +02:00
Wisser c6d6997dfc "LOCAL_DATABASE" led to concurrency problems and connection leaks 2018-06-13 14:11:45 +02:00
Wisser 2d69a07943 improved DesktopIFrameStateChangeRenderer 2018-06-13 12:10:55 +02:00
Wisser 754d873f47 new class DesktopIFrameStateChangeRenderer 2018-06-13 10:26:35 +02:00
Wisser 8cf01ea83e more robustness if table has no primary key 2018-06-12 13:02:59 +02:00
Wisser b151191696 adjusted colors 2018-06-12 11:39:29 +02:00
Wisser 8dd427af95 prevent creating ui-components in other thread than EDT 2018-06-12 11:01:19 +02:00
Wisser c9de663911 no "Create Script" menu for anonymous tables 2018-06-12 09:18:03 +02:00
Wisser 4378e59a1b removed obsolete TODO comment 2018-06-12 08:07:48 +02:00
Wisser 80671e3802 UI improvements 2018-06-12 08:07:21 +02:00
Wisser d624142787 prefer leftmost table 2018-06-11 15:06:09 +02:00
Wisser 56527be4db release notes update 2018-06-11 14:33:04 +02:00
Wisser 694b436b50 automatic select/deselect of single rows 2018-06-11 14:31:21 +02:00
Wisser 0723d007aa prevent updateUIThread from aborting 2018-06-08 07:34:01 +02:00
Wisser 3241853eb2 assure that value of millis is not negative 2018-06-08 07:28:26 +02:00
Wisser 6f809bc67a release notes update 2018-06-08 07:00:18 +02:00
Wisser 6d9adac372 increased STEP_DELAY 2018-06-08 06:59:51 +02:00
Wisser bb3c8b04a1 release notes updates 2018-06-07 13:06:40 +02:00
Wisser ec2213d474 changed background color of tables 2018-06-07 13:02:17 +02:00
Wisser 1e8a688e8e set alpha of marker color 2018-06-07 12:08:10 +02:00
Wisser 3b038ce89c UI improvements 2018-06-07 10:28:14 +02:00
Wisser 0f43a9ed61 animated row-to-row-links 2018-06-06 13:41:57 +02:00
Wisser 17cdae8737 animation of row-to-row links 2018-06-06 08:17:48 +02:00
Wisser 168aacaf3d Increased rendering quality of row-link. 2018-06-05 14:08:59 +02:00
Wisser 21b1ef0307 Increased rendering quality of row-link. 2018-06-05 13:32:05 +02:00
Wisser ddd700cdca Increased rendering quality of row-link. 2018-06-05 09:24:12 +02:00
Wisser de5bea6073 improved render quality 2018-06-05 08:52:48 +02:00
Wisser 1107806610 release notes update 2018-06-05 08:21:00 +02:00
Wisser 2b584b224d Merge branch 'master' of https://github.com/Wisser/Jailer.git 2018-06-05 08:18:10 +02:00
Wisser 54960ad2d7 increased rendering quality of row-links 2018-06-05 08:17:50 +02:00
105 changed files with 11677 additions and 4008 deletions
+25 -17
View File
@@ -1,17 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/test"/>
<classpathentry kind="src" path="src/main/engine"/>
<classpathentry kind="src" path="src/main/gui"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/dbunit-2.4.4.jar"/>
<classpathentry kind="lib" path="lib/junit-4.4.jar"/>
<classpathentry kind="lib" path="lib/log4j.jar"/>
<classpathentry kind="lib" path="lib/prefuse.jar" />
<classpathentry kind="lib" path="lib/sdoc-0.5.0-beta.jar" />
<classpathentry kind="lib" path="lib/args4j.jar"/>
<classpathentry kind="lib" path="config"/>
<classpathentry kind="lib" path="lib/jsqlparser-1.1.jar" />
<classpathentry kind="lib" path="lib/tablefilter-swing-5.3.1.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/test"/>
<classpathentry kind="src" path="src/main/engine"/>
<classpathentry kind="src" path="src/main/gui"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/dbunit-2.4.4.jar"/>
<classpathentry kind="lib" path="lib/junit-4.4.jar"/>
<classpathentry kind="lib" path="lib/log4j.jar"/>
<classpathentry kind="lib" path="lib/prefuse.jar"/>
<classpathentry kind="lib" path="lib/sdoc-0.5.0-beta.jar"/>
<classpathentry kind="lib" path="lib/args4j.jar"/>
<classpathentry kind="lib" path="config"/>
<classpathentry kind="lib" path="lib/jsqlparser-1.1.jar"/>
<classpathentry kind="lib" path="lib/tablefilter-swing-5.3.1.jar"/>
<classpathentry kind="lib" path="lib/jaxb-api-2.3.0-b170201.1204.jar"/>
<classpathentry kind="lib" path="lib/jaxb-core-2.3.0-b170127.1453.jar"/>
<classpathentry kind="lib" path="lib/jaxb-impl-2.3.0-b170127.1453.jar"/>
<classpathentry kind="lib" path="lib/activation-1.0.2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
BIN
View File
Binary file not shown.
+2 -2
View File
@@ -12,8 +12,8 @@ Informix Dynamic Server;jdbc:informix-sqli://<HOST>:<PORT>/<DB>:INFORMIXSERVER=<
InstantDB (v3.13 and earlier);jdbc:idb:<DB>;jdbc.idbDriver
InstantDB (v3.14 and later);jdbc:idb:<DB>;org.enhydra.instantdb.jdbc.idbDriver
Interbase (InterClient Driver);jdbc:interbase://<HOST>/<DB>;interbase.interclient.Driver
H2 embedded (Java SQL database);jdbc:h2:<DB-File>;org.h2.Driver;lib/h2-1.3.160.jar
H2 TCP (Java SQL database);jdbc:h2:tcp://<HOST>/<DB-File>;org.h2.Driver;lib/h2-1.3.160.jar
H2 embedded (Java SQL database);jdbc:h2:<DB-File>;org.h2.Driver;lib/h2-1.3.175.jar
H2 TCP (Java SQL database);jdbc:h2:tcp://<HOST>/<DB-File>;org.h2.Driver;lib/h2-1.3.175.jar
HyperSQL;jdbc:hsqldb:<file|hsql|http>:<DB>;org.hsqldb.jdbcDriver
# Microsoft SQL Server (jTDS);jdbc:jtds:sqlserver://<server>[:<port>][/<database>];net.sourceforge.jtds.jdbc.Driver;lib/jtds-1.3.1.jar
# Microsoft SQL Server (JTurbo Driver);jdbc:JTurbo://<HOST>:<PORT>/<DB>;com.ashna.jturbo.driver.Driver
1 IBM DB2 Alias jdbc:db2://<HOST>:<PORT>/<DB> COM.ibm.db2.jdbc.app.DB2Driver
12 InstantDB (v3.13 and earlier) jdbc:idb:<DB> jdbc.idbDriver
13 InstantDB (v3.14 and later) jdbc:idb:<DB> org.enhydra.instantdb.jdbc.idbDriver
14 Interbase (InterClient Driver) jdbc:interbase://<HOST>/<DB> interbase.interclient.Driver
15 H2 embedded (Java SQL database) jdbc:h2:<DB-File> org.h2.Driver
16 H2 TCP (Java SQL database) jdbc:h2:tcp://<HOST>/<DB-File> org.h2.Driver
17 HyperSQL jdbc:hsqldb:<file|hsql|http>:<DB> org.hsqldb.jdbcDriver
18 # Microsoft SQL Server (jTDS) jdbc:jtds:sqlserver://<server>[:<port>][/<database>] net.sourceforge.jtds.jdbc.Driver
19 # Microsoft SQL Server (JTurbo Driver) jdbc:JTurbo://<HOST>:<PORT>/<DB> com.ashna.jturbo.driver.Driver
Binary file not shown.
Binary file not shown.
+53
View File
@@ -1,3 +1,56 @@
8.0.1
- Foreign key columns can be set to null if parent row is not exported.
- Increased responsiveness and performance of the data browser GUI.
8.0
- The new "PathFinder" feature allows elaborate finding
of association paths between tables in complex data models.
7.11.1
- Closing a root table did not work properly in the data browser.
- Minor bug fixes.
7.11
- Database analysis not only finds primary keys and foreign keys for tables,
but also for views and synonyms by analyzing the underlying tables.
- Fixed a memory leak in data browser.
7.10.8
- Data browser improvements
- New layout feature: "align table horizontally with predecessor"
- Improved layout strategy in the data browser.
- Improved row-to-row-link rendering performance.
- Feature Request "Improve the usability of the Data Model Editor" (partially). see https://sourceforge.net/p/jailer/feature-requests/43/
7.10.7
- Zoom in / out using the mouse wheel in the data browser
7.10.6
- Minor bug fixes.
7.10.5
- Animated desktop layout in the data browser.
- Improved row-link rendering quality and performance.
7.10.4
- The estimated number of rows of the tables is displayed.
- Limited fetch size of statements to prevent an OOM exception when the default fetch size is too large (MySQL).
- Updated H2 DBMS from version 1.3.160 to 1.3.175
7.10.3
- Fix for "Can't connect to SOCKS proxy:http" https://github.com/Wisser/Jailer/issues/8
7.10.2
- Added context menu to columns view of results table.
7.10
- Comprehensive usability improvements of the data browser.
- Animated row-to-row links.
- Increased rendering quality of row-to-row link.
- Automatic layouting of data browser desktop.
- Using working-table-scope "LOCAL_DATABASE" led to concurrency problems and connection leaks.
- Update of SQL keyword catalog to SQL 2003 standard.
7.9.3
- Data browser: prevented that context menu automatically gets closed if the item doesn't have the focus.
@@ -77,7 +77,7 @@ public class ExecutionContext {
this.importFilterMappingTableSchema = other.importFilterMappingTableSchema;
this.scope = other.scope;
this.rawparameters = other.rawparameters;
this.progressListenerRegistry = other.progressListenerRegistry;
// don't share progressListenerRegistry, was: this.progressListenerRegistry = other.progressListenerRegistry;
}
/**
@@ -639,7 +639,7 @@ public class ExecutionContext {
}
private URL datamodelURL;
/**
* Gets URL of the current data model (the datamodels base folder)
*/
@@ -652,14 +652,14 @@ public class ExecutionContext {
fn = datamodelFolder + File.separator + currentModelSubfolder;
}
try {
datamodelURL = new File(fn).toURI().toURL();
return new File(fn).toURI().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
return datamodelURL;
}
/**
* Sets URL of the current data model (the datamodels base folder)
*/
@@ -815,4 +815,4 @@ public class ExecutionContext {
return map == null? null : new HashMap<String, String>(map);
}
}
}
@@ -131,7 +131,6 @@ public class Jailer {
*/
public static boolean jailerMain(String[] args, StringBuffer warnings, ProgressListener progressListener) throws Exception {
CancellationHandler.reset(null);
Session.closeTemporaryTableSession();
try {
CommandLine commandLine = CommandLineParser.parse(args, false);
@@ -268,8 +267,6 @@ public class Jailer {
String workingDirectory = System.getProperty("user.dir");
_log.error("working directory is " + workingDirectory);
throw e;
} finally {
Session.closeTemporaryTableSession();
}
}
@@ -25,7 +25,7 @@ public class JailerVersion {
/**
* The Jailer version.
*/
public static final String VERSION = "7.9.3";
public static final String VERSION = "8.0.1";
/**
* The Jailer working tables version.
@@ -42,7 +42,7 @@ public class APIExample {
new BasicDataSource(
"org.h2.Driver", "jdbc:h2:demo-scott", "sa", "",
POOL_SIZE,
new File("lib/h2-1.3.160.jar")),
new File("lib/h2-1.3.175.jar")),
null,
APIExample.class.getResource("Demo-Scott"),
APIExample.class.getResource("Demo-Scott.csv"),
@@ -54,7 +54,7 @@ public class APIExample {
new BasicDataSource(
"org.h2.Driver", "jdbc:h2:demo-scott-subset", "sa", "",
10,
new File("lib/h2-1.3.160.jar")));
new File("lib/h2-1.3.175.jar")));
/**
* Exports data related with employee "SCOTT"
@@ -113,6 +113,17 @@ public class Configuration {
private int columnsPerIFMTable = 8;
private String additionalSQLKeywords;
public String getAdditionalSQLKeywords() {
return additionalSQLKeywords;
}
public void setAdditionalSQLKeywords(String additionalSQLKeywords) {
this.additionalSQLKeywords = additionalSQLKeywords;
}
/**
* Gets replacement for null in DBUnit datasets.
*
@@ -238,5 +249,4 @@ public class Configuration {
static {
DBMS.values(); // trigger static init
}
}
@@ -104,6 +104,9 @@ public class DBMS {
this.rowidName = other.rowidName;
this.supportsSchemasInIndexDefinitions = other.supportsSchemasInIndexDefinitions;
this.useInlineViewsInDataBrowser = other.useInlineViewsInDataBrowser;
this.viewTextOrDDLQuery = other.viewTextOrDDLQuery;
this.synonymTableQuery = other.synonymTableQuery;
this.estimatedRowCountQuery = other.estimatedRowCountQuery;
this.virtualColumnsQuery = other.virtualColumnsQuery;
this.userDefinedColumnsQuery = other.userDefinedColumnsQuery;
this.importedKeysQuery = other.importedKeysQuery;
@@ -291,12 +294,12 @@ public class DBMS {
private Boolean supportsSchemasInIndexDefinitions = null;
private boolean useInlineViewsInDataBrowser = true;
private String virtualColumnsQuery = null;
private String synonymTableQuery;
private String viewTextOrDDLQuery = "SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%1$s' and TABLE_NAME = '%2$s'";
private String estimatedRowCountQuery = null;
private String userDefinedColumnsQuery = null;
private String importedKeysQuery = null;
private String primaryKeysQuery = null;
private String indexInfoQuery = null;
private String identifierQuoteString = "\"";
@@ -520,7 +523,11 @@ public class DBMS {
public Map<String, String> getTypeReplacement() {
if (!this.equals(DBMS.ORACLE)) {
if (typeReplacement == null || !typeReplacement.containsKey("VARCHAR2")) {
typeReplacement = new HashMap<String, String>(typeReplacement);
if (typeReplacement == null) {
typeReplacement = new HashMap<String, String>();
} else {
typeReplacement = new HashMap<String, String>(typeReplacement);
}
typeReplacement.put("VARCHAR2", "VARCHAR");
}
}
@@ -1007,6 +1014,42 @@ public class DBMS {
this.constraintsQuery = constraintsQuery;
}
/**
* Gets query to get row count.
*/
public String getEstimatedRowCountQuery() {
return estimatedRowCountQuery;
}
/**
* Sets query to get row count.
*/
public void setEstimatedRowCountQuery(String estimatedRowCountQuery) {
this.estimatedRowCountQuery = estimatedRowCountQuery;
}
/**
* Gets query to get view text.
*/
public String getViewTextOrDDLQuery() {
return viewTextOrDDLQuery;
}
public void setViewTextOrDDLQuery(String viewTextOrDDLQuery) {
this.viewTextOrDDLQuery = viewTextOrDDLQuery;
}
/**
* Gets query to get underlying table of a synonym.
*/
public String getSynonymTableQuery() {
return synonymTableQuery;
}
public void setSynonymTableQuery(String synonymTableQuery) {
this.synonymTableQuery = synonymTableQuery;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@@ -32,7 +32,7 @@ public class LocalDatabaseConfiguration {
private String password = "";
private String driver = "org.h2.Driver";
private String lib = "lib/h2-1.3.160.jar";
private String lib = "lib/h2-1.3.175.jar";
/**
* @return the localPKType
@@ -4,7 +4,7 @@
<!-- Configuration of the local database -->
<localDatabase>
<databaseFolder>local</databaseFolder>
<lib>lib/h2-1.3.160.jar</lib>
<lib>lib/h2-1.3.175.jar</lib>
<driver>org.h2.Driver</driver>
<urlPattern>jdbc:h2:%s;LOG=0;UNDO_LOG=0</urlPattern>
<localPKType>VARCHAR</localPKType>
@@ -43,6 +43,9 @@
<maxDepth>0</maxDepth>
<outputFolder>render</outputFolder>
</renderer>
<!-- additional SQL keywords -->
<additionalSQLKeywords>sensitive, datetime</additionalSQLKeywords>
<!-- for Oracle -->
<dbms>
@@ -60,12 +63,6 @@
<key>CatalogOptions</key>
<value>0</value>
</entry>
<!--
<entry>
<key>includeSynonyms</key>
<value>true</value>
</entry>
-->
</jdbcProperties>
<statisticRenovator>
<scriptFileName>script/oracle/gatherStatistics.sql</scriptFileName>
@@ -108,6 +105,7 @@
<rowidName>ROWID</rowidName>
<rowidType>ROWID</rowidType>
<useInlineViewsInDataBrowser>false</useInlineViewsInDataBrowser>
<estimatedRowCountQuery>select TABLE_NAME, NUM_ROWS from all_tables where OWNER = '%s'</estimatedRowCountQuery>
<virtualColumnsQuery>SELECT TABLE_NAME, COLUMN_NAME FROM ALL_TAB_COLS WHERE OWNER = '${SCHEMA}' AND VIRTUAL_COLUMN = 'YES' AND NOT DATA_TYPE = 'XMLTYPE'</virtualColumnsQuery>
<importedKeysQuery>SELECT null, c_dest.OWNER, c_dest.TABLE_NAME, c_dest.COLUMN_NAME, null, c_src.OWNER, c_src.TABLE_NAME, c_src.COLUMN_NAME, c_src.POSITION, null, null, c_list.CONSTRAINT_NAME, c_list.R_CONSTRAINT_NAME, null FROM ALL_CONSTRAINTS c_list, ALL_CONS_COLUMNS c_src, ALL_CONS_COLUMNS c_dest WHERE c_list.CONSTRAINT_NAME = c_src.CONSTRAINT_NAME AND c_list.OWNER = c_src.OWNER AND c_list.R_CONSTRAINT_NAME = c_dest.CONSTRAINT_NAME AND c_list.R_OWNER = c_dest.OWNER AND c_list.CONSTRAINT_TYPE = 'R' AND c_src.POSITION = c_dest.POSITION AND c_src.OWNER = '${SCHEMA}' ORDER BY c_src.POSITION</importedKeysQuery>
<primaryKeysQuery>SELECT null, c_src.OWNER, c_src.TABLE_NAME, c_src.COLUMN_NAME, c_src.POSITION, c_list.CONSTRAINT_NAME FROM ALL_CONSTRAINTS c_list, ALL_CONS_COLUMNS c_src WHERE c_list.CONSTRAINT_NAME = c_src.CONSTRAINT_NAME AND c_list.OWNER = c_src.OWNER AND c_list.CONSTRAINT_TYPE = 'P' AND c_list.CONSTRAINT_NAME not like 'BIN$%' AND c_src.OWNER = '${SCHEMA}' ORDER BY c_src.POSITION</primaryKeysQuery>
@@ -117,6 +115,8 @@
<explainPrepare>explain plan set statement_id = '%2$s' for %1$s</explainPrepare>
<explainQuery>select * from table(dbms_xplan.display(NULL, '%2$s'))</explainQuery>
<explainCleanup></explainCleanup>
<synonymTableQuery>select '"' || TABLE_OWNER || '"."' || TABLE_NAME || '"' from ALL_SYNONYMS where OWNER = '%1$s' and SYNONYM_NAME = '%2$s'</synonymTableQuery>
<viewTextOrDDLQuery>select TEXT from all_views where OWNER = '%1$s' and VIEW_NAME = '%2$s'</viewTextOrDDLQuery>
<functionSourceQuery>SELECT 'Source', text FROM all_source WHERE type = 'FUNCTION' and name = '%2$s' AND owner = '%1$s' ORDER BY line</functionSourceQuery>
<procedureSourceQuery>SELECT 'Source', text FROM all_source WHERE type = 'PROCEDURE' and name = '%2$s' AND owner = '%1$s' ORDER BY line</procedureSourceQuery>
<packageNamesQuery>SELECT OBJECT_NAME FROM ALL_OBJECTS WHERE OBJECT_TYPE = 'PACKAGE' AND OWNER = '%1$s'</packageNamesQuery>
@@ -257,6 +257,15 @@ union all
<avoidLeftJoin>false</avoidLeftJoin>
<supportsSchemasInIndexDefinitions>false</supportsSchemasInIndexDefinitions>
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
<estimatedRowCountQuery>
SELECT tbl.name, p.rows
FROM sys.tables AS tbl
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and idx.index_id &lt; 2
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int)
AND p.index_id=idx.index_id
WHERE SCHEMA_NAME(tbl.schema_id)='%s'
</estimatedRowCountQuery>
<viewTextOrDDLQuery>SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%1$s' and TABLE_NAME = '%2$s'</viewTextOrDDLQuery>
<virtualColumnsQuery>SELECT sysobjects.name AS TableName, syscolumns.name AS ColumnName FROM syscolumns JOIN sysobjects ON syscolumns.id = sysobjects.id AND sysobjects.xtype = 'U' WHERE syscolumns.iscomputed = 1</virtualColumnsQuery>
<userDefinedColumnsQuery>SELECT distinct DOMAIN_NAME from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '%s' AND DOMAIN_NAME is not null</userDefinedColumnsQuery>
<!--
@@ -432,7 +441,10 @@ union all
<binaryPattern>x'%s'</binaryPattern>
<avoidLeftJoin>false</avoidLeftJoin>
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
<virtualColumnsQuery>SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${SCHEMA}' AND EXTRA LIKE '%VIRTUAL%'</virtualColumnsQuery>
<estimatedRowCountQuery>select TABLE_NAME, CARDINALITY from INFORMATION_SCHEMA.STATISTICS where TABLE_SCHEMA = '%s'</estimatedRowCountQuery>
<viewTextOrDDLQuery>SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%1$s' and TABLE_NAME = '%2$s'</viewTextOrDDLQuery>
<virtualColumnsQuery>SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${SCHEMA}' AND EXTRA LIKE '%VIRTUAL%'</virtualColumnsQuery>
<!--
<importedKeysQuery>SELECT PKCU.TABLE_SCHEMA, null, PKCU.TABLE_NAME, PKCU.COLUMN_NAME, KCU.TABLE_SCHEMA, null, KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.ORDINAL_POSITION, null, null, RC.CONSTRAINT_NAME, RC.UNIQUE_CONSTRAINT_NAME, null FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU ON KCU.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG AND KCU.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA AND KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PKCU ON PKCU.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG AND PKCU.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA AND PKCU.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME AND PKCU.TABLE_NAME = RC.REFERENCED_TABLE_NAME AND PKCU.ORDINAL_POSITION = KCU.ORDINAL_POSITION WHERE PKCU.TABLE_SCHEMA = '${SCHEMA}' ORDER BY KCU.ORDINAL_POSITION</importedKeysQuery>
<primaryKeysQuery>SELECT null, KCU.TABLE_SCHEMA, KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.ORDINAL_POSITION, C.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS C JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU ON KCU.CONSTRAINT_CATALOG = C.CONSTRAINT_CATALOG AND KCU.CONSTRAINT_SCHEMA = C.CONSTRAINT_SCHEMA AND KCU.TABLE_NAME = C.TABLE_NAME AND KCU.CONSTRAINT_NAME = C.CONSTRAINT_NAME WHERE C.CONSTRAINT_TYPE = 'PRIMARY KEY' AND KCU.TABLE_SCHEMA = '${SCHEMA}' ORDER BY KCU.ORDINAL_POSITION</primaryKeysQuery>
@@ -545,6 +557,8 @@ union all
<binaryPattern>x'%s'</binaryPattern>
<avoidLeftJoin>false</avoidLeftJoin>
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
<estimatedRowCountQuery>SELECT TABNAME, CARD FROM SYSSTAT.TABLES WHERE TABSCHEMA = '%s'</estimatedRowCountQuery>
<viewTextOrDDLQuery>SELECT TEXT FROM SYSCAT.VIEWS WHERE VIEWSCHEMA = '%1$s' and VIEWNAME = '%2$s'</viewTextOrDDLQuery>
<virtualColumnsQuery>SELECT TABNAME, COLNAME from syscat.columns WHERE TABSCHEMA='${SCHEMA}' AND GENERATED='A'</virtualColumnsQuery>
<importedKeysQuery> SELECT null, REF.REFTABSCHEMA, REF.REFTABNAME, PKCOL.COLNAME, null, REF.TABSCHEMA, REF.TABNAME, FKCOL.COLNAME, FKCOL.COLSEQ, null, null, REF.CONSTNAME, REF.REFKEYNAME, null FROM syscat.references REF, syscat.keycoluse PKCOL, syscat.keycoluse FKCOL WHERE REF.CONSTNAME = FKCOL.CONSTNAME AND REF.TABSCHEMA = FKCOL.TABSCHEMA AND REF.TABNAME = FKCOL.TABNAME AND REF.REFKEYNAME = PKCOL.CONSTNAME AND REF.REFTABSCHEMA = PKCOL.TABSCHEMA AND REF.REFTABNAME = PKCOL.TABNAME AND FKCOL.COLSEQ = PKCOL.COLSEQ AND REF.REFTABSCHEMA = '${SCHEMA}' ORDER BY FKCOL.COLSEQ</importedKeysQuery>
<primaryKeysQuery> SELECT null, CONST.TABSCHEMA, CONST.TABNAME, PKCOL.COLNAME, PKCOL.COLSEQ, CONST.CONSTNAME FROM syscat.tabconst CONST, syscat.keycoluse PKCOL WHERE CONST.CONSTNAME = PKCOL.CONSTNAME AND CONST.TABSCHEMA = PKCOL.TABSCHEMA AND CONST.TABNAME = PKCOL.TABNAME AND CONST.TYPE = 'P' AND CONST.TABSCHEMA = '${SCHEMA}' ORDER BY PKCOL.COLSEQ</primaryKeysQuery>
@@ -661,6 +675,8 @@ Select CNAME, TNAME, COLNAME, CTYPE, DETAIL From
<binaryPattern>x'%s'</binaryPattern>
<avoidLeftJoin>false</avoidLeftJoin>
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
<viewTextOrDDLQuery>SELECT TEXT FROM SYSCAT.VIEWS WHERE VIEWSCHEMA = '%1$s' and VIEWNAME = '%2$s'</viewTextOrDDLQuery>
<estimatedRowCountQuery>SELECT TABNAME, CARD FROM SYSSTAT.TABLES WHERE TABSCHEMA = '%s'</estimatedRowCountQuery>
<virtualColumnsQuery>SELECT TABNAME, COLNAME from syscat.columns WHERE TABSCHEMA='${SCHEMA}' AND GENERATED='A'</virtualColumnsQuery>
<importedKeysQuery>SELECT null, REF.REFTABSCHEMA, REF.REFTABNAME, PKCOL.COLNAME, null, REF.TABSCHEMA, REF.TABNAME, FKCOL.COLNAME, FKCOL.COLSEQ, null, null, REF.CONSTNAME, REF.REFKEYNAME, null FROM syscat.references REF, syscat.keycoluse PKCOL, syscat.keycoluse FKCOL WHERE REF.CONSTNAME = FKCOL.CONSTNAME AND REF.TABSCHEMA = FKCOL.TABSCHEMA AND REF.TABNAME = FKCOL.TABNAME AND REF.REFKEYNAME = PKCOL.CONSTNAME AND REF.REFTABSCHEMA = PKCOL.TABSCHEMA AND REF.REFTABNAME = PKCOL.TABNAME AND FKCOL.COLSEQ = PKCOL.COLSEQ AND REF.REFTABSCHEMA = '${SCHEMA}' ORDER BY FKCOL.COLSEQ</importedKeysQuery>
<primaryKeysQuery>SELECT null, CONST.TABSCHEMA, CONST.TABNAME, PKCOL.COLNAME, PKCOL.COLSEQ, CONST.CONSTNAME FROM syscat.tabconst CONST, syscat.keycoluse PKCOL WHERE CONST.CONSTNAME = PKCOL.CONSTNAME AND CONST.TABSCHEMA = PKCOL.TABSCHEMA AND CONST.TABNAME = PKCOL.TABNAME AND CONST.TYPE = 'P' AND CONST.TABSCHEMA = '${SCHEMA}' ORDER BY PKCOL.COLSEQ</primaryKeysQuery>
@@ -789,6 +805,13 @@ Select CNAME, TNAME, COLNAME, CTYPE, DETAIL From
<supportsSchemasInIndexDefinitions>false</supportsSchemasInIndexDefinitions>
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
<identifierQuoteString>"</identifierQuoteString>
<viewTextOrDDLQuery>SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%1$s' and TABLE_NAME = '%2$s'</viewTextOrDDLQuery>
<estimatedRowCountQuery>
SELECT c.relname, c.reltuples::bigint AS estimate
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = '%s'
</estimatedRowCountQuery>
<explainPrepare></explainPrepare>
<explainQuery>explain %1$s</explainQuery>
<explainCleanup></explainCleanup>
@@ -1106,6 +1129,7 @@ union all
<binaryPattern>x'%s'</binaryPattern>
<avoidLeftJoin>false</avoidLeftJoin>
<useInlineViewsInDataBrowser>false</useInlineViewsInDataBrowser>
<estimatedRowCountQuery>select TABLE_NAME, ROW_COUNT_ESTIMATE from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = '%s'</estimatedRowCountQuery>
<virtualColumnsQuery>SELECT TABLE_NAME, COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='${SCHEMA}' AND IS_COMPUTED</virtualColumnsQuery>
<identifierQuoteString>"</identifierQuoteString>
<explainPrepare></explainPrepare>
@@ -19,10 +19,12 @@ import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
@@ -48,7 +50,7 @@ public class BasicDataSource implements DataSource {
/**
* Name of JDBC-driver class.
*/
private final String driverClassName;
final String driverClassName;
/**
* The DB URL.
@@ -196,6 +198,8 @@ public class BasicDataSource implements DataSource {
}
}
private static Set<String> registeredDriverClassNames = new HashSet<String>();
private void loadDriver(URL[] jdbcDriverURL) {
ClassLoader classLoaderForJdbcDriver = addJarToClasspath(jdbcDriverURL);
try {
@@ -204,6 +208,7 @@ public class BasicDataSource implements DataSource {
try {
d = (Driver) Class.forName(driverClassName, true, classLoaderForJdbcDriver).newInstance();
DriverManager.registerDriver(new DriverShim(d));
registeredDriverClassNames.add(driverClassName);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
@@ -215,7 +220,9 @@ public class BasicDataSource implements DataSource {
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
if (!registeredDriverClassNames.contains(driverClassName)) {
throw new RuntimeException(e);
}
}
}
@@ -66,12 +66,12 @@ public class Session {
/**
* The session in which temporary tables lives, if any.
*/
private static Connection temporaryTableSession = null;
private Connection temporaryTableSession = null;
/**
* Shared scope of temporary tables.
*/
private static WorkingTableScope temporaryTableScope;
private WorkingTableScope temporaryTableScope;
/**
* Scope of temporary tables.
@@ -201,6 +201,11 @@ public class Session {
*/
public final DBMS dbms;
/**
* The DBMS.
*/
public final String driverClassName;
/**
* The dbUrl (<code>null</code> if unknown)
*/
@@ -238,12 +243,11 @@ public class Session {
this.local = local;
this.scope = scope;
this.dbms = dbms;
this.driverClassName = (dataSource instanceof BasicDataSource)? ((BasicDataSource) dataSource).driverClassName : null;
this.dbUrl = (dataSource instanceof BasicDataSource)? ((BasicDataSource) dataSource).dbUrl : null;
this.schema = (dataSource instanceof BasicDataSource)? ((BasicDataSource) dataSource).dbUser : "";
if (scope != null) {
closeTemporaryTableSession();
temporaryTableScope = scope;
}
this.temporaryTableScope = scope;
connectionFactory = new ConnectionFactory() {
private Connection defaultConnection = null;
private Random random = new Random();
@@ -291,7 +295,7 @@ public class Session {
} catch (SQLException e) {
_log.info("can't set isolation level to UR. Reason: " + e.getMessage());
}
if (scope != null && scope != WorkingTableScope.GLOBAL) {
if (scope == WorkingTableScope.SESSION_LOCAL || scope == WorkingTableScope.TRANSACTION_LOCAL) {
temporaryTableSession = con;
} else {
connection.set(con);
@@ -793,6 +797,7 @@ public class Session {
for (Connection con: connections) {
con.close();
}
closeTemporaryTableSession();
_log.info("connection closed");
}
@@ -849,7 +854,7 @@ public class Session {
/**
* Closes the session in which temporary tables lives, if any.
*/
public static void closeTemporaryTableSession() {
private void closeTemporaryTableSession() {
try {
if (temporaryTableSession != null) {
if (temporaryTableScope == WorkingTableScope.TRANSACTION_LOCAL) {
@@ -968,4 +973,24 @@ public class Session {
}
}
/**
* Checks SQL query.
*
* @param sql
* @return <code>true</code> iff sql is executable without errors
*/
public boolean checkQuery(String sql) {
try {
executeQuery(sql, new AbstractResultSetReader() {
@Override
public void readCurrentRow(ResultSet resultSet) throws SQLException {
// nothing to do
}
});
} catch (Exception e) {
return false;
}
return true;
}
}
@@ -552,4 +552,51 @@ public class Association extends ModelElement {
return mapping;
}
}
public boolean hasNullableFK() {
if (!isInsertDestinationBeforeSource()) {
return false;
}
Map<Column, Column> sdMap = createSourceToDestinationKeyMapping();
if (sdMap.isEmpty()) {
return false;
}
for (Column c: sdMap.keySet()) {
if (!c.isNullable) {
return false;
}
if (c.getFilter() != null && !c.getFilter().isDerived() && !c.getFilter().isNullFilter()) {
return false;
}
for (Column pk: source.primaryKey.getColumns()) {
if (c.name.equals(pk.name)) {
return false;
}
}
}
return true;
}
public boolean fkHasNullFilter() {
Map<Column, Column> sdMap = createSourceToDestinationKeyMapping();
for (Column c: sdMap.keySet()) {
if (c.getFilter() == null || !c.getFilter().isNullFilter()) {
return false;
}
}
return true;
}
public void setOrResetFKNullFilter(boolean set) {
Map<Column, Column> sdMap = createSourceToDestinationKeyMapping();
for (Column c: sdMap.keySet()) {
if (set) {
c.setFilter(new Filter("null", null, false, null));
} else {
c.setFilter(null);
}
}
getDataModel().deriveFilters();
getDataModel().version++;
}
}
@@ -184,4 +184,8 @@ public class Filter {
return applyAtExport;
}
public boolean isNullFilter() {
return "null".equalsIgnoreCase(expression.trim());
}
}
@@ -200,6 +200,11 @@ public class PrimaryKey {
return toSQL(null);
}
public void assign(List<Column> primaryKeyColumns) {
columns.clear();
columns.addAll(primaryKeyColumns);
}
public static boolean isIncreasable(Column uPKColumn, Column column) {
if(!uPKColumn.type.equals(column.type)) {
return false;
@@ -228,4 +233,5 @@ public class PrimaryKey {
// never should get THIS far !
return false;
}
}
@@ -16,6 +16,7 @@
package net.sf.jailer.datamodel;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -23,6 +24,7 @@ import java.util.List;
import net.sf.jailer.ExecutionContext;
import net.sf.jailer.configuration.DBMS;
import net.sf.jailer.database.Session;
import net.sf.jailer.util.Quoting;
/**
@@ -99,15 +101,27 @@ public class RowIdSupport {
* @param table the table
* @return the primary key of the table
*/
public PrimaryKey getPrimaryKey(Table table) {
public PrimaryKey getPrimaryKey(Table table, Session session) {
if (table.primaryKey != null) {
if (useRowIds && (!useRowIdsOnlyForTablesWithoutPK || table.primaryKey.getColumns().isEmpty())) {
return tablePK;
if (session == null || isRowIDApplicable(table, session)) {
return tablePK;
}
}
}
return table.primaryKey;
}
/**
* Gets the primary key of a table.
*
* @param table the table
* @return the primary key of the table
*/
public PrimaryKey getPrimaryKey(Table table) {
return getPrimaryKey(table, null);
}
/**
* Gets the universal primary key.
*
@@ -147,13 +161,15 @@ public class RowIdSupport {
* @param table the table
* @return the columns of the table
*/
public List<Column> getColumns(Table table) {
public List<Column> getColumns(Table table, Session session) {
List<Column> columns = table.getColumns();
if (table.primaryKey != null) {
if (useRowIds && (!useRowIdsOnlyForTablesWithoutPK || table.primaryKey.getColumns().isEmpty())) {
columns = new ArrayList<Column>(columns);
columns.addAll(tablePK.getColumns());
return columns;
if (session == null || isRowIDApplicable(table, session)) {
columns = new ArrayList<Column>(columns);
columns.addAll(tablePK.getColumns());
return columns;
}
}
}
return columns;
@@ -163,4 +179,35 @@ public class RowIdSupport {
return rowIdColumn != null && rowIdColumn.name.equals(column.name);
}
private boolean isRowIDApplicable(Table table, Session session) {
Boolean result = (Boolean) session.getSessionProperty(RowIdSupport.class, table.getName());
if (result != null) {
return result;
}
Quoting quoting;
result = false;
try {
quoting = new Quoting(session);
String schema = table.getSchema("");
String tableName;
if (schema.length() == 0) {
tableName = quoting.requote(table.getUnqualifiedName());
} else {
tableName = quoting.requote(schema) + "." + quoting.requote(table.getUnqualifiedName());
}
if (rowIdColumn != null) {
if (session.checkQuery("Select 1 from " + tableName + " Where 1=0")) {
result = session.checkQuery("Select 1 from " + tableName + " Where 1=0 and " + rowIdColumn.name + "=" + rowIdColumn.name);
} else {
return false;
}
}
} catch (SQLException e) {
result = true;
}
session.setSessionProperty(RowIdSupport.class, table.getName(), result);
return result;
}
}
@@ -1530,7 +1530,7 @@ public class LocalEntityGraph extends EntityGraph {
*/
@Override
public void shutDown() throws SQLException {
localSession.shutDown();
remoteSession.shutDown();
}
@Override
@@ -15,6 +15,7 @@
*/
package net.sf.jailer.modelbuilder;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
@@ -26,8 +27,10 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
@@ -48,6 +51,44 @@ import net.sf.jailer.util.CancellationHandler;
import net.sf.jailer.util.Pair;
import net.sf.jailer.util.Quoting;
import net.sf.jailer.util.SqlUtil;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Commit;
import net.sf.jsqlparser.statement.SetStatement;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.Statements;
import net.sf.jsqlparser.statement.UseStatement;
import net.sf.jsqlparser.statement.alter.Alter;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.create.view.AlterView;
import net.sf.jsqlparser.statement.create.view.CreateView;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.drop.Drop;
import net.sf.jsqlparser.statement.execute.Execute;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.merge.Merge;
import net.sf.jsqlparser.statement.replace.Replace;
import net.sf.jsqlparser.statement.select.AllColumns;
import net.sf.jsqlparser.statement.select.AllTableColumns;
import net.sf.jsqlparser.statement.select.FromItemVisitor;
import net.sf.jsqlparser.statement.select.LateralSubSelect;
import net.sf.jsqlparser.statement.select.ParenthesisFromItem;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
import net.sf.jsqlparser.statement.select.SelectItem;
import net.sf.jsqlparser.statement.select.SelectItemVisitor;
import net.sf.jsqlparser.statement.select.SelectVisitor;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.select.SubJoin;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.select.TableFunction;
import net.sf.jsqlparser.statement.select.ValuesList;
import net.sf.jsqlparser.statement.select.WithItem;
import net.sf.jsqlparser.statement.truncate.Truncate;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.upsert.Upsert;
/**
* Finds associations and tables by analyzing the JDBC meta data.
@@ -123,11 +164,26 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
Quoting quoting = new Quoting(session);
ResultSet resultSet;
String defaultSchema = getDefaultSchema(session, session.getSchema());
for (Table table: dataModel.getTables()) {
Set<Association> toRemove = new HashSet<Association>();
for (Table viewOrTable: dataModel.getTables()) {
Table table;
Table underlyingTable = null;
UnderlyingTableInfo uti = null;
uti = underlyingTableInfos.get(viewOrTable.getName());
if (uti != null) {
underlyingTable = uti.underlyingTable;
}
table = viewOrTable;
_log.info("find associations with " + table.getName());
try {
resultSet = getImportedKeys(session, metaData, quoting.unquote(table.getOriginalSchema(quoting.quote(defaultSchema))), quoting.unquote(table.getUnqualifiedName()), true);
Table child = underlyingTable != null? underlyingTable : table;
String ikSchema = quoting.unquote(child.getOriginalSchema(quoting.quote(defaultSchema)));
Session ikSession = session;
if (sessionWithPermissionToReadSchema.containsKey(Quoting.normalizeIdentifier(ikSchema))) {
ikSession = sessionWithPermissionToReadSchema.get(Quoting.normalizeIdentifier(ikSchema));
}
resultSet = getImportedKeys(ikSession, metaData, ikSchema, quoting.unquote(child.getUnqualifiedName()), true);
} catch (Exception e) {
_log.info("failed. " + e.getMessage());
continue;
@@ -135,38 +191,82 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
Map<String, Association> fkMap = new HashMap<String, Association>();
Map<String, Integer> unknownFKCounter = new HashMap<String, Integer>();
while (resultSet.next()) {
Table pkTable = dataModel.getTable(toQualifiedTableName(quoting.quote(defaultSchema), quoting.quote(resultSet.getString(DBMS.MySQL.equals(session.dbms)? 1 : 2)), quoting.quote(resultSet.getString(3))));
String pkColumn = quoting.quote(resultSet.getString(4));
Table fkTable = dataModel.getTable(toQualifiedTableName(quoting.quote(defaultSchema), quoting.quote(resultSet.getString(DBMS.MySQL.equals(session.dbms)? 5 : 6)), quoting.quote(resultSet.getString(7))));
String qualifiedPKTableName = toQualifiedTableName(quoting.quote(defaultSchema), quoting.quote(resultSet.getString(DBMS.MySQL.equals(session.dbms)? 1 : 2)), quoting.quote(resultSet.getString(3)));
// String qualifiedFKTableName = toQualifiedTableName(quoting.quote(defaultSchema), quoting.quote(resultSet.getString(DBMS.MySQL.equals(session.dbms)? 5 : 6)), quoting.quote(resultSet.getString(7)));
Table defaultPkTable = dataModel.getTable(qualifiedPKTableName);
Table fkTable = table;
String fkColumn = quoting.quote(resultSet.getString(8));
String foreignKey = resultSet.getString(12);
if (fkTable != null) {
if (foreignKey == null || foreignKey.trim().length() == 0) {
foreignKey = pkTable.getName();
int seq = resultSet.getInt(9);
String fkKey = fkTable.getName() + "." + foreignKey;
if (seq == 1) {
Integer count = unknownFKCounter.get(fkKey);
if (count == null) {
count = 1;
} else {
count++;
}
unknownFKCounter.put(fkKey, count);
}
foreignKey += "." + unknownFKCounter.get(fkKey);
if (uti != null) {
fkColumn = uti.columnMapping.get(fkColumn);
}
// collect all PKTables
Map<Table, UnderlyingTableInfo> infos = new LinkedHashMap<Table, UnderlyingTableInfo>();
if (defaultPkTable != null) {
infos.put(defaultPkTable, null);
}
for (Entry<String, UnderlyingTableInfo> e: underlyingTableInfos.entrySet()) {
Table view = dataModel.getTable(e.getKey());
if (view != null && qualifiedPKTableName.equals(e.getValue().underlyingTable.getName())) {
infos.put(view, e.getValue());
}
String fkName = fkTable.getName() + "." + foreignKey;
if (foreignKey != null && fkMap.containsKey(fkName)) {
fkMap.get(fkName).appendCondition("A." + fkColumn + "=B." + pkColumn);
} else {
if (pkTable != null && fkTable != null) {
Association association = new Association(fkTable, pkTable, false, true, "A." + fkColumn + "=B." + pkColumn, dataModel, false, Cardinality.MANY_TO_ONE);
association.setAuthor(metaData.getDriverName());
associations.add(association);
fkMap.put(fkName, association);
if (foreignKey != null) {
namingSuggestion.put(association, new String[] { foreignKey, fkTable.getUnqualifiedName() + "." + foreignKey });
}
for (Entry<Table, UnderlyingTableInfo> e: infos.entrySet()) {
Table pkTable = e.getKey();
String pkColumn = quoting.quote(resultSet.getString(4));
String foreignKey = resultSet.getString(12);
UnderlyingTableInfo info = e.getValue();
if (info != null) {
pkColumn = info.columnMapping.get(pkColumn);
}
if (pkTable != null) {
if (foreignKey == null || foreignKey.trim().length() == 0) {
foreignKey = pkTable.getName();
if (info != null) {
foreignKey += "." + quoting.unquote(pkTable.getUnqualifiedName());
}
int seq = resultSet.getInt(9);
String fkKey = pkTable.getName() + "." + foreignKey;
if (seq == 1) {
Integer count = unknownFKCounter.get(fkKey);
if (count == null) {
count = 1;
} else {
count++;
}
unknownFKCounter.put(fkKey, count);
}
foreignKey += "." + unknownFKCounter.get(fkKey);
} else {
if (info != null) {
foreignKey += "." + quoting.unquote(pkTable.getUnqualifiedName());
}
}
String fkName = pkTable.getName() + "." + foreignKey;
if (foreignKey != null && fkMap.containsKey(fkName)) {
if (fkColumn == null || pkColumn == null) {
toRemove.add(fkMap.get(fkName));
} else {
fkMap.get(fkName).appendCondition("A." + fkColumn + "=B." + pkColumn);
}
} else {
if (pkTable != null && fkTable != null) {
Association association = new Association(fkTable, pkTable, false, true, "A." + fkColumn + "=B." + pkColumn, dataModel, false, Cardinality.MANY_TO_ONE);
association.setAuthor(metaData.getDriverName());
associations.add(association);
fkMap.put(fkName, association);
if (foreignKey != null) {
namingSuggestion.put(association, new String[] { foreignKey, fkTable.getUnqualifiedName() + "." + foreignKey });
}
if (fkColumn == null || pkColumn == null) {
toRemove.add(association);
}
}
}
}
@@ -175,6 +275,8 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
resultSet.close();
CancellationHandler.checkForCancellation(null);
}
associations.removeAll(toRemove);
shutDownSessionsWithPermissionToReadSchema();
return associations;
}
@@ -219,6 +321,31 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
return table;
}
private class UnderlyingTableInfo {
Table underlyingTable;
Map<String, String> columnMapping = new LinkedHashMap<String, String>();
@Override
public String toString() {
return "UnderlyingTableInfo [underlyingTable=" + underlyingTable + ", columnMapping=" + columnMapping + "]";
}
public void join() {
UnderlyingTableInfo u2TableInfo = underlyingTableInfos.get(underlyingTable.getName());
if (u2TableInfo != null) {
Map<String, String> newColumnMapping = new HashMap<String, String>();
for (Entry<String, String> e: u2TableInfo.columnMapping.entrySet()) {
String cMapped = columnMapping.get(e.getValue());
if (cMapped != null) {
newColumnMapping.put(e.getKey(), cMapped);
}
}
columnMapping = newColumnMapping;
underlyingTable = u2TableInfo.underlyingTable;
}
}
};
/**
* Finds all tables in DB schema.
*
@@ -226,6 +353,28 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
*/
@Override
public Set<Table> findTables(Session session, ExecutionContext executionContext) throws Exception {
String introspectionSchema = session.getIntrospectionSchema();
String tableNamePattern = "%";
return findTables(session, executionContext, introspectionSchema, tableNamePattern, 0);
}
private Map<String, UnderlyingTableInfo> underlyingTableInfos = new LinkedHashMap<String, UnderlyingTableInfo>();
private Map<String, String> tableTypes = new HashMap<String, String>();
/**
* Finds all tables in DB schema.
*
* @param session the statement executor for executing SQL-statements
* @param introspectionSchema the schema
* @param tableNamePattern table name pattern
*/
private Set<Table> findTables(Session session, ExecutionContext executionContext, String introspectionSchema,
String tableNamePattern, int depth) throws SQLException {
final int MAX_DEPTH = 100;
if (depth > MAX_DEPTH) {
return new HashSet<Table>();
}
PrimaryKeyFactory primaryKeyFactory = new PrimaryKeyFactory();
Set<Table> tables = new HashSet<Table>();
@@ -233,14 +382,14 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
Quoting quoting = new Quoting(session);
ResultSet resultSet;
List<String> types = getTypes(executionContext);
resultSet = getTables(session, metaData, session.getIntrospectionSchema(), "%", types.toArray(new String[0]));
resultSet = getTables(session, metaData, introspectionSchema, tableNamePattern, types.toArray(new String[0]));
List<String> tableNames = new ArrayList<String>();
while (resultSet.next()) {
String tableName = resultSet.getString(3);
if (resultSet.getString(4) != null && types.contains(resultSet.getString(4).toUpperCase())) {
if (isValidName(tableName, session)) {
tableName = quoting.quote(tableName);
if (executionContext.getQualifyNames()) {
if (executionContext.getQualifyNames() || (depth > 0 && introspectionSchema != null && !introspectionSchema.equals(session.getIntrospectionSchema()))) {
String schemaName = resultSet.getString(DBMS.MySQL.equals(session.dbms)? 1 : 2);
if (schemaName != null) {
schemaName = quoting.quote(schemaName.trim());
@@ -250,6 +399,7 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
}
}
tableNames.add(tableName);
tableTypes.put(tableName, resultSet.getString(4).toUpperCase());
_log.info("found table " + tableName);
} else {
_log.info("skip table " + tableName);
@@ -261,7 +411,7 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
Map<String, Map<Integer, Column>> pkColumns = new HashMap<String, Map<Integer, Column>>();
for (String tableName: tableNames) {
Table tmp = new Table(tableName, null, false, false);
resultSet = getPrimaryKeys(session, metaData, quoting.unquote(tmp.getOriginalSchema(quoting.quote(session.getIntrospectionSchema()))), quoting.unquote(tmp.getUnqualifiedName()), true);
resultSet = getPrimaryKeys(session, metaData, quoting.unquote(tmp.getOriginalSchema(quoting.quote(introspectionSchema))), quoting.unquote(tmp.getUnqualifiedName()), true);
Map<Integer, Column> pk = pkColumns.get(tableName);
if (pk == null) {
pk = new HashMap<Integer, Column>();
@@ -280,7 +430,7 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
}
if (!hasPK) {
_log.info("find unique index of table " + tableName);
hasPK = findUniqueIndexBasedKey(metaData, quoting, session, tmp, pk);
hasPK = findUniqueIndexBasedKey(metaData, quoting, session, tmp, pk, tableTypes.get(tableName));
}
_log.info((hasPK? "" : "no ") + "primary key found for table " + tableName);
resultSet.close();
@@ -288,8 +438,8 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
}
for (String tableName: tableNames) {
Table tmp = new Table(tableName, null, false, false);
_log.info("getting columns for " + quoting.unquote(tmp.getOriginalSchema(quoting.quote(session.getIntrospectionSchema()))) + "." + quoting.unquote(tmp.getUnqualifiedName()));
resultSet = getColumns(session, metaData, quoting.unquote(tmp.getOriginalSchema(quoting.quote(session.getIntrospectionSchema()))), quoting.unquote(tmp.getUnqualifiedName()), "%", true);
_log.info("getting columns for " + quoting.unquote(tmp.getOriginalSchema(quoting.quote(introspectionSchema))) + "." + quoting.unquote(tmp.getUnqualifiedName()));
resultSet = getColumns(session, metaData, quoting.unquote(tmp.getOriginalSchema(quoting.quote(introspectionSchema))), quoting.unquote(tmp.getUnqualifiedName()), tableNamePattern, true, tableTypes.get(tableName));
_log.info("done");
Map<Integer, Column> pk = pkColumns.get(tableName);
while (resultSet.next()) {
@@ -349,9 +499,299 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
CancellationHandler.checkForCancellation(null);
}
for (Table table: tables) {
String viewText = null;
String viewTextOrDDLQuery = session.dbms.getViewTextOrDDLQuery();
if ("VIEW".equals(tableTypes.get(table.getName())) && viewTextOrDDLQuery != null) {
String viewTextQuery = String.format(viewTextOrDDLQuery, introspectionSchema, table.getUnqualifiedName());
final String[] viewTextContainer = new String[1];
try {
session.executeQuery(viewTextQuery, new Session.AbstractResultSetReader() {
@Override
public void readCurrentRow(ResultSet resultSet) throws SQLException {
viewTextContainer[0] = resultSet.getString(1);
}
});
viewText = viewTextContainer[0];
if (viewText != null) {
viewText = viewText.trim();
viewText = viewText.replaceFirst("(?is)^create.*as\\b(\\W*select\\b)(.*)$", "$1$2").trim();
}
} catch (Exception e) {
_log.info("can't get view text: " + viewTextQuery);
_log.info(e.getMessage());
}
} else if ("SYNONYM".equals(tableTypes.get(table.getName())) || "ALIAS".equals(tableTypes.get(table.getName()))) {
if (session.dbms.getSynonymTableQuery() != null) {
String synonymTableQuery = String.format(session.dbms.getSynonymTableQuery(), introspectionSchema, table.getUnqualifiedName());
final String[] synonymTableQueryContainer = new String[1];
try {
session.executeQuery(synonymTableQuery, new Session.AbstractResultSetReader() {
@Override
public void readCurrentRow(ResultSet resultSet) throws SQLException {
synonymTableQueryContainer[0] = "Select * from " + resultSet.getString(1);
}
});
viewText = synonymTableQueryContainer[0];
} catch (Exception e) {
_log.info("can't get synonym table: " + synonymTableQuery);
_log.info(e.getMessage());
}
}
} else {
continue;
}
if (viewText != null) {
UnderlyingTableInfo uti = parseViewText(session, executionContext, quoting, depth, viewText, introspectionSchema, table);
if (uti != null) {
List<Column> columns = findColumns(table, session, executionContext);
uti.join();
if (table.primaryKey.getColumns().isEmpty()) {
if (uti.underlyingTable.primaryKey != null && !uti.underlyingTable.primaryKey.getColumns().isEmpty()) {
List<Column> newPK = new ArrayList<Column>();
for (Column pkc: uti.underlyingTable.primaryKey.getColumns()) {
String newPkc = uti.columnMapping.get(quoting.normalizeCase(Quoting.staticUnquote(pkc.name)));
if (newPkc != null) {
Column newC = null;
for (Column c: columns) {
if (Quoting.equalsIgnoreQuotingAndCase(c.name, newPkc)) {
newC = c;
break;
}
}
if (newC != null) {
newPK.add(newC);
} else {
newPK = null;
}
} else {
newPK = null;
break;
}
}
if (newPK != null) {
table.primaryKey.assign(newPK);
}
}
}
}
}
}
return tables;
}
private UnderlyingTableInfo parseViewText(final Session session, final ExecutionContext executionContext, final Quoting quoting, final int depth, String viewText, final String defaultSchema, final Table view) {
net.sf.jsqlparser.statement.Statement st;
try {
_log.info("analyzing view \"" + view.getName() + "\": " + viewText.replaceAll("\\s+", " "));
final List<Column> columns = findColumns(view, session, executionContext);
final boolean[] isValid = new boolean[] { true };
final boolean[] selectExists = new boolean[] { false };
final UnderlyingTableInfo underlyingTableInfo = new UnderlyingTableInfo();
st = CCJSqlParserUtil.parse(viewText);
st.accept(new StatementVisitor() {
@Override
public void visit(Upsert arg0) {
}
@Override
public void visit(Select select) {
select.getSelectBody().accept(new SelectVisitor() {
@Override
public void visit(WithItem withItem) {
isValid[0] = false;
}
@Override
public void visit(SetOperationList setOpList) {
isValid[0] = false;
}
@Override
public void visit(PlainSelect plainSelect) {
if (plainSelect.getFromItem() != null && plainSelect.getJoins() == null) {
selectExists[0] = true;
for (SelectItem sItem: plainSelect.getSelectItems()) {
sItem.accept(new SelectItemVisitor() {
@Override
public void visit(SelectExpressionItem eItem) {
Expression expression = eItem.getExpression();
if (expression instanceof net.sf.jsqlparser.schema.Column) {
String column = ((net.sf.jsqlparser.schema.Column) expression).getColumnName();
column = Quoting.staticUnquote(column);
String alias = column;
if (eItem.getAlias() != null) {
if (eItem.getAlias().getName() != null) {
alias = Quoting.staticUnquote(eItem.getAlias().getName());
}
}
underlyingTableInfo.columnMapping.put(quoting.normalizeCase(Quoting.staticUnquote(column)), quoting.normalizeCase(Quoting.staticUnquote(alias)));
}
}
@Override
public void visit(AllTableColumns arg0) {
for (Column column: columns) {
underlyingTableInfo.columnMapping.put(quoting.normalizeCase(Quoting.staticUnquote(column.name)), quoting.normalizeCase(Quoting.staticUnquote(column.name)));
}
}
@Override
public void visit(AllColumns arg0) {
for (Column column: columns) {
underlyingTableInfo.columnMapping.put(quoting.normalizeCase(Quoting.staticUnquote(column.name)), quoting.normalizeCase(Quoting.staticUnquote(column.name)));
}
}
});
}
FromItemVisitor fromItemVisitor = new FromItemVisitor() {
private void unknownTable() {
isValid[0] = false;
selectExists[0] = false;
}
@Override
public void visit(TableFunction tableFunction) {
unknownTable();
}
@Override
public void visit(ValuesList valuesList) {
unknownTable();
}
@Override
public void visit(LateralSubSelect lateralSubSelect) {
unknownTable();
}
@Override
public void visit(SubJoin subjoin) {
unknownTable();
}
@Override
public void visit(SubSelect subSelect) {
unknownTable();
}
@Override
public void visit(net.sf.jsqlparser.schema.Table tableName) {
String schema = Quoting.staticUnquote(tableName.getSchemaName());
if (schema == null) {
schema = defaultSchema;
}
String name = Quoting.staticUnquote(tableName.getName());
if (tableName.getPivot() != null) {
unknownTable();
} else {
try {
Session theSession = session;
while (theSession != null) {
Quoting quoting = new Quoting(theSession);
Set<Table> tables = findTables(theSession, executionContext, quoting.normalizeCase(schema), quoting.normalizeCase(name), depth + 1);
if (tables.size() < 1) {
tables = findTables(theSession, executionContext, schema, name, depth + 1);
}
if (tables.size() >= 1) {
underlyingTableInfo.underlyingTable = tables.iterator().next();
break;
} else {
if (session == theSession && Quoting.equalsIgnoreQuotingAndCase(theSession.getIntrospectionSchema(), schema)
||
checkReadPermission(theSession, schema)
|| checkReadPermission(theSession, quoting.normalizeCase(schema))) {
_log.warn("View or Synonym \"" + view.getName() + "\": can't find underlying table \"" + schema + "." + name + "\"");
break;
} else {
Session newSession = sessionWithPermissionToReadSchema.get(Quoting.normalizeIdentifier(schema));
if (newSession != null && newSession != theSession) {
theSession = newSession;
} else {
theSession = askForSessionWithPermissionToReadSchema(session, view, Quoting.normalizeIdentifier(schema), quoting.normalizeCase(schema), quoting.normalizeCase(name), executionContext);
if (theSession == null) {
_log.warn("Insufficient privileges to analyze table \"" + schema + "." + name + "\"");
}
}
}
}
}
} catch (SQLException e) {
_log.error("paring failed", e);
}
}
}
@Override
public void visit(ParenthesisFromItem aThis) {
if (aThis.getFromItem() != null) {
aThis.getFromItem().accept(this);
}
}
};
plainSelect.getFromItem().accept(fromItemVisitor);
}
}
});
}
@Override
public void visit(Merge arg0) {
}
@Override
public void visit(SetStatement arg0) {
}
@Override
public void visit(Execute arg0) {
}
@Override
public void visit(Statements arg0) {
}
@Override
public void visit(Alter arg0) {
}
@Override
public void visit(AlterView arg0) {
}
@Override
public void visit(CreateView arg0) {
}
@Override
public void visit(CreateTable arg0) {
}
@Override
public void visit(CreateIndex arg0) {
}
@Override
public void visit(Truncate arg0) {
}
@Override
public void visit(Drop arg0) {
}
@Override
public void visit(Replace arg0) {
}
@Override
public void visit(Insert arg0) {
}
@Override
public void visit(Update arg0) {
}
@Override
public void visit(Delete arg0) {
}
@Override
public void visit(Commit arg0) {
}
@Override
public void visit(UseStatement use) {
}
});
if (isValid[0] && selectExists[0] && underlyingTableInfo.underlyingTable != null) {
underlyingTableInfos.put(view.getName(), underlyingTableInfo);
return underlyingTableInfo;
}
} catch (Exception e) {
_log.info("can't parse view definition");
_log.info(e.getMessage());
}
return null;
}
private List<String> getTypes(ExecutionContext executionContext) {
ArrayList<String> result = new ArrayList<String>();
result.add("TABLE");
@@ -395,10 +835,11 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
/**
* Find a key of a table based on an unique index on non-nullable columns.
* @param string
*/
private boolean findUniqueIndexBasedKey(DatabaseMetaData metaData, Quoting quoting, Session session, Table tmp, Map<Integer, Column> pk) {
private boolean findUniqueIndexBasedKey(DatabaseMetaData metaData, Quoting quoting, Session session, Table tmp, Map<Integer, Column> pk, String tableType) {
try {
ResultSet resultSet = getColumns(session, metaData, quoting.unquote(tmp.getOriginalSchema(quoting.quote(session.getIntrospectionSchema()))), quoting.unquote(tmp.getUnqualifiedName()), "%", true);
ResultSet resultSet = getColumns(session, metaData, quoting.unquote(tmp.getOriginalSchema(quoting.quote(session.getIntrospectionSchema()))), quoting.unquote(tmp.getUnqualifiedName()), "%", true, tableType);
List<String> nonNullColumns = new ArrayList<String>();
boolean hasNullable = false;
@@ -470,22 +911,22 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
}
}
if (!hasNullable) {
if (nonNullColumns.size() <= 6) {
for (int i = 1; i <= nonNullColumns.size(); ++i) {
pk.put(i, new Column(quoting.quote(nonNullColumns.get(i - 1)), "", 0, -1));
}
return true;
}
}
// if (!hasNullable && "TABLE".equalsIgnoreCase(tableType)) {
// if (nonNullColumns.size() <= 6) {
// for (int i = 1; i <= nonNullColumns.size(); ++i) {
// pk.put(i, new Column(quoting.quote(nonNullColumns.get(i - 1)), "", 0, -1));
// }
// return true;
// }
// }
//
return false;
} catch (Exception e) {
_log.error(e.getMessage(), e);
return false;
}
}
private ResultSet getIndexInfo(Session session, DatabaseMetaData metaData, String schema, String table, boolean unique, boolean approximate) throws SQLException {
final String NAME = "getIndexInfo " + schema;
MetaDataCache metaDataCache = (MetaDataCache) session.getSessionProperty(JDBCMetaDataBasedModelElementFinder.class, NAME);
@@ -518,38 +959,63 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
* Calls {@link DatabaseMetaData#getColumns(String, String, String, String)}. Uses schemaPattern as catalogPattern on MySQL.
* @param withCaching
*/
public static ResultSet getColumns(Session session, DatabaseMetaData metaData, String schemaPattern, String tableNamePattern, String columnNamePattern, boolean withCaching) throws SQLException {
if (withCaching) {
synchronized (session) {
final String NAME = "getColumns " + schemaPattern;
MetaDataCache metaDataCache = (MetaDataCache) session.getSessionProperty(JDBCMetaDataBasedModelElementFinder.class, NAME);
if (metaDataCache == null) {
metaDataCache = MetaDataCache.readColumns(session, metaData, schemaPattern);
session.setSessionProperty(JDBCMetaDataBasedModelElementFinder.class, NAME, metaDataCache);
}
ResultSet resultSet = metaDataCache.forTable(tableNamePattern);
if (resultSet != null) {
return resultSet;
}
public static ResultSet getColumns(Session session, DatabaseMetaData metaData, String schemaPattern, String tableNamePattern, String columnNamePattern, boolean withCaching, String tableType) throws SQLException {
boolean includeSynonym = false;
if (DBMS.ORACLE.equals(session.dbms)) {
if ("ALIAS".equalsIgnoreCase(tableType) || "SYNONYM".equalsIgnoreCase(tableType)) {
includeSynonym = true;
}
}
if (DBMS.MySQL.equals(session.dbms)) {
return metaData.getColumns(schemaPattern, null, tableNamePattern, columnNamePattern);
includeSynonym = setIncludeSynonyms(includeSynonym, session);
}
try {
return metaData.getColumns(null, schemaPattern, tableNamePattern, columnNamePattern);
} catch (Exception e) {
String catalogs = "";
try {
ResultSet r = metaData.getCatalogs();
while (r.next()) {
catalogs += r.getString(1) + " ";
if (withCaching) {
synchronized (session) {
final String NAME = "getColumns " + includeSynonym + " " + schemaPattern;
MetaDataCache metaDataCache = (MetaDataCache) session.getSessionProperty(JDBCMetaDataBasedModelElementFinder.class, NAME);
if (metaDataCache == null) {
metaDataCache = MetaDataCache.readColumns(session, metaData, schemaPattern);
session.setSessionProperty(JDBCMetaDataBasedModelElementFinder.class, NAME, metaDataCache);
}
ResultSet resultSet = metaDataCache.forTable(tableNamePattern);
if (resultSet != null) {
return resultSet;
}
}
r.close();
} catch (Exception e2) {
catalogs += "?";
}
throw new RuntimeException("Error in getColumns(): catalogs= " + catalogs + ", schemaPattern=" + schemaPattern + ", tableNamePattern=" + tableNamePattern + ", columnNamePattern=" + columnNamePattern, e);
if (DBMS.MySQL.equals(session.dbms)) {
return metaData.getColumns(schemaPattern, null, tableNamePattern, columnNamePattern);
}
try {
return metaData.getColumns(null, schemaPattern, tableNamePattern, columnNamePattern);
} catch (Exception e) {
String catalogs = "";
try {
ResultSet r = metaData.getCatalogs();
while (r.next()) {
catalogs += r.getString(1) + " ";
}
r.close();
} catch (Exception e2) {
catalogs += "?";
}
throw new RuntimeException("Error in getColumns(): catalogs= " + catalogs + ", schemaPattern=" + schemaPattern + ", tableNamePattern=" + tableNamePattern + ", columnNamePattern=" + columnNamePattern, e);
}
} finally {
if (DBMS.ORACLE.equals(session.dbms)) {
if (includeSynonym) {
setIncludeSynonyms(false, session);
}
}
}
}
private static boolean setIncludeSynonyms(boolean includeSynonyms, Session session) {
try {
Connection con = session.getConnection();
con.getClass().getClassLoader().loadClass("oracle.jdbc.OracleConnection").getMethod("setIncludeSynonyms", new Class[] { boolean.class }).invoke(con, includeSynonyms);
return includeSynonyms;
} catch (Throwable t) {
return false;
}
}
@@ -647,7 +1113,9 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
return schema;
}
if (schema.equalsIgnoreCase(userName.trim())) {
userSchema = schema;
if (userSchema == null || !userSchema.equals(userName.trim())) {
userSchema = schema;
}
}
}
if (userSchema != null) {
@@ -672,7 +1140,7 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
* @throws Exception on each error
*/
@Override
public List<Column> findColumns(Table table, Session session, ExecutionContext executionContext) throws Exception {
public List<Column> findColumns(Table table, Session session, ExecutionContext executionContext) throws SQLException {
List<Column> columns = new ArrayList<Column>();
DatabaseMetaData metaData = session.getMetaData();
Quoting quoting = new Quoting(session);
@@ -685,7 +1153,7 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
String schemaName = quoting.unquote(table.getOriginalSchema(defaultSchema));
String tableName = quoting.unquote(table.getUnqualifiedName());
_log.info("getting columns for " + table.getOriginalSchema(defaultSchema) + "." + tableName);
ResultSet resultSet = getColumns(session, metaData, schemaName, tableName, "%", true);
ResultSet resultSet = getColumns(session, metaData, schemaName, tableName, "%", true, tableTypes.get(table.getName()));
_log.info("done");
while (resultSet.next()) {
String colName = quoting.quote(resultSet.getString(4));
@@ -906,6 +1374,56 @@ public class JDBCMetaDataBasedModelElementFinder implements ModelElementFinder {
session.removeSessionProperties(JDBCMetaDataBasedModelElementFinder.class);
}
private Map<String, Session> sessionWithPermissionToReadSchema = new HashMap<String, Session>();
private void shutDownSessionsWithPermissionToReadSchema() {
for (Session s: sessionWithPermissionToReadSchema.values()) {
try {
s.shutDown();
} catch (SQLException e) {
_log.warn(e.getMessage());
}
}
sessionWithPermissionToReadSchema.clear();
}
public static interface PrivilegedSessionProvider {
Session askForSessionWithPermissionToReadSchema(Session session, Table view, String schema, String tableName, ExecutionContext executionContext);
};
public static PrivilegedSessionProvider privilegedSessionProvider;
private Session askForSessionWithPermissionToReadSchema(Session session, Table view, String schemaID, String schema, String tableName, ExecutionContext executionContext) {
if (privilegedSessionProvider == null) {
return null;
}
if (Quoting.equalsIgnoreQuotingAndCase(session.getIntrospectionSchema(), schema)) {
return null;
}
Session newSession = privilegedSessionProvider.askForSessionWithPermissionToReadSchema(session, view, schema, tableName, executionContext);
if (newSession != null) {
Session s = sessionWithPermissionToReadSchema.get(schemaID);
if (s != null) {
try {
s.shutDown();
} catch (SQLException e) {
// ignore
}
sessionWithPermissionToReadSchema.remove(schemaID);
}
sessionWithPermissionToReadSchema.put(schemaID, newSession);
}
return newSession;
}
private boolean checkReadPermission(Session theSession, String schema) {
return false;
}
/**
* Gets description.
*/
@@ -76,7 +76,7 @@ public class MetaDataCache {
MetaDataCache metaDataCache = new MetaDataCache();
try {
Set<Integer> intIndex = new HashSet<Integer>(Arrays.asList(5));
readMetaData(metaDataCache, session, primaryKeysQuery.replace("${SCHEMA}", schema), intIndex);
readMetaData(metaDataCache, session, primaryKeysQuery.replace("${SCHEMA}", schema), intIndex, 2);
return metaDataCache;
} catch (Exception e) {
_log.info(e.getMessage());
@@ -104,7 +104,7 @@ public class MetaDataCache {
MetaDataCache metaDataCache = new MetaDataCache();
try {
Set<Integer> intIndex = new HashSet<Integer>(Arrays.asList(4));
readMetaData(metaDataCache, session, indexInfoQuery.replace("${SCHEMA}", schema), intIndex);
readMetaData(metaDataCache, session, indexInfoQuery.replace("${SCHEMA}", schema), intIndex, 2);
return metaDataCache;
} catch (Exception e) {
_log.info(e.getMessage());
@@ -132,7 +132,7 @@ public class MetaDataCache {
MetaDataCache metaDataCache = new MetaDataCache();
try {
Set<Integer> intIndex = new HashSet<Integer>(Arrays.asList(9, 10, 11, 14));
readMetaData(metaDataCache, session, importedKeysQuery.replace("${SCHEMA}", schema), intIndex);
readMetaData(metaDataCache, session, importedKeysQuery.replace("${SCHEMA}", schema), intIndex, 6);
return metaDataCache;
} catch (Exception e) {
_log.info(e.getMessage());
@@ -226,7 +226,7 @@ public class MetaDataCache {
* Reads meta data.
*/
private static void readMetaData(final MetaDataCache metaDataCache, Session session, String query,
final Set<Integer> intIndex) throws SQLException {
final Set<Integer> intIndex, final int tableIndex) throws SQLException {
metaDataCache.cache = new HashMap<String, List<Object[]>>();
boolean wasSilent = session.getSilent();
session.setSilent(true);
@@ -243,7 +243,7 @@ public class MetaDataCache {
row[i - 1] = resultSet.getString(i);
}
}
String table = (String) row[2];
String table = (String) row[tableIndex];
List<Object[]> rowList = metaDataCache.cache.get(table);
if (rowList == null) {
rowList = new LinkedList<Object[]>();
@@ -270,6 +270,11 @@ public class RestrictionModel {
}
restriction.put(association, condition);
}
if (!association.isIgnored()) {
if (association.hasNullableFK() && association.fkHasNullFilter()) {
association.setOrResetFKNullFilter(false);
}
}
}
/**
View File
View File
View File
View File
+4 -4
View File
@@ -1,5 +1,5 @@
-- keeps DB-statistic up-to-date for the following tables:
-- JAILER_ENTITY
-- JAILER_GRAPH
-- JAILER_DEPENDENCY
-- JAILER_SET
ANALYZE TABLE ${JAILER_ENTITY};
ANALYZE TABLE ${JAILER_GRAPH};
ANALYZE TABLE ${JAILER_DEPENDENCY};
ANALYZE TABLE ${JAILER_SET};
View File
View File
@@ -245,10 +245,11 @@ public class CsvFile {
* @return decoded and splitted line
*/
public static String[] decodeLine(String line) {
List<String> cells = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
List<String> cells = new ArrayList<String>(1000);
StringBuilder sb = new StringBuilder(1000);
boolean esc = false;
for (int i = 0; i < line.length(); ++i) {
int length = line.length();
for (int i = 0; i < length; ++i) {
char c = line.charAt(i);
if (c == '\\') {
if (esc) {
+448 -57
View File
@@ -25,6 +25,7 @@ import java.util.Map;
import java.util.Set;
import net.sf.jailer.ExecutionContext;
import net.sf.jailer.configuration.Configuration;
import net.sf.jailer.database.Session;
import net.sf.jailer.datamodel.Table;
@@ -96,17 +97,22 @@ public class Quoting {
}
String k = metaData.getSQLKeywords();
if (k != null) {
keyWords = keyWordsMap.get(k);
if (keyWords == null) {
keyWords = new HashSet<String>();
for (String key : k.split(",")) {
keyWords.add(key.trim().toUpperCase());
}
// add all SQL 92 keywords
keyWords.addAll(UCSQL92KEYWORDS);
keyWordsMap.put(k, keyWords);
if (k == null) {
k = "";
}
keyWords = keyWordsMap.get(k);
if (keyWords == null) {
keyWords = new HashSet<String>();
String additionalKeyWords = Configuration.getInstance().getAdditionalSQLKeywords();
if (additionalKeyWords != null) {
k += "," + additionalKeyWords;
}
for (String key : k.split(",")) {
keyWords.add(key.trim().toUpperCase());
}
// add all SQL 92 keywords
keyWords.addAll(UCSQL2003KEYWORDS);
keyWordsMap.put(k, keyWords);
}
}
@@ -242,6 +248,9 @@ public class Quoting {
private static boolean isQuoted(String identifier, String qu) {
if (identifier != null && identifier.length() > 1) {
String q = identifier.substring(0, 1);
if (q.equals("[") && identifier.endsWith("]")) {
return true;
}
if (identifier.endsWith(q)) {
char c = q.charAt(0);
if (q.equals(qu) || isPotentialIdentifierQuote(c)) {
@@ -281,6 +290,19 @@ public class Quoting {
return staticUnquote(identifier).toUpperCase(Locale.ENGLISH);
}
public String normalizeCase(String identifier) {
if (identifier == null) {
return null;
}
if (unquotedIdentifierInMixedCase) {
return identifier;
}
if (unquotedIdentifierInUpperCase) {
return identifier.toUpperCase();
}
return identifier.toLowerCase();
}
/**
* Compares a String to another String, ignoring case considerations and quoting.
*
@@ -298,51 +320,420 @@ public class Quoting {
return staticUnquote(a).equalsIgnoreCase(staticUnquote(b));
}
public static final HashSet<String> UCSQL92KEYWORDS = new HashSet<String>(Arrays.asList(new String[] { "ABSOLUTE", "ACTION",
"ADD", "ALL", "ALLOCATE", "ALTER", "AND", "ANY", "ARE", "AS",
"ASC", "ASSERTION", "AT", "AUTHORIZATION", "AVG", "BEGIN",
"BETWEEN", "BIT", "BIT_LENGTH", "BOTH", "BY", "CALL",
"CASCADE", "CASCADED", "CASE", "CAST", "CATALOG", "CHAR",
"CHARACTER", "CHARACTER_LENGTH", "CHAR_LENGTH", "CHECK",
"CLOSE", "COALESCE", "COLLATE", "COLLATION", "COLUMN",
"COMMIT", "CONDITION", "CONNECT", "CONNECTION", "CONSTRAINT",
"CONSTRAINTS", "CONTAINS", "CONTINUE", "CONVERT",
"CORRESPONDING", "COUNT", "CREATE", "CROSS", "CURRENT",
"CURRENT_DATE", "CURRENT_PATH", "CURRENT_TIME",
"CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DATE", "DATETIME", "DAY",
"DEALLOCATE", "DEC", "DECIMAL", "DECLARE", "DEFAULT",
"DEFERRABLE", "DEFERRED", "DELETE", "DESC", "DESCRIBE",
"DESCRIPTOR", "DETERMINISTIC", "DIAGNOSTICS", "DISCONNECT",
"DISTINCT", "DO", "DOMAIN", "DOUBLE", "DROP", "ELSE", "ELSEIF",
"END", "ESCAPE", "EXCEPT", "EXCEPTION", "EXEC", "EXECUTE",
"EXISTS", "EXIT", "EXTERNAL", "EXTRACT", "FALSE", "FETCH",
"FIRST", "FLOAT", "FOR", "FOREIGN", "FOUND", "FROM", "FULL",
"FUNCTION", "GET", "GLOBAL", "GO", "GOTO", "GRANT", "GROUP",
"HANDLER", "HAVING", "HOUR", "IDENTITY", "IF", "IMMEDIATE",
"IN", "INDICATOR", "INITIALLY", "INNER", "INOUT", "INPUT",
"INSENSITIVE", "INSERT", "INT", "INTEGER", "INTERSECT",
"INTERVAL", "INTO", "IS", "ISOLATION", "JOIN", "KEY",
"LAST", "LEADING", "LEAVE", "LEFT", "LEVEL",
"LIKE", "LOCAL", "LOOP", "LOWER", "MATCH", "MAX", "MIN",
"MINUTE", "MODULE", "MONTH", "NAMES", "NATIONAL", "NATURAL",
"NCHAR", "NEXT", "NO", "NOT", "NULL", "NULLIF", "NUMERIC",
"OCTET_LENGTH", "OF", "ON", "ONLY", "OPEN", "OPTION", "OR",
"ORDER", "OUT", "OUTER", "OUTPUT", "OVERLAPS", "PAD",
"PARAMETER", "PARTIAL", "PATH", "POSITION", "PRECISION",
"PREPARE", "PRESERVE", "PRIMARY", "PRIOR", "PRIVILEGES",
"PROCEDURE", "READ", "REAL", "REFERENCES",
"RELATIVE", "REPEAT", "RESIGNAL", "RESTRICT", "RETURN",
"RETURNS", "REVOKE", "RIGHT", "ROLLBACK", "ROUTINE", "ROWS",
"SCHEMA", "SCROLL", "SECOND", "SECTION", "SELECT", "SESSION",
"SESSION_USER", "SET", "SIGNAL", "SIZE", "SMALLINT", "SOME",
"SPACE", "SPECIFIC", "SQL", "SQLCODE", "SQLERROR",
"SQLEXCEPTION", "SQLSTATE", "SQLWARNING", "SUBSTRING", "SUM",
"SYSTEM_USER", "TABLE", "TEMPORARY", "THEN", "TIME",
"TIMESTAMP", "TIMEZONE_HOUR", "TIMEZONE_MINUTE", "TO",
"TRAILING", "TRANSACTION", "TRANSLATE", "TRANSLATION", "TRIM",
"TRUE", "UNDO", "UNION", "UNIQUE", "UNKNOWN", "UNTIL",
"UPDATE", "UPPER", "USAGE", "USER", "USING", "VALUE", "VALUES",
"VARCHAR", "VARYING", "VIEW", "VIRTUAL", "WHEN", "WHENEVER", "WHERE",
"WHILE", "WITH", "WORK", "WRITE", "YEAR", "ZONE" }));
public static final HashSet<String> UCSQL2003KEYWORDS = new HashSet<String>(Arrays.asList(new String[] {
"ABS",
"ABSOLUTE",
"ACTION",
"ADD",
"ADMIN",
"AFTER",
"AGGREGATE",
"ALIAS",
"ALL",
"ALLOCATE",
"ALTER",
"ANALYSE",
"ANALYZE",
"AND",
"ANY",
"ARE",
"ARRAY",
"AS",
"ASC",
"ASENSITIVE",
"ASSERTION",
"ASYMMETRIC",
"AT",
"ATOMIC",
"AUTHORIZATION",
"AVG",
"BEFORE",
"BEGIN",
"BETWEEN",
"BIGINT",
"BINARY",
"BIT",
"BIT_LENGTH",
"BLOB",
"BOOLEAN",
"BOTH",
"BREADTH",
"BY",
"CALL",
"CALLED",
"CARDINALITY",
"CASCADE",
"CASCADED",
"CASE",
"CAST",
"CATALOG",
"CEIL",
"CEILING",
"CHAR",
"CHARACTER",
"CHARACTER_LENGTH",
"CHAR_LENGTH",
"CHECK",
"CLASS",
"CLOB",
"CLOSE",
"COALESCE",
"COLLATE",
"COLLATION",
"COLLECT",
"COLUMN",
"COMMIT",
"COMPLETION",
"CONDITION",
"CONNECT",
"CONNECTION",
"CONSTRAINT",
"CONSTRAINTS",
"CONSTRUCTOR",
"CONTINUE",
"CONVERT",
"CORR",
"CORRESPONDING",
"COUNT",
"COVAR_POP",
"COVAR_SAMP",
"CREATE",
"CROSS",
"CUBE",
"CUME_DIST",
"CURRENT",
"CURRENT_DATE",
"CURRENT_DEFAULT_TRANSFORM_GROUP",
"CURRENT_PATH",
"CURRENT_ROLE",
"CURRENT_TIME",
"CURRENT_TIMESTAMP",
"CURRENT_TRANSFORM_GROUP_FOR_TYPE",
"CURRENT_USER",
"CURSOR",
"CYCLE",
"DATA",
"DATE",
"DAY",
"DEALLOCATE",
"DEC",
"DECIMAL",
"DECLARE",
"DEFAULT",
"DEFERRABLE",
"DEFERRED",
"DELETE",
"DENSE_RANK",
"DEPTH",
"DEREF",
"DESC",
"DESCRIBE",
"DESCRIPTOR",
"DESTROY",
"DESTRUCTOR",
"DETERMINISTIC",
"DIAGNOSTICS",
"DICTIONARY",
"DISCONNECT",
"DISTINCT",
"DO",
"DOMAIN",
"DOUBLE",
"DROP",
"DYNAMIC",
"EACH",
"ELEMENT",
"ELSE",
"END",
"END-EXEC",
"EQUALS",
"ESCAPE",
"EVERY",
"EXCEPT",
"EXCEPTION",
"EXEC",
"EXECUTE",
"EXISTS",
"EXP",
"EXTERNAL",
"EXTRACT",
"FALSE",
"FETCH",
"FILTER",
"FIRST",
"FLOAT",
"FLOOR",
"FOR",
"FOREIGN",
"FOUND",
"FREE",
"FREEZE",
"FROM",
"FULL",
"FUNCTION",
"FUSION",
"GENERAL",
"GET",
"GLOBAL",
"GO",
"GOTO",
"GRANT",
"GROUP",
"GROUPING",
"HAVING",
"HOLD",
"HOST",
"HOUR",
"IDENTITY",
"IGNORE",
"ILIKE",
"IMMEDIATE",
"IN",
"INDICATOR",
"INITIALIZE",
"INITIALLY",
"INNER",
"INOUT",
"INPUT",
"INSENSITIVE",
"INSERT",
"INT",
"INTEGER",
"INTERSECT",
"INTERSECTION",
"INTERVAL",
"INTO",
"IS",
"ISNULL",
"ISOLATION",
"ITERATE",
"JOIN",
"KEY",
"LARGE",
"LAST",
"LATERAL",
"LEADING",
"LEFT",
"LESS",
"LEVEL",
"LIKE",
"LIMIT",
"LN",
"LOCAL",
"LOCALTIME",
"LOCALTIMESTAMP",
"LOCATOR",
"LOWER",
"MAP",
"MATCH",
"MAX",
"MEMBER",
"MERGE",
"METHOD",
"MIN",
"MINUTE",
"MOD",
"MODIFIES",
"MODIFY",
"MODULE",
"MONTH",
"MULTISET",
"NAMES",
"NATIONAL",
"NATURAL",
"NCHAR",
"NCLOB",
"NEW",
"NEXT",
"NO",
"NONE",
"NORMALIZE",
"NOT",
"NOTNULL",
"NULL",
"NULLIF",
"NUMERIC",
"OBJECT",
"OCTET_LENGTH",
"OF",
"OFF",
"OFFSET",
"OLD",
"ON",
"ONLY",
"OPEN",
"OPERATION",
"OPTION",
"OR",
"ORDER",
"ORDINALITY",
"OUT",
"OUTER",
"OUTPUT",
"OVER",
"OVERLAPS",
"OVERLAY",
"PAD",
"PARAMETER",
"PARAMETERS",
"PARTIAL",
"PARTITION",
"PATH",
"PERCENTILE_CONT",
"PERCENTILE_DISC",
"PERCENT_RANK",
"PLACING",
"POSITION",
"POSTFIX",
"POWER",
"PRECISION",
"PREFIX",
"PREORDER",
"PREPARE",
"PRESERVE",
"PRIMARY",
"PRIOR",
"PRIVILEGES",
"PROCEDURE",
"PUBLIC",
"RANGE",
"RANK",
"READ",
"READS",
"REAL",
"RECURSIVE",
"REF",
"REFERENCES",
"REFERENCING",
"REGR_AVGX",
"REGR_AVGY",
"REGR_COUNT",
"REGR_INTERCEPT",
"REGR_R2",
"REGR_SLOPE",
"REGR_SXX",
"REGR_SXY",
"REGR_SYY",
"RELATIVE",
"RELEASE",
"RESTRICT",
"RESULT",
"RETURN",
"RETURNING",
"RETURNS",
"REVOKE",
"RIGHT",
"ROLLBACK",
"ROLLUP",
"ROUTINE",
"ROW",
"ROWS",
"ROW_NUMBER",
"SAVEPOINT",
"SCHEMA",
"SCOPE",
"SCROLL",
"SEARCH",
"SECOND",
"SECTION",
"SELECT",
"SENSITIVE",
"SEQUENCE",
"SESSION",
"SESSION_USER",
"SET",
"SETS",
"SIMILAR",
"SIZE",
"SMALLINT",
"SOME",
"SPACE",
"SPECIFIC",
"SPECIFICTYPE",
"SQL",
"SQLCODE",
"SQLERROR",
"SQLEXCEPTION",
"SQLSTATE",
"SQLWARNING",
"SQRT",
"START",
"STATE",
"STATEMENT",
"STATIC",
"STDDEV_POP",
"STDDEV_SAMP",
"STRUCTURE",
"SUBMULTISET",
"SUBSTRING",
"SUM",
"SYMMETRIC",
"SYSTEM",
"SYSTEM_USER",
"TABLE",
"TABLESAMPLE",
"TEMPORARY",
"TERMINATE",
"THAN",
"THEN",
"TIME",
"TIMESTAMP",
"TIMEZONE_HOUR",
"TIMEZONE_MINUTE",
"TO",
"TRAILING",
"TRANSACTION",
"TRANSLATE",
"TRANSLATION",
"TREAT",
"TRIGGER",
"TRIM",
"TRUE",
"UESCAPE",
"UNDER",
"UNION",
"UNIQUE",
"UNKNOWN",
"UNNEST",
"UPDATE",
"UPPER",
"USAGE",
"USER",
"USING",
"VALUE",
"VALUES",
"VARCHAR",
"VARIABLE",
"VARYING",
"VAR_POP",
"VAR_SAMP",
"VERBOSE",
"VIEW",
"WHEN",
"WHENEVER",
"WHERE",
"WIDTH_BUCKET",
"WINDOW",
"WITH",
"WITHIN",
"WITHOUT",
"WORK",
"WRITE",
"XML",
"XMLAGG",
"XMLATTRIBUTES",
"XMLBINARY",
"XMLCOMMENT",
"XMLCONCAT",
"XMLELEMENT",
"XMLFOREST",
"XMLNAMESPACES",
"XMLPARSE",
"XMLPI",
"XMLROOT",
"XMLSERIALIZE",
"YEAR",
"ZONE",
}));
}
}
@@ -1,5 +0,0 @@
package net.sf.jailer.util;
public class ToDo {
}
@@ -16,7 +16,6 @@
package net.sf.jailer.ui;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.Image;
@@ -430,7 +429,7 @@ public class AdditionalSubjectsDialog extends javax.swing.JDialog {
private void addAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addAllButtonActionPerformed
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
List<Table> tables = new ArrayList<Table>(remaining);
Collections.sort(tables);
@@ -443,7 +442,7 @@ public class AdditionalSubjectsDialog extends javax.swing.JDialog {
additionalSubjectListEditor.setModel(subjects);
collectRemaining();
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}//GEN-LAST:event_addAllButtonActionPerformed
+36 -3
View File
@@ -27,7 +27,7 @@
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,-64,0,0,3,124"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,-64,0,0,2,121"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
@@ -133,7 +133,7 @@
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="1.0" weightY="0.0"/>
<GridBagConstraints gridX="7" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@@ -153,7 +153,7 @@
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
<GridBagConstraints gridX="-1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@@ -164,6 +164,39 @@
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="5" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="4" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JComboBox" name="findPathComboBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4">
<StringItem index="0" value="Item 1"/>
<StringItem index="1" value="Item 2"/>
<StringItem index="2" value="Item 3"/>
<StringItem index="3" value="Item 4"/>
</StringArray>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findPathComboBoxActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="findPathButton">
<Properties>
<Property name="text" type="java.lang.String" value="Search"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findPathButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="4" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
+281 -31
View File
@@ -21,11 +21,13 @@ import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
@@ -45,6 +47,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
@@ -67,6 +70,10 @@ import javax.swing.table.TableColumn;
import net.sf.jailer.datamodel.Association;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.ui.StringSearchPanel.AdditionalComponentFactory;
import net.sf.jailer.ui.pathfinder.HistoryPanel;
import net.sf.jailer.ui.pathfinder.PathFinder;
import net.sf.jailer.ui.pathfinder.PathFinder.Result;
import net.sf.jailer.ui.scrollmenu.JScrollMenu;
import net.sf.jailer.ui.scrollmenu.JScrollPopupMenu;
import net.sf.jailer.util.Pair;
@@ -167,6 +174,71 @@ public abstract class ClosureView extends javax.swing.JDialog {
findButton.setVisible(false);
searchButton.setText("Find Table");
AutoCompletion.enable(findPathComboBox);
findPathComboBox.getEditor().getEditorComponent().addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == '\n') {
findButtonActionPerformed(null);
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent arg0) {
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 2;
Object currentSelection = rootTable.getSelectedItem();
Table source = null;
if (currentSelection instanceof String) {
source = getDataModel().getTableByDisplayName((String) currentSelection);
}
final javax.swing.JComboBox comboBox = findPathComboBox;
JButton stFindButtonButton = StringSearchPanel.createSearchButton(extractionModelEditor.extractionModelFrame, comboBox,
new Object() {
public String toString() {
Table source = null;
Object currentSelection = ClosureView.this.rootTable.getSelectedItem();
if (currentSelection instanceof String) {
source = getDataModel().getTableByDisplayName((String) currentSelection);
}
return (source != null? ("From " + getDataModel().getDisplayName(source) + " - ") : "") + "Select destination or choose from History";
}
},
new Runnable() {
@Override
public void run() {
findPathButtonActionPerformed(null);
}
}, null, null, null, true,
new AdditionalComponentFactory() {
@Override
public JComponent create(final StringSearchPanel searchPanel) {
HistoryPanel historyPanel = new HistoryPanel(ClosureView.this.getSelectedTable(), getDataModel()) {
private static final long serialVersionUID = 1L;
@Override
protected void close() {
searchPanel.close();
}
@Override
protected void apply(Table source, Table destination) {
findPath(source, destination, true);
}
};
return historyPanel;
}
});
tablePanel.add(stFindButtonButton, gridBagConstraints);
findPathComboBox.setVisible(false);
findPathButton.setVisible(false);
stFindButtonButton.setText("Find Path to...");
columnsComboBox.setModel(new DefaultComboBoxModel<Integer>(new Integer[] {
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
}));
@@ -245,6 +317,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
};
closureTable.setShowGrid(false);
closureTable.setSurrendersFocusOnKeystroke(true);
closureTable.getTableHeader().setReorderingAllowed(false);
jScrollPane1.setViewportView(closureTable);
closureTable.addMouseListener(new MouseListener() {
@@ -262,7 +335,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
if (value == null || !(value instanceof String)) return;
Table table = getDataModel().getTableByDisplayName((String) value);
if (table != null) {
JPopupMenu popup = ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, true);
JPopupMenu popup = ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, createFindPathMenuItem(table), true);
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
@@ -362,7 +435,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
selectTableCell(column, row);
}
ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, false);
ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, null, false);
popup.show(e.getComponent(), cellRect.x, cellRect.y + cellRect.height + 4);
}
}
@@ -385,6 +458,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
private Font font = new JLabel("normal").getFont();
private Font normal = new Font(font.getName(), font.getStyle() & ~Font.BOLD, font.getSize());
private Font bold = new Font(font.getName(), font.getStyle() | Font.BOLD, font.getSize());
// private Font italic = new Font(font.getName(), font.getStyle() | Font.ITALIC, font.getSize());
@Override
public Component getTableCellRendererComponent(JTable table,
@@ -436,6 +510,10 @@ public abstract class ClosureView extends javax.swing.JDialog {
} else if (!allDisabled && someRestricted) {
((JLabel) render).setForeground(new Color(0, 80, 160));
}
if (currentForcedDistance != null && currentForcedDistance.containsKey(t)) {
((JLabel) render).setFont(bold);
// ((JLabel) render).setForeground(new Color(150, 150, 150));
}
}
}
return render;
@@ -541,8 +619,8 @@ public abstract class ClosureView extends javax.swing.JDialog {
Table table = getDataModel().getTableByDisplayName(selectedTable);
if (table != null) {
CellInfo selectionInfo = cellInfo.get(selectedTable);
selectionInfo.select();
if (selectionInfo != null) {
selectionInfo.select();
Association association = null;
for (CellInfo parent: selectionInfo.parents) {
Table pre = parent.table;
@@ -557,6 +635,58 @@ public abstract class ClosureView extends javax.swing.JDialog {
}
}
}
Stack<Table> toSelect = new Stack<Table>();
CellInfo ci = selectionInfo;
final int MAX_PATH_LENGTH = 1000;
while (ci != null) {
if (toSelect.size() > MAX_PATH_LENGTH) {
break;
}
if (ci.table != null) {
toSelect.push(ci.table);
}
CellInfo nextCi = null;
for (CellInfo parent: ci.parents) {
Table pre = parent.table;
if (pre != null) {
CellInfo preInfo = cellInfo.get(getDataModel().getDisplayName(pre));
if (preInfo != null) {
if (preInfo.selected) {
if (preInfo.table != null) {
nextCi = preInfo;
break;
}
}
}
}
}
ci = nextCi;
}
Table selTable = getSelectedTable();
if (currentForcedDistance != null) {
if (selTable != null && !toSelect.contains(selTable)
||
!currentForcedDistance.containsKey(table)) {
refresh();
selectTableCell(col, row);
return;
}
}
extractionModelEditor.incCaptureLevel();
try {
if (!toSelect.isEmpty()) {
Table source = toSelect.pop();
while (!toSelect.isEmpty()) {
Table dest = toSelect.pop();
if (!ClosureView.this.extractionModelEditor.graphView.isTableVisible(dest)) {
ClosureView.this.extractionModelEditor.graphView.showTable(source, dest);
}
source = dest;
}
}
} finally {
extractionModelEditor.decCaptureLevel();
}
if (association != null && ClosureView.this.extractionModelEditor.select(association)) {
return;
}
@@ -617,7 +747,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
// }
// table model
refreshTableModel();
refreshTableModel(null);
refreshing = false;
}
@@ -627,7 +757,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
*/
public void refresh() {
String prevSelection = selectedTable;
refreshTableModel();
refreshTableModel(null);
if (cellInfo.containsKey(prevSelection)) {
selectedTable = prevSelection;
} else {
@@ -637,15 +767,23 @@ public abstract class ClosureView extends javax.swing.JDialog {
repaintClosureView();
}
private Map<Table, Integer> currentForcedDistance = null;
/**
* Refreshes the table model.
* @param excludedTables
* @param path
*/
private void refreshTableModel() {
private void refreshTableModel(Map<Table, Integer> forcedDistance) {
cellInfo.clear();
dependencies.clear();
currentForcedDistance = forcedDistance;
if (forcedDistance == null) {
forcedDistance = new HashMap<Table, Integer>();
}
Table selectedTable = getSelectedTable();
refreshAssociationView(selectedTable);
Object[] columns = new Object[tablesPerLine + 1];
for (int i = 0; i < columns.length; ++i) {
columns[i] = "";
@@ -673,7 +811,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
boolean isolated = false;
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
final Color BG3 = new Color(255, 255, 240);
final Color BG4 = new Color(220, 220, 220);
final Color BG5 = new Color(255, 240, 240);
@@ -682,6 +820,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
TreeSet<String> nonIsolated = new TreeSet<String>();
while (!currentLine.isEmpty()) {
// add current line to table model
if (distance == OMEGA || isolated) {
Object[] lineAsObjects = new Object[tablesPerLine + 1];
@@ -725,18 +864,32 @@ public abstract class ClosureView extends javax.swing.JDialog {
// get next line
List<String> nextLine = new ArrayList<String>();
for (String t: currentLine) {
Table table = getDataModel().getTableByDisplayName(t);
if (table != null) {
CellInfo cellInfoT = this.cellInfo.get(t);
for (Association association: table.associations) {
Integer fd = forcedDistance.get(association.destination);
if (fd != null && fd != distance + 1) {
continue;
}
boolean addToParent = true;
if (forcedDistance.containsKey(association.destination)) {
if (!forcedDistance.containsKey(table)) {
addToParent = false;
}
}
String displayName = getDataModel().getDisplayName(association.destination);
if (!association.isIgnored()) {
if (!association.isIgnored() ||
(forcedDistance.containsKey(association.source) && forcedDistance.containsKey(association.destination))) {
if (!visited.contains(displayName)) {
nextLine.add(displayName);
visited.add(displayName);
CellInfo cellInfo = new CellInfo(distance);
cellInfo.parents.add(cellInfoT);
if (addToParent) {
cellInfo.parents.add(cellInfoT);
}
cellInfo.table = association.destination;
if (association.isInsertDestinationBeforeSource()) {
dependencies.add(new Pair<String, String>(t, displayName));
@@ -744,7 +897,9 @@ public abstract class ClosureView extends javax.swing.JDialog {
this.cellInfo.put(displayName, cellInfo);
} else {
if (nextLine.contains(displayName)) {
this.cellInfo.get(displayName).parents.add(cellInfoT);
if (addToParent) {
this.cellInfo.get(displayName).parents.add(cellInfoT);
}
if (association.isInsertDestinationBeforeSource()) {
dependencies.add(new Pair<String, String>(t, displayName));
}
@@ -852,6 +1007,8 @@ public abstract class ClosureView extends javax.swing.JDialog {
vector.addAll(nonIsolated);
searchComboBox.setModel(new DefaultComboBoxModel<String>(vector));
searchComboBox.setSelectedItem("");
findPathComboBox.setModel(new DefaultComboBoxModel<String>(vector));
findPathComboBox.setSelectedItem("");
}
private Table getSelectedTable() {
@@ -1102,9 +1259,9 @@ public abstract class ClosureView extends javax.swing.JDialog {
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
if (tableName != null) {
Table table = getDataModel().getTable(tableName);
final Table table = getDataModel().getTable(tableName);
if (table != null) {
JPopupMenu popup = ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, false);
JPopupMenu popup = ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, createFindPathMenuItem(table), false);
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
@@ -1125,7 +1282,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
}
return label;
}
/**
* Collects names of associations in the closure ordered by distance into {@link #associationClosure}.
*
@@ -1209,10 +1366,12 @@ public abstract class ClosureView extends javax.swing.JDialog {
tablePanel = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
closureTable = new javax.swing.JTable();
searchComboBox = new net.sf.jailer.ui.JComboBox();
searchComboBox = new JComboBox();
jLabel7 = new javax.swing.JLabel();
columnsComboBox = new net.sf.jailer.ui.JComboBox();
columnsComboBox = new JComboBox();
findButton = new javax.swing.JButton();
findPathComboBox = new JComboBox();
findPathButton = new javax.swing.JButton();
associationPane = new javax.swing.JPanel();
associationPanel = new javax.swing.JPanel();
jScrollPane2 = new javax.swing.JScrollPane();
@@ -1236,8 +1395,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
tabbedPane.setMinimumSize(new java.awt.Dimension(182, 190));
tabbedPane.addChangeListener(new javax.swing.event.ChangeListener() {
@Override
public void stateChanged(javax.swing.event.ChangeEvent evt) {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
tabbedPaneStateChanged(evt);
}
});
@@ -1277,8 +1435,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
searchComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
searchComboBox.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
searchComboBoxActionPerformed(evt);
}
});
@@ -1289,7 +1446,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
jLabel7.setText("Columns ");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridx = 7;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.weightx = 1.0;
@@ -1297,29 +1454,50 @@ public abstract class ClosureView extends javax.swing.JDialog {
columnsComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
columnsComboBox.addItemListener(new java.awt.event.ItemListener() {
@Override
public void itemStateChanged(java.awt.event.ItemEvent evt) {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
columnsComboBoxItemStateChanged(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 2;
tablePanel.add(columnsComboBox, gridBagConstraints);
findButton.setText("Search");
findButton.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
findButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 5;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
tablePanel.add(findButton, gridBagConstraints);
findPathComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
findPathComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
findPathComboBoxActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 2;
tablePanel.add(findPathComboBox, gridBagConstraints);
findPathButton.setText("Search");
findPathButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
findPathButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
tablePanel.add(findButton, gridBagConstraints);
tablePanel.add(findPathButton, gridBagConstraints);
tablePane.add(tablePanel);
@@ -1388,8 +1566,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
showOnlyEnabledCheckBox.setText("Show only enabled associations");
showOnlyEnabledCheckBox.addItemListener(new java.awt.event.ItemListener() {
@Override
public void itemStateChanged(java.awt.event.ItemEvent evt) {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
showOnlyEnabledCheckBoxItemStateChanged(evt);
}
});
@@ -1466,6 +1643,72 @@ public abstract class ClosureView extends javax.swing.JDialog {
}
}//GEN-LAST:event_findButtonActionPerformed
private void findPathComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findPathComboBoxActionPerformed
}//GEN-LAST:event_findPathComboBoxActionPerformed
private void findPathButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findPathButtonActionPerformed
Object toFind = findPathComboBox.getSelectedItem();
if (toFind != null) {
CellInfo cellInfo = this.cellInfo.get(toFind);
if (cellInfo != null) {
Object currentSelection = rootTable.getSelectedItem();
if (currentSelection instanceof String) {
final Table source = getDataModel().getTableByDisplayName((String) currentSelection);
// if (source.closure(true).contains(cellInfo.table)) {
findPath(source, cellInfo.table, false);
// }
}
}
}
}//GEN-LAST:event_findPathButtonActionPerformed
protected JMenuItem createFindPathMenuItem(final Table table) {
JMenuItem findPath = new JMenuItem("Find Path to " + getDataModel().getDisplayName(table));
Object currentSelection = rootTable.getSelectedItem();
if (currentSelection instanceof String) {
final Table source = getDataModel().getTableByDisplayName((String) currentSelection);
if (source.closure(false).contains(table)) {
findPath.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
findPath(source, table, false);
}
});
return findPath;
}
}
findPath.setEnabled(false);
return findPath;
}
private void findPath(Table source, Table destination, boolean fromHistory) {
Frame parent = null;
Window w = SwingUtilities.getWindowAncestor(rootTable);
if (w instanceof Frame) {
parent = (Frame) w;
}
Result result = new PathFinder().find(source, destination, getDataModel(), false, fromHistory, parent);
if (result != null) {
Map<Table, Integer> fd = new HashMap<Table, Integer>();
for (int i = 0; i < result.path.size(); ++i) {
fd.put(result.path.get(i), i);
}
refreshTableModel(fd);
List<Table> path = result.path;
Table table = null;
for (int i = 0; i < path.size(); i++) {
table = path.get(i);
// ClosureView.this.extractionModelEditor.select(table);
}
if (table != null) {
CellInfo ci = cellInfo.get(getDataModel().getDisplayName(table));
if (ci != null) {
selectTableCell(ci.column, ci.row);
}
}
}
}
private void initTabbedPane() {
if (tabbedPane.getSelectedIndex() == 2) {
tabAssTabPanel.removeAll();
@@ -1493,9 +1736,11 @@ public abstract class ClosureView extends javax.swing.JDialog {
private javax.swing.JPanel associationPane;
private javax.swing.JPanel associationPanel;
private javax.swing.JTable closureTable;
private net.sf.jailer.ui.JComboBox columnsComboBox;
private JComboBox columnsComboBox;
public javax.swing.JPanel contentPanel;
private javax.swing.JButton findButton;
private javax.swing.JButton findPathButton;
private JComboBox findPathComboBox;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
@@ -1505,7 +1750,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JSeparator jSeparator1;
private net.sf.jailer.ui.JComboBox searchComboBox;
private JComboBox searchComboBox;
private javax.swing.JCheckBox showOnlyEnabledCheckBox;
private javax.swing.JPanel tabAssAssPanel;
private javax.swing.JPanel tabAssPanel;
@@ -1523,4 +1768,9 @@ public abstract class ClosureView extends javax.swing.JDialog {
public void addTabComponent(String titel, Container tab) {
tabbedPane.addTab(titel, tab);
}
public void selectTabComponent(Container tab) {
tabbedPane.setSelectedComponent(tab);
}
}
@@ -17,7 +17,6 @@ package net.sf.jailer.ui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Font;
import java.io.FileNotFoundException;
import java.util.ArrayList;
@@ -140,7 +139,7 @@ public class ColumnOrderEditor extends javax.swing.JPanel {
final TableCellRenderer defaultTableCellRenderer = columnOrderTable.getDefaultRenderer(String.class);
TableCellRenderer renderer = new TableCellRenderer() {
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
@@ -179,7 +178,7 @@ public class ColumnOrderEditor extends javax.swing.JPanel {
};
try {
owner.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(owner);
Set<String> pks = new HashSet<String>();
Set<String> fks = new HashSet<String>();
@@ -236,7 +235,7 @@ public class ColumnOrderEditor extends javax.swing.JPanel {
columnOrderTable.getRowSorter().setSortKeys(keys);
adjustTableColumnsWidth();
} finally {
owner.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(owner);
}
dialog = new EscapableDialog(owner, "Column Ordering") {
};
@@ -16,7 +16,10 @@
package net.sf.jailer.ui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
@@ -34,6 +37,8 @@ import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import org.fife.rsta.ui.EscapableDialog;
import net.sf.jailer.datamodel.Column;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
@@ -50,12 +55,12 @@ import net.sf.jailer.util.SqlUtil;
*
* @author Ralf Wisser
*/
public class ConditionEditor extends javax.swing.JDialog {
public class ConditionEditor extends EscapableDialog {
private boolean ok;
private ParameterSelector parameterSelector;
private DataModelBasedSQLCompletionProvider provider;
/** Creates new form ConditionEditor */
public ConditionEditor(java.awt.Frame parent, ParameterSelector.ParametersGetter parametersGetter, DataModel dataModel) {
super(parent, true);
@@ -525,6 +530,21 @@ public class ConditionEditor extends javax.swing.JDialog {
return sb.toString();
}
public void setLocationAndFit(Point pos) {
setLocation(pos);
// UIUtil.fit(this);
try {
// Get the size of the screen
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int hd = getY() - (dim.height - 80);
if (hd > 0) {
setLocation(getX(), Math.max(getY() - hd, 0));
}
} catch (Throwable t) {
// ignore
}
}
/**
* Converts multi-line text into single line presentation.
*/
@@ -610,4 +630,5 @@ public class ConditionEditor extends javax.swing.JDialog {
public final RSyntaxTextAreaWithSQLSyntaxStyle editorPane;
private static final long serialVersionUID = -5169934807182707970L;
}
@@ -149,7 +149,7 @@ public class CyclesView extends javax.swing.JDialog {
if (value == null || !(value instanceof String)) return;
Table table = getDataModel().getTableByDisplayName((String) value);
if (table != null) {
JPopupMenu popup = CyclesView.this.extractionModelFrame.extractionModelEditor.graphView.createPopupMenu(table, false);
JPopupMenu popup = CyclesView.this.extractionModelFrame.extractionModelEditor.graphView.createPopupMenu(table, null, false);
UIUtil.fit(popup);
popup.show(e.getComponent(), e.getX(), e.getY());
}
@@ -364,7 +364,7 @@ public class CyclesView extends javax.swing.JDialog {
int distance = 0;
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
bgColor.clear();
for (CycleFinder.Path cycle: cycles) {
@@ -17,6 +17,8 @@ package net.sf.jailer.ui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
@@ -41,6 +43,7 @@ import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter.SortKey;
import javax.swing.SortOrder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
@@ -53,6 +56,8 @@ import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import net.coderazzi.filters.gui.AutoChoices;
import net.coderazzi.filters.gui.TableFilterHeader;
import net.sf.jailer.ExecutionContext;
import net.sf.jailer.JailerVersion;
import net.sf.jailer.datamodel.DataModel;
@@ -243,7 +248,17 @@ public class DataModelEditor extends javax.swing.JDialog {
sortLineList(associations, false);
initComponents();
TableFilterHeader filterHeader = new TableFilterHeader();
filterHeader.setAutoChoices(AutoChoices.ENABLED);
filterHeader.setTable(tablesTable);
filterHeader.setMaxVisibleRows(20);
filterHeader = new TableFilterHeader();
filterHeader.setAutoChoices(AutoChoices.ENABLED);
filterHeader.setTable(associationsTable);
filterHeader.setMaxVisibleRows(20);
String modelpath = executionContext.getQualifiedDatamodelFolder();
try {
modelpath = new File(modelpath).getAbsolutePath();
@@ -278,8 +293,13 @@ public class DataModelEditor extends javax.swing.JDialog {
UIUtil.wireComponentWithButton(tablesTable, editTable);
UIUtil.wireComponentWithButton(associationsTable, editAssociation);
setSize(1000, 700);
setLocation(100, 32);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if (screenSize == null || screenSize.width < 1200) {
setSize(1000, 700);
} else {
setSize(Math.min(screenSize.width - 2 * getX(), 2000), Math.min(screenSize.height - 2 * getY(), 800));
}
File modelFinderColumnFile = new File(ModelBuilder.getModelBuilderColumnsFilename(executionContext));
if (merge && modelFinderColumnFile.exists()) {
@@ -310,73 +330,47 @@ public class DataModelEditor extends javax.swing.JDialog {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
boolean fromModelFinder = linesFromModelFinder.contains(value);
if (!(value instanceof CsvFile.Line)) {
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (value == null) {
value = "";
}
CsvFile.Line line = (CsvFile.Line) value;
String tableName = line.cells.get(0);
String pk = "";
for (int i = 2; i < line.length; ++i) {
if (line.cells.get(i).length() == 0) {
break;
}
if (pk.length() > 0) {
pk += ", ";
}
pk += line.cells.get(i);
}
value = column == 0? line.cells.get(0) : (pk.isEmpty()? "" : pk);
boolean fromModelFinder = tableTableRowsFromModelFinder.contains(tablesTable.getRowSorter().convertRowIndexToModel(row));
Component render = super.getTableCellRendererComponent(table, value, isSelected, false, row, column);
render.setForeground(Color.BLACK);
if (pk.equals("")) {
render.setForeground(Color.RED);
}
if (fromModelFinder || modifiedColumnTables.contains(tableName)) {
if (fromModelFinder || modifiedColumnTables.contains(value) && column == 0) {
render.setBackground(isSelected? BG_SELCOLOR : BG_COLOR);
} else {
render.setBackground(isSelected? BG_SELCOLOR : (row % 2 == 0) ? BG1 : BG2);
}
if (tableTableRowsWithoutPK.contains(tablesTable.getRowSorter().convertRowIndexToModel(row))) {
render.setForeground(Color.RED);
}
if (render instanceof JLabel) {
((JLabel) render).setToolTipText(UIUtil.toHTML(String.valueOf(value), 100));
if (!"".equals(value)) {
((JLabel) render).setToolTipText(UIUtil.toHTML(String.valueOf(value), 100));
} else {
((JLabel) render).setToolTipText(null);
}
}
return render;
}
private static final long serialVersionUID = -8591324056536900244L;
};
DefaultTableCellRenderer associationsListItemRenderer = new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
boolean fromModelFinder = linesFromModelFinder.contains(value);
if (!(value instanceof CsvFile.Line)) {
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
boolean fromModelFinder = associationTableRowsFromModelFinder.contains(associationsTable.getRowSorter().convertRowIndexToModel(row));
if (value == null) {
value = "";
}
CsvFile.Line line = (CsvFile.Line) value;
String type = "associates";
String typeTT = "associates";
if ("B".equalsIgnoreCase(line.cells.get(2))) {
type = "depends on";
if (value.equals("depends on")) {
typeTT = "depends on (has parent)";
}
if ("A".equalsIgnoreCase(line.cells.get(2))) {
type = "has dependent (has child)";
typeTT = "has dependent";
if (value.equals("has dependent")) {
typeTT = "has dependent (has child)";
}
String name = "";
if (line.cells.get(5).length() > 0) {
name = line.cells.get(5);
}
switch (column) {
case 0: value = line.cells.get(0); break;
case 1: value = line.cells.get(1); break;
case 2: value = line.cells.get(4); break;
case 3: value = type; break;
case 4: value = line.cells.get(3); break;
case 5: value = name; break;
}
// value = line.cells.get(0) + " " + type + " " + line.cells.get(1) + " " + name + line.cells.get(3) + " on " + line.cells.get(4);
Component render = super.getTableCellRendererComponent(table, value, isSelected, false, row, column);
if (fromModelFinder) {
render.setBackground(isSelected? BG_SELCOLOR: BG_COLOR);
@@ -399,7 +393,7 @@ public class DataModelEditor extends javax.swing.JDialog {
tablesTable.setAutoCreateRowSorter(true);
tablesTable.setDefaultRenderer(Object.class, tablesListItemRenderer);
tablesTable.setModel(createTablesListModel());
resetTableTableModel();
// tablesTable.setRowSelectionAllowed(false);
tablesTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
@@ -409,17 +403,13 @@ public class DataModelEditor extends javax.swing.JDialog {
updateButtons();
}
});
initRowSorter(tablesTable, new int[] { 0, 2 });
initRowSorter(tablesTable);
adjustTableColumnsWidth(tablesTable);
associationsTable.setDefaultRenderer(Object.class, associationsListItemRenderer);
associationsTable.setAutoCreateRowSorter(true);
// List<SortKey> keys = new ArrayList<SortKey>();
// keys.add(new SortKey(1, SortOrder.ASCENDING));
// keys.add(new SortKey(3, SortOrder.ASCENDING));
// associationsTable.getRowSorter().setSortKeys(keys);
associationsTable.setModel(createAssociationsListModel());
resetAssociationTableModel();
adjustTableColumnsWidth(associationsTable);
associationsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@@ -428,7 +418,7 @@ public class DataModelEditor extends javax.swing.JDialog {
updateButtons();
}
});
initRowSorter(associationsTable, new int[] { 0, 1, 4, 2, 3, 5 });
initRowSorter(associationsTable);
invalidate();
if (initiallyDirty) {
@@ -463,6 +453,7 @@ public class DataModelEditor extends javax.swing.JDialog {
if (toEdit.getName().equals(l.cells.get(0))) {
if (new TableEditor(DataModelEditor.this, displayNames, tables, associations, excludeFromDeletion).edit(l, columns)) {
markDirty();
resetTableTableModel();
repaint();
}
break;
@@ -471,13 +462,13 @@ public class DataModelEditor extends javax.swing.JDialog {
}
}
});
if (merge) {
ModelBuilder.cleanUp(executionContext);
}
}
private void initRowSorter(JTable table, final int[] mapping) {
private void initRowSorter(JTable table) {
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()) {
@Override
protected boolean useToString(int column) {
@@ -495,22 +486,6 @@ public class DataModelEditor extends javax.swing.JDialog {
}
super.toggleSortOrder(column);
}
@Override
public Comparator<?> getComparator(final int n) {
return new Comparator<Object>() {
@SuppressWarnings("unchecked")
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Line) {
if (o2 instanceof Line) {
return ((Line) o1).cells.get(mapping[n]).compareTo(((Line) o2).cells.get(mapping[n]));
}
}
return String.valueOf(o1).compareTo(String.valueOf(o2));
}
};
}
};
table.setRowSorter(sorter);
}
@@ -529,9 +504,9 @@ public class DataModelEditor extends javax.swing.JDialog {
comp = table.getCellRenderer(line, i).getTableCellRendererComponent(table, dtm.getValueAt(line, i), false, false, line, i);
width = Math.max(width, comp.getPreferredSize().width);
}
column.setPreferredWidth(Math.min(width, 200));
column.setPreferredWidth(Math.min(width, 400));
}
table.getColumnModel().getColumn(table.getColumnModel().getColumnCount() - 1).setPreferredWidth(80);
table.getColumnModel().getColumn(table.getColumnModel().getColumnCount() - 1).setPreferredWidth(120);
}
private KnownIdentifierMap createKnownIdentifierMap() throws IOException {
@@ -853,7 +828,7 @@ public class DataModelEditor extends javax.swing.JDialog {
CsvFile.Line line = new CsvFile.Line("?", cells);
if (new AssociationEditor(this, tables, associations, columns).edit(line)) {
associations.add(0, line);
associationsTable.setModel(createAssociationsListModel());
resetAssociationTableModel();
repaint();
markDirty();
}
@@ -866,12 +841,29 @@ public class DataModelEditor extends javax.swing.JDialog {
}
if (line != null) {
if (new AssociationEditor(this, tables, associations, columns).edit(line)) {
resetAssociationTableModel();
markDirty();
repaint();
}
}
}//GEN-LAST:event_editAssociationActionPerformed
private void resetAssociationTableModel() {
List<? extends SortKey> keys = associationsTable.getRowSorter().getSortKeys();
associationsTable.setModel(createAssociationsListModel());
initRowSorter(associationsTable);
adjustTableColumnsWidth(associationsTable);
associationsTable.getRowSorter().setSortKeys(keys);
}
private void resetTableTableModel() {
List<? extends SortKey> keys = tablesTable.getRowSorter().getSortKeys();
tablesTable.setModel(createTablesListModel());
initRowSorter(tablesTable);
adjustTableColumnsWidth(tablesTable);
tablesTable.getRowSorter().setSortKeys(keys);
}
private void newTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTableActionPerformed
List<String> cells = new ArrayList<String>();
cells.add("");
@@ -884,7 +876,7 @@ public class DataModelEditor extends javax.swing.JDialog {
CsvFile.Line line = new CsvFile.Line("?", cells);
if (new TableEditor(this, displayNames, tables, associations, excludeFromDeletion).edit(line, columns)) {
tables.add(0, line);
tablesTable.setModel(createTablesListModel());
resetTableTableModel();
markDirty();
repaint();
}
@@ -895,6 +887,7 @@ public class DataModelEditor extends javax.swing.JDialog {
CsvFile.Line line = tables.get(tablesTable.getRowSorter().convertRowIndexToModel(tablesTable.getSelectedRow()));
if (new TableEditor(this, displayNames, tables, associations, excludeFromDeletion).edit(line, columns)) {
markDirty();
resetTableTableModel();
repaint();
}
}
@@ -931,9 +924,9 @@ public class DataModelEditor extends javax.swing.JDialog {
displayNames.remove(k);
}
excludeFromDeletion.removeAll(namesOfTablesToDelete);
tablesTable.setModel(createTablesListModel());
resetTableTableModel();
associations.removeAll(assToDelete);
associationsTable.setModel(createAssociationsListModel());
resetAssociationTableModel();
for (Line l: toDelete) {
columns.remove(l.cells.get(0));
}
@@ -947,10 +940,14 @@ public class DataModelEditor extends javax.swing.JDialog {
toDelete.add(associations.get(associationsTable.getRowSorter().convertRowIndexToModel(i)));
}
associations.removeAll(toDelete);
associationsTable.setModel(createAssociationsListModel());
resetAssociationTableModel();
markDirty();
}//GEN-LAST:event_deleteAssociationsActionPerformed
private Set<Integer> tableTableRowsFromModelFinder = new HashSet<Integer>();
private Set<Integer> tableTableRowsWithoutPK = new HashSet<Integer>();
private Set<Integer> associationTableRowsFromModelFinder = new HashSet<Integer>();
/**
* Creates model for tables-list component.
*
@@ -963,8 +960,28 @@ public class DataModelEditor extends javax.swing.JDialog {
return false;
}
};
tableTableRowsFromModelFinder.clear();
tableTableRowsWithoutPK.clear();
int row = 0;
for (CsvFile.Line line: tables) {
tablesTableModel.addRow(new Object[] { line, line });
String pk = "";
for (int i = 2; i < line.length; ++i) {
if (line.cells.get(i).length() == 0) {
break;
}
if (pk.length() > 0) {
pk += ", ";
}
pk += line.cells.get(i);
}
if (linesFromModelFinder.contains(line)) {
tableTableRowsFromModelFinder.add(row);
}
if (pk.isEmpty()) {
tableTableRowsWithoutPK.add(row);
}
tablesTableModel.addRow(new Object[] { line.cells.get(0), pk });
++row;
}
return tablesTableModel;
}
@@ -981,8 +998,25 @@ public class DataModelEditor extends javax.swing.JDialog {
return false;
}
};
associationTableRowsFromModelFinder.clear();
int row = 0;
for (CsvFile.Line line: associations) {
associationsTableModel.addRow(new Object[] { line, line, line, line, line, line });
String type = "associates";
if ("B".equalsIgnoreCase(line.cells.get(2))) {
type = "depends on";
}
if ("A".equalsIgnoreCase(line.cells.get(2))) {
type = "has dependent";
}
String name = "";
if (line.cells.get(5).length() > 0) {
name = line.cells.get(5);
}
if (linesFromModelFinder.contains(line)) {
associationTableRowsFromModelFinder.add(row);
}
associationsTableModel.addRow(new Object[] { line.cells.get(0), line.cells.get(1), line.cells.get(4), type, line.cells.get(3), name });
++row;
}
return associationsTableModel;
}
@@ -1156,4 +1190,4 @@ public class DataModelEditor extends javax.swing.JDialog {
// End of variables declaration//GEN-END:variables
private static final long serialVersionUID = -1267039412732180237L;
}
}
@@ -61,6 +61,7 @@ import javax.swing.table.TableColumn;
import net.sf.jailer.ExecutionContext;
import net.sf.jailer.JailerVersion;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
import net.sf.jailer.modelbuilder.ModelBuilder;
import net.sf.jailer.util.CancellationHandler;
import net.sf.jailer.util.Pair;
@@ -156,7 +157,7 @@ public abstract class DataModelManagerDialog extends javax.swing.JFrame {
false, hasFocus, row, column);
if (render instanceof JLabel) {
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
if (!isSelected) {
((JLabel) render)
.setBackground((row % 2 == 0) ? BG1
@@ -788,6 +789,7 @@ public abstract class DataModelManagerDialog extends javax.swing.JFrame {
activateCurrentModel();
try {
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = new PrivilegedSessionProviderDialog.Provider(this);
DbConnectionDialog dbConnectionDialog = new DbConnectionDialog(this, applicationName,
new InfoBar("Connect with Database",
"Select a connection to the database to be analyzed, or create a new connection.\n" +
@@ -837,6 +839,7 @@ public abstract class DataModelManagerDialog extends javax.swing.JFrame {
UIUtil.showException(this, "Error", e);
} finally {
ModelBuilder.assocFilter = null;
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = null;
}
}//GEN-LAST:event_analyzeButtonActionPerformed
@@ -844,6 +847,7 @@ public abstract class DataModelManagerDialog extends javax.swing.JFrame {
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
String folder = choseFolder();
if (folder != null) {
new File(folder).mkdir();
executionContext.setDatamodelFolder(folder);
baseFolders.remove(folder);
baseFolders.add(0, folder);
@@ -170,7 +170,7 @@
<Container class="javax.swing.JPanel" name="jPanel2">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="100" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
<GridBagConstraints gridX="0" gridY="100" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="4" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
@@ -178,14 +178,14 @@
<SubComponents>
<Component class="javax.swing.JButton" name="okButton">
<Properties>
<Property name="text" type="java.lang.String" value=" Ok "/>
<Property name="text" type="java.lang.String" value=" Ok "/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="0" insetsRight="4" anchor="14" weightX="0.0" weightY="0.0"/>
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="0" insetsRight="4" anchor="14" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@@ -198,7 +198,7 @@
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="14" weightX="0.0" weightY="0.0"/>
<GridBagConstraints gridX="3" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="14" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@@ -209,6 +209,19 @@
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="testConnectionButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="0" insetsRight="12" anchor="14" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="selectConnectionButton">
<Properties>
<Property name="text" type="java.lang.String" value="Select Connection "/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="selectConnectionButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="0" insetsRight="12" anchor="14" weightX="1.0" weightY="0.0"/>
@@ -228,6 +241,9 @@
</Constraints>
</Component>
<Component class="javax.swing.JPasswordField" name="password">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="80" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="1.0"/>
@@ -16,6 +16,7 @@
package net.sf.jailer.ui;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.io.File;
import java.net.URI;
@@ -42,6 +43,11 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
* The connection to edit.
*/
private ConnectionInfo ci;
/**
* <code>true</code> if connection must be tested on OK.
*/
private final boolean needsTest;
/**
* Opens detail editor for a connection.
@@ -50,6 +56,18 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
* @return <code>true</code> if connection has been edited
*/
public boolean edit(ConnectionInfo ci) {
setDetails(ci);
setVisible(true);
return isOk;
}
/**
* Sets details.
*
* @param ci the connection
* @return <code>true</code> if connection has been edited
*/
public void setDetails(ConnectionInfo ci) {
this.ci = ci;
alias.setText(ci.alias);
dbUrl.setText(ci.url);
@@ -60,16 +78,32 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
jar2.setText(ci.jar2);
jar3.setText(ci.jar3);
jar4.setText(ci.jar4);
setVisible(true);
return isOk;
}
/** Creates new form DbConnectionDialog
* @param forNew */
public DbConnectionDetailsEditor(java.awt.Frame parent, final String jdbcHelpURL, boolean forNew) {
this(parent, jdbcHelpURL, forNew, null, false);
}
private final Frame parent;
/** Creates new form DbConnectionDialog
* @param forNew
* @param b */
public DbConnectionDetailsEditor(java.awt.Frame parent, final String jdbcHelpURL, boolean forNew, InfoBar infoBar, boolean needsTest) {
super(parent, true);
this.parent = parent;
this.needsTest = needsTest;
initComponents();
if (forNew) {
if (needsTest) {
testConnectionButton.setVisible(false);
} else {
selectConnectionButton.setVisible(false);
}
if (infoBar != null) {
UIUtil.replace(infoBarLabel, infoBar);
} else if (forNew) {
UIUtil.replace(infoBarLabel, new InfoBar("New Connection",
"Enter connection credentials for the database.\n" +
"Replace placeholders (\"<...>\") with appropriate URL parameters.", null));
@@ -173,6 +207,7 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
okButton = new javax.swing.JButton();
cancelButton = new javax.swing.JButton();
testConnectionButton = new javax.swing.JButton();
selectConnectionButton = new javax.swing.JButton();
jLabel11 = new javax.swing.JLabel();
password = new javax.swing.JPasswordField();
helpjdbc = new javax.swing.JLabel();
@@ -288,14 +323,14 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
jPanel2.setLayout(new java.awt.GridBagLayout());
okButton.setText(" Ok ");
okButton.setText(" Ok ");
okButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
okButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 4);
@@ -308,7 +343,7 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 0);
@@ -321,13 +356,27 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 12);
jPanel2.add(testConnectionButton, gridBagConstraints);
selectConnectionButton.setText("Select Connection ");
selectConnectionButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
selectConnectionButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 12);
jPanel2.add(selectConnectionButton, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 100;
@@ -335,6 +384,7 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(0, 0, 4, 0);
jPanel1.add(jPanel2, gridBagConstraints);
jLabel11.setText(" ");
@@ -448,14 +498,23 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
pack();
}// </editor-fold>//GEN-END:initComponents
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
if (fillConnectionInfo()) {
isOk = true;
setVisible(false);
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
if (fillConnectionInfo()) {
if (needsTest) {
if (!DbConnectionDialog.testConnection(isVisible()? this : parent, ci)) {
return;
}
}
isOk = true;
onClose(isOk, ci);
}
}//GEN-LAST:event_okButtonActionPerformed
@SuppressWarnings("deprecation")
protected void onClose(boolean ok, ConnectionInfo info) {
setVisible(false);
}
@SuppressWarnings("deprecation")
private boolean fillConnectionInfo() {
boolean ok = true;
Color red = new Color(255, 200, 180);
@@ -486,13 +545,13 @@ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRS
}
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
setVisible(false);
onClose(false, ci);
}//GEN-LAST:event_cancelButtonActionPerformed
private void testConnectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testConnectionButtonActionPerformed
if (fillConnectionInfo()) {
if (DbConnectionDialog.testConnection(this, ci)) {
JOptionPane.showMessageDialog(this, "Successfully established connection.", "Connected", JOptionPane.INFORMATION_MESSAGE);
if (DbConnectionDialog.testConnection(isVisible()? this : parent, ci)) {
JOptionPane.showMessageDialog(isVisible()? this : parent, "Successfully established connection.", "Connected", JOptionPane.INFORMATION_MESSAGE);
}
}
}//GEN-LAST:event_testConnectionButtonActionPerformed
@@ -509,6 +568,13 @@ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRS
private void loadButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadButton4ActionPerformed
}//GEN-LAST:event_loadButton4ActionPerformed
private void selectConnectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectConnectionButtonActionPerformed
onSelect();
}//GEN-LAST:event_selectConnectionButtonActionPerformed
protected void onSelect() {
}
// Variables declaration - do not modify//GEN-BEGIN:variables
public javax.swing.JTextField alias;
private javax.swing.JButton cancelButton;
@@ -539,7 +605,8 @@ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRS
private javax.swing.JButton loadButton3;
private javax.swing.JButton loadButton4;
private javax.swing.JButton okButton;
private javax.swing.JPasswordField password;
javax.swing.JPasswordField password;
private javax.swing.JButton selectConnectionButton;
private javax.swing.JButton testConnectionButton;
public javax.swing.JTextField user;
// End of variables declaration//GEN-END:variables
@@ -241,7 +241,7 @@ public class DbConnectionDialog extends javax.swing.JDialog {
if (render instanceof JLabel) {
if (!isSelected) {
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
((JLabel) render)
.setBackground((row % 2 == 0) ? BG1
: BG2);
@@ -354,11 +354,7 @@ public class DbConnectionDialog extends javax.swing.JDialog {
private boolean inRefresh = false;
private String jdbcHelpURL = "http://jailer.sourceforge.net/doc/jdbc.html?src=app";
public synchronized void setJdbcHelpURL(String jdbcHelpURL) {
this.jdbcHelpURL = jdbcHelpURL;
}
public static final String jdbcHelpURL = "http://jailer.sourceforge.net/doc/jdbc.html?src=app";
/**
* Refreshes the dialog after model changes.
@@ -526,7 +522,7 @@ public class DbConnectionDialog extends javax.swing.JDialog {
ConnectionInfo ci = new ConnectionInfo(executionContext);
ci.alias = "Demo Scott";
ci.driverClass = "org.h2.Driver";
ci.jar1 = "lib" + File.separator + "h2-1.3.160.jar";
ci.jar1 = "lib" + File.separator + "h2-1.3.175.jar";
ci.url = "jdbc:h2:" + Environment.newFile("demo-scott").getPath();
ci.user = "sa";
ci.password = "";
@@ -538,7 +534,7 @@ public class DbConnectionDialog extends javax.swing.JDialog {
ConnectionInfo ci = new ConnectionInfo(executionContext);
ci.alias = "Demo Sakila";
ci.driverClass = "org.h2.Driver";
ci.jar1 = "lib" + File.separator + "h2-1.3.160.jar";
ci.jar1 = "lib" + File.separator + "h2-1.3.175.jar";
ci.url = "jdbc:h2:" + Environment.newFile("demo-sakila").getPath();
ci.user = "sa";
ci.password = "";
@@ -11,6 +11,7 @@
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
@@ -439,7 +440,7 @@
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="80" green="80" red="80" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" value=" (best for single-thread performance)"/>
<Property name="text" type="java.lang.String" value=" (best for single-threaded performance)"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
@@ -452,7 +453,7 @@
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="80" green="80" red="80" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" value=" (best for multi-thread performance)"/>
<Property name="text" type="java.lang.String" value=" (best for multi-threaded performance)"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
@@ -465,7 +466,7 @@
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="80" green="80" red="80" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" value=" (no write-access needed)"/>
<Property name="text" type="java.lang.String" value=" (no write-access required)"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
File diff suppressed because it is too large Load Diff
@@ -19,7 +19,6 @@ import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
@@ -218,7 +217,7 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
* The execution context.
*/
private final ExecutionContext executionContext;
/**
* Creates new form ModelTree.
*
@@ -240,12 +239,6 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
}
};
columnMapperDialog = new ColumnMapperDialog(extractionModelFrame, parametersGetter);
try {
dataModel = new DataModel(executionContext);
} catch (Exception e) {
UIUtil.showException(this, "Error in Data Model", e);
return;
}
try {
if (extractionModelFile == null || !new File(extractionModelFile).exists()) {
needsSave = extractionModelFile != null;
@@ -282,10 +275,10 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
public void itemStateChanged(ItemEvent arg0) {
Object o1 = rootTable.getSelectedItem();
Object o2 = subjectTable.getSelectedItem();
resetFocus.setEnabled(!(o1 == null && o2 == null || o1 != null && o1.equals(o2)));
resetFocus.setEnabled(!(o1 == null && o2 == null || o1 != null && o1.equals(o2)));
}
};
rootTable.addItemListener(aListener);
subjectTable.addItemListener(aListener);
@@ -320,6 +313,10 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
closureView.addTabComponent("Closure Border", closureBorderView.getContentPane());
closureBorderView.dispose();
restrDepsView = extractionModelFrame.restrictedDependenciesView.getContentPane();
closureView.addTabComponent("Restricted Dependencies", restrDepsView);
extractionModelFrame.restrictedDependenciesView.dispose();
Container cVContentPane = closureView.getContentPane();
closureView.dispose();
@@ -402,7 +399,7 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
});
final TableCellRenderer defaultTableCellRenderer = restrictionsTable.getDefaultRenderer(String.class);
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
restrictionsTable.setDefaultRenderer(Object.class, new TableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table,
@@ -480,6 +477,15 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
onApply(false);
}
});
restrictionEditor.fkToNullCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (currentAssociation != null) {
currentAssociation.setOrResetFKNullFilter(restrictionEditor.fkToNullCheckBox.isSelected());
}
onApply(false);
}
});
// restrictionEditor.jump.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// onJump();
@@ -659,7 +665,7 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
/**
* The "closure view" component.
*/
private ClosureView closureView;
ClosureView closureView;
void setOrientation(boolean horizontal) {
isHorizontalLayout = horizontal;
@@ -1388,7 +1394,7 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
if (selNode instanceof Association) {
table = ((Association) selNode).destination;
}
JPopupMenu popup = graphView.createPopupMenu(table, false);
JPopupMenu popup = graphView.createPopupMenu(table, null, false);
popup.show(evt.getComponent(), evt.getX(), evt.getY());
}
}
@@ -1763,7 +1769,11 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
}
private void initRestrictedDependencyWarningField() {
restrictionEditor.restrictedDependencyWarning.setVisible(currentAssociation != null && !ScriptFormat.XML.equals(scriptFormat) && currentAssociation.isInsertDestinationBeforeSource() && currentAssociation.isRestricted());
boolean restrictedDep = currentAssociation != null && !ScriptFormat.XML.equals(scriptFormat) && currentAssociation.isInsertDestinationBeforeSource() && currentAssociation.isRestricted();
restrictionEditor.restrictedDependencyWarning.setVisible(restrictedDep);
restrictionEditor.fkToNullCheckBox.setVisible(restrictedDep);
restrictionEditor.fkToNullCheckBox.setEnabled(restrictedDep && currentAssociation.hasNullableFK());
restrictionEditor.fkToNullCheckBox.setSelected(restrictedDep && currentAssociation.fkHasNullFilter());
}
/**
@@ -1801,6 +1811,11 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
needsSave = true;
extractionModelFrame.updateTitle(needsSave);
}
if (restrictionEditor.restricted.isSelected() && currentAssociation.hasNullableFK() && currentAssociation.fkHasNullFilter()) {
currentAssociation.setOrResetFKNullFilter(false);
}
String condition;
if (restrictionEditor.ignore.getModel().isSelected()) {
condition = "ignore";
@@ -2048,10 +2063,10 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
private void additionalSubjectsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_additionalSubjectsButtonActionPerformed
AdditionalSubjectsDialog additionalSubjectsDialog;
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
additionalSubjectsDialog = new AdditionalSubjectsDialog(extractionModelFrame, extractionModel, subject, condition.getText());
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
if (additionalSubjectsDialog.edit()) {
needsSave = true;
@@ -2223,24 +2238,28 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
}
}
}
for (DefaultMutableTreeNode node: treeNodes) {
if (node.getChildCount() > 0) {
Table t = null;
Association a = null;
if (node.getUserObject() instanceof Association) {
a = (Association) node.getUserObject();
t = a.destination;
}
if (t != null && a != null && table.equals(t)) {
select(a);
TreePath treePath = new TreePath(node.getPath());
tree.expandPath(treePath);
for (int i = 0; i < node.getChildCount(); ++i) {
DefaultMutableTreeNode c = (DefaultMutableTreeNode) node.getChildAt(i);
tree.collapsePath(new TreePath(c.getPath()));
for (boolean checkVisibility: new boolean [] { true, false }) {
for (DefaultMutableTreeNode node: treeNodes) {
if (node.getChildCount() > 0) {
Table t = null;
Association a = null;
if (node.getUserObject() instanceof Association) {
a = (Association) node.getUserObject();
t = a.destination;
}
if (t != null && a != null && table.equals(t)) {
if (!checkVisibility || (graphView.isTableVisible(a.source) && graphView.isTableVisible(a.destination))) {
select(a);
TreePath treePath = new TreePath(node.getPath());
tree.expandPath(treePath);
for (int i = 0; i < node.getChildCount(); ++i) {
DefaultMutableTreeNode c = (DefaultMutableTreeNode) node.getChildAt(i);
tree.collapsePath(new TreePath(c.getPath()));
}
tree.scrollPathToVisible(treePath);
return true;
}
}
tree.scrollPathToVisible(treePath);
return true;
}
}
}
@@ -2931,7 +2950,9 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
private javax.swing.JPanel xmlMappingPanel;
private javax.swing.JButton xmlTagApply;
// End of variables declaration//GEN-END:variables
Container restrDepsView;
private Icon dropDownIcon;
private Icon conditionEditorIcon;
private Icon conditionEditorSelectedIcon;
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Form version="1.9" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="steptimeGroup">
</Component>
@@ -471,14 +471,6 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cycleViewActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="restrictedDependenciesToolMenuItem">
<Properties>
<Property name="text" type="java.lang.String" value="Restricted Dependencies View"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="restrictedDependenciesToolMenuItemActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="renderHtml">
<Properties>
<Property name="text" type="java.lang.String" value="HTML Rendering"/>
@@ -564,14 +556,80 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="editorPanel">
<Container class="javax.swing.JLayeredPane" name="jLayeredPane1">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="editorPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="updateInfoPanel">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ec" green="ff" red="ff" type="rgb"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="32" insetsRight="24" anchor="14" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="updateInfoLabel">
<Properties>
<Property name="text" type="java.lang.String" value="Release x available"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="4" insetsRight="4" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="downloadButton">
<Properties>
<Property name="text" type="java.lang.String" value="Download"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="downloadButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="4" insetsBottom="4" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="jButton1">
<Properties>
<Property name="text" type="java.lang.String" value="Close"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="2" insetsBottom="4" insetsRight="4" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>
@@ -16,7 +16,7 @@
package net.sf.jailer.ui;
import java.awt.CardLayout;
import java.awt.Cursor;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -44,12 +44,12 @@ import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.WindowConstants;
@@ -69,12 +69,14 @@ import net.sf.jailer.datamodel.Table;
import net.sf.jailer.ddl.DDLCreator;
import net.sf.jailer.extractionmodel.ExtractionModel;
import net.sf.jailer.extractionmodel.ExtractionModel.AdditionalSubject;
import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
import net.sf.jailer.modelbuilder.ModelBuilder;
import net.sf.jailer.render.HtmlDataModelRenderer;
import net.sf.jailer.subsetting.ScriptFormat;
import net.sf.jailer.ui.associationproposer.AssociationProposerView;
import net.sf.jailer.ui.databrowser.DataBrowser;
import net.sf.jailer.ui.progress.ExportAndDeleteStageProgressListener;
import net.sf.jailer.ui.util.UpdateInfoManager;
import net.sf.jailer.util.CancellationHandler;
import net.sf.jailer.util.PrintUtil;
@@ -140,9 +142,33 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
this.executionContext = executionContext;
initComponents();
initSandbox();
initAnimationSteptime();
UpdateInfoManager.checkUpdateAvailability(updateInfoPanel, updateInfoLabel);
initAnimationSteptime();
isHorizontalLayout = isHorizonal;
horizontalLayoutMenuItem.setSelected(isHorizontalLayout);
restrictedDependenciesView = new RestrictedDependenciesListDialog(this) {
private static final long serialVersionUID = -7426280043553389753L;
@Override
protected Table getRoot() {
return extractionModelEditor == null? null : extractionModelEditor.root;
}
@Override
protected DataModel getDataModel() {
return extractionModelEditor == null? null : extractionModelEditor.dataModel;
}
@Override
protected void removeRestrictions(Collection<Association> associations) {
if (extractionModelEditor != null) {
extractionModelEditor.removeRestrictions(associations);
}
}
@Override
protected void onSelect(Association association) {
extractionModelEditor.select(association);
}
};
editorPanel.add(extractionModelEditor = new ExtractionModelEditor(extractionModelFile, this, isHorizontalLayout, getConnectivityState(), getConnectivityStateToolTip(), executionContext), "editor");
extractionModelEditor.extractionModelFile = extractionModelFile;
pack();
@@ -173,28 +199,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
updateMenuItems();
restrictedDependenciesView = new RestrictedDependenciesListDialog(this) {
private static final long serialVersionUID = -7426280043553389753L;
@Override
protected Table getRoot() {
return extractionModelEditor == null? null : extractionModelEditor.root;
}
@Override
protected DataModel getDataModel() {
return extractionModelEditor == null? null : extractionModelEditor.dataModel;
}
@Override
protected void removeRestrictions(Collection<Association> associations) {
if (extractionModelEditor != null) {
extractionModelEditor.removeRestrictions(associations);
}
}
@Override
protected void onSelect(Association association) {
extractionModelEditor.select(association);
}
};
cycleViewDialog = new CyclesView(this);
filterEditorDialog = new FilterEditorDialog(this, new ParameterSelector.ParametersGetter() {
@Override
@@ -214,7 +218,8 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
for (final String item: list) {
JMenuItem menuItem = new JMenuItem(item.split(",")[0]);
sandBox.add(menuItem);
menuItem.addActionListener(new ActionListener() {
final ActionListener a;
menuItem.addActionListener(a = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
@@ -222,12 +227,20 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
String tmpFileName = Configuration.getInstance().createTempFile().getPath();
extractionModelEditor.save(tmpFileName);
ExtractionModel extractionModel = new ExtractionModel(tmpFileName, new HashMap<String, String>(), new HashMap<String, String>(), executionContext);
c.getMethod("main", ExtractionModel.class).invoke(c.newInstance(), extractionModel);
c.getMethod("main", ExtractionModel.class, JFrame.class).invoke(c.newInstance(), extractionModel, ExtractionModelFrame.this);
} catch (Throwable t) {
UIUtil.showException(ExtractionModelFrame.this, "Error", t);
}
}
});
if (menuItem.getText().endsWith("!")) {
UIUtil.invokeLater(4, new Runnable() {
@Override
public void run() {
a.actionPerformed(null);
}
});
}
}
}
} catch (Throwable e) {
@@ -280,7 +293,12 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
java.awt.GridBagConstraints gridBagConstraints;
steptimeGroup = new javax.swing.ButtonGroup();
jLayeredPane1 = new javax.swing.JLayeredPane();
editorPanel = new javax.swing.JPanel();
updateInfoPanel = new javax.swing.JPanel();
updateInfoLabel = new javax.swing.JLabel();
downloadButton = new javax.swing.JButton();
jButton1 = new javax.swing.JButton();
jMenuBar2 = new javax.swing.JMenuBar();
fileMenu = new javax.swing.JMenu();
newModel = new javax.swing.JMenuItem();
@@ -338,7 +356,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
openDataBrowserItem = new javax.swing.JMenuItem();
queryBuilder = new javax.swing.JMenuItem();
cycleView = new javax.swing.JMenuItem();
restrictedDependenciesToolMenuItem = new javax.swing.JMenuItem();
renderHtml = new javax.swing.JMenuItem();
jMenu2 = new javax.swing.JMenu();
helpContent = new javax.swing.JMenuItem();
@@ -365,12 +382,68 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
});
getContentPane().setLayout(new java.awt.GridBagLayout());
jLayeredPane1.setLayout(new java.awt.GridBagLayout());
editorPanel.setLayout(new java.awt.CardLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
getContentPane().add(editorPanel, gridBagConstraints);
jLayeredPane1.add(editorPanel, gridBagConstraints);
updateInfoPanel.setBackground(new java.awt.Color(255, 255, 236));
updateInfoPanel.setLayout(new java.awt.GridBagLayout());
updateInfoLabel.setText("Release x available");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
updateInfoPanel.add(updateInfoLabel, gridBagConstraints);
downloadButton.setText("Download");
downloadButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
downloadButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.insets = new java.awt.Insets(0, 4, 4, 0);
updateInfoPanel.add(downloadButton, gridBagConstraints);
jButton1.setText("Close");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 2;
gridBagConstraints.insets = new java.awt.Insets(0, 2, 4, 4);
updateInfoPanel.add(jButton1, gridBagConstraints);
jLayeredPane1.setLayer(updateInfoPanel, javax.swing.JLayeredPane.MODAL_LAYER);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
gridBagConstraints.insets = new java.awt.Insets(0, 0, 32, 24);
jLayeredPane1.add(updateInfoPanel, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
getContentPane().add(jLayeredPane1, gridBagConstraints);
fileMenu.setText("File");
fileMenu.addActionListener(new java.awt.event.ActionListener() {
@@ -759,14 +832,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
});
jMenu3.add(cycleView);
restrictedDependenciesToolMenuItem.setText("Restricted Dependencies View");
restrictedDependenciesToolMenuItem.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
restrictedDependenciesToolMenuItemActionPerformed(evt);
}
});
jMenu3.add(restrictedDependenciesToolMenuItem);
renderHtml.setText("HTML Rendering");
renderHtml.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@@ -1008,6 +1073,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
@Override
public Boolean call() {
try {
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = new PrivilegedSessionProviderDialog.Provider(ExtractionModelFrame.this);
if (connectToDBIfNeeded("Analyze Database")) {
List<String> args = new ArrayList<String>();
args.add("build-model-wo-merge");
@@ -1016,13 +1082,13 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
AnalyseOptionsDialog analyseOptionsDialog = new AnalyseOptionsDialog(ExtractionModelFrame.this, extractionModelEditor.dataModel, executionContext);
boolean[] isDefaultSchema = new boolean[1];
String[] defaultSchema = new String[1];
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(ExtractionModelFrame.this);
List<String> schemas;
try {
CancellationHandler.reset(null);
schemas = dbConnectionDialog.getDBSchemas(defaultSchema);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(ExtractionModelFrame.this);
}
if (analyseOptionsDialog.edit(schemas, defaultSchema[0], isDefaultSchema, dbConnectionDialog.currentConnection.user)) {
String schema = analyseOptionsDialog.getSelectedSchema();
@@ -1049,6 +1115,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
UIUtil.showException(ExtractionModelFrame.this, "Error", e);
} finally {
ModelBuilder.assocFilter = null;
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = null;
}
return true;
}
@@ -1084,11 +1151,10 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
if (restrictedDependency != null) {
switch (JOptionPane.showOptionDialog(this,
"Dependency from '" + restrictedDependency.source.getName() + "' to '" + restrictedDependency.destination.getName() + "'\n" +
"is restricted.\nReferential integrity is not guaranteed!", "Restricted Dependency", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "Ok", "Cancel", "Show Dependency" }, "Cancel")) {
"is restricted.\nReferential integrity is not guaranteed!", "Restricted Dependency", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "Ok", "Cancel", "Show dependency" }, "Cancel")) {
case 1: return;
case 2:
restrictedDependenciesView.setVisible(true);
restrictedDependenciesView.toFront();
extractionModelEditor.closureView.selectTabComponent(extractionModelEditor.restrDepsView);
return;
}
}
@@ -1111,7 +1177,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
List<String> args = new ArrayList<String>();
args.add(tmpFileName != null? tmpFileName : extractionModelEditor.extractionModelFile);
dbConnectionDialog.addDbArgs(args);
Session.closeTemporaryTableSession();
BasicDataSource dataSource = new BasicDataSource(dbConnectionDialog.currentConnection.driverClass, dbConnectionDialog.currentConnection.url, dbConnectionDialog.currentConnection.user, dbConnectionDialog.getPassword(), 0, dbConnectionDialog.currentJarURLs());
Session session = SessionForUI.createSession(dataSource, dataSource.dbms, this);
@@ -1131,7 +1196,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
ExportDialog exportDialog = new ExportDialog(this, extractionModelEditor.dataModel, extractionModelEditor.getSubject(), extractionModelEditor.getSubjectCondition(), extractionModelEditor.extractionModel.additionalSubjects, session, args, dbConnectionDialog.getUser(), dbConnectionDialog.getPassword(), checkRI, dbConnectionDialog, extractionModelEditor.extractionModelFile, executionContext);
session.shutDown();
Session.closeTemporaryTableSession();
if (exportDialog.isOk()) {
exportDialog.fillCLIArgs(args);
List<String> ddlArgs = new ArrayList<String>();
@@ -1198,7 +1262,9 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
private Association findRestrictedDependency(DataModel dataModel) {
for (Association association: dataModel.namedAssociations.values()) {
if (association.isInsertDestinationBeforeSource() && association.isRestricted()) {
return association;
if (!association.fkHasNullFilter()) {
return association;
}
}
}
return null;
@@ -1326,10 +1392,10 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
load(modelFile);
} else {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
createFrame(modelFile, false);
UIUtil.setWaitCursor(this);
createFrame(modelFile, false, executionContext);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}
}
@@ -1365,7 +1431,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
JOptionPane.showMessageDialog(this, "Unable to load \"" + new File(modelFile).getName() + "\"\nExtraction model is assigned to data model \"" + DataModelManager.getModelDetails(dmf, executionContext).a + "\"", "Wrong Data Model", JOptionPane.ERROR_MESSAGE);
return;
}
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
extractionModelEditor.extractionModelFrame = null;
editorPanel.remove(extractionModelEditor);
extractionModelEditor = null;
@@ -1378,13 +1444,13 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
} catch (Throwable t) {
UIUtil.showException(this, "Error", t);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}
private void newModelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newModelActionPerformed
try {
createFrame(null, false);
createFrame(null, false, executionContext);
} catch (Throwable t) {
UIUtil.showException(this, "Error", t);
} finally {
@@ -1393,7 +1459,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
private void reload() {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
extractionModelEditor.extractionModelFrame = null;
editorPanel.remove(extractionModelEditor);
editorPanel.add(extractionModelEditor = new ExtractionModelEditor(extractionModelEditor.extractionModelFile, this, isHorizontalLayout, getConnectivityState(), getConnectivityStateToolTip(), executionContext), "editor");
@@ -1405,7 +1471,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
} catch (Throwable t) {
UIUtil.showException(this, "Error", t);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}
@@ -1626,11 +1692,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
extractionModelEditor.closureBorderView.toFront();
}//GEN-LAST:event_closureBorderToolMenuItemActionPerformed
private void restrictedDependenciesToolMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_restrictedDependenciesToolMenuItemActionPerformed
restrictedDependenciesView.setVisible(true);
restrictedDependenciesView.toFront();
}//GEN-LAST:event_restrictedDependenciesToolMenuItemActionPerformed
private void reloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reloadActionPerformed
try {
if (extractionModelEditor.extractionModelFile == null) {
@@ -1665,6 +1726,15 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
});
}//GEN-LAST:event_columnOrderItemActionPerformed
private void downloadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadButtonActionPerformed
updateInfoPanel.setVisible(false);
UpdateInfoManager.download();
}//GEN-LAST:event_downloadButtonActionPerformed
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
updateInfoPanel.setVisible(false);
}//GEN-LAST:event_jButton1ActionPerformed
private void executeAndReload(Callable<Boolean> callable) {
File tmpFile = null;
String extractionModelFile = extractionModelEditor.extractionModelFile;
@@ -1730,12 +1800,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
* Changes some nimbus LAF defaults.
*/
public static void customizeNimbus() {
try {
ToolTipManager.sharedInstance().setInitialDelay(500);
ToolTipManager.sharedInstance().setDismissDelay(7000);
} catch (Exception x) {
x.printStackTrace();
}
// nothing to do yet
}
/**
@@ -1797,6 +1862,12 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
if (new Integer(10).equals(dSize)) {
UIManager.put("SplitPane.dividerSize", new Integer(14));
}
if (UIManager.get("InternalFrame:InternalFrameTitlePane[Enabled].textForeground") instanceof Color) {
UIManager.put("InternalFrame:InternalFrameTitlePane[Enabled].textForeground", Color.BLUE);
}
UIUtil.prepareUI();
} catch (Exception x) {
}
@@ -1808,7 +1879,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
file = commandLine.arguments.get(0);
}
}
createFrame(file, true);
createFrame(file, true, null);
} catch (Throwable e) {
UIUtil.showException(null, "Error", e);
}
@@ -1865,11 +1936,15 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
return extractionModelFrame;
}
public static void createFrame(String file, final boolean withStartupWizzard) {
public static void createFrame(String file, final boolean withStartupWizzard, ExecutionContext executionContext) {
try {
final String finalFile = file;
if (file != null && new File(file).exists()) {
ExecutionContext executionContext = new ExecutionContext(CommandLineInstance.getInstance());
if (executionContext == null) {
executionContext = new ExecutionContext(CommandLineInstance.getInstance());
} else {
executionContext = new ExecutionContext(executionContext);
}
DataModelManager.setCurrentModelSubfolder(ExtractionModel.loadDatamodelFolder(file, executionContext), executionContext);
createFrame(finalFile, true, true, null, executionContext);
} else {
@@ -1951,6 +2026,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
private javax.swing.JMenuItem dataExport;
private javax.swing.JMenuItem dataImport;
private javax.swing.JMenuItem disconnectDb;
private javax.swing.JButton downloadButton;
private javax.swing.JMenu editMenu;
private javax.swing.JPanel editorPanel;
private javax.swing.JMenuItem exit;
@@ -1962,6 +2038,8 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
private javax.swing.JMenuItem helpForum;
private javax.swing.JCheckBoxMenuItem horizontalLayoutMenuItem;
private javax.swing.JMenuItem ignoreAll;
private javax.swing.JButton jButton1;
private javax.swing.JLayeredPane jLayeredPane1;
private javax.swing.JMenu jMenu1;
private javax.swing.JMenu jMenu2;
private javax.swing.JMenu jMenu3;
@@ -1991,7 +2069,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
public javax.swing.JMenuItem reload;
private javax.swing.JMenuItem removeAllRestrictions;
private javax.swing.JMenuItem renderHtml;
private javax.swing.JMenuItem restrictedDependenciesToolMenuItem;
private javax.swing.JMenuItem save;
private javax.swing.JMenuItem saveAs;
private javax.swing.JCheckBoxMenuItem showIgnored;
@@ -2008,6 +2085,8 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
private javax.swing.ButtonGroup steptimeGroup;
private javax.swing.JMenuItem tutorial;
private javax.swing.JMenuItem updateDataModel;
private javax.swing.JLabel updateInfoLabel;
private javax.swing.JPanel updateInfoPanel;
private javax.swing.JMenu view;
private javax.swing.JMenu viewMenu;
private javax.swing.JMenuItem zoomToFit;
@@ -2015,4 +2094,4 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
private static final long serialVersionUID = -2252377308370736756L;
}
}
@@ -121,7 +121,7 @@ public abstract class ListEditor<T> extends javax.swing.JPanel {
deleteButton.setVisible(false);
}
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
final Color BGSEL = new Color(0, 200, 255);
TableCellRenderer renderer = new DefaultTableCellRenderer() {
@Override
@@ -108,8 +108,10 @@ public class NeighborhoodPanel extends javax.swing.JPanel {
length = graphView.getHeight() / (getFontMetrics(font).getHeight() + 2) - 12;
if (length < 2) {
length = 2;
} else if (length > 20) {
length = 20;
}
initTableList(dataModel, table, hideIgnored, graphView);
createTableLinks(dataModel, table, graphView, hideIgnored);
@@ -161,7 +163,7 @@ public class NeighborhoodPanel extends javax.swing.JPanel {
@Override
protected void onRightClick(MouseEvent e) {
if (t != null) {
JPopupMenu popup = graphView.createPopupMenu(t, true);
JPopupMenu popup = graphView.createPopupMenu(t, null, true);
popup.show(e.getComponent(), e.getX(), e.getY());
popup.addPopupMenuListener(new PopupMenuListener() {
@Override
@@ -64,7 +64,7 @@ public class ParameterSelector extends javax.swing.JPanel {
isSelected, hasFocus, row, column);
if (render instanceof JLabel && !isSelected) {
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
((JLabel) render)
.setBackground((row % 2 == 0) ? BG1
: BG2);
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="detailsContainerPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>
@@ -0,0 +1,189 @@
/*
* Copyright 2007 - 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.jailer.ui;
import java.awt.Frame;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.SwingUtilities;
import net.sf.jailer.ExecutionContext;
import net.sf.jailer.JailerVersion;
import net.sf.jailer.database.BasicDataSource;
import net.sf.jailer.database.Session;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
import net.sf.jailer.ui.DbConnectionDialog.ConnectionInfo;
import net.sf.jailer.util.ClasspathUtil;
/**
* Asks for an alternative connection if the database analyzers connection has
* insufficient privileges to analyze a certain schema.
*
* @author Ralf Wisser
*/
public class PrivilegedSessionProviderDialog extends javax.swing.JDialog {
public static class Provider implements JDBCMetaDataBasedModelElementFinder.PrivilegedSessionProvider {
private final Frame parent;
private Set<String> tabu = new HashSet<String>();
public Provider(Frame parent) {
synchronized(this) {
this.parent = parent;
}
}
@Override
public Session askForSessionWithPermissionToReadSchema(final Session session, final Table view, final String schema, final String tableName,
final ExecutionContext executionContext) {
final Frame theParent;
synchronized(this) {
theParent = parent;
}
if (tabu.contains(schema)) {
return null;
}
final AtomicReference<Session> newSession = new AtomicReference<>();
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
InfoBar infoBar = new InfoBar("Insufficient Privileges",
"Need to analyze schema \"" + schema + "\" because\n" +
"view \"" + view.getName() + "\" is based on table \"" + schema + "." + tableName +"\".\n" +
"but that's not possible with the current connection.\n ",
"Please choose an alternative connection with the required privileges."
);
final PrivilegedSessionProviderDialog dialog = new PrivilegedSessionProviderDialog(theParent);
ConnectionInfo ci = new ConnectionInfo();
final DbConnectionDialog connectionDialog = new DbConnectionDialog(theParent, JailerVersion.APPLICATION_NAME, infoBar, executionContext, true) {
@Override
protected boolean isAssignedToDataModel(String dataModelFolder) {
return true;
}
};
final DbConnectionDetailsEditor detailsEditor = new DbConnectionDetailsEditor(theParent, DbConnectionDialog.jdbcHelpURL, false, infoBar, true) {
@Override
protected void onClose(boolean ok, ConnectionInfo info) {
dialog.setVisible(false);
if (ok) {
try {
BasicDataSource dataSource = new BasicDataSource(info.driverClass,
info.url, info.user,
info.password, 0, ClasspathUtil.toURLArray(info.jar1, info.jar2, info.jar3, info.jar4));
newSession.set(new Session(dataSource, dataSource.dbms));
} catch (Exception e) {
UIUtil.showException(theParent, "Error", e);
}
}
}
@Override
protected void onSelect() {
if (connectionDialog.connect("Analyze Database")) {
try {
setDetails((ConnectionInfo) connectionDialog.currentConnection.clone());
} catch (CloneNotSupportedException e) {
setDetails(connectionDialog.currentConnection);
}
}
}
};
ci.alias = "(temporary)";
ci.driverClass = session.driverClassName;
ci.url = session.dbUrl;
ci.user = schema;
detailsEditor.setDetails(ci);
dialog.detailsContainerPanel.add(detailsEditor.getContentPane());
detailsEditor.password.grabFocus();
dialog.setLocation(100, 150);
dialog.pack();
dialog.setSize(Math.max(500, dialog.getWidth()), dialog.getHeight());
UIUtil.initPeer();
dialog.setVisible(true);
}
});
Session result = newSession.get();
if (result == null) {
tabu.add(schema);
}
return result;
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
// ignore
}
return null;
}
}
/**
* Creates new form PrivilegedSessionProvider
*/
public PrivilegedSessionProviderDialog(Frame parent) {
super(parent, true);
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
jPanel1 = new javax.swing.JPanel();
detailsContainerPanel = new javax.swing.JPanel();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
getContentPane().setLayout(new java.awt.GridBagLayout());
jPanel1.setLayout(new java.awt.GridBagLayout());
detailsContainerPanel.setLayout(new java.awt.BorderLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
jPanel1.add(detailsContainerPanel, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
getContentPane().add(jPanel1, gridBagConstraints);
pack();
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel detailsContainerPanel;
private javax.swing.JPanel jPanel1;
// End of variables declaration//GEN-END:variables
}
@@ -198,6 +198,19 @@
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JCheckBox" name="fkToNullCheckBox">
<Properties>
<Property name="text" type="java.lang.String" value="Set foreign key columns to null"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="1"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="10" gridWidth="6" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel4">
@@ -72,6 +72,7 @@ public class RestrictionEditor extends javax.swing.JPanel {
jPanel9 = new javax.swing.JPanel();
restriction = new javax.swing.JTextField();
apply = new javax.swing.JButton();
fkToNullCheckBox = new javax.swing.JCheckBox();
jPanel4 = new javax.swing.JPanel();
columnsA = new javax.swing.JLabel();
source = new javax.swing.JLabel();
@@ -168,6 +169,15 @@ public class RestrictionEditor extends javax.swing.JPanel {
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
jPanel7.add(jPanel9, gridBagConstraints);
fkToNullCheckBox.setText("Set foreign key columns to null");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 10;
gridBagConstraints.gridwidth = 6;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.insets = new java.awt.Insets(2, 0, 0, 0);
jPanel7.add(fkToNullCheckBox, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 3;
@@ -257,6 +267,7 @@ public class RestrictionEditor extends javax.swing.JPanel {
javax.swing.JLabel columnsA;
javax.swing.JLabel columnsB;
public javax.swing.JLabel destination;
public javax.swing.JCheckBox fkToNullCheckBox;
public javax.swing.JRadioButton ignore;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel4;
@@ -40,7 +40,7 @@
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,85,0,0,1,-63"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
@@ -200,5 +200,14 @@
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="plugInPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="10" gridY="1" gridWidth="1" gridHeight="3" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
</Container>
</SubComponents>
</Form>
@@ -17,7 +17,6 @@ package net.sf.jailer.ui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
@@ -30,6 +29,8 @@ import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -48,6 +49,8 @@ import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JPanel;
@@ -56,6 +59,8 @@ import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
@@ -80,29 +85,46 @@ public class StringSearchPanel extends javax.swing.JPanel {
public interface Prepare {
void prepare(Set<MDSchema> selectedSchemas);
}
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final String titel, final Runnable onSuccess) {
return createSearchButton(owner, comboBox, titel, onSuccess, null);
public interface AdditionalComponentFactory {
JComponent create(StringSearchPanel searchPanel);
}
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess) {
return createSearchButton(owner, comboBox, titel, onSuccess, false);
}
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess, boolean alternativeIcon) {
return createSearchButton(owner, comboBox, titel, onSuccess, null, alternativeIcon);
}
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final String titel, final Runnable onSuccess, final Prepare prepare) {
return createSearchButton(owner, comboBox, titel, onSuccess, null, null, null);
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess, final Prepare prepare, boolean alternativeIcon) {
return createSearchButton(owner, comboBox, titel, onSuccess, null, null, null, alternativeIcon, null);
}
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final String titel, final Runnable onSuccess, final Prepare prepare, final MetaDataSource metaDataSource, final DataModel dataModel) {
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess, final Prepare prepare, final MetaDataSource metaDataSource, final DataModel dataModel) {
return createSearchButton(owner, comboBox, titel, onSuccess, prepare, metaDataSource, dataModel, false, null);
}
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess, final Prepare prepare, final MetaDataSource metaDataSource, final DataModel dataModel, boolean alternativeIcon, final AdditionalComponentFactory additionalComponentFactory) {
final JButton button = new JButton();
button.setIcon(UIUtil.scaleIcon(button, icon));
button.setIcon(UIUtil.scaleIcon(button, alternativeIcon? icon2 : icon));
button.setToolTipText("Find Table");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
button.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(button);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
Point location = button.getLocationOnScreen();
StringSearchPanel searchPanel = new StringSearchPanel(comboBox, metaDataSource, dataModel, prepare);
if (additionalComponentFactory != null) {
searchPanel.plugInPanel.add(additionalComponentFactory.create(searchPanel), java.awt.BorderLayout.CENTER);
} else {
searchPanel.plugInPanel.setVisible(false);
}
String result = searchPanel.find(owner, titel, location.x, location.y);
if (result != null && !result.equals(searchPanel.showAllLabel)) {
comboBox.setSelectedItem(result);
@@ -111,17 +133,44 @@ public class StringSearchPanel extends javax.swing.JPanel {
}
}
} finally {
button.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(button);
}
}
});
}
});
if (prepare == null) {
updateEnabledState(button, comboBox);
comboBox.getModel().addListDataListener(new ListDataListener() {
@Override
public void intervalRemoved(ListDataEvent arg0) {
updateEnabledState(button, comboBox);
}
@Override
public void intervalAdded(ListDataEvent arg0) {
updateEnabledState(button, comboBox);
}
@Override
public void contentsChanged(ListDataEvent arg0) {
updateEnabledState(button, comboBox);
}
});
comboBox.addPropertyChangeListener("model", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent arg0) {
updateEnabledState(button, comboBox);
}
});
}
return button;
}
public String find(Frame owner, String titel, int x, int y) {
dialog = new EscapableDialog(owner, titel, true) {
private static void updateEnabledState(JButton button, JComboBox comboBox) {
button.setEnabled(comboBox.getModel().getSize() > 1 || comboBox.getModel().getSize() == 1 && !"".equals(comboBox.getModel().getElementAt(0)));
}
public String find(Frame owner, Object titel, int x, int y) {
dialog = new EscapableDialog(owner, String.valueOf(titel), true) {
};
dialog.getContentPane().add(this);
dialog.pack();
@@ -214,12 +263,12 @@ public class StringSearchPanel extends javax.swing.JPanel {
@Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_ESCAPE) {
dialog.setVisible(false);
close();
} else if (e.getKeyChar() == KeyEvent.VK_DOWN) {
searchList.grabFocus();
} else if (e.getKeyChar() == '\n') {
result = searchList.getSelectedValue();
dialog.setVisible(false);
close();
}
}
@Override
@@ -276,9 +325,9 @@ public class StringSearchPanel extends javax.swing.JPanel {
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() >1) {
if (e.getClickCount() > 1) {
result = searchList.getSelectedValue();
dialog.setVisible(false);
close();
}
}
});
@@ -500,6 +549,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
jPanel1 = new javax.swing.JPanel();
okButton = new javax.swing.JButton();
cancelButton = new javax.swing.JButton();
plugInPanel = new javax.swing.JPanel();
loadingPanel.setBackground(java.awt.Color.white);
@@ -509,8 +559,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
cancelLoadiingButton.setText("Cancel");
cancelLoadiingButton.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cancelLoadiingButtonActionPerformed(evt);
}
});
@@ -529,10 +578,8 @@ public class StringSearchPanel extends javax.swing.JPanel {
searchList.setModel(new javax.swing.AbstractListModel<String>() {
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
@Override
public int getSize() { return strings.length; }
@Override
public String getElementAt(int i) { return strings[i]; }
public int getSize() { return strings.length; }
public String getElementAt(int i) { return strings[i]; }
});
jScrollPane1.setViewportView(searchList);
@@ -576,8 +623,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
selectAllButton.setText("Select all");
selectAllButton.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
selectAllButtonActionPerformed(evt);
}
});
@@ -608,8 +654,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
okButton.setText(" Ok ");
okButton.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
okButtonActionPerformed(evt);
}
});
@@ -622,8 +667,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
cancelButton.setText("Cancel");
cancelButton.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cancelButtonActionPerformed(evt);
}
});
@@ -638,17 +682,29 @@ public class StringSearchPanel extends javax.swing.JPanel {
gridBagConstraints.gridwidth = 3;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
add(jPanel1, gridBagConstraints);
plugInPanel.setLayout(new java.awt.BorderLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 10;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridheight = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
add(plugInPanel, gridBagConstraints);
}// </editor-fold>//GEN-END:initComponents
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
result = searchList.getSelectedValue();
dialog.setVisible(false);
close();
}//GEN-LAST:event_okButtonActionPerformed
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
dialog.setVisible(false);
close();
}//GEN-LAST:event_cancelButtonActionPerformed
public void close() {
dialog.setVisible(false);
}
private void cancelLoadiingButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelLoadiingButtonActionPerformed
cancelLoading.set(true);
}//GEN-LAST:event_cancelLoadiingButtonActionPerformed
@@ -670,6 +726,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JPanel loadingPanel;
private javax.swing.JButton okButton;
private javax.swing.JPanel plugInPanel;
private javax.swing.JPanel schemaPanel;
private javax.swing.JList<String> searchList;
private javax.swing.JTextField searchTextField;
@@ -678,12 +735,14 @@ public class StringSearchPanel extends javax.swing.JPanel {
// End of variables declaration//GEN-END:variables
static private ImageIcon icon;
static private ImageIcon icon2;
static {
String dir = "/net/sf/jailer/ui/resource";
// load images
try {
icon = new ImageIcon(MetaDataPanel.class.getResource(dir + "/search.png"));
icon2 = new ImageIcon(MetaDataPanel.class.getResource(dir + "/search2.png"));
} catch (Exception e) {
e.printStackTrace();
}
+88 -1
View File
@@ -17,6 +17,7 @@ package net.sf.jailer.ui;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FileDialog;
@@ -34,6 +35,8 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -49,6 +52,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -80,6 +84,7 @@ import net.sf.jailer.ui.databrowser.BrowserContentPane.TableModelItem;
import net.sf.jailer.ui.databrowser.Row;
import net.sf.jailer.ui.scrollmenu.JScrollC2PopupMenu;
import net.sf.jailer.ui.scrollmenu.JScrollPopupMenu;
import net.sf.jailer.ui.syntaxtextarea.RSyntaxTextAreaWithSQLSyntaxStyle;
import net.sf.jailer.util.CancellationException;
import net.sf.jailer.util.CancellationHandler;
import net.sf.jailer.util.CycleFinder;
@@ -947,7 +952,7 @@ public class UIUtil {
/**
* Pair of Icon and Text.
*/
public static class IconWithText {
public static class IconWithText implements Comparable<IconWithText> {
public final String text;
public final ImageIcon icon;
@@ -960,6 +965,88 @@ public class UIUtil {
public String toString() {
return text;
}
@Override
public int compareTo(IconWithText o) {
return text.compareTo(o.text);
}
}
private static boolean isPopupActive = false;
public static synchronized boolean isPopupActive() {
return isPopupActive;
}
private static synchronized void setPopupActive(boolean b) {
isPopupActive = b;
}
public static void showPopup(final Component invoker, final int x, final int y, final JPopupMenu popup) {
popup.addPropertyChangeListener("visible", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (Boolean.FALSE.equals(evt.getNewValue())) {
setPopupActive(false);
}
}
});
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
setPopupActive(true);
popup.show(invoker, x, y);
}
});
}
public static void invokeLater(final int ticks, final Runnable runnable) {
SwingUtilities.invokeLater(new Runnable() {
int count = ticks;
@Override
public void run() {
if (--count <= 0) {
runnable.run();
} else {
SwingUtilities.invokeLater(this);
}
}
});
}
private static Map<Component, Integer> waitLevel = new WeakHashMap<Component, Integer>();
public static void setWaitCursor(Component component) {
if (component != null) {
Integer level = waitLevel.get(component);
if (level != null) {
waitLevel.put(component, level + 1);
} else {
waitLevel.put(component, 1);
component.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
}
}
public static void resetWaitCursor(Component component) {
if (component != null) {
Integer level = waitLevel.get(component);
if (level != null) {
if (level == 1) {
component.setCursor(null);
waitLevel.remove(component);
} else {
waitLevel.put(component, level - 1);
}
}
}
}
/**
* Triggers UI initializations.
*/
public static void prepareUI() {
new RSyntaxTextAreaWithSQLSyntaxStyle(false, false);
}
}
@@ -54,6 +54,7 @@ import net.sf.jsqlparser.statement.Commit;
import net.sf.jsqlparser.statement.SetStatement;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.Statements;
import net.sf.jsqlparser.statement.UseStatement;
import net.sf.jsqlparser.statement.alter.Alter;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.table.CreateTable;
@@ -70,6 +71,7 @@ import net.sf.jsqlparser.statement.select.AllTableColumns;
import net.sf.jsqlparser.statement.select.FromItemVisitor;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.LateralSubSelect;
import net.sf.jsqlparser.statement.select.ParenthesisFromItem;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
@@ -405,12 +407,16 @@ public class AssociationProposer {
if (subjoin.getLeft() != null) {
subjoin.getLeft().accept(this);
}
if (subjoin.getJoin() != null) {
if (subjoin.getJoin().getRightItem() != null) {
subjoin.getJoin().getRightItem().accept(this);
}
if (subjoin.getJoin().getOnExpression() != null) {
scopes.peek().expressions.add(subjoin.getJoin().getOnExpression());
if (subjoin.getJoinList() != null) {
for (Join join: subjoin.getJoinList()) {
if (join != null) {
if (join.getRightItem() != null) {
join.getRightItem().accept(this);
}
if (join.getOnExpression() != null) {
scopes.peek().expressions.add(join.getOnExpression());
}
}
}
}
}
@@ -437,6 +443,13 @@ public class AssociationProposer {
fn += Quoting.normalizeIdentifier(tableName.getName());
scopes.peek().aliasToTable.put(Quoting.normalizeIdentifier(alias), fn);
}
@Override
public void visit(ParenthesisFromItem aThis) {
if (aThis.getFromItem() != null) {
aThis.getFromItem().accept(this);
}
}
};
if (plainSelect.getFromItem() != null) {
plainSelect.getFromItem().accept(fromItemVisitor);
@@ -508,6 +521,10 @@ public class AssociationProposer {
public void visit(AnalyticExpression expr) {
}
@Override
public void visit(UseStatement use) {
}
private void analyseTopScope() {
for (Expression expr: scopes.peek().expressions) {
expr.accept(new ExpressionVisitorAdapter() {
@@ -629,7 +646,6 @@ public class AssociationProposer {
return dColumn;
}
}
break;
}
}
}
@@ -185,7 +185,7 @@ public class AssociationProposerView extends javax.swing.JPanel {
final TableCellRenderer defaultTableCellRenderer = proposalTable.getDefaultRenderer(String.class);
TableCellRenderer renderer = new TableCellRenderer() {
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
@@ -443,6 +443,8 @@ public class AssociationProposerView extends javax.swing.JPanel {
adjustTableColumnsWidth();
if (proposalsModel.getRowCount() == 0 && knownModel.getRowCount() == 0 && numErrors > 0) {
tabbedPane.setSelectedComponent(problemTabPanel);
} else if (proposalsModel.getRowCount() == 0 && knownModel.getRowCount() > 0) {
tabbedPane.setSelectedComponent(knownPanel);
}
}
@@ -114,7 +114,7 @@ public abstract class ConstraintChecker extends javax.swing.JPanel {
final TableCellRenderer defaultTableCellRenderer = problemsTable.getDefaultRenderer(String.class);
problemsTable.setDefaultRenderer(Object.class, new TableCellRenderer() {
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
@@ -80,7 +80,7 @@ public class BrowserContentCellEditor {
@Override
boolean isEditable(int columnType, Object content) {
return content == null || content instanceof String;
return content == null || (content instanceof String && !(content.toString().indexOf('\n') >= 0 || content.toString().indexOf('\t') >= 0));
}
},
DATE {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -120,7 +120,7 @@
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="1.0" weightY="0.0"/>
<GridBagConstraints gridX="7" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@@ -140,7 +140,7 @@
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
<GridBagConstraints gridX="8" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@@ -237,6 +237,39 @@
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JComboBox" name="findPathComboBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4">
<StringItem index="0" value="Item 1"/>
<StringItem index="1" value="Item 2"/>
<StringItem index="2" value="Item 3"/>
<StringItem index="3" value="Item 4"/>
</StringArray>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findPathComboBoxActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="findPathButton">
<Properties>
<Property name="text" type="java.lang.String" value="Find Path to..."/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findPathButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="5" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="4" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
@@ -53,7 +53,7 @@ import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
@@ -70,9 +70,15 @@ import net.sf.jailer.datamodel.Association;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.ui.AutoCompletion;
import net.sf.jailer.ui.ClosureView;
import net.sf.jailer.ui.JComboBox;
import net.sf.jailer.ui.StringSearchPanel;
import net.sf.jailer.ui.UIUtil;
import net.sf.jailer.ui.StringSearchPanel.AdditionalComponentFactory;
import net.sf.jailer.ui.databrowser.Desktop.RowBrowser;
import net.sf.jailer.ui.pathfinder.HistoryPanel;
import net.sf.jailer.ui.pathfinder.PathFinder;
import net.sf.jailer.ui.pathfinder.PathFinder.Result;
import net.sf.jailer.util.Pair;
/**
@@ -97,7 +103,282 @@ public abstract class DBClosureView extends javax.swing.JDialog {
*/
private final List<Color> bgColor = new ArrayList<Color>();
/**
private final class TableMouseListener implements MouseListener {
private Map<Integer, String> manuallySelected = new TreeMap<Integer, String>();
public void openPathFinder(final Table table, boolean fromHistory) {
PathFinder pathFinder = new PathFinder();
Result result = pathFinder.find(getRootTable(), table, getDataModel(), true, fromHistory, DBClosureView.this.parent);
if (result != null) {
List<Table> path = result.path;
mainPath.clear();
mainPathAsSet.clear();
Map<Table, Integer> fd = new HashMap<Table, Integer>();
for (int i = 0; i < result.path.size(); ++i) {
fd.put(result.path.get(i), i);
}
refreshTableModel(fd);
selectedTable = null;
// refresh();
for (int i = 0; i < path.size(); ++i) {
Table r = path.get(i);
String tabName = getDataModel().getDisplayName(r);
selectCell(result.expand && i == path.size() - 1, tabName, r);
}
}
}
private void expandPath() {
List<Table> path = new ArrayList<Table>();
for (CellInfo ci: mainPath) {
path.add(ci.table);
}
expandTablePath(path);
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseClicked(final MouseEvent e) {
// reset view
{
Point position = e.getPoint();
int row = closureTable.rowAtPoint(position);
int column = closureTable.columnAtPoint(position);
if (row >= 0 && column >= 0) {
Object value = closureTable.getModel().getValueAt(row, column);
CellInfo ci = cellInfo.get(value);
if (currentForcedDistance != null && ci != null && !mainPathAsSet.contains(ci)) {
mainPath.clear();
mainPathAsSet.clear();
currentForcedDistance = null;
refreshTableModel(null);
selectedTable = null;
refresh();
}
}
}
// context menu
if (SwingUtilities.isRightMouseButton(e)) {
int row = closureTable.rowAtPoint(e.getPoint());
int column = closureTable.columnAtPoint(e.getPoint());
if (row < 0 || column < 0) return;
final Object value = closureTable.getModel().getValueAt(row, column);
if (value == null || !(value instanceof String)) return;
final Table table = getDataModel().getTableByDisplayName((String) value);
if (table != null) {
if (selectedTable == null || !selectedTable.equals(value)) {
if (cellInfo.containsKey(value) && !cellInfo.get(value).selected) {
selectTableCell(column, row);
}
}
// int tableLevel = -1;
// if (cellInfo.containsKey(value)) {
// tableLevel = cellInfo.get(value).level;
// }
// JCheckBoxMenuItem exclude = new JCheckBoxMenuItem("Exclude " + getDataModel().getDisplayName(table) + " from Path");
// exclude.setSelected(excludedFromPath.contains(table));
// exclude.setEnabled(mainPath.contains(cellInfo.get(value)) || excludedFromPath.contains(table));
// exclude.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// if (!excludedFromPath.contains(table)) {
// excludedFromPath.add(table);
// } else {
// excludedFromPath.remove(table);
// }
// mainPath.clear();
// mainPathAsSet.clear();
// refresh();
// CellInfo ci = cellInfo.get(selectedTable);
// if (ci != null) {
// String st = selectedTable;
// selectedTable = null;
// select(st, ci);
// }
// }
// });
//
// final Set<Table> toExclude = new HashSet<Table>();
// for (Entry<String, CellInfo> ciE: cellInfo.entrySet()) {
// if (ciE.getValue().selected && ciE.getValue().level == tableLevel) {
// Table tableByDisplayName = getDataModel().getTableByDisplayName(ciE.getKey());
// if (tableByDisplayName != null) {
// toExclude.add(tableByDisplayName);
// }
// }
// }
// JCheckBoxMenuItem excludeAll = new JCheckBoxMenuItem("Exclude all with Distance " + (tableLevel + 1) + " from Path");
// excludeAll.setEnabled(toExclude.size() > 1);
// excludeAll.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// excludedFromPath.addAll(toExclude);
// mainPath.clear();
// mainPathAsSet.clear();
// refresh();
// CellInfo ci = cellInfo.get(selectedTable);
// if (ci != null) {
// String st = selectedTable;
// selectedTable = null;
// select(st, ci);
// }
// }
// });
// JMenuItem deselect = new JMenuItem("Deselect path");
// deselect.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// mainPath.clear();
// mainPathAsSet.clear();
// excludedFromPath.clear();
// refreshTableModel();
// selectedTable = null;
// refresh();
// }
// });
JMenuItem pathFinder = new JMenuItem("Find more complex path to " + getDataModel().getDisplayName(table));
Table rt = getRootTable();
if (rt == null || !rt.closure(false).contains(table)) {
pathFinder.setEnabled(false);
}
pathFinder.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
openPathFinder(table, false);
}
});
JMenuItem openPath = new JMenuItem("Open path to " + getDataModel().getDisplayName(table));
if (rt == null || !rt.closure(false).contains(table)) {
openPath.setEnabled(false);
}
openPath.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
expandPath();
DBClosureView.this.select(selectedTable);
}
});
RowBrowser rb = getVisibleTables().get(table);
if (rb == null) {
if (!mainPath.isEmpty()) {
JPopupMenu menu = new JPopupMenu();
menu.add(openPath);
menu.add(new JSeparator());
menu.add(pathFinder);
UIUtil.showPopup(e.getComponent(), e.getX(), e.getY(), menu);
}
} else {
JPopupMenu menu = new JPopupMenu();
JMenuItem select = new JMenuItem("Select " + getDataModel().getDisplayName(table));
select.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DBClosureView.this.select((String) value);
}
});
menu.add(select);
// menu.addSeparator();
// menu.add(exclude);
// menu.add(excludeAll);
menu.addSeparator();
JPopupMenu popup = rb.browserContentPane.createPopupMenu(null, -1, 0, 0, false);
JPopupMenu popup2 = rb.browserContentPane.createSqlPopupMenu(null, -1, 0, 0, true, closureTable);
popup.add(new JSeparator());
for (Component c : popup.getComponents()) {
menu.add(c);
}
for (Component c : popup2.getComponents()) {
menu.add(c);
}
if (!mainPath.isEmpty()) {
// menu.addSeparator();
// menu.add(deselect);
menu.addSeparator();
menu.add(openPath);
menu.add(pathFinder);
}
UIUtil.showPopup(e.getComponent(), e.getX(), e.getY(), menu);
}
}
}
if (SwingUtilities.isLeftMouseButton(e)) {
Point position = e.getPoint();
int row = closureTable.rowAtPoint(position);
int column = closureTable.columnAtPoint(position);
if (row < 0 || column < 0) return;
Object value = closureTable.getModel().getValueAt(row, column);
if (value == null || !(value instanceof String)) return;
final Table table = getDataModel().getTableByDisplayName((String) value);
selectCell(e.getClickCount() > 1, value, table);
}
}
private void selectCell(boolean expandPath, Object value, final Table table) {
if (table != null) {
if (cellInfo.containsKey(value)) {
String prevSelectedTable = selectedTable;
CellInfo selectedCellInfo = cellInfo.get(value);
if (selectedCellInfo.selected && !mainPathAsSet.contains(selectedCellInfo)) {
manuallySelected.put(selectedCellInfo.level, (String) value);
select(prevSelectedTable, selectedCellInfo);
} else if (!selectedCellInfo.selected) {
manuallySelected.clear();
selectTableCell((String) value);
} else {
scrollToTable(table);
}
}
if (expandPath) {
if (!mainPath.isEmpty()) {
expandPath();
}
}
}
}
private void select(String toSelect, CellInfo selectedCellInfo) {
TreeMap<Integer, String> newMS = new TreeMap<Integer, String>(manuallySelected);
String lastFound = null;
for (Entry<Integer, String> ms: manuallySelected.entrySet()) {
find(ms.getValue());
if (selectedCellInfo.level < ms.getKey() && !mainPathAsSet.contains(selectedCellInfo)) {
manuallySelected = newMS;
if (lastFound != null) {
find(lastFound);
}
break;
}
newMS.put(ms.getKey(), ms.getValue());
lastFound = ms.getValue();
}
if (toSelect != null && !toSelect.equals(selectedTable)) {
find(toSelect);
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
}
/**
* Holds infos about a cell in the closure-table.
*/
private class CellInfo {
@@ -126,8 +407,10 @@ public abstract class DBClosureView extends javax.swing.JDialog {
private List<CellInfo> mainPath = new ArrayList<CellInfo>();
private HashSet<CellInfo> mainPathAsSet = new HashSet<CellInfo>();
private Set<Pair<String, String>> dependencies = new HashSet<Pair<String,String>>();
private Set<Table> excludedFromPath = new HashSet<Table>();
private Map<Table, Integer> currentForcedDistance = null;
private final JFrame parent;
private TableMouseListener tableMouseListener;
/** Creates new form FindDialog
* @param rootTable */
@@ -166,6 +449,68 @@ public abstract class DBClosureView extends javax.swing.JDialog {
findButton.setVisible(false);
searchButton.setText("Find Table");
AutoCompletion.enable(findPathComboBox);
findPathComboBox.getEditor().getEditorComponent().addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == '\n') {
findPathComboBoxActionPerformed(null);
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent arg0) {
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 20;
JButton stFindPathButton = StringSearchPanel.createSearchButton(
this.parent, findPathComboBox,
new Object() {
public String toString() {
Table rootTable = getRootTable();
return (rootTable != null? ("From " + getDataModel().getDisplayName(rootTable) + " - ") : "") + "Select destination or choose from History";
}
},
new Runnable() {
@Override
public void run() {
Object toFind = findPathComboBox.getSelectedItem();
if (toFind != null) {
CellInfo cellInfo = DBClosureView.this.cellInfo.get(toFind);
if (cellInfo != null) {
tableMouseListener.openPathFinder(cellInfo.table, false);
}
}
}
}, null, null, null, true, new AdditionalComponentFactory() {
@Override
public JComponent create(final StringSearchPanel searchPanel) {
HistoryPanel historyPanel = new HistoryPanel(getRootTable(), getDataModel()) {
private static final long serialVersionUID = 1L;
@Override
protected void close() {
searchPanel.close();
}
@Override
protected void apply(Table source, Table destination) {
tableMouseListener.openPathFinder(destination, true);
}
};
return historyPanel;
}
});
tablePanel.add(stFindPathButton, gridBagConstraints);
findPathComboBox.setVisible(false);
findPathButton.setVisible(false);
stFindPathButton.setText("Find Path to...");
columnsComboBox.setModel(new DefaultComboBoxModel<Integer>(new Integer[] {
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
}));
@@ -245,197 +590,10 @@ public abstract class DBClosureView extends javax.swing.JDialog {
};
closureTable.setShowGrid(false);
closureTable.setSurrendersFocusOnKeystroke(true);
closureTable.getTableHeader().setReorderingAllowed(false);
jScrollPane1.setViewportView(closureTable);
closureTable.addMouseListener(new MouseListener() {
private Map<Integer, String> manuallySelected = new TreeMap<Integer, String>();
private void expandPath() {
List<Table> path = new ArrayList<Table>();
for (CellInfo ci: mainPath) {
path.add(ci.table);
}
expandTablePath(path);
}
@Override
public void mouseClicked(final MouseEvent e) {
mouseReleased(e);
}
@Override
public void mouseReleased(MouseEvent e) {
// context menu
if (SwingUtilities.isRightMouseButton(e)) {
int row = closureTable.rowAtPoint(e.getPoint());
int column = closureTable.columnAtPoint(e.getPoint());
if (row < 0 || column < 0) return;
final Object value = closureTable.getModel().getValueAt(row, column);
if (value == null || !(value instanceof String)) return;
final Table table = getDataModel().getTableByDisplayName((String) value);
if (table != null) {
if (selectedTable == null || !selectedTable.equals(value)) {
if (cellInfo.containsKey(value) && !cellInfo.get(value).selected) {
selectTableCell(column, row);
}
}
JCheckBoxMenuItem exclude = new JCheckBoxMenuItem("Exclude " + getDataModel().getDisplayName(table) + " from Path");
exclude.setSelected(excludedFromPath.contains(table));
exclude.setEnabled(mainPath.contains(cellInfo.get(value)) || excludedFromPath.contains(table));
exclude.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!excludedFromPath.contains(table)) {
excludedFromPath.add(table);
} else {
excludedFromPath.remove(table);
}
mainPath.clear();
mainPathAsSet.clear();
refresh();
CellInfo ci = cellInfo.get(selectedTable);
if (ci != null) {
String st = selectedTable;
selectedTable = null;
select(st, ci);
}
}
});
JMenuItem deselect = new JMenuItem("Deselect Path");
deselect.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mainPath.clear();
mainPathAsSet.clear();
excludedFromPath.clear();
refreshTableModel();
selectedTable = null;
refresh();
}
});
RowBrowser rb = getVisibleTables().get(table);
if (rb == null) {
if (!mainPath.isEmpty()) {
JPopupMenu menu = new JPopupMenu();
JMenuItem open = new JMenuItem("Open Path to " + selectedTable);
open.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
expandPath();
}
});
menu.add(open);
JMenuItem openAndSelect = new JMenuItem("Open Path to and Select " + selectedTable);
openAndSelect.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
expandPath();
DBClosureView.this.select(selectedTable);
}
});
menu.add(openAndSelect);
menu.add(new JSeparator());
menu.add(exclude);
menu.add(deselect);
menu.show(e.getComponent(), e.getX(), e.getY());
}
} else {
JPopupMenu menu = new JPopupMenu();
JMenuItem select = new JMenuItem("Select " + getDataModel().getDisplayName(table));
select.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DBClosureView.this.select((String) value);
}
});
menu.add(select);
menu.addSeparator();
menu.add(exclude);
menu.addSeparator();
JPopupMenu popup = rb.browserContentPane.createPopupMenu(null, -1, 0, 0, false);
JPopupMenu popup2 = rb.browserContentPane.createSqlPopupMenu(null, -1, 0, 0, true);
popup.add(new JSeparator());
for (Component c : popup.getComponents()) {
menu.add(c);
}
for (Component c : popup2.getComponents()) {
menu.add(c);
}
if (!mainPath.isEmpty()) {
menu.addSeparator();
menu.add(deselect);
}
UIUtil.fit(popup);
menu.show(e.getComponent(), e.getX(), e.getY());
}
}
}
if (SwingUtilities.isLeftMouseButton(e)) {
Point position = e.getPoint();
int row = closureTable.rowAtPoint(position);
int column = closureTable.columnAtPoint(position);
if (row < 0 || column < 0) return;
Object value = closureTable.getModel().getValueAt(row, column);
if (value == null || !(value instanceof String)) return;
final Table table = getDataModel().getTableByDisplayName((String) value);
if (table != null) {
if (cellInfo.containsKey(value)) {
String prevSelectedTable = selectedTable;
CellInfo selectedCellInfo = cellInfo.get(value);
if (selectedCellInfo.selected && !mainPathAsSet.contains(selectedCellInfo)) {
manuallySelected.put(selectedCellInfo.level, (String) value);
select(prevSelectedTable, selectedCellInfo);
} else if (!selectedCellInfo.selected) {
manuallySelected.clear();
selectTableCell(column, row);
}
}
if (e.getClickCount() > 1) {
RowBrowser rb = getVisibleTables().get(table);
if (rb == null) {
if (!mainPath.isEmpty()) {
expandPath();
}
}
}
}
}
}
private void select(String toSelect, CellInfo selectedCellInfo) {
TreeMap<Integer, String> newMS = new TreeMap<Integer, String>(manuallySelected);
String lastFound = null;
for (Entry<Integer, String> ms: manuallySelected.entrySet()) {
find(ms.getValue());
if (selectedCellInfo.level < ms.getKey() && !mainPathAsSet.contains(selectedCellInfo)) {
manuallySelected = newMS;
if (lastFound != null) {
find(lastFound);
}
break;
}
newMS.put(ms.getKey(), ms.getValue());
lastFound = ms.getValue();
}
if (toSelect != null && !toSelect.equals(selectedTable)) {
find(toSelect);
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
});
closureTable.addMouseListener(tableMouseListener = new TableMouseListener());
searchComboBox.setMaximumRowCount(30);
@@ -506,9 +664,9 @@ public abstract class DBClosureView extends javax.swing.JDialog {
} else if (getVisibleTables().containsKey(t)) {
((JLabel) render).setFont(onPath? italicBold : italic);
}
if (excludedFromPath.contains(t)) {
((JLabel) render).setForeground(new Color(180, 180, 180));
}
// if (currentForcedDistance != null && currentForcedDistance.containsKey(t)) {
// ((JLabel) render).setForeground(new Color(180, 180, 180));
// }
if (getVisibleTables().containsKey(t)) {
((JLabel) render).setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.lightGray, Color.gray));
}
@@ -597,42 +755,46 @@ public abstract class DBClosureView extends javax.swing.JDialog {
private void selectTableCell(int col, int row) {
if (col >= 1 && row >= 0) {
String displayName = (String) closureTable.getModel().getValueAt(row, col);
closureTable.getSelectionModel().clearSelection();
for (CellInfo c: cellInfo.values()) {
c.selected = false;
selectTableCell(displayName);
}
}
private void selectTableCell(String displayName) {
closureTable.getSelectionModel().clearSelection();
for (CellInfo c: cellInfo.values()) {
c.selected = false;
}
if (displayName != null && !"".equals(displayName)) {
Table prevTable = null;
if (selectedTable != null) {
prevTable = getDataModel().getTableByDisplayName(selectedTable);
}
if (displayName != null && !"".equals(displayName)) {
Table prevTable = null;
if (selectedTable != null) {
prevTable = getDataModel().getTableByDisplayName(selectedTable);
}
selectedTable = displayName;
searchComboBox.setSelectedItem(selectedTable);
repaintClosureView();
Table table = getDataModel().getTableByDisplayName(selectedTable);
if (table != null) {
CellInfo selectionInfo = cellInfo.get(selectedTable);
selectionInfo.select();
if (prevTable != table) {
Set<Table> visibleTables = getVisibleTables().keySet();
Set<Table> mainPathTables = new HashSet<Table>();
for (CellInfo ci: mainPath) {
mainPathTables.add(ci.table);
}
Set<CellInfo> pathToVisibleTable = shortestPathToVisibleTable(visibleTables, selectionInfo);
Set<CellInfo> pathToMainPathTable = shortestPathToVisibleTable(mainPathTables, selectionInfo);
List<CellInfo> pathVT = new ArrayList<CellInfo>();
int vtMaxRow = fillPath(selectionInfo, visibleTables, pathToVisibleTable, pathVT);
List<CellInfo> pathST = new ArrayList<CellInfo>();
int stMaxRow = fillPath(selectionInfo, mainPathTables, pathToMainPathTable, pathST);
if (pathToMainPathTable.isEmpty()) { // (vtMaxRow > stMaxRow) {
mainPath = pathVT;
} else {
mainPath = pathST;
}
selectedTable = displayName;
searchComboBox.setSelectedItem(selectedTable);
repaintClosureView();
Table table = getDataModel().getTableByDisplayName(selectedTable);
if (table != null) {
CellInfo selectionInfo = cellInfo.get(selectedTable);
selectionInfo.select();
if (prevTable != table) {
Set<Table> visibleTables = getVisibleTables().keySet();
Set<Table> mainPathTables = new HashSet<Table>();
for (CellInfo ci: mainPath) {
mainPathTables.add(ci.table);
}
Set<CellInfo> pathToVisibleTable = shortestPathToVisibleTable(visibleTables, selectionInfo);
Set<CellInfo> pathToMainPathTable = shortestPathToVisibleTable(mainPathTables, selectionInfo);
List<CellInfo> pathVT = new ArrayList<CellInfo>();
int vtMaxRow = fillPath(selectionInfo, visibleTables, pathToVisibleTable, pathVT);
List<CellInfo> pathST = new ArrayList<CellInfo>();
int stMaxRow = fillPath(selectionInfo, mainPathTables, pathToMainPathTable, pathST);
if (pathToMainPathTable.isEmpty()) { // (vtMaxRow > stMaxRow) {
mainPath = pathVT;
} else {
mainPath = pathST;
}
mainPathAsSet = new HashSet<CellInfo>(mainPath);
}
mainPathAsSet = new HashSet<CellInfo>(mainPath);
}
}
}
@@ -696,7 +858,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
*/
public void refresh() {
String prevSelection = selectedTable;
refreshTableModel();
refreshTableModel(null);
if (cellInfo.containsKey(prevSelection)) {
selectedTable = prevSelection;
} else {
@@ -708,12 +870,17 @@ public abstract class DBClosureView extends javax.swing.JDialog {
/**
* Refreshes the table model.
*/
private void refreshTableModel() {
private void refreshTableModel(Map<Table, Integer> forcedDistance) {
cellInfo.clear();
dependencies.clear();
Table selectedTable = getSelectedTable();
Object[] columns = new Object[tablesPerLine + 1];
currentForcedDistance = forcedDistance;
if (forcedDistance == null) {
forcedDistance = new HashMap<Table, Integer>();
}
Object[] columns = new Object[tablesPerLine + 1];
for (int i = 0; i < columns.length; ++i) {
columns[i] = "";
}
@@ -740,7 +907,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
boolean isolated = false;
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
final Color BG2 = new Color(242, 255, 242);
final Color BG3 = new Color(255, 255, 240);
final Color BG4 = new Color(220, 220, 220);
final Color BG5 = new Color(255, 240, 240);
@@ -796,27 +963,40 @@ public abstract class DBClosureView extends javax.swing.JDialog {
Table table = getDataModel().getTableByDisplayName(t);
if (table != null) {
CellInfo cellInfoT = this.cellInfo.get(t);
if (!excludedFromPath.contains(table)) {
for (Association association: table.associations) {
String displayName = getDataModel().getDisplayName(association.destination);
if (!association.isIgnored()) {
if (!visited.contains(displayName)) {
nextLine.add(displayName);
visited.add(displayName);
CellInfo cellInfo = new CellInfo(distance);
cellInfo.parents.add(cellInfoT);
cellInfo.table = association.destination;
for (Association association: table.associations) {
Integer fd = forcedDistance.get(association.destination);
if (fd != null && fd != distance + 1) {
continue;
}
boolean addToParent = true;
if (forcedDistance.containsKey(association.destination)) {
if (!forcedDistance.containsKey(table)) {
addToParent = false;
}
}
String displayName = getDataModel().getDisplayName(association.destination);
if (!association.isIgnored() ||
(forcedDistance.containsKey(association.source) && forcedDistance.containsKey(association.destination))) {
if (!visited.contains(displayName)) {
nextLine.add(displayName);
visited.add(displayName);
CellInfo cellInfo = new CellInfo(distance);
if (addToParent) {
cellInfo.parents.add(cellInfoT);
}
cellInfo.table = association.destination;
if (association.isInsertDestinationBeforeSource()) {
dependencies.add(new Pair<String, String>(t, displayName));
}
this.cellInfo.put(displayName, cellInfo);
} else {
if (nextLine.contains(displayName)) {
if (addToParent) {
this.cellInfo.get(displayName).parents.add(cellInfoT);
}
if (association.isInsertDestinationBeforeSource()) {
dependencies.add(new Pair<String, String>(t, displayName));
}
this.cellInfo.put(displayName, cellInfo);
} else {
if (nextLine.contains(displayName)) {
this.cellInfo.get(displayName).parents.add(cellInfoT);
if (association.isInsertDestinationBeforeSource()) {
dependencies.add(new Pair<String, String>(t, displayName));
}
}
}
}
}
@@ -939,6 +1119,8 @@ public abstract class DBClosureView extends javax.swing.JDialog {
vector.addAll(nonIsolated);
searchComboBox.setModel(new DefaultComboBoxModel<String>(vector));
searchComboBox.setSelectedItem("");
findPathComboBox.setModel(new DefaultComboBoxModel<String>(vector));
findPathComboBox.setSelectedItem("");
}
private Table getSelectedTable() {
@@ -965,9 +1147,9 @@ public abstract class DBClosureView extends javax.swing.JDialog {
tablePanel = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
closureTable = new javax.swing.JTable();
searchComboBox = new net.sf.jailer.ui.JComboBox();
searchComboBox = new JComboBox();
jLabel7 = new javax.swing.JLabel();
columnsComboBox = new net.sf.jailer.ui.JComboBox();
columnsComboBox = new javax.swing.JComboBox();
findButton = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
@@ -977,6 +1159,8 @@ public abstract class DBClosureView extends javax.swing.JDialog {
jLabel6 = new javax.swing.JLabel();
jLabel8 = new javax.swing.JLabel();
jLabel9 = new javax.swing.JLabel();
findPathComboBox = new JComboBox();
findPathButton = new javax.swing.JButton();
contentPanel.setLayout(new java.awt.GridBagLayout());
@@ -1018,8 +1202,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
searchComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
searchComboBox.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
searchComboBoxActionPerformed(evt);
}
});
@@ -1030,7 +1213,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
jLabel7.setText("Columns ");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridx = 7;
gridBagConstraints.gridy = 20;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.weightx = 1.0;
@@ -1038,20 +1221,18 @@ public abstract class DBClosureView extends javax.swing.JDialog {
columnsComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
columnsComboBox.addItemListener(new java.awt.event.ItemListener() {
@Override
public void itemStateChanged(java.awt.event.ItemEvent evt) {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
columnsComboBoxItemStateChanged(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridx = 8;
gridBagConstraints.gridy = 20;
tablePanel.add(columnsComboBox, gridBagConstraints);
findButton.setText("Find");
findButton.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
findButtonActionPerformed(evt);
}
});
@@ -1110,6 +1291,30 @@ public abstract class DBClosureView extends javax.swing.JDialog {
gridBagConstraints.gridy = 8;
tablePanel.add(jLabel9, gridBagConstraints);
findPathComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
findPathComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
findPathComboBoxActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 20;
tablePanel.add(findPathComboBox, gridBagConstraints);
findPathButton.setText("Find Path to...");
findPathButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
findPathButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 5;
gridBagConstraints.gridy = 20;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
tablePanel.add(findPathButton, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
@@ -1132,6 +1337,12 @@ public abstract class DBClosureView extends javax.swing.JDialog {
find((String) toFind);
}//GEN-LAST:event_findButtonActionPerformed
private void findPathComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findPathComboBoxActionPerformed
}//GEN-LAST:event_findPathComboBoxActionPerformed
private void findPathButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findPathButtonActionPerformed
}//GEN-LAST:event_findPathButtonActionPerformed
protected void find(String toFind) {
if (toFind != null && !toFind.equals(selectedTable)) {
CellInfo cellInfo = this.cellInfo.get(toFind);
@@ -1145,12 +1356,15 @@ public abstract class DBClosureView extends javax.swing.JDialog {
protected abstract Map<Table, RowBrowser> getVisibleTables();
protected abstract void expandTablePath(List<Table> path);
protected abstract void select(String selectedTable);
protected abstract void scrollToTable(Table table);
// Variables declaration - do not modify//GEN-BEGIN:variables
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTable closureTable;
private net.sf.jailer.ui.JComboBox columnsComboBox;
private javax.swing.JComboBox columnsComboBox;
public javax.swing.JPanel contentPanel;
private javax.swing.JButton findButton;
private javax.swing.JButton findPathButton;
private JComboBox findPathComboBox;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
@@ -1161,7 +1375,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
private javax.swing.JLabel jLabel8;
private javax.swing.JLabel jLabel9;
private javax.swing.JScrollPane jScrollPane1;
private net.sf.jailer.ui.JComboBox searchComboBox;
private JComboBox searchComboBox;
public javax.swing.JPanel tablePanel;
// End of variables declaration//GEN-END:variables
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,271 @@
/*
* Copyright 2007 - 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.jailer.ui.databrowser;
import java.awt.Component;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Stack;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import javax.swing.plaf.basic.BasicInternalFrameUI;
import net.sf.jailer.ui.databrowser.Desktop.RowBrowser;
/**
* Desktop Anchor Manager.
*
* @author Ralf Wisser
*/
public abstract class DesktopAnchorManager {
private final JPanel anchorPanel;
private final JButton anchorButton;
private Long disabledUntil;
private Long showedAt;
private RowBrowser currentBrowser;
private RowBrowser newestBrowser;
private final static int MAX_RETENDION = 2000;
public DesktopAnchorManager(JPanel anchorPanel) {
this.anchorPanel = anchorPanel;
this.anchorButton = new JButton(anchorIcon);
this.anchorPanel.setVisible(false);
anchorPanel.add(anchorButton);
anchorButton.setToolTipText("align horizontally with predecessors");
anchorButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (currentBrowser != null) {
reset(1000);
layout(currentBrowser);
}
}
});
anchorButton.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
showedAt = System.currentTimeMillis();
}
@Override
public void mouseEntered(MouseEvent e) {
showedAt = null;
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
}
public void onNewTableBrowser(final RowBrowser tableBrowser) {
newestBrowser = tableBrowser;
tableBrowser.internalFrame.addInternalFrameListener(new InternalFrameListener() {
@Override
public void internalFrameOpened(InternalFrameEvent e) {
}
@Override
public void internalFrameIconified(InternalFrameEvent e) {
reset();
}
@Override
public void internalFrameDeiconified(InternalFrameEvent e) {
reset();
}
@Override
public void internalFrameDeactivated(InternalFrameEvent e) {
}
@Override
public void internalFrameClosing(InternalFrameEvent e) {
}
@Override
public void internalFrameClosed(InternalFrameEvent e) {
reset();
newestBrowser = null;
}
@Override
public void internalFrameActivated(InternalFrameEvent e) {
}
});
MouseListener showButton = new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
if (isApplicable(tableBrowser)) {
showButton(tableBrowser);
} else {
reset();
}
}
@Override
public void mouseClicked(MouseEvent e) {
}
};
tableBrowser.browserContentPane.menuPanel.addMouseListener(showButton);
Stack<JPanel> panels = new Stack<JPanel>();
panels.add(tableBrowser.browserContentPane.menuPanel);
while (!panels.isEmpty()) {
JPanel panel = panels.pop();
synchronized (panel.getTreeLock()) {
for (Component comp: panel.getComponents()) {
if (comp instanceof JPanel) {
if (comp != tableBrowser.browserContentPane.sqlPanel) {
if (comp != tableBrowser.browserContentPane.relatedRowsPanel) {
panels.push((JPanel) comp);
}
}
} else if (comp instanceof JLabel) {
comp.addMouseListener(showButton);
}
}
}
}
tableBrowser.browserContentPane.addMouseListener(showButton);
tableBrowser.browserContentPane.sqlPanel.addMouseListener(showButton);
tableBrowser.browserContentPane.relatedRowsPanel.addMouseListener(showButton);
tableBrowser.browserContentPane.loadButton.addMouseListener(showButton);
tableBrowser.browserContentPane.rowsTable.addMouseListener(showButton);
if (tableBrowser.browserContentPane.thumbnail != null) {
tableBrowser.browserContentPane.thumbnail.addMouseListener(showButton);
}
if (tableBrowser.browserContentPane.andCondition.getEditor() != null) {
if (tableBrowser.browserContentPane.andCondition.getEditor().getEditorComponent() != null) {
tableBrowser.browserContentPane.andCondition.getEditor().getEditorComponent().addMouseListener(showButton);
}
}
Object bi = tableBrowser.internalFrame.getUI();
if (bi instanceof BasicInternalFrameUI) {
JComponent northPane = ((BasicInternalFrameUI) bi).getNorthPane();
if (northPane != null) {
northPane.addMouseListener(showButton);
}
}
tableBrowser.internalFrame.addComponentListener(new ComponentListener() {
@Override
public void componentShown(ComponentEvent e) {
}
@Override
public void componentResized(ComponentEvent e) {
reset(100);
}
@Override
public void componentMoved(ComponentEvent e) {
reset(100);
}
@Override
public void componentHidden(ComponentEvent e) {
reset();
}
});
reset();
}
protected void showButton(RowBrowser tableBrowser) {
if (disabledUntil != null && disabledUntil > System.currentTimeMillis()) {
return;
}
currentBrowser = tableBrowser;
anchorButton.setSize(anchorButton.getPreferredSize());
anchorPanel.setSize(anchorButton.getPreferredSize());
Point loc;
loc = tableBrowser.internalFrame.getLocation();
loc.translate(-anchorButton.getWidth(), 0);
anchorPanel.setLocation(0, 0);
loc = SwingUtilities.convertPoint(tableBrowser.internalFrame.getParent(), loc, anchorPanel);
anchorPanel.setLocation(loc);
anchorButton.setVisible(true);
anchorPanel.setVisible(true);
showedAt = System.currentTimeMillis();
}
void reset() {
reset(0);
}
void reset(int delay) {
anchorButton.setVisible(false);
anchorPanel.setVisible(false);
if (delay > 0) {
disabledUntil = System.currentTimeMillis() + delay;
}
}
public RowBrowser getNewestBrowser() {
return newestBrowser;
}
public void setNewestBrowser(RowBrowser browser) {
newestBrowser = browser;
}
public void checkRetention() {
long now = System.currentTimeMillis();
if (showedAt != null && showedAt + MAX_RETENDION < now) {
reset();
}
}
protected abstract void layout(RowBrowser anchor);
protected abstract boolean isApplicable(RowBrowser tableBrowser);
private ImageIcon anchorIcon;
{
String dir = "/net/sf/jailer/ui/resource";
// load images
try {
anchorIcon = new ImageIcon(DataBrowser.class.getResource(dir + "/anchor.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,283 @@
/*
* Copyright 2007 - 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.jailer.ui.databrowser;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import net.sf.jailer.ui.UIUtil;
/**
* Animates layout changes of {@link Desktop}.
*
* @author Ralf Wisser
*/
public class DesktopAnimation {
private final double DURATION = 750;
private final Desktop desktop;
/**
* Animation.
*/
abstract class Animation {
private long startTime;
public void start() {
startTime = System.currentTimeMillis();
stopScrolling = false;
}
abstract boolean animate(double f);
};
/**
* Animation per subject (started).
*/
private Map<Object, Animation> animations = Collections.synchronizedMap(new LinkedHashMap<Object, Animation>());
/**
* Animation per subject (waiting).
*/
private Map<Object, Animation> waiting = new LinkedHashMap<Object, Animation>();
/**
* Constructor.
*
* @param desktop the desktop
*/
public DesktopAnimation(Desktop desktop) {
this.desktop = desktop;
}
/**
* Scrolls desktop to a given location.
*/
class ScrollTo extends Animation {
private final Point scrollFrom;
private final int initialWidth;
private final int initialHeight;
private final Rectangle scrollTo;
public ScrollTo(Rectangle scrollTo, Point scrollFrom, int initialWidth, int initialHeight) {
this.scrollFrom = scrollFrom;
this.initialWidth = initialWidth;
this.initialHeight = initialHeight;
this.scrollTo = scrollTo;
}
public boolean animate(double f) {
if (stopScrolling) {
return false;
}
if (scrollTo != null) {
int w = wAvg(f, initialWidth, scrollTo.width);
int h = wAvg(f, initialHeight, scrollTo.height);
int x = (int) (scrollFrom.x + f * (scrollTo.x + scrollTo.width / 2 - scrollFrom.x)) - w / 2;
int y = (int) (scrollFrom.y + f * (scrollTo.y + scrollTo.height / 2 - scrollFrom.y)) - h / 2;
desktop.checkDesktopSize();
desktop.scrollRectToVisible(new Rectangle(x, y, w, h));
}
return true;
}
}
/**
* Moves an internal frame of the desktop.
*/
class MoveIFrame extends Animation {
private final JInternalFrame iFrame;
private final Rectangle moveTo;
private final Rectangle moveFrom;
private final BrowserContentPane browserContentPane;
public MoveIFrame(JInternalFrame iFrame, BrowserContentPane browserContentPane, Rectangle moveTo) {
this.iFrame = iFrame;
this.browserContentPane = browserContentPane;
this.moveTo = moveTo;
this.moveFrom = iFrame.getBounds();
}
public boolean animate(double f) {
int wx = wAvg(f, moveFrom.x, moveTo.x);
int wy = wAvg(f, moveFrom.y, moveTo.y);
int ww = wAvg(f, moveFrom.width, moveTo.width);
int wh = wAvg(f, moveFrom.height, moveTo.height);
if (f < 1.0 && Math.abs(ww - iFrame.getWidth()) < 4 && Math.abs(wh - iFrame.getHeight()) < 4) {
iFrame.setLocation(wx, wy);
} else {
iFrame.setBounds(wx, wy, ww, wh);
}
if (f == 1.0) {
browserContentPane.adjustRowTableColumnsWidth();
}
return !(wx == moveTo.x && wy == moveTo.y && ww == moveTo.width && wh == moveTo.height);
}
}
/**
* Performs an animation step for each animation.
*/
public boolean animate() {
boolean result = false;
for (Iterator<Entry<Object, Animation>> i = animations.entrySet().iterator(); i.hasNext(); ) {
Animation animation = i.next().getValue();
double f = (System.currentTimeMillis() - animation.startTime) / DURATION;
double fs;
if (f > 1.0) {
f = 1.0;
fs = 1.0;
} else {
final double M1 = -3;
final double M2 = 5;
fs = sig(f * (-M1 + M2) + M1);
}
if (!animation.animate(fs)) {
i.remove();
continue;
}
result = true;
if (f == 1.0) {
i.remove();
}
}
desktop.checkDesktopSize();
return result;
}
private double sig(double x) {
return 1.0 / (1.0 + Math.exp(-x));
}
/**
* Scrolls desktop to a given location (animated).
*
* @param vr the location
*/
public void scrollRectToVisible(Rectangle vr) {
Rectangle svr = desktop.getScrollPane().getViewport().getViewRect();
if (!svr.contains(vr)) {
int mx = vr.x + vr.width / 2;
int my = vr.y + vr.height / 2;
if (mx < svr.x) {
mx = svr.x;
}
if (my < svr.y) {
my = svr.y;
}
if (mx > svr.x + svr.width) {
mx = svr.x + svr.width;
}
if (my > svr.y + svr.height) {
my = svr.y + svr.height;
}
startAnimation(desktop, new ScrollTo(vr, new Point(mx, my), 2 * Math.min(mx - svr.x, svr.x + svr.width - mx), 2 * Math.min(my - svr.y, svr.y + svr.height - my)));
} else {
waiting.remove(desktop);
animations.remove(desktop);
}
}
/**
* Scrolls desktop to a given location (immediately).
*
* @param vr the location
*/
public void scrollRectToVisibleImmediately(Rectangle vr) {
desktop.scrollRectToVisible(vr);
waiting.remove(desktop);
animations.remove(desktop);
}
/**
* Sets the bounds of an internal frame (animated).
*
* @param iFrame the frame
* @param browserContentPane the content pane
* @param r new bounds
*/
public void setIFrameBounds(JInternalFrame iFrame, BrowserContentPane browserContentPane, Rectangle r) {
startAnimation(iFrame, new MoveIFrame(iFrame, browserContentPane, r));
}
/**
* Sets the bounds of an internal frame (immediately).
*
* @param iFrame the frame
* @param browserContentPane the content pane
* @param r new bounds
*/
public void setIFrameBoundsImmediately(JInternalFrame internalFrame, BrowserContentPane browserContentPane, Rectangle newBounds) {
internalFrame.setBounds(newBounds);
browserContentPane.adjustRowTableColumnsWidth();
waiting.remove(internalFrame);
animations.remove(internalFrame);
}
public Rectangle getIFrameBounds(JInternalFrame iFrame) {
Animation animation = animations.get(iFrame);
if (animation instanceof MoveIFrame) {
return ((MoveIFrame) animation).moveTo;
}
animation = waiting.get(iFrame);
if (animation instanceof MoveIFrame) {
return ((MoveIFrame) animation).moveTo;
}
return iFrame.getBounds();
}
private int wAvg(double f, int a, int b) {
return (int) (a + f * (b - a));
}
private void startAnimation(Object key, Animation animation) {
Component desktopAncestor = SwingUtilities.getWindowAncestor(desktop);
if (desktopAncestor == null) {
desktopAncestor = desktop;
}
final Component fDesktopAncestor = desktopAncestor;
UIUtil.setWaitCursor(desktopAncestor);
waiting.put(key, animation);
UIUtil.invokeLater(12, new Runnable() {
@Override
public void run() {
UIUtil.resetWaitCursor(fDesktopAncestor);
for (Entry<Object, Animation> e: waiting.entrySet()) {
e.getValue().start();
animations.put(e.getKey(), e.getValue());
}
waiting.clear();
}
});
}
public static boolean stopScrolling = false;
public boolean isActive() {
return !animations.isEmpty();
}
}
@@ -0,0 +1,158 @@
/*
* Copyright 2007 - 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.jailer.ui.databrowser;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JInternalFrame;
import net.sf.jailer.ui.UIUtil;
/**
* Renders state changes of {@link JInternalFrame}s in {@link Desktop}.
*
* @author Ralf Wisser
*/
public class DesktopIFrameStateChangeRenderer {
private final double DURATION = 1500.0;
private List<JInternalFrame> atomicBlock = null;
private class StateChange {
JInternalFrame iFrame;
long startTime;
double factorOffset = 0;
}
private Map<JInternalFrame, StateChange> stateChanges = new LinkedHashMap<JInternalFrame, StateChange>();
public void onNewIFrame(final JInternalFrame iFrame) {
if (atomicBlock != null) {
atomicBlock.add(iFrame);
} else {
UIUtil.invokeLater(12, new Runnable() {
@Override
public void run() {
StateChange stateChange = new StateChange();
stateChange.iFrame = iFrame;
stateChange.startTime = System.currentTimeMillis();
stateChanges.put(iFrame, stateChange);
}
});
}
}
public void onIFrameSelected(JInternalFrame iFrame) {
onIFrameSelected(iFrame, 0);
}
public void onIFrameSelected(final JInternalFrame iFrame, final double factorOffset) {
if (atomicBlock == null) {
UIUtil.invokeLater(12, new Runnable() {
@Override
public void run() {
if (!stateChanges.containsKey(iFrame)) {
StateChange stateChange = new StateChange();
stateChange.iFrame = iFrame;
stateChange.startTime = System.currentTimeMillis();
stateChange.factorOffset = factorOffset;
stateChanges.put(iFrame, stateChange);
}
}
});
}
}
public void render(Graphics2D g2d) {
for (Iterator<Entry<JInternalFrame, StateChange>> iter = stateChanges.entrySet().iterator(); iter.hasNext(); ) {
StateChange stateChange = iter.next().getValue();
double factor = (System.currentTimeMillis() - stateChange.startTime) / DURATION;
factor += stateChange.factorOffset;
if (factor >= 1) {
iter.remove();
continue;
}
if (factor < 0) {
factor = 0;
}
if (stateChange.iFrame.isVisible()) {
Color color = new Color(255, 255, 0, (int) (170 * (1 - factor)));
g2d.setColor(color);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
double width = stateChange.iFrame.getWidth() / 12 * ((factor - stateChange.factorOffset) / (1 - stateChange.factorOffset) + 0.1);
BasicStroke stroke = new BasicStroke((float) width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g2d.setStroke(stroke);
Rectangle rect = stateChange.iFrame.getBounds();
int w = (int) (0.5 * width);
rect = new Rectangle(rect.x + w / 2, rect.y + w / 2, rect.width - w, rect.height - w);
Path2D.Double path = new Path2D.Double();
path.moveTo(rect.getX(), rect.getY());
path.lineTo(rect.getX() + rect.getWidth(), rect.getY());
path.lineTo(rect.getX() + rect.getWidth(), rect.getY() + rect.getHeight());
path.lineTo(rect.getX(), rect.getY() + rect.getHeight());
path.lineTo(rect.getX(), rect.getY());
g2d.draw(path);
}
}
}
public void startAtomic() {
atomicBlock = new ArrayList<JInternalFrame>();
}
public void endAtomic() {
if (atomicBlock != null) {
final List<JInternalFrame> iFrames = atomicBlock;
atomicBlock = null;
UIUtil.invokeLater(12, new Runnable() {
@Override
public void run() {
long currentTimeMillis = System.currentTimeMillis();
long offset = 0;
for (int i = iFrames.size() - 1; i >= 0; --i) {
JInternalFrame iFrame = iFrames.get(i);
StateChange stateChange = new StateChange();
stateChange.iFrame = iFrame;
stateChange.startTime = currentTimeMillis - offset;
stateChanges.put(iFrame, stateChange);
offset += DURATION / 3;
}
}
});
}
}
public void rollbackAtomic() {
atomicBlock = null;
}
}
@@ -17,6 +17,7 @@ package net.sf.jailer.ui.databrowser;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
@@ -40,6 +41,7 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.TableModel;
import net.sf.jailer.database.Session;
import net.sf.jailer.datamodel.Column;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.RowIdSupport;
@@ -61,18 +63,24 @@ public abstract class DetailsView extends javax.swing.JPanel {
private final RowSorter<? extends TableModel> rowSorter;
private final RowIdSupport rowIdSupport;
private final boolean showSpinner;
private final Session session;
/** Creates new form DetailsView
* @param rowSorter
* @param showSelectButton
* @param deselect
*/
public DetailsView(List<Row> rows, int size, DataModel dataModel, Table table, int rowIndex, RowSorter<? extends TableModel> rowSorter, boolean showSpinner, boolean showSelectButton, RowIdSupport rowIdSupport) {
public DetailsView(List<Row> rows, int size, DataModel dataModel, Table table, int rowIndex, RowSorter<? extends TableModel> rowSorter, boolean showSpinner, boolean showSelectButton, RowIdSupport rowIdSupport, boolean deselect, Session session) {
this.table = table;
this.rows = rows;
this.rowSorter = rowSorter;
this.rowIdSupport = rowIdSupport;
this.showSpinner = showSpinner;
this.session = session;
initComponents();
if (deselect) {
selectButton.setText("Deselect Row");
}
if (rowSorter != null) {
rowIndex = rowSorter.convertRowIndexToView(rowIndex);
}
@@ -125,8 +133,7 @@ public abstract class DetailsView extends javax.swing.JPanel {
@Override
public void ancestorAdded(AncestorEvent event) {
closeButton.grabFocus();
jScrollPane1.getVerticalScrollBar().setValue(jScrollPane1.getVerticalScrollBar().getMinimum());
jScrollPane1.getHorizontalScrollBar().setValue(jScrollPane1.getHorizontalScrollBar().getMinimum());
resetScrollPane();
}
});
}
@@ -137,8 +144,12 @@ public abstract class DetailsView extends javax.swing.JPanel {
private final Font nonbold = new Font(font.getName(), font.getStyle() & ~Font.BOLD, font.getSize());
private final Font italic = new Font(font.getName(), font.getStyle() & ~Font.BOLD | Font.ITALIC, font.getSize());
private final Color BG1 = new Color(255, 255, 255);
private final Color BG2 = new Color(230, 255, 255);
private final Color BG2 = new Color(242, 255, 242);
private final Color BG3 = new Color(194, 228, 255);
private final Color BG3_2 = new Color(184, 220, 255);
private final Color FG1 = new Color(155, 0, 0);
private List<JLabel> labels = new ArrayList<JLabel>();
private List<Color> labelColors = new ArrayList<Color>();
public void setBorderColor(Color color) {
jScrollPane1.setBorder(BorderFactory.createEtchedBorder(color, Color.GRAY));
@@ -147,13 +158,17 @@ public abstract class DetailsView extends javax.swing.JPanel {
private int currentRow;
private boolean sortColumns;
private JPanel content;
private boolean isPacked = false;
private void setCurrentRow(int row, boolean selectableFields) {
currentRow = row;
java.awt.GridBagConstraints gridBagConstraints;
JPanel oldContent = content;
labels.clear();
labelColors.clear();
final JPanel oldContent = content;
content = new JPanel(new GridBagLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.weightx = 1;
@@ -163,7 +178,7 @@ public abstract class DetailsView extends javax.swing.JPanel {
gridBagConstraints.gridy = 0;
int i = 0;
final List<Column> columns = rowIdSupport.getColumns(table);
final List<Column> columns = rowIdSupport.getColumns(table, session);
List<Integer> columnIndex = new ArrayList<Integer>();
for (int j = 0; j < columns.size(); ++j) {
columnIndex.add(j);
@@ -240,6 +255,8 @@ public abstract class DetailsView extends javax.swing.JPanel {
} else {
l.setForeground(Color.BLUE);
}
labelColors.add(f.getBackground());
labels.add(f);
}
++i;
}
@@ -255,12 +272,30 @@ public abstract class DetailsView extends javax.swing.JPanel {
gridBagConstraints.gridy = i;
content.add(l, gridBagConstraints);
}
jPanel1.add(content, gridBagConstraints);
if (oldContent != null) {
jPanel1.remove(oldContent);
Runnable update = new Runnable() {
@Override
public void run() {
if (oldContent != null) {
jPanel1.remove(oldContent);
}
GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.weightx = 1;
gridBagConstraints.weighty = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
jPanel1.add(content, gridBagConstraints);
jPanel1.revalidate();
jPanel1.repaint();
}
};
if (isPacked) {
UIUtil.invokeLater(2, update);
} else {
update.run();
isPacked = true;
}
jPanel1.revalidate();
jPanel1.repaint();
onRowChanged(row);
}
@@ -354,6 +389,12 @@ public abstract class DetailsView extends javax.swing.JPanel {
private void sortCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortCheckBoxActionPerformed
sortColumns = !sortColumns;
setCurrentRow(currentRow, showSpinner);
UIUtil.invokeLater(4, new Runnable() {
@Override
public void run() {
resetScrollPane();
}
});
}//GEN-LAST:event_sortCheckBoxActionPerformed
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
@@ -364,6 +405,22 @@ public abstract class DetailsView extends javax.swing.JPanel {
onSelectRow(rows.get(rowSorter != null? rowSorter.convertRowIndexToModel(currentRow) : currentRow));
}//GEN-LAST:event_selectButtonActionPerformed
public void updateInClosureState(boolean inClosure) {
if (inClosure) {
int r = 0;
for (JLabel label: labels) {
label.setBackground(r++ % 2 == 0? BG3 : BG3_2);
}
} else {
for (int i = 0; i < labels.size(); ++i) {
labels.get(i).setBackground(labelColors.get(i));
}
}
}
public JPanel getDetailsPanel() {
return jPanel1;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton closeButton;
@@ -380,4 +437,9 @@ public abstract class DetailsView extends javax.swing.JPanel {
setCurrentRow(currentRow, showSpinner);
}
private void resetScrollPane() {
jScrollPane1.getVerticalScrollBar().setValue(jScrollPane1.getVerticalScrollBar().getMinimum());
jScrollPane1.getHorizontalScrollBar().setValue(jScrollPane1.getHorizontalScrollBar().getMinimum());
}
}
@@ -32,13 +32,26 @@ public class Row {
this.rowId = rowId;
this.values = v;
this.primaryKey = primaryKey;
if (rowId.isEmpty()) {
synchronized (this) {
this.nonEmptyRowId = Long.toString(nextUniqueId++);
}
} else {
nonEmptyRowId = rowId;
}
}
/**
* Unique ID, also serves as SQL predicate which identifies this row.
* Empty string if row has no key.
*/
public final String rowId;
/**
* Unique ID. Equals rowId if it's not empty.
*/
public final String nonEmptyRowId;
/**
* Column values.
*/
@@ -68,4 +81,6 @@ public class Row {
this.parentModelIndex = parentModelIndex;
}
private static long nextUniqueId = 0;
}
@@ -204,7 +204,6 @@ public class SbEDialog extends javax.swing.JDialog {
}//GEN-LAST:event_jButton3ActionPerformed
private void regardButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_regardButtonActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_regardButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
@@ -15,7 +15,6 @@
*/
package net.sf.jailer.ui.databrowser;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.Window;
import java.io.File;
@@ -36,6 +35,7 @@ import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
import net.sf.jailer.ui.DbConnectionDialog;
import net.sf.jailer.ui.Environment;
import net.sf.jailer.ui.JComboBox;
import net.sf.jailer.ui.UIUtil;
/**
* Schema Mapping Dialog.
@@ -58,7 +58,7 @@ public class SchemaMappingDialog extends javax.swing.JDialog {
Window windowAncestor = parent; // SwingUtilities.getWindowAncestor(parent);
try {
if (windowAncestor != null) {
windowAncestor.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(windowAncestor);
}
String defSchema = JDBCMetaDataBasedModelElementFinder.getDefaultSchema(session, session.getSchema());
if (!defSchema.isEmpty()) {
@@ -108,7 +108,7 @@ public class SchemaMappingDialog extends javax.swing.JDialog {
}
} finally {
if (windowAncestor != null) {
windowAncestor.setCursor(Cursor.getDefaultCursor());
UIUtil.resetWaitCursor(windowAncestor);
}
}
pack();
@@ -29,6 +29,7 @@ public class TreeLayoutOptimizer<T> {
public static class Node<T> {
private final T userObject;
private final List<Node<T>> children = new ArrayList<Node<T>>();
private final boolean isAnchor;
int level = 0;
Node<T> parent = null;
double position = 0;
@@ -37,8 +38,9 @@ public class TreeLayoutOptimizer<T> {
return userObject;
}
public Node(T userObject) {
public Node(T userObject, boolean isAnchor) {
this.userObject = userObject;
this.isAnchor = isAnchor;
}
public void addChild(Node<T> child) {
@@ -67,6 +69,21 @@ public class TreeLayoutOptimizer<T> {
return 1 + maxChildDepth;
}
public double getMinPosition() {
double minPos = position;
for (Node<T> child: children) {
minPos = Math.min(minPos, child.getMinPosition());
}
return minPos;
}
public void adjustPosition(double delta) {
position -= delta;
for (Node<T> child: children) {
child.adjustPosition(delta);
}
}
public int getNodesCount() {
int count = 1;
for (Node<T> child: children) {
@@ -77,15 +94,36 @@ public class TreeLayoutOptimizer<T> {
public double getCompactness() {
double compactness = 0;
if (children.size() > 1) {
if (children.size() > 0) {
compactness = children.get(children.size() - 1).position - children.get(0).position;
compactness *= compactness;
Node<T> pre = null;
for (Node<T> child: children) {
compactness += child.getCompactness();
if (pre != null) {
if (pre.position + 1 > child.position) {
double w = pre.position + 1 - child.position;
compactness += w * w * 1000;
}
}
pre = child;
}
}
return compactness;
}
public double getAnchorQuality() {
double quality = 0;
for (Node<T> child: children) {
quality += child.getAnchorQuality();
}
if (isAnchor && parent != null) {
double d = parent.position - position;
quality += d * d;
}
return quality;
}
};
public static <T> void optimizeTreeLayout(Node<T> root) {
@@ -93,6 +131,7 @@ public class TreeLayoutOptimizer<T> {
optimizeChildrenOrder(root, System.currentTimeMillis(), MAX_OPTIM_TIME_MS, numNodes);
layoutTree(root, numNodes);
optimizeLeafs(root);
root.adjustPosition(root.getMinPosition());
}
private static long MAX_OPTIM_TIME_MS = 1000;
@@ -111,7 +150,7 @@ public class TreeLayoutOptimizer<T> {
sumMaxPositionSqr += maxPositionPerLevel[i] * maxPositionPerLevel[i];
}
}
return sumMaxPositionSqr / numNodes + root.getCompactness();
return sumMaxPositionSqr / numNodes + root.getCompactness() + root.getAnchorQuality();
}
private static <T> void layoutNode(Node<T> node, double[] maxPositionPerLevel) {
@@ -125,18 +164,31 @@ public class TreeLayoutOptimizer<T> {
private static <T> void adjustParentPosition(Node<T> node, double[] maxPositionPerLevel) {
while (node != null) {
double parentPos = node.children.get(0).position + (maxPositionPerLevel[node.level + 1] - node.children.get(0).position) / 2.0;
if (node.position < parentPos) {
node.position = parentPos;
// node.position = (node.position + parentPos) / 2.0;
maxPositionPerLevel[node.level] = parentPos;
Node<T> anchorChild = null;
if (node.isAnchor) {
for (Node<T> child: node.children) {
if (child.isAnchor) {
anchorChild = child;
break;
}
}
}
if (anchorChild != null) {
node.position = anchorChild.position;
} else {
break;
double parentPos = node.children.get(0).position + (maxPositionPerLevel[node.level + 1] - node.children.get(0).position) / 2.0;
if (node.position < parentPos) {
node.position = parentPos;
// node.position = (node.position + parentPos) / 2.0;
maxPositionPerLevel[node.level] = parentPos;
} else {
break;
}
}
node = node.parent;
}
}
private static <T> void optimizeLeafs(Node<T> node) {
if (node.children.isEmpty() && node.parent != null && node.position < node.parent.position) {
int i = node.parent.children.indexOf(node);
@@ -36,6 +36,7 @@ import javax.swing.ImageIcon;
import org.apache.log4j.Logger;
import net.sf.jailer.database.Session.AbstractResultSetReader;
import net.sf.jailer.modelbuilder.MemorizedResultSet;
import net.sf.jailer.ui.UIUtil;
import net.sf.jailer.util.Quoting;
@@ -148,6 +149,7 @@ public class MDSchema extends MDObject {
if (tables == null) {
try {
tables = new ArrayList<MDTable>();
Map<String, Long> estimatedRowCounts = readEstimatedRowCounts();
MetaDataSource metaDataSource = getMetaDataSource();
synchronized (metaDataSource.getSession().getMetaData()) {
ResultSet rs = metaDataSource.readTables(getName());
@@ -156,7 +158,8 @@ public class MDSchema extends MDObject {
String tableName = metaDataSource.getQuoting().quote(rs.getString(3));
final MDTable table = new MDTable(tableName, this, "VIEW".equalsIgnoreCase(rs.getString(4)),
"SYNONYM".equalsIgnoreCase(rs.getString(4))
|| "ALIAS".equalsIgnoreCase(rs.getString(4)));
|| "ALIAS".equalsIgnoreCase(rs.getString(4)),
estimatedRowCounts.get(rs.getString(3)));
tables.add(table);
if (loadTableColumns) {
loadJobs.put(tableName, new Runnable() {
@@ -194,6 +197,30 @@ public class MDSchema extends MDObject {
}
}
private Map<String, Long> readEstimatedRowCounts() {
final Map<String, Long> result = new HashMap<String, Long>();
String query = getMetaDataSource().getSession().dbms.getEstimatedRowCountQuery();
if (query != null) {
try {
getMetaDataSource().getSession().executeQuery(String.format(query, getUnquotedName()), new AbstractResultSetReader() {
@Override
public void readCurrentRow(ResultSet resultSet) throws SQLException {
String tableName = resultSet.getString(1);
long rowCount = resultSet.getLong(2);
if (!resultSet.wasNull() && rowCount >= 0) {
result.put(tableName, rowCount);
}
}
});
} catch (SQLException e) {
// ignore
}
}
return result;
}
/**
* Have the tables of the schema been loaded?
*/
@@ -15,7 +15,6 @@
*/
package net.sf.jailer.ui.databrowser.metadata;
import java.awt.Cursor;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
@@ -42,6 +41,7 @@ import net.sf.jailer.database.Session;
import net.sf.jailer.datamodel.Column;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
import net.sf.jailer.ui.UIUtil;
import net.sf.jailer.util.Quoting;
import net.sf.jailer.util.SqlUtil;
@@ -67,6 +67,8 @@ public class MDTable extends MDObject {
private final boolean isView;
private final boolean isSynonym;
public final Long estimatedRowCount;
// DDL of the table or <code>null</code>, if no DDL is available
private String ddl;
@@ -76,11 +78,12 @@ public class MDTable extends MDObject {
* @param name table name
* @param schema the tables schema
*/
public MDTable(String name, MDSchema schema, boolean isView, boolean isSynonym) {
public MDTable(String name, MDSchema schema, boolean isView, boolean isSynonym, Long estimatedRowCount) {
super(name, schema.getMetaDataSource());
this.isView = isView;
this.isSynonym = isSynonym;
this.schema = schema;
this.estimatedRowCount = estimatedRowCount;
}
/**
@@ -111,7 +114,7 @@ public class MDTable extends MDObject {
if (isLoaded()) {
return getColumns();
}
waitCursorSubject.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(waitCursorSubject);
try {
loading.set(true);
queue.add(new Runnable() {
@@ -132,7 +135,7 @@ public class MDTable extends MDObject {
}
}
} finally {
waitCursorSubject.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(waitCursorSubject);
}
if (loading.get()) {
return new ArrayList<String>();
@@ -159,7 +162,7 @@ public class MDTable extends MDObject {
MetaDataSource metaDataSource = getMetaDataSource();
synchronized (metaDataSource.getSession().getMetaData()) {
ResultSet resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(getSchema().getMetaDataSource().getSession(), getSchema().getMetaDataSource().getSession().getMetaData(), Quoting.staticUnquote(getSchema().getName()), Quoting.staticUnquote(getName()), "%",
true);
true, isSynonym? "SYNONYM" : null);
while (resultSet.next()) {
String colName = metaDataSource.getQuoting().quote(resultSet.getString(4));
columns.add(colName);
@@ -208,7 +211,23 @@ public class MDTable extends MDObject {
}
pk.put(keySeq, metaDataSource.getQuoting().quote(resultSet.getString(4)));
}
primaryKey.addAll(pk.values());
if (pk.isEmpty()) {
Table table = metaDataSource.toTable(this);
if (table != null) {
if (table.primaryKey != null) {
for (Column c: table.primaryKey.getColumns()) {
for (String mc: columns) {
if (Quoting.equalsIgnoreQuotingAndCase(c.name, mc)) {
primaryKey.add(mc);
break;
}
}
}
}
}
} else {
primaryKey.addAll(pk.values());
}
resultSet.close();
}
} finally {
@@ -327,6 +346,22 @@ public class MDTable extends MDObject {
}
}
}
if (ddl == null && isView) {
String viewTextOrDDLQuery = session.dbms.getViewTextOrDDLQuery();
if (viewTextOrDDLQuery != null) {
String viewTextQuery = String.format(viewTextOrDDLQuery, Quoting.staticUnquote(getSchema().getName()), Quoting.staticUnquote(getName()));
try {
session.executeQuery(viewTextQuery, new Session.AbstractResultSetReader() {
@Override
public void readCurrentRow(ResultSet resultSet) throws SQLException {
ddl = resultSet.getString(1);
}
});
} catch (Exception e) {
// ignore
}
}
}
if (ddl == null) {
try {
ddl = createDDL();
@@ -39,7 +39,7 @@ public enum MetaDataDetails {
COLUMNS("Columns", 0) {
@Override
public ResultSet readMetaDataDetails(Session session, MDTable mdTable) throws SQLException {
return JDBCMetaDataBasedModelElementFinder.getColumns(session, session.getMetaData(), Quoting.staticUnquote(mdTable.getSchema().getName()), Quoting.staticUnquote(mdTable.getName()), "%", true);
return JDBCMetaDataBasedModelElementFinder.getColumns(session, session.getMetaData(), Quoting.staticUnquote(mdTable.getSchema().getName()), Quoting.staticUnquote(mdTable.getName()), "%", true, mdTable.isSynonym()? "SYNONYM" : null);
}
@Override
public void adjustRowsTable(JTable rowsTable) {
@@ -226,11 +226,16 @@ public abstract class MetaDataDetailsPanel extends javax.swing.JPanel {
final int tableNameColumnIndex = 3;
final Set<String> pkNames = Collections.synchronizedSet(new HashSet<String>());
final BrowserContentPane rb = new BrowserContentPane(datamodel.get(), null, "", session, null, null,
null, null, new BrowserContentPane.RowsClosure(), 0, false, false, executionContext) {
null, null, new BrowserContentPane.RowsClosure(), false, false, executionContext) {
{
noSingleRowDetailsView = true;
rowsTableScrollPane.setWheelScrollingEnabled(true);
}
@Override
protected int getReloadLimit() {
return Integer.MAX_VALUE;
}
@Override
protected void unhide() {
}
@@ -257,7 +262,8 @@ public abstract class MetaDataDetailsPanel extends javax.swing.JPanel {
protected void onContentChange(List<Row> rows, boolean reloadChildren) {
}
@Override
protected void navigateTo(Association association, int rowIndex, Row row) {
protected RowBrowser navigateTo(Association association, int rowIndex, Row row) {
return null;
}
@Override
protected List<RowBrowser> getTableBrowser() {
@@ -338,6 +344,9 @@ public abstract class MetaDataDetailsPanel extends javax.swing.JPanel {
protected SQLConsole getSqlConsole(boolean switchToConsole) {
return null;
}
@Override
protected void deselectChildrenIfNeededWithoutReload() {
}
};
final MemorizedResultSet[] metaDataDetails = new MemorizedResultSet[1];
@@ -357,7 +366,7 @@ public abstract class MetaDataDetailsPanel extends javax.swing.JPanel {
rs.close();
}
} catch (SQLException e) {
logger.info("error", e);
// ignore
}
SwingUtilities.invokeLater(new Runnable() {
@Override
@@ -17,7 +17,6 @@ package net.sf.jailer.ui.databrowser.metadata;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
@@ -699,7 +698,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
popup.add(menu);
++itemCount;
menu.add(createScriptMenuItem("Delete Script", "Delete from %1$s;", "", mdTables, false));
menu.add(createScriptMenuItem("Drop Table Script", "Drop Table %1$s;", "", mdTables, false));
menu.add(createScriptMenuItem("Drop Table Script", "Drop %2$s %1$s;", "", mdTables, false));
menu.addSeparator();
menu.add(createScriptMenuItem("Count Rows Script", "Select '%1$s' as Tab, count(*) as NumberOfRows From %1$s", " union all", mdTables, true));
}
@@ -709,7 +708,9 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
if (evt.getButton() == MouseEvent.BUTTON1) {
if (mdTable != null) {
if (evt.getClickCount() > 1) {
openTable(mdTable);
if (node != null && metaDataTree.getSelectionModel().isPathSelected(node)) {
openTable(mdTable);
}
}
}
}
@@ -725,12 +726,19 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
script.append(separator + "\n");
}
String tableName;
String tableType = "Table";
if (mdTable.isView()) {
tableType = "View";
}
if (mdTable.isSynonym()) {
tableType = "Synonym";
}
if (mdTable.getSchema().isDefaultSchema) {
tableName = mdTable.getName();
} else {
tableName = mdTable.getSchema() + "." + mdTable.getName();
}
script.append(String.format(template, tableName));
script.append(String.format(template, tableName, tableType));
}
script.append("\n");
appendScript(script.toString(), execute);
@@ -815,6 +823,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
boolean isSynonym = false;
Boolean isDirty = false;
Icon image = null;
Long estRowCount = null;
if (value instanceof DefaultMutableTreeNode) {
Object uo = ((DefaultMutableTreeNode) value).getUserObject();
if (uo instanceof JLabel) {
@@ -851,11 +860,11 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
}
}
}
if (ModelBuilder.isJailerTable(((MDTable) uo).getUnquotedName())) {
isJailerTable = true;
}
isView = ((MDTable) uo).isView();
isSynonym = ((MDTable) uo).isSynonym();
if (!isView) {
estRowCount = ((MDTable) uo).estimatedRowCount;
}
if (isView) {
image = viewIcon;
} else if (isSynonym) {
@@ -863,6 +872,9 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
} else {
image = tableIcon;
}
if (ModelBuilder.isJailerTable(((MDTable) uo).getUnquotedName())) {
isJailerTable = true;
}
}
}
Component comp = super.getTreeCellRendererComponent(tree, value + (unknownTable? "" : (isDirty? " !" : " ")), sel, expanded, leaf, row, hasFocus);
@@ -874,13 +886,29 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
// TODO tooltips dont work with tree nodes
tooltip = text;
}
if (estRowCount != null) {
Color fg = ((JLabel) comp).getForeground();
String estRowCountFormatted;
if (estRowCount >= 1000000) {
estRowCountFormatted = String.format("%1.1f M", (double) estRowCount / 1000000.0);
} else if (estRowCount >= 1000) {
estRowCountFormatted = String.format("%1.1f K", (double) estRowCount / 1000.0);
} else {
estRowCountFormatted = estRowCount.toString();
}
if (fg.getRed() + fg.getGreen() + fg.getBlue() < 255 * 3 / 2) {
((JLabel) comp).setText("<html>" + text + "&nbsp;<font color=\"#7777ff\">(~</font><font color=\"#3333ff\">" + estRowCountFormatted + "</font><font color=\"#7777ff\">)</font>");
} else {
((JLabel) comp).setText("<html>" + text + "&nbsp;<font color=\"#aaaaff\">(~</font><font color=\"#eeeeff\">" + estRowCountFormatted + "</font><font color=\"#aaaaff\">)</font>");
}
}
}
Font font = comp.getFont();
if (font != null) {
Font bold = new Font(font.getName(), unknownTable || isDirty? (font.getStyle() | Font.ITALIC) : (font.getStyle() & ~Font.ITALIC), font.getSize());
comp.setFont(bold);
}
if (isJailerTable) {
if (isJailerTable && !sel) {
comp.setEnabled(false);
}
if (image != null) {
@@ -941,7 +969,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(MetaDataPanel.this);
try {
if (metaDataTree.getSelectionPath() != null && metaDataTree.getSelectionPath().getLastPathComponent() == last) {
if (uo instanceof MDSchema) {
@@ -961,7 +989,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
}
}
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(MetaDataPanel.this);
}
}
});
@@ -1040,7 +1068,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
}
public void reset() {
refreshButton.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(refreshButton);
JDBCMetaDataBasedModelElementFinder.resetCaches(metaDataSource.getSession());
setOutline(new ArrayList<OutlineInfo>(), -1);
proceduresPerSchema.clear();
@@ -1071,7 +1099,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
}
}
} finally {
refreshButton.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(refreshButton);
}
}
});
@@ -1100,7 +1128,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
if (bounds != null) {
int b = 18;
bounds = new Rectangle(bounds.x, Math.max(bounds.y - b, 0), bounds.width, bounds.height + 2 * b);
metaDataTree.scrollRectToVisible(new Rectangle(bounds.x, bounds.y, 1, bounds.height));
metaDataTree.scrollRectToVisible(new Rectangle(0, bounds.y, 1, bounds.height));
}
}
@@ -1200,12 +1228,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
}
DefaultTreeModel treeModel = new DefaultTreeModel(root);
metaDataTree.setModel(treeModel);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
metaDataTree.scrollRectToVisible(new Rectangle(0, 0, 1, 1));
}
});
metaDataTree.scrollRectToVisible(new Rectangle(0, 0, 1, 1));
selectSchema(metaDataSource.getDefaultSchema());
}
@@ -1262,10 +1285,10 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
@Override
public void run() {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(MetaDataPanel.this);
expandImmediatelly();
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(MetaDataPanel.this);
}
}
});
@@ -1290,11 +1313,16 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
if (mdSchema != null) {
DefaultMutableTreeNode node = treeNodePerSchema.get(mdSchema);
if (node != null) {
TreePath path = new TreePath(node.getPath());
final TreePath path = new TreePath(node.getPath());
metaDataTree.expandPath(path);
metaDataTree.getSelectionModel().setSelectionPath(path);
if (scrollToNode) {
scrollToNode(path);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
scrollToNode(path);
}
});
}
}
}
@@ -34,6 +34,7 @@ import net.sf.jailer.database.Session;
import net.sf.jailer.datamodel.Association;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.modelbuilder.MemorizedResultSet;
import net.sf.jailer.ui.DbConnectionDialog;
import net.sf.jailer.ui.QueryBuilderDialog;
import net.sf.jailer.ui.QueryBuilderDialog.Relationship;
@@ -59,13 +60,23 @@ public class ResultSetRenderer extends javax.swing.JPanel {
*/
public ResultSetRenderer(ResultSet resultSet, String titel, DataModel datamodel, Session session, ExecutionContext executionContext) throws SQLException {
initComponents();
titelLabel.setText(titel);
if (titel != null && titel.length() > 40) {
titelLabel.setText(titel.substring(0, 40) + "...");
titelLabel.setToolTipText(titel);
} else {
titelLabel.setText(titel);
titelLabel.setToolTipText(null);
}
final BrowserContentPane rb = new ResultContentPane(datamodel, null, "", session, null, null,
null, null, new RowsClosure(), Integer.MAX_VALUE, false, false,
resultSet.getMetaData().getColumnCount() > 1? 180 : 400,
executionContext);
rb.setTableFilterEnabled(false);
if (resultSet instanceof MemorizedResultSet && ((MemorizedResultSet) resultSet).getSize() > 1) {
rb.setTableFilterEnabled(true);
} else {
rb.setTableFilterEnabled(false);
}
LoadJob loadJob = rb.newLoadJob(resultSet, Integer.MAX_VALUE);
loadJob.run();
JComponent rTabContainer = rb.getRowsTableContainer();
@@ -122,16 +133,25 @@ public class ResultSetRenderer extends javax.swing.JPanel {
private javax.swing.JLabel titelLabel;
// End of variables declaration//GEN-END:variables
class ResultContentPane extends BrowserContentPane {
public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, Row parentRow,
private final Integer limit;
public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, Row parentRow,
List<Row> parentRows, Association association, Frame parentFrame,
RowsClosure rowsClosure, Integer limit, Boolean selectDistinct,
boolean reload, int maxColumnWidth, ExecutionContext executionContext) {
super(dataModel, table, condition, session, parentRow, parentRows, association, parentFrame,
rowsClosure, limit, selectDistinct, reload, executionContext);
rowsClosure, selectDistinct, reload, executionContext);
singleRowDetailsViewTitel = "Details";
this.maxColumnWidth = maxColumnWidth;
this.limit = limit;
rowsTableScrollPane.setWheelScrollingEnabled(true);
rowsCount.setVisible(false);
}
@Override
protected int getReloadLimit() {
if (limit == null) {
return Integer.MAX_VALUE;
}
return limit;
}
@Override
protected void unhide() {
@@ -159,7 +179,8 @@ public class ResultSetRenderer extends javax.swing.JPanel {
protected void onContentChange(List<Row> rows, boolean reloadChildren) {
}
@Override
protected void navigateTo(Association association, int rowIndex, Row row) {
protected RowBrowser navigateTo(Association association, int rowIndex, Row row) {
return null;
}
@Override
protected List<RowBrowser> getTableBrowser() {
@@ -240,6 +261,9 @@ public class ResultSetRenderer extends javax.swing.JPanel {
protected SQLConsole getSqlConsole(boolean switchToConsole) {
return null;
}
@Override
protected void deselectChildrenIfNeededWithoutReload() {
}
};
}
@@ -47,11 +47,13 @@ import net.sf.jsqlparser.expression.TimeKeyExpression;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.UserVariable;
import net.sf.jsqlparser.expression.ValueListExpression;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.WithinGroupExpression;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
@@ -305,11 +307,6 @@ class AbstractExpressionVisitor implements ExpressionVisitor {
}
@Override
public void visit(WithinGroupExpression arg0) {
}
@Override
public void visit(ExtractExpression arg0) {
@@ -389,4 +386,19 @@ class AbstractExpressionVisitor implements ExpressionVisitor {
public void visit(NotExpression arg0) {
}
@Override
public void visit(BitwiseRightShift arg0) {
}
@Override
public void visit(BitwiseLeftShift arg0) {
}
@Override
public void visit(ValueListExpression arg0) {
}
}
@@ -18,6 +18,7 @@ package net.sf.jailer.ui.databrowser.sqlconsole;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -38,14 +39,18 @@ import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import net.sf.jailer.ui.UIUtil;
import net.sf.jailer.ui.databrowser.BrowserContentPane;
import net.sf.jailer.ui.databrowser.Row;
/**
* "Column view" of a query result table.
@@ -56,10 +61,13 @@ public class ColumnsTable extends JTable {
private final int MAX_ROWS = 198;
private static final KeyStroke KS_COPY_TO_CLIPBOARD = KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK);
final BrowserContentPane rb;
public ColumnsTable(final BrowserContentPane rb) {
this.rb = rb;
final JTable rowsTable = rb.rowsTable;
public ColumnsTable(final JTable rowsTable) {
TableModel rDm = rowsTable.getModel();
RowSorter<? extends TableModel> sorter = rowsTable.getRowSorter();
final RowSorter<? extends TableModel> sorter = rowsTable.getRowSorter();
Vector cNames = new Vector();
cNames.add("Column");
for (int i = 0; i < sorter.getViewRowCount(); ++i) {
@@ -69,31 +77,57 @@ public class ColumnsTable extends JTable {
}
cNames.add("Row " + (i + 1));
}
DefaultTableModel cDm = new DefaultTableModel(cNames, rDm.getColumnCount()) {
final TableColumnModel cm = rowsTable.getColumnModel();
TableModel cDm = new DefaultTableModel(cNames, rowsTable.getModel().getColumnCount()) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return false;
}
int row = rowsTable.getRowSorter().convertRowIndexToModel(columnIndex - 1);
int column = cm.getColumn(rowIndex).getModelIndex();
return rowsTable.getModel().isCellEditable(row, column);
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
int column = cm.getColumn(rowIndex).getModelIndex();
if (columnIndex == 0) {
return rowsTable.getModel().getColumnName(column);
}
int row = rowsTable.getRowSorter().convertRowIndexToModel(columnIndex - 1);
return rowsTable.getModel().getValueAt(row, column);
}
@Override
public void setValueAt(Object value, int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return;
}
int row = rowsTable.getRowSorter().convertRowIndexToModel(columnIndex - 1);
int column = cm.getColumn(rowIndex).getModelIndex();
rowsTable.getModel().setValueAt(value, row, column);
}
};
TableColumnModel cm = rowsTable.getColumnModel();
for (int x = 0; x < rDm.getColumnCount(); ++x) {
int mx = cm.getColumn(x).getModelIndex();
cDm.setValueAt(rDm.getColumnName(mx), x, 0);
for (int y = 0; y < sorter.getViewRowCount(); ++y) {
cDm.setValueAt(rDm.getValueAt(sorter.convertRowIndexToModel(y), mx), x, y + 1);
if (y > MAX_ROWS) {
break;
}
}
}
setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
setRowSelectionAllowed(true);
setColumnSelectionAllowed(true);
setCellSelectionEnabled(true);
// getTableHeader().setReorderingAllowed(false);
setShowGrid(false);
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
setModel(cDm);
for (int i = 0; i < getColumnCount(); i++) {
TableCellEditor defaultEditor = rowsTable.getDefaultEditor(getColumnClass(i));
if (defaultEditor != null) {
defaultEditor.cancelCellEditing();
}
setDefaultEditor(getColumnClass(i), defaultEditor);
}
InputMap im = getInputMap();
Object key = "copyClipboard";
im.put(KS_COPY_TO_CLIPBOARD, key);
@@ -115,14 +149,23 @@ public class ColumnsTable extends JTable {
public void mousePressed(MouseEvent e) {
int ri = rowAtPoint(e.getPoint());
if (ri >= 0) {
Rectangle r = getCellRect(ri, 0, false);
int x = Math.max(e.getPoint().x, (int) r.getMinX());
int y = (int) r.getMaxY() - 2;
if (e.getButton() != MouseEvent.BUTTON1) {
JPopupMenu popup;
popup = createPopupMenu();
if (popup != null) {
popup.show(ColumnsTable.this, x, y);
Rectangle r = getCellRect(ri, 0, false);
int x = Math.max(e.getPoint().x, (int) r.getMinX());
int y = (int) r.getMaxY() - 2;
if (e.getButton() != MouseEvent.BUTTON1) {
JPopupMenu popup;
popup = createPopupMenu(e);
if (popup != null) {
popup.show(ColumnsTable.this, x, y);
}
} else if (e.getClickCount() > 1) {
int i = -1;
ri = columnAtPoint(e.getPoint()) - 1;
if (ri >= 0 && !rb.rows.isEmpty() && rb.rowsTable.getRowSorter().getViewRowCount() > 0) {
i = rb.rowsTable.getRowSorter().convertRowIndexToModel(ri);
Point p = new Point(e.getX(), e.getY());
SwingUtilities.convertPointToScreen(p, ColumnsTable.this);
rb.openDetailsView(i, (int) p.getX(), (int) p.getY());
}
}
}
@@ -158,8 +201,6 @@ public class ColumnsTable extends JTable {
if (column == 0) {
((JLabel) render).setFont(italic);
((JLabel) render).setBackground(BGCOLUMNS);
// } else if (isSelected) {
// ((JLabel) render).setBackground(BGSELECTED);
}
}
return render;
@@ -170,10 +211,20 @@ public class ColumnsTable extends JTable {
/**
* Creates popup menu.
* @param e mouse event
*/
public JPopupMenu createPopupMenu() {
private JPopupMenu createPopupMenu(MouseEvent e) {
int i = -1;
Row row = null;
int ri = columnAtPoint(e.getPoint()) - 1;
if (ri >= 0 && !rb.rows.isEmpty() && rb.rowsTable.getRowSorter().getViewRowCount() > 0) {
i = rb.rowsTable.getRowSorter().convertRowIndexToModel(ri);
row = rb.rows.get(i);
} else {
return null;
}
JMenuItem copyTCB = new JMenuItem("Copy to Clipboard");
copyTCB.setAccelerator(KS_COPY_TO_CLIPBOARD);
// copyTCB.setAccelerator(KS_COPY_TO_CLIPBOARD);
copyTCB.setEnabled(getSelectedColumnCount() > 0);
copyTCB.addActionListener(new ActionListener() {
@Override
@@ -181,10 +232,20 @@ public class ColumnsTable extends JTable {
UIUtil.copyToClipboard(ColumnsTable.this, false);
}
});
JPopupMenu popup = new JPopupMenu();
popup.add(copyTCB);
return popup;
Point p = new Point(e.getX(), e.getY());
SwingUtilities.convertPointToScreen(p, this);
return rb.createPopupMenu(row, i, (int) p.getX(), (int) p.getY(), false, copyTCB, new Runnable() {
@Override
public void run() {
repaint();
for (int i = 0; i < getColumnCount(); i++) {
TableCellEditor defaultEditor = getDefaultEditor(getColumnClass(i));
if (defaultEditor != null) {
defaultEditor.cancelCellEditing();
}
}
}
}, false);
}
private void adjustTableColumnsWidth() {
@@ -67,11 +67,13 @@ import net.sf.jsqlparser.expression.TimeKeyExpression;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.UserVariable;
import net.sf.jsqlparser.expression.ValueListExpression;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.WithinGroupExpression;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
@@ -102,6 +104,7 @@ import net.sf.jsqlparser.statement.SetStatement;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.Statements;
import net.sf.jsqlparser.statement.UseStatement;
import net.sf.jsqlparser.statement.alter.Alter;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.table.CreateTable;
@@ -118,6 +121,7 @@ import net.sf.jsqlparser.statement.select.AllTableColumns;
import net.sf.jsqlparser.statement.select.FromItemVisitor;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.LateralSubSelect;
import net.sf.jsqlparser.statement.select.ParenthesisFromItem;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
@@ -310,9 +314,9 @@ public class QueryTypeAnalyser {
@Override
public void visit(PlainSelect plainSelect) {
ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(result);
final ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(result);
if (plainSelect.getFromItem() != null) {
FromItemVisitor fromItemVisitor = new FromItemVisitor() {
final FromItemVisitor fromItemVisitor = new FromItemVisitor() {
private void unknownTable() {
result.put("-unknown-" + (unknownTableCounter++), null);
}
@@ -333,7 +337,18 @@ public class QueryTypeAnalyser {
@Override
public void visit(SubJoin subjoin) {
unknownTable();
subjoin.getLeft().accept(this);
if (subjoin.getJoinList() != null) {
for (Join join: subjoin.getJoinList()) {
join.getRightItem().accept(this);
}
for (Join join: subjoin.getJoinList()) {
expressionAnalyzer.setOuterJoinExpression(join.isOuter() || join.isLeft() || join.isRight());
if (join.getOnExpression() != null) {
join.getOnExpression().accept(expressionAnalyzer);
}
}
}
}
@Override
@@ -364,6 +379,12 @@ public class QueryTypeAnalyser {
}
}
}
@Override
public void visit(ParenthesisFromItem parenthesisFromItem) {
if (parenthesisFromItem.getFromItem() != null) {
parenthesisFromItem.getFromItem().accept(this);
}
}
};
plainSelect.getFromItem().accept(fromItemVisitor);
if (plainSelect.getJoins() != null) {
@@ -424,7 +445,13 @@ public class QueryTypeAnalyser {
pkColumns.add(new net.sf.jailer.datamodel.Column(pk, "", 0, -1));
}
PrimaryKey primaryKey = new PrimaryKeyFactory().createPrimaryKey(pkColumns);
Table table = new Table((schemaName == null? "" : schemaName + ".") + tableName, primaryKey, false, false);
Table toTable = theTable.getMetaDataSource().toTable(theTable);
Table table;
if (toTable != null) {
table = new Table(toTable.getName(), primaryKey, false, false);
} else {
table = new Table((schemaName == null? "" : schemaName + ".") + tableName, primaryKey, false, false);
}
List<net.sf.jailer.datamodel.Column> columns = new ArrayList<net.sf.jailer.datamodel.Column>();
for (String pk: columnNames) {
columns.add(new net.sf.jailer.datamodel.Column(pk, "", 0, -1));
@@ -556,11 +583,6 @@ public class QueryTypeAnalyser {
noSubexpression[0] = false;
}
@Override
public void visit(WithinGroupExpression wgexpr) {
noSubexpression[0] = false;
}
@Override
public void visit(AnalyticExpression aexpr) {
noSubexpression[0] = false;
@@ -775,6 +797,21 @@ public class QueryTypeAnalyser {
public void visit(NullValue nullValue) {
noSubexpression[0] = false;
}
@Override
public void visit(BitwiseRightShift aThis) {
noSubexpression[0] = false;
}
@Override
public void visit(BitwiseLeftShift aThis) {
noSubexpression[0] = false;
}
@Override
public void visit(ValueListExpression valueList) {
noSubexpression[0] = false;
}
};
}
@@ -869,6 +906,11 @@ public class QueryTypeAnalyser {
public void visit(Upsert upsert) {
throw new QueryTooComplexException();
}
@Override
public void visit(UseStatement use) {
throw new QueryTooComplexException();
}
}
@@ -23,6 +23,7 @@ import java.awt.Font;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
@@ -160,6 +161,8 @@ public abstract class SQLConsole extends javax.swing.JPanel {
private JMenuItem menuItemToggle;
private JMenuItem menuItemSubstituteVariables;
private JMenuItem menuItemAnalyse;
private int initialTabbedPaneSelection = 0;
private int initialTabbedPaneSelectionLoc = -1;
private final String IGNORED_STATEMENTS = "(\\s*/\\s*)";
@@ -676,7 +679,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
* @param statementStartOffset
* @param explain
*/
private void executeSQL(final String sql, Status status, int statementStartOffset, final boolean explain) {
private void executeSQL(final String sql, final Status status, int statementStartOffset, final boolean explain) {
Statement statement = null;
ResultSet resultSet = null;
final Status localStatus = new Status();
@@ -688,6 +691,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
localStatus.numStatements++;
status.updateView(false);
statement = session.getConnection().createStatement();
// SqlUtil.limitFetchSize(statement, session);
CancellationHandler.begin(statement, SQLConsole.this);
long startTime = System.currentTimeMillis();
sqlStatement =
@@ -723,7 +727,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
hasUpdateCount = false;
hasResultSet = false;
} else {
hasResultSet = statement.execute(sqlStatement);
hasResultSet = executeStatementWithLimit(statement, sqlStatement, session);
}
}
if (hasResultSet) {
@@ -733,15 +737,15 @@ public abstract class SQLConsole extends javax.swing.JPanel {
for (int i = 0; i < metaData.getColumnCount(); ++i) {
columnLabels[i] = metaData.getColumnLabel(i + 1);
}
ResultSetRenderer theMetaDataRenderer = null;
ResultSet theMetaDataResultSet = null;
String resultSetType = null;
try {
resultSetType = TabContentPanel.toType(metaData, session, executionContext);
theMetaDataRenderer = new ResultSetRenderer(TabContentPanel.toMetaDataResultSet(metaData, session, executionContext), null, datamodel.get(), session, executionContext);
theMetaDataResultSet = TabContentPanel.toMetaDataResultSet(metaData, session, executionContext);
} catch (Throwable e1) {
logger.info("error", e1);
}
final ResultSetRenderer metaDataRenderer = theMetaDataRenderer;
final ResultSet metaDataResultSet = theMetaDataResultSet;
final String finalResultSetType = resultSetType;
final Integer limit = (Integer) limitComboBox.getSelectedItem();
final List<Table> resultTypes = explain || sqlPlusResultSet != null? null : QueryTypeAnalyser.getType(sqlStatement, metaDataSource);
@@ -803,7 +807,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
@Override
public void run() {
final BrowserContentPane rb = new ResultContentPane(datamodel.get(), finalResultType, "", session, null, null,
null, null, new RowsClosure(), limit, false, false, executionContext);
null, null, new RowsClosure(), false, false, executionContext);
if (resultTypes != null && resultTypes.size() > 1) {
rb.setResultSetType(resultTypes);
}
@@ -815,6 +819,12 @@ public abstract class SQLConsole extends javax.swing.JPanel {
loadJob.run();
JComponent rTabContainer = rb.getRowsTableContainer();
metaDataDetails.reset();
JComponent metaDataRenderer = null;
try {
metaDataRenderer = new ResultSetRenderer(metaDataResultSet, null, datamodel.get(), session, executionContext);
} catch (Throwable e1) {
logger.info("error", e1);
}
final TabContentPanel tabContentPanel =
new TabContentPanel(rb.rowsCount,
metaDataRenderer,
@@ -857,9 +867,17 @@ public abstract class SQLConsole extends javax.swing.JPanel {
rTabContainer = tabContentPanel;
final int MAXLENGTH = 30;
String title = shortSQL(sqlE, MAXLENGTH);
final int loc = status != null && status.location != null? status.location.a : -1;
if (initialTabbedPaneSelection >= 0 && initialTabbedPaneSelectionLoc == loc) {
if (initialTabbedPaneSelection < tabContentPanel.tabbedPane.getTabCount()) {
tabContentPanel.tabbedPane.setSelectedIndex(initialTabbedPaneSelection);
}
}
tabContentPanel.tabbedPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
initialTabbedPaneSelection = tabContentPanel.tabbedPane.getSelectedIndex();
initialTabbedPaneSelectionLoc = loc;
updateColumnsAndTextView(rb, tabContentPanel);
}
});
@@ -886,12 +904,28 @@ public abstract class SQLConsole extends javax.swing.JPanel {
}
List<? extends SortKey> skeys = sorter.getSortKeys();
if (!skeys.isEmpty()) {
tableSortAndFilterState = tableSortAndFilterState + (tableSortAndFilterState.isEmpty()? "Sorted" : " and sorted")
+ " by \"" + rb.rowsTable.getColumnName(skeys.get(0).getColumn()) + "\"";
for (int i = 0; i < rb.rowsTable.getColumnCount(); ++i) {
if (rb.rowsTable.getColumnModel().getColumn(i).getModelIndex() == skeys.get(0).getColumn()) {
tableSortAndFilterState = tableSortAndFilterState + (tableSortAndFilterState.isEmpty()? "Sorted" : " and sorted")
+ " by \"" + rb.rowsTable.getColumnName(i) + "\"";
break;
}
}
}
if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel) {
columnsTable = new ColumnsTable(rb.rowsTable);
if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel || tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.contentPanel) {
Point vp = null;
if (columnsTable != null) {
if (tabContentPanel.columnsScrollPane.getViewport() != null) {
vp = tabContentPanel.columnsScrollPane.getViewport().getViewPosition();
}
}
columnsTable = new ColumnsTable(rb);
tabContentPanel.columnsScrollPane.setViewportView(columnsTable);
if (vp != null) {
if (tabContentPanel.columnsScrollPane.getViewport() != null) {
tabContentPanel.columnsScrollPane.getViewport().setViewPosition(vp);
}
}
tabContentPanel.columnsSortedStateLabel.setText(" " + tableSortAndFilterState);
tabContentPanel.columnsSortedStateLabel.setVisible(!tableSortAndFilterState.isEmpty());
}
@@ -989,6 +1023,17 @@ public abstract class SQLConsole extends javax.swing.JPanel {
}
}
private boolean executeStatementWithLimit(Statement statement, String sqlStatement, Session session) throws SQLException {
if (DBMS.MySQL.equals(session.dbms)) {
try {
return statement.execute("(" + sqlStatement + "\n) limit " + (1 + (Integer) limitComboBox.getSelectedItem()));
} catch (Throwable e) {
return statement.execute(sqlStatement);
}
}
return statement.execute(sqlStatement);
}
public void setCaretPosition(int position) {
if (editorPane.getDocument().getLength() >= position) {
try {
@@ -1005,6 +1050,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
}
private void updateOutline(String sql, int startPosition) {
sql = sql.replaceFirst(";\\s*$", "");
final int MAX_CONTEXT_LENGTH = 80;
final int MAX_TOOLTIP_LENGTH = 100;
List<OutlineInfo> outlineInfos = new ArrayList<OutlineInfo>();
@@ -1536,6 +1582,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
statusLabel.setText("Canceling...");
statusLabel.setForeground(Color.RED);
CancellationHandler.cancel(this);
cancelButton.setEnabled(false);
}//GEN-LAST:event_cancelButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
@@ -1561,10 +1608,10 @@ public abstract class SQLConsole extends javax.swing.JPanel {
class ResultContentPane extends BrowserContentPane {
public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, Row parentRow,
List<Row> parentRows, Association association, Frame parentFrame,
RowsClosure rowsClosure, Integer limit, Boolean selectDistinct,
RowsClosure rowsClosure, Boolean selectDistinct,
boolean reload, ExecutionContext executionContext) {
super(dataModel, table, condition, session, parentRow, parentRows, association, parentFrame,
rowsClosure, limit, selectDistinct, reload, executionContext);
rowsClosure, selectDistinct, reload, executionContext);
noSingleRowDetailsView = true;
rowsTableScrollPane.setWheelScrollingEnabled(true);
}
@@ -1598,7 +1645,8 @@ public abstract class SQLConsole extends javax.swing.JPanel {
protected void onContentChange(List<Row> rows, boolean reloadChildren) {
}
@Override
protected void navigateTo(Association association, int rowIndex, Row row) {
protected RowBrowser navigateTo(Association association, int rowIndex, Row row) {
return null;
}
@Override
protected List<RowBrowser> getTableBrowser() {
@@ -1680,6 +1728,9 @@ public abstract class SQLConsole extends javax.swing.JPanel {
protected SQLConsole getSqlConsole(boolean switchToConsole) {
return SQLConsole.this;
}
@Override
protected void deselectChildrenIfNeededWithoutReload() {
}
};
private class TitelPanel extends JPanel {
@@ -2007,6 +2058,15 @@ public abstract class SQLConsole extends javax.swing.JPanel {
public boolean isEmpty() {
return editorPane.getDocument().getLength() == 0;
}
/**
* Sets the row limit.
*
* @param limit the row limit
*/
public void setRowLimit(Integer limit) {
limitComboBox.setSelectedItem(limit);
}
private int initialContentSize;
private int initialContentHash;
@@ -2123,4 +2183,5 @@ public abstract class SQLConsole extends javax.swing.JPanel {
logger.info("error", e);
}
}
}
@@ -1,6 +1,5 @@
package net.sf.jailer.ui.graphical_view;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
@@ -16,6 +15,7 @@ import java.util.HashSet;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import net.sf.jailer.ui.UIUtil;
import prefuse.Display;
import prefuse.Visualization;
import prefuse.util.GraphicsLib;
@@ -113,7 +113,7 @@ public class DisplayExporter {
String m_group = Visualization.ALL_ITEMS;
try {
display.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(display);
// Now comes the nice part
@@ -165,7 +165,7 @@ public class DisplayExporter {
return true;
} finally {
display.setCursor(Cursor.getDefaultCursor());
UIUtil.resetWaitCursor(display);
}
}
@@ -115,7 +115,7 @@ public class GraphicalDataModelView extends JPanel {
/**
* Maximum number of tables to make visible during expansion ("expand single table").
*/
public static final int EXPAND_SINGLE_TABLE_LIMIT = 10;
public static final int EXPAND_SINGLE_TABLE_LIMIT = 4;
/**
* The selected association.
@@ -362,7 +362,7 @@ public class GraphicalDataModelView extends JPanel {
popup.show(e.getComponent(), e.getX(), e.getY());
}
if (table != null) {
JPopupMenu popup = createPopupMenu(table, true);
JPopupMenu popup = createPopupMenu(table, null, true);
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
@@ -693,9 +693,10 @@ public class GraphicalDataModelView extends JPanel {
* Creates popup menu.
*
* @param table the table for which the menu pops up
* @param findPathMenuItem additional menu item
* @return the popup menu
*/
public JPopupMenu createPopupMenu(final Table table, boolean withNavigation) {
public JPopupMenu createPopupMenu(final Table table, JMenuItem findPathMenuItem, boolean withNavigation) {
JPopupMenu popup = new JScrollPopupMenu();
boolean withModifications = modelEditor.getAdditionalPopupMenuItems().isEmpty();
@@ -771,7 +772,7 @@ public class GraphicalDataModelView extends JPanel {
// modelEditor.select(table);
// }
// });
JMenuItem selectAsRoot = new JMenuItem("Focus " + table.getName());
JMenuItem selectAsRoot = new JMenuItem("Focus on " + table.getName());
selectAsRoot.addActionListener(new ActionListener () {
@Override
public void actionPerformed(ActionEvent e) {
@@ -892,6 +893,9 @@ public class GraphicalDataModelView extends JPanel {
if (navigateTo != null) {
popup.add(navigateTo);
}
if (findPathMenuItem != null) {
popup.add(findPathMenuItem);
}
if (withModifications){
popup.add(dataBrowser);
}
@@ -1360,10 +1364,12 @@ public class GraphicalDataModelView extends JPanel {
* Creates visible node for given table.
*/
public void showTable(Table source, Table destination) {
List<Table> toCheck = new ArrayList<Table>();
toCheck.add(destination);
addEdges(theGraph, source, null, toCheck, false, new HashSet<Table>(toCheck));
checkForExpansion(theGraph, model.getTables(), true);
synchronized (visualization) {
List<Table> toCheck = new ArrayList<Table>();
toCheck.add(destination);
addEdges(theGraph, source, null, toCheck, false, new HashSet<Table>(toCheck));
checkForExpansion(theGraph, model.getTables(), true);
}
}
/**
@@ -0,0 +1,42 @@
/*
* Copyright 2007 - 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.jailer.ui.pathfinder;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
/**
* Item in the path-history of {@link PathFinderView}.
*
* @author Ralf Wisser
*/
public class HistoryItem implements Serializable {
private static final long serialVersionUID = -2228012653415732355L;
public String source;
public String destination;
public boolean implicit = false;
public List<String> pathStations;
public List<String> path;
public Set<String> excludedTables;
public boolean isValid() {
return path != null && pathStations != null && excludedTables != null && source != null && destination != null;
}
}
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel2">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="History"/>
</Border>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="historyTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="4" rowCount="4">
<Column editable="true" title="Title 1" type="java.lang.Object"/>
<Column editable="true" title="Title 2" type="java.lang.Object"/>
<Column editable="true" title="Title 3" type="java.lang.Object"/>
<Column editable="true" title="Title 4" type="java.lang.Object"/>
</Table>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" value=" "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>
@@ -0,0 +1,218 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package net.sf.jailer.ui.pathfinder;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.ui.UIUtil;
/**
* Path History Panel.
*
* @author Ralf Wisser
*/
public abstract class HistoryPanel extends javax.swing.JPanel {
private static final long serialVersionUID = -482021751302785536L;
private final DataModel dataModel;
private final Table source;
/**
* Creates new form HistoryPanel
*/
public HistoryPanel(Table source, DataModel dataModel) {
this.dataModel = dataModel;
this.source = source;
initComponents();
if (source == null) {
setVisible(false);
} else {
initTable();
}
}
private void initTable() {
final TableCellRenderer defaultTableCellRenderer = historyTable.getDefaultRenderer(String.class);
TableCellRenderer renderer = new TableCellRenderer() {
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(242, 255, 242);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component render = defaultTableCellRenderer.getTableCellRendererComponent(table, value, isSelected, false, row, column);
if (!isSelected) {
render.setBackground((row % 2 == 0) ? BG1 : BG2);
}
if (render instanceof JLabel) {
((JLabel) render).setToolTipText(UIUtil.toHTML(String.valueOf(value), 200));
}
return render;
}
};
historyTable.getColumnModel().getColumn(0).setCellRenderer(renderer);
historyTable.setDefaultRenderer(Object.class, renderer);
historyTable.setAutoCreateRowSorter(true);
historyTable.setRowSelectionAllowed(true);
historyTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
historyTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
int sr = historyTable.getSelectedRow();
if (sr >= 0) {
close();
apply(source, dests.get(historyTable.getRowSorter().convertRowIndexToModel(sr)));
}
}
});
}
});
historyTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
}
});
DefaultTableModel tableModel = new DefaultTableModel(new String[] { "Destination" }, 0) {
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return column == 0;
}
};
dests = PathFinderView.getHistoricDestinations(source, dataModel);
for (Table table: dests) {
tableModel.addRow(new Object[] { dataModel.getDisplayName(table) });
}
historyTable.setModel(tableModel);
adjustTableColumnsWidth(historyTable);
}
private List<Table> dests;
public void adjustTableColumnsWidth(JTable table) {
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
DefaultTableCellRenderer defaultTableCellRenderer = new DefaultTableCellRenderer();
for (int i = 0; i < table.getColumnCount(); i++) {
TableColumn column = table.getColumnModel().getColumn(i);
Component comp = defaultTableCellRenderer.getTableCellRendererComponent(table, column.getHeaderValue(), false, false, 0, i);
int width = 1;
width = Math.max(width, comp.getPreferredSize().width);
int line = 0;
for (; line < table.getRowCount(); ++line) {
comp = table.getCellRenderer(line, i).getTableCellRendererComponent(table, dtm.getValueAt(line, i), false, false, line, i);
width = Math.max(width, comp.getPreferredSize().width);
}
column.setPreferredWidth(Math.min(width, 400));
if (i == 0) {
column.setWidth(column.getPreferredWidth());
}
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
jPanel1 = new javax.swing.JPanel();
jPanel2 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
historyTable = new javax.swing.JTable();
jLabel1 = new javax.swing.JLabel();
setLayout(new java.awt.GridBagLayout());
jPanel1.setLayout(new java.awt.GridBagLayout());
jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("History"));
jPanel2.setLayout(new java.awt.GridBagLayout());
historyTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null},
{null, null, null, null},
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"Title 1", "Title 2", "Title 3", "Title 4"
}
));
jScrollPane1.setViewportView(historyTable);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
jPanel2.add(jScrollPane1, gridBagConstraints);
jLabel1.setText(" ");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
jPanel2.add(jLabel1, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jPanel2, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
add(jPanel1, gridBagConstraints);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTable historyTable;
private javax.swing.JLabel jLabel1;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables
protected abstract void close();
protected abstract void apply(Table source, Table destination);
}
@@ -0,0 +1,104 @@
/*
* Copyright 2007 - 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.jailer.ui.pathfinder;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.List;
import org.fife.rsta.ui.EscapableDialog;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.ui.UIUtil;
/**
* Finds path between two tables.
*
* @author Ralf Wisser
*/
public class PathFinder {
private List<Table> path;
private boolean expand;
public class Result {
public List<Table> path;
public boolean expand;
}
public Result find(Table source, Table destination, DataModel dataModel, boolean withOpenTablesButton, boolean fromHistory, Frame owner) {
final EscapableDialog dialog = new EscapableDialog(owner, "PathFinder", true) {
private static final long serialVersionUID = 1L;
};
final PathFinderView view = new PathFinderView(dataModel, source, destination, withOpenTablesButton, fromHistory) {
@Override
protected void applyPath(List<Table> path, boolean expand) {
PathFinder.this.path = path;
PathFinder.this.expand = expand;
dialog.setVisible(false);
}
private static final long serialVersionUID = 1L;
};
view.showGraph(true);
dialog.getContentPane().add(view);
dialog.pack();
int minWidth = 1200;
dialog.setSize(minWidth, Math.min(Math.max(dialog.getHeight() + 20, 440), 600));
dialog.addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent arg0) {
view.sepLabel.setVisible(false);
}
});
Point ownerLoc;
Dimension ownerSize;
if (owner != null) {
ownerLoc = owner.getLocation();
ownerSize = owner.getSize();
} else {
ownerLoc = new Point();
ownerSize = Toolkit.getDefaultToolkit().getScreenSize();
}
int x = (int) (ownerLoc.getX() + ownerSize.getWidth() / 2 - dialog.getWidth() / 2);
int y = (int) (ownerLoc.getY() + ownerSize.getHeight() / 2 - dialog.getHeight() / 2);
dialog.setLocation(x, y);
int h = dialog.getHeight();
UIUtil.fit(dialog);
if (h > dialog.getHeight()) {
dialog.setLocation(x, y - (h - dialog.getHeight()));
dialog.setSize(Math.max(minWidth, dialog.getWidth()), Math.min(Math.max(dialog.getHeight() + 20, 400), 600));
UIUtil.fit(dialog);
}
dialog.setVisible(true);
if (path == null) {
return null;
}
Result result = new Result();
result.path = path;
result.expand = expand;
return result;
}
}
@@ -0,0 +1,304 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,83,0,0,2,-34"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties>
<Property name="resizeWeight" type="double" value="1.0"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel2">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Union of all shortest paths without excluded tables."/>
</Border>
</Property>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="ff" id="white" palette="1" red="ff" type="palette"/>
</Property>
<Property name="opaque" type="boolean" value="false"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="pathContainerPanel">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="ff" id="white" palette="1" red="ff" type="palette"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
</Container>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="okButton">
<Properties>
<Property name="text" type="java.lang.String" value="Show Path"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="okExpandButton">
<Properties>
<Property name="text" type="java.lang.String" value="Show Path and open Tables"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okExpandButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="sepLabel">
<Properties>
<Property name="text" type="java.lang.String" value=" "/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="2" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="80" green="80" id="gray" palette="1" red="80" type="palette"/>
</Property>
<Property name="text" type="java.lang.String" value="Open context menu (right mouse click on table) to define its direct successor."/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="2" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel3">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Excluded Tables"/>
</Border>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="exclusionTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="4" rowCount="4">
<Column editable="true" title="Title 1" type="java.lang.Object"/>
<Column editable="true" title="Title 2" type="java.lang.Object"/>
<Column editable="true" title="Title 3" type="java.lang.Object"/>
<Column editable="true" title="Title 4" type="java.lang.Object"/>
</Table>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" value=" "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel4">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JButton" name="undoButton">
<Properties>
<Property name="text" type="java.lang.String" value="jButton1"/>
<Property name="focusable" type="boolean" value="false"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="undoButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="redoButton">
<Properties>
<Property name="text" type="java.lang.String" value="jButton1"/>
<Property name="focusable" type="boolean" value="false"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="redoButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator2">
<Properties>
<Property name="orientation" type="int" value="1"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="0" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="0" insetsRight="8" anchor="10" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="historyButton">
<Properties>
<Property name="text" type="java.lang.String" value="From History"/>
<Property name="toolTipText" type="java.lang.String" value="Take the previously determined path."/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="historyButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator3">
<Properties>
<Property name="orientation" type="int" value="1"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="5" gridY="0" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="0" insetsRight="8" anchor="10" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JCheckBox" name="considerRestrictionsCheckbox">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="Consider restrictions"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="considerRestrictionsCheckboxActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="10" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="8" anchor="13" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="resetButton">
<Properties>
<Property name="text" type="java.lang.String" value="Reset"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="resetButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="6" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JSeparator" name="jSeparator1">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,298 @@
/*
* Copyright 2007 - 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.jailer.ui.pathfinder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.sf.jailer.datamodel.Association;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.util.Pair;
/**
* Union of equi-length paths as directed graph.
*
* @author Ralf Wisser
*/
public class PathGraph {
private final Table source;
private final Table destination;
private Map<Table, Node> nodePerTable = new HashMap<Table, Node>();
private Map<Pair<Node, Node>, EdgeType> edgeTypes = new HashMap<Pair<Node, Node>, EdgeType>();
private Set<Table> visitedExcludedTables = new HashSet<Table>();
public enum EdgeType { PARENT, CHILD, ASSOCIATION, IGNORED };
public class Node {
Table table;
int column;
Set<Node> next = new HashSet<Node>();
Set<Node> prev = new HashSet<Node>();
public String toString() {
return table.getName() + ":" + column;
}
public void collectPrevClosure(Set<Table> closure) {
if (!closure.contains(table)) {
closure.add(table);
for (Node p: prev) {
p.collectPrevClosure(closure);
}
}
}
public void collectNextClosure(Set<Table> closure) {
if (!closure.contains(table)) {
closure.add(table);
for (Node p: next) {
p.collectNextClosure(closure);
}
}
}
}
/**
* Gets the node of a given table.
*
* @param table the table
* @return node representing table
*/
public Node getNode(Table table) {
return nodePerTable.get(table);
}
/**
* Gets all nodes on a given column.
*
* @param column the column
* @return all nodes on a given column
*/
public List<Node> getNodes(int column) {
List<Node> result = new ArrayList<Node>();
for (Entry<Table, Node> e:nodePerTable.entrySet()) {
if (e.getValue().column == column) {
result.add(e.getValue());
}
}
return result;
}
/**
* Gets edge-type of a given edge.
*
* @param from left node of edge
* @param to right node of edge
* @return edge type
*/
public EdgeType getEdgeType(Node from, Node to) {
Pair<Node, Node> edgeKey = new Pair<Node, Node>(from, to);
return edgeTypes.get(edgeKey);
}
/**
* Resets the graph to an empty graph.
*/
private void reset() {
nodePerTable.clear();
edgeTypes.clear();
}
/**
* Returns <code>true</code> if this graph is empty.
*/
public boolean isEmpty() {
return nodePerTable.isEmpty();
}
/**
* Creates new Graph.
* @param excludedTables
* @param pathStations
* @param considerRestrictions
*/
public PathGraph(DataModel dataModel, Table source, Table destination, Set<Table> excludedTables, List<Table> pathStations, boolean considerRestrictions) {
this(dataModel, source, destination, excludedTables, pathStations, considerRestrictions, false);
}
/**
* Creates new Graph.
* @param excludedTables
* @param pathStations
* @param considerRestrictions
*/
public PathGraph(DataModel dataModel, Table source, Table destination, Set<Table> excludedTables, List<Table> pathStations, boolean considerRestrictions, boolean strict) {
this.source = source;
this.destination = destination;
List<Table> stations = new ArrayList<Table>(pathStations);
Node destNode;
for (;;) {
visitedExcludedTables.clear();
createGraph(excludedTables, stations, visitedExcludedTables, considerRestrictions);
destNode = nodePerTable.get(this.destination);
if (destNode == null) {
// retry with shorter path
if (!stations.isEmpty() && !strict) {
stations.remove(stations.size() - 1);
continue;
}
reset();
return;
}
break;
}
Set<Table> destClosure = new HashSet<Table>();
destNode.collectPrevClosure(destClosure);
Set<Table> excluded = new HashSet<Table>(dataModel.getTables());
excluded.removeAll(destClosure);
excluded.addAll(excludedTables);
visitedExcludedTables.clear();
createGraph(excluded, stations, visitedExcludedTables, considerRestrictions);
visitedExcludedTables.retainAll(excludedTables);
}
private void createGraph(Set<Table> excluded, List<Table> pathStations, Set<Table> visitedExTables, boolean considerRestrictions) {
reset();
Map<Table, Table> forcedSucc = new HashMap<Table, Table>();
for (int i = 1; i < pathStations.size(); ++i) {
Table a = pathStations.get(i - 1);
Table b = pathStations.get(i);
for (Association as: a.associations) {
if (!as.isIgnored() || !considerRestrictions) {
if (as.destination.equals(b)) {
forcedSucc.put(a, b);
break;
}
}
}
}
Set<Table> currentColumn = new HashSet<Table>();
currentColumn.add(source);
int column = 0;
Node node = new Node();
node.table = source;
node.column = column;
nodePerTable.put(source, node);
List<Table> stations = new LinkedList<Table>(pathStations);
stations.remove(source);
stations.remove(destination);
stations.removeAll(excluded);
Set<Table> onPath = new HashSet<Table>(pathStations);
onPath.add(source);
onPath.add(destination);
Set<Table> lastVisitedExTables = new HashSet<Table>();
do {
boolean onStation = false;
if (!stations.isEmpty()) {
Table nextStat = stations.get(0);
if (currentColumn.contains(nextStat)) {
currentColumn.clear();
currentColumn.add(nextStat);
stations.remove(0);
onStation = true;
}
}
if (!onStation) {
visitedExTables.addAll(lastVisitedExTables);
}
lastVisitedExTables.clear();
Set<Table> nextColumn = new HashSet<Table>();
for (Table table: currentColumn) {
node = nodePerTable.get(table);
for (Association a: table.associations) {
if (!a.isIgnored() || !considerRestrictions
|| (onPath.contains(a.source) && onPath.contains(a.destination))) {
Table dest = a.destination;
if (excluded.contains(dest)) {
lastVisitedExTables.add(dest);
continue;
}
if (forcedSucc.containsKey(table) && !forcedSucc.get(table).equals(dest)) {
continue;
}
Node newNode = nodePerTable.get(dest);
if (newNode != null && newNode.column != column + 1) {
continue;
}
nextColumn.add(dest);
EdgeType type;
if (a.isIgnored()) {
type = EdgeType.IGNORED;
} else if (a.isInsertDestinationBeforeSource()) {
type = EdgeType.PARENT;
} else if (a.isInsertSourceBeforeDestination()) {
type = EdgeType.CHILD;
} else {
type = EdgeType.ASSOCIATION;
}
if (newNode == null) {
newNode = new Node();
newNode.table = dest;
newNode.column = column + 1;
nodePerTable.put(dest, newNode);
}
Pair<Node, Node> edgeKey = new Pair<Node, Node>(node, newNode);
EdgeType oldType = edgeTypes.get(edgeKey);
if (oldType != null && !oldType.equals(EdgeType.IGNORED) && !type.equals(oldType)) {
type = EdgeType.ASSOCIATION;
}
edgeTypes.put(edgeKey, type);
node.next.add(newNode);
newNode.prev.add(node);
}
}
}
++column;
currentColumn = nextColumn;
} while (!currentColumn.isEmpty());
visitedExTables.addAll(lastVisitedExTables);
}
public Set<Table> getVisitedExcludedTables() {
return visitedExcludedTables;
}
/**
* Is this graph a unique non-empty path?
*/
public boolean isUnique() {
if (isEmpty()) {
return false;
}
for (int column = 0; ; ++column) {
int n = getNodes(column).size();
if (n == 0) {
return true;
} else if (n > 1) {
return false;
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Some files were not shown because too many files have changed in this diff Show More