Compare commits

...

118 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
91 changed files with 8146 additions and 2640 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>
+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.
+43 -1
View File
@@ -1,4 +1,46 @@
7.10.1
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
@@ -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);
}
}
}
@@ -25,7 +25,7 @@ public class JailerVersion {
/**
* The Jailer version.
*/
public static final String VERSION = "7.10.1";
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"
@@ -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>
@@ -63,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>
@@ -111,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>
@@ -120,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>
@@ -260,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>
<!--
@@ -435,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>
@@ -548,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>
@@ -664,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>
@@ -792,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>
@@ -1109,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);
}
}
}
@@ -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,6 +243,7 @@ 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 : "";
this.temporaryTableScope = scope;
@@ -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;
}
}
@@ -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) {
@@ -248,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)) {
@@ -287,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.
*
@@ -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"/>
+280 -30
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] = "";
@@ -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;
@@ -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());
}
@@ -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;
@@ -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
@@ -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();
@@ -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;
@@ -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"/>
@@ -17,7 +17,6 @@ package net.sf.jailer.ui;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -45,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;
@@ -70,6 +69,7 @@ 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;
@@ -146,6 +146,29 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
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();
@@ -176,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
@@ -217,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 {
@@ -225,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) {
@@ -346,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();
@@ -823,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) {
@@ -1072,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");
@@ -1080,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();
@@ -1113,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;
}
@@ -1148,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;
}
}
@@ -1260,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;
@@ -1388,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);
}
}
}
@@ -1427,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;
@@ -1440,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 {
@@ -1455,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");
@@ -1467,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);
}
}
@@ -1688,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) {
@@ -1801,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
}
/**
@@ -1873,6 +1867,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
UIManager.put("InternalFrame:InternalFrameTitlePane[Enabled].textForeground", Color.BLUE);
}
UIUtil.prepareUI();
} catch (Exception x) {
}
@@ -1884,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);
}
@@ -1941,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 {
@@ -2070,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;
@@ -2096,4 +2094,4 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
private static final long serialVersionUID = -2252377308370736756L;
}
}
@@ -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
@@ -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();
}
+76 -3
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,9 +965,42 @@ public class UIUtil {
public String toString() {
return text;
}
@Override
public int compareTo(IconWithText o) {
return text.compareTo(o.text);
}
}
public static void invokeLater(final int ticks, final Runnable runnable) {
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
@@ -975,5 +1013,40 @@ public class UIUtil {
}
});
}
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;
}
}
}
@@ -18,6 +18,11 @@
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="openEditorLabel">
<Properties>
<Property name="text" type="java.lang.String" value=" And "/>
</Properties>
</Component>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
@@ -34,151 +39,10 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel7">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="8" gridWidth="5" gridHeight="1" fill="2" 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.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JButton" name="loadButton">
<Properties>
<Property name="text" type="java.lang.String" value=" Reload "/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="loadButtonActionPerformed"/>
</Events>
<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="2" 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>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="onPanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[66, 17]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="6" gridWidth="4" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="16" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="on">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="jLabel3"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="joinPanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[66, 17]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="5" gridWidth="4" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="16" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="join">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="jLabel3"/>
</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="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="jLabel6">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" as B "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" 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>
<Container class="javax.swing.JPanel" name="jPanel10">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[66, 17]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="4" 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>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="from">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="jLabel3"/>
</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="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="jLabel5">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="horizontalAlignment" type="int" value="2"/>
<Property name="text" type="java.lang.String" value=" as A"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" 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>
<Container class="javax.swing.JPanel" name="pendingNonpendingPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="12" gridWidth="7" 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="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>
@@ -675,180 +539,344 @@
</Container>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" Join "/>
</Properties>
<Container class="javax.swing.JPanel" name="menuPanel">
<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="5" gridWidth="1" 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>
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" On "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="6" gridWidth="2" 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>
<Component class="javax.swing.JLabel" name="andLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" Where "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="8" gridWidth="1" 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>
<Component class="javax.swing.JLabel" name="openEditorLabel">
<Properties>
<Property name="text" type="java.lang.String" value=" And "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="8" gridWidth="1" 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>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" From "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="4" gridWidth="1" 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>
<Container class="javax.swing.JPanel" name="jPanel3">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="9" gridWidth="2" 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>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="rrPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="7" gridY="4" gridWidth="2" gridHeight="3" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="2" anchor="11" weightX="0.0" weightY="0.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="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="relatedRowsPanel">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="f0" red="e0" type="rgb"/>
</Property>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.SoftBevelBorderInfo">
<BevelBorder/>
</Border>
</Property>
</Properties>
<Container class="javax.swing.JPanel" name="jPanel7">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="7" gridY="4" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="0" insetsBottom="4" insetsRight="0" anchor="13" weightX="0.0" weightY="1.0"/>
<GridBagConstraints gridX="4" gridY="8" gridWidth="5" gridHeight="1" fill="2" 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.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="relatedRowsLabel">
<Component class="javax.swing.JButton" name="loadButton">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="f0" red="e0" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" value=" Related Rows "/>
<Property name="opaque" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value=" Reload "/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="loadButtonActionPerformed"/>
</Events>
<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="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="2" 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>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="sqlPanel">
<Container class="javax.swing.JPanel" name="onPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.SoftBevelBorderInfo">
<BevelBorder/>
</Border>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[66, 17]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="8" gridY="5" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
<GridBagConstraints gridX="4" gridY="6" gridWidth="4" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="16" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="on">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="jLabel3"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="joinPanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[66, 17]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="5" gridWidth="4" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="16" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="join">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="jLabel3"/>
</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="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="jLabel6">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" as B "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" 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>
<Container class="javax.swing.JPanel" name="jPanel10">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[66, 17]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="4" 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>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="from">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="jLabel3"/>
</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="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="jLabel5">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="horizontalAlignment" type="int" value="2"/>
<Property name="text" type="java.lang.String" value=" as A"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" 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>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" Join "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="5" gridWidth="1" 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>
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" On "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="6" gridWidth="2" 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>
<Component class="javax.swing.JLabel" name="andLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" Where "/>
</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="2" gridY="8" gridWidth="1" 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>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value=" From "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="4" gridWidth="1" 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>
<Container class="javax.swing.JPanel" name="jPanel3">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="9" gridWidth="2" 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>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="rrPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="7" gridY="4" gridWidth="2" gridHeight="3" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="2" anchor="11" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="sqlLabel1">
<Container class="javax.swing.JPanel" name="relatedRowsPanel">
<Properties>
<Property name="text" type="java.lang.String" value=" Menu "/>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="f0" red="e0" type="rgb"/>
</Property>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.SoftBevelBorderInfo">
<BevelBorder/>
</Border>
</Property>
</Properties>
</Component>
<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="7" gridY="4" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="0" insetsBottom="4" insetsRight="0" anchor="13" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="relatedRowsLabel">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="f0" red="e0" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" value=" Related Rows "/>
<Property name="opaque" type="boolean" value="true"/>
</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>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="sqlPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.SoftBevelBorderInfo">
<BevelBorder/>
</Border>
</Property>
</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="8" gridY="5" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="sqlLabel1">
<Properties>
<Property name="text" type="java.lang.String" value=" Menu "/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel9">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="5" gridY="5" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
</Container>
<Component class="javax.swing.JLabel" name="dropA">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value="drop"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="4" 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.JLabel" name="dropB">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value="drop"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="5" 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="openEditorButton">
<Properties>
<Property name="text" type="java.lang.String" value="jButton1"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="8" 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>
<Container class="javax.swing.JPanel" name="jPanel9">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="5" gridY="5" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
</Container>
<Component class="javax.swing.JLabel" name="dropA">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value="drop"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="4" 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.JLabel" name="dropB">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="DejaVu Sans" size="13" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value="drop"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="5" 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>
</Form>
@@ -19,7 +19,6 @@ import java.awt.BasicStroke;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
@@ -529,7 +528,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
* {@link Association} with parent row
*/
public BrowserContentPane(final DataModel dataModel, final Table table, String condition, Session session, Row parentRow, List<Row> parentRows,
final Association association, Frame parentFrame, RowsClosure rowsClosure,
final Association association, final Frame parentFrame, RowsClosure rowsClosure,
Boolean selectDistinct, boolean reload, ExecutionContext executionContext) {
this.table = table;
this.session = session;
@@ -766,11 +765,8 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
registerAccelerator(KS_DETAILS, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
Point loc = SwingUtilities.convertPoint(
BrowserContentPane.this,
0, 0,
SwingUtilities.getWindowAncestor(BrowserContentPane.this)
);
Point loc = new Point(18, 16);
SwingUtilities.convertPointToScreen(loc, rowsTable);
openDetails(loc.x, loc.y);
}
});
@@ -829,7 +825,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
Component render = defaultTableCellRenderer.getTableCellRendererComponent(rowsTable, value, isSelected, false, row, column);
final RowSorter<?> rowSorter = rowsTable.getRowSorter();
if (rowSorter.getViewRowCount() == 0) {
if (rowSorter.getViewRowCount() == 0 && table == rowsTable) {
return render;
}
@@ -965,7 +961,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
JPopupMenu popup;
popup = createPopupMenu(row, i, p.x + getOwner().getX(), p.y + getOwner().getY(), rows.size() == 1);
if (popup != null) {
showPopup(source, x, y, popup);
UIUtil.showPopup(source, x, y, popup);
popup.addPropertyChangeListener("visible", new PropertyChangeListener() {
@Override
@@ -1005,20 +1001,21 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
rowsTableScrollPane.addMouseListener(rowTableListener);
singleRowViewScrollContentPanel.addMouseListener(rowTableListener);
andConditionEditor = new ConditionEditor(parentFrame, null, dataModel);
openEditorLabel.setIcon(conditionEditorIcon);
openEditorLabel.setText(null);
openEditorLabel.addMouseListener(new java.awt.event.MouseAdapter() {
openEditorButton.setIcon(UIUtil.scaleIcon(this, conditionEditorIcon));
openEditorButton.setText(null);
openEditorButton.addActionListener(new ActionListener() {
@Override
public void mouseReleased(MouseEvent e) {
mouseClicked(e);
}
@Override
public void mouseClicked(MouseEvent e) {
public void actionPerformed(ActionEvent e) {
final Point pos = new Point(openEditorButton.getX(), openEditorButton.getY() + openEditorButton.getHeight());
SwingUtilities.convertPointToScreen(pos, openEditorButton.getParent());
loadButton.grabFocus();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (andConditionEditor == null) {
andConditionEditor = new ConditionEditor(parentFrame, null, dataModel);
}
andConditionEditor.setLocationAndFit(pos);
String cond = andConditionEditor.edit(getAndConditionText(), "Table", "A", table, null, null, null, false, true);
if (cond != null) {
if (!getAndConditionText().equals(ConditionEditor.toSingleLine(cond))) {
@@ -1031,16 +1028,6 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
});
}
@Override
public void mouseEntered(java.awt.event.MouseEvent evt) {
openEditorLabel.setIcon(conditionEditorSelectedIcon);
}
@Override
public void mouseExited(java.awt.event.MouseEvent evt) {
openEditorLabel.setIcon(conditionEditorIcon);
}
});
relatedRowsLabel.setIcon(UIUtil.scaleIcon(this, relatedRowsIcon));
relatedRowsLabel.setFont(relatedRowsLabel.getFont().deriveFont(relatedRowsLabel.getFont().getSize() * 1.1f));
@@ -1057,11 +1044,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// if (rows.size() == 1) {
// popup = createPopupMenu(rows.get(0), 0, 0, 0);
// } else {
popup = createPopupMenu(null, -1, 0, 0, false);
// }
popup = createPopupMenu(null, -1, 0, 0, false);
setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-2);
popup.addPropertyChangeListener("visible", new PropertyChangeListener() {
@Override
@@ -1073,7 +1056,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
}
});
showPopup(relatedRowsPanel, 0, relatedRowsPanel.getHeight(), popup);
UIUtil.showPopup(relatedRowsPanel, 0, relatedRowsPanel.getHeight(), popup);
}
});
}
@@ -1107,7 +1090,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
@Override
public void run() {
Point loc = sqlPanel.getLocationOnScreen();
popup = createSqlPopupMenu(BrowserContentPane.this.parentRow, 0, (int) loc.getX(), (int) loc.getY(), false);
popup = createSqlPopupMenu(BrowserContentPane.this.parentRow, 0, (int) loc.getX(), (int) loc.getY(), false, BrowserContentPane.this);
setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-2);
popup.addPropertyChangeListener("visible", new PropertyChangeListener() {
@Override
@@ -1119,7 +1102,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
}
});
showPopup(sqlPanel, 0, sqlPanel.getHeight(), popup);
UIUtil.showPopup(sqlPanel, 0, sqlPanel.getHeight(), popup);
}
});
}
@@ -1264,9 +1247,10 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
if (parent == null) {
parent = BrowserContentPane.this;
}
parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(parent);
try {
Desktop.noArrangeLayoutOnNewTableBrowser = true;
Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = todoList.size() > 1;
Desktop.resetLastArrangeLayoutOnNewTableBrowser();
for (int i = 0; i < todoList.size(); ++i) {
if (i == todoList.size() - 1) {
@@ -1276,7 +1260,8 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
} finally {
Desktop.noArrangeLayoutOnNewTableBrowser = false;
parent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = false;
UIUtil.resetWaitCursor(parent);
}
}
});
@@ -1325,8 +1310,21 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
* @param runnable
*/
public JPopupMenu createPopupMenu(final Row row, final int rowIndex, final int x, final int y, boolean navigateFromAllRows, JMenuItem altCopyTCB, final Runnable repaint) {
return createPopupMenu(row, rowIndex, x, y, navigateFromAllRows, altCopyTCB, repaint, true);
}
/**
* Creates popup menu for navigation.
* @param navigateFromAllRows
* @param runnable
*/
public JPopupMenu createPopupMenu(final Row row, final int rowIndex, final int x, final int y, boolean navigateFromAllRows, JMenuItem altCopyTCB, final Runnable repaint, final boolean withKeyStroke) {
JMenuItem tableFilter = new JCheckBoxMenuItem("Table Filter");
tableFilter.setAccelerator(KS_FILTER);
if (withKeyStroke) {
tableFilter.setAccelerator(KS_FILTER);
} else {
tableFilter.setVisible(false);
}
tableFilter.setSelected(isTableFilterEnabled);
if (isLimitExceeded) {
tableFilter.setForeground(Color.red);
@@ -1344,7 +1342,9 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
copyTCB = altCopyTCB;
} else {
copyTCB = new JMenuItem("Copy to Clipboard");
copyTCB.setAccelerator(KS_COPY_TO_CLIPBOARD);
if (withKeyStroke) {
copyTCB.setAccelerator(KS_COPY_TO_CLIPBOARD);
}
copyTCB.setEnabled(rowsTable.getSelectedColumnCount() > 0);
copyTCB.addActionListener(new ActionListener() {
@Override
@@ -1358,7 +1358,9 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
JPopupMenu jPopupMenu = new JPopupMenu();
if (row != null) {
JMenuItem det = new JMenuItem("Details");
det.setAccelerator(KS_DETAILS);
if (withKeyStroke) {
det.setAccelerator(KS_DETAILS);
}
jPopupMenu.add(det);
jPopupMenu.add(new JSeparator());
det.addActionListener(new ActionListener() {
@@ -1376,7 +1378,9 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
jPopupMenu.addSeparator();
jPopupMenu.add(tableFilter);
JMenuItem editMode = new JMenuItem("Edit Mode");
editMode.setAccelerator(KS_EDIT);
if (withKeyStroke) {
editMode.setAccelerator(KS_EDIT);
}
jPopupMenu.add(editMode);
editMode.setEnabled(false);
return jPopupMenu;
@@ -1456,7 +1460,9 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
if (row != null) {
JMenuItem det = new JMenuItem("Details");
det.setAccelerator(KS_DETAILS);
if (withKeyStroke) {
det.setAccelerator(KS_DETAILS);
}
popup.insert(det, 0);
popup.insert(new JSeparator(), 1);
det.addActionListener(new ActionListener() {
@@ -1477,9 +1483,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
qb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<String> whereClauses = new ArrayList<String>();
whereClauses.add(SqlUtil.replaceAliases(row.rowId, "A", "A"));
getQueryBuilderDialog().buildQuery(table, true, false, new ArrayList<Association>(), whereClauses, dataModel, session, getMetaDataSource(), false);
openQueryBuilder(false, SqlUtil.replaceAliases(row.rowId, "A", "A"));
}
});
@@ -1489,9 +1493,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
sqlConsole.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<String> whereClauses = new ArrayList<String>();
whereClauses.add(SqlUtil.replaceAliases(row.rowId, "A", "A"));
getQueryBuilderDialog().buildQuery(table, true, false, new ArrayList<Association>(), whereClauses, dataModel, session, getMetaDataSource(), true);
openQueryBuilder(true, SqlUtil.replaceAliases(row.rowId, "A", "A"));
}
});
@@ -1605,7 +1607,9 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
popup.addSeparator();
popup.add(tableFilter);
JCheckBoxMenuItem editMode = new JCheckBoxMenuItem("Edit Mode");
editMode.setAccelerator(KS_EDIT);
if (withKeyStroke) {
editMode.setAccelerator(KS_EDIT);
}
editMode.setSelected(isEditMode);
editMode.addActionListener(new ActionListener() {
@Override
@@ -1626,8 +1630,9 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
/**
* Creates popup menu for SQL.
* @param forNavTree
* @param browserContentPane
*/
public JPopupMenu createSqlPopupMenu(final Row parentrow, final int rowIndex, final int x, final int y, boolean forNavTree) {
public JPopupMenu createSqlPopupMenu(final Row parentrow, final int rowIndex, final int x, final int y, boolean forNavTree, final Component parentComponent) {
JPopupMenu popup = new JPopupMenu();
JMenuItem qb = new JMenuItem("Query Builder");
@@ -1734,7 +1739,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
});
popup.addSeparator();
JMenuItem m = new JMenuItem("Hide from View");
JMenuItem m = new JMenuItem("Hide (Minimize)");
popup.add(m);
m.addActionListener(new ActionListener() {
@Override
@@ -1742,27 +1747,12 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
onHide();
}
});
m = new JMenuItem("Close" + (getChildBrowsers().isEmpty()? "" : " Subtree"));
m = new JMenuItem("Close");
popup.add(m);
m.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Component parent = SwingUtilities.getWindowAncestor(BrowserContentPane.this);
if (parent == null) {
parent = BrowserContentPane.this;
}
parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
closeSubTree(BrowserContentPane.this);
} finally {
parent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
private void closeSubTree(BrowserContentPane cp) {
for (RowBrowser c: cp.getChildBrowsers()) {
closeSubTree(c.browserContentPane);
}
cp.close();
closeWithChildren(parentComponent);
}
});
popup.add(new JSeparator());
@@ -1795,6 +1785,65 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
return popup;
}
public boolean closeWithChildren(Component parentComponent) {
int count = countSubNodes(this);
Component parent = SwingUtilities.getWindowAncestor(this);
if (parent == null) {
parent = BrowserContentPane.this;
}
boolean closeThisToo = true;
if (count > 1) {
int o = JOptionPane.showOptionDialog(parentComponent, "Which tables do you want to close?", "Close",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null,
new Object[] {
"Only this table",
"This and related tables (" + (count) + ")",
"Related tables (" + (count - 1) + ")"
},
null);
if (o == 0) {
UIUtil.setWaitCursor(parent);
try {
close();
} finally {
UIUtil.resetWaitCursor(parent);
}
return true;
}
if (o == 1) {
closeThisToo = true;
} else if (o == 2) {
closeThisToo = false;
} else {
return false;
}
}
UIUtil.setWaitCursor(parent);
try {
closeSubTree(BrowserContentPane.this, closeThisToo);
} finally {
UIUtil.resetWaitCursor(parent);
}
return true;
}
private int countSubNodes(BrowserContentPane cp) {
int count = 0;
for (RowBrowser c: cp.getChildBrowsers()) {
count += countSubNodes(c.browserContentPane);
}
return count + 1;
}
private void closeSubTree(BrowserContentPane cp, boolean closeThisToo) {
for (RowBrowser c: cp.getChildBrowsers()) {
closeSubTree(c.browserContentPane, true);
}
if (closeThisToo) {
cp.close();
}
}
private JMenu createInsertChildMenu(Row row, final int x, final int y) {
JScrollMenu insertNewRow = new JScrollMenu("Insert Child");
if (table == null || table.getName() == null) {
@@ -1863,7 +1912,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
if (parent == null) {
parent = this;
}
parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(parent);
try {
String file;
String ts = new SimpleDateFormat("HH-mm-ss-SSS").format(new Date());
@@ -2037,10 +2086,9 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
newFile.delete();
} catch (Throwable e) {
parent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.showException(this, "Error", e, session);
} finally {
parent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(parent);
}
}
@@ -2252,7 +2300,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
private void openSQLDialog(String titel, int x, int y, Object sql) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
JDialog d;
try {
String LF = System.getProperty("line.separator", "\n");
@@ -2299,7 +2347,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
UIUtil.showException(this, "Error", e);
return;
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
d.setVisible(true);
}
@@ -2394,6 +2442,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
++l;
final JMenuItem item = new JMenuItem(" " + (name.substring(1)) + " ");
item.setToolTipText(association.getUnrestrictedJoinCondition());
final JLabel countLabel = new JLabel(". >99999 ") {
@Override
public void paint(Graphics g) {
@@ -2473,7 +2522,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
String cs = " " + (count.count < 0? "?" : (count.count > MAX_RC)? (">" + MAX_RC) : count.isExact? count.count : (">=" + count.count)) + " ";
String cs = " " + (count.count < 0? "?" : (count.count > MAX_RC)? (">" + MAX_RC) : count.isExact? count.count : (">" + count.count)) + " ";
countLabel.setText(cs);
if (count.count == 0) {
countLabel.setForeground(Color.lightGray);
@@ -2587,7 +2636,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
String defaultSchema = JDBCMetaDataBasedModelElementFinder.getDefaultSchema(session, session.getSchema());
String schema = quoting.unquote(table.getOriginalSchema(defaultSchema));
String tableName = quoting.unquote(table.getUnqualifiedName());
ResultSet resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(session, metaData, schema, tableName, "%", false);
ResultSet resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(session, metaData, schema, tableName, "%", false, null);
while (resultSet.next()) {
String colName = resultSet.getString(4).toLowerCase();
columns.add(colName);
@@ -2601,7 +2650,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
schema = schema.toLowerCase();
tableName = tableName.toLowerCase();
}
resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(session, metaData, schema, tableName, "%", false);
resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(session, metaData, schema, tableName, "%", false, null);
while (resultSet.next()) {
String colName = resultSet.getString(4).toLowerCase();
columns.add(colName);
@@ -2991,14 +3040,10 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
f = false;
}
f = true;
String orderBy = "";
String olapOrderBy = "";
if (selectParentPK) {
int j = 0;
for (Column pk: rowIdSupport.getPrimaryKey(association.source, session).getColumns()) {
parentPkColumnNames.add(quoting.requote(pk.name));
orderBy += (f ? "" : ", ") + "B." + quoting.requote(pk.name);
olapOrderBy += (f ? "" : ", ") + "S.B" + j;
++j;
f = false;
}
@@ -3006,8 +3051,6 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
int j = 0;
for (Column pk: rowIdSupport.getPrimaryKey(table, session).getColumns()) {
pkColumnNames.add(quoting.requote(pk.name));
orderBy += (f ? "" : ", ") + "A." + quoting.requote(pk.name);
olapOrderBy += (f ? "" : ", ") + "S.A" + j;
++j;
f = false;
}
@@ -3086,14 +3129,9 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
if (andCond.trim().length() > 0) {
sql += (whereExists ? " and" : " Where") + " (" + ConditionEditor.toMultiLine(andCond) + ")";
}
if (orderBy.length() > 0) {
if (sqlLimitSuffix != null && !useOLAPLimitation) {
sql += " order by " + orderBy;
}
}
olapPrefix += " From (";
if (useOLAPLimitation) {
sql = olapPrefix + sql + olapSuffix + " Order by " + olapOrderBy;
sql = olapPrefix + sql + olapSuffix;
}
if (sqlLimitSuffix != null && !limitSuffixInSelectClause) {
sql += " " + (sqlLimitSuffix.replace("%s", Integer.toString(limit)));
@@ -3552,6 +3590,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if (table != rowsTable) {
column = table.convertColumnIndexToModel(column);
if (column == 0) {
return null;
}
@@ -3924,6 +3963,9 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
if (table == null || table instanceof SqlStatementTable || getQueryBuilderDialog() == null /* SQL Console */) {
return -1;
}
if (association != null && association.isInsertDestinationBeforeSource()) {
return table.getColumns().size() - 1;
}
if (table.primaryKey.getColumns() != null && table.primaryKey.getColumns().size() > 0) {
Column pk = table.primaryKey.getColumns().get(0);
for (int i = 0; i < table.getColumns().size(); ++i) {
@@ -4025,16 +4067,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
java.awt.GridBagConstraints gridBagConstraints;
andCondition = new javax.swing.JComboBox();
jPanel7 = new javax.swing.JPanel();
loadButton = new javax.swing.JButton();
onPanel = new javax.swing.JPanel();
on = new javax.swing.JLabel();
joinPanel = new javax.swing.JPanel();
join = new javax.swing.JLabel();
jLabel6 = new javax.swing.JLabel();
jPanel10 = new javax.swing.JPanel();
from = new javax.swing.JLabel();
jLabel5 = new javax.swing.JLabel();
openEditorLabel = new javax.swing.JLabel();
pendingNonpendingPanel = new javax.swing.JPanel();
cardPanel = new javax.swing.JPanel();
tablePanel = new javax.swing.JPanel();
@@ -4072,10 +4105,20 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
jLabel8 = new javax.swing.JLabel();
jPanel8 = new javax.swing.JPanel();
jLabel11 = new javax.swing.JLabel();
menuPanel = new javax.swing.JPanel();
jPanel7 = new javax.swing.JPanel();
loadButton = new javax.swing.JButton();
onPanel = new javax.swing.JPanel();
on = new javax.swing.JLabel();
joinPanel = new javax.swing.JPanel();
join = new javax.swing.JLabel();
jLabel6 = new javax.swing.JLabel();
jPanel10 = new javax.swing.JPanel();
from = new javax.swing.JLabel();
jLabel5 = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
jLabel4 = new javax.swing.JLabel();
andLabel = new javax.swing.JLabel();
openEditorLabel = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
jPanel3 = new javax.swing.JPanel();
rrPanel = new javax.swing.JPanel();
@@ -4086,103 +4129,15 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
jPanel9 = new javax.swing.JPanel();
dropA = new javax.swing.JLabel();
dropB = new javax.swing.JLabel();
openEditorButton = new javax.swing.JButton();
andCondition.setEditable(true);
andCondition.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
openEditorLabel.setText(" And ");
setLayout(new java.awt.GridBagLayout());
jPanel7.setLayout(new java.awt.GridBagLayout());
loadButton.setText(" Reload ");
loadButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
loadButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
jPanel7.add(loadButton, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 8;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
add(jPanel7, gridBagConstraints);
onPanel.setMinimumSize(new java.awt.Dimension(66, 17));
onPanel.setLayout(new java.awt.BorderLayout());
on.setFont(new java.awt.Font("DejaVu Sans", 0, 13)); // NOI18N
on.setText("jLabel3");
onPanel.add(on, java.awt.BorderLayout.CENTER);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 6;
gridBagConstraints.gridwidth = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
gridBagConstraints.weightx = 1.0;
add(onPanel, gridBagConstraints);
joinPanel.setMinimumSize(new java.awt.Dimension(66, 17));
joinPanel.setLayout(new java.awt.GridBagLayout());
join.setFont(new java.awt.Font("DejaVu Sans", 0, 13)); // NOI18N
join.setText("jLabel3");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
joinPanel.add(join, gridBagConstraints);
jLabel6.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
jLabel6.setText(" as B ");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
joinPanel.add(jLabel6, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 5;
gridBagConstraints.gridwidth = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
gridBagConstraints.weightx = 1.0;
add(joinPanel, gridBagConstraints);
jPanel10.setMinimumSize(new java.awt.Dimension(66, 17));
jPanel10.setLayout(new java.awt.GridBagLayout());
from.setFont(new java.awt.Font("DejaVu Sans", 0, 13)); // NOI18N
from.setText("jLabel3");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
jPanel10.add(from, gridBagConstraints);
jLabel5.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
jLabel5.setText(" as A");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
jPanel10.add(jLabel5, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
add(jPanel10, gridBagConstraints);
pendingNonpendingPanel.setLayout(new java.awt.CardLayout());
cardPanel.setLayout(new java.awt.CardLayout());
@@ -4530,21 +4485,113 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
pendingNonpendingPanel.add(jPanel8, "pending");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 12;
gridBagConstraints.gridwidth = 7;
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
add(pendingNonpendingPanel, gridBagConstraints);
menuPanel.setLayout(new java.awt.GridBagLayout());
jPanel7.setLayout(new java.awt.GridBagLayout());
loadButton.setText(" Reload ");
loadButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
loadButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
jPanel7.add(loadButton, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 8;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
menuPanel.add(jPanel7, gridBagConstraints);
onPanel.setMinimumSize(new java.awt.Dimension(66, 17));
onPanel.setLayout(new java.awt.BorderLayout());
on.setFont(new java.awt.Font("DejaVu Sans", 0, 13)); // NOI18N
on.setText("jLabel3");
onPanel.add(on, java.awt.BorderLayout.CENTER);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 6;
gridBagConstraints.gridwidth = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
gridBagConstraints.weightx = 1.0;
menuPanel.add(onPanel, gridBagConstraints);
joinPanel.setMinimumSize(new java.awt.Dimension(66, 17));
joinPanel.setLayout(new java.awt.GridBagLayout());
join.setFont(new java.awt.Font("DejaVu Sans", 0, 13)); // NOI18N
join.setText("jLabel3");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
joinPanel.add(join, gridBagConstraints);
jLabel6.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
jLabel6.setText(" as B ");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
joinPanel.add(jLabel6, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 5;
gridBagConstraints.gridwidth = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
gridBagConstraints.weightx = 1.0;
menuPanel.add(joinPanel, gridBagConstraints);
jPanel10.setMinimumSize(new java.awt.Dimension(66, 17));
jPanel10.setLayout(new java.awt.GridBagLayout());
from.setFont(new java.awt.Font("DejaVu Sans", 0, 13)); // NOI18N
from.setText("jLabel3");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
jPanel10.add(from, gridBagConstraints);
jLabel5.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
jLabel5.setText(" as A");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
jPanel10.add(jLabel5, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
menuPanel.add(jPanel10, gridBagConstraints);
jLabel1.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
jLabel1.setText(" Join ");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 5;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
add(jLabel1, gridBagConstraints);
menuPanel.add(jLabel1, gridBagConstraints);
jLabel4.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
jLabel4.setText(" On ");
@@ -4553,7 +4600,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
gridBagConstraints.gridy = 6;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
add(jLabel4, gridBagConstraints);
menuPanel.add(jLabel4, gridBagConstraints);
andLabel.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
andLabel.setText(" Where ");
@@ -4561,14 +4608,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 8;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
add(andLabel, gridBagConstraints);
openEditorLabel.setText(" And ");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 8;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
add(openEditorLabel, gridBagConstraints);
menuPanel.add(andLabel, gridBagConstraints);
jLabel3.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
jLabel3.setText(" From ");
@@ -4576,7 +4616,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 4;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
add(jLabel3, gridBagConstraints);
menuPanel.add(jLabel3, gridBagConstraints);
jPanel3.setLayout(new javax.swing.BoxLayout(jPanel3, javax.swing.BoxLayout.LINE_AXIS));
gridBagConstraints = new java.awt.GridBagConstraints();
@@ -4584,7 +4624,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
gridBagConstraints.gridy = 9;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
add(jPanel3, gridBagConstraints);
menuPanel.add(jPanel3, gridBagConstraints);
rrPanel.setLayout(new java.awt.GridBagLayout());
@@ -4632,7 +4672,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
gridBagConstraints.gridheight = 3;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2);
add(rrPanel, gridBagConstraints);
menuPanel.add(rrPanel, gridBagConstraints);
jPanel9.setLayout(new java.awt.GridBagLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
@@ -4641,21 +4681,33 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0);
add(jPanel9, gridBagConstraints);
menuPanel.add(jPanel9, gridBagConstraints);
dropA.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
dropA.setText("drop");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 4;
add(dropA, gridBagConstraints);
menuPanel.add(dropA, gridBagConstraints);
dropB.setFont(new java.awt.Font("DejaVu Sans", 1, 13)); // NOI18N
dropB.setText("drop");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 5;
add(dropB, gridBagConstraints);
menuPanel.add(dropB, gridBagConstraints);
openEditorButton.setText("jButton1");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 8;
menuPanel.add(openEditorButton, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
add(menuPanel, gridBagConstraints);
}// </editor-fold>//GEN-END:initComponents
private void cancelLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelLoadButtonActionPerformed
@@ -4691,9 +4743,16 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
}// GEN-LAST:event_limitBoxItemStateChanged
private void openQueryBuilder(boolean openSQLConsole) {
void openQueryBuilder(boolean openSQLConsole) {
openQueryBuilder(openSQLConsole, null);
}
void openQueryBuilder(boolean openSQLConsole, String alternativeWhere) {
QueryBuilderDialog.Relationship root = createQBRelations(true);
if (root != null) {
if (alternativeWhere != null) {
root.whereClause = alternativeWhere;
}
root.selectColumns = true;
getQueryBuilderDialog().buildQuery(table, root, dataModel, session, getMetaDataSource(), openSQLConsole);
}
@@ -4701,7 +4760,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
// Variables declaration - do not modify//GEN-BEGIN:variables
javax.swing.JComboBox andCondition;
private javax.swing.JLabel andLabel;
javax.swing.JLabel andLabel;
private javax.swing.JButton cancelLoadButton;
private javax.swing.JPanel cardPanel;
private javax.swing.JButton deselectButton;
@@ -4740,13 +4799,15 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
private javax.swing.JLabel loadingCauseLabel;
private javax.swing.JLabel loadingLabel;
private javax.swing.JPanel loadingPanel;
javax.swing.JPanel menuPanel;
private javax.swing.JPanel noRowsFoundPanel;
private javax.swing.JLabel on;
private javax.swing.JPanel onPanel;
private javax.swing.JButton openEditorButton;
private javax.swing.JLabel openEditorLabel;
private javax.swing.JPanel pendingNonpendingPanel;
private javax.swing.JLabel relatedRowsLabel;
private javax.swing.JPanel relatedRowsPanel;
javax.swing.JPanel relatedRowsPanel;
private javax.swing.JButton removeConditionButton;
public javax.swing.JLabel rowsCount;
public javax.swing.JTable rowsTable;
@@ -4760,12 +4821,13 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
private javax.swing.JPanel singleRowViewScrollPaneContainer;
public javax.swing.JCheckBox sortColumnsCheckBox;
private javax.swing.JLabel sqlLabel1;
private javax.swing.JPanel sqlPanel;
javax.swing.JPanel sqlPanel;
private javax.swing.JPanel tablePanel;
// End of variables declaration//GEN-END:variables
JPanel thumbnail;
private ConditionEditor andConditionEditor;
private Icon conditionEditorIcon;
private ImageIcon conditionEditorIcon;
private Icon conditionEditorSelectedIcon;
{
String dir = "/net/sf/jailer/ui/resource";
@@ -4878,7 +4940,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
popup.add(m);
}
UIUtil.fit(popup);
showPopup(label, 0, label.getHeight(), popup);
UIUtil.showPopup(label, 0, label.getHeight(), popup);
}
/**
@@ -4924,7 +4986,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
return null;
}
protected abstract void navigateTo(Association association, int rowIndex, Row row);
protected abstract RowBrowser navigateTo(Association association, int rowIndex, Row row);
protected abstract void onContentChange(List<Row> rows, boolean reloadChildren);
@@ -5232,7 +5294,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
private Map<Table, int[]> pkColumnIndexes = new HashMap<Table, int[]>();
private String[] alternativeColumnLabels;
public void setAlternativeColumnLabels(String[] columnLabels) {
this.alternativeColumnLabels = columnLabels;
}
@@ -5281,7 +5343,7 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
}
}
private static String readCharacterStream(final Reader reader)
throws IOException {
final StringBuilder sb = new StringBuilder();
@@ -5321,15 +5383,6 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
}
private void showPopup(final Component invoker, final int x, final int y, final JPopupMenu popup) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
popup.show(invoker, x, y);
}
});
}
private static String readClob(Clob clob) throws SQLException, IOException {
return readCharacterStream(clob.getCharacterStream());
}
@@ -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,199 +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);
} else {
scrollToTable(table);
}
}
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);
@@ -508,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));
}
@@ -599,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);
}
}
}
@@ -698,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 {
@@ -710,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] = "";
}
@@ -798,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));
}
}
}
}
}
@@ -941,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() {
@@ -967,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();
@@ -979,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());
@@ -1020,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);
}
});
@@ -1032,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;
@@ -1040,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);
}
});
@@ -1112,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;
@@ -1134,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);
@@ -1149,11 +1358,13 @@ public abstract class DBClosureView extends javax.swing.JDialog {
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;
@@ -1164,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
@@ -37,6 +37,10 @@ import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
@@ -88,7 +92,6 @@ import javax.swing.JTree;
import javax.swing.JViewport;
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;
@@ -108,6 +111,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.JDBCMetaDataBasedModelElementFinder;
import net.sf.jailer.modelbuilder.ModelBuilder;
import net.sf.jailer.ui.About;
import net.sf.jailer.ui.AnalyseOptionsDialog;
@@ -127,6 +131,7 @@ import net.sf.jailer.ui.Environment;
import net.sf.jailer.ui.ExtractionModelFrame;
import net.sf.jailer.ui.ImportDialog;
import net.sf.jailer.ui.JComboBox;
import net.sf.jailer.ui.PrivilegedSessionProviderDialog;
import net.sf.jailer.ui.SessionForUI;
import net.sf.jailer.ui.StringSearchPanel;
import net.sf.jailer.ui.UIUtil;
@@ -236,6 +241,22 @@ public class DataBrowser extends javax.swing.JFrame {
tableTreesTabbedPane.setTabComponentAt(0, new JLabel("Navigation", navigationIcon, JLabel.LEFT));
tableTreesTabbedPane.setTabComponentAt(1, new JLabel("Database", databaseIcon, JLabel.LEFT));
tableTreesTabbedPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (createMetaDataPanel != null && tableTreesTabbedPane.getSelectedComponent() == tablesPanel) {
UIUtil.invokeLater(10, new Runnable() {
@Override
public void run() {
if (createMetaDataPanel != null) {
createMetaDataPanel.run();
}
}
});
}
}
});
initialized = true;
tablesComboBox = new JComboBox<String>() {
@@ -287,7 +308,7 @@ public class DataBrowser extends javax.swing.JFrame {
metaDataViewPanel.add(metaDataDetailsPanel);
jLayeredPane1.removeAll();
jLayeredPane1.setLayout(new GridBagLayout());
jLayeredPane1.setLayout(null);
jLayeredPane1.setLayer(layeredPaneContent, JLayeredPane.PALETTE_LAYER);
jLayeredPane1.setLayer(dummy, JLayeredPane.DEFAULT_LAYER);
gridBagConstraints = new GridBagConstraints();
@@ -296,16 +317,106 @@ public class DataBrowser extends javax.swing.JFrame {
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1;
gridBagConstraints.weighty = 1;
jLayeredPane1.add(layeredPaneContent, gridBagConstraints);
jLayeredPane1.add(dummy, gridBagConstraints);
jLayeredPane1.add(layeredPaneContent /*, gridBagConstraints */);
layeredPaneContent.setLocation(0, 0);
// jLayeredPane1.add(dummy /*, gridBagConstraints */);
addComponentListener(new ComponentListener() {
@Override
public void componentShown(ComponentEvent e) {
layeredPaneContent.setSize(jLayeredPane1.getSize());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
desktopSplitPane.setDividerLocation(0.75);
}
});
}
@Override
public void componentResized(ComponentEvent e) {
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
jLayeredPane1.addComponentListener(new ComponentListener() {
@Override
public void componentShown(ComponentEvent e) {
layeredPaneContent.setSize(jLayeredPane1.getSize());
}
@Override
public void componentResized(ComponentEvent e) {
layeredPaneContent.setSize(jLayeredPane1.getSize());
}
@Override
public void componentMoved(ComponentEvent e) {
layeredPaneContent.setSize(jLayeredPane1.getSize());
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1;
gridBagConstraints.weighty = 1;
JPanel anchorPanel = new JPanel(null);
anchorPanel.setOpaque(false);
jLayeredPane1.setLayer(anchorPanel, JLayeredPane.POPUP_LAYER);
jLayeredPane1.add(anchorPanel/* , gridBagConstraints */);
anchorManager = new DesktopAnchorManager(anchorPanel) {
@Override
protected void layout(RowBrowser anchor) {
try {
anchor.internalFrame.setSelected(true);
} catch (PropertyVetoException e) {
// ignore
}
arrangeLayout(true, anchor);
}
@Override
protected boolean isApplicable(RowBrowser tableBrowser) {
if (tableBrowser.parent == null) {
return false;
}
if (desktop.desktopAnimation != null && desktop.desktopAnimation.isActive()) {
return false;
}
RowBrowser visParent = tableBrowser.parent;
while (visParent != null && !visParent.internalFrame.isVisible()) {
visParent = visParent.parent;
}
return visParent != null && Math.abs(tableBrowser.internalFrame.getY() - visParent.internalFrame.getY()) > 2;
}
};
if (jScrollPane1.getVerticalScrollBar() != null) {
jScrollPane1.getVerticalScrollBar().setUnitIncrement(16);
jScrollPane1.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
anchorManager.reset();
}
});
}
if (jScrollPane1.getHorizontalScrollBar() != null) {
jScrollPane1.getHorizontalScrollBar().setUnitIncrement(16);
jScrollPane1.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
anchorManager.reset();
}
});
}
hiddenPanel.setVisible(false);
borderBrowserPanel.add(borderBrowser, java.awt.BorderLayout.CENTER);
@@ -424,7 +535,7 @@ public class DataBrowser extends javax.swing.JFrame {
if (dbConnectionDialog != null) {
createSession(dbConnectionDialog);
}
desktop = new Desktop(this.datamodel, jailerIcon, session, this, dbConnectionDialog, executionContext) {
desktop = new Desktop(this.datamodel, jailerIcon, session, this, dbConnectionDialog, anchorManager, executionContext) {
@Override
public void openSchemaAnalyzer() {
updateDataModel();
@@ -493,6 +604,18 @@ public class DataBrowser extends javax.swing.JFrame {
}
return ROW_LIMIT_DEFAULT;
}
@Override
protected boolean isDesktopVisible() {
return workbenchTabbedPane.getSelectedComponent() == desktopSplitPane;
}
@Override
protected void checkAnchorRetension() {
if (anchorManager != null) {
anchorManager.checkRetention();
}
}
};
jScrollPane1.setViewportView(desktop);
@@ -557,6 +680,7 @@ public class DataBrowser extends javax.swing.JFrame {
if (newY > maxY)
newY = maxY;
jv.setViewPosition(new Point(newX, newY));
DesktopAnimation.stopScrolling = true;
}
}
@@ -568,6 +692,7 @@ public class DataBrowser extends javax.swing.JFrame {
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
m_XDifference = e.getX();
m_YDifference = e.getY();
DesktopAnimation.stopScrolling = true;
}
@Override
@@ -575,7 +700,7 @@ public class DataBrowser extends javax.swing.JFrame {
if (e.getButton() == MouseEvent.BUTTON3) {
return;
}
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
setCursor(null);
}
@Override
@@ -644,7 +769,7 @@ public class DataBrowser extends javax.swing.JFrame {
largeLayoutRadioButtonMenuItemActionPerformed(e);
}
});
showPopup(desktop, e.getX(), e.getY(), popup);
UIUtil.showPopup(desktop, e.getX(), e.getY(), popup);
}
};
@@ -1989,7 +2114,7 @@ public class DataBrowser extends javax.swing.JFrame {
}// GEN-LAST:event_tinyLayoutRadioButtonMenuItemActionPerformed
private void wheelzoomTip() {
TipDialog.showTip(this, "WHEELZOOM", "While holding down the Ctrl-key you can use the mouse-wheel to zoom in or out.");
TipDialog.showTip(this, "WHEELZOOM", "You can use the mouse-wheel to zoom in or out.");
}
private void smallLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_smallLayoutRadioButtonMenuItemActionPerformed
@@ -2035,6 +2160,7 @@ public class DataBrowser extends javax.swing.JFrame {
if (rowBrowser != null) {
desktop.scrollToCenter(rowBrowser.internalFrame);
desktop.getiFrameStateChangeRenderer().onIFrameSelected(rowBrowser.internalFrame);
navigationTree.setSelectionPath(node);
}
}
if (evt.getButton() == MouseEvent.BUTTON3) {
@@ -2043,7 +2169,7 @@ public class DataBrowser extends javax.swing.JFrame {
navigationTree.setSelectionRow(row);
JPopupMenu popup = rowBrowser.browserContentPane.createPopupMenu(null, -1, 0, 0, false);
if (popup != null) {
JPopupMenu popup2 = rowBrowser.browserContentPane.createSqlPopupMenu(null, -1, 0, 0, true);
JPopupMenu popup2 = rowBrowser.browserContentPane.createSqlPopupMenu(null, -1, 0, 0, true, navigationTreeScrollPane);
if (popup2.getComponentCount() > 0 && popup.getComponentCount() > 0) {
popup.add(new JSeparator());
}
@@ -2051,38 +2177,36 @@ public class DataBrowser extends javax.swing.JFrame {
popup.add(c);
}
UIUtil.fit(popup);
showPopup(evt.getComponent(), evt.getX(), evt.getY(), popup);
UIUtil.showPopup(evt.getComponent(), evt.getX(), evt.getY(), popup);
}
}
}
}
}// GEN-LAST:event_navigationTreeMouseClicked
private void showPopup(final Component invoker, final int x, final int y, final JPopupMenu popup) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
popup.show(invoker, x, y);
}
});
}
private void layoutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_layoutMenuItemActionPerformed
arrangeLayout(true);
}// GEN-LAST:event_layoutMenuItemActionPerformed
public void arrangeLayout(boolean scrollToCenter) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
arrangeLayout(scrollToCenter, Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor? null : anchorManager.getNewestBrowser());
anchorManager.setNewestBrowser(null);
}
public void arrangeLayout(boolean scrollToCenter, RowBrowser anchor) {
UIUtil.setWaitCursor(this);
try {
desktop.layoutBrowser(null, scrollToCenter);
desktop.layoutBrowser(null, scrollToCenter, anchor);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}
private void jScrollPane1MouseWheelMoved(java.awt.event.MouseWheelEvent evt) {// GEN-FIRST:event_jScrollPane1MouseWheelMoved
desktop.onMouseWheelMoved(evt);
desktop.onMouseWheelMoved(evt, jScrollPane1);
long currentTime = System.currentTimeMillis();
desktop.startRescaleMode(currentTime, evt);
desktop.onMouseWheelMoved(evt, currentTime);
desktop.onMouseWheelMoved(evt, jScrollPane1, currentTime);
}// GEN-LAST:event_jScrollPane1MouseWheelMoved
private void openNewTableBrowser(boolean offerAlternatives) {
@@ -2204,11 +2328,9 @@ public class DataBrowser extends javax.swing.JFrame {
UIManager.put("InternalFrame:InternalFrameTitlePane[Enabled].textForeground", Color.BLUE);
}
UIUtil.prepareUI();
} catch (Exception x) {
}
ToolTipManager.sharedInstance().setInitialDelay(500);
ToolTipManager.sharedInstance().setDismissDelay(7000);
createFrame();
} catch (Exception e) {
e.printStackTrace();
@@ -2318,6 +2440,8 @@ public class DataBrowser extends javax.swing.JFrame {
private void updateDataModel(String schemaName, boolean withViews, boolean withSynonyms) {
try {
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = new PrivilegedSessionProviderDialog.Provider(this);
List<String> args = new ArrayList<String>();
args.add("build-model-wo-merge");
dbConnectionDialog.addDbArgs(args);
@@ -2328,12 +2452,12 @@ public class DataBrowser extends javax.swing.JFrame {
boolean[] isDefaultSchema = new boolean[1];
String[] defaultSchema = new String[1];
List<String> schemas;
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
try {
CancellationHandler.reset(null);
schemas = dbConnectionDialog.getDBSchemas(defaultSchema);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
if (analyseOptionsDialog.edit(schemas, defaultSchema[0], schemaName == null? null : Quoting.staticUnquote(schemaName), isDefaultSchema, dbConnectionDialog.currentConnection.user)) {
String schema = analyseOptionsDialog.getSelectedSchema();
@@ -2369,6 +2493,7 @@ public class DataBrowser extends javax.swing.JFrame {
UIUtil.showException(this, "Error", e, session);
} finally {
ModelBuilder.assocFilter = null;
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = null;
}
}
@@ -2690,7 +2815,7 @@ public class DataBrowser extends javax.swing.JFrame {
return;
}
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
Collection<AssociationModel> model = new ArrayList<AssociationModel>();
if (desktop != null) {
@@ -2726,7 +2851,7 @@ public class DataBrowser extends javax.swing.JFrame {
borderBrowser.setModel(model);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}
@@ -2745,7 +2870,7 @@ public class DataBrowser extends javax.swing.JFrame {
@Override
public void run() {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(DataBrowser.this);
if (dataModelViewFrame == null) {
dataModelViewFrame = ExtractionModelFrame.createFrame(null, false, false, null, executionContext);
JComponent graphViewContainer = dataModelViewFrame.tearOutGraphViewContainer();
@@ -2781,7 +2906,7 @@ public class DataBrowser extends javax.swing.JFrame {
}
}
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(DataBrowser.this);
}
}
});
@@ -2789,7 +2914,7 @@ public class DataBrowser extends javax.swing.JFrame {
protected void resolveSelection(Collection<AssociationModel> selection) {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
disableBorderBrowserUpdates = true;
JInternalFrame currentSelection = desktop.getSelectedFrame();
@@ -2807,7 +2932,7 @@ public class DataBrowser extends javax.swing.JFrame {
}
}
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
disableBorderBrowserUpdates = false;
updateBorderBrowser();
}
@@ -2898,9 +3023,9 @@ public class DataBrowser extends javax.swing.JFrame {
try {
JInternalFrame iFrame = ((TreeNodeForRowBrowser) userObject).rowBrowser.internalFrame;
desktop.scrollToCenter(iFrame);
desktop.getiFrameStateChangeRenderer().onIFrameSelected(iFrame);
iFrame.setSelected(true);
iFrame.grabFocus();
desktop.getiFrameStateChangeRenderer().onIFrameSelected(iFrame);
} catch (PropertyVetoException e1) {
// ignore
}
@@ -3018,12 +3143,18 @@ public class DataBrowser extends javax.swing.JFrame {
desktop.getiFrameStateChangeRenderer().startAtomic();
disableBorderBrowserUpdates = true;
suppressUpdateClosureBrowser = true;
RowBrowser nextRb = null;
while (i > 0) {
Table table = path.get(i);
RowBrowser rb = getVisibleTables().get(table);
RowBrowser rb;
if (nextRb != null && nextRb.association != null && nextRb.association.destination.equals(table)) {
rb = nextRb;
} else {
rb = getVisibleTables().get(table);
}
Association association = associations[i - 1];
if (association != null) {
rb.browserContentPane.navigateTo(association, -1, null);
nextRb = rb.browserContentPane.navigateTo(association, -1, null);
visibleTables = null;
} else {
break;
@@ -3065,6 +3196,9 @@ public class DataBrowser extends javax.swing.JFrame {
}
private Association[] openAssociationPathPanel(List<Table> path) {
if (path.isEmpty()) {
return null;
}
final AssociationPathPanel assocPanel = new AssociationPathPanel(getDataModel(), path, dependsOn.getForeground(), hasDependent.getForeground(), associatedWith.getForeground(), ignored.getForeground());
if (!assocPanel.needToAsk) {
return assocPanel.selectedAssociations;
@@ -3119,7 +3253,8 @@ public class DataBrowser extends javax.swing.JFrame {
}
private MetaDataPanel metaDataPanel;
private Runnable createMetaDataPanel;
private void onNewSession(Session newSession) {
if (session == null) {
return;
@@ -3128,7 +3263,7 @@ public class DataBrowser extends javax.swing.JFrame {
ConnectionInfo connection = dbConnectionDialog != null ? dbConnectionDialog.currentConnection : null;
String alias = connection != null ? " " + connection.alias : " ";
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
try {
updateNavigationCombobox();
@@ -3150,150 +3285,7 @@ public class DataBrowser extends javax.swing.JFrame {
metaDataViewPanel.remove(metaDataDetailsPanel);
metaDataDetailsPanel = createMetaDataDetailsPanel(executionContext);
metaDataViewPanel.add(metaDataDetailsPanel);
if (metaDataPanel == null) {
metaDataPanel = new MetaDataPanel(this, metaDataSource, metaDataDetailsPanel, datamodel.get(), executionContext) {
@Override
protected void open(Table table) {
if (!selectNavTreeNode(navigationTree.getModel().getRoot(), table)) {
if (workbenchTabbedPane.getSelectedComponent() != getCurrentSQLConsole()) {
desktop.addTableBrowser(null, null, 0, table, null, "", null, true);
}
}
try {
String sql;
Quoting quoting = new Quoting(session);
MDTable mdTable = getMetaDataSource(session).toMDTable(table);
String tableName;
String schemaName;
if (mdTable != null) {
tableName = mdTable.getName();
schemaName = mdTable.getSchema().isDefaultSchema? "": mdTable.getSchema().getName();
} else {
tableName = table.getUnqualifiedName();
schemaName = table.getSchema("");
}
sql = "Select * From " + (schemaName == null || schemaName.length() == 0? "" : quoting.quote(schemaName) + ".") + quoting.quote(tableName);
if (workbenchTabbedPane.getSelectedComponent() == getCurrentSQLConsole()) {
workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole());
getCurrentSQLConsole().grabFocus();
getCurrentSQLConsole().appendStatement(sql, true);
}
} catch (SQLException e) {
UIUtil.showException(this, "Error", e);
}
}
private boolean selectNavTreeNode(Object root, Table table) {
if (root instanceof DefaultMutableTreeNode) {
Object userObject = ((DefaultMutableTreeNode) root).getUserObject();
if (userObject instanceof TreeNodeForRowBrowser) {
RowBrowser rowBrowser = ((TreeNodeForRowBrowser) userObject).rowBrowser;
if (table.equals(rowBrowser.browserContentPane.table)) {
navigationTree.getSelectionModel().setSelectionPath(new TreePath(((DefaultMutableTreeNode) root).getPath()));
return true;
}
}
int cc = ((DefaultMutableTreeNode) root).getChildCount();
for (int i = 0; i < cc; ++i) {
if (selectNavTreeNode(((DefaultMutableTreeNode) root).getChildAt(i), table)) {
return true;
}
}
}
return false;
}
private boolean selectNavTreeNode(Object root, MDTable mdTable) {
if (root instanceof DefaultMutableTreeNode) {
Object userObject = ((DefaultMutableTreeNode) root).getUserObject();
if (userObject instanceof TreeNodeForRowBrowser) {
RowBrowser rowBrowser = ((TreeNodeForRowBrowser) userObject).rowBrowser;
if (mdTable.equals(rowBrowser.getMDTable())) {
navigationTree.getSelectionModel().setSelectionPath(new TreePath(((DefaultMutableTreeNode) root).getPath()));
return true;
}
}
int cc = ((DefaultMutableTreeNode) root).getChildCount();
for (int i = 0; i < cc; ++i) {
if (selectNavTreeNode(((DefaultMutableTreeNode) root).getChildAt(i), mdTable)) {
return true;
}
}
}
return false;
}
@Override
protected void analyseSchema(String schemaName) {
updateDataModel(schemaName, false, false);
}
@Override
protected void open(MDTable mdTable) {
String schemaName = mdTable.getSchema().isDefaultSchema? null : mdTable.getSchema().getName();
String tableName = mdTable.getName();
try {
Quoting quoting = new Quoting(session);
String sql = "Select * From " + (schemaName == null? "" : quoting.quote(schemaName) + ".") + quoting.quote(tableName);
if (!selectNavTreeNode(navigationTree.getModel().getRoot(), mdTable)
|| workbenchTabbedPane.getSelectedComponent() == getCurrentSQLConsole()) {
workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole());
getCurrentSQLConsole().grabFocus();
getCurrentSQLConsole().appendStatement(sql, true);
}
} catch (SQLException e) {
UIUtil.showException(this, "Error", e);
}
}
@Override
protected void appendScript(String script, boolean execute) {
try {
workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole());
getCurrentSQLConsole().grabFocus();
getCurrentSQLConsole().appendStatement(script, execute);
} catch (Throwable e) {
UIUtil.showException(this, "Error", e);
}
}
@Override
protected void onTableSelect(MDTable mdTable) {
metaDataDetailsPanel
.showMetaDataDetails(mdTable, getMetaDataSource(session).toTable(mdTable), datamodel.get());
}
@Override
protected void onMDOtherSelect(MDGeneric mdOther, ExecutionContext executionContext) {
metaDataDetailsPanel
.showMetaDataDetails(mdOther, executionContext);
}
@Override
protected void onSchemaSelect(MDSchema mdSchema) {
metaDataDetailsPanel.clear();
}
@Override
protected void openNewTableBrowser() {
DataBrowser.this.openNewTableBrowser(false);
}
@Override
protected void updateDataModelView(Table table) {
DataBrowser.this.updateDataModelView(table);
}
@Override
protected void setCaretPosition(int position) {
getCurrentSQLConsole().setCaretPosition(position);
}
};
}
session.setSessionProperty(getClass(), "metaDataPanel", metaDataPanel);
tablesPanel.add(metaDataPanel, java.awt.BorderLayout.CENTER);
try {
if (sqlConsoles.isEmpty()) {
createNewSQLConsole(metaDataSource);
@@ -3306,9 +3298,163 @@ public class DataBrowser extends javax.swing.JFrame {
} catch (SQLException e) {
e.printStackTrace();
}
final MetaDataSource fMetaDataSource = metaDataSource;
createMetaDataPanel = new Runnable() {
@Override
public void run() {
if (metaDataPanel == null) {
metaDataPanel = new MetaDataPanel(DataBrowser.this, fMetaDataSource, metaDataDetailsPanel, datamodel.get(), executionContext) {
@Override
protected void open(Table table) {
if (!selectNavTreeNode(navigationTree.getModel().getRoot(), table)) {
if (workbenchTabbedPane.getSelectedComponent() != getCurrentSQLConsole()) {
desktop.addTableBrowser(null, null, 0, table, null, "", null, true);
}
}
try {
String sql;
Quoting quoting = new Quoting(session);
MDTable mdTable = getMetaDataSource(session).toMDTable(table);
String tableName;
String schemaName;
if (mdTable != null) {
tableName = mdTable.getName();
schemaName = mdTable.getSchema().isDefaultSchema? "": mdTable.getSchema().getName();
} else {
tableName = table.getUnqualifiedName();
schemaName = table.getSchema("");
}
sql = "Select * From " + (schemaName == null || schemaName.length() == 0? "" : quoting.quote(schemaName) + ".") + quoting.quote(tableName);
if (workbenchTabbedPane.getSelectedComponent() == getCurrentSQLConsole()) {
workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole());
getCurrentSQLConsole().grabFocus();
getCurrentSQLConsole().appendStatement(sql, true);
}
} catch (SQLException e) {
UIUtil.showException(this, "Error", e);
}
}
private boolean selectNavTreeNode(Object root, Table table) {
if (root instanceof DefaultMutableTreeNode) {
Object userObject = ((DefaultMutableTreeNode) root).getUserObject();
if (userObject instanceof TreeNodeForRowBrowser) {
RowBrowser rowBrowser = ((TreeNodeForRowBrowser) userObject).rowBrowser;
if (table.equals(rowBrowser.browserContentPane.table)) {
navigationTree.getSelectionModel().setSelectionPath(new TreePath(((DefaultMutableTreeNode) root).getPath()));
return true;
}
}
int cc = ((DefaultMutableTreeNode) root).getChildCount();
for (int i = 0; i < cc; ++i) {
if (selectNavTreeNode(((DefaultMutableTreeNode) root).getChildAt(i), table)) {
return true;
}
}
}
return false;
}
private boolean selectNavTreeNode(Object root, MDTable mdTable) {
if (root instanceof DefaultMutableTreeNode) {
Object userObject = ((DefaultMutableTreeNode) root).getUserObject();
if (userObject instanceof TreeNodeForRowBrowser) {
RowBrowser rowBrowser = ((TreeNodeForRowBrowser) userObject).rowBrowser;
if (mdTable.equals(rowBrowser.getMDTable())) {
navigationTree.getSelectionModel().setSelectionPath(new TreePath(((DefaultMutableTreeNode) root).getPath()));
return true;
}
}
int cc = ((DefaultMutableTreeNode) root).getChildCount();
for (int i = 0; i < cc; ++i) {
if (selectNavTreeNode(((DefaultMutableTreeNode) root).getChildAt(i), mdTable)) {
return true;
}
}
}
return false;
}
@Override
protected void analyseSchema(String schemaName) {
updateDataModel(schemaName, false, false);
}
@Override
protected void open(MDTable mdTable) {
String schemaName = mdTable.getSchema().isDefaultSchema? null : mdTable.getSchema().getName();
String tableName = mdTable.getName();
try {
Quoting quoting = new Quoting(session);
String sql = "Select * From " + (schemaName == null? "" : quoting.quote(schemaName) + ".") + quoting.quote(tableName);
if (!selectNavTreeNode(navigationTree.getModel().getRoot(), mdTable)
|| workbenchTabbedPane.getSelectedComponent() == getCurrentSQLConsole()) {
workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole());
getCurrentSQLConsole().grabFocus();
getCurrentSQLConsole().appendStatement(sql, true);
}
} catch (SQLException e) {
UIUtil.showException(this, "Error", e);
}
}
@Override
protected void appendScript(String script, boolean execute) {
try {
workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole());
getCurrentSQLConsole().grabFocus();
getCurrentSQLConsole().appendStatement(script, execute);
} catch (Throwable e) {
UIUtil.showException(this, "Error", e);
}
}
@Override
protected void onTableSelect(MDTable mdTable) {
metaDataDetailsPanel
.showMetaDataDetails(mdTable, getMetaDataSource(session).toTable(mdTable), datamodel.get());
}
@Override
protected void onMDOtherSelect(MDGeneric mdOther, ExecutionContext executionContext) {
metaDataDetailsPanel
.showMetaDataDetails(mdOther, executionContext);
}
@Override
protected void onSchemaSelect(MDSchema mdSchema) {
metaDataDetailsPanel.clear();
}
@Override
protected void openNewTableBrowser() {
DataBrowser.this.openNewTableBrowser(false);
}
@Override
protected void updateDataModelView(Table table) {
DataBrowser.this.updateDataModelView(table);
}
@Override
protected void setCaretPosition(int position) {
getCurrentSQLConsole().setCaretPosition(position);
}
};
}
session.setSessionProperty(getClass(), "metaDataPanel", metaDataPanel);
tablesPanel.add(metaDataPanel, java.awt.BorderLayout.CENTER);
createMetaDataPanel = null;
}
};
if (tableTreesTabbedPane.getSelectedComponent() == tablesPanel) {
createMetaDataPanel.run();
}
}
finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}
@@ -3326,17 +3472,23 @@ public class DataBrowser extends javax.swing.JFrame {
@Override
protected void refreshMetaData() {
metaDataPanel.reset();
if (metaDataPanel != null) {
metaDataPanel.reset();
}
}
@Override
protected void selectTable(MDTable mdTable) {
metaDataPanel.select(mdTable);
if (metaDataPanel != null) {
metaDataPanel.select(mdTable);
}
}
@Override
protected void setOutlineTables(List<OutlineInfo> outlineTables, int indexOfInfoAtCaret) {
metaDataPanel.setOutline(outlineTables, indexOfInfoAtCaret);
if (metaDataPanel != null) {
metaDataPanel.setOutline(outlineTables, indexOfInfoAtCaret);
}
}
@Override
@@ -3474,12 +3626,12 @@ public class DataBrowser extends javax.swing.JFrame {
}
}
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
createNewSQLConsole(getMetaDataSource()).loadFromFile(file);
} catch (Throwable e) {
UIUtil.showException(this, "Error", e, session);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}
@@ -3490,12 +3642,12 @@ public class DataBrowser extends javax.swing.JFrame {
saveScriptAsMenuItemActionPerformed(evt);
} else {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
sqlConsole.storeToFile(null);
} catch (Throwable e) {
UIUtil.showException(this, "Error", e, session);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}
}
@@ -3508,12 +3660,12 @@ public class DataBrowser extends javax.swing.JFrame {
if (fName != null) {
File file = new File(fName);
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
UIUtil.setWaitCursor(this);
sqlConsole.storeToFile(file);
} catch (Throwable e) {
UIUtil.showException(this, "Error", e, session);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
UIUtil.resetWaitCursor(this);
}
}
}
@@ -3659,7 +3811,9 @@ public class DataBrowser extends javax.swing.JFrame {
});
}
private DesktopAnchorManager anchorManager;
private ImageIcon tableIcon;
private ImageIcon databaseIcon;
private ImageIcon redIcon;
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();
}
}
@@ -39,7 +39,7 @@ import net.sf.jailer.ui.UIUtil;
*/
public class DesktopIFrameStateChangeRenderer {
private final double DURATION = 1000.0;
private final double DURATION = 1500.0;
private List<JInternalFrame> atomicBlock = null;
private class StateChange {
@@ -70,16 +70,23 @@ public class DesktopIFrameStateChangeRenderer {
onIFrameSelected(iFrame, 0);
}
public void onIFrameSelected(JInternalFrame iFrame, double factorOffset) {
public void onIFrameSelected(final JInternalFrame iFrame, final double factorOffset) {
if (atomicBlock == null) {
StateChange stateChange = new StateChange();
stateChange.iFrame = iFrame;
stateChange.startTime = System.currentTimeMillis();
stateChange.factorOffset = factorOffset;
stateChanges.put(iFrame, stateChange);
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();
@@ -94,25 +101,27 @@ public class DesktopIFrameStateChangeRenderer {
factor = 0;
}
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);
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);
}
}
}
@@ -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;
@@ -132,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();
}
});
}
@@ -158,7 +158,8 @@ 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;
@@ -167,7 +168,7 @@ public abstract class DetailsView extends javax.swing.JPanel {
labels.clear();
labelColors.clear();
JPanel oldContent = content;
final JPanel oldContent = content;
content = new JPanel(new GridBagLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.weightx = 1;
@@ -271,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);
}
@@ -370,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
@@ -412,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());
}
}
@@ -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) {
@@ -262,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() {
@@ -365,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);
}
}
});
@@ -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;
@@ -71,7 +72,11 @@ public class ResultSetRenderer extends javax.swing.JPanel {
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();
@@ -140,7 +145,7 @@ public class ResultSetRenderer extends javax.swing.JPanel {
this.limit = limit;
rowsTableScrollPane.setWheelScrollingEnabled(true);
rowsCount.setVisible(false);
}
}
@Override
protected int getReloadLimit() {
if (limit == null) {
@@ -174,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() {
@@ -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) {
}
}
@@ -115,6 +115,7 @@ public class ColumnsTable extends JTable {
setRowSelectionAllowed(true);
setColumnSelectionAllowed(true);
setCellSelectionEnabled(true);
// getTableHeader().setReorderingAllowed(false);
setShowGrid(false);
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
setModel(cDm);
@@ -223,7 +224,7 @@ public class ColumnsTable extends JTable {
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
@@ -244,7 +245,7 @@ public class ColumnsTable extends JTable {
}
}
}
});
}, 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) {
@@ -562,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;
@@ -781,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;
}
};
}
@@ -875,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) {
@@ -863,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);
}
});
@@ -901,8 +913,19 @@ public abstract class SQLConsole extends javax.swing.JPanel {
}
}
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());
}
@@ -1000,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 {
@@ -1016,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>();
@@ -1547,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
@@ -1609,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() {
@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -5,6 +5,7 @@ import java.awt.event.MouseListener;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public abstract class SmallButton extends JLabel {
@@ -14,7 +15,9 @@ public abstract class SmallButton extends JLabel {
addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
onClick();
if (SwingUtilities.isLeftMouseButton(e)) {
onClick();
}
}
@Override
public void mousePressed(MouseEvent e) {
@@ -29,7 +32,9 @@ public abstract class SmallButton extends JLabel {
}
@Override
public void mouseClicked(MouseEvent e) {
onClick();
if (SwingUtilities.isLeftMouseButton(e)) {
onClick();
}
}
});
}
@@ -49,7 +49,6 @@ public class UpdateInfoManager {
}
}
System.setProperty("java.net.useSystemProxies", "true");
URI uri = new URI(versionURL);
URLConnection connection = uri.toURL().openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
@@ -63,17 +62,19 @@ public class UpdateInfoManager {
return;
}
}
Thread.sleep(DELAY);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(lastTSFile));
out.writeLong(System.currentTimeMillis());
out.close();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
infoLabel.setText("Release " + versions[0].trim() + " available");
ui.setVisible(true);
}
});
if (isValid(versions[0].trim())) {
Thread.sleep(DELAY);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(lastTSFile));
out.writeLong(System.currentTimeMillis());
out.close();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
infoLabel.setText("Release " + versions[0].trim() + " available");
ui.setVisible(true);
}
});
}
}
} catch (Throwable t) {
// ignore
@@ -85,6 +86,10 @@ public class UpdateInfoManager {
checkThread.start();
}
private static boolean isValid(String version) {
return version.matches("\\d+\\.\\d+(\\.\\d+)?");
}
public static void download() {
try {
URI uri = new URI(downloadURL);
@@ -93,4 +98,5 @@ public class UpdateInfoManager {
e.printStackTrace();
}
}
}