mirror of
https://github.com/Wisser/Jailer.git
synced 2026-05-15 12:08:24 -05:00
Compare commits
169 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| acd0ec4f17 | |||
| a4ef8ac522 | |||
| 0bb4e9f649 | |||
| da1e4ccd2a | |||
| cecf7d33b8 | |||
| 95951cf824 | |||
| e1c7f5074f | |||
| 408ecfc5fc | |||
| 971a870e51 | |||
| 25cedf87d0 | |||
| b750d45050 | |||
| 97b435aa1b | |||
| 40aa392935 | |||
| 0046ef0f2d | |||
| 5eb5677799 | |||
| 03a2bf820e | |||
| 6592f0f86f | |||
| efd799b217 | |||
| 7c0ce25871 | |||
| d0b1465177 | |||
| e7e9634768 | |||
| 3a95e5e86c | |||
| 40b56a2f0f | |||
| 9ae5037037 | |||
| b217529023 | |||
| 108791f0b4 | |||
| 3934482984 | |||
| 7efa9721c9 | |||
| 78977fde51 | |||
| 40d80f6ae1 | |||
| 0bf59e8340 | |||
| 1099d41e68 | |||
| cf52be38ec | |||
| a0db0e8387 | |||
| a48b4faba1 | |||
| 75e2b1164c | |||
| 253032ba92 | |||
| 20da29b810 | |||
| 7b12c5df99 | |||
| 2e487cd77a | |||
| c0d097e8ea | |||
| 42c7f60ac6 | |||
| 3683debe1e | |||
| 1026bab646 | |||
| 8a0ef29cda | |||
| 029459a9d5 | |||
| 9bd30aef3e | |||
| 17161ed441 | |||
| 0a1c74b8d0 | |||
| 67a0f71a31 | |||
| a72e7fdb20 | |||
| ae60ccd0fc | |||
| d9ff02d0d9 | |||
| 09be36cade | |||
| e50d88ddfe | |||
| 7146e61013 | |||
| 67e552a7a1 | |||
| 5a48e73bc1 | |||
| cd838a2858 | |||
| 5a2ce2eac8 | |||
| 68ddf0a175 | |||
| e389c53861 | |||
| 9ee90fc714 | |||
| c2c04ab1fb | |||
| e3093b9593 | |||
| 971613186f | |||
| 3463fb4766 | |||
| 282c1cd180 | |||
| 3a1f98c7bd | |||
| e1b0c23404 | |||
| 07f25822d5 | |||
| 3d03b1227a | |||
| 1d7806f96d | |||
| dc5992e0e5 | |||
| c9f53810d1 | |||
| 051d24e1b1 | |||
| 7ae893da24 | |||
| ed913077c7 | |||
| f35c5b0329 | |||
| 33262683f1 | |||
| 40a6d7d853 | |||
| aded0c6529 | |||
| db972ee841 | |||
| 1f3e0182c9 | |||
| aaaa07b381 | |||
| d26423bf9f | |||
| 09bc381a4e | |||
| 8f5147f870 | |||
| e367fc6062 | |||
| 395b447f86 | |||
| 0ed829c065 | |||
| 9c85f3955e | |||
| 2a379b8543 | |||
| d00acf3881 | |||
| ce3c3192e9 | |||
| 29cbd7dcf9 | |||
| f92e7d6f13 | |||
| 6c55ea8092 | |||
| b2ce10891f | |||
| d86866758b | |||
| f3224ad625 | |||
| 5b391b85b7 | |||
| 8a8cd325b1 | |||
| c1a885f220 | |||
| 2fa811b6c6 | |||
| 3bfc6aa51d | |||
| 322c830054 | |||
| 29e460f79f | |||
| 0254c26e09 | |||
| c37064be01 | |||
| 92bc5b3ef9 | |||
| 6a99fd76a6 | |||
| a584fa787b | |||
| 8e08a70e21 | |||
| b72802c67c | |||
| 04a5df43e8 | |||
| 1518e02736 | |||
| 9e2a04abd1 | |||
| d8bf797c16 | |||
| 2778b8d843 | |||
| 5bc07beffa | |||
| c85fddde8e | |||
| 2a2b0fbe60 | |||
| 7b7bfc289a | |||
| 830a37f55e | |||
| b2ae7d6d79 | |||
| 384411c2eb | |||
| fff9e21a2b | |||
| d663e19099 | |||
| 92956ee4bd | |||
| 08d12c7b6f | |||
| 9462a21513 | |||
| c40fb7c739 | |||
| 4b57dcc48a | |||
| a6b65a2981 | |||
| 82d4f7778f | |||
| 277afba7e7 | |||
| 528c3f83c6 | |||
| edb946cd81 | |||
| bf414de46b | |||
| c6d6997dfc | |||
| 2d69a07943 | |||
| 754d873f47 | |||
| 8cf01ea83e | |||
| b151191696 | |||
| 8dd427af95 | |||
| c9de663911 | |||
| 4378e59a1b | |||
| 80671e3802 | |||
| d624142787 | |||
| 56527be4db | |||
| 694b436b50 | |||
| 0723d007aa | |||
| 3241853eb2 | |||
| 6f809bc67a | |||
| 6d9adac372 | |||
| bb3c8b04a1 | |||
| ec2213d474 | |||
| 1e8a688e8e | |||
| 3b038ce89c | |||
| 0f43a9ed61 | |||
| 17cdae8737 | |||
| 168aacaf3d | |||
| 21b1ef0307 | |||
| ddd700cdca | |||
| de5bea6073 | |||
| 1107806610 | |||
| 2b584b224d | |||
| 54960ad2d7 |
+25
-17
@@ -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>
|
||||
|
||||
Binary file not shown.
+2
-2
@@ -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
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,56 @@
|
||||
8.0.1
|
||||
- Foreign key columns can be set to null if parent row is not exported.
|
||||
- Increased responsiveness and performance of the data browser GUI.
|
||||
|
||||
8.0
|
||||
- The new "PathFinder" feature allows elaborate finding
|
||||
of association paths between tables in complex data models.
|
||||
|
||||
7.11.1
|
||||
- Closing a root table did not work properly in the data browser.
|
||||
- Minor bug fixes.
|
||||
|
||||
7.11
|
||||
- Database analysis not only finds primary keys and foreign keys for tables,
|
||||
but also for views and synonyms by analyzing the underlying tables.
|
||||
- Fixed a memory leak in data browser.
|
||||
|
||||
7.10.8
|
||||
- Data browser improvements
|
||||
- New layout feature: "align table horizontally with predecessor"
|
||||
- Improved layout strategy in the data browser.
|
||||
- Improved row-to-row-link rendering performance.
|
||||
- Feature Request "Improve the usability of the Data Model Editor" (partially). see https://sourceforge.net/p/jailer/feature-requests/43/
|
||||
|
||||
7.10.7
|
||||
- Zoom in / out using the mouse wheel in the data browser
|
||||
|
||||
7.10.6
|
||||
- Minor bug fixes.
|
||||
|
||||
7.10.5
|
||||
- Animated desktop layout in the data browser.
|
||||
- Improved row-link rendering quality and performance.
|
||||
|
||||
7.10.4
|
||||
- The estimated number of rows of the tables is displayed.
|
||||
- Limited fetch size of statements to prevent an OOM exception when the default fetch size is too large (MySQL).
|
||||
- Updated H2 DBMS from version 1.3.160 to 1.3.175
|
||||
|
||||
7.10.3
|
||||
- Fix for "Can't connect to SOCKS proxy:http" https://github.com/Wisser/Jailer/issues/8
|
||||
|
||||
7.10.2
|
||||
- Added context menu to columns view of results table.
|
||||
|
||||
7.10
|
||||
- Comprehensive usability improvements of the data browser.
|
||||
- Animated row-to-row links.
|
||||
- Increased rendering quality of row-to-row link.
|
||||
- Automatic layouting of data browser desktop.
|
||||
- Using working-table-scope "LOCAL_DATABASE" led to concurrency problems and connection leaks.
|
||||
- Update of SQL keyword catalog to SQL 2003 standard.
|
||||
|
||||
7.9.3
|
||||
- Data browser: prevented that context menu automatically gets closed if the item doesn't have the focus.
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public class ExecutionContext {
|
||||
this.importFilterMappingTableSchema = other.importFilterMappingTableSchema;
|
||||
this.scope = other.scope;
|
||||
this.rawparameters = other.rawparameters;
|
||||
this.progressListenerRegistry = other.progressListenerRegistry;
|
||||
// don't share progressListenerRegistry, was: this.progressListenerRegistry = other.progressListenerRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,7 +639,7 @@ public class ExecutionContext {
|
||||
}
|
||||
|
||||
private URL datamodelURL;
|
||||
|
||||
|
||||
/**
|
||||
* Gets URL of the current data model (the datamodels base folder)
|
||||
*/
|
||||
@@ -652,14 +652,14 @@ public class ExecutionContext {
|
||||
fn = datamodelFolder + File.separator + currentModelSubfolder;
|
||||
}
|
||||
try {
|
||||
datamodelURL = new File(fn).toURI().toURL();
|
||||
return new File(fn).toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return datamodelURL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets URL of the current data model (the datamodels base folder)
|
||||
*/
|
||||
@@ -815,4 +815,4 @@ public class ExecutionContext {
|
||||
return map == null? null : new HashMap<String, String>(map);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,6 @@ public class Jailer {
|
||||
*/
|
||||
public static boolean jailerMain(String[] args, StringBuffer warnings, ProgressListener progressListener) throws Exception {
|
||||
CancellationHandler.reset(null);
|
||||
Session.closeTemporaryTableSession();
|
||||
|
||||
try {
|
||||
CommandLine commandLine = CommandLineParser.parse(args, false);
|
||||
@@ -268,8 +267,6 @@ public class Jailer {
|
||||
String workingDirectory = System.getProperty("user.dir");
|
||||
_log.error("working directory is " + workingDirectory);
|
||||
throw e;
|
||||
} finally {
|
||||
Session.closeTemporaryTableSession();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public class JailerVersion {
|
||||
/**
|
||||
* The Jailer version.
|
||||
*/
|
||||
public static final String VERSION = "7.9.3";
|
||||
public static final String VERSION = "8.0.1";
|
||||
|
||||
/**
|
||||
* The Jailer working tables version.
|
||||
|
||||
@@ -42,7 +42,7 @@ public class APIExample {
|
||||
new BasicDataSource(
|
||||
"org.h2.Driver", "jdbc:h2:demo-scott", "sa", "",
|
||||
POOL_SIZE,
|
||||
new File("lib/h2-1.3.160.jar")),
|
||||
new File("lib/h2-1.3.175.jar")),
|
||||
null,
|
||||
APIExample.class.getResource("Demo-Scott"),
|
||||
APIExample.class.getResource("Demo-Scott.csv"),
|
||||
@@ -54,7 +54,7 @@ public class APIExample {
|
||||
new BasicDataSource(
|
||||
"org.h2.Driver", "jdbc:h2:demo-scott-subset", "sa", "",
|
||||
10,
|
||||
new File("lib/h2-1.3.160.jar")));
|
||||
new File("lib/h2-1.3.175.jar")));
|
||||
|
||||
/**
|
||||
* Exports data related with employee "SCOTT"
|
||||
|
||||
@@ -113,6 +113,17 @@ public class Configuration {
|
||||
|
||||
private int columnsPerIFMTable = 8;
|
||||
|
||||
|
||||
private String additionalSQLKeywords;
|
||||
|
||||
public String getAdditionalSQLKeywords() {
|
||||
return additionalSQLKeywords;
|
||||
}
|
||||
|
||||
public void setAdditionalSQLKeywords(String additionalSQLKeywords) {
|
||||
this.additionalSQLKeywords = additionalSQLKeywords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets replacement for null in DBUnit datasets.
|
||||
*
|
||||
@@ -238,5 +249,4 @@ public class Configuration {
|
||||
static {
|
||||
DBMS.values(); // trigger static init
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -104,6 +104,9 @@ public class DBMS {
|
||||
this.rowidName = other.rowidName;
|
||||
this.supportsSchemasInIndexDefinitions = other.supportsSchemasInIndexDefinitions;
|
||||
this.useInlineViewsInDataBrowser = other.useInlineViewsInDataBrowser;
|
||||
this.viewTextOrDDLQuery = other.viewTextOrDDLQuery;
|
||||
this.synonymTableQuery = other.synonymTableQuery;
|
||||
this.estimatedRowCountQuery = other.estimatedRowCountQuery;
|
||||
this.virtualColumnsQuery = other.virtualColumnsQuery;
|
||||
this.userDefinedColumnsQuery = other.userDefinedColumnsQuery;
|
||||
this.importedKeysQuery = other.importedKeysQuery;
|
||||
@@ -291,12 +294,12 @@ public class DBMS {
|
||||
private Boolean supportsSchemasInIndexDefinitions = null;
|
||||
private boolean useInlineViewsInDataBrowser = true;
|
||||
private String virtualColumnsQuery = null;
|
||||
private String synonymTableQuery;
|
||||
private String viewTextOrDDLQuery = "SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%1$s' and TABLE_NAME = '%2$s'";
|
||||
private String estimatedRowCountQuery = null;
|
||||
private String userDefinedColumnsQuery = null;
|
||||
|
||||
private String importedKeysQuery = null;
|
||||
|
||||
private String primaryKeysQuery = null;
|
||||
|
||||
private String indexInfoQuery = null;
|
||||
private String identifierQuoteString = "\"";
|
||||
|
||||
@@ -520,7 +523,11 @@ public class DBMS {
|
||||
public Map<String, String> getTypeReplacement() {
|
||||
if (!this.equals(DBMS.ORACLE)) {
|
||||
if (typeReplacement == null || !typeReplacement.containsKey("VARCHAR2")) {
|
||||
typeReplacement = new HashMap<String, String>(typeReplacement);
|
||||
if (typeReplacement == null) {
|
||||
typeReplacement = new HashMap<String, String>();
|
||||
} else {
|
||||
typeReplacement = new HashMap<String, String>(typeReplacement);
|
||||
}
|
||||
typeReplacement.put("VARCHAR2", "VARCHAR");
|
||||
}
|
||||
}
|
||||
@@ -1007,6 +1014,42 @@ public class DBMS {
|
||||
this.constraintsQuery = constraintsQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets query to get row count.
|
||||
*/
|
||||
public String getEstimatedRowCountQuery() {
|
||||
return estimatedRowCountQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets query to get row count.
|
||||
*/
|
||||
public void setEstimatedRowCountQuery(String estimatedRowCountQuery) {
|
||||
this.estimatedRowCountQuery = estimatedRowCountQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets query to get view text.
|
||||
*/
|
||||
public String getViewTextOrDDLQuery() {
|
||||
return viewTextOrDDLQuery;
|
||||
}
|
||||
|
||||
public void setViewTextOrDDLQuery(String viewTextOrDDLQuery) {
|
||||
this.viewTextOrDDLQuery = viewTextOrDDLQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets query to get underlying table of a synonym.
|
||||
*/
|
||||
public String getSynonymTableQuery() {
|
||||
return synonymTableQuery;
|
||||
}
|
||||
|
||||
public void setSynonymTableQuery(String synonymTableQuery) {
|
||||
this.synonymTableQuery = synonymTableQuery;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,7 @@ public class LocalDatabaseConfiguration {
|
||||
private String password = "";
|
||||
|
||||
private String driver = "org.h2.Driver";
|
||||
private String lib = "lib/h2-1.3.160.jar";
|
||||
private String lib = "lib/h2-1.3.175.jar";
|
||||
|
||||
/**
|
||||
* @return the localPKType
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<!-- Configuration of the local database -->
|
||||
<localDatabase>
|
||||
<databaseFolder>local</databaseFolder>
|
||||
<lib>lib/h2-1.3.160.jar</lib>
|
||||
<lib>lib/h2-1.3.175.jar</lib>
|
||||
<driver>org.h2.Driver</driver>
|
||||
<urlPattern>jdbc:h2:%s;LOG=0;UNDO_LOG=0</urlPattern>
|
||||
<localPKType>VARCHAR</localPKType>
|
||||
@@ -43,6 +43,9 @@
|
||||
<maxDepth>0</maxDepth>
|
||||
<outputFolder>render</outputFolder>
|
||||
</renderer>
|
||||
|
||||
<!-- additional SQL keywords -->
|
||||
<additionalSQLKeywords>sensitive, datetime</additionalSQLKeywords>
|
||||
|
||||
<!-- for Oracle -->
|
||||
<dbms>
|
||||
@@ -60,12 +63,6 @@
|
||||
<key>CatalogOptions</key>
|
||||
<value>0</value>
|
||||
</entry>
|
||||
<!--
|
||||
<entry>
|
||||
<key>includeSynonyms</key>
|
||||
<value>true</value>
|
||||
</entry>
|
||||
-->
|
||||
</jdbcProperties>
|
||||
<statisticRenovator>
|
||||
<scriptFileName>script/oracle/gatherStatistics.sql</scriptFileName>
|
||||
@@ -108,6 +105,7 @@
|
||||
<rowidName>ROWID</rowidName>
|
||||
<rowidType>ROWID</rowidType>
|
||||
<useInlineViewsInDataBrowser>false</useInlineViewsInDataBrowser>
|
||||
<estimatedRowCountQuery>select TABLE_NAME, NUM_ROWS from all_tables where OWNER = '%s'</estimatedRowCountQuery>
|
||||
<virtualColumnsQuery>SELECT TABLE_NAME, COLUMN_NAME FROM ALL_TAB_COLS WHERE OWNER = '${SCHEMA}' AND VIRTUAL_COLUMN = 'YES' AND NOT DATA_TYPE = 'XMLTYPE'</virtualColumnsQuery>
|
||||
<importedKeysQuery>SELECT null, c_dest.OWNER, c_dest.TABLE_NAME, c_dest.COLUMN_NAME, null, c_src.OWNER, c_src.TABLE_NAME, c_src.COLUMN_NAME, c_src.POSITION, null, null, c_list.CONSTRAINT_NAME, c_list.R_CONSTRAINT_NAME, null FROM ALL_CONSTRAINTS c_list, ALL_CONS_COLUMNS c_src, ALL_CONS_COLUMNS c_dest WHERE c_list.CONSTRAINT_NAME = c_src.CONSTRAINT_NAME AND c_list.OWNER = c_src.OWNER AND c_list.R_CONSTRAINT_NAME = c_dest.CONSTRAINT_NAME AND c_list.R_OWNER = c_dest.OWNER AND c_list.CONSTRAINT_TYPE = 'R' AND c_src.POSITION = c_dest.POSITION AND c_src.OWNER = '${SCHEMA}' ORDER BY c_src.POSITION</importedKeysQuery>
|
||||
<primaryKeysQuery>SELECT null, c_src.OWNER, c_src.TABLE_NAME, c_src.COLUMN_NAME, c_src.POSITION, c_list.CONSTRAINT_NAME FROM ALL_CONSTRAINTS c_list, ALL_CONS_COLUMNS c_src WHERE c_list.CONSTRAINT_NAME = c_src.CONSTRAINT_NAME AND c_list.OWNER = c_src.OWNER AND c_list.CONSTRAINT_TYPE = 'P' AND c_list.CONSTRAINT_NAME not like 'BIN$%' AND c_src.OWNER = '${SCHEMA}' ORDER BY c_src.POSITION</primaryKeysQuery>
|
||||
@@ -117,6 +115,8 @@
|
||||
<explainPrepare>explain plan set statement_id = '%2$s' for %1$s</explainPrepare>
|
||||
<explainQuery>select * from table(dbms_xplan.display(NULL, '%2$s'))</explainQuery>
|
||||
<explainCleanup></explainCleanup>
|
||||
<synonymTableQuery>select '"' || TABLE_OWNER || '"."' || TABLE_NAME || '"' from ALL_SYNONYMS where OWNER = '%1$s' and SYNONYM_NAME = '%2$s'</synonymTableQuery>
|
||||
<viewTextOrDDLQuery>select TEXT from all_views where OWNER = '%1$s' and VIEW_NAME = '%2$s'</viewTextOrDDLQuery>
|
||||
<functionSourceQuery>SELECT 'Source', text FROM all_source WHERE type = 'FUNCTION' and name = '%2$s' AND owner = '%1$s' ORDER BY line</functionSourceQuery>
|
||||
<procedureSourceQuery>SELECT 'Source', text FROM all_source WHERE type = 'PROCEDURE' and name = '%2$s' AND owner = '%1$s' ORDER BY line</procedureSourceQuery>
|
||||
<packageNamesQuery>SELECT OBJECT_NAME FROM ALL_OBJECTS WHERE OBJECT_TYPE = 'PACKAGE' AND OWNER = '%1$s'</packageNamesQuery>
|
||||
@@ -257,6 +257,15 @@ union all
|
||||
<avoidLeftJoin>false</avoidLeftJoin>
|
||||
<supportsSchemasInIndexDefinitions>false</supportsSchemasInIndexDefinitions>
|
||||
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
|
||||
<estimatedRowCountQuery>
|
||||
SELECT tbl.name, p.rows
|
||||
FROM sys.tables AS tbl
|
||||
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and idx.index_id < 2
|
||||
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int)
|
||||
AND p.index_id=idx.index_id
|
||||
WHERE SCHEMA_NAME(tbl.schema_id)='%s'
|
||||
</estimatedRowCountQuery>
|
||||
<viewTextOrDDLQuery>SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%1$s' and TABLE_NAME = '%2$s'</viewTextOrDDLQuery>
|
||||
<virtualColumnsQuery>SELECT sysobjects.name AS TableName, syscolumns.name AS ColumnName FROM syscolumns JOIN sysobjects ON syscolumns.id = sysobjects.id AND sysobjects.xtype = 'U' WHERE syscolumns.iscomputed = 1</virtualColumnsQuery>
|
||||
<userDefinedColumnsQuery>SELECT distinct DOMAIN_NAME from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '%s' AND DOMAIN_NAME is not null</userDefinedColumnsQuery>
|
||||
<!--
|
||||
@@ -432,7 +441,10 @@ union all
|
||||
<binaryPattern>x'%s'</binaryPattern>
|
||||
<avoidLeftJoin>false</avoidLeftJoin>
|
||||
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
|
||||
<virtualColumnsQuery>SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${SCHEMA}' AND EXTRA LIKE '%VIRTUAL%'</virtualColumnsQuery>
|
||||
<estimatedRowCountQuery>select TABLE_NAME, CARDINALITY from INFORMATION_SCHEMA.STATISTICS where TABLE_SCHEMA = '%s'</estimatedRowCountQuery>
|
||||
<viewTextOrDDLQuery>SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%1$s' and TABLE_NAME = '%2$s'</viewTextOrDDLQuery>
|
||||
|
||||
<virtualColumnsQuery>SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${SCHEMA}' AND EXTRA LIKE '%VIRTUAL%'</virtualColumnsQuery>
|
||||
<!--
|
||||
<importedKeysQuery>SELECT PKCU.TABLE_SCHEMA, null, PKCU.TABLE_NAME, PKCU.COLUMN_NAME, KCU.TABLE_SCHEMA, null, KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.ORDINAL_POSITION, null, null, RC.CONSTRAINT_NAME, RC.UNIQUE_CONSTRAINT_NAME, null FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU ON KCU.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG AND KCU.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA AND KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PKCU ON PKCU.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG AND PKCU.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA AND PKCU.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME AND PKCU.TABLE_NAME = RC.REFERENCED_TABLE_NAME AND PKCU.ORDINAL_POSITION = KCU.ORDINAL_POSITION WHERE PKCU.TABLE_SCHEMA = '${SCHEMA}' ORDER BY KCU.ORDINAL_POSITION</importedKeysQuery>
|
||||
<primaryKeysQuery>SELECT null, KCU.TABLE_SCHEMA, KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.ORDINAL_POSITION, C.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS C JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU ON KCU.CONSTRAINT_CATALOG = C.CONSTRAINT_CATALOG AND KCU.CONSTRAINT_SCHEMA = C.CONSTRAINT_SCHEMA AND KCU.TABLE_NAME = C.TABLE_NAME AND KCU.CONSTRAINT_NAME = C.CONSTRAINT_NAME WHERE C.CONSTRAINT_TYPE = 'PRIMARY KEY' AND KCU.TABLE_SCHEMA = '${SCHEMA}' ORDER BY KCU.ORDINAL_POSITION</primaryKeysQuery>
|
||||
@@ -545,6 +557,8 @@ union all
|
||||
<binaryPattern>x'%s'</binaryPattern>
|
||||
<avoidLeftJoin>false</avoidLeftJoin>
|
||||
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
|
||||
<estimatedRowCountQuery>SELECT TABNAME, CARD FROM SYSSTAT.TABLES WHERE TABSCHEMA = '%s'</estimatedRowCountQuery>
|
||||
<viewTextOrDDLQuery>SELECT TEXT FROM SYSCAT.VIEWS WHERE VIEWSCHEMA = '%1$s' and VIEWNAME = '%2$s'</viewTextOrDDLQuery>
|
||||
<virtualColumnsQuery>SELECT TABNAME, COLNAME from syscat.columns WHERE TABSCHEMA='${SCHEMA}' AND GENERATED='A'</virtualColumnsQuery>
|
||||
<importedKeysQuery> SELECT null, REF.REFTABSCHEMA, REF.REFTABNAME, PKCOL.COLNAME, null, REF.TABSCHEMA, REF.TABNAME, FKCOL.COLNAME, FKCOL.COLSEQ, null, null, REF.CONSTNAME, REF.REFKEYNAME, null FROM syscat.references REF, syscat.keycoluse PKCOL, syscat.keycoluse FKCOL WHERE REF.CONSTNAME = FKCOL.CONSTNAME AND REF.TABSCHEMA = FKCOL.TABSCHEMA AND REF.TABNAME = FKCOL.TABNAME AND REF.REFKEYNAME = PKCOL.CONSTNAME AND REF.REFTABSCHEMA = PKCOL.TABSCHEMA AND REF.REFTABNAME = PKCOL.TABNAME AND FKCOL.COLSEQ = PKCOL.COLSEQ AND REF.REFTABSCHEMA = '${SCHEMA}' ORDER BY FKCOL.COLSEQ</importedKeysQuery>
|
||||
<primaryKeysQuery> SELECT null, CONST.TABSCHEMA, CONST.TABNAME, PKCOL.COLNAME, PKCOL.COLSEQ, CONST.CONSTNAME FROM syscat.tabconst CONST, syscat.keycoluse PKCOL WHERE CONST.CONSTNAME = PKCOL.CONSTNAME AND CONST.TABSCHEMA = PKCOL.TABSCHEMA AND CONST.TABNAME = PKCOL.TABNAME AND CONST.TYPE = 'P' AND CONST.TABSCHEMA = '${SCHEMA}' ORDER BY PKCOL.COLSEQ</primaryKeysQuery>
|
||||
@@ -661,6 +675,8 @@ Select CNAME, TNAME, COLNAME, CTYPE, DETAIL From
|
||||
<binaryPattern>x'%s'</binaryPattern>
|
||||
<avoidLeftJoin>false</avoidLeftJoin>
|
||||
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
|
||||
<viewTextOrDDLQuery>SELECT TEXT FROM SYSCAT.VIEWS WHERE VIEWSCHEMA = '%1$s' and VIEWNAME = '%2$s'</viewTextOrDDLQuery>
|
||||
<estimatedRowCountQuery>SELECT TABNAME, CARD FROM SYSSTAT.TABLES WHERE TABSCHEMA = '%s'</estimatedRowCountQuery>
|
||||
<virtualColumnsQuery>SELECT TABNAME, COLNAME from syscat.columns WHERE TABSCHEMA='${SCHEMA}' AND GENERATED='A'</virtualColumnsQuery>
|
||||
<importedKeysQuery>SELECT null, REF.REFTABSCHEMA, REF.REFTABNAME, PKCOL.COLNAME, null, REF.TABSCHEMA, REF.TABNAME, FKCOL.COLNAME, FKCOL.COLSEQ, null, null, REF.CONSTNAME, REF.REFKEYNAME, null FROM syscat.references REF, syscat.keycoluse PKCOL, syscat.keycoluse FKCOL WHERE REF.CONSTNAME = FKCOL.CONSTNAME AND REF.TABSCHEMA = FKCOL.TABSCHEMA AND REF.TABNAME = FKCOL.TABNAME AND REF.REFKEYNAME = PKCOL.CONSTNAME AND REF.REFTABSCHEMA = PKCOL.TABSCHEMA AND REF.REFTABNAME = PKCOL.TABNAME AND FKCOL.COLSEQ = PKCOL.COLSEQ AND REF.REFTABSCHEMA = '${SCHEMA}' ORDER BY FKCOL.COLSEQ</importedKeysQuery>
|
||||
<primaryKeysQuery>SELECT null, CONST.TABSCHEMA, CONST.TABNAME, PKCOL.COLNAME, PKCOL.COLSEQ, CONST.CONSTNAME FROM syscat.tabconst CONST, syscat.keycoluse PKCOL WHERE CONST.CONSTNAME = PKCOL.CONSTNAME AND CONST.TABSCHEMA = PKCOL.TABSCHEMA AND CONST.TABNAME = PKCOL.TABNAME AND CONST.TYPE = 'P' AND CONST.TABSCHEMA = '${SCHEMA}' ORDER BY PKCOL.COLSEQ</primaryKeysQuery>
|
||||
@@ -789,6 +805,13 @@ Select CNAME, TNAME, COLNAME, CTYPE, DETAIL From
|
||||
<supportsSchemasInIndexDefinitions>false</supportsSchemasInIndexDefinitions>
|
||||
<useInlineViewsInDataBrowser>true</useInlineViewsInDataBrowser>
|
||||
<identifierQuoteString>"</identifierQuoteString>
|
||||
<viewTextOrDDLQuery>SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%1$s' and TABLE_NAME = '%2$s'</viewTextOrDDLQuery>
|
||||
<estimatedRowCountQuery>
|
||||
SELECT c.relname, c.reltuples::bigint AS estimate
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE n.nspname = '%s'
|
||||
</estimatedRowCountQuery>
|
||||
<explainPrepare></explainPrepare>
|
||||
<explainQuery>explain %1$s</explainQuery>
|
||||
<explainCleanup></explainCleanup>
|
||||
@@ -1106,6 +1129,7 @@ union all
|
||||
<binaryPattern>x'%s'</binaryPattern>
|
||||
<avoidLeftJoin>false</avoidLeftJoin>
|
||||
<useInlineViewsInDataBrowser>false</useInlineViewsInDataBrowser>
|
||||
<estimatedRowCountQuery>select TABLE_NAME, ROW_COUNT_ESTIMATE from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = '%s'</estimatedRowCountQuery>
|
||||
<virtualColumnsQuery>SELECT TABLE_NAME, COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='${SCHEMA}' AND IS_COMPUTED</virtualColumnsQuery>
|
||||
<identifierQuoteString>"</identifierQuoteString>
|
||||
<explainPrepare></explainPrepare>
|
||||
|
||||
@@ -19,10 +19,12 @@ import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -48,7 +50,7 @@ public class BasicDataSource implements DataSource {
|
||||
/**
|
||||
* Name of JDBC-driver class.
|
||||
*/
|
||||
private final String driverClassName;
|
||||
final String driverClassName;
|
||||
|
||||
/**
|
||||
* The DB URL.
|
||||
@@ -196,6 +198,8 @@ public class BasicDataSource implements DataSource {
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> registeredDriverClassNames = new HashSet<String>();
|
||||
|
||||
private void loadDriver(URL[] jdbcDriverURL) {
|
||||
ClassLoader classLoaderForJdbcDriver = addJarToClasspath(jdbcDriverURL);
|
||||
try {
|
||||
@@ -204,6 +208,7 @@ public class BasicDataSource implements DataSource {
|
||||
try {
|
||||
d = (Driver) Class.forName(driverClassName, true, classLoaderForJdbcDriver).newInstance();
|
||||
DriverManager.registerDriver(new DriverShim(d));
|
||||
registeredDriverClassNames.add(driverClassName);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -215,7 +220,9 @@ public class BasicDataSource implements DataSource {
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
if (!registeredDriverClassNames.contains(driverClassName)) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,12 +66,12 @@ public class Session {
|
||||
/**
|
||||
* The session in which temporary tables lives, if any.
|
||||
*/
|
||||
private static Connection temporaryTableSession = null;
|
||||
private Connection temporaryTableSession = null;
|
||||
|
||||
/**
|
||||
* Shared scope of temporary tables.
|
||||
*/
|
||||
private static WorkingTableScope temporaryTableScope;
|
||||
private WorkingTableScope temporaryTableScope;
|
||||
|
||||
/**
|
||||
* Scope of temporary tables.
|
||||
@@ -201,6 +201,11 @@ public class Session {
|
||||
*/
|
||||
public final DBMS dbms;
|
||||
|
||||
/**
|
||||
* The DBMS.
|
||||
*/
|
||||
public final String driverClassName;
|
||||
|
||||
/**
|
||||
* The dbUrl (<code>null</code> if unknown)
|
||||
*/
|
||||
@@ -238,12 +243,11 @@ public class Session {
|
||||
this.local = local;
|
||||
this.scope = scope;
|
||||
this.dbms = dbms;
|
||||
this.driverClassName = (dataSource instanceof BasicDataSource)? ((BasicDataSource) dataSource).driverClassName : null;
|
||||
this.dbUrl = (dataSource instanceof BasicDataSource)? ((BasicDataSource) dataSource).dbUrl : null;
|
||||
this.schema = (dataSource instanceof BasicDataSource)? ((BasicDataSource) dataSource).dbUser : "";
|
||||
if (scope != null) {
|
||||
closeTemporaryTableSession();
|
||||
temporaryTableScope = scope;
|
||||
}
|
||||
this.temporaryTableScope = scope;
|
||||
|
||||
connectionFactory = new ConnectionFactory() {
|
||||
private Connection defaultConnection = null;
|
||||
private Random random = new Random();
|
||||
@@ -291,7 +295,7 @@ public class Session {
|
||||
} catch (SQLException e) {
|
||||
_log.info("can't set isolation level to UR. Reason: " + e.getMessage());
|
||||
}
|
||||
if (scope != null && scope != WorkingTableScope.GLOBAL) {
|
||||
if (scope == WorkingTableScope.SESSION_LOCAL || scope == WorkingTableScope.TRANSACTION_LOCAL) {
|
||||
temporaryTableSession = con;
|
||||
} else {
|
||||
connection.set(con);
|
||||
@@ -793,6 +797,7 @@ public class Session {
|
||||
for (Connection con: connections) {
|
||||
con.close();
|
||||
}
|
||||
closeTemporaryTableSession();
|
||||
_log.info("connection closed");
|
||||
}
|
||||
|
||||
@@ -849,7 +854,7 @@ public class Session {
|
||||
/**
|
||||
* Closes the session in which temporary tables lives, if any.
|
||||
*/
|
||||
public static void closeTemporaryTableSession() {
|
||||
private void closeTemporaryTableSession() {
|
||||
try {
|
||||
if (temporaryTableSession != null) {
|
||||
if (temporaryTableScope == WorkingTableScope.TRANSACTION_LOCAL) {
|
||||
@@ -968,4 +973,24 @@ public class Session {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks SQL query.
|
||||
*
|
||||
* @param sql
|
||||
* @return <code>true</code> iff sql is executable without errors
|
||||
*/
|
||||
public boolean checkQuery(String sql) {
|
||||
try {
|
||||
executeQuery(sql, new AbstractResultSetReader() {
|
||||
@Override
|
||||
public void readCurrentRow(ResultSet resultSet) throws SQLException {
|
||||
// nothing to do
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -552,4 +552,51 @@ public class Association extends ModelElement {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
}
|
||||
public boolean hasNullableFK() {
|
||||
if (!isInsertDestinationBeforeSource()) {
|
||||
return false;
|
||||
}
|
||||
Map<Column, Column> sdMap = createSourceToDestinationKeyMapping();
|
||||
if (sdMap.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (Column c: sdMap.keySet()) {
|
||||
if (!c.isNullable) {
|
||||
return false;
|
||||
}
|
||||
if (c.getFilter() != null && !c.getFilter().isDerived() && !c.getFilter().isNullFilter()) {
|
||||
return false;
|
||||
}
|
||||
for (Column pk: source.primaryKey.getColumns()) {
|
||||
if (c.name.equals(pk.name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean fkHasNullFilter() {
|
||||
Map<Column, Column> sdMap = createSourceToDestinationKeyMapping();
|
||||
for (Column c: sdMap.keySet()) {
|
||||
if (c.getFilter() == null || !c.getFilter().isNullFilter()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setOrResetFKNullFilter(boolean set) {
|
||||
Map<Column, Column> sdMap = createSourceToDestinationKeyMapping();
|
||||
for (Column c: sdMap.keySet()) {
|
||||
if (set) {
|
||||
c.setFilter(new Filter("null", null, false, null));
|
||||
} else {
|
||||
c.setFilter(null);
|
||||
}
|
||||
}
|
||||
getDataModel().deriveFilters();
|
||||
getDataModel().version++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -184,4 +184,8 @@ public class Filter {
|
||||
return applyAtExport;
|
||||
}
|
||||
|
||||
public boolean isNullFilter() {
|
||||
return "null".equalsIgnoreCase(expression.trim());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -200,6 +200,11 @@ public class PrimaryKey {
|
||||
return toSQL(null);
|
||||
}
|
||||
|
||||
public void assign(List<Column> primaryKeyColumns) {
|
||||
columns.clear();
|
||||
columns.addAll(primaryKeyColumns);
|
||||
}
|
||||
|
||||
public static boolean isIncreasable(Column uPKColumn, Column column) {
|
||||
if(!uPKColumn.type.equals(column.type)) {
|
||||
return false;
|
||||
@@ -228,4 +233,5 @@ public class PrimaryKey {
|
||||
// never should get THIS far !
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package net.sf.jailer.datamodel;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -23,6 +24,7 @@ import java.util.List;
|
||||
import net.sf.jailer.ExecutionContext;
|
||||
import net.sf.jailer.configuration.DBMS;
|
||||
import net.sf.jailer.database.Session;
|
||||
import net.sf.jailer.util.Quoting;
|
||||
|
||||
|
||||
/**
|
||||
@@ -99,15 +101,27 @@ public class RowIdSupport {
|
||||
* @param table the table
|
||||
* @return the primary key of the table
|
||||
*/
|
||||
public PrimaryKey getPrimaryKey(Table table) {
|
||||
public PrimaryKey getPrimaryKey(Table table, Session session) {
|
||||
if (table.primaryKey != null) {
|
||||
if (useRowIds && (!useRowIdsOnlyForTablesWithoutPK || table.primaryKey.getColumns().isEmpty())) {
|
||||
return tablePK;
|
||||
if (session == null || isRowIDApplicable(table, session)) {
|
||||
return tablePK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return table.primaryKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the primary key of a table.
|
||||
*
|
||||
* @param table the table
|
||||
* @return the primary key of the table
|
||||
*/
|
||||
public PrimaryKey getPrimaryKey(Table table) {
|
||||
return getPrimaryKey(table, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the universal primary key.
|
||||
*
|
||||
@@ -147,13 +161,15 @@ public class RowIdSupport {
|
||||
* @param table the table
|
||||
* @return the columns of the table
|
||||
*/
|
||||
public List<Column> getColumns(Table table) {
|
||||
public List<Column> getColumns(Table table, Session session) {
|
||||
List<Column> columns = table.getColumns();
|
||||
if (table.primaryKey != null) {
|
||||
if (useRowIds && (!useRowIdsOnlyForTablesWithoutPK || table.primaryKey.getColumns().isEmpty())) {
|
||||
columns = new ArrayList<Column>(columns);
|
||||
columns.addAll(tablePK.getColumns());
|
||||
return columns;
|
||||
if (session == null || isRowIDApplicable(table, session)) {
|
||||
columns = new ArrayList<Column>(columns);
|
||||
columns.addAll(tablePK.getColumns());
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
}
|
||||
return columns;
|
||||
@@ -163,4 +179,35 @@ public class RowIdSupport {
|
||||
return rowIdColumn != null && rowIdColumn.name.equals(column.name);
|
||||
}
|
||||
|
||||
private boolean isRowIDApplicable(Table table, Session session) {
|
||||
Boolean result = (Boolean) session.getSessionProperty(RowIdSupport.class, table.getName());
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
Quoting quoting;
|
||||
result = false;
|
||||
try {
|
||||
quoting = new Quoting(session);
|
||||
String schema = table.getSchema("");
|
||||
String tableName;
|
||||
if (schema.length() == 0) {
|
||||
tableName = quoting.requote(table.getUnqualifiedName());
|
||||
} else {
|
||||
tableName = quoting.requote(schema) + "." + quoting.requote(table.getUnqualifiedName());
|
||||
}
|
||||
if (rowIdColumn != null) {
|
||||
if (session.checkQuery("Select 1 from " + tableName + " Where 1=0")) {
|
||||
result = session.checkQuery("Select 1 from " + tableName + " Where 1=0 and " + rowIdColumn.name + "=" + rowIdColumn.name);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
result = true;
|
||||
}
|
||||
|
||||
session.setSessionProperty(RowIdSupport.class, table.getName(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1530,7 +1530,7 @@ public class LocalEntityGraph extends EntityGraph {
|
||||
*/
|
||||
@Override
|
||||
public void shutDown() throws SQLException {
|
||||
localSession.shutDown();
|
||||
remoteSession.shutDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+599
-81
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+4
-4
@@ -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};
|
||||
|
||||
Executable → Regular
Executable → Regular
@@ -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) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sf.jailer.ExecutionContext;
|
||||
import net.sf.jailer.configuration.Configuration;
|
||||
import net.sf.jailer.database.Session;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
|
||||
@@ -96,17 +97,22 @@ public class Quoting {
|
||||
}
|
||||
|
||||
String k = metaData.getSQLKeywords();
|
||||
if (k != null) {
|
||||
keyWords = keyWordsMap.get(k);
|
||||
if (keyWords == null) {
|
||||
keyWords = new HashSet<String>();
|
||||
for (String key : k.split(",")) {
|
||||
keyWords.add(key.trim().toUpperCase());
|
||||
}
|
||||
// add all SQL 92 keywords
|
||||
keyWords.addAll(UCSQL92KEYWORDS);
|
||||
keyWordsMap.put(k, keyWords);
|
||||
if (k == null) {
|
||||
k = "";
|
||||
}
|
||||
keyWords = keyWordsMap.get(k);
|
||||
if (keyWords == null) {
|
||||
keyWords = new HashSet<String>();
|
||||
String additionalKeyWords = Configuration.getInstance().getAdditionalSQLKeywords();
|
||||
if (additionalKeyWords != null) {
|
||||
k += "," + additionalKeyWords;
|
||||
}
|
||||
for (String key : k.split(",")) {
|
||||
keyWords.add(key.trim().toUpperCase());
|
||||
}
|
||||
// add all SQL 92 keywords
|
||||
keyWords.addAll(UCSQL2003KEYWORDS);
|
||||
keyWordsMap.put(k, keyWords);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,6 +248,9 @@ public class Quoting {
|
||||
private static boolean isQuoted(String identifier, String qu) {
|
||||
if (identifier != null && identifier.length() > 1) {
|
||||
String q = identifier.substring(0, 1);
|
||||
if (q.equals("[") && identifier.endsWith("]")) {
|
||||
return true;
|
||||
}
|
||||
if (identifier.endsWith(q)) {
|
||||
char c = q.charAt(0);
|
||||
if (q.equals(qu) || isPotentialIdentifierQuote(c)) {
|
||||
@@ -281,6 +290,19 @@ public class Quoting {
|
||||
return staticUnquote(identifier).toUpperCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
public String normalizeCase(String identifier) {
|
||||
if (identifier == null) {
|
||||
return null;
|
||||
}
|
||||
if (unquotedIdentifierInMixedCase) {
|
||||
return identifier;
|
||||
}
|
||||
if (unquotedIdentifierInUpperCase) {
|
||||
return identifier.toUpperCase();
|
||||
}
|
||||
return identifier.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares a String to another String, ignoring case considerations and quoting.
|
||||
*
|
||||
@@ -298,51 +320,420 @@ public class Quoting {
|
||||
return staticUnquote(a).equalsIgnoreCase(staticUnquote(b));
|
||||
}
|
||||
|
||||
public static final HashSet<String> UCSQL92KEYWORDS = new HashSet<String>(Arrays.asList(new String[] { "ABSOLUTE", "ACTION",
|
||||
"ADD", "ALL", "ALLOCATE", "ALTER", "AND", "ANY", "ARE", "AS",
|
||||
"ASC", "ASSERTION", "AT", "AUTHORIZATION", "AVG", "BEGIN",
|
||||
"BETWEEN", "BIT", "BIT_LENGTH", "BOTH", "BY", "CALL",
|
||||
"CASCADE", "CASCADED", "CASE", "CAST", "CATALOG", "CHAR",
|
||||
"CHARACTER", "CHARACTER_LENGTH", "CHAR_LENGTH", "CHECK",
|
||||
"CLOSE", "COALESCE", "COLLATE", "COLLATION", "COLUMN",
|
||||
"COMMIT", "CONDITION", "CONNECT", "CONNECTION", "CONSTRAINT",
|
||||
"CONSTRAINTS", "CONTAINS", "CONTINUE", "CONVERT",
|
||||
"CORRESPONDING", "COUNT", "CREATE", "CROSS", "CURRENT",
|
||||
"CURRENT_DATE", "CURRENT_PATH", "CURRENT_TIME",
|
||||
"CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DATE", "DATETIME", "DAY",
|
||||
"DEALLOCATE", "DEC", "DECIMAL", "DECLARE", "DEFAULT",
|
||||
"DEFERRABLE", "DEFERRED", "DELETE", "DESC", "DESCRIBE",
|
||||
"DESCRIPTOR", "DETERMINISTIC", "DIAGNOSTICS", "DISCONNECT",
|
||||
"DISTINCT", "DO", "DOMAIN", "DOUBLE", "DROP", "ELSE", "ELSEIF",
|
||||
"END", "ESCAPE", "EXCEPT", "EXCEPTION", "EXEC", "EXECUTE",
|
||||
"EXISTS", "EXIT", "EXTERNAL", "EXTRACT", "FALSE", "FETCH",
|
||||
"FIRST", "FLOAT", "FOR", "FOREIGN", "FOUND", "FROM", "FULL",
|
||||
"FUNCTION", "GET", "GLOBAL", "GO", "GOTO", "GRANT", "GROUP",
|
||||
"HANDLER", "HAVING", "HOUR", "IDENTITY", "IF", "IMMEDIATE",
|
||||
"IN", "INDICATOR", "INITIALLY", "INNER", "INOUT", "INPUT",
|
||||
"INSENSITIVE", "INSERT", "INT", "INTEGER", "INTERSECT",
|
||||
"INTERVAL", "INTO", "IS", "ISOLATION", "JOIN", "KEY",
|
||||
"LAST", "LEADING", "LEAVE", "LEFT", "LEVEL",
|
||||
"LIKE", "LOCAL", "LOOP", "LOWER", "MATCH", "MAX", "MIN",
|
||||
"MINUTE", "MODULE", "MONTH", "NAMES", "NATIONAL", "NATURAL",
|
||||
"NCHAR", "NEXT", "NO", "NOT", "NULL", "NULLIF", "NUMERIC",
|
||||
"OCTET_LENGTH", "OF", "ON", "ONLY", "OPEN", "OPTION", "OR",
|
||||
"ORDER", "OUT", "OUTER", "OUTPUT", "OVERLAPS", "PAD",
|
||||
"PARAMETER", "PARTIAL", "PATH", "POSITION", "PRECISION",
|
||||
"PREPARE", "PRESERVE", "PRIMARY", "PRIOR", "PRIVILEGES",
|
||||
"PROCEDURE", "READ", "REAL", "REFERENCES",
|
||||
"RELATIVE", "REPEAT", "RESIGNAL", "RESTRICT", "RETURN",
|
||||
"RETURNS", "REVOKE", "RIGHT", "ROLLBACK", "ROUTINE", "ROWS",
|
||||
"SCHEMA", "SCROLL", "SECOND", "SECTION", "SELECT", "SESSION",
|
||||
"SESSION_USER", "SET", "SIGNAL", "SIZE", "SMALLINT", "SOME",
|
||||
"SPACE", "SPECIFIC", "SQL", "SQLCODE", "SQLERROR",
|
||||
"SQLEXCEPTION", "SQLSTATE", "SQLWARNING", "SUBSTRING", "SUM",
|
||||
"SYSTEM_USER", "TABLE", "TEMPORARY", "THEN", "TIME",
|
||||
"TIMESTAMP", "TIMEZONE_HOUR", "TIMEZONE_MINUTE", "TO",
|
||||
"TRAILING", "TRANSACTION", "TRANSLATE", "TRANSLATION", "TRIM",
|
||||
"TRUE", "UNDO", "UNION", "UNIQUE", "UNKNOWN", "UNTIL",
|
||||
"UPDATE", "UPPER", "USAGE", "USER", "USING", "VALUE", "VALUES",
|
||||
"VARCHAR", "VARYING", "VIEW", "VIRTUAL", "WHEN", "WHENEVER", "WHERE",
|
||||
"WHILE", "WITH", "WORK", "WRITE", "YEAR", "ZONE" }));
|
||||
public static final HashSet<String> UCSQL2003KEYWORDS = new HashSet<String>(Arrays.asList(new String[] {
|
||||
"ABS",
|
||||
"ABSOLUTE",
|
||||
"ACTION",
|
||||
"ADD",
|
||||
"ADMIN",
|
||||
"AFTER",
|
||||
"AGGREGATE",
|
||||
"ALIAS",
|
||||
"ALL",
|
||||
"ALLOCATE",
|
||||
"ALTER",
|
||||
"ANALYSE",
|
||||
"ANALYZE",
|
||||
"AND",
|
||||
"ANY",
|
||||
"ARE",
|
||||
"ARRAY",
|
||||
"AS",
|
||||
"ASC",
|
||||
"ASENSITIVE",
|
||||
"ASSERTION",
|
||||
"ASYMMETRIC",
|
||||
"AT",
|
||||
"ATOMIC",
|
||||
"AUTHORIZATION",
|
||||
"AVG",
|
||||
"BEFORE",
|
||||
"BEGIN",
|
||||
"BETWEEN",
|
||||
"BIGINT",
|
||||
"BINARY",
|
||||
"BIT",
|
||||
"BIT_LENGTH",
|
||||
"BLOB",
|
||||
"BOOLEAN",
|
||||
"BOTH",
|
||||
"BREADTH",
|
||||
"BY",
|
||||
"CALL",
|
||||
"CALLED",
|
||||
"CARDINALITY",
|
||||
"CASCADE",
|
||||
"CASCADED",
|
||||
"CASE",
|
||||
"CAST",
|
||||
"CATALOG",
|
||||
"CEIL",
|
||||
"CEILING",
|
||||
"CHAR",
|
||||
"CHARACTER",
|
||||
"CHARACTER_LENGTH",
|
||||
"CHAR_LENGTH",
|
||||
"CHECK",
|
||||
"CLASS",
|
||||
"CLOB",
|
||||
"CLOSE",
|
||||
"COALESCE",
|
||||
"COLLATE",
|
||||
"COLLATION",
|
||||
"COLLECT",
|
||||
"COLUMN",
|
||||
"COMMIT",
|
||||
"COMPLETION",
|
||||
"CONDITION",
|
||||
"CONNECT",
|
||||
"CONNECTION",
|
||||
"CONSTRAINT",
|
||||
"CONSTRAINTS",
|
||||
"CONSTRUCTOR",
|
||||
"CONTINUE",
|
||||
"CONVERT",
|
||||
"CORR",
|
||||
"CORRESPONDING",
|
||||
"COUNT",
|
||||
"COVAR_POP",
|
||||
"COVAR_SAMP",
|
||||
"CREATE",
|
||||
"CROSS",
|
||||
"CUBE",
|
||||
"CUME_DIST",
|
||||
"CURRENT",
|
||||
"CURRENT_DATE",
|
||||
"CURRENT_DEFAULT_TRANSFORM_GROUP",
|
||||
"CURRENT_PATH",
|
||||
"CURRENT_ROLE",
|
||||
"CURRENT_TIME",
|
||||
"CURRENT_TIMESTAMP",
|
||||
"CURRENT_TRANSFORM_GROUP_FOR_TYPE",
|
||||
"CURRENT_USER",
|
||||
"CURSOR",
|
||||
"CYCLE",
|
||||
"DATA",
|
||||
"DATE",
|
||||
"DAY",
|
||||
"DEALLOCATE",
|
||||
"DEC",
|
||||
"DECIMAL",
|
||||
"DECLARE",
|
||||
"DEFAULT",
|
||||
"DEFERRABLE",
|
||||
"DEFERRED",
|
||||
"DELETE",
|
||||
"DENSE_RANK",
|
||||
"DEPTH",
|
||||
"DEREF",
|
||||
"DESC",
|
||||
"DESCRIBE",
|
||||
"DESCRIPTOR",
|
||||
"DESTROY",
|
||||
"DESTRUCTOR",
|
||||
"DETERMINISTIC",
|
||||
"DIAGNOSTICS",
|
||||
"DICTIONARY",
|
||||
"DISCONNECT",
|
||||
"DISTINCT",
|
||||
"DO",
|
||||
"DOMAIN",
|
||||
"DOUBLE",
|
||||
"DROP",
|
||||
"DYNAMIC",
|
||||
"EACH",
|
||||
"ELEMENT",
|
||||
"ELSE",
|
||||
"END",
|
||||
"END-EXEC",
|
||||
"EQUALS",
|
||||
"ESCAPE",
|
||||
"EVERY",
|
||||
"EXCEPT",
|
||||
"EXCEPTION",
|
||||
"EXEC",
|
||||
"EXECUTE",
|
||||
"EXISTS",
|
||||
"EXP",
|
||||
"EXTERNAL",
|
||||
"EXTRACT",
|
||||
"FALSE",
|
||||
"FETCH",
|
||||
"FILTER",
|
||||
"FIRST",
|
||||
"FLOAT",
|
||||
"FLOOR",
|
||||
"FOR",
|
||||
"FOREIGN",
|
||||
"FOUND",
|
||||
"FREE",
|
||||
"FREEZE",
|
||||
"FROM",
|
||||
"FULL",
|
||||
"FUNCTION",
|
||||
"FUSION",
|
||||
"GENERAL",
|
||||
"GET",
|
||||
"GLOBAL",
|
||||
"GO",
|
||||
"GOTO",
|
||||
"GRANT",
|
||||
"GROUP",
|
||||
"GROUPING",
|
||||
"HAVING",
|
||||
"HOLD",
|
||||
"HOST",
|
||||
"HOUR",
|
||||
"IDENTITY",
|
||||
"IGNORE",
|
||||
"ILIKE",
|
||||
"IMMEDIATE",
|
||||
"IN",
|
||||
"INDICATOR",
|
||||
"INITIALIZE",
|
||||
"INITIALLY",
|
||||
"INNER",
|
||||
"INOUT",
|
||||
"INPUT",
|
||||
"INSENSITIVE",
|
||||
"INSERT",
|
||||
"INT",
|
||||
"INTEGER",
|
||||
"INTERSECT",
|
||||
"INTERSECTION",
|
||||
"INTERVAL",
|
||||
"INTO",
|
||||
"IS",
|
||||
"ISNULL",
|
||||
"ISOLATION",
|
||||
"ITERATE",
|
||||
"JOIN",
|
||||
"KEY",
|
||||
"LARGE",
|
||||
"LAST",
|
||||
"LATERAL",
|
||||
"LEADING",
|
||||
"LEFT",
|
||||
"LESS",
|
||||
"LEVEL",
|
||||
"LIKE",
|
||||
"LIMIT",
|
||||
"LN",
|
||||
"LOCAL",
|
||||
"LOCALTIME",
|
||||
"LOCALTIMESTAMP",
|
||||
"LOCATOR",
|
||||
"LOWER",
|
||||
"MAP",
|
||||
"MATCH",
|
||||
"MAX",
|
||||
"MEMBER",
|
||||
"MERGE",
|
||||
"METHOD",
|
||||
"MIN",
|
||||
"MINUTE",
|
||||
"MOD",
|
||||
"MODIFIES",
|
||||
"MODIFY",
|
||||
"MODULE",
|
||||
"MONTH",
|
||||
"MULTISET",
|
||||
"NAMES",
|
||||
"NATIONAL",
|
||||
"NATURAL",
|
||||
"NCHAR",
|
||||
"NCLOB",
|
||||
"NEW",
|
||||
"NEXT",
|
||||
"NO",
|
||||
"NONE",
|
||||
"NORMALIZE",
|
||||
"NOT",
|
||||
"NOTNULL",
|
||||
"NULL",
|
||||
"NULLIF",
|
||||
"NUMERIC",
|
||||
"OBJECT",
|
||||
"OCTET_LENGTH",
|
||||
"OF",
|
||||
"OFF",
|
||||
"OFFSET",
|
||||
"OLD",
|
||||
"ON",
|
||||
"ONLY",
|
||||
"OPEN",
|
||||
"OPERATION",
|
||||
"OPTION",
|
||||
"OR",
|
||||
"ORDER",
|
||||
"ORDINALITY",
|
||||
"OUT",
|
||||
"OUTER",
|
||||
"OUTPUT",
|
||||
"OVER",
|
||||
"OVERLAPS",
|
||||
"OVERLAY",
|
||||
"PAD",
|
||||
"PARAMETER",
|
||||
"PARAMETERS",
|
||||
"PARTIAL",
|
||||
"PARTITION",
|
||||
"PATH",
|
||||
"PERCENTILE_CONT",
|
||||
"PERCENTILE_DISC",
|
||||
"PERCENT_RANK",
|
||||
"PLACING",
|
||||
"POSITION",
|
||||
"POSTFIX",
|
||||
"POWER",
|
||||
"PRECISION",
|
||||
"PREFIX",
|
||||
"PREORDER",
|
||||
"PREPARE",
|
||||
"PRESERVE",
|
||||
"PRIMARY",
|
||||
"PRIOR",
|
||||
"PRIVILEGES",
|
||||
"PROCEDURE",
|
||||
"PUBLIC",
|
||||
"RANGE",
|
||||
"RANK",
|
||||
"READ",
|
||||
"READS",
|
||||
"REAL",
|
||||
"RECURSIVE",
|
||||
"REF",
|
||||
"REFERENCES",
|
||||
"REFERENCING",
|
||||
"REGR_AVGX",
|
||||
"REGR_AVGY",
|
||||
"REGR_COUNT",
|
||||
"REGR_INTERCEPT",
|
||||
"REGR_R2",
|
||||
"REGR_SLOPE",
|
||||
"REGR_SXX",
|
||||
"REGR_SXY",
|
||||
"REGR_SYY",
|
||||
"RELATIVE",
|
||||
"RELEASE",
|
||||
"RESTRICT",
|
||||
"RESULT",
|
||||
"RETURN",
|
||||
"RETURNING",
|
||||
"RETURNS",
|
||||
"REVOKE",
|
||||
"RIGHT",
|
||||
"ROLLBACK",
|
||||
"ROLLUP",
|
||||
"ROUTINE",
|
||||
"ROW",
|
||||
"ROWS",
|
||||
"ROW_NUMBER",
|
||||
"SAVEPOINT",
|
||||
"SCHEMA",
|
||||
"SCOPE",
|
||||
"SCROLL",
|
||||
"SEARCH",
|
||||
"SECOND",
|
||||
"SECTION",
|
||||
"SELECT",
|
||||
"SENSITIVE",
|
||||
"SEQUENCE",
|
||||
"SESSION",
|
||||
"SESSION_USER",
|
||||
"SET",
|
||||
"SETS",
|
||||
"SIMILAR",
|
||||
"SIZE",
|
||||
"SMALLINT",
|
||||
"SOME",
|
||||
"SPACE",
|
||||
"SPECIFIC",
|
||||
"SPECIFICTYPE",
|
||||
"SQL",
|
||||
"SQLCODE",
|
||||
"SQLERROR",
|
||||
"SQLEXCEPTION",
|
||||
"SQLSTATE",
|
||||
"SQLWARNING",
|
||||
"SQRT",
|
||||
"START",
|
||||
"STATE",
|
||||
"STATEMENT",
|
||||
"STATIC",
|
||||
"STDDEV_POP",
|
||||
"STDDEV_SAMP",
|
||||
"STRUCTURE",
|
||||
"SUBMULTISET",
|
||||
"SUBSTRING",
|
||||
"SUM",
|
||||
"SYMMETRIC",
|
||||
"SYSTEM",
|
||||
"SYSTEM_USER",
|
||||
"TABLE",
|
||||
"TABLESAMPLE",
|
||||
"TEMPORARY",
|
||||
"TERMINATE",
|
||||
"THAN",
|
||||
"THEN",
|
||||
"TIME",
|
||||
"TIMESTAMP",
|
||||
"TIMEZONE_HOUR",
|
||||
"TIMEZONE_MINUTE",
|
||||
"TO",
|
||||
"TRAILING",
|
||||
"TRANSACTION",
|
||||
"TRANSLATE",
|
||||
"TRANSLATION",
|
||||
"TREAT",
|
||||
"TRIGGER",
|
||||
"TRIM",
|
||||
"TRUE",
|
||||
"UESCAPE",
|
||||
"UNDER",
|
||||
"UNION",
|
||||
"UNIQUE",
|
||||
"UNKNOWN",
|
||||
"UNNEST",
|
||||
"UPDATE",
|
||||
"UPPER",
|
||||
"USAGE",
|
||||
"USER",
|
||||
"USING",
|
||||
"VALUE",
|
||||
"VALUES",
|
||||
"VARCHAR",
|
||||
"VARIABLE",
|
||||
"VARYING",
|
||||
"VAR_POP",
|
||||
"VAR_SAMP",
|
||||
"VERBOSE",
|
||||
"VIEW",
|
||||
"WHEN",
|
||||
"WHENEVER",
|
||||
"WHERE",
|
||||
"WIDTH_BUCKET",
|
||||
"WINDOW",
|
||||
"WITH",
|
||||
"WITHIN",
|
||||
"WITHOUT",
|
||||
"WORK",
|
||||
"WRITE",
|
||||
"XML",
|
||||
"XMLAGG",
|
||||
"XMLATTRIBUTES",
|
||||
"XMLBINARY",
|
||||
"XMLCOMMENT",
|
||||
"XMLCONCAT",
|
||||
"XMLELEMENT",
|
||||
"XMLFOREST",
|
||||
"XMLNAMESPACES",
|
||||
"XMLPARSE",
|
||||
"XMLPI",
|
||||
"XMLROOT",
|
||||
"XMLSERIALIZE",
|
||||
"YEAR",
|
||||
"ZONE",
|
||||
}));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package net.sf.jailer.util;
|
||||
|
||||
public class ToDo {
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
package net.sf.jailer.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Image;
|
||||
@@ -430,7 +429,7 @@ public class AdditionalSubjectsDialog extends javax.swing.JDialog {
|
||||
|
||||
private void addAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addAllButtonActionPerformed
|
||||
try {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(this);
|
||||
|
||||
List<Table> tables = new ArrayList<Table>(remaining);
|
||||
Collections.sort(tables);
|
||||
@@ -443,7 +442,7 @@ public class AdditionalSubjectsDialog extends javax.swing.JDialog {
|
||||
additionalSubjectListEditor.setModel(subjects);
|
||||
collectRemaining();
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(this);
|
||||
}
|
||||
}//GEN-LAST:event_addAllButtonActionPerformed
|
||||
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -21,11 +21,13 @@ import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
@@ -45,6 +47,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.Stack;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Vector;
|
||||
@@ -67,6 +70,10 @@ import javax.swing.table.TableColumn;
|
||||
import net.sf.jailer.datamodel.Association;
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
import net.sf.jailer.ui.StringSearchPanel.AdditionalComponentFactory;
|
||||
import net.sf.jailer.ui.pathfinder.HistoryPanel;
|
||||
import net.sf.jailer.ui.pathfinder.PathFinder;
|
||||
import net.sf.jailer.ui.pathfinder.PathFinder.Result;
|
||||
import net.sf.jailer.ui.scrollmenu.JScrollMenu;
|
||||
import net.sf.jailer.ui.scrollmenu.JScrollPopupMenu;
|
||||
import net.sf.jailer.util.Pair;
|
||||
@@ -167,6 +174,71 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
findButton.setVisible(false);
|
||||
searchButton.setText("Find Table");
|
||||
|
||||
AutoCompletion.enable(findPathComboBox);
|
||||
findPathComboBox.getEditor().getEditorComponent().addKeyListener(new KeyListener() {
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
if (e.getKeyChar() == '\n') {
|
||||
findButtonActionPerformed(null);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void keyPressed(KeyEvent arg0) {
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 3;
|
||||
gridBagConstraints.gridy = 2;
|
||||
Object currentSelection = rootTable.getSelectedItem();
|
||||
Table source = null;
|
||||
if (currentSelection instanceof String) {
|
||||
source = getDataModel().getTableByDisplayName((String) currentSelection);
|
||||
}
|
||||
final javax.swing.JComboBox comboBox = findPathComboBox;
|
||||
JButton stFindButtonButton = StringSearchPanel.createSearchButton(extractionModelEditor.extractionModelFrame, comboBox,
|
||||
new Object() {
|
||||
public String toString() {
|
||||
Table source = null;
|
||||
Object currentSelection = ClosureView.this.rootTable.getSelectedItem();
|
||||
if (currentSelection instanceof String) {
|
||||
source = getDataModel().getTableByDisplayName((String) currentSelection);
|
||||
}
|
||||
return (source != null? ("From " + getDataModel().getDisplayName(source) + " - ") : "") + "Select destination or choose from History";
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
findPathButtonActionPerformed(null);
|
||||
}
|
||||
}, null, null, null, true,
|
||||
new AdditionalComponentFactory() {
|
||||
@Override
|
||||
public JComponent create(final StringSearchPanel searchPanel) {
|
||||
HistoryPanel historyPanel = new HistoryPanel(ClosureView.this.getSelectedTable(), getDataModel()) {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected void close() {
|
||||
searchPanel.close();
|
||||
}
|
||||
@Override
|
||||
protected void apply(Table source, Table destination) {
|
||||
findPath(source, destination, true);
|
||||
}
|
||||
};
|
||||
return historyPanel;
|
||||
}
|
||||
});
|
||||
tablePanel.add(stFindButtonButton, gridBagConstraints);
|
||||
|
||||
findPathComboBox.setVisible(false);
|
||||
findPathButton.setVisible(false);
|
||||
stFindButtonButton.setText("Find Path to...");
|
||||
|
||||
columnsComboBox.setModel(new DefaultComboBoxModel<Integer>(new Integer[] {
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
|
||||
}));
|
||||
@@ -245,6 +317,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
};
|
||||
closureTable.setShowGrid(false);
|
||||
closureTable.setSurrendersFocusOnKeystroke(true);
|
||||
closureTable.getTableHeader().setReorderingAllowed(false);
|
||||
jScrollPane1.setViewportView(closureTable);
|
||||
|
||||
closureTable.addMouseListener(new MouseListener() {
|
||||
@@ -262,7 +335,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
if (value == null || !(value instanceof String)) return;
|
||||
Table table = getDataModel().getTableByDisplayName((String) value);
|
||||
if (table != null) {
|
||||
JPopupMenu popup = ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, true);
|
||||
JPopupMenu popup = ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, createFindPathMenuItem(table), true);
|
||||
popup.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
@@ -362,7 +435,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
selectTableCell(column, row);
|
||||
}
|
||||
|
||||
ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, false);
|
||||
ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, null, false);
|
||||
popup.show(e.getComponent(), cellRect.x, cellRect.y + cellRect.height + 4);
|
||||
}
|
||||
}
|
||||
@@ -385,6 +458,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
private Font font = new JLabel("normal").getFont();
|
||||
private Font normal = new Font(font.getName(), font.getStyle() & ~Font.BOLD, font.getSize());
|
||||
private Font bold = new Font(font.getName(), font.getStyle() | Font.BOLD, font.getSize());
|
||||
// private Font italic = new Font(font.getName(), font.getStyle() | Font.ITALIC, font.getSize());
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table,
|
||||
@@ -436,6 +510,10 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
} else if (!allDisabled && someRestricted) {
|
||||
((JLabel) render).setForeground(new Color(0, 80, 160));
|
||||
}
|
||||
if (currentForcedDistance != null && currentForcedDistance.containsKey(t)) {
|
||||
((JLabel) render).setFont(bold);
|
||||
// ((JLabel) render).setForeground(new Color(150, 150, 150));
|
||||
}
|
||||
}
|
||||
}
|
||||
return render;
|
||||
@@ -541,8 +619,8 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
Table table = getDataModel().getTableByDisplayName(selectedTable);
|
||||
if (table != null) {
|
||||
CellInfo selectionInfo = cellInfo.get(selectedTable);
|
||||
selectionInfo.select();
|
||||
if (selectionInfo != null) {
|
||||
selectionInfo.select();
|
||||
Association association = null;
|
||||
for (CellInfo parent: selectionInfo.parents) {
|
||||
Table pre = parent.table;
|
||||
@@ -557,6 +635,58 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
}
|
||||
}
|
||||
}
|
||||
Stack<Table> toSelect = new Stack<Table>();
|
||||
CellInfo ci = selectionInfo;
|
||||
final int MAX_PATH_LENGTH = 1000;
|
||||
while (ci != null) {
|
||||
if (toSelect.size() > MAX_PATH_LENGTH) {
|
||||
break;
|
||||
}
|
||||
if (ci.table != null) {
|
||||
toSelect.push(ci.table);
|
||||
}
|
||||
CellInfo nextCi = null;
|
||||
for (CellInfo parent: ci.parents) {
|
||||
Table pre = parent.table;
|
||||
if (pre != null) {
|
||||
CellInfo preInfo = cellInfo.get(getDataModel().getDisplayName(pre));
|
||||
if (preInfo != null) {
|
||||
if (preInfo.selected) {
|
||||
if (preInfo.table != null) {
|
||||
nextCi = preInfo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ci = nextCi;
|
||||
}
|
||||
Table selTable = getSelectedTable();
|
||||
if (currentForcedDistance != null) {
|
||||
if (selTable != null && !toSelect.contains(selTable)
|
||||
||
|
||||
!currentForcedDistance.containsKey(table)) {
|
||||
refresh();
|
||||
selectTableCell(col, row);
|
||||
return;
|
||||
}
|
||||
}
|
||||
extractionModelEditor.incCaptureLevel();
|
||||
try {
|
||||
if (!toSelect.isEmpty()) {
|
||||
Table source = toSelect.pop();
|
||||
while (!toSelect.isEmpty()) {
|
||||
Table dest = toSelect.pop();
|
||||
if (!ClosureView.this.extractionModelEditor.graphView.isTableVisible(dest)) {
|
||||
ClosureView.this.extractionModelEditor.graphView.showTable(source, dest);
|
||||
}
|
||||
source = dest;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
extractionModelEditor.decCaptureLevel();
|
||||
}
|
||||
if (association != null && ClosureView.this.extractionModelEditor.select(association)) {
|
||||
return;
|
||||
}
|
||||
@@ -617,7 +747,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
// }
|
||||
|
||||
// table model
|
||||
refreshTableModel();
|
||||
refreshTableModel(null);
|
||||
|
||||
refreshing = false;
|
||||
}
|
||||
@@ -627,7 +757,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
*/
|
||||
public void refresh() {
|
||||
String prevSelection = selectedTable;
|
||||
refreshTableModel();
|
||||
refreshTableModel(null);
|
||||
if (cellInfo.containsKey(prevSelection)) {
|
||||
selectedTable = prevSelection;
|
||||
} else {
|
||||
@@ -637,15 +767,23 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
repaintClosureView();
|
||||
}
|
||||
|
||||
private Map<Table, Integer> currentForcedDistance = null;
|
||||
|
||||
/**
|
||||
* Refreshes the table model.
|
||||
* @param excludedTables
|
||||
* @param path
|
||||
*/
|
||||
private void refreshTableModel() {
|
||||
private void refreshTableModel(Map<Table, Integer> forcedDistance) {
|
||||
cellInfo.clear();
|
||||
dependencies.clear();
|
||||
currentForcedDistance = forcedDistance;
|
||||
if (forcedDistance == null) {
|
||||
forcedDistance = new HashMap<Table, Integer>();
|
||||
}
|
||||
Table selectedTable = getSelectedTable();
|
||||
refreshAssociationView(selectedTable);
|
||||
|
||||
|
||||
Object[] columns = new Object[tablesPerLine + 1];
|
||||
for (int i = 0; i < columns.length; ++i) {
|
||||
columns[i] = "";
|
||||
@@ -673,7 +811,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
boolean isolated = false;
|
||||
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
final Color BG3 = new Color(255, 255, 240);
|
||||
final Color BG4 = new Color(220, 220, 220);
|
||||
final Color BG5 = new Color(255, 240, 240);
|
||||
@@ -682,6 +820,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
TreeSet<String> nonIsolated = new TreeSet<String>();
|
||||
|
||||
while (!currentLine.isEmpty()) {
|
||||
|
||||
// add current line to table model
|
||||
if (distance == OMEGA || isolated) {
|
||||
Object[] lineAsObjects = new Object[tablesPerLine + 1];
|
||||
@@ -725,18 +864,32 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
|
||||
// get next line
|
||||
List<String> nextLine = new ArrayList<String>();
|
||||
|
||||
for (String t: currentLine) {
|
||||
Table table = getDataModel().getTableByDisplayName(t);
|
||||
if (table != null) {
|
||||
CellInfo cellInfoT = this.cellInfo.get(t);
|
||||
for (Association association: table.associations) {
|
||||
Integer fd = forcedDistance.get(association.destination);
|
||||
if (fd != null && fd != distance + 1) {
|
||||
continue;
|
||||
}
|
||||
boolean addToParent = true;
|
||||
if (forcedDistance.containsKey(association.destination)) {
|
||||
if (!forcedDistance.containsKey(table)) {
|
||||
addToParent = false;
|
||||
}
|
||||
}
|
||||
String displayName = getDataModel().getDisplayName(association.destination);
|
||||
if (!association.isIgnored()) {
|
||||
if (!association.isIgnored() ||
|
||||
(forcedDistance.containsKey(association.source) && forcedDistance.containsKey(association.destination))) {
|
||||
if (!visited.contains(displayName)) {
|
||||
nextLine.add(displayName);
|
||||
visited.add(displayName);
|
||||
CellInfo cellInfo = new CellInfo(distance);
|
||||
cellInfo.parents.add(cellInfoT);
|
||||
if (addToParent) {
|
||||
cellInfo.parents.add(cellInfoT);
|
||||
}
|
||||
cellInfo.table = association.destination;
|
||||
if (association.isInsertDestinationBeforeSource()) {
|
||||
dependencies.add(new Pair<String, String>(t, displayName));
|
||||
@@ -744,7 +897,9 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
this.cellInfo.put(displayName, cellInfo);
|
||||
} else {
|
||||
if (nextLine.contains(displayName)) {
|
||||
this.cellInfo.get(displayName).parents.add(cellInfoT);
|
||||
if (addToParent) {
|
||||
this.cellInfo.get(displayName).parents.add(cellInfoT);
|
||||
}
|
||||
if (association.isInsertDestinationBeforeSource()) {
|
||||
dependencies.add(new Pair<String, String>(t, displayName));
|
||||
}
|
||||
@@ -852,6 +1007,8 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
vector.addAll(nonIsolated);
|
||||
searchComboBox.setModel(new DefaultComboBoxModel<String>(vector));
|
||||
searchComboBox.setSelectedItem("");
|
||||
findPathComboBox.setModel(new DefaultComboBoxModel<String>(vector));
|
||||
findPathComboBox.setSelectedItem("");
|
||||
}
|
||||
|
||||
private Table getSelectedTable() {
|
||||
@@ -1102,9 +1259,9 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (SwingUtilities.isRightMouseButton(e)) {
|
||||
if (tableName != null) {
|
||||
Table table = getDataModel().getTable(tableName);
|
||||
final Table table = getDataModel().getTable(tableName);
|
||||
if (table != null) {
|
||||
JPopupMenu popup = ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, false);
|
||||
JPopupMenu popup = ClosureView.this.extractionModelEditor.graphView.createPopupMenu(table, createFindPathMenuItem(table), false);
|
||||
popup.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
@@ -1125,7 +1282,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collects names of associations in the closure ordered by distance into {@link #associationClosure}.
|
||||
*
|
||||
@@ -1209,10 +1366,12 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
tablePanel = new javax.swing.JPanel();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
closureTable = new javax.swing.JTable();
|
||||
searchComboBox = new net.sf.jailer.ui.JComboBox();
|
||||
searchComboBox = new JComboBox();
|
||||
jLabel7 = new javax.swing.JLabel();
|
||||
columnsComboBox = new net.sf.jailer.ui.JComboBox();
|
||||
columnsComboBox = new JComboBox();
|
||||
findButton = new javax.swing.JButton();
|
||||
findPathComboBox = new JComboBox();
|
||||
findPathButton = new javax.swing.JButton();
|
||||
associationPane = new javax.swing.JPanel();
|
||||
associationPanel = new javax.swing.JPanel();
|
||||
jScrollPane2 = new javax.swing.JScrollPane();
|
||||
@@ -1236,8 +1395,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
|
||||
tabbedPane.setMinimumSize(new java.awt.Dimension(182, 190));
|
||||
tabbedPane.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
tabbedPaneStateChanged(evt);
|
||||
}
|
||||
});
|
||||
@@ -1277,8 +1435,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
|
||||
searchComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
searchComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
searchComboBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
@@ -1289,7 +1446,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
|
||||
jLabel7.setText("Columns ");
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 3;
|
||||
gridBagConstraints.gridx = 7;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
@@ -1297,29 +1454,50 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
|
||||
columnsComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
columnsComboBox.addItemListener(new java.awt.event.ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
columnsComboBoxItemStateChanged(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 4;
|
||||
gridBagConstraints.gridy = 2;
|
||||
tablePanel.add(columnsComboBox, gridBagConstraints);
|
||||
|
||||
findButton.setText("Search");
|
||||
findButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
findButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 5;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
|
||||
tablePanel.add(findButton, gridBagConstraints);
|
||||
|
||||
findPathComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
findPathComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
findPathComboBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 4;
|
||||
gridBagConstraints.gridy = 2;
|
||||
tablePanel.add(findPathComboBox, gridBagConstraints);
|
||||
|
||||
findPathButton.setText("Search");
|
||||
findPathButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
findPathButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 3;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
|
||||
tablePanel.add(findButton, gridBagConstraints);
|
||||
tablePanel.add(findPathButton, gridBagConstraints);
|
||||
|
||||
tablePane.add(tablePanel);
|
||||
|
||||
@@ -1388,8 +1566,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
|
||||
showOnlyEnabledCheckBox.setText("Show only enabled associations");
|
||||
showOnlyEnabledCheckBox.addItemListener(new java.awt.event.ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
showOnlyEnabledCheckBoxItemStateChanged(evt);
|
||||
}
|
||||
});
|
||||
@@ -1466,6 +1643,72 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
}
|
||||
}//GEN-LAST:event_findButtonActionPerformed
|
||||
|
||||
private void findPathComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findPathComboBoxActionPerformed
|
||||
}//GEN-LAST:event_findPathComboBoxActionPerformed
|
||||
|
||||
private void findPathButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findPathButtonActionPerformed
|
||||
Object toFind = findPathComboBox.getSelectedItem();
|
||||
if (toFind != null) {
|
||||
CellInfo cellInfo = this.cellInfo.get(toFind);
|
||||
if (cellInfo != null) {
|
||||
Object currentSelection = rootTable.getSelectedItem();
|
||||
if (currentSelection instanceof String) {
|
||||
final Table source = getDataModel().getTableByDisplayName((String) currentSelection);
|
||||
// if (source.closure(true).contains(cellInfo.table)) {
|
||||
findPath(source, cellInfo.table, false);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_findPathButtonActionPerformed
|
||||
|
||||
protected JMenuItem createFindPathMenuItem(final Table table) {
|
||||
JMenuItem findPath = new JMenuItem("Find Path to " + getDataModel().getDisplayName(table));
|
||||
Object currentSelection = rootTable.getSelectedItem();
|
||||
if (currentSelection instanceof String) {
|
||||
final Table source = getDataModel().getTableByDisplayName((String) currentSelection);
|
||||
if (source.closure(false).contains(table)) {
|
||||
findPath.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
findPath(source, table, false);
|
||||
}
|
||||
});
|
||||
return findPath;
|
||||
}
|
||||
}
|
||||
findPath.setEnabled(false);
|
||||
return findPath;
|
||||
}
|
||||
|
||||
private void findPath(Table source, Table destination, boolean fromHistory) {
|
||||
Frame parent = null;
|
||||
Window w = SwingUtilities.getWindowAncestor(rootTable);
|
||||
if (w instanceof Frame) {
|
||||
parent = (Frame) w;
|
||||
}
|
||||
Result result = new PathFinder().find(source, destination, getDataModel(), false, fromHistory, parent);
|
||||
if (result != null) {
|
||||
Map<Table, Integer> fd = new HashMap<Table, Integer>();
|
||||
for (int i = 0; i < result.path.size(); ++i) {
|
||||
fd.put(result.path.get(i), i);
|
||||
}
|
||||
refreshTableModel(fd);
|
||||
List<Table> path = result.path;
|
||||
Table table = null;
|
||||
for (int i = 0; i < path.size(); i++) {
|
||||
table = path.get(i);
|
||||
// ClosureView.this.extractionModelEditor.select(table);
|
||||
}
|
||||
if (table != null) {
|
||||
CellInfo ci = cellInfo.get(getDataModel().getDisplayName(table));
|
||||
if (ci != null) {
|
||||
selectTableCell(ci.column, ci.row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initTabbedPane() {
|
||||
if (tabbedPane.getSelectedIndex() == 2) {
|
||||
tabAssTabPanel.removeAll();
|
||||
@@ -1493,9 +1736,11 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
private javax.swing.JPanel associationPane;
|
||||
private javax.swing.JPanel associationPanel;
|
||||
private javax.swing.JTable closureTable;
|
||||
private net.sf.jailer.ui.JComboBox columnsComboBox;
|
||||
private JComboBox columnsComboBox;
|
||||
public javax.swing.JPanel contentPanel;
|
||||
private javax.swing.JButton findButton;
|
||||
private javax.swing.JButton findPathButton;
|
||||
private JComboBox findPathComboBox;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JLabel jLabel3;
|
||||
private javax.swing.JLabel jLabel4;
|
||||
@@ -1505,7 +1750,7 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JScrollPane jScrollPane2;
|
||||
private javax.swing.JSeparator jSeparator1;
|
||||
private net.sf.jailer.ui.JComboBox searchComboBox;
|
||||
private JComboBox searchComboBox;
|
||||
private javax.swing.JCheckBox showOnlyEnabledCheckBox;
|
||||
private javax.swing.JPanel tabAssAssPanel;
|
||||
private javax.swing.JPanel tabAssPanel;
|
||||
@@ -1523,4 +1768,9 @@ public abstract class ClosureView extends javax.swing.JDialog {
|
||||
public void addTabComponent(String titel, Container tab) {
|
||||
tabbedPane.addTab(titel, tab);
|
||||
}
|
||||
|
||||
public void selectTabComponent(Container tab) {
|
||||
tabbedPane.setSelectedComponent(tab);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package net.sf.jailer.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Font;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
@@ -140,7 +139,7 @@ public class ColumnOrderEditor extends javax.swing.JPanel {
|
||||
final TableCellRenderer defaultTableCellRenderer = columnOrderTable.getDefaultRenderer(String.class);
|
||||
TableCellRenderer renderer = new TableCellRenderer() {
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
@@ -179,7 +178,7 @@ public class ColumnOrderEditor extends javax.swing.JPanel {
|
||||
};
|
||||
|
||||
try {
|
||||
owner.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(owner);
|
||||
|
||||
Set<String> pks = new HashSet<String>();
|
||||
Set<String> fks = new HashSet<String>();
|
||||
@@ -236,7 +235,7 @@ public class ColumnOrderEditor extends javax.swing.JPanel {
|
||||
columnOrderTable.getRowSorter().setSortKeys(keys);
|
||||
adjustTableColumnsWidth();
|
||||
} finally {
|
||||
owner.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(owner);
|
||||
}
|
||||
dialog = new EscapableDialog(owner, "Column Ordering") {
|
||||
};
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
package net.sf.jailer.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Point;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.sql.SQLException;
|
||||
@@ -34,6 +37,8 @@ import javax.swing.JScrollPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.fife.rsta.ui.EscapableDialog;
|
||||
|
||||
import net.sf.jailer.datamodel.Column;
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
@@ -50,12 +55,12 @@ import net.sf.jailer.util.SqlUtil;
|
||||
*
|
||||
* @author Ralf Wisser
|
||||
*/
|
||||
public class ConditionEditor extends javax.swing.JDialog {
|
||||
|
||||
public class ConditionEditor extends EscapableDialog {
|
||||
|
||||
private boolean ok;
|
||||
private ParameterSelector parameterSelector;
|
||||
private DataModelBasedSQLCompletionProvider provider;
|
||||
|
||||
|
||||
/** Creates new form ConditionEditor */
|
||||
public ConditionEditor(java.awt.Frame parent, ParameterSelector.ParametersGetter parametersGetter, DataModel dataModel) {
|
||||
super(parent, true);
|
||||
@@ -525,6 +530,21 @@ public class ConditionEditor extends javax.swing.JDialog {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void setLocationAndFit(Point pos) {
|
||||
setLocation(pos);
|
||||
// UIUtil.fit(this);
|
||||
try {
|
||||
// Get the size of the screen
|
||||
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
int hd = getY() - (dim.height - 80);
|
||||
if (hd > 0) {
|
||||
setLocation(getX(), Math.max(getY() - hd, 0));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts multi-line text into single line presentation.
|
||||
*/
|
||||
@@ -610,4 +630,5 @@ public class ConditionEditor extends javax.swing.JDialog {
|
||||
public final RSyntaxTextAreaWithSQLSyntaxStyle editorPane;
|
||||
|
||||
private static final long serialVersionUID = -5169934807182707970L;
|
||||
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public class CyclesView extends javax.swing.JDialog {
|
||||
if (value == null || !(value instanceof String)) return;
|
||||
Table table = getDataModel().getTableByDisplayName((String) value);
|
||||
if (table != null) {
|
||||
JPopupMenu popup = CyclesView.this.extractionModelFrame.extractionModelEditor.graphView.createPopupMenu(table, false);
|
||||
JPopupMenu popup = CyclesView.this.extractionModelFrame.extractionModelEditor.graphView.createPopupMenu(table, null, false);
|
||||
UIUtil.fit(popup);
|
||||
popup.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
@@ -364,7 +364,7 @@ public class CyclesView extends javax.swing.JDialog {
|
||||
|
||||
int distance = 0;
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
bgColor.clear();
|
||||
|
||||
for (CycleFinder.Path cycle: cycles) {
|
||||
|
||||
@@ -17,6 +17,8 @@ package net.sf.jailer.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.io.File;
|
||||
@@ -41,6 +43,7 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.RowSorter.SortKey;
|
||||
import javax.swing.SortOrder;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
@@ -53,6 +56,8 @@ import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableModel;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
|
||||
import net.coderazzi.filters.gui.AutoChoices;
|
||||
import net.coderazzi.filters.gui.TableFilterHeader;
|
||||
import net.sf.jailer.ExecutionContext;
|
||||
import net.sf.jailer.JailerVersion;
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
@@ -243,7 +248,17 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
|
||||
sortLineList(associations, false);
|
||||
initComponents();
|
||||
|
||||
|
||||
TableFilterHeader filterHeader = new TableFilterHeader();
|
||||
filterHeader.setAutoChoices(AutoChoices.ENABLED);
|
||||
filterHeader.setTable(tablesTable);
|
||||
filterHeader.setMaxVisibleRows(20);
|
||||
|
||||
filterHeader = new TableFilterHeader();
|
||||
filterHeader.setAutoChoices(AutoChoices.ENABLED);
|
||||
filterHeader.setTable(associationsTable);
|
||||
filterHeader.setMaxVisibleRows(20);
|
||||
|
||||
String modelpath = executionContext.getQualifiedDatamodelFolder();
|
||||
try {
|
||||
modelpath = new File(modelpath).getAbsolutePath();
|
||||
@@ -278,8 +293,13 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
UIUtil.wireComponentWithButton(tablesTable, editTable);
|
||||
UIUtil.wireComponentWithButton(associationsTable, editAssociation);
|
||||
|
||||
setSize(1000, 700);
|
||||
setLocation(100, 32);
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
if (screenSize == null || screenSize.width < 1200) {
|
||||
setSize(1000, 700);
|
||||
} else {
|
||||
setSize(Math.min(screenSize.width - 2 * getX(), 2000), Math.min(screenSize.height - 2 * getY(), 800));
|
||||
}
|
||||
|
||||
File modelFinderColumnFile = new File(ModelBuilder.getModelBuilderColumnsFilename(executionContext));
|
||||
if (merge && modelFinderColumnFile.exists()) {
|
||||
@@ -310,73 +330,47 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
boolean fromModelFinder = linesFromModelFinder.contains(value);
|
||||
if (!(value instanceof CsvFile.Line)) {
|
||||
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
CsvFile.Line line = (CsvFile.Line) value;
|
||||
String tableName = line.cells.get(0);
|
||||
String pk = "";
|
||||
for (int i = 2; i < line.length; ++i) {
|
||||
if (line.cells.get(i).length() == 0) {
|
||||
break;
|
||||
}
|
||||
if (pk.length() > 0) {
|
||||
pk += ", ";
|
||||
}
|
||||
pk += line.cells.get(i);
|
||||
}
|
||||
value = column == 0? line.cells.get(0) : (pk.isEmpty()? "" : pk);
|
||||
boolean fromModelFinder = tableTableRowsFromModelFinder.contains(tablesTable.getRowSorter().convertRowIndexToModel(row));
|
||||
Component render = super.getTableCellRendererComponent(table, value, isSelected, false, row, column);
|
||||
render.setForeground(Color.BLACK);
|
||||
if (pk.equals("")) {
|
||||
render.setForeground(Color.RED);
|
||||
}
|
||||
if (fromModelFinder || modifiedColumnTables.contains(tableName)) {
|
||||
if (fromModelFinder || modifiedColumnTables.contains(value) && column == 0) {
|
||||
render.setBackground(isSelected? BG_SELCOLOR : BG_COLOR);
|
||||
} else {
|
||||
render.setBackground(isSelected? BG_SELCOLOR : (row % 2 == 0) ? BG1 : BG2);
|
||||
}
|
||||
if (tableTableRowsWithoutPK.contains(tablesTable.getRowSorter().convertRowIndexToModel(row))) {
|
||||
render.setForeground(Color.RED);
|
||||
}
|
||||
if (render instanceof JLabel) {
|
||||
((JLabel) render).setToolTipText(UIUtil.toHTML(String.valueOf(value), 100));
|
||||
if (!"".equals(value)) {
|
||||
((JLabel) render).setToolTipText(UIUtil.toHTML(String.valueOf(value), 100));
|
||||
} else {
|
||||
((JLabel) render).setToolTipText(null);
|
||||
}
|
||||
}
|
||||
return render;
|
||||
}
|
||||
private static final long serialVersionUID = -8591324056536900244L;
|
||||
};
|
||||
|
||||
|
||||
DefaultTableCellRenderer associationsListItemRenderer = new DefaultTableCellRenderer() {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
boolean fromModelFinder = linesFromModelFinder.contains(value);
|
||||
if (!(value instanceof CsvFile.Line)) {
|
||||
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
boolean fromModelFinder = associationTableRowsFromModelFinder.contains(associationsTable.getRowSorter().convertRowIndexToModel(row));
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
CsvFile.Line line = (CsvFile.Line) value;
|
||||
String type = "associates";
|
||||
String typeTT = "associates";
|
||||
if ("B".equalsIgnoreCase(line.cells.get(2))) {
|
||||
type = "depends on";
|
||||
if (value.equals("depends on")) {
|
||||
typeTT = "depends on (has parent)";
|
||||
}
|
||||
if ("A".equalsIgnoreCase(line.cells.get(2))) {
|
||||
type = "has dependent (has child)";
|
||||
typeTT = "has dependent";
|
||||
if (value.equals("has dependent")) {
|
||||
typeTT = "has dependent (has child)";
|
||||
}
|
||||
String name = "";
|
||||
if (line.cells.get(5).length() > 0) {
|
||||
name = line.cells.get(5);
|
||||
}
|
||||
switch (column) {
|
||||
case 0: value = line.cells.get(0); break;
|
||||
case 1: value = line.cells.get(1); break;
|
||||
case 2: value = line.cells.get(4); break;
|
||||
case 3: value = type; break;
|
||||
case 4: value = line.cells.get(3); break;
|
||||
case 5: value = name; break;
|
||||
}
|
||||
// value = line.cells.get(0) + " " + type + " " + line.cells.get(1) + " " + name + line.cells.get(3) + " on " + line.cells.get(4);
|
||||
Component render = super.getTableCellRendererComponent(table, value, isSelected, false, row, column);
|
||||
if (fromModelFinder) {
|
||||
render.setBackground(isSelected? BG_SELCOLOR: BG_COLOR);
|
||||
@@ -399,7 +393,7 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
tablesTable.setAutoCreateRowSorter(true);
|
||||
|
||||
tablesTable.setDefaultRenderer(Object.class, tablesListItemRenderer);
|
||||
tablesTable.setModel(createTablesListModel());
|
||||
resetTableTableModel();
|
||||
|
||||
// tablesTable.setRowSelectionAllowed(false);
|
||||
tablesTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
@@ -409,17 +403,13 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
initRowSorter(tablesTable, new int[] { 0, 2 });
|
||||
initRowSorter(tablesTable);
|
||||
adjustTableColumnsWidth(tablesTable);
|
||||
|
||||
associationsTable.setDefaultRenderer(Object.class, associationsListItemRenderer);
|
||||
|
||||
associationsTable.setAutoCreateRowSorter(true);
|
||||
// List<SortKey> keys = new ArrayList<SortKey>();
|
||||
// keys.add(new SortKey(1, SortOrder.ASCENDING));
|
||||
// keys.add(new SortKey(3, SortOrder.ASCENDING));
|
||||
// associationsTable.getRowSorter().setSortKeys(keys);
|
||||
associationsTable.setModel(createAssociationsListModel());
|
||||
resetAssociationTableModel();
|
||||
adjustTableColumnsWidth(associationsTable);
|
||||
|
||||
associationsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@@ -428,7 +418,7 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
initRowSorter(associationsTable, new int[] { 0, 1, 4, 2, 3, 5 });
|
||||
initRowSorter(associationsTable);
|
||||
|
||||
invalidate();
|
||||
if (initiallyDirty) {
|
||||
@@ -463,6 +453,7 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
if (toEdit.getName().equals(l.cells.get(0))) {
|
||||
if (new TableEditor(DataModelEditor.this, displayNames, tables, associations, excludeFromDeletion).edit(l, columns)) {
|
||||
markDirty();
|
||||
resetTableTableModel();
|
||||
repaint();
|
||||
}
|
||||
break;
|
||||
@@ -471,13 +462,13 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (merge) {
|
||||
ModelBuilder.cleanUp(executionContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void initRowSorter(JTable table, final int[] mapping) {
|
||||
private void initRowSorter(JTable table) {
|
||||
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()) {
|
||||
@Override
|
||||
protected boolean useToString(int column) {
|
||||
@@ -495,22 +486,6 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
}
|
||||
super.toggleSortOrder(column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator<?> getComparator(final int n) {
|
||||
return new Comparator<Object>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public int compare(Object o1, Object o2) {
|
||||
if (o1 instanceof Line) {
|
||||
if (o2 instanceof Line) {
|
||||
return ((Line) o1).cells.get(mapping[n]).compareTo(((Line) o2).cells.get(mapping[n]));
|
||||
}
|
||||
}
|
||||
return String.valueOf(o1).compareTo(String.valueOf(o2));
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
table.setRowSorter(sorter);
|
||||
}
|
||||
@@ -529,9 +504,9 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
comp = table.getCellRenderer(line, i).getTableCellRendererComponent(table, dtm.getValueAt(line, i), false, false, line, i);
|
||||
width = Math.max(width, comp.getPreferredSize().width);
|
||||
}
|
||||
column.setPreferredWidth(Math.min(width, 200));
|
||||
column.setPreferredWidth(Math.min(width, 400));
|
||||
}
|
||||
table.getColumnModel().getColumn(table.getColumnModel().getColumnCount() - 1).setPreferredWidth(80);
|
||||
table.getColumnModel().getColumn(table.getColumnModel().getColumnCount() - 1).setPreferredWidth(120);
|
||||
}
|
||||
|
||||
private KnownIdentifierMap createKnownIdentifierMap() throws IOException {
|
||||
@@ -853,7 +828,7 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
CsvFile.Line line = new CsvFile.Line("?", cells);
|
||||
if (new AssociationEditor(this, tables, associations, columns).edit(line)) {
|
||||
associations.add(0, line);
|
||||
associationsTable.setModel(createAssociationsListModel());
|
||||
resetAssociationTableModel();
|
||||
repaint();
|
||||
markDirty();
|
||||
}
|
||||
@@ -866,12 +841,29 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
}
|
||||
if (line != null) {
|
||||
if (new AssociationEditor(this, tables, associations, columns).edit(line)) {
|
||||
resetAssociationTableModel();
|
||||
markDirty();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_editAssociationActionPerformed
|
||||
|
||||
private void resetAssociationTableModel() {
|
||||
List<? extends SortKey> keys = associationsTable.getRowSorter().getSortKeys();
|
||||
associationsTable.setModel(createAssociationsListModel());
|
||||
initRowSorter(associationsTable);
|
||||
adjustTableColumnsWidth(associationsTable);
|
||||
associationsTable.getRowSorter().setSortKeys(keys);
|
||||
}
|
||||
|
||||
private void resetTableTableModel() {
|
||||
List<? extends SortKey> keys = tablesTable.getRowSorter().getSortKeys();
|
||||
tablesTable.setModel(createTablesListModel());
|
||||
initRowSorter(tablesTable);
|
||||
adjustTableColumnsWidth(tablesTable);
|
||||
tablesTable.getRowSorter().setSortKeys(keys);
|
||||
}
|
||||
|
||||
private void newTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTableActionPerformed
|
||||
List<String> cells = new ArrayList<String>();
|
||||
cells.add("");
|
||||
@@ -884,7 +876,7 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
CsvFile.Line line = new CsvFile.Line("?", cells);
|
||||
if (new TableEditor(this, displayNames, tables, associations, excludeFromDeletion).edit(line, columns)) {
|
||||
tables.add(0, line);
|
||||
tablesTable.setModel(createTablesListModel());
|
||||
resetTableTableModel();
|
||||
markDirty();
|
||||
repaint();
|
||||
}
|
||||
@@ -895,6 +887,7 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
CsvFile.Line line = tables.get(tablesTable.getRowSorter().convertRowIndexToModel(tablesTable.getSelectedRow()));
|
||||
if (new TableEditor(this, displayNames, tables, associations, excludeFromDeletion).edit(line, columns)) {
|
||||
markDirty();
|
||||
resetTableTableModel();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
@@ -931,9 +924,9 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
displayNames.remove(k);
|
||||
}
|
||||
excludeFromDeletion.removeAll(namesOfTablesToDelete);
|
||||
tablesTable.setModel(createTablesListModel());
|
||||
resetTableTableModel();
|
||||
associations.removeAll(assToDelete);
|
||||
associationsTable.setModel(createAssociationsListModel());
|
||||
resetAssociationTableModel();
|
||||
for (Line l: toDelete) {
|
||||
columns.remove(l.cells.get(0));
|
||||
}
|
||||
@@ -947,10 +940,14 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
toDelete.add(associations.get(associationsTable.getRowSorter().convertRowIndexToModel(i)));
|
||||
}
|
||||
associations.removeAll(toDelete);
|
||||
associationsTable.setModel(createAssociationsListModel());
|
||||
resetAssociationTableModel();
|
||||
markDirty();
|
||||
}//GEN-LAST:event_deleteAssociationsActionPerformed
|
||||
|
||||
private Set<Integer> tableTableRowsFromModelFinder = new HashSet<Integer>();
|
||||
private Set<Integer> tableTableRowsWithoutPK = new HashSet<Integer>();
|
||||
private Set<Integer> associationTableRowsFromModelFinder = new HashSet<Integer>();
|
||||
|
||||
/**
|
||||
* Creates model for tables-list component.
|
||||
*
|
||||
@@ -963,8 +960,28 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
tableTableRowsFromModelFinder.clear();
|
||||
tableTableRowsWithoutPK.clear();
|
||||
int row = 0;
|
||||
for (CsvFile.Line line: tables) {
|
||||
tablesTableModel.addRow(new Object[] { line, line });
|
||||
String pk = "";
|
||||
for (int i = 2; i < line.length; ++i) {
|
||||
if (line.cells.get(i).length() == 0) {
|
||||
break;
|
||||
}
|
||||
if (pk.length() > 0) {
|
||||
pk += ", ";
|
||||
}
|
||||
pk += line.cells.get(i);
|
||||
}
|
||||
if (linesFromModelFinder.contains(line)) {
|
||||
tableTableRowsFromModelFinder.add(row);
|
||||
}
|
||||
if (pk.isEmpty()) {
|
||||
tableTableRowsWithoutPK.add(row);
|
||||
}
|
||||
tablesTableModel.addRow(new Object[] { line.cells.get(0), pk });
|
||||
++row;
|
||||
}
|
||||
return tablesTableModel;
|
||||
}
|
||||
@@ -981,8 +998,25 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
associationTableRowsFromModelFinder.clear();
|
||||
int row = 0;
|
||||
for (CsvFile.Line line: associations) {
|
||||
associationsTableModel.addRow(new Object[] { line, line, line, line, line, line });
|
||||
String type = "associates";
|
||||
if ("B".equalsIgnoreCase(line.cells.get(2))) {
|
||||
type = "depends on";
|
||||
}
|
||||
if ("A".equalsIgnoreCase(line.cells.get(2))) {
|
||||
type = "has dependent";
|
||||
}
|
||||
String name = "";
|
||||
if (line.cells.get(5).length() > 0) {
|
||||
name = line.cells.get(5);
|
||||
}
|
||||
if (linesFromModelFinder.contains(line)) {
|
||||
associationTableRowsFromModelFinder.add(row);
|
||||
}
|
||||
associationsTableModel.addRow(new Object[] { line.cells.get(0), line.cells.get(1), line.cells.get(4), type, line.cells.get(3), name });
|
||||
++row;
|
||||
}
|
||||
return associationsTableModel;
|
||||
}
|
||||
@@ -1156,4 +1190,4 @@ public class DataModelEditor extends javax.swing.JDialog {
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
private static final long serialVersionUID = -1267039412732180237L;
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,7 @@ import javax.swing.table.TableColumn;
|
||||
import net.sf.jailer.ExecutionContext;
|
||||
import net.sf.jailer.JailerVersion;
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
|
||||
import net.sf.jailer.modelbuilder.ModelBuilder;
|
||||
import net.sf.jailer.util.CancellationHandler;
|
||||
import net.sf.jailer.util.Pair;
|
||||
@@ -156,7 +157,7 @@ public abstract class DataModelManagerDialog extends javax.swing.JFrame {
|
||||
false, hasFocus, row, column);
|
||||
if (render instanceof JLabel) {
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
if (!isSelected) {
|
||||
((JLabel) render)
|
||||
.setBackground((row % 2 == 0) ? BG1
|
||||
@@ -788,6 +789,7 @@ public abstract class DataModelManagerDialog extends javax.swing.JFrame {
|
||||
activateCurrentModel();
|
||||
|
||||
try {
|
||||
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = new PrivilegedSessionProviderDialog.Provider(this);
|
||||
DbConnectionDialog dbConnectionDialog = new DbConnectionDialog(this, applicationName,
|
||||
new InfoBar("Connect with Database",
|
||||
"Select a connection to the database to be analyzed, or create a new connection.\n" +
|
||||
@@ -837,6 +839,7 @@ public abstract class DataModelManagerDialog extends javax.swing.JFrame {
|
||||
UIUtil.showException(this, "Error", e);
|
||||
} finally {
|
||||
ModelBuilder.assocFilter = null;
|
||||
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = null;
|
||||
}
|
||||
|
||||
}//GEN-LAST:event_analyzeButtonActionPerformed
|
||||
@@ -844,6 +847,7 @@ public abstract class DataModelManagerDialog extends javax.swing.JFrame {
|
||||
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
|
||||
String folder = choseFolder();
|
||||
if (folder != null) {
|
||||
new File(folder).mkdir();
|
||||
executionContext.setDatamodelFolder(folder);
|
||||
baseFolders.remove(folder);
|
||||
baseFolders.add(0, folder);
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
<Container class="javax.swing.JPanel" name="jPanel2">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="100" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
<GridBagConstraints gridX="0" gridY="100" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="4" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
@@ -178,14 +178,14 @@
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="okButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value=" Ok "/>
|
||||
<Property name="text" type="java.lang.String" value=" Ok "/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="0" insetsRight="4" anchor="14" weightX="0.0" weightY="0.0"/>
|
||||
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="0" insetsRight="4" anchor="14" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
@@ -198,7 +198,7 @@
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="14" weightX="0.0" weightY="0.0"/>
|
||||
<GridBagConstraints gridX="3" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="14" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
@@ -209,6 +209,19 @@
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="testConnectionButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="0" insetsRight="12" anchor="14" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="selectConnectionButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Select Connection "/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="selectConnectionButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="0" insetsRight="12" anchor="14" weightX="1.0" weightY="0.0"/>
|
||||
@@ -228,6 +241,9 @@
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="password">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="80" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="1.0"/>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package net.sf.jailer.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
@@ -42,6 +43,11 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
|
||||
* The connection to edit.
|
||||
*/
|
||||
private ConnectionInfo ci;
|
||||
|
||||
/**
|
||||
* <code>true</code> if connection must be tested on OK.
|
||||
*/
|
||||
private final boolean needsTest;
|
||||
|
||||
/**
|
||||
* Opens detail editor for a connection.
|
||||
@@ -50,6 +56,18 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
|
||||
* @return <code>true</code> if connection has been edited
|
||||
*/
|
||||
public boolean edit(ConnectionInfo ci) {
|
||||
setDetails(ci);
|
||||
setVisible(true);
|
||||
return isOk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets details.
|
||||
*
|
||||
* @param ci the connection
|
||||
* @return <code>true</code> if connection has been edited
|
||||
*/
|
||||
public void setDetails(ConnectionInfo ci) {
|
||||
this.ci = ci;
|
||||
alias.setText(ci.alias);
|
||||
dbUrl.setText(ci.url);
|
||||
@@ -60,16 +78,32 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
|
||||
jar2.setText(ci.jar2);
|
||||
jar3.setText(ci.jar3);
|
||||
jar4.setText(ci.jar4);
|
||||
setVisible(true);
|
||||
return isOk;
|
||||
}
|
||||
|
||||
|
||||
/** Creates new form DbConnectionDialog
|
||||
* @param forNew */
|
||||
public DbConnectionDetailsEditor(java.awt.Frame parent, final String jdbcHelpURL, boolean forNew) {
|
||||
this(parent, jdbcHelpURL, forNew, null, false);
|
||||
}
|
||||
|
||||
private final Frame parent;
|
||||
|
||||
/** Creates new form DbConnectionDialog
|
||||
* @param forNew
|
||||
* @param b */
|
||||
public DbConnectionDetailsEditor(java.awt.Frame parent, final String jdbcHelpURL, boolean forNew, InfoBar infoBar, boolean needsTest) {
|
||||
super(parent, true);
|
||||
this.parent = parent;
|
||||
this.needsTest = needsTest;
|
||||
initComponents();
|
||||
if (forNew) {
|
||||
if (needsTest) {
|
||||
testConnectionButton.setVisible(false);
|
||||
} else {
|
||||
selectConnectionButton.setVisible(false);
|
||||
}
|
||||
if (infoBar != null) {
|
||||
UIUtil.replace(infoBarLabel, infoBar);
|
||||
} else if (forNew) {
|
||||
UIUtil.replace(infoBarLabel, new InfoBar("New Connection",
|
||||
"Enter connection credentials for the database.\n" +
|
||||
"Replace placeholders (\"<...>\") with appropriate URL parameters.", null));
|
||||
@@ -173,6 +207,7 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
|
||||
okButton = new javax.swing.JButton();
|
||||
cancelButton = new javax.swing.JButton();
|
||||
testConnectionButton = new javax.swing.JButton();
|
||||
selectConnectionButton = new javax.swing.JButton();
|
||||
jLabel11 = new javax.swing.JLabel();
|
||||
password = new javax.swing.JPasswordField();
|
||||
helpjdbc = new javax.swing.JLabel();
|
||||
@@ -288,14 +323,14 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
|
||||
|
||||
jPanel2.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
okButton.setText(" Ok ");
|
||||
okButton.setText(" Ok ");
|
||||
okButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
okButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 4);
|
||||
@@ -308,7 +343,7 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridx = 3;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 0);
|
||||
@@ -321,13 +356,27 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 12);
|
||||
jPanel2.add(testConnectionButton, gridBagConstraints);
|
||||
|
||||
selectConnectionButton.setText("Select Connection ");
|
||||
selectConnectionButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
selectConnectionButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 12);
|
||||
jPanel2.add(selectConnectionButton, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 100;
|
||||
@@ -335,6 +384,7 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 4, 0);
|
||||
jPanel1.add(jPanel2, gridBagConstraints);
|
||||
|
||||
jLabel11.setText(" ");
|
||||
@@ -448,14 +498,23 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
if (fillConnectionInfo()) {
|
||||
isOk = true;
|
||||
setVisible(false);
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
if (fillConnectionInfo()) {
|
||||
if (needsTest) {
|
||||
if (!DbConnectionDialog.testConnection(isVisible()? this : parent, ci)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
isOk = true;
|
||||
onClose(isOk, ci);
|
||||
}
|
||||
}//GEN-LAST:event_okButtonActionPerformed
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void onClose(boolean ok, ConnectionInfo info) {
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private boolean fillConnectionInfo() {
|
||||
boolean ok = true;
|
||||
Color red = new Color(255, 200, 180);
|
||||
@@ -486,13 +545,13 @@ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRS
|
||||
}
|
||||
|
||||
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||
setVisible(false);
|
||||
onClose(false, ci);
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
|
||||
private void testConnectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testConnectionButtonActionPerformed
|
||||
if (fillConnectionInfo()) {
|
||||
if (DbConnectionDialog.testConnection(this, ci)) {
|
||||
JOptionPane.showMessageDialog(this, "Successfully established connection.", "Connected", JOptionPane.INFORMATION_MESSAGE);
|
||||
if (DbConnectionDialog.testConnection(isVisible()? this : parent, ci)) {
|
||||
JOptionPane.showMessageDialog(isVisible()? this : parent, "Successfully established connection.", "Connected", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_testConnectionButtonActionPerformed
|
||||
@@ -509,6 +568,13 @@ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRS
|
||||
private void loadButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadButton4ActionPerformed
|
||||
}//GEN-LAST:event_loadButton4ActionPerformed
|
||||
|
||||
private void selectConnectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectConnectionButtonActionPerformed
|
||||
onSelect();
|
||||
}//GEN-LAST:event_selectConnectionButtonActionPerformed
|
||||
|
||||
protected void onSelect() {
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
public javax.swing.JTextField alias;
|
||||
private javax.swing.JButton cancelButton;
|
||||
@@ -539,7 +605,8 @@ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRS
|
||||
private javax.swing.JButton loadButton3;
|
||||
private javax.swing.JButton loadButton4;
|
||||
private javax.swing.JButton okButton;
|
||||
private javax.swing.JPasswordField password;
|
||||
javax.swing.JPasswordField password;
|
||||
private javax.swing.JButton selectConnectionButton;
|
||||
private javax.swing.JButton testConnectionButton;
|
||||
public javax.swing.JTextField user;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
@@ -241,7 +241,7 @@ public class DbConnectionDialog extends javax.swing.JDialog {
|
||||
if (render instanceof JLabel) {
|
||||
if (!isSelected) {
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
((JLabel) render)
|
||||
.setBackground((row % 2 == 0) ? BG1
|
||||
: BG2);
|
||||
@@ -354,11 +354,7 @@ public class DbConnectionDialog extends javax.swing.JDialog {
|
||||
|
||||
private boolean inRefresh = false;
|
||||
|
||||
private String jdbcHelpURL = "http://jailer.sourceforge.net/doc/jdbc.html?src=app";
|
||||
|
||||
public synchronized void setJdbcHelpURL(String jdbcHelpURL) {
|
||||
this.jdbcHelpURL = jdbcHelpURL;
|
||||
}
|
||||
public static final String jdbcHelpURL = "http://jailer.sourceforge.net/doc/jdbc.html?src=app";
|
||||
|
||||
/**
|
||||
* Refreshes the dialog after model changes.
|
||||
@@ -526,7 +522,7 @@ public class DbConnectionDialog extends javax.swing.JDialog {
|
||||
ConnectionInfo ci = new ConnectionInfo(executionContext);
|
||||
ci.alias = "Demo Scott";
|
||||
ci.driverClass = "org.h2.Driver";
|
||||
ci.jar1 = "lib" + File.separator + "h2-1.3.160.jar";
|
||||
ci.jar1 = "lib" + File.separator + "h2-1.3.175.jar";
|
||||
ci.url = "jdbc:h2:" + Environment.newFile("demo-scott").getPath();
|
||||
ci.user = "sa";
|
||||
ci.password = "";
|
||||
@@ -538,7 +534,7 @@ public class DbConnectionDialog extends javax.swing.JDialog {
|
||||
ConnectionInfo ci = new ConnectionInfo(executionContext);
|
||||
ci.alias = "Demo Sakila";
|
||||
ci.driverClass = "org.h2.Driver";
|
||||
ci.jar1 = "lib" + File.separator + "h2-1.3.160.jar";
|
||||
ci.jar1 = "lib" + File.separator + "h2-1.3.175.jar";
|
||||
ci.url = "jdbc:h2:" + Environment.newFile("demo-sakila").getPath();
|
||||
ci.user = "sa";
|
||||
ci.password = "";
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||
</SyntheticProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
@@ -439,7 +440,7 @@
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="80" green="80" red="80" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value=" (best for single-thread performance)"/>
|
||||
<Property name="text" type="java.lang.String" value=" (best for single-threaded performance)"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
@@ -452,7 +453,7 @@
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="80" green="80" red="80" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value=" (best for multi-thread performance)"/>
|
||||
<Property name="text" type="java.lang.String" value=" (best for multi-threaded performance)"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
@@ -465,7 +466,7 @@
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="80" green="80" red="80" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value=" (no write-access needed)"/>
|
||||
<Property name="text" type="java.lang.String" value=" (no write-access required)"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,6 @@ import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
@@ -218,7 +217,7 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
* The execution context.
|
||||
*/
|
||||
private final ExecutionContext executionContext;
|
||||
|
||||
|
||||
/**
|
||||
* Creates new form ModelTree.
|
||||
*
|
||||
@@ -240,12 +239,6 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
}
|
||||
};
|
||||
columnMapperDialog = new ColumnMapperDialog(extractionModelFrame, parametersGetter);
|
||||
try {
|
||||
dataModel = new DataModel(executionContext);
|
||||
} catch (Exception e) {
|
||||
UIUtil.showException(this, "Error in Data Model", e);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (extractionModelFile == null || !new File(extractionModelFile).exists()) {
|
||||
needsSave = extractionModelFile != null;
|
||||
@@ -282,10 +275,10 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
public void itemStateChanged(ItemEvent arg0) {
|
||||
Object o1 = rootTable.getSelectedItem();
|
||||
Object o2 = subjectTable.getSelectedItem();
|
||||
resetFocus.setEnabled(!(o1 == null && o2 == null || o1 != null && o1.equals(o2)));
|
||||
resetFocus.setEnabled(!(o1 == null && o2 == null || o1 != null && o1.equals(o2)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
rootTable.addItemListener(aListener);
|
||||
subjectTable.addItemListener(aListener);
|
||||
|
||||
@@ -320,6 +313,10 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
|
||||
closureView.addTabComponent("Closure Border", closureBorderView.getContentPane());
|
||||
closureBorderView.dispose();
|
||||
|
||||
restrDepsView = extractionModelFrame.restrictedDependenciesView.getContentPane();
|
||||
closureView.addTabComponent("Restricted Dependencies", restrDepsView);
|
||||
extractionModelFrame.restrictedDependenciesView.dispose();
|
||||
|
||||
Container cVContentPane = closureView.getContentPane();
|
||||
closureView.dispose();
|
||||
@@ -402,7 +399,7 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
});
|
||||
final TableCellRenderer defaultTableCellRenderer = restrictionsTable.getDefaultRenderer(String.class);
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
restrictionsTable.setDefaultRenderer(Object.class, new TableCellRenderer() {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table,
|
||||
@@ -480,6 +477,15 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
onApply(false);
|
||||
}
|
||||
});
|
||||
restrictionEditor.fkToNullCheckBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (currentAssociation != null) {
|
||||
currentAssociation.setOrResetFKNullFilter(restrictionEditor.fkToNullCheckBox.isSelected());
|
||||
}
|
||||
onApply(false);
|
||||
}
|
||||
});
|
||||
// restrictionEditor.jump.addActionListener(new ActionListener() {
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// onJump();
|
||||
@@ -659,7 +665,7 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
/**
|
||||
* The "closure view" component.
|
||||
*/
|
||||
private ClosureView closureView;
|
||||
ClosureView closureView;
|
||||
|
||||
void setOrientation(boolean horizontal) {
|
||||
isHorizontalLayout = horizontal;
|
||||
@@ -1388,7 +1394,7 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
if (selNode instanceof Association) {
|
||||
table = ((Association) selNode).destination;
|
||||
}
|
||||
JPopupMenu popup = graphView.createPopupMenu(table, false);
|
||||
JPopupMenu popup = graphView.createPopupMenu(table, null, false);
|
||||
popup.show(evt.getComponent(), evt.getX(), evt.getY());
|
||||
}
|
||||
}
|
||||
@@ -1763,7 +1769,11 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
}
|
||||
|
||||
private void initRestrictedDependencyWarningField() {
|
||||
restrictionEditor.restrictedDependencyWarning.setVisible(currentAssociation != null && !ScriptFormat.XML.equals(scriptFormat) && currentAssociation.isInsertDestinationBeforeSource() && currentAssociation.isRestricted());
|
||||
boolean restrictedDep = currentAssociation != null && !ScriptFormat.XML.equals(scriptFormat) && currentAssociation.isInsertDestinationBeforeSource() && currentAssociation.isRestricted();
|
||||
restrictionEditor.restrictedDependencyWarning.setVisible(restrictedDep);
|
||||
restrictionEditor.fkToNullCheckBox.setVisible(restrictedDep);
|
||||
restrictionEditor.fkToNullCheckBox.setEnabled(restrictedDep && currentAssociation.hasNullableFK());
|
||||
restrictionEditor.fkToNullCheckBox.setSelected(restrictedDep && currentAssociation.fkHasNullFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1801,6 +1811,11 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
needsSave = true;
|
||||
extractionModelFrame.updateTitle(needsSave);
|
||||
}
|
||||
|
||||
if (restrictionEditor.restricted.isSelected() && currentAssociation.hasNullableFK() && currentAssociation.fkHasNullFilter()) {
|
||||
currentAssociation.setOrResetFKNullFilter(false);
|
||||
}
|
||||
|
||||
String condition;
|
||||
if (restrictionEditor.ignore.getModel().isSelected()) {
|
||||
condition = "ignore";
|
||||
@@ -2048,10 +2063,10 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
private void additionalSubjectsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_additionalSubjectsButtonActionPerformed
|
||||
AdditionalSubjectsDialog additionalSubjectsDialog;
|
||||
try {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(this);
|
||||
additionalSubjectsDialog = new AdditionalSubjectsDialog(extractionModelFrame, extractionModel, subject, condition.getText());
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(this);
|
||||
}
|
||||
if (additionalSubjectsDialog.edit()) {
|
||||
needsSave = true;
|
||||
@@ -2223,24 +2238,28 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (DefaultMutableTreeNode node: treeNodes) {
|
||||
if (node.getChildCount() > 0) {
|
||||
Table t = null;
|
||||
Association a = null;
|
||||
if (node.getUserObject() instanceof Association) {
|
||||
a = (Association) node.getUserObject();
|
||||
t = a.destination;
|
||||
}
|
||||
if (t != null && a != null && table.equals(t)) {
|
||||
select(a);
|
||||
TreePath treePath = new TreePath(node.getPath());
|
||||
tree.expandPath(treePath);
|
||||
for (int i = 0; i < node.getChildCount(); ++i) {
|
||||
DefaultMutableTreeNode c = (DefaultMutableTreeNode) node.getChildAt(i);
|
||||
tree.collapsePath(new TreePath(c.getPath()));
|
||||
for (boolean checkVisibility: new boolean [] { true, false }) {
|
||||
for (DefaultMutableTreeNode node: treeNodes) {
|
||||
if (node.getChildCount() > 0) {
|
||||
Table t = null;
|
||||
Association a = null;
|
||||
if (node.getUserObject() instanceof Association) {
|
||||
a = (Association) node.getUserObject();
|
||||
t = a.destination;
|
||||
}
|
||||
if (t != null && a != null && table.equals(t)) {
|
||||
if (!checkVisibility || (graphView.isTableVisible(a.source) && graphView.isTableVisible(a.destination))) {
|
||||
select(a);
|
||||
TreePath treePath = new TreePath(node.getPath());
|
||||
tree.expandPath(treePath);
|
||||
for (int i = 0; i < node.getChildCount(); ++i) {
|
||||
DefaultMutableTreeNode c = (DefaultMutableTreeNode) node.getChildAt(i);
|
||||
tree.collapsePath(new TreePath(c.getPath()));
|
||||
}
|
||||
tree.scrollPathToVisible(treePath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
tree.scrollPathToVisible(treePath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2931,7 +2950,9 @@ public class ExtractionModelEditor extends javax.swing.JPanel {
|
||||
private javax.swing.JPanel xmlMappingPanel;
|
||||
private javax.swing.JButton xmlTagApply;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
|
||||
Container restrDepsView;
|
||||
|
||||
private Icon dropDownIcon;
|
||||
private Icon conditionEditorIcon;
|
||||
private Icon conditionEditorSelectedIcon;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
|
||||
<Form version="1.9" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
|
||||
<NonVisualComponents>
|
||||
<Component class="javax.swing.ButtonGroup" name="steptimeGroup">
|
||||
</Component>
|
||||
@@ -471,14 +471,6 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cycleViewActionPerformed"/>
|
||||
</Events>
|
||||
</MenuItem>
|
||||
<MenuItem class="javax.swing.JMenuItem" name="restrictedDependenciesToolMenuItem">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Restricted Dependencies View"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="restrictedDependenciesToolMenuItemActionPerformed"/>
|
||||
</Events>
|
||||
</MenuItem>
|
||||
<MenuItem class="javax.swing.JMenuItem" name="renderHtml">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="HTML Rendering"/>
|
||||
@@ -564,14 +556,80 @@
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="editorPanel">
|
||||
<Container class="javax.swing.JLayeredPane" name="jLayeredPane1">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="editorPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="updateInfoPanel">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="ec" green="ff" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="32" insetsRight="24" anchor="14" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="updateInfoLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Release x available"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="4" insetsRight="4" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="downloadButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Download"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="downloadButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="4" insetsBottom="4" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="jButton1">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Close"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="2" insetsBottom="4" insetsRight="4" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package net.sf.jailer.ui;
|
||||
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Color;
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
@@ -44,12 +44,12 @@ import java.util.logging.Logger;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.InputMap;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.ToolTipManager;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UIManager.LookAndFeelInfo;
|
||||
import javax.swing.WindowConstants;
|
||||
@@ -69,12 +69,14 @@ import net.sf.jailer.datamodel.Table;
|
||||
import net.sf.jailer.ddl.DDLCreator;
|
||||
import net.sf.jailer.extractionmodel.ExtractionModel;
|
||||
import net.sf.jailer.extractionmodel.ExtractionModel.AdditionalSubject;
|
||||
import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
|
||||
import net.sf.jailer.modelbuilder.ModelBuilder;
|
||||
import net.sf.jailer.render.HtmlDataModelRenderer;
|
||||
import net.sf.jailer.subsetting.ScriptFormat;
|
||||
import net.sf.jailer.ui.associationproposer.AssociationProposerView;
|
||||
import net.sf.jailer.ui.databrowser.DataBrowser;
|
||||
import net.sf.jailer.ui.progress.ExportAndDeleteStageProgressListener;
|
||||
import net.sf.jailer.ui.util.UpdateInfoManager;
|
||||
import net.sf.jailer.util.CancellationHandler;
|
||||
import net.sf.jailer.util.PrintUtil;
|
||||
|
||||
@@ -140,9 +142,33 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
this.executionContext = executionContext;
|
||||
initComponents();
|
||||
initSandbox();
|
||||
initAnimationSteptime();
|
||||
UpdateInfoManager.checkUpdateAvailability(updateInfoPanel, updateInfoLabel);
|
||||
initAnimationSteptime();
|
||||
isHorizontalLayout = isHorizonal;
|
||||
horizontalLayoutMenuItem.setSelected(isHorizontalLayout);
|
||||
|
||||
restrictedDependenciesView = new RestrictedDependenciesListDialog(this) {
|
||||
private static final long serialVersionUID = -7426280043553389753L;
|
||||
@Override
|
||||
protected Table getRoot() {
|
||||
return extractionModelEditor == null? null : extractionModelEditor.root;
|
||||
}
|
||||
@Override
|
||||
protected DataModel getDataModel() {
|
||||
return extractionModelEditor == null? null : extractionModelEditor.dataModel;
|
||||
}
|
||||
@Override
|
||||
protected void removeRestrictions(Collection<Association> associations) {
|
||||
if (extractionModelEditor != null) {
|
||||
extractionModelEditor.removeRestrictions(associations);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onSelect(Association association) {
|
||||
extractionModelEditor.select(association);
|
||||
}
|
||||
};
|
||||
|
||||
editorPanel.add(extractionModelEditor = new ExtractionModelEditor(extractionModelFile, this, isHorizontalLayout, getConnectivityState(), getConnectivityStateToolTip(), executionContext), "editor");
|
||||
extractionModelEditor.extractionModelFile = extractionModelFile;
|
||||
pack();
|
||||
@@ -173,28 +199,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
|
||||
updateMenuItems();
|
||||
|
||||
restrictedDependenciesView = new RestrictedDependenciesListDialog(this) {
|
||||
private static final long serialVersionUID = -7426280043553389753L;
|
||||
@Override
|
||||
protected Table getRoot() {
|
||||
return extractionModelEditor == null? null : extractionModelEditor.root;
|
||||
}
|
||||
@Override
|
||||
protected DataModel getDataModel() {
|
||||
return extractionModelEditor == null? null : extractionModelEditor.dataModel;
|
||||
}
|
||||
@Override
|
||||
protected void removeRestrictions(Collection<Association> associations) {
|
||||
if (extractionModelEditor != null) {
|
||||
extractionModelEditor.removeRestrictions(associations);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onSelect(Association association) {
|
||||
extractionModelEditor.select(association);
|
||||
}
|
||||
};
|
||||
|
||||
cycleViewDialog = new CyclesView(this);
|
||||
filterEditorDialog = new FilterEditorDialog(this, new ParameterSelector.ParametersGetter() {
|
||||
@Override
|
||||
@@ -214,7 +218,8 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
for (final String item: list) {
|
||||
JMenuItem menuItem = new JMenuItem(item.split(",")[0]);
|
||||
sandBox.add(menuItem);
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
final ActionListener a;
|
||||
menuItem.addActionListener(a = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
@@ -222,12 +227,20 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
String tmpFileName = Configuration.getInstance().createTempFile().getPath();
|
||||
extractionModelEditor.save(tmpFileName);
|
||||
ExtractionModel extractionModel = new ExtractionModel(tmpFileName, new HashMap<String, String>(), new HashMap<String, String>(), executionContext);
|
||||
c.getMethod("main", ExtractionModel.class).invoke(c.newInstance(), extractionModel);
|
||||
c.getMethod("main", ExtractionModel.class, JFrame.class).invoke(c.newInstance(), extractionModel, ExtractionModelFrame.this);
|
||||
} catch (Throwable t) {
|
||||
UIUtil.showException(ExtractionModelFrame.this, "Error", t);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (menuItem.getText().endsWith("!")) {
|
||||
UIUtil.invokeLater(4, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
a.actionPerformed(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
@@ -280,7 +293,12 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
steptimeGroup = new javax.swing.ButtonGroup();
|
||||
jLayeredPane1 = new javax.swing.JLayeredPane();
|
||||
editorPanel = new javax.swing.JPanel();
|
||||
updateInfoPanel = new javax.swing.JPanel();
|
||||
updateInfoLabel = new javax.swing.JLabel();
|
||||
downloadButton = new javax.swing.JButton();
|
||||
jButton1 = new javax.swing.JButton();
|
||||
jMenuBar2 = new javax.swing.JMenuBar();
|
||||
fileMenu = new javax.swing.JMenu();
|
||||
newModel = new javax.swing.JMenuItem();
|
||||
@@ -338,7 +356,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
openDataBrowserItem = new javax.swing.JMenuItem();
|
||||
queryBuilder = new javax.swing.JMenuItem();
|
||||
cycleView = new javax.swing.JMenuItem();
|
||||
restrictedDependenciesToolMenuItem = new javax.swing.JMenuItem();
|
||||
renderHtml = new javax.swing.JMenuItem();
|
||||
jMenu2 = new javax.swing.JMenu();
|
||||
helpContent = new javax.swing.JMenuItem();
|
||||
@@ -365,12 +382,68 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
});
|
||||
getContentPane().setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
jLayeredPane1.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
editorPanel.setLayout(new java.awt.CardLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
getContentPane().add(editorPanel, gridBagConstraints);
|
||||
jLayeredPane1.add(editorPanel, gridBagConstraints);
|
||||
|
||||
updateInfoPanel.setBackground(new java.awt.Color(255, 255, 236));
|
||||
updateInfoPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
updateInfoLabel.setText("Release x available");
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
|
||||
updateInfoPanel.add(updateInfoLabel, gridBagConstraints);
|
||||
|
||||
downloadButton.setText("Download");
|
||||
downloadButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
downloadButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 4, 4, 0);
|
||||
updateInfoPanel.add(downloadButton, gridBagConstraints);
|
||||
|
||||
jButton1.setText("Close");
|
||||
jButton1.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
jButton1ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 2, 4, 4);
|
||||
updateInfoPanel.add(jButton1, gridBagConstraints);
|
||||
|
||||
jLayeredPane1.setLayer(updateInfoPanel, javax.swing.JLayeredPane.MODAL_LAYER);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 32, 24);
|
||||
jLayeredPane1.add(updateInfoPanel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
getContentPane().add(jLayeredPane1, gridBagConstraints);
|
||||
|
||||
fileMenu.setText("File");
|
||||
fileMenu.addActionListener(new java.awt.event.ActionListener() {
|
||||
@@ -759,14 +832,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
});
|
||||
jMenu3.add(cycleView);
|
||||
|
||||
restrictedDependenciesToolMenuItem.setText("Restricted Dependencies View");
|
||||
restrictedDependenciesToolMenuItem.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
restrictedDependenciesToolMenuItemActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
jMenu3.add(restrictedDependenciesToolMenuItem);
|
||||
|
||||
renderHtml.setText("HTML Rendering");
|
||||
renderHtml.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
@@ -1008,6 +1073,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
try {
|
||||
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = new PrivilegedSessionProviderDialog.Provider(ExtractionModelFrame.this);
|
||||
if (connectToDBIfNeeded("Analyze Database")) {
|
||||
List<String> args = new ArrayList<String>();
|
||||
args.add("build-model-wo-merge");
|
||||
@@ -1016,13 +1082,13 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
AnalyseOptionsDialog analyseOptionsDialog = new AnalyseOptionsDialog(ExtractionModelFrame.this, extractionModelEditor.dataModel, executionContext);
|
||||
boolean[] isDefaultSchema = new boolean[1];
|
||||
String[] defaultSchema = new String[1];
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(ExtractionModelFrame.this);
|
||||
List<String> schemas;
|
||||
try {
|
||||
CancellationHandler.reset(null);
|
||||
schemas = dbConnectionDialog.getDBSchemas(defaultSchema);
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(ExtractionModelFrame.this);
|
||||
}
|
||||
if (analyseOptionsDialog.edit(schemas, defaultSchema[0], isDefaultSchema, dbConnectionDialog.currentConnection.user)) {
|
||||
String schema = analyseOptionsDialog.getSelectedSchema();
|
||||
@@ -1049,6 +1115,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
UIUtil.showException(ExtractionModelFrame.this, "Error", e);
|
||||
} finally {
|
||||
ModelBuilder.assocFilter = null;
|
||||
JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1084,11 +1151,10 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
if (restrictedDependency != null) {
|
||||
switch (JOptionPane.showOptionDialog(this,
|
||||
"Dependency from '" + restrictedDependency.source.getName() + "' to '" + restrictedDependency.destination.getName() + "'\n" +
|
||||
"is restricted.\nReferential integrity is not guaranteed!", "Restricted Dependency", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "Ok", "Cancel", "Show Dependency" }, "Cancel")) {
|
||||
"is restricted.\nReferential integrity is not guaranteed!", "Restricted Dependency", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "Ok", "Cancel", "Show dependency" }, "Cancel")) {
|
||||
case 1: return;
|
||||
case 2:
|
||||
restrictedDependenciesView.setVisible(true);
|
||||
restrictedDependenciesView.toFront();
|
||||
extractionModelEditor.closureView.selectTabComponent(extractionModelEditor.restrDepsView);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1111,7 +1177,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
List<String> args = new ArrayList<String>();
|
||||
args.add(tmpFileName != null? tmpFileName : extractionModelEditor.extractionModelFile);
|
||||
dbConnectionDialog.addDbArgs(args);
|
||||
Session.closeTemporaryTableSession();
|
||||
BasicDataSource dataSource = new BasicDataSource(dbConnectionDialog.currentConnection.driverClass, dbConnectionDialog.currentConnection.url, dbConnectionDialog.currentConnection.user, dbConnectionDialog.getPassword(), 0, dbConnectionDialog.currentJarURLs());
|
||||
Session session = SessionForUI.createSession(dataSource, dataSource.dbms, this);
|
||||
|
||||
@@ -1131,7 +1196,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
|
||||
ExportDialog exportDialog = new ExportDialog(this, extractionModelEditor.dataModel, extractionModelEditor.getSubject(), extractionModelEditor.getSubjectCondition(), extractionModelEditor.extractionModel.additionalSubjects, session, args, dbConnectionDialog.getUser(), dbConnectionDialog.getPassword(), checkRI, dbConnectionDialog, extractionModelEditor.extractionModelFile, executionContext);
|
||||
session.shutDown();
|
||||
Session.closeTemporaryTableSession();
|
||||
if (exportDialog.isOk()) {
|
||||
exportDialog.fillCLIArgs(args);
|
||||
List<String> ddlArgs = new ArrayList<String>();
|
||||
@@ -1198,7 +1262,9 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
private Association findRestrictedDependency(DataModel dataModel) {
|
||||
for (Association association: dataModel.namedAssociations.values()) {
|
||||
if (association.isInsertDestinationBeforeSource() && association.isRestricted()) {
|
||||
return association;
|
||||
if (!association.fkHasNullFilter()) {
|
||||
return association;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -1326,10 +1392,10 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
load(modelFile);
|
||||
} else {
|
||||
try {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
createFrame(modelFile, false);
|
||||
UIUtil.setWaitCursor(this);
|
||||
createFrame(modelFile, false, executionContext);
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1365,7 +1431,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
JOptionPane.showMessageDialog(this, "Unable to load \"" + new File(modelFile).getName() + "\"\nExtraction model is assigned to data model \"" + DataModelManager.getModelDetails(dmf, executionContext).a + "\"", "Wrong Data Model", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(this);
|
||||
extractionModelEditor.extractionModelFrame = null;
|
||||
editorPanel.remove(extractionModelEditor);
|
||||
extractionModelEditor = null;
|
||||
@@ -1378,13 +1444,13 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
} catch (Throwable t) {
|
||||
UIUtil.showException(this, "Error", t);
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void newModelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newModelActionPerformed
|
||||
try {
|
||||
createFrame(null, false);
|
||||
createFrame(null, false, executionContext);
|
||||
} catch (Throwable t) {
|
||||
UIUtil.showException(this, "Error", t);
|
||||
} finally {
|
||||
@@ -1393,7 +1459,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
|
||||
private void reload() {
|
||||
try {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(this);
|
||||
extractionModelEditor.extractionModelFrame = null;
|
||||
editorPanel.remove(extractionModelEditor);
|
||||
editorPanel.add(extractionModelEditor = new ExtractionModelEditor(extractionModelEditor.extractionModelFile, this, isHorizontalLayout, getConnectivityState(), getConnectivityStateToolTip(), executionContext), "editor");
|
||||
@@ -1405,7 +1471,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
} catch (Throwable t) {
|
||||
UIUtil.showException(this, "Error", t);
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1626,11 +1692,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
extractionModelEditor.closureBorderView.toFront();
|
||||
}//GEN-LAST:event_closureBorderToolMenuItemActionPerformed
|
||||
|
||||
private void restrictedDependenciesToolMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_restrictedDependenciesToolMenuItemActionPerformed
|
||||
restrictedDependenciesView.setVisible(true);
|
||||
restrictedDependenciesView.toFront();
|
||||
}//GEN-LAST:event_restrictedDependenciesToolMenuItemActionPerformed
|
||||
|
||||
private void reloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reloadActionPerformed
|
||||
try {
|
||||
if (extractionModelEditor.extractionModelFile == null) {
|
||||
@@ -1665,6 +1726,15 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
});
|
||||
}//GEN-LAST:event_columnOrderItemActionPerformed
|
||||
|
||||
private void downloadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadButtonActionPerformed
|
||||
updateInfoPanel.setVisible(false);
|
||||
UpdateInfoManager.download();
|
||||
}//GEN-LAST:event_downloadButtonActionPerformed
|
||||
|
||||
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
|
||||
updateInfoPanel.setVisible(false);
|
||||
}//GEN-LAST:event_jButton1ActionPerformed
|
||||
|
||||
private void executeAndReload(Callable<Boolean> callable) {
|
||||
File tmpFile = null;
|
||||
String extractionModelFile = extractionModelEditor.extractionModelFile;
|
||||
@@ -1730,12 +1800,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
* Changes some nimbus LAF defaults.
|
||||
*/
|
||||
public static void customizeNimbus() {
|
||||
try {
|
||||
ToolTipManager.sharedInstance().setInitialDelay(500);
|
||||
ToolTipManager.sharedInstance().setDismissDelay(7000);
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1797,6 +1862,12 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
if (new Integer(10).equals(dSize)) {
|
||||
UIManager.put("SplitPane.dividerSize", new Integer(14));
|
||||
}
|
||||
|
||||
if (UIManager.get("InternalFrame:InternalFrameTitlePane[Enabled].textForeground") instanceof Color) {
|
||||
UIManager.put("InternalFrame:InternalFrameTitlePane[Enabled].textForeground", Color.BLUE);
|
||||
}
|
||||
|
||||
UIUtil.prepareUI();
|
||||
} catch (Exception x) {
|
||||
}
|
||||
|
||||
@@ -1808,7 +1879,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
file = commandLine.arguments.get(0);
|
||||
}
|
||||
}
|
||||
createFrame(file, true);
|
||||
createFrame(file, true, null);
|
||||
} catch (Throwable e) {
|
||||
UIUtil.showException(null, "Error", e);
|
||||
}
|
||||
@@ -1865,11 +1936,15 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
return extractionModelFrame;
|
||||
}
|
||||
|
||||
public static void createFrame(String file, final boolean withStartupWizzard) {
|
||||
public static void createFrame(String file, final boolean withStartupWizzard, ExecutionContext executionContext) {
|
||||
try {
|
||||
final String finalFile = file;
|
||||
if (file != null && new File(file).exists()) {
|
||||
ExecutionContext executionContext = new ExecutionContext(CommandLineInstance.getInstance());
|
||||
if (executionContext == null) {
|
||||
executionContext = new ExecutionContext(CommandLineInstance.getInstance());
|
||||
} else {
|
||||
executionContext = new ExecutionContext(executionContext);
|
||||
}
|
||||
DataModelManager.setCurrentModelSubfolder(ExtractionModel.loadDatamodelFolder(file, executionContext), executionContext);
|
||||
createFrame(finalFile, true, true, null, executionContext);
|
||||
} else {
|
||||
@@ -1951,6 +2026,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
private javax.swing.JMenuItem dataExport;
|
||||
private javax.swing.JMenuItem dataImport;
|
||||
private javax.swing.JMenuItem disconnectDb;
|
||||
private javax.swing.JButton downloadButton;
|
||||
private javax.swing.JMenu editMenu;
|
||||
private javax.swing.JPanel editorPanel;
|
||||
private javax.swing.JMenuItem exit;
|
||||
@@ -1962,6 +2038,8 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
private javax.swing.JMenuItem helpForum;
|
||||
private javax.swing.JCheckBoxMenuItem horizontalLayoutMenuItem;
|
||||
private javax.swing.JMenuItem ignoreAll;
|
||||
private javax.swing.JButton jButton1;
|
||||
private javax.swing.JLayeredPane jLayeredPane1;
|
||||
private javax.swing.JMenu jMenu1;
|
||||
private javax.swing.JMenu jMenu2;
|
||||
private javax.swing.JMenu jMenu3;
|
||||
@@ -1991,7 +2069,6 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
public javax.swing.JMenuItem reload;
|
||||
private javax.swing.JMenuItem removeAllRestrictions;
|
||||
private javax.swing.JMenuItem renderHtml;
|
||||
private javax.swing.JMenuItem restrictedDependenciesToolMenuItem;
|
||||
private javax.swing.JMenuItem save;
|
||||
private javax.swing.JMenuItem saveAs;
|
||||
private javax.swing.JCheckBoxMenuItem showIgnored;
|
||||
@@ -2008,6 +2085,8 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
private javax.swing.ButtonGroup steptimeGroup;
|
||||
private javax.swing.JMenuItem tutorial;
|
||||
private javax.swing.JMenuItem updateDataModel;
|
||||
private javax.swing.JLabel updateInfoLabel;
|
||||
private javax.swing.JPanel updateInfoPanel;
|
||||
private javax.swing.JMenu view;
|
||||
private javax.swing.JMenu viewMenu;
|
||||
private javax.swing.JMenuItem zoomToFit;
|
||||
@@ -2015,4 +2094,4 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
|
||||
|
||||
private static final long serialVersionUID = -2252377308370736756L;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ public abstract class ListEditor<T> extends javax.swing.JPanel {
|
||||
deleteButton.setVisible(false);
|
||||
}
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
final Color BGSEL = new Color(0, 200, 255);
|
||||
TableCellRenderer renderer = new DefaultTableCellRenderer() {
|
||||
@Override
|
||||
|
||||
@@ -108,8 +108,10 @@ public class NeighborhoodPanel extends javax.swing.JPanel {
|
||||
length = graphView.getHeight() / (getFontMetrics(font).getHeight() + 2) - 12;
|
||||
if (length < 2) {
|
||||
length = 2;
|
||||
} else if (length > 20) {
|
||||
length = 20;
|
||||
}
|
||||
|
||||
|
||||
initTableList(dataModel, table, hideIgnored, graphView);
|
||||
createTableLinks(dataModel, table, graphView, hideIgnored);
|
||||
|
||||
@@ -161,7 +163,7 @@ public class NeighborhoodPanel extends javax.swing.JPanel {
|
||||
@Override
|
||||
protected void onRightClick(MouseEvent e) {
|
||||
if (t != null) {
|
||||
JPopupMenu popup = graphView.createPopupMenu(t, true);
|
||||
JPopupMenu popup = graphView.createPopupMenu(t, null, true);
|
||||
popup.show(e.getComponent(), e.getX(), e.getY());
|
||||
popup.addPopupMenuListener(new PopupMenuListener() {
|
||||
@Override
|
||||
|
||||
@@ -64,7 +64,7 @@ public class ParameterSelector extends javax.swing.JPanel {
|
||||
isSelected, hasFocus, row, column);
|
||||
if (render instanceof JLabel && !isSelected) {
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
((JLabel) render)
|
||||
.setBackground((row % 2 == 0) ? BG1
|
||||
: BG2);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||
</SyntheticProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="detailsContainerPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2007 - 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package net.sf.jailer.ui;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import net.sf.jailer.ExecutionContext;
|
||||
import net.sf.jailer.JailerVersion;
|
||||
import net.sf.jailer.database.BasicDataSource;
|
||||
import net.sf.jailer.database.Session;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
|
||||
import net.sf.jailer.ui.DbConnectionDialog.ConnectionInfo;
|
||||
import net.sf.jailer.util.ClasspathUtil;
|
||||
|
||||
/**
|
||||
* Asks for an alternative connection if the database analyzers connection has
|
||||
* insufficient privileges to analyze a certain schema.
|
||||
*
|
||||
* @author Ralf Wisser
|
||||
*/
|
||||
public class PrivilegedSessionProviderDialog extends javax.swing.JDialog {
|
||||
|
||||
public static class Provider implements JDBCMetaDataBasedModelElementFinder.PrivilegedSessionProvider {
|
||||
private final Frame parent;
|
||||
private Set<String> tabu = new HashSet<String>();
|
||||
|
||||
public Provider(Frame parent) {
|
||||
synchronized(this) {
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session askForSessionWithPermissionToReadSchema(final Session session, final Table view, final String schema, final String tableName,
|
||||
final ExecutionContext executionContext) {
|
||||
final Frame theParent;
|
||||
synchronized(this) {
|
||||
theParent = parent;
|
||||
}
|
||||
if (tabu.contains(schema)) {
|
||||
return null;
|
||||
}
|
||||
final AtomicReference<Session> newSession = new AtomicReference<>();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
InfoBar infoBar = new InfoBar("Insufficient Privileges",
|
||||
"Need to analyze schema \"" + schema + "\" because\n" +
|
||||
"view \"" + view.getName() + "\" is based on table \"" + schema + "." + tableName +"\".\n" +
|
||||
"but that's not possible with the current connection.\n ",
|
||||
"Please choose an alternative connection with the required privileges."
|
||||
);
|
||||
final PrivilegedSessionProviderDialog dialog = new PrivilegedSessionProviderDialog(theParent);
|
||||
ConnectionInfo ci = new ConnectionInfo();
|
||||
final DbConnectionDialog connectionDialog = new DbConnectionDialog(theParent, JailerVersion.APPLICATION_NAME, infoBar, executionContext, true) {
|
||||
@Override
|
||||
protected boolean isAssignedToDataModel(String dataModelFolder) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
final DbConnectionDetailsEditor detailsEditor = new DbConnectionDetailsEditor(theParent, DbConnectionDialog.jdbcHelpURL, false, infoBar, true) {
|
||||
@Override
|
||||
protected void onClose(boolean ok, ConnectionInfo info) {
|
||||
dialog.setVisible(false);
|
||||
if (ok) {
|
||||
try {
|
||||
BasicDataSource dataSource = new BasicDataSource(info.driverClass,
|
||||
info.url, info.user,
|
||||
info.password, 0, ClasspathUtil.toURLArray(info.jar1, info.jar2, info.jar3, info.jar4));
|
||||
newSession.set(new Session(dataSource, dataSource.dbms));
|
||||
} catch (Exception e) {
|
||||
UIUtil.showException(theParent, "Error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onSelect() {
|
||||
if (connectionDialog.connect("Analyze Database")) {
|
||||
try {
|
||||
setDetails((ConnectionInfo) connectionDialog.currentConnection.clone());
|
||||
} catch (CloneNotSupportedException e) {
|
||||
setDetails(connectionDialog.currentConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
ci.alias = "(temporary)";
|
||||
ci.driverClass = session.driverClassName;
|
||||
ci.url = session.dbUrl;
|
||||
ci.user = schema;
|
||||
detailsEditor.setDetails(ci);
|
||||
dialog.detailsContainerPanel.add(detailsEditor.getContentPane());
|
||||
detailsEditor.password.grabFocus();
|
||||
dialog.setLocation(100, 150);
|
||||
dialog.pack();
|
||||
dialog.setSize(Math.max(500, dialog.getWidth()), dialog.getHeight());
|
||||
UIUtil.initPeer();
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
Session result = newSession.get();
|
||||
if (result == null) {
|
||||
tabu.add(schema);
|
||||
}
|
||||
return result;
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new form PrivilegedSessionProvider
|
||||
*/
|
||||
public PrivilegedSessionProviderDialog(Frame parent) {
|
||||
super(parent, true);
|
||||
initComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
detailsContainerPanel = new javax.swing.JPanel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
getContentPane().setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
jPanel1.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
detailsContainerPanel.setLayout(new java.awt.BorderLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
jPanel1.add(detailsContainerPanel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
getContentPane().add(jPanel1, gridBagConstraints);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JPanel detailsContainerPanel;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
@@ -198,6 +198,19 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JCheckBox" name="fkToNullCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Set foreign key columns to null"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="1"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="10" gridWidth="6" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel4">
|
||||
|
||||
@@ -72,6 +72,7 @@ public class RestrictionEditor extends javax.swing.JPanel {
|
||||
jPanel9 = new javax.swing.JPanel();
|
||||
restriction = new javax.swing.JTextField();
|
||||
apply = new javax.swing.JButton();
|
||||
fkToNullCheckBox = new javax.swing.JCheckBox();
|
||||
jPanel4 = new javax.swing.JPanel();
|
||||
columnsA = new javax.swing.JLabel();
|
||||
source = new javax.swing.JLabel();
|
||||
@@ -168,6 +169,15 @@ public class RestrictionEditor extends javax.swing.JPanel {
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
|
||||
jPanel7.add(jPanel9, gridBagConstraints);
|
||||
|
||||
fkToNullCheckBox.setText("Set foreign key columns to null");
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 10;
|
||||
gridBagConstraints.gridwidth = 6;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.insets = new java.awt.Insets(2, 0, 0, 0);
|
||||
jPanel7.add(fkToNullCheckBox, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 3;
|
||||
@@ -257,6 +267,7 @@ public class RestrictionEditor extends javax.swing.JPanel {
|
||||
javax.swing.JLabel columnsA;
|
||||
javax.swing.JLabel columnsB;
|
||||
public javax.swing.JLabel destination;
|
||||
public javax.swing.JCheckBox fkToNullCheckBox;
|
||||
public javax.swing.JRadioButton ignore;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel4;
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,85,0,0,1,-63"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
@@ -200,5 +200,14 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="plugInPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="10" gridY="1" gridWidth="1" gridHeight="3" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
||||
@@ -17,7 +17,6 @@ package net.sf.jailer.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridLayout;
|
||||
@@ -30,6 +29,8 @@ import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -48,6 +49,8 @@ import javax.swing.DefaultListModel;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
@@ -56,6 +59,8 @@ import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
@@ -80,29 +85,46 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
public interface Prepare {
|
||||
void prepare(Set<MDSchema> selectedSchemas);
|
||||
}
|
||||
|
||||
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final String titel, final Runnable onSuccess) {
|
||||
return createSearchButton(owner, comboBox, titel, onSuccess, null);
|
||||
|
||||
public interface AdditionalComponentFactory {
|
||||
JComponent create(StringSearchPanel searchPanel);
|
||||
}
|
||||
|
||||
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess) {
|
||||
return createSearchButton(owner, comboBox, titel, onSuccess, false);
|
||||
}
|
||||
|
||||
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess, boolean alternativeIcon) {
|
||||
return createSearchButton(owner, comboBox, titel, onSuccess, null, alternativeIcon);
|
||||
}
|
||||
|
||||
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final String titel, final Runnable onSuccess, final Prepare prepare) {
|
||||
return createSearchButton(owner, comboBox, titel, onSuccess, null, null, null);
|
||||
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess, final Prepare prepare, boolean alternativeIcon) {
|
||||
return createSearchButton(owner, comboBox, titel, onSuccess, null, null, null, alternativeIcon, null);
|
||||
}
|
||||
|
||||
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final String titel, final Runnable onSuccess, final Prepare prepare, final MetaDataSource metaDataSource, final DataModel dataModel) {
|
||||
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess, final Prepare prepare, final MetaDataSource metaDataSource, final DataModel dataModel) {
|
||||
return createSearchButton(owner, comboBox, titel, onSuccess, prepare, metaDataSource, dataModel, false, null);
|
||||
}
|
||||
|
||||
public static JButton createSearchButton(final Frame owner, final javax.swing.JComboBox comboBox, final Object titel, final Runnable onSuccess, final Prepare prepare, final MetaDataSource metaDataSource, final DataModel dataModel, boolean alternativeIcon, final AdditionalComponentFactory additionalComponentFactory) {
|
||||
final JButton button = new JButton();
|
||||
button.setIcon(UIUtil.scaleIcon(button, icon));
|
||||
button.setIcon(UIUtil.scaleIcon(button, alternativeIcon? icon2 : icon));
|
||||
button.setToolTipText("Find Table");
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
button.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(button);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Point location = button.getLocationOnScreen();
|
||||
StringSearchPanel searchPanel = new StringSearchPanel(comboBox, metaDataSource, dataModel, prepare);
|
||||
if (additionalComponentFactory != null) {
|
||||
searchPanel.plugInPanel.add(additionalComponentFactory.create(searchPanel), java.awt.BorderLayout.CENTER);
|
||||
} else {
|
||||
searchPanel.plugInPanel.setVisible(false);
|
||||
}
|
||||
String result = searchPanel.find(owner, titel, location.x, location.y);
|
||||
if (result != null && !result.equals(searchPanel.showAllLabel)) {
|
||||
comboBox.setSelectedItem(result);
|
||||
@@ -111,17 +133,44 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
button.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(button);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (prepare == null) {
|
||||
updateEnabledState(button, comboBox);
|
||||
comboBox.getModel().addListDataListener(new ListDataListener() {
|
||||
@Override
|
||||
public void intervalRemoved(ListDataEvent arg0) {
|
||||
updateEnabledState(button, comboBox);
|
||||
}
|
||||
@Override
|
||||
public void intervalAdded(ListDataEvent arg0) {
|
||||
updateEnabledState(button, comboBox);
|
||||
}
|
||||
@Override
|
||||
public void contentsChanged(ListDataEvent arg0) {
|
||||
updateEnabledState(button, comboBox);
|
||||
}
|
||||
});
|
||||
comboBox.addPropertyChangeListener("model", new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent arg0) {
|
||||
updateEnabledState(button, comboBox);
|
||||
}
|
||||
});
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
public String find(Frame owner, String titel, int x, int y) {
|
||||
dialog = new EscapableDialog(owner, titel, true) {
|
||||
|
||||
private static void updateEnabledState(JButton button, JComboBox comboBox) {
|
||||
button.setEnabled(comboBox.getModel().getSize() > 1 || comboBox.getModel().getSize() == 1 && !"".equals(comboBox.getModel().getElementAt(0)));
|
||||
}
|
||||
|
||||
public String find(Frame owner, Object titel, int x, int y) {
|
||||
dialog = new EscapableDialog(owner, String.valueOf(titel), true) {
|
||||
};
|
||||
dialog.getContentPane().add(this);
|
||||
dialog.pack();
|
||||
@@ -214,12 +263,12 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
if (e.getKeyChar() == KeyEvent.VK_ESCAPE) {
|
||||
dialog.setVisible(false);
|
||||
close();
|
||||
} else if (e.getKeyChar() == KeyEvent.VK_DOWN) {
|
||||
searchList.grabFocus();
|
||||
} else if (e.getKeyChar() == '\n') {
|
||||
result = searchList.getSelectedValue();
|
||||
dialog.setVisible(false);
|
||||
close();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
@@ -276,9 +325,9 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
}
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() >1) {
|
||||
if (e.getClickCount() > 1) {
|
||||
result = searchList.getSelectedValue();
|
||||
dialog.setVisible(false);
|
||||
close();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -500,6 +549,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
okButton = new javax.swing.JButton();
|
||||
cancelButton = new javax.swing.JButton();
|
||||
plugInPanel = new javax.swing.JPanel();
|
||||
|
||||
loadingPanel.setBackground(java.awt.Color.white);
|
||||
|
||||
@@ -509,8 +559,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
|
||||
cancelLoadiingButton.setText("Cancel");
|
||||
cancelLoadiingButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cancelLoadiingButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
@@ -529,10 +578,8 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
|
||||
searchList.setModel(new javax.swing.AbstractListModel<String>() {
|
||||
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
|
||||
@Override
|
||||
public int getSize() { return strings.length; }
|
||||
@Override
|
||||
public String getElementAt(int i) { return strings[i]; }
|
||||
public int getSize() { return strings.length; }
|
||||
public String getElementAt(int i) { return strings[i]; }
|
||||
});
|
||||
jScrollPane1.setViewportView(searchList);
|
||||
|
||||
@@ -576,8 +623,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
|
||||
selectAllButton.setText("Select all");
|
||||
selectAllButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
selectAllButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
@@ -608,8 +654,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
|
||||
okButton.setText(" Ok ");
|
||||
okButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
okButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
@@ -622,8 +667,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
|
||||
cancelButton.setText("Cancel");
|
||||
cancelButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cancelButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
@@ -638,17 +682,29 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
add(jPanel1, gridBagConstraints);
|
||||
|
||||
plugInPanel.setLayout(new java.awt.BorderLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 10;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridheight = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
add(plugInPanel, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
result = searchList.getSelectedValue();
|
||||
dialog.setVisible(false);
|
||||
close();
|
||||
}//GEN-LAST:event_okButtonActionPerformed
|
||||
|
||||
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||
dialog.setVisible(false);
|
||||
close();
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
|
||||
public void close() {
|
||||
dialog.setVisible(false);
|
||||
}
|
||||
|
||||
private void cancelLoadiingButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelLoadiingButtonActionPerformed
|
||||
cancelLoading.set(true);
|
||||
}//GEN-LAST:event_cancelLoadiingButtonActionPerformed
|
||||
@@ -670,6 +726,7 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
private javax.swing.JScrollPane jScrollPane2;
|
||||
private javax.swing.JPanel loadingPanel;
|
||||
private javax.swing.JButton okButton;
|
||||
private javax.swing.JPanel plugInPanel;
|
||||
private javax.swing.JPanel schemaPanel;
|
||||
private javax.swing.JList<String> searchList;
|
||||
private javax.swing.JTextField searchTextField;
|
||||
@@ -678,12 +735,14 @@ public class StringSearchPanel extends javax.swing.JPanel {
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
static private ImageIcon icon;
|
||||
static private ImageIcon icon2;
|
||||
static {
|
||||
String dir = "/net/sf/jailer/ui/resource";
|
||||
|
||||
// load images
|
||||
try {
|
||||
icon = new ImageIcon(MetaDataPanel.class.getResource(dir + "/search.png"));
|
||||
icon2 = new ImageIcon(MetaDataPanel.class.getResource(dir + "/search2.png"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package net.sf.jailer.ui;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FileDialog;
|
||||
@@ -34,6 +35,8 @@ import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -49,6 +52,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -80,6 +84,7 @@ import net.sf.jailer.ui.databrowser.BrowserContentPane.TableModelItem;
|
||||
import net.sf.jailer.ui.databrowser.Row;
|
||||
import net.sf.jailer.ui.scrollmenu.JScrollC2PopupMenu;
|
||||
import net.sf.jailer.ui.scrollmenu.JScrollPopupMenu;
|
||||
import net.sf.jailer.ui.syntaxtextarea.RSyntaxTextAreaWithSQLSyntaxStyle;
|
||||
import net.sf.jailer.util.CancellationException;
|
||||
import net.sf.jailer.util.CancellationHandler;
|
||||
import net.sf.jailer.util.CycleFinder;
|
||||
@@ -947,7 +952,7 @@ public class UIUtil {
|
||||
/**
|
||||
* Pair of Icon and Text.
|
||||
*/
|
||||
public static class IconWithText {
|
||||
public static class IconWithText implements Comparable<IconWithText> {
|
||||
public final String text;
|
||||
public final ImageIcon icon;
|
||||
|
||||
@@ -960,6 +965,88 @@ public class UIUtil {
|
||||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(IconWithText o) {
|
||||
return text.compareTo(o.text);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPopupActive = false;
|
||||
|
||||
public static synchronized boolean isPopupActive() {
|
||||
return isPopupActive;
|
||||
}
|
||||
|
||||
private static synchronized void setPopupActive(boolean b) {
|
||||
isPopupActive = b;
|
||||
}
|
||||
|
||||
public static void showPopup(final Component invoker, final int x, final int y, final JPopupMenu popup) {
|
||||
popup.addPropertyChangeListener("visible", new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (Boolean.FALSE.equals(evt.getNewValue())) {
|
||||
setPopupActive(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setPopupActive(true);
|
||||
popup.show(invoker, x, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void invokeLater(final int ticks, final Runnable runnable) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
int count = ticks;
|
||||
@Override
|
||||
public void run() {
|
||||
if (--count <= 0) {
|
||||
runnable.run();
|
||||
} else {
|
||||
SwingUtilities.invokeLater(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Map<Component, Integer> waitLevel = new WeakHashMap<Component, Integer>();
|
||||
|
||||
public static void setWaitCursor(Component component) {
|
||||
if (component != null) {
|
||||
Integer level = waitLevel.get(component);
|
||||
if (level != null) {
|
||||
waitLevel.put(component, level + 1);
|
||||
} else {
|
||||
waitLevel.put(component, 1);
|
||||
component.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetWaitCursor(Component component) {
|
||||
if (component != null) {
|
||||
Integer level = waitLevel.get(component);
|
||||
if (level != null) {
|
||||
if (level == 1) {
|
||||
component.setCursor(null);
|
||||
waitLevel.remove(component);
|
||||
} else {
|
||||
waitLevel.put(component, level - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers UI initializations.
|
||||
*/
|
||||
public static void prepareUI() {
|
||||
new RSyntaxTextAreaWithSQLSyntaxStyle(false, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import net.sf.jsqlparser.statement.Commit;
|
||||
import net.sf.jsqlparser.statement.SetStatement;
|
||||
import net.sf.jsqlparser.statement.StatementVisitor;
|
||||
import net.sf.jsqlparser.statement.Statements;
|
||||
import net.sf.jsqlparser.statement.UseStatement;
|
||||
import net.sf.jsqlparser.statement.alter.Alter;
|
||||
import net.sf.jsqlparser.statement.create.index.CreateIndex;
|
||||
import net.sf.jsqlparser.statement.create.table.CreateTable;
|
||||
@@ -70,6 +71,7 @@ import net.sf.jsqlparser.statement.select.AllTableColumns;
|
||||
import net.sf.jsqlparser.statement.select.FromItemVisitor;
|
||||
import net.sf.jsqlparser.statement.select.Join;
|
||||
import net.sf.jsqlparser.statement.select.LateralSubSelect;
|
||||
import net.sf.jsqlparser.statement.select.ParenthesisFromItem;
|
||||
import net.sf.jsqlparser.statement.select.PlainSelect;
|
||||
import net.sf.jsqlparser.statement.select.Select;
|
||||
import net.sf.jsqlparser.statement.select.SelectBody;
|
||||
@@ -405,12 +407,16 @@ public class AssociationProposer {
|
||||
if (subjoin.getLeft() != null) {
|
||||
subjoin.getLeft().accept(this);
|
||||
}
|
||||
if (subjoin.getJoin() != null) {
|
||||
if (subjoin.getJoin().getRightItem() != null) {
|
||||
subjoin.getJoin().getRightItem().accept(this);
|
||||
}
|
||||
if (subjoin.getJoin().getOnExpression() != null) {
|
||||
scopes.peek().expressions.add(subjoin.getJoin().getOnExpression());
|
||||
if (subjoin.getJoinList() != null) {
|
||||
for (Join join: subjoin.getJoinList()) {
|
||||
if (join != null) {
|
||||
if (join.getRightItem() != null) {
|
||||
join.getRightItem().accept(this);
|
||||
}
|
||||
if (join.getOnExpression() != null) {
|
||||
scopes.peek().expressions.add(join.getOnExpression());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -437,6 +443,13 @@ public class AssociationProposer {
|
||||
fn += Quoting.normalizeIdentifier(tableName.getName());
|
||||
scopes.peek().aliasToTable.put(Quoting.normalizeIdentifier(alias), fn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ParenthesisFromItem aThis) {
|
||||
if (aThis.getFromItem() != null) {
|
||||
aThis.getFromItem().accept(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (plainSelect.getFromItem() != null) {
|
||||
plainSelect.getFromItem().accept(fromItemVisitor);
|
||||
@@ -508,6 +521,10 @@ public class AssociationProposer {
|
||||
public void visit(AnalyticExpression expr) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UseStatement use) {
|
||||
}
|
||||
|
||||
private void analyseTopScope() {
|
||||
for (Expression expr: scopes.peek().expressions) {
|
||||
expr.accept(new ExpressionVisitorAdapter() {
|
||||
@@ -629,7 +646,6 @@ public class AssociationProposer {
|
||||
return dColumn;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ public class AssociationProposerView extends javax.swing.JPanel {
|
||||
final TableCellRenderer defaultTableCellRenderer = proposalTable.getDefaultRenderer(String.class);
|
||||
TableCellRenderer renderer = new TableCellRenderer() {
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
@@ -443,6 +443,8 @@ public class AssociationProposerView extends javax.swing.JPanel {
|
||||
adjustTableColumnsWidth();
|
||||
if (proposalsModel.getRowCount() == 0 && knownModel.getRowCount() == 0 && numErrors > 0) {
|
||||
tabbedPane.setSelectedComponent(problemTabPanel);
|
||||
} else if (proposalsModel.getRowCount() == 0 && knownModel.getRowCount() > 0) {
|
||||
tabbedPane.setSelectedComponent(knownPanel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ public abstract class ConstraintChecker extends javax.swing.JPanel {
|
||||
final TableCellRenderer defaultTableCellRenderer = problemsTable.getDefaultRenderer(String.class);
|
||||
problemsTable.setDefaultRenderer(Object.class, new TableCellRenderer() {
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
|
||||
@@ -80,7 +80,7 @@ public class BrowserContentCellEditor {
|
||||
|
||||
@Override
|
||||
boolean isEditable(int columnType, Object content) {
|
||||
return content == null || content instanceof String;
|
||||
return content == null || (content instanceof String && !(content.toString().indexOf('\n') >= 0 || content.toString().indexOf('\t') >= 0));
|
||||
}
|
||||
},
|
||||
DATE {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -120,7 +120,7 @@
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="3" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="1.0" weightY="0.0"/>
|
||||
<GridBagConstraints gridX="7" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
@@ -140,7 +140,7 @@
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="4" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
<GridBagConstraints gridX="8" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
@@ -237,6 +237,39 @@
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="findPathComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="4">
|
||||
<StringItem index="0" value="Item 1"/>
|
||||
<StringItem index="1" value="Item 2"/>
|
||||
<StringItem index="2" value="Item 3"/>
|
||||
<StringItem index="3" value="Item 4"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findPathComboBoxActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="4" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="findPathButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Find Path to..."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findPathButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="5" gridY="20" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="4" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
||||
@@ -53,7 +53,7 @@ import java.util.Vector;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
@@ -70,9 +70,15 @@ import net.sf.jailer.datamodel.Association;
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
import net.sf.jailer.ui.AutoCompletion;
|
||||
import net.sf.jailer.ui.ClosureView;
|
||||
import net.sf.jailer.ui.JComboBox;
|
||||
import net.sf.jailer.ui.StringSearchPanel;
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
import net.sf.jailer.ui.StringSearchPanel.AdditionalComponentFactory;
|
||||
import net.sf.jailer.ui.databrowser.Desktop.RowBrowser;
|
||||
import net.sf.jailer.ui.pathfinder.HistoryPanel;
|
||||
import net.sf.jailer.ui.pathfinder.PathFinder;
|
||||
import net.sf.jailer.ui.pathfinder.PathFinder.Result;
|
||||
import net.sf.jailer.util.Pair;
|
||||
|
||||
/**
|
||||
@@ -97,7 +103,282 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
*/
|
||||
private final List<Color> bgColor = new ArrayList<Color>();
|
||||
|
||||
/**
|
||||
private final class TableMouseListener implements MouseListener {
|
||||
private Map<Integer, String> manuallySelected = new TreeMap<Integer, String>();
|
||||
|
||||
public void openPathFinder(final Table table, boolean fromHistory) {
|
||||
PathFinder pathFinder = new PathFinder();
|
||||
Result result = pathFinder.find(getRootTable(), table, getDataModel(), true, fromHistory, DBClosureView.this.parent);
|
||||
if (result != null) {
|
||||
List<Table> path = result.path;
|
||||
mainPath.clear();
|
||||
mainPathAsSet.clear();
|
||||
Map<Table, Integer> fd = new HashMap<Table, Integer>();
|
||||
for (int i = 0; i < result.path.size(); ++i) {
|
||||
fd.put(result.path.get(i), i);
|
||||
}
|
||||
refreshTableModel(fd);
|
||||
selectedTable = null;
|
||||
// refresh();
|
||||
|
||||
for (int i = 0; i < path.size(); ++i) {
|
||||
Table r = path.get(i);
|
||||
String tabName = getDataModel().getDisplayName(r);
|
||||
selectCell(result.expand && i == path.size() - 1, tabName, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void expandPath() {
|
||||
List<Table> path = new ArrayList<Table>();
|
||||
for (CellInfo ci: mainPath) {
|
||||
path.add(ci.table);
|
||||
}
|
||||
expandTablePath(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(final MouseEvent e) {
|
||||
// reset view
|
||||
{
|
||||
Point position = e.getPoint();
|
||||
int row = closureTable.rowAtPoint(position);
|
||||
int column = closureTable.columnAtPoint(position);
|
||||
if (row >= 0 && column >= 0) {
|
||||
Object value = closureTable.getModel().getValueAt(row, column);
|
||||
CellInfo ci = cellInfo.get(value);
|
||||
if (currentForcedDistance != null && ci != null && !mainPathAsSet.contains(ci)) {
|
||||
mainPath.clear();
|
||||
mainPathAsSet.clear();
|
||||
currentForcedDistance = null;
|
||||
refreshTableModel(null);
|
||||
selectedTable = null;
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// context menu
|
||||
if (SwingUtilities.isRightMouseButton(e)) {
|
||||
int row = closureTable.rowAtPoint(e.getPoint());
|
||||
int column = closureTable.columnAtPoint(e.getPoint());
|
||||
if (row < 0 || column < 0) return;
|
||||
final Object value = closureTable.getModel().getValueAt(row, column);
|
||||
if (value == null || !(value instanceof String)) return;
|
||||
final Table table = getDataModel().getTableByDisplayName((String) value);
|
||||
if (table != null) {
|
||||
if (selectedTable == null || !selectedTable.equals(value)) {
|
||||
if (cellInfo.containsKey(value) && !cellInfo.get(value).selected) {
|
||||
selectTableCell(column, row);
|
||||
}
|
||||
}
|
||||
// int tableLevel = -1;
|
||||
// if (cellInfo.containsKey(value)) {
|
||||
// tableLevel = cellInfo.get(value).level;
|
||||
// }
|
||||
// JCheckBoxMenuItem exclude = new JCheckBoxMenuItem("Exclude " + getDataModel().getDisplayName(table) + " from Path");
|
||||
// exclude.setSelected(excludedFromPath.contains(table));
|
||||
// exclude.setEnabled(mainPath.contains(cellInfo.get(value)) || excludedFromPath.contains(table));
|
||||
// exclude.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// if (!excludedFromPath.contains(table)) {
|
||||
// excludedFromPath.add(table);
|
||||
// } else {
|
||||
// excludedFromPath.remove(table);
|
||||
// }
|
||||
// mainPath.clear();
|
||||
// mainPathAsSet.clear();
|
||||
// refresh();
|
||||
// CellInfo ci = cellInfo.get(selectedTable);
|
||||
// if (ci != null) {
|
||||
// String st = selectedTable;
|
||||
// selectedTable = null;
|
||||
// select(st, ci);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// final Set<Table> toExclude = new HashSet<Table>();
|
||||
// for (Entry<String, CellInfo> ciE: cellInfo.entrySet()) {
|
||||
// if (ciE.getValue().selected && ciE.getValue().level == tableLevel) {
|
||||
// Table tableByDisplayName = getDataModel().getTableByDisplayName(ciE.getKey());
|
||||
// if (tableByDisplayName != null) {
|
||||
// toExclude.add(tableByDisplayName);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// JCheckBoxMenuItem excludeAll = new JCheckBoxMenuItem("Exclude all with Distance " + (tableLevel + 1) + " from Path");
|
||||
// excludeAll.setEnabled(toExclude.size() > 1);
|
||||
// excludeAll.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// excludedFromPath.addAll(toExclude);
|
||||
// mainPath.clear();
|
||||
// mainPathAsSet.clear();
|
||||
// refresh();
|
||||
// CellInfo ci = cellInfo.get(selectedTable);
|
||||
// if (ci != null) {
|
||||
// String st = selectedTable;
|
||||
// selectedTable = null;
|
||||
// select(st, ci);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// JMenuItem deselect = new JMenuItem("Deselect path");
|
||||
// deselect.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// mainPath.clear();
|
||||
// mainPathAsSet.clear();
|
||||
// excludedFromPath.clear();
|
||||
// refreshTableModel();
|
||||
// selectedTable = null;
|
||||
// refresh();
|
||||
// }
|
||||
// });
|
||||
JMenuItem pathFinder = new JMenuItem("Find more complex path to " + getDataModel().getDisplayName(table));
|
||||
Table rt = getRootTable();
|
||||
if (rt == null || !rt.closure(false).contains(table)) {
|
||||
pathFinder.setEnabled(false);
|
||||
}
|
||||
pathFinder.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
openPathFinder(table, false);
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem openPath = new JMenuItem("Open path to " + getDataModel().getDisplayName(table));
|
||||
if (rt == null || !rt.closure(false).contains(table)) {
|
||||
openPath.setEnabled(false);
|
||||
}
|
||||
openPath.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
expandPath();
|
||||
DBClosureView.this.select(selectedTable);
|
||||
}
|
||||
});
|
||||
|
||||
RowBrowser rb = getVisibleTables().get(table);
|
||||
if (rb == null) {
|
||||
if (!mainPath.isEmpty()) {
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
menu.add(openPath);
|
||||
menu.add(new JSeparator());
|
||||
menu.add(pathFinder);
|
||||
UIUtil.showPopup(e.getComponent(), e.getX(), e.getY(), menu);
|
||||
}
|
||||
} else {
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
JMenuItem select = new JMenuItem("Select " + getDataModel().getDisplayName(table));
|
||||
select.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
DBClosureView.this.select((String) value);
|
||||
}
|
||||
});
|
||||
menu.add(select);
|
||||
// menu.addSeparator();
|
||||
// menu.add(exclude);
|
||||
// menu.add(excludeAll);
|
||||
menu.addSeparator();
|
||||
JPopupMenu popup = rb.browserContentPane.createPopupMenu(null, -1, 0, 0, false);
|
||||
JPopupMenu popup2 = rb.browserContentPane.createSqlPopupMenu(null, -1, 0, 0, true, closureTable);
|
||||
popup.add(new JSeparator());
|
||||
for (Component c : popup.getComponents()) {
|
||||
menu.add(c);
|
||||
}
|
||||
for (Component c : popup2.getComponents()) {
|
||||
menu.add(c);
|
||||
}
|
||||
if (!mainPath.isEmpty()) {
|
||||
// menu.addSeparator();
|
||||
// menu.add(deselect);
|
||||
menu.addSeparator();
|
||||
menu.add(openPath);
|
||||
menu.add(pathFinder);
|
||||
}
|
||||
UIUtil.showPopup(e.getComponent(), e.getX(), e.getY(), menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||
Point position = e.getPoint();
|
||||
int row = closureTable.rowAtPoint(position);
|
||||
int column = closureTable.columnAtPoint(position);
|
||||
if (row < 0 || column < 0) return;
|
||||
|
||||
Object value = closureTable.getModel().getValueAt(row, column);
|
||||
if (value == null || !(value instanceof String)) return;
|
||||
final Table table = getDataModel().getTableByDisplayName((String) value);
|
||||
selectCell(e.getClickCount() > 1, value, table);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectCell(boolean expandPath, Object value, final Table table) {
|
||||
if (table != null) {
|
||||
if (cellInfo.containsKey(value)) {
|
||||
String prevSelectedTable = selectedTable;
|
||||
CellInfo selectedCellInfo = cellInfo.get(value);
|
||||
if (selectedCellInfo.selected && !mainPathAsSet.contains(selectedCellInfo)) {
|
||||
manuallySelected.put(selectedCellInfo.level, (String) value);
|
||||
select(prevSelectedTable, selectedCellInfo);
|
||||
} else if (!selectedCellInfo.selected) {
|
||||
manuallySelected.clear();
|
||||
selectTableCell((String) value);
|
||||
} else {
|
||||
scrollToTable(table);
|
||||
}
|
||||
}
|
||||
|
||||
if (expandPath) {
|
||||
if (!mainPath.isEmpty()) {
|
||||
expandPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void select(String toSelect, CellInfo selectedCellInfo) {
|
||||
TreeMap<Integer, String> newMS = new TreeMap<Integer, String>(manuallySelected);
|
||||
String lastFound = null;
|
||||
for (Entry<Integer, String> ms: manuallySelected.entrySet()) {
|
||||
find(ms.getValue());
|
||||
if (selectedCellInfo.level < ms.getKey() && !mainPathAsSet.contains(selectedCellInfo)) {
|
||||
manuallySelected = newMS;
|
||||
if (lastFound != null) {
|
||||
find(lastFound);
|
||||
}
|
||||
break;
|
||||
}
|
||||
newMS.put(ms.getKey(), ms.getValue());
|
||||
lastFound = ms.getValue();
|
||||
}
|
||||
if (toSelect != null && !toSelect.equals(selectedTable)) {
|
||||
find(toSelect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Holds infos about a cell in the closure-table.
|
||||
*/
|
||||
private class CellInfo {
|
||||
@@ -126,8 +407,10 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
private List<CellInfo> mainPath = new ArrayList<CellInfo>();
|
||||
private HashSet<CellInfo> mainPathAsSet = new HashSet<CellInfo>();
|
||||
private Set<Pair<String, String>> dependencies = new HashSet<Pair<String,String>>();
|
||||
private Set<Table> excludedFromPath = new HashSet<Table>();
|
||||
private Map<Table, Integer> currentForcedDistance = null;
|
||||
private final JFrame parent;
|
||||
|
||||
private TableMouseListener tableMouseListener;
|
||||
|
||||
/** Creates new form FindDialog
|
||||
* @param rootTable */
|
||||
@@ -166,6 +449,68 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
findButton.setVisible(false);
|
||||
searchButton.setText("Find Table");
|
||||
|
||||
AutoCompletion.enable(findPathComboBox);
|
||||
findPathComboBox.getEditor().getEditorComponent().addKeyListener(new KeyListener() {
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
if (e.getKeyChar() == '\n') {
|
||||
findPathComboBoxActionPerformed(null);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void keyPressed(KeyEvent arg0) {
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 20;
|
||||
JButton stFindPathButton = StringSearchPanel.createSearchButton(
|
||||
this.parent, findPathComboBox,
|
||||
new Object() {
|
||||
public String toString() {
|
||||
Table rootTable = getRootTable();
|
||||
return (rootTable != null? ("From " + getDataModel().getDisplayName(rootTable) + " - ") : "") + "Select destination or choose from History";
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Object toFind = findPathComboBox.getSelectedItem();
|
||||
if (toFind != null) {
|
||||
CellInfo cellInfo = DBClosureView.this.cellInfo.get(toFind);
|
||||
if (cellInfo != null) {
|
||||
tableMouseListener.openPathFinder(cellInfo.table, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null, null, null, true, new AdditionalComponentFactory() {
|
||||
@Override
|
||||
public JComponent create(final StringSearchPanel searchPanel) {
|
||||
HistoryPanel historyPanel = new HistoryPanel(getRootTable(), getDataModel()) {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected void close() {
|
||||
searchPanel.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(Table source, Table destination) {
|
||||
tableMouseListener.openPathFinder(destination, true);
|
||||
}
|
||||
};
|
||||
return historyPanel;
|
||||
}
|
||||
});
|
||||
tablePanel.add(stFindPathButton, gridBagConstraints);
|
||||
|
||||
findPathComboBox.setVisible(false);
|
||||
findPathButton.setVisible(false);
|
||||
stFindPathButton.setText("Find Path to...");
|
||||
|
||||
columnsComboBox.setModel(new DefaultComboBoxModel<Integer>(new Integer[] {
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
|
||||
}));
|
||||
@@ -245,197 +590,10 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
};
|
||||
closureTable.setShowGrid(false);
|
||||
closureTable.setSurrendersFocusOnKeystroke(true);
|
||||
closureTable.getTableHeader().setReorderingAllowed(false);
|
||||
jScrollPane1.setViewportView(closureTable);
|
||||
|
||||
closureTable.addMouseListener(new MouseListener() {
|
||||
|
||||
private Map<Integer, String> manuallySelected = new TreeMap<Integer, String>();
|
||||
|
||||
private void expandPath() {
|
||||
List<Table> path = new ArrayList<Table>();
|
||||
for (CellInfo ci: mainPath) {
|
||||
path.add(ci.table);
|
||||
}
|
||||
expandTablePath(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(final MouseEvent e) {
|
||||
mouseReleased(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
// context menu
|
||||
if (SwingUtilities.isRightMouseButton(e)) {
|
||||
int row = closureTable.rowAtPoint(e.getPoint());
|
||||
int column = closureTable.columnAtPoint(e.getPoint());
|
||||
if (row < 0 || column < 0) return;
|
||||
final Object value = closureTable.getModel().getValueAt(row, column);
|
||||
if (value == null || !(value instanceof String)) return;
|
||||
final Table table = getDataModel().getTableByDisplayName((String) value);
|
||||
if (table != null) {
|
||||
if (selectedTable == null || !selectedTable.equals(value)) {
|
||||
if (cellInfo.containsKey(value) && !cellInfo.get(value).selected) {
|
||||
selectTableCell(column, row);
|
||||
}
|
||||
}
|
||||
JCheckBoxMenuItem exclude = new JCheckBoxMenuItem("Exclude " + getDataModel().getDisplayName(table) + " from Path");
|
||||
exclude.setSelected(excludedFromPath.contains(table));
|
||||
exclude.setEnabled(mainPath.contains(cellInfo.get(value)) || excludedFromPath.contains(table));
|
||||
exclude.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!excludedFromPath.contains(table)) {
|
||||
excludedFromPath.add(table);
|
||||
} else {
|
||||
excludedFromPath.remove(table);
|
||||
}
|
||||
mainPath.clear();
|
||||
mainPathAsSet.clear();
|
||||
refresh();
|
||||
CellInfo ci = cellInfo.get(selectedTable);
|
||||
if (ci != null) {
|
||||
String st = selectedTable;
|
||||
selectedTable = null;
|
||||
select(st, ci);
|
||||
}
|
||||
}
|
||||
});
|
||||
JMenuItem deselect = new JMenuItem("Deselect Path");
|
||||
deselect.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainPath.clear();
|
||||
mainPathAsSet.clear();
|
||||
excludedFromPath.clear();
|
||||
refreshTableModel();
|
||||
selectedTable = null;
|
||||
refresh();
|
||||
}
|
||||
});
|
||||
RowBrowser rb = getVisibleTables().get(table);
|
||||
if (rb == null) {
|
||||
if (!mainPath.isEmpty()) {
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
JMenuItem open = new JMenuItem("Open Path to " + selectedTable);
|
||||
open.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
expandPath();
|
||||
}
|
||||
});
|
||||
menu.add(open);
|
||||
JMenuItem openAndSelect = new JMenuItem("Open Path to and Select " + selectedTable);
|
||||
openAndSelect.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
expandPath();
|
||||
DBClosureView.this.select(selectedTable);
|
||||
}
|
||||
});
|
||||
menu.add(openAndSelect);
|
||||
menu.add(new JSeparator());
|
||||
menu.add(exclude);
|
||||
menu.add(deselect);
|
||||
menu.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
} else {
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
JMenuItem select = new JMenuItem("Select " + getDataModel().getDisplayName(table));
|
||||
select.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
DBClosureView.this.select((String) value);
|
||||
}
|
||||
});
|
||||
menu.add(select);
|
||||
menu.addSeparator();
|
||||
menu.add(exclude);
|
||||
menu.addSeparator();
|
||||
JPopupMenu popup = rb.browserContentPane.createPopupMenu(null, -1, 0, 0, false);
|
||||
JPopupMenu popup2 = rb.browserContentPane.createSqlPopupMenu(null, -1, 0, 0, true);
|
||||
popup.add(new JSeparator());
|
||||
for (Component c : popup.getComponents()) {
|
||||
menu.add(c);
|
||||
}
|
||||
for (Component c : popup2.getComponents()) {
|
||||
menu.add(c);
|
||||
}
|
||||
if (!mainPath.isEmpty()) {
|
||||
menu.addSeparator();
|
||||
menu.add(deselect);
|
||||
}
|
||||
UIUtil.fit(popup);
|
||||
menu.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||
Point position = e.getPoint();
|
||||
int row = closureTable.rowAtPoint(position);
|
||||
int column = closureTable.columnAtPoint(position);
|
||||
if (row < 0 || column < 0) return;
|
||||
|
||||
Object value = closureTable.getModel().getValueAt(row, column);
|
||||
if (value == null || !(value instanceof String)) return;
|
||||
final Table table = getDataModel().getTableByDisplayName((String) value);
|
||||
if (table != null) {
|
||||
if (cellInfo.containsKey(value)) {
|
||||
String prevSelectedTable = selectedTable;
|
||||
CellInfo selectedCellInfo = cellInfo.get(value);
|
||||
if (selectedCellInfo.selected && !mainPathAsSet.contains(selectedCellInfo)) {
|
||||
manuallySelected.put(selectedCellInfo.level, (String) value);
|
||||
select(prevSelectedTable, selectedCellInfo);
|
||||
} else if (!selectedCellInfo.selected) {
|
||||
manuallySelected.clear();
|
||||
selectTableCell(column, row);
|
||||
}
|
||||
}
|
||||
|
||||
if (e.getClickCount() > 1) {
|
||||
RowBrowser rb = getVisibleTables().get(table);
|
||||
if (rb == null) {
|
||||
if (!mainPath.isEmpty()) {
|
||||
expandPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void select(String toSelect, CellInfo selectedCellInfo) {
|
||||
TreeMap<Integer, String> newMS = new TreeMap<Integer, String>(manuallySelected);
|
||||
String lastFound = null;
|
||||
for (Entry<Integer, String> ms: manuallySelected.entrySet()) {
|
||||
find(ms.getValue());
|
||||
if (selectedCellInfo.level < ms.getKey() && !mainPathAsSet.contains(selectedCellInfo)) {
|
||||
manuallySelected = newMS;
|
||||
if (lastFound != null) {
|
||||
find(lastFound);
|
||||
}
|
||||
break;
|
||||
}
|
||||
newMS.put(ms.getKey(), ms.getValue());
|
||||
lastFound = ms.getValue();
|
||||
}
|
||||
if (toSelect != null && !toSelect.equals(selectedTable)) {
|
||||
find(toSelect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
}
|
||||
});
|
||||
closureTable.addMouseListener(tableMouseListener = new TableMouseListener());
|
||||
|
||||
searchComboBox.setMaximumRowCount(30);
|
||||
|
||||
@@ -506,9 +664,9 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
} else if (getVisibleTables().containsKey(t)) {
|
||||
((JLabel) render).setFont(onPath? italicBold : italic);
|
||||
}
|
||||
if (excludedFromPath.contains(t)) {
|
||||
((JLabel) render).setForeground(new Color(180, 180, 180));
|
||||
}
|
||||
// if (currentForcedDistance != null && currentForcedDistance.containsKey(t)) {
|
||||
// ((JLabel) render).setForeground(new Color(180, 180, 180));
|
||||
// }
|
||||
if (getVisibleTables().containsKey(t)) {
|
||||
((JLabel) render).setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.lightGray, Color.gray));
|
||||
}
|
||||
@@ -597,42 +755,46 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
private void selectTableCell(int col, int row) {
|
||||
if (col >= 1 && row >= 0) {
|
||||
String displayName = (String) closureTable.getModel().getValueAt(row, col);
|
||||
closureTable.getSelectionModel().clearSelection();
|
||||
for (CellInfo c: cellInfo.values()) {
|
||||
c.selected = false;
|
||||
selectTableCell(displayName);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectTableCell(String displayName) {
|
||||
closureTable.getSelectionModel().clearSelection();
|
||||
for (CellInfo c: cellInfo.values()) {
|
||||
c.selected = false;
|
||||
}
|
||||
if (displayName != null && !"".equals(displayName)) {
|
||||
Table prevTable = null;
|
||||
if (selectedTable != null) {
|
||||
prevTable = getDataModel().getTableByDisplayName(selectedTable);
|
||||
}
|
||||
if (displayName != null && !"".equals(displayName)) {
|
||||
Table prevTable = null;
|
||||
if (selectedTable != null) {
|
||||
prevTable = getDataModel().getTableByDisplayName(selectedTable);
|
||||
}
|
||||
selectedTable = displayName;
|
||||
searchComboBox.setSelectedItem(selectedTable);
|
||||
repaintClosureView();
|
||||
Table table = getDataModel().getTableByDisplayName(selectedTable);
|
||||
if (table != null) {
|
||||
CellInfo selectionInfo = cellInfo.get(selectedTable);
|
||||
selectionInfo.select();
|
||||
if (prevTable != table) {
|
||||
Set<Table> visibleTables = getVisibleTables().keySet();
|
||||
Set<Table> mainPathTables = new HashSet<Table>();
|
||||
for (CellInfo ci: mainPath) {
|
||||
mainPathTables.add(ci.table);
|
||||
}
|
||||
Set<CellInfo> pathToVisibleTable = shortestPathToVisibleTable(visibleTables, selectionInfo);
|
||||
Set<CellInfo> pathToMainPathTable = shortestPathToVisibleTable(mainPathTables, selectionInfo);
|
||||
List<CellInfo> pathVT = new ArrayList<CellInfo>();
|
||||
int vtMaxRow = fillPath(selectionInfo, visibleTables, pathToVisibleTable, pathVT);
|
||||
List<CellInfo> pathST = new ArrayList<CellInfo>();
|
||||
int stMaxRow = fillPath(selectionInfo, mainPathTables, pathToMainPathTable, pathST);
|
||||
if (pathToMainPathTable.isEmpty()) { // (vtMaxRow > stMaxRow) {
|
||||
mainPath = pathVT;
|
||||
} else {
|
||||
mainPath = pathST;
|
||||
}
|
||||
selectedTable = displayName;
|
||||
searchComboBox.setSelectedItem(selectedTable);
|
||||
repaintClosureView();
|
||||
Table table = getDataModel().getTableByDisplayName(selectedTable);
|
||||
if (table != null) {
|
||||
CellInfo selectionInfo = cellInfo.get(selectedTable);
|
||||
selectionInfo.select();
|
||||
if (prevTable != table) {
|
||||
Set<Table> visibleTables = getVisibleTables().keySet();
|
||||
Set<Table> mainPathTables = new HashSet<Table>();
|
||||
for (CellInfo ci: mainPath) {
|
||||
mainPathTables.add(ci.table);
|
||||
}
|
||||
Set<CellInfo> pathToVisibleTable = shortestPathToVisibleTable(visibleTables, selectionInfo);
|
||||
Set<CellInfo> pathToMainPathTable = shortestPathToVisibleTable(mainPathTables, selectionInfo);
|
||||
List<CellInfo> pathVT = new ArrayList<CellInfo>();
|
||||
int vtMaxRow = fillPath(selectionInfo, visibleTables, pathToVisibleTable, pathVT);
|
||||
List<CellInfo> pathST = new ArrayList<CellInfo>();
|
||||
int stMaxRow = fillPath(selectionInfo, mainPathTables, pathToMainPathTable, pathST);
|
||||
if (pathToMainPathTable.isEmpty()) { // (vtMaxRow > stMaxRow) {
|
||||
mainPath = pathVT;
|
||||
} else {
|
||||
mainPath = pathST;
|
||||
}
|
||||
mainPathAsSet = new HashSet<CellInfo>(mainPath);
|
||||
}
|
||||
mainPathAsSet = new HashSet<CellInfo>(mainPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -696,7 +858,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
*/
|
||||
public void refresh() {
|
||||
String prevSelection = selectedTable;
|
||||
refreshTableModel();
|
||||
refreshTableModel(null);
|
||||
if (cellInfo.containsKey(prevSelection)) {
|
||||
selectedTable = prevSelection;
|
||||
} else {
|
||||
@@ -708,12 +870,17 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
/**
|
||||
* Refreshes the table model.
|
||||
*/
|
||||
private void refreshTableModel() {
|
||||
private void refreshTableModel(Map<Table, Integer> forcedDistance) {
|
||||
cellInfo.clear();
|
||||
dependencies.clear();
|
||||
Table selectedTable = getSelectedTable();
|
||||
|
||||
Object[] columns = new Object[tablesPerLine + 1];
|
||||
currentForcedDistance = forcedDistance;
|
||||
if (forcedDistance == null) {
|
||||
forcedDistance = new HashMap<Table, Integer>();
|
||||
}
|
||||
|
||||
Object[] columns = new Object[tablesPerLine + 1];
|
||||
for (int i = 0; i < columns.length; ++i) {
|
||||
columns[i] = "";
|
||||
}
|
||||
@@ -740,7 +907,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
boolean isolated = false;
|
||||
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(230, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
final Color BG3 = new Color(255, 255, 240);
|
||||
final Color BG4 = new Color(220, 220, 220);
|
||||
final Color BG5 = new Color(255, 240, 240);
|
||||
@@ -796,27 +963,40 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
Table table = getDataModel().getTableByDisplayName(t);
|
||||
if (table != null) {
|
||||
CellInfo cellInfoT = this.cellInfo.get(t);
|
||||
if (!excludedFromPath.contains(table)) {
|
||||
for (Association association: table.associations) {
|
||||
String displayName = getDataModel().getDisplayName(association.destination);
|
||||
if (!association.isIgnored()) {
|
||||
if (!visited.contains(displayName)) {
|
||||
nextLine.add(displayName);
|
||||
visited.add(displayName);
|
||||
CellInfo cellInfo = new CellInfo(distance);
|
||||
cellInfo.parents.add(cellInfoT);
|
||||
cellInfo.table = association.destination;
|
||||
for (Association association: table.associations) {
|
||||
Integer fd = forcedDistance.get(association.destination);
|
||||
if (fd != null && fd != distance + 1) {
|
||||
continue;
|
||||
}
|
||||
boolean addToParent = true;
|
||||
if (forcedDistance.containsKey(association.destination)) {
|
||||
if (!forcedDistance.containsKey(table)) {
|
||||
addToParent = false;
|
||||
}
|
||||
}
|
||||
String displayName = getDataModel().getDisplayName(association.destination);
|
||||
if (!association.isIgnored() ||
|
||||
(forcedDistance.containsKey(association.source) && forcedDistance.containsKey(association.destination))) {
|
||||
if (!visited.contains(displayName)) {
|
||||
nextLine.add(displayName);
|
||||
visited.add(displayName);
|
||||
CellInfo cellInfo = new CellInfo(distance);
|
||||
if (addToParent) {
|
||||
cellInfo.parents.add(cellInfoT);
|
||||
}
|
||||
cellInfo.table = association.destination;
|
||||
if (association.isInsertDestinationBeforeSource()) {
|
||||
dependencies.add(new Pair<String, String>(t, displayName));
|
||||
}
|
||||
this.cellInfo.put(displayName, cellInfo);
|
||||
} else {
|
||||
if (nextLine.contains(displayName)) {
|
||||
if (addToParent) {
|
||||
this.cellInfo.get(displayName).parents.add(cellInfoT);
|
||||
}
|
||||
if (association.isInsertDestinationBeforeSource()) {
|
||||
dependencies.add(new Pair<String, String>(t, displayName));
|
||||
}
|
||||
this.cellInfo.put(displayName, cellInfo);
|
||||
} else {
|
||||
if (nextLine.contains(displayName)) {
|
||||
this.cellInfo.get(displayName).parents.add(cellInfoT);
|
||||
if (association.isInsertDestinationBeforeSource()) {
|
||||
dependencies.add(new Pair<String, String>(t, displayName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -939,6 +1119,8 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
vector.addAll(nonIsolated);
|
||||
searchComboBox.setModel(new DefaultComboBoxModel<String>(vector));
|
||||
searchComboBox.setSelectedItem("");
|
||||
findPathComboBox.setModel(new DefaultComboBoxModel<String>(vector));
|
||||
findPathComboBox.setSelectedItem("");
|
||||
}
|
||||
|
||||
private Table getSelectedTable() {
|
||||
@@ -965,9 +1147,9 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
tablePanel = new javax.swing.JPanel();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
closureTable = new javax.swing.JTable();
|
||||
searchComboBox = new net.sf.jailer.ui.JComboBox();
|
||||
searchComboBox = new JComboBox();
|
||||
jLabel7 = new javax.swing.JLabel();
|
||||
columnsComboBox = new net.sf.jailer.ui.JComboBox();
|
||||
columnsComboBox = new javax.swing.JComboBox();
|
||||
findButton = new javax.swing.JButton();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
jLabel2 = new javax.swing.JLabel();
|
||||
@@ -977,6 +1159,8 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
jLabel6 = new javax.swing.JLabel();
|
||||
jLabel8 = new javax.swing.JLabel();
|
||||
jLabel9 = new javax.swing.JLabel();
|
||||
findPathComboBox = new JComboBox();
|
||||
findPathButton = new javax.swing.JButton();
|
||||
|
||||
contentPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
@@ -1018,8 +1202,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
|
||||
searchComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
searchComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
searchComboBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
@@ -1030,7 +1213,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
|
||||
jLabel7.setText("Columns ");
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 3;
|
||||
gridBagConstraints.gridx = 7;
|
||||
gridBagConstraints.gridy = 20;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
@@ -1038,20 +1221,18 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
|
||||
columnsComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
columnsComboBox.addItemListener(new java.awt.event.ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
columnsComboBoxItemStateChanged(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 4;
|
||||
gridBagConstraints.gridx = 8;
|
||||
gridBagConstraints.gridy = 20;
|
||||
tablePanel.add(columnsComboBox, gridBagConstraints);
|
||||
|
||||
findButton.setText("Find");
|
||||
findButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
findButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
@@ -1110,6 +1291,30 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
gridBagConstraints.gridy = 8;
|
||||
tablePanel.add(jLabel9, gridBagConstraints);
|
||||
|
||||
findPathComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
findPathComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
findPathComboBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 4;
|
||||
gridBagConstraints.gridy = 20;
|
||||
tablePanel.add(findPathComboBox, gridBagConstraints);
|
||||
|
||||
findPathButton.setText("Find Path to...");
|
||||
findPathButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
findPathButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 5;
|
||||
gridBagConstraints.gridy = 20;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
|
||||
tablePanel.add(findPathButton, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
@@ -1132,6 +1337,12 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
find((String) toFind);
|
||||
}//GEN-LAST:event_findButtonActionPerformed
|
||||
|
||||
private void findPathComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findPathComboBoxActionPerformed
|
||||
}//GEN-LAST:event_findPathComboBoxActionPerformed
|
||||
|
||||
private void findPathButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findPathButtonActionPerformed
|
||||
}//GEN-LAST:event_findPathButtonActionPerformed
|
||||
|
||||
protected void find(String toFind) {
|
||||
if (toFind != null && !toFind.equals(selectedTable)) {
|
||||
CellInfo cellInfo = this.cellInfo.get(toFind);
|
||||
@@ -1145,12 +1356,15 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
protected abstract Map<Table, RowBrowser> getVisibleTables();
|
||||
protected abstract void expandTablePath(List<Table> path);
|
||||
protected abstract void select(String selectedTable);
|
||||
protected abstract void scrollToTable(Table table);
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JTable closureTable;
|
||||
private net.sf.jailer.ui.JComboBox columnsComboBox;
|
||||
private javax.swing.JComboBox columnsComboBox;
|
||||
public javax.swing.JPanel contentPanel;
|
||||
private javax.swing.JButton findButton;
|
||||
private javax.swing.JButton findPathButton;
|
||||
private JComboBox findPathComboBox;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JLabel jLabel3;
|
||||
@@ -1161,7 +1375,7 @@ public abstract class DBClosureView extends javax.swing.JDialog {
|
||||
private javax.swing.JLabel jLabel8;
|
||||
private javax.swing.JLabel jLabel9;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private net.sf.jailer.ui.JComboBox searchComboBox;
|
||||
private JComboBox searchComboBox;
|
||||
public javax.swing.JPanel tablePanel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright 2007 - 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package net.sf.jailer.ui.databrowser;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.InternalFrameEvent;
|
||||
import javax.swing.event.InternalFrameListener;
|
||||
import javax.swing.plaf.basic.BasicInternalFrameUI;
|
||||
|
||||
import net.sf.jailer.ui.databrowser.Desktop.RowBrowser;
|
||||
|
||||
/**
|
||||
* Desktop Anchor Manager.
|
||||
*
|
||||
* @author Ralf Wisser
|
||||
*/
|
||||
public abstract class DesktopAnchorManager {
|
||||
|
||||
private final JPanel anchorPanel;
|
||||
private final JButton anchorButton;
|
||||
private Long disabledUntil;
|
||||
private Long showedAt;
|
||||
private RowBrowser currentBrowser;
|
||||
private RowBrowser newestBrowser;
|
||||
private final static int MAX_RETENDION = 2000;
|
||||
|
||||
public DesktopAnchorManager(JPanel anchorPanel) {
|
||||
this.anchorPanel = anchorPanel;
|
||||
this.anchorButton = new JButton(anchorIcon);
|
||||
|
||||
this.anchorPanel.setVisible(false);
|
||||
|
||||
anchorPanel.add(anchorButton);
|
||||
anchorButton.setToolTipText("align horizontally with predecessors");
|
||||
anchorButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (currentBrowser != null) {
|
||||
reset(1000);
|
||||
layout(currentBrowser);
|
||||
}
|
||||
}
|
||||
});
|
||||
anchorButton.addMouseListener(new MouseListener() {
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
showedAt = System.currentTimeMillis();
|
||||
}
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
showedAt = null;
|
||||
}
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onNewTableBrowser(final RowBrowser tableBrowser) {
|
||||
newestBrowser = tableBrowser;
|
||||
tableBrowser.internalFrame.addInternalFrameListener(new InternalFrameListener() {
|
||||
@Override
|
||||
public void internalFrameOpened(InternalFrameEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalFrameIconified(InternalFrameEvent e) {
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalFrameDeiconified(InternalFrameEvent e) {
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalFrameDeactivated(InternalFrameEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalFrameClosing(InternalFrameEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalFrameClosed(InternalFrameEvent e) {
|
||||
reset();
|
||||
newestBrowser = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalFrameActivated(InternalFrameEvent e) {
|
||||
}
|
||||
});
|
||||
MouseListener showButton = new MouseListener() {
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
if (isApplicable(tableBrowser)) {
|
||||
showButton(tableBrowser);
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
}
|
||||
};
|
||||
tableBrowser.browserContentPane.menuPanel.addMouseListener(showButton);
|
||||
|
||||
Stack<JPanel> panels = new Stack<JPanel>();
|
||||
panels.add(tableBrowser.browserContentPane.menuPanel);
|
||||
while (!panels.isEmpty()) {
|
||||
JPanel panel = panels.pop();
|
||||
synchronized (panel.getTreeLock()) {
|
||||
for (Component comp: panel.getComponents()) {
|
||||
if (comp instanceof JPanel) {
|
||||
if (comp != tableBrowser.browserContentPane.sqlPanel) {
|
||||
if (comp != tableBrowser.browserContentPane.relatedRowsPanel) {
|
||||
panels.push((JPanel) comp);
|
||||
}
|
||||
}
|
||||
} else if (comp instanceof JLabel) {
|
||||
comp.addMouseListener(showButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tableBrowser.browserContentPane.addMouseListener(showButton);
|
||||
tableBrowser.browserContentPane.sqlPanel.addMouseListener(showButton);
|
||||
tableBrowser.browserContentPane.relatedRowsPanel.addMouseListener(showButton);
|
||||
tableBrowser.browserContentPane.loadButton.addMouseListener(showButton);
|
||||
tableBrowser.browserContentPane.rowsTable.addMouseListener(showButton);
|
||||
if (tableBrowser.browserContentPane.thumbnail != null) {
|
||||
tableBrowser.browserContentPane.thumbnail.addMouseListener(showButton);
|
||||
}
|
||||
if (tableBrowser.browserContentPane.andCondition.getEditor() != null) {
|
||||
if (tableBrowser.browserContentPane.andCondition.getEditor().getEditorComponent() != null) {
|
||||
tableBrowser.browserContentPane.andCondition.getEditor().getEditorComponent().addMouseListener(showButton);
|
||||
}
|
||||
}
|
||||
Object bi = tableBrowser.internalFrame.getUI();
|
||||
if (bi instanceof BasicInternalFrameUI) {
|
||||
JComponent northPane = ((BasicInternalFrameUI) bi).getNorthPane();
|
||||
if (northPane != null) {
|
||||
northPane.addMouseListener(showButton);
|
||||
}
|
||||
}
|
||||
tableBrowser.internalFrame.addComponentListener(new ComponentListener() {
|
||||
@Override
|
||||
public void componentShown(ComponentEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
reset(100);
|
||||
}
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
reset(100);
|
||||
}
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent e) {
|
||||
reset();
|
||||
}
|
||||
});
|
||||
reset();
|
||||
}
|
||||
|
||||
protected void showButton(RowBrowser tableBrowser) {
|
||||
if (disabledUntil != null && disabledUntil > System.currentTimeMillis()) {
|
||||
return;
|
||||
}
|
||||
currentBrowser = tableBrowser;
|
||||
anchorButton.setSize(anchorButton.getPreferredSize());
|
||||
anchorPanel.setSize(anchorButton.getPreferredSize());
|
||||
Point loc;
|
||||
loc = tableBrowser.internalFrame.getLocation();
|
||||
loc.translate(-anchorButton.getWidth(), 0);
|
||||
anchorPanel.setLocation(0, 0);
|
||||
loc = SwingUtilities.convertPoint(tableBrowser.internalFrame.getParent(), loc, anchorPanel);
|
||||
anchorPanel.setLocation(loc);
|
||||
anchorButton.setVisible(true);
|
||||
anchorPanel.setVisible(true);
|
||||
showedAt = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
reset(0);
|
||||
}
|
||||
|
||||
void reset(int delay) {
|
||||
anchorButton.setVisible(false);
|
||||
anchorPanel.setVisible(false);
|
||||
if (delay > 0) {
|
||||
disabledUntil = System.currentTimeMillis() + delay;
|
||||
}
|
||||
}
|
||||
|
||||
public RowBrowser getNewestBrowser() {
|
||||
return newestBrowser;
|
||||
}
|
||||
|
||||
public void setNewestBrowser(RowBrowser browser) {
|
||||
newestBrowser = browser;
|
||||
}
|
||||
|
||||
public void checkRetention() {
|
||||
long now = System.currentTimeMillis();
|
||||
if (showedAt != null && showedAt + MAX_RETENDION < now) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void layout(RowBrowser anchor);
|
||||
protected abstract boolean isApplicable(RowBrowser tableBrowser);
|
||||
|
||||
private ImageIcon anchorIcon;
|
||||
{
|
||||
String dir = "/net/sf/jailer/ui/resource";
|
||||
|
||||
// load images
|
||||
try {
|
||||
anchorIcon = new ImageIcon(DataBrowser.class.getResource(dir + "/anchor.png"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright 2007 - 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package net.sf.jailer.ui.databrowser;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
|
||||
/**
|
||||
* Animates layout changes of {@link Desktop}.
|
||||
*
|
||||
* @author Ralf Wisser
|
||||
*/
|
||||
public class DesktopAnimation {
|
||||
|
||||
private final double DURATION = 750;
|
||||
private final Desktop desktop;
|
||||
|
||||
/**
|
||||
* Animation.
|
||||
*/
|
||||
abstract class Animation {
|
||||
private long startTime;
|
||||
public void start() {
|
||||
startTime = System.currentTimeMillis();
|
||||
stopScrolling = false;
|
||||
}
|
||||
abstract boolean animate(double f);
|
||||
};
|
||||
|
||||
/**
|
||||
* Animation per subject (started).
|
||||
*/
|
||||
private Map<Object, Animation> animations = Collections.synchronizedMap(new LinkedHashMap<Object, Animation>());
|
||||
|
||||
/**
|
||||
* Animation per subject (waiting).
|
||||
*/
|
||||
private Map<Object, Animation> waiting = new LinkedHashMap<Object, Animation>();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param desktop the desktop
|
||||
*/
|
||||
public DesktopAnimation(Desktop desktop) {
|
||||
this.desktop = desktop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls desktop to a given location.
|
||||
*/
|
||||
class ScrollTo extends Animation {
|
||||
private final Point scrollFrom;
|
||||
private final int initialWidth;
|
||||
private final int initialHeight;
|
||||
private final Rectangle scrollTo;
|
||||
|
||||
public ScrollTo(Rectangle scrollTo, Point scrollFrom, int initialWidth, int initialHeight) {
|
||||
this.scrollFrom = scrollFrom;
|
||||
this.initialWidth = initialWidth;
|
||||
this.initialHeight = initialHeight;
|
||||
this.scrollTo = scrollTo;
|
||||
}
|
||||
|
||||
public boolean animate(double f) {
|
||||
if (stopScrolling) {
|
||||
return false;
|
||||
}
|
||||
if (scrollTo != null) {
|
||||
int w = wAvg(f, initialWidth, scrollTo.width);
|
||||
int h = wAvg(f, initialHeight, scrollTo.height);
|
||||
int x = (int) (scrollFrom.x + f * (scrollTo.x + scrollTo.width / 2 - scrollFrom.x)) - w / 2;
|
||||
int y = (int) (scrollFrom.y + f * (scrollTo.y + scrollTo.height / 2 - scrollFrom.y)) - h / 2;
|
||||
desktop.checkDesktopSize();
|
||||
desktop.scrollRectToVisible(new Rectangle(x, y, w, h));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves an internal frame of the desktop.
|
||||
*/
|
||||
class MoveIFrame extends Animation {
|
||||
private final JInternalFrame iFrame;
|
||||
private final Rectangle moveTo;
|
||||
private final Rectangle moveFrom;
|
||||
private final BrowserContentPane browserContentPane;
|
||||
|
||||
public MoveIFrame(JInternalFrame iFrame, BrowserContentPane browserContentPane, Rectangle moveTo) {
|
||||
this.iFrame = iFrame;
|
||||
this.browserContentPane = browserContentPane;
|
||||
this.moveTo = moveTo;
|
||||
this.moveFrom = iFrame.getBounds();
|
||||
}
|
||||
|
||||
public boolean animate(double f) {
|
||||
int wx = wAvg(f, moveFrom.x, moveTo.x);
|
||||
int wy = wAvg(f, moveFrom.y, moveTo.y);
|
||||
int ww = wAvg(f, moveFrom.width, moveTo.width);
|
||||
int wh = wAvg(f, moveFrom.height, moveTo.height);
|
||||
if (f < 1.0 && Math.abs(ww - iFrame.getWidth()) < 4 && Math.abs(wh - iFrame.getHeight()) < 4) {
|
||||
iFrame.setLocation(wx, wy);
|
||||
} else {
|
||||
iFrame.setBounds(wx, wy, ww, wh);
|
||||
}
|
||||
if (f == 1.0) {
|
||||
browserContentPane.adjustRowTableColumnsWidth();
|
||||
}
|
||||
return !(wx == moveTo.x && wy == moveTo.y && ww == moveTo.width && wh == moveTo.height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an animation step for each animation.
|
||||
*/
|
||||
public boolean animate() {
|
||||
boolean result = false;
|
||||
for (Iterator<Entry<Object, Animation>> i = animations.entrySet().iterator(); i.hasNext(); ) {
|
||||
Animation animation = i.next().getValue();
|
||||
double f = (System.currentTimeMillis() - animation.startTime) / DURATION;
|
||||
double fs;
|
||||
|
||||
if (f > 1.0) {
|
||||
f = 1.0;
|
||||
fs = 1.0;
|
||||
} else {
|
||||
final double M1 = -3;
|
||||
final double M2 = 5;
|
||||
fs = sig(f * (-M1 + M2) + M1);
|
||||
}
|
||||
|
||||
if (!animation.animate(fs)) {
|
||||
i.remove();
|
||||
continue;
|
||||
}
|
||||
result = true;
|
||||
|
||||
if (f == 1.0) {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
desktop.checkDesktopSize();
|
||||
return result;
|
||||
}
|
||||
|
||||
private double sig(double x) {
|
||||
return 1.0 / (1.0 + Math.exp(-x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls desktop to a given location (animated).
|
||||
*
|
||||
* @param vr the location
|
||||
*/
|
||||
public void scrollRectToVisible(Rectangle vr) {
|
||||
Rectangle svr = desktop.getScrollPane().getViewport().getViewRect();
|
||||
if (!svr.contains(vr)) {
|
||||
int mx = vr.x + vr.width / 2;
|
||||
int my = vr.y + vr.height / 2;
|
||||
if (mx < svr.x) {
|
||||
mx = svr.x;
|
||||
}
|
||||
if (my < svr.y) {
|
||||
my = svr.y;
|
||||
}
|
||||
if (mx > svr.x + svr.width) {
|
||||
mx = svr.x + svr.width;
|
||||
}
|
||||
if (my > svr.y + svr.height) {
|
||||
my = svr.y + svr.height;
|
||||
}
|
||||
startAnimation(desktop, new ScrollTo(vr, new Point(mx, my), 2 * Math.min(mx - svr.x, svr.x + svr.width - mx), 2 * Math.min(my - svr.y, svr.y + svr.height - my)));
|
||||
} else {
|
||||
waiting.remove(desktop);
|
||||
animations.remove(desktop);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls desktop to a given location (immediately).
|
||||
*
|
||||
* @param vr the location
|
||||
*/
|
||||
public void scrollRectToVisibleImmediately(Rectangle vr) {
|
||||
desktop.scrollRectToVisible(vr);
|
||||
waiting.remove(desktop);
|
||||
animations.remove(desktop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bounds of an internal frame (animated).
|
||||
*
|
||||
* @param iFrame the frame
|
||||
* @param browserContentPane the content pane
|
||||
* @param r new bounds
|
||||
*/
|
||||
public void setIFrameBounds(JInternalFrame iFrame, BrowserContentPane browserContentPane, Rectangle r) {
|
||||
startAnimation(iFrame, new MoveIFrame(iFrame, browserContentPane, r));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bounds of an internal frame (immediately).
|
||||
*
|
||||
* @param iFrame the frame
|
||||
* @param browserContentPane the content pane
|
||||
* @param r new bounds
|
||||
*/
|
||||
public void setIFrameBoundsImmediately(JInternalFrame internalFrame, BrowserContentPane browserContentPane, Rectangle newBounds) {
|
||||
internalFrame.setBounds(newBounds);
|
||||
browserContentPane.adjustRowTableColumnsWidth();
|
||||
waiting.remove(internalFrame);
|
||||
animations.remove(internalFrame);
|
||||
}
|
||||
|
||||
public Rectangle getIFrameBounds(JInternalFrame iFrame) {
|
||||
Animation animation = animations.get(iFrame);
|
||||
if (animation instanceof MoveIFrame) {
|
||||
return ((MoveIFrame) animation).moveTo;
|
||||
}
|
||||
animation = waiting.get(iFrame);
|
||||
if (animation instanceof MoveIFrame) {
|
||||
return ((MoveIFrame) animation).moveTo;
|
||||
}
|
||||
return iFrame.getBounds();
|
||||
}
|
||||
|
||||
private int wAvg(double f, int a, int b) {
|
||||
return (int) (a + f * (b - a));
|
||||
}
|
||||
|
||||
private void startAnimation(Object key, Animation animation) {
|
||||
Component desktopAncestor = SwingUtilities.getWindowAncestor(desktop);
|
||||
if (desktopAncestor == null) {
|
||||
desktopAncestor = desktop;
|
||||
}
|
||||
final Component fDesktopAncestor = desktopAncestor;
|
||||
UIUtil.setWaitCursor(desktopAncestor);
|
||||
waiting.put(key, animation);
|
||||
UIUtil.invokeLater(12, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UIUtil.resetWaitCursor(fDesktopAncestor);
|
||||
for (Entry<Object, Animation> e: waiting.entrySet()) {
|
||||
e.getValue().start();
|
||||
animations.put(e.getKey(), e.getValue());
|
||||
}
|
||||
waiting.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean stopScrolling = false;
|
||||
|
||||
public boolean isActive() {
|
||||
return !animations.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2007 - 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package net.sf.jailer.ui.databrowser;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.swing.JInternalFrame;
|
||||
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
|
||||
/**
|
||||
* Renders state changes of {@link JInternalFrame}s in {@link Desktop}.
|
||||
*
|
||||
* @author Ralf Wisser
|
||||
*/
|
||||
public class DesktopIFrameStateChangeRenderer {
|
||||
|
||||
private final double DURATION = 1500.0;
|
||||
private List<JInternalFrame> atomicBlock = null;
|
||||
|
||||
private class StateChange {
|
||||
JInternalFrame iFrame;
|
||||
long startTime;
|
||||
double factorOffset = 0;
|
||||
}
|
||||
|
||||
private Map<JInternalFrame, StateChange> stateChanges = new LinkedHashMap<JInternalFrame, StateChange>();
|
||||
|
||||
public void onNewIFrame(final JInternalFrame iFrame) {
|
||||
if (atomicBlock != null) {
|
||||
atomicBlock.add(iFrame);
|
||||
} else {
|
||||
UIUtil.invokeLater(12, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
StateChange stateChange = new StateChange();
|
||||
stateChange.iFrame = iFrame;
|
||||
stateChange.startTime = System.currentTimeMillis();
|
||||
stateChanges.put(iFrame, stateChange);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void onIFrameSelected(JInternalFrame iFrame) {
|
||||
onIFrameSelected(iFrame, 0);
|
||||
}
|
||||
|
||||
public void onIFrameSelected(final JInternalFrame iFrame, final double factorOffset) {
|
||||
if (atomicBlock == null) {
|
||||
UIUtil.invokeLater(12, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!stateChanges.containsKey(iFrame)) {
|
||||
StateChange stateChange = new StateChange();
|
||||
stateChange.iFrame = iFrame;
|
||||
stateChange.startTime = System.currentTimeMillis();
|
||||
stateChange.factorOffset = factorOffset;
|
||||
stateChanges.put(iFrame, stateChange);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void render(Graphics2D g2d) {
|
||||
for (Iterator<Entry<JInternalFrame, StateChange>> iter = stateChanges.entrySet().iterator(); iter.hasNext(); ) {
|
||||
StateChange stateChange = iter.next().getValue();
|
||||
|
||||
double factor = (System.currentTimeMillis() - stateChange.startTime) / DURATION;
|
||||
factor += stateChange.factorOffset;
|
||||
if (factor >= 1) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
if (factor < 0) {
|
||||
factor = 0;
|
||||
}
|
||||
|
||||
if (stateChange.iFrame.isVisible()) {
|
||||
Color color = new Color(255, 255, 0, (int) (170 * (1 - factor)));
|
||||
g2d.setColor(color);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
double width = stateChange.iFrame.getWidth() / 12 * ((factor - stateChange.factorOffset) / (1 - stateChange.factorOffset) + 0.1);
|
||||
BasicStroke stroke = new BasicStroke((float) width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
|
||||
g2d.setStroke(stroke);
|
||||
|
||||
Rectangle rect = stateChange.iFrame.getBounds();
|
||||
int w = (int) (0.5 * width);
|
||||
rect = new Rectangle(rect.x + w / 2, rect.y + w / 2, rect.width - w, rect.height - w);
|
||||
|
||||
Path2D.Double path = new Path2D.Double();
|
||||
path.moveTo(rect.getX(), rect.getY());
|
||||
path.lineTo(rect.getX() + rect.getWidth(), rect.getY());
|
||||
path.lineTo(rect.getX() + rect.getWidth(), rect.getY() + rect.getHeight());
|
||||
path.lineTo(rect.getX(), rect.getY() + rect.getHeight());
|
||||
path.lineTo(rect.getX(), rect.getY());
|
||||
|
||||
g2d.draw(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void startAtomic() {
|
||||
atomicBlock = new ArrayList<JInternalFrame>();
|
||||
}
|
||||
|
||||
public void endAtomic() {
|
||||
if (atomicBlock != null) {
|
||||
final List<JInternalFrame> iFrames = atomicBlock;
|
||||
atomicBlock = null;
|
||||
UIUtil.invokeLater(12, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
long offset = 0;
|
||||
for (int i = iFrames.size() - 1; i >= 0; --i) {
|
||||
JInternalFrame iFrame = iFrames.get(i);
|
||||
StateChange stateChange = new StateChange();
|
||||
stateChange.iFrame = iFrame;
|
||||
stateChange.startTime = currentTimeMillis - offset;
|
||||
stateChanges.put(iFrame, stateChange);
|
||||
offset += DURATION / 3;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void rollbackAtomic() {
|
||||
atomicBlock = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,6 +17,7 @@ package net.sf.jailer.ui.databrowser;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
@@ -40,6 +41,7 @@ import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.table.TableModel;
|
||||
|
||||
import net.sf.jailer.database.Session;
|
||||
import net.sf.jailer.datamodel.Column;
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
import net.sf.jailer.datamodel.RowIdSupport;
|
||||
@@ -61,18 +63,24 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
private final RowSorter<? extends TableModel> rowSorter;
|
||||
private final RowIdSupport rowIdSupport;
|
||||
private final boolean showSpinner;
|
||||
|
||||
private final Session session;
|
||||
|
||||
/** Creates new form DetailsView
|
||||
* @param rowSorter
|
||||
* @param showSelectButton
|
||||
* @param deselect
|
||||
*/
|
||||
public DetailsView(List<Row> rows, int size, DataModel dataModel, Table table, int rowIndex, RowSorter<? extends TableModel> rowSorter, boolean showSpinner, boolean showSelectButton, RowIdSupport rowIdSupport) {
|
||||
public DetailsView(List<Row> rows, int size, DataModel dataModel, Table table, int rowIndex, RowSorter<? extends TableModel> rowSorter, boolean showSpinner, boolean showSelectButton, RowIdSupport rowIdSupport, boolean deselect, Session session) {
|
||||
this.table = table;
|
||||
this.rows = rows;
|
||||
this.rowSorter = rowSorter;
|
||||
this.rowIdSupport = rowIdSupport;
|
||||
this.showSpinner = showSpinner;
|
||||
this.session = session;
|
||||
initComponents();
|
||||
if (deselect) {
|
||||
selectButton.setText("Deselect Row");
|
||||
}
|
||||
if (rowSorter != null) {
|
||||
rowIndex = rowSorter.convertRowIndexToView(rowIndex);
|
||||
}
|
||||
@@ -125,8 +133,7 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
@Override
|
||||
public void ancestorAdded(AncestorEvent event) {
|
||||
closeButton.grabFocus();
|
||||
jScrollPane1.getVerticalScrollBar().setValue(jScrollPane1.getVerticalScrollBar().getMinimum());
|
||||
jScrollPane1.getHorizontalScrollBar().setValue(jScrollPane1.getHorizontalScrollBar().getMinimum());
|
||||
resetScrollPane();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -137,8 +144,12 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
private final Font nonbold = new Font(font.getName(), font.getStyle() & ~Font.BOLD, font.getSize());
|
||||
private final Font italic = new Font(font.getName(), font.getStyle() & ~Font.BOLD | Font.ITALIC, font.getSize());
|
||||
private final Color BG1 = new Color(255, 255, 255);
|
||||
private final Color BG2 = new Color(230, 255, 255);
|
||||
private final Color BG2 = new Color(242, 255, 242);
|
||||
private final Color BG3 = new Color(194, 228, 255);
|
||||
private final Color BG3_2 = new Color(184, 220, 255);
|
||||
private final Color FG1 = new Color(155, 0, 0);
|
||||
private List<JLabel> labels = new ArrayList<JLabel>();
|
||||
private List<Color> labelColors = new ArrayList<Color>();
|
||||
|
||||
public void setBorderColor(Color color) {
|
||||
jScrollPane1.setBorder(BorderFactory.createEtchedBorder(color, Color.GRAY));
|
||||
@@ -147,13 +158,17 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
private int currentRow;
|
||||
private boolean sortColumns;
|
||||
private JPanel content;
|
||||
|
||||
private boolean isPacked = false;
|
||||
|
||||
private void setCurrentRow(int row, boolean selectableFields) {
|
||||
currentRow = row;
|
||||
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
JPanel oldContent = content;
|
||||
labels.clear();
|
||||
labelColors.clear();
|
||||
|
||||
final JPanel oldContent = content;
|
||||
content = new JPanel(new GridBagLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.weightx = 1;
|
||||
@@ -163,7 +178,7 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
gridBagConstraints.gridy = 0;
|
||||
|
||||
int i = 0;
|
||||
final List<Column> columns = rowIdSupport.getColumns(table);
|
||||
final List<Column> columns = rowIdSupport.getColumns(table, session);
|
||||
List<Integer> columnIndex = new ArrayList<Integer>();
|
||||
for (int j = 0; j < columns.size(); ++j) {
|
||||
columnIndex.add(j);
|
||||
@@ -240,6 +255,8 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
} else {
|
||||
l.setForeground(Color.BLUE);
|
||||
}
|
||||
labelColors.add(f.getBackground());
|
||||
labels.add(f);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
@@ -255,12 +272,30 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
gridBagConstraints.gridy = i;
|
||||
content.add(l, gridBagConstraints);
|
||||
}
|
||||
jPanel1.add(content, gridBagConstraints);
|
||||
if (oldContent != null) {
|
||||
jPanel1.remove(oldContent);
|
||||
Runnable update = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (oldContent != null) {
|
||||
jPanel1.remove(oldContent);
|
||||
}
|
||||
GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.weightx = 1;
|
||||
gridBagConstraints.weighty = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
jPanel1.add(content, gridBagConstraints);
|
||||
jPanel1.revalidate();
|
||||
jPanel1.repaint();
|
||||
}
|
||||
};
|
||||
if (isPacked) {
|
||||
UIUtil.invokeLater(2, update);
|
||||
} else {
|
||||
update.run();
|
||||
isPacked = true;
|
||||
}
|
||||
jPanel1.revalidate();
|
||||
jPanel1.repaint();
|
||||
onRowChanged(row);
|
||||
}
|
||||
|
||||
@@ -354,6 +389,12 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
private void sortCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortCheckBoxActionPerformed
|
||||
sortColumns = !sortColumns;
|
||||
setCurrentRow(currentRow, showSpinner);
|
||||
UIUtil.invokeLater(4, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resetScrollPane();
|
||||
}
|
||||
});
|
||||
}//GEN-LAST:event_sortCheckBoxActionPerformed
|
||||
|
||||
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
|
||||
@@ -364,6 +405,22 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
onSelectRow(rows.get(rowSorter != null? rowSorter.convertRowIndexToModel(currentRow) : currentRow));
|
||||
}//GEN-LAST:event_selectButtonActionPerformed
|
||||
|
||||
public void updateInClosureState(boolean inClosure) {
|
||||
if (inClosure) {
|
||||
int r = 0;
|
||||
for (JLabel label: labels) {
|
||||
label.setBackground(r++ % 2 == 0? BG3 : BG3_2);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < labels.size(); ++i) {
|
||||
labels.get(i).setBackground(labelColors.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public JPanel getDetailsPanel() {
|
||||
return jPanel1;
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton closeButton;
|
||||
@@ -380,4 +437,9 @@ public abstract class DetailsView extends javax.swing.JPanel {
|
||||
setCurrentRow(currentRow, showSpinner);
|
||||
}
|
||||
|
||||
private void resetScrollPane() {
|
||||
jScrollPane1.getVerticalScrollBar().setValue(jScrollPane1.getVerticalScrollBar().getMinimum());
|
||||
jScrollPane1.getHorizontalScrollBar().setValue(jScrollPane1.getHorizontalScrollBar().getMinimum());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,13 +32,26 @@ public class Row {
|
||||
this.rowId = rowId;
|
||||
this.values = v;
|
||||
this.primaryKey = primaryKey;
|
||||
if (rowId.isEmpty()) {
|
||||
synchronized (this) {
|
||||
this.nonEmptyRowId = Long.toString(nextUniqueId++);
|
||||
}
|
||||
} else {
|
||||
nonEmptyRowId = rowId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unique ID, also serves as SQL predicate which identifies this row.
|
||||
* Empty string if row has no key.
|
||||
*/
|
||||
public final String rowId;
|
||||
|
||||
/**
|
||||
* Unique ID. Equals rowId if it's not empty.
|
||||
*/
|
||||
public final String nonEmptyRowId;
|
||||
|
||||
/**
|
||||
* Column values.
|
||||
*/
|
||||
@@ -68,4 +81,6 @@ public class Row {
|
||||
this.parentModelIndex = parentModelIndex;
|
||||
}
|
||||
|
||||
private static long nextUniqueId = 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -204,7 +204,6 @@ public class SbEDialog extends javax.swing.JDialog {
|
||||
}//GEN-LAST:event_jButton3ActionPerformed
|
||||
|
||||
private void regardButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_regardButtonActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_regardButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package net.sf.jailer.ui.databrowser;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Window;
|
||||
import java.io.File;
|
||||
@@ -36,6 +35,7 @@ import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
|
||||
import net.sf.jailer.ui.DbConnectionDialog;
|
||||
import net.sf.jailer.ui.Environment;
|
||||
import net.sf.jailer.ui.JComboBox;
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
|
||||
/**
|
||||
* Schema Mapping Dialog.
|
||||
@@ -58,7 +58,7 @@ public class SchemaMappingDialog extends javax.swing.JDialog {
|
||||
Window windowAncestor = parent; // SwingUtilities.getWindowAncestor(parent);
|
||||
try {
|
||||
if (windowAncestor != null) {
|
||||
windowAncestor.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(windowAncestor);
|
||||
}
|
||||
String defSchema = JDBCMetaDataBasedModelElementFinder.getDefaultSchema(session, session.getSchema());
|
||||
if (!defSchema.isEmpty()) {
|
||||
@@ -108,7 +108,7 @@ public class SchemaMappingDialog extends javax.swing.JDialog {
|
||||
}
|
||||
} finally {
|
||||
if (windowAncestor != null) {
|
||||
windowAncestor.setCursor(Cursor.getDefaultCursor());
|
||||
UIUtil.resetWaitCursor(windowAncestor);
|
||||
}
|
||||
}
|
||||
pack();
|
||||
|
||||
@@ -29,6 +29,7 @@ public class TreeLayoutOptimizer<T> {
|
||||
public static class Node<T> {
|
||||
private final T userObject;
|
||||
private final List<Node<T>> children = new ArrayList<Node<T>>();
|
||||
private final boolean isAnchor;
|
||||
int level = 0;
|
||||
Node<T> parent = null;
|
||||
double position = 0;
|
||||
@@ -37,8 +38,9 @@ public class TreeLayoutOptimizer<T> {
|
||||
return userObject;
|
||||
}
|
||||
|
||||
public Node(T userObject) {
|
||||
public Node(T userObject, boolean isAnchor) {
|
||||
this.userObject = userObject;
|
||||
this.isAnchor = isAnchor;
|
||||
}
|
||||
|
||||
public void addChild(Node<T> child) {
|
||||
@@ -67,6 +69,21 @@ public class TreeLayoutOptimizer<T> {
|
||||
return 1 + maxChildDepth;
|
||||
}
|
||||
|
||||
public double getMinPosition() {
|
||||
double minPos = position;
|
||||
for (Node<T> child: children) {
|
||||
minPos = Math.min(minPos, child.getMinPosition());
|
||||
}
|
||||
return minPos;
|
||||
}
|
||||
|
||||
public void adjustPosition(double delta) {
|
||||
position -= delta;
|
||||
for (Node<T> child: children) {
|
||||
child.adjustPosition(delta);
|
||||
}
|
||||
}
|
||||
|
||||
public int getNodesCount() {
|
||||
int count = 1;
|
||||
for (Node<T> child: children) {
|
||||
@@ -77,15 +94,36 @@ public class TreeLayoutOptimizer<T> {
|
||||
|
||||
public double getCompactness() {
|
||||
double compactness = 0;
|
||||
if (children.size() > 1) {
|
||||
if (children.size() > 0) {
|
||||
compactness = children.get(children.size() - 1).position - children.get(0).position;
|
||||
compactness *= compactness;
|
||||
Node<T> pre = null;
|
||||
for (Node<T> child: children) {
|
||||
compactness += child.getCompactness();
|
||||
if (pre != null) {
|
||||
if (pre.position + 1 > child.position) {
|
||||
double w = pre.position + 1 - child.position;
|
||||
compactness += w * w * 1000;
|
||||
}
|
||||
}
|
||||
pre = child;
|
||||
}
|
||||
}
|
||||
return compactness;
|
||||
}
|
||||
|
||||
public double getAnchorQuality() {
|
||||
double quality = 0;
|
||||
for (Node<T> child: children) {
|
||||
quality += child.getAnchorQuality();
|
||||
}
|
||||
|
||||
if (isAnchor && parent != null) {
|
||||
double d = parent.position - position;
|
||||
quality += d * d;
|
||||
}
|
||||
return quality;
|
||||
}
|
||||
};
|
||||
|
||||
public static <T> void optimizeTreeLayout(Node<T> root) {
|
||||
@@ -93,6 +131,7 @@ public class TreeLayoutOptimizer<T> {
|
||||
optimizeChildrenOrder(root, System.currentTimeMillis(), MAX_OPTIM_TIME_MS, numNodes);
|
||||
layoutTree(root, numNodes);
|
||||
optimizeLeafs(root);
|
||||
root.adjustPosition(root.getMinPosition());
|
||||
}
|
||||
|
||||
private static long MAX_OPTIM_TIME_MS = 1000;
|
||||
@@ -111,7 +150,7 @@ public class TreeLayoutOptimizer<T> {
|
||||
sumMaxPositionSqr += maxPositionPerLevel[i] * maxPositionPerLevel[i];
|
||||
}
|
||||
}
|
||||
return sumMaxPositionSqr / numNodes + root.getCompactness();
|
||||
return sumMaxPositionSqr / numNodes + root.getCompactness() + root.getAnchorQuality();
|
||||
}
|
||||
|
||||
private static <T> void layoutNode(Node<T> node, double[] maxPositionPerLevel) {
|
||||
@@ -125,18 +164,31 @@ public class TreeLayoutOptimizer<T> {
|
||||
|
||||
private static <T> void adjustParentPosition(Node<T> node, double[] maxPositionPerLevel) {
|
||||
while (node != null) {
|
||||
double parentPos = node.children.get(0).position + (maxPositionPerLevel[node.level + 1] - node.children.get(0).position) / 2.0;
|
||||
if (node.position < parentPos) {
|
||||
node.position = parentPos;
|
||||
// node.position = (node.position + parentPos) / 2.0;
|
||||
maxPositionPerLevel[node.level] = parentPos;
|
||||
Node<T> anchorChild = null;
|
||||
if (node.isAnchor) {
|
||||
for (Node<T> child: node.children) {
|
||||
if (child.isAnchor) {
|
||||
anchorChild = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (anchorChild != null) {
|
||||
node.position = anchorChild.position;
|
||||
} else {
|
||||
break;
|
||||
double parentPos = node.children.get(0).position + (maxPositionPerLevel[node.level + 1] - node.children.get(0).position) / 2.0;
|
||||
if (node.position < parentPos) {
|
||||
node.position = parentPos;
|
||||
// node.position = (node.position + parentPos) / 2.0;
|
||||
maxPositionPerLevel[node.level] = parentPos;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static <T> void optimizeLeafs(Node<T> node) {
|
||||
if (node.children.isEmpty() && node.parent != null && node.position < node.parent.position) {
|
||||
int i = node.parent.children.indexOf(node);
|
||||
|
||||
@@ -36,6 +36,7 @@ import javax.swing.ImageIcon;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import net.sf.jailer.database.Session.AbstractResultSetReader;
|
||||
import net.sf.jailer.modelbuilder.MemorizedResultSet;
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
import net.sf.jailer.util.Quoting;
|
||||
@@ -148,6 +149,7 @@ public class MDSchema extends MDObject {
|
||||
if (tables == null) {
|
||||
try {
|
||||
tables = new ArrayList<MDTable>();
|
||||
Map<String, Long> estimatedRowCounts = readEstimatedRowCounts();
|
||||
MetaDataSource metaDataSource = getMetaDataSource();
|
||||
synchronized (metaDataSource.getSession().getMetaData()) {
|
||||
ResultSet rs = metaDataSource.readTables(getName());
|
||||
@@ -156,7 +158,8 @@ public class MDSchema extends MDObject {
|
||||
String tableName = metaDataSource.getQuoting().quote(rs.getString(3));
|
||||
final MDTable table = new MDTable(tableName, this, "VIEW".equalsIgnoreCase(rs.getString(4)),
|
||||
"SYNONYM".equalsIgnoreCase(rs.getString(4))
|
||||
|| "ALIAS".equalsIgnoreCase(rs.getString(4)));
|
||||
|| "ALIAS".equalsIgnoreCase(rs.getString(4)),
|
||||
estimatedRowCounts.get(rs.getString(3)));
|
||||
tables.add(table);
|
||||
if (loadTableColumns) {
|
||||
loadJobs.put(tableName, new Runnable() {
|
||||
@@ -194,6 +197,30 @@ public class MDSchema extends MDObject {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Long> readEstimatedRowCounts() {
|
||||
final Map<String, Long> result = new HashMap<String, Long>();
|
||||
|
||||
String query = getMetaDataSource().getSession().dbms.getEstimatedRowCountQuery();
|
||||
if (query != null) {
|
||||
try {
|
||||
getMetaDataSource().getSession().executeQuery(String.format(query, getUnquotedName()), new AbstractResultSetReader() {
|
||||
@Override
|
||||
public void readCurrentRow(ResultSet resultSet) throws SQLException {
|
||||
String tableName = resultSet.getString(1);
|
||||
long rowCount = resultSet.getLong(2);
|
||||
if (!resultSet.wasNull() && rowCount >= 0) {
|
||||
result.put(tableName, rowCount);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (SQLException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the tables of the schema been loaded?
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package net.sf.jailer.ui.databrowser.metadata;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
@@ -42,6 +41,7 @@ import net.sf.jailer.database.Session;
|
||||
import net.sf.jailer.datamodel.Column;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
import net.sf.jailer.util.Quoting;
|
||||
import net.sf.jailer.util.SqlUtil;
|
||||
|
||||
@@ -67,6 +67,8 @@ public class MDTable extends MDObject {
|
||||
private final boolean isView;
|
||||
private final boolean isSynonym;
|
||||
|
||||
public final Long estimatedRowCount;
|
||||
|
||||
// DDL of the table or <code>null</code>, if no DDL is available
|
||||
private String ddl;
|
||||
|
||||
@@ -76,11 +78,12 @@ public class MDTable extends MDObject {
|
||||
* @param name table name
|
||||
* @param schema the tables schema
|
||||
*/
|
||||
public MDTable(String name, MDSchema schema, boolean isView, boolean isSynonym) {
|
||||
public MDTable(String name, MDSchema schema, boolean isView, boolean isSynonym, Long estimatedRowCount) {
|
||||
super(name, schema.getMetaDataSource());
|
||||
this.isView = isView;
|
||||
this.isSynonym = isSynonym;
|
||||
this.schema = schema;
|
||||
this.estimatedRowCount = estimatedRowCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,7 +114,7 @@ public class MDTable extends MDObject {
|
||||
if (isLoaded()) {
|
||||
return getColumns();
|
||||
}
|
||||
waitCursorSubject.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(waitCursorSubject);
|
||||
try {
|
||||
loading.set(true);
|
||||
queue.add(new Runnable() {
|
||||
@@ -132,7 +135,7 @@ public class MDTable extends MDObject {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
waitCursorSubject.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(waitCursorSubject);
|
||||
}
|
||||
if (loading.get()) {
|
||||
return new ArrayList<String>();
|
||||
@@ -159,7 +162,7 @@ public class MDTable extends MDObject {
|
||||
MetaDataSource metaDataSource = getMetaDataSource();
|
||||
synchronized (metaDataSource.getSession().getMetaData()) {
|
||||
ResultSet resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(getSchema().getMetaDataSource().getSession(), getSchema().getMetaDataSource().getSession().getMetaData(), Quoting.staticUnquote(getSchema().getName()), Quoting.staticUnquote(getName()), "%",
|
||||
true);
|
||||
true, isSynonym? "SYNONYM" : null);
|
||||
while (resultSet.next()) {
|
||||
String colName = metaDataSource.getQuoting().quote(resultSet.getString(4));
|
||||
columns.add(colName);
|
||||
@@ -208,7 +211,23 @@ public class MDTable extends MDObject {
|
||||
}
|
||||
pk.put(keySeq, metaDataSource.getQuoting().quote(resultSet.getString(4)));
|
||||
}
|
||||
primaryKey.addAll(pk.values());
|
||||
if (pk.isEmpty()) {
|
||||
Table table = metaDataSource.toTable(this);
|
||||
if (table != null) {
|
||||
if (table.primaryKey != null) {
|
||||
for (Column c: table.primaryKey.getColumns()) {
|
||||
for (String mc: columns) {
|
||||
if (Quoting.equalsIgnoreQuotingAndCase(c.name, mc)) {
|
||||
primaryKey.add(mc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
primaryKey.addAll(pk.values());
|
||||
}
|
||||
resultSet.close();
|
||||
}
|
||||
} finally {
|
||||
@@ -327,6 +346,22 @@ public class MDTable extends MDObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ddl == null && isView) {
|
||||
String viewTextOrDDLQuery = session.dbms.getViewTextOrDDLQuery();
|
||||
if (viewTextOrDDLQuery != null) {
|
||||
String viewTextQuery = String.format(viewTextOrDDLQuery, Quoting.staticUnquote(getSchema().getName()), Quoting.staticUnquote(getName()));
|
||||
try {
|
||||
session.executeQuery(viewTextQuery, new Session.AbstractResultSetReader() {
|
||||
@Override
|
||||
public void readCurrentRow(ResultSet resultSet) throws SQLException {
|
||||
ddl = resultSet.getString(1);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ddl == null) {
|
||||
try {
|
||||
ddl = createDDL();
|
||||
|
||||
@@ -39,7 +39,7 @@ public enum MetaDataDetails {
|
||||
COLUMNS("Columns", 0) {
|
||||
@Override
|
||||
public ResultSet readMetaDataDetails(Session session, MDTable mdTable) throws SQLException {
|
||||
return JDBCMetaDataBasedModelElementFinder.getColumns(session, session.getMetaData(), Quoting.staticUnquote(mdTable.getSchema().getName()), Quoting.staticUnquote(mdTable.getName()), "%", true);
|
||||
return JDBCMetaDataBasedModelElementFinder.getColumns(session, session.getMetaData(), Quoting.staticUnquote(mdTable.getSchema().getName()), Quoting.staticUnquote(mdTable.getName()), "%", true, mdTable.isSynonym()? "SYNONYM" : null);
|
||||
}
|
||||
@Override
|
||||
public void adjustRowsTable(JTable rowsTable) {
|
||||
|
||||
@@ -226,11 +226,16 @@ public abstract class MetaDataDetailsPanel extends javax.swing.JPanel {
|
||||
final int tableNameColumnIndex = 3;
|
||||
final Set<String> pkNames = Collections.synchronizedSet(new HashSet<String>());
|
||||
final BrowserContentPane rb = new BrowserContentPane(datamodel.get(), null, "", session, null, null,
|
||||
null, null, new BrowserContentPane.RowsClosure(), 0, false, false, executionContext) {
|
||||
null, null, new BrowserContentPane.RowsClosure(), false, false, executionContext) {
|
||||
{
|
||||
noSingleRowDetailsView = true;
|
||||
rowsTableScrollPane.setWheelScrollingEnabled(true);
|
||||
}
|
||||
@Override
|
||||
protected int getReloadLimit() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unhide() {
|
||||
}
|
||||
@@ -257,7 +262,8 @@ public abstract class MetaDataDetailsPanel extends javax.swing.JPanel {
|
||||
protected void onContentChange(List<Row> rows, boolean reloadChildren) {
|
||||
}
|
||||
@Override
|
||||
protected void navigateTo(Association association, int rowIndex, Row row) {
|
||||
protected RowBrowser navigateTo(Association association, int rowIndex, Row row) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
protected List<RowBrowser> getTableBrowser() {
|
||||
@@ -338,6 +344,9 @@ public abstract class MetaDataDetailsPanel extends javax.swing.JPanel {
|
||||
protected SQLConsole getSqlConsole(boolean switchToConsole) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
protected void deselectChildrenIfNeededWithoutReload() {
|
||||
}
|
||||
};
|
||||
|
||||
final MemorizedResultSet[] metaDataDetails = new MemorizedResultSet[1];
|
||||
@@ -357,7 +366,7 @@ public abstract class MetaDataDetailsPanel extends javax.swing.JPanel {
|
||||
rs.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
logger.info("error", e);
|
||||
// ignore
|
||||
}
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -17,7 +17,6 @@ package net.sf.jailer.ui.databrowser.metadata;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Font;
|
||||
@@ -699,7 +698,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
popup.add(menu);
|
||||
++itemCount;
|
||||
menu.add(createScriptMenuItem("Delete Script", "Delete from %1$s;", "", mdTables, false));
|
||||
menu.add(createScriptMenuItem("Drop Table Script", "Drop Table %1$s;", "", mdTables, false));
|
||||
menu.add(createScriptMenuItem("Drop Table Script", "Drop %2$s %1$s;", "", mdTables, false));
|
||||
menu.addSeparator();
|
||||
menu.add(createScriptMenuItem("Count Rows Script", "Select '%1$s' as Tab, count(*) as NumberOfRows From %1$s", " union all", mdTables, true));
|
||||
}
|
||||
@@ -709,7 +708,9 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
if (evt.getButton() == MouseEvent.BUTTON1) {
|
||||
if (mdTable != null) {
|
||||
if (evt.getClickCount() > 1) {
|
||||
openTable(mdTable);
|
||||
if (node != null && metaDataTree.getSelectionModel().isPathSelected(node)) {
|
||||
openTable(mdTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -725,12 +726,19 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
script.append(separator + "\n");
|
||||
}
|
||||
String tableName;
|
||||
String tableType = "Table";
|
||||
if (mdTable.isView()) {
|
||||
tableType = "View";
|
||||
}
|
||||
if (mdTable.isSynonym()) {
|
||||
tableType = "Synonym";
|
||||
}
|
||||
if (mdTable.getSchema().isDefaultSchema) {
|
||||
tableName = mdTable.getName();
|
||||
} else {
|
||||
tableName = mdTable.getSchema() + "." + mdTable.getName();
|
||||
}
|
||||
script.append(String.format(template, tableName));
|
||||
script.append(String.format(template, tableName, tableType));
|
||||
}
|
||||
script.append("\n");
|
||||
appendScript(script.toString(), execute);
|
||||
@@ -815,6 +823,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
boolean isSynonym = false;
|
||||
Boolean isDirty = false;
|
||||
Icon image = null;
|
||||
Long estRowCount = null;
|
||||
if (value instanceof DefaultMutableTreeNode) {
|
||||
Object uo = ((DefaultMutableTreeNode) value).getUserObject();
|
||||
if (uo instanceof JLabel) {
|
||||
@@ -851,11 +860,11 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ModelBuilder.isJailerTable(((MDTable) uo).getUnquotedName())) {
|
||||
isJailerTable = true;
|
||||
}
|
||||
isView = ((MDTable) uo).isView();
|
||||
isSynonym = ((MDTable) uo).isSynonym();
|
||||
if (!isView) {
|
||||
estRowCount = ((MDTable) uo).estimatedRowCount;
|
||||
}
|
||||
if (isView) {
|
||||
image = viewIcon;
|
||||
} else if (isSynonym) {
|
||||
@@ -863,6 +872,9 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
} else {
|
||||
image = tableIcon;
|
||||
}
|
||||
if (ModelBuilder.isJailerTable(((MDTable) uo).getUnquotedName())) {
|
||||
isJailerTable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Component comp = super.getTreeCellRendererComponent(tree, value + (unknownTable? "" : (isDirty? " !" : " ")), sel, expanded, leaf, row, hasFocus);
|
||||
@@ -874,13 +886,29 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
// TODO tooltips dont work with tree nodes
|
||||
tooltip = text;
|
||||
}
|
||||
if (estRowCount != null) {
|
||||
Color fg = ((JLabel) comp).getForeground();
|
||||
String estRowCountFormatted;
|
||||
if (estRowCount >= 1000000) {
|
||||
estRowCountFormatted = String.format("%1.1f M", (double) estRowCount / 1000000.0);
|
||||
} else if (estRowCount >= 1000) {
|
||||
estRowCountFormatted = String.format("%1.1f K", (double) estRowCount / 1000.0);
|
||||
} else {
|
||||
estRowCountFormatted = estRowCount.toString();
|
||||
}
|
||||
if (fg.getRed() + fg.getGreen() + fg.getBlue() < 255 * 3 / 2) {
|
||||
((JLabel) comp).setText("<html>" + text + " <font color=\"#7777ff\">(~</font><font color=\"#3333ff\">" + estRowCountFormatted + "</font><font color=\"#7777ff\">)</font>");
|
||||
} else {
|
||||
((JLabel) comp).setText("<html>" + text + " <font color=\"#aaaaff\">(~</font><font color=\"#eeeeff\">" + estRowCountFormatted + "</font><font color=\"#aaaaff\">)</font>");
|
||||
}
|
||||
}
|
||||
}
|
||||
Font font = comp.getFont();
|
||||
if (font != null) {
|
||||
Font bold = new Font(font.getName(), unknownTable || isDirty? (font.getStyle() | Font.ITALIC) : (font.getStyle() & ~Font.ITALIC), font.getSize());
|
||||
comp.setFont(bold);
|
||||
}
|
||||
if (isJailerTable) {
|
||||
if (isJailerTable && !sel) {
|
||||
comp.setEnabled(false);
|
||||
}
|
||||
if (image != null) {
|
||||
@@ -941,7 +969,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(MetaDataPanel.this);
|
||||
try {
|
||||
if (metaDataTree.getSelectionPath() != null && metaDataTree.getSelectionPath().getLastPathComponent() == last) {
|
||||
if (uo instanceof MDSchema) {
|
||||
@@ -961,7 +989,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(MetaDataPanel.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1040,7 +1068,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
refreshButton.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(refreshButton);
|
||||
JDBCMetaDataBasedModelElementFinder.resetCaches(metaDataSource.getSession());
|
||||
setOutline(new ArrayList<OutlineInfo>(), -1);
|
||||
proceduresPerSchema.clear();
|
||||
@@ -1071,7 +1099,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
refreshButton.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(refreshButton);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1100,7 +1128,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
if (bounds != null) {
|
||||
int b = 18;
|
||||
bounds = new Rectangle(bounds.x, Math.max(bounds.y - b, 0), bounds.width, bounds.height + 2 * b);
|
||||
metaDataTree.scrollRectToVisible(new Rectangle(bounds.x, bounds.y, 1, bounds.height));
|
||||
metaDataTree.scrollRectToVisible(new Rectangle(0, bounds.y, 1, bounds.height));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1200,12 +1228,7 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
}
|
||||
DefaultTreeModel treeModel = new DefaultTreeModel(root);
|
||||
metaDataTree.setModel(treeModel);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
metaDataTree.scrollRectToVisible(new Rectangle(0, 0, 1, 1));
|
||||
}
|
||||
});
|
||||
metaDataTree.scrollRectToVisible(new Rectangle(0, 0, 1, 1));
|
||||
selectSchema(metaDataSource.getDefaultSchema());
|
||||
}
|
||||
|
||||
@@ -1262,10 +1285,10 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(MetaDataPanel.this);
|
||||
expandImmediatelly();
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
UIUtil.resetWaitCursor(MetaDataPanel.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1290,11 +1313,16 @@ public abstract class MetaDataPanel extends javax.swing.JPanel {
|
||||
if (mdSchema != null) {
|
||||
DefaultMutableTreeNode node = treeNodePerSchema.get(mdSchema);
|
||||
if (node != null) {
|
||||
TreePath path = new TreePath(node.getPath());
|
||||
final TreePath path = new TreePath(node.getPath());
|
||||
metaDataTree.expandPath(path);
|
||||
metaDataTree.getSelectionModel().setSelectionPath(path);
|
||||
if (scrollToNode) {
|
||||
scrollToNode(path);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
scrollToNode(path);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import net.sf.jailer.database.Session;
|
||||
import net.sf.jailer.datamodel.Association;
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
import net.sf.jailer.modelbuilder.MemorizedResultSet;
|
||||
import net.sf.jailer.ui.DbConnectionDialog;
|
||||
import net.sf.jailer.ui.QueryBuilderDialog;
|
||||
import net.sf.jailer.ui.QueryBuilderDialog.Relationship;
|
||||
@@ -59,13 +60,23 @@ public class ResultSetRenderer extends javax.swing.JPanel {
|
||||
*/
|
||||
public ResultSetRenderer(ResultSet resultSet, String titel, DataModel datamodel, Session session, ExecutionContext executionContext) throws SQLException {
|
||||
initComponents();
|
||||
titelLabel.setText(titel);
|
||||
if (titel != null && titel.length() > 40) {
|
||||
titelLabel.setText(titel.substring(0, 40) + "...");
|
||||
titelLabel.setToolTipText(titel);
|
||||
} else {
|
||||
titelLabel.setText(titel);
|
||||
titelLabel.setToolTipText(null);
|
||||
}
|
||||
|
||||
final BrowserContentPane rb = new ResultContentPane(datamodel, null, "", session, null, null,
|
||||
null, null, new RowsClosure(), Integer.MAX_VALUE, false, false,
|
||||
resultSet.getMetaData().getColumnCount() > 1? 180 : 400,
|
||||
executionContext);
|
||||
rb.setTableFilterEnabled(false);
|
||||
if (resultSet instanceof MemorizedResultSet && ((MemorizedResultSet) resultSet).getSize() > 1) {
|
||||
rb.setTableFilterEnabled(true);
|
||||
} else {
|
||||
rb.setTableFilterEnabled(false);
|
||||
}
|
||||
LoadJob loadJob = rb.newLoadJob(resultSet, Integer.MAX_VALUE);
|
||||
loadJob.run();
|
||||
JComponent rTabContainer = rb.getRowsTableContainer();
|
||||
@@ -122,16 +133,25 @@ public class ResultSetRenderer extends javax.swing.JPanel {
|
||||
private javax.swing.JLabel titelLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
class ResultContentPane extends BrowserContentPane {
|
||||
public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, Row parentRow,
|
||||
private final Integer limit;
|
||||
public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, Row parentRow,
|
||||
List<Row> parentRows, Association association, Frame parentFrame,
|
||||
RowsClosure rowsClosure, Integer limit, Boolean selectDistinct,
|
||||
boolean reload, int maxColumnWidth, ExecutionContext executionContext) {
|
||||
super(dataModel, table, condition, session, parentRow, parentRows, association, parentFrame,
|
||||
rowsClosure, limit, selectDistinct, reload, executionContext);
|
||||
rowsClosure, selectDistinct, reload, executionContext);
|
||||
singleRowDetailsViewTitel = "Details";
|
||||
this.maxColumnWidth = maxColumnWidth;
|
||||
this.limit = limit;
|
||||
rowsTableScrollPane.setWheelScrollingEnabled(true);
|
||||
rowsCount.setVisible(false);
|
||||
}
|
||||
@Override
|
||||
protected int getReloadLimit() {
|
||||
if (limit == null) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
@Override
|
||||
protected void unhide() {
|
||||
@@ -159,7 +179,8 @@ public class ResultSetRenderer extends javax.swing.JPanel {
|
||||
protected void onContentChange(List<Row> rows, boolean reloadChildren) {
|
||||
}
|
||||
@Override
|
||||
protected void navigateTo(Association association, int rowIndex, Row row) {
|
||||
protected RowBrowser navigateTo(Association association, int rowIndex, Row row) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
protected List<RowBrowser> getTableBrowser() {
|
||||
@@ -240,6 +261,9 @@ public class ResultSetRenderer extends javax.swing.JPanel {
|
||||
protected SQLConsole getSqlConsole(boolean switchToConsole) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
protected void deselectChildrenIfNeededWithoutReload() {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+18
-6
@@ -47,11 +47,13 @@ import net.sf.jsqlparser.expression.TimeKeyExpression;
|
||||
import net.sf.jsqlparser.expression.TimeValue;
|
||||
import net.sf.jsqlparser.expression.TimestampValue;
|
||||
import net.sf.jsqlparser.expression.UserVariable;
|
||||
import net.sf.jsqlparser.expression.ValueListExpression;
|
||||
import net.sf.jsqlparser.expression.WhenClause;
|
||||
import net.sf.jsqlparser.expression.WithinGroupExpression;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
|
||||
@@ -305,11 +307,6 @@ class AbstractExpressionVisitor implements ExpressionVisitor {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WithinGroupExpression arg0) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ExtractExpression arg0) {
|
||||
|
||||
@@ -389,4 +386,19 @@ class AbstractExpressionVisitor implements ExpressionVisitor {
|
||||
public void visit(NotExpression arg0) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BitwiseRightShift arg0) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BitwiseLeftShift arg0) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ValueListExpression arg0) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package net.sf.jailer.ui.databrowser.sqlconsole;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
@@ -38,14 +39,18 @@ import javax.swing.JTable;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.RowSorter;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import javax.swing.table.TableModel;
|
||||
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
import net.sf.jailer.ui.databrowser.BrowserContentPane;
|
||||
import net.sf.jailer.ui.databrowser.Row;
|
||||
|
||||
/**
|
||||
* "Column view" of a query result table.
|
||||
@@ -56,10 +61,13 @@ public class ColumnsTable extends JTable {
|
||||
|
||||
private final int MAX_ROWS = 198;
|
||||
private static final KeyStroke KS_COPY_TO_CLIPBOARD = KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK);
|
||||
final BrowserContentPane rb;
|
||||
|
||||
public ColumnsTable(final BrowserContentPane rb) {
|
||||
this.rb = rb;
|
||||
final JTable rowsTable = rb.rowsTable;
|
||||
|
||||
public ColumnsTable(final JTable rowsTable) {
|
||||
TableModel rDm = rowsTable.getModel();
|
||||
RowSorter<? extends TableModel> sorter = rowsTable.getRowSorter();
|
||||
final RowSorter<? extends TableModel> sorter = rowsTable.getRowSorter();
|
||||
Vector cNames = new Vector();
|
||||
cNames.add("Column");
|
||||
for (int i = 0; i < sorter.getViewRowCount(); ++i) {
|
||||
@@ -69,31 +77,57 @@ public class ColumnsTable extends JTable {
|
||||
}
|
||||
cNames.add("Row " + (i + 1));
|
||||
}
|
||||
DefaultTableModel cDm = new DefaultTableModel(cNames, rDm.getColumnCount()) {
|
||||
final TableColumnModel cm = rowsTable.getColumnModel();
|
||||
TableModel cDm = new DefaultTableModel(cNames, rowsTable.getModel().getColumnCount()) {
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
return false;
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
if (columnIndex == 0) {
|
||||
return false;
|
||||
}
|
||||
int row = rowsTable.getRowSorter().convertRowIndexToModel(columnIndex - 1);
|
||||
int column = cm.getColumn(rowIndex).getModelIndex();
|
||||
return rowsTable.getModel().isCellEditable(row, column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
int column = cm.getColumn(rowIndex).getModelIndex();
|
||||
if (columnIndex == 0) {
|
||||
return rowsTable.getModel().getColumnName(column);
|
||||
}
|
||||
int row = rowsTable.getRowSorter().convertRowIndexToModel(columnIndex - 1);
|
||||
return rowsTable.getModel().getValueAt(row, column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object value, int rowIndex, int columnIndex) {
|
||||
if (columnIndex == 0) {
|
||||
return;
|
||||
}
|
||||
int row = rowsTable.getRowSorter().convertRowIndexToModel(columnIndex - 1);
|
||||
int column = cm.getColumn(rowIndex).getModelIndex();
|
||||
rowsTable.getModel().setValueAt(value, row, column);
|
||||
}
|
||||
};
|
||||
TableColumnModel cm = rowsTable.getColumnModel();
|
||||
for (int x = 0; x < rDm.getColumnCount(); ++x) {
|
||||
int mx = cm.getColumn(x).getModelIndex();
|
||||
cDm.setValueAt(rDm.getColumnName(mx), x, 0);
|
||||
for (int y = 0; y < sorter.getViewRowCount(); ++y) {
|
||||
cDm.setValueAt(rDm.getValueAt(sorter.convertRowIndexToModel(y), mx), x, y + 1);
|
||||
if (y > MAX_ROWS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
setRowSelectionAllowed(true);
|
||||
setColumnSelectionAllowed(true);
|
||||
setCellSelectionEnabled(true);
|
||||
// getTableHeader().setReorderingAllowed(false);
|
||||
setShowGrid(false);
|
||||
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||
setModel(cDm);
|
||||
|
||||
for (int i = 0; i < getColumnCount(); i++) {
|
||||
TableCellEditor defaultEditor = rowsTable.getDefaultEditor(getColumnClass(i));
|
||||
if (defaultEditor != null) {
|
||||
defaultEditor.cancelCellEditing();
|
||||
}
|
||||
setDefaultEditor(getColumnClass(i), defaultEditor);
|
||||
}
|
||||
|
||||
InputMap im = getInputMap();
|
||||
Object key = "copyClipboard";
|
||||
im.put(KS_COPY_TO_CLIPBOARD, key);
|
||||
@@ -115,14 +149,23 @@ public class ColumnsTable extends JTable {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
int ri = rowAtPoint(e.getPoint());
|
||||
if (ri >= 0) {
|
||||
Rectangle r = getCellRect(ri, 0, false);
|
||||
int x = Math.max(e.getPoint().x, (int) r.getMinX());
|
||||
int y = (int) r.getMaxY() - 2;
|
||||
if (e.getButton() != MouseEvent.BUTTON1) {
|
||||
JPopupMenu popup;
|
||||
popup = createPopupMenu();
|
||||
if (popup != null) {
|
||||
popup.show(ColumnsTable.this, x, y);
|
||||
Rectangle r = getCellRect(ri, 0, false);
|
||||
int x = Math.max(e.getPoint().x, (int) r.getMinX());
|
||||
int y = (int) r.getMaxY() - 2;
|
||||
if (e.getButton() != MouseEvent.BUTTON1) {
|
||||
JPopupMenu popup;
|
||||
popup = createPopupMenu(e);
|
||||
if (popup != null) {
|
||||
popup.show(ColumnsTable.this, x, y);
|
||||
}
|
||||
} else if (e.getClickCount() > 1) {
|
||||
int i = -1;
|
||||
ri = columnAtPoint(e.getPoint()) - 1;
|
||||
if (ri >= 0 && !rb.rows.isEmpty() && rb.rowsTable.getRowSorter().getViewRowCount() > 0) {
|
||||
i = rb.rowsTable.getRowSorter().convertRowIndexToModel(ri);
|
||||
Point p = new Point(e.getX(), e.getY());
|
||||
SwingUtilities.convertPointToScreen(p, ColumnsTable.this);
|
||||
rb.openDetailsView(i, (int) p.getX(), (int) p.getY());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,8 +201,6 @@ public class ColumnsTable extends JTable {
|
||||
if (column == 0) {
|
||||
((JLabel) render).setFont(italic);
|
||||
((JLabel) render).setBackground(BGCOLUMNS);
|
||||
// } else if (isSelected) {
|
||||
// ((JLabel) render).setBackground(BGSELECTED);
|
||||
}
|
||||
}
|
||||
return render;
|
||||
@@ -170,10 +211,20 @@ public class ColumnsTable extends JTable {
|
||||
|
||||
/**
|
||||
* Creates popup menu.
|
||||
* @param e mouse event
|
||||
*/
|
||||
public JPopupMenu createPopupMenu() {
|
||||
private JPopupMenu createPopupMenu(MouseEvent e) {
|
||||
int i = -1;
|
||||
Row row = null;
|
||||
int ri = columnAtPoint(e.getPoint()) - 1;
|
||||
if (ri >= 0 && !rb.rows.isEmpty() && rb.rowsTable.getRowSorter().getViewRowCount() > 0) {
|
||||
i = rb.rowsTable.getRowSorter().convertRowIndexToModel(ri);
|
||||
row = rb.rows.get(i);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
JMenuItem copyTCB = new JMenuItem("Copy to Clipboard");
|
||||
copyTCB.setAccelerator(KS_COPY_TO_CLIPBOARD);
|
||||
// copyTCB.setAccelerator(KS_COPY_TO_CLIPBOARD);
|
||||
copyTCB.setEnabled(getSelectedColumnCount() > 0);
|
||||
copyTCB.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
@@ -181,10 +232,20 @@ public class ColumnsTable extends JTable {
|
||||
UIUtil.copyToClipboard(ColumnsTable.this, false);
|
||||
}
|
||||
});
|
||||
|
||||
JPopupMenu popup = new JPopupMenu();
|
||||
popup.add(copyTCB);
|
||||
return popup;
|
||||
Point p = new Point(e.getX(), e.getY());
|
||||
SwingUtilities.convertPointToScreen(p, this);
|
||||
return rb.createPopupMenu(row, i, (int) p.getX(), (int) p.getY(), false, copyTCB, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
repaint();
|
||||
for (int i = 0; i < getColumnCount(); i++) {
|
||||
TableCellEditor defaultEditor = getDefaultEditor(getColumnClass(i));
|
||||
if (defaultEditor != null) {
|
||||
defaultEditor.cancelCellEditing();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
private void adjustTableColumnsWidth() {
|
||||
|
||||
@@ -67,11 +67,13 @@ import net.sf.jsqlparser.expression.TimeKeyExpression;
|
||||
import net.sf.jsqlparser.expression.TimeValue;
|
||||
import net.sf.jsqlparser.expression.TimestampValue;
|
||||
import net.sf.jsqlparser.expression.UserVariable;
|
||||
import net.sf.jsqlparser.expression.ValueListExpression;
|
||||
import net.sf.jsqlparser.expression.WhenClause;
|
||||
import net.sf.jsqlparser.expression.WithinGroupExpression;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
|
||||
@@ -102,6 +104,7 @@ import net.sf.jsqlparser.statement.SetStatement;
|
||||
import net.sf.jsqlparser.statement.Statement;
|
||||
import net.sf.jsqlparser.statement.StatementVisitor;
|
||||
import net.sf.jsqlparser.statement.Statements;
|
||||
import net.sf.jsqlparser.statement.UseStatement;
|
||||
import net.sf.jsqlparser.statement.alter.Alter;
|
||||
import net.sf.jsqlparser.statement.create.index.CreateIndex;
|
||||
import net.sf.jsqlparser.statement.create.table.CreateTable;
|
||||
@@ -118,6 +121,7 @@ import net.sf.jsqlparser.statement.select.AllTableColumns;
|
||||
import net.sf.jsqlparser.statement.select.FromItemVisitor;
|
||||
import net.sf.jsqlparser.statement.select.Join;
|
||||
import net.sf.jsqlparser.statement.select.LateralSubSelect;
|
||||
import net.sf.jsqlparser.statement.select.ParenthesisFromItem;
|
||||
import net.sf.jsqlparser.statement.select.PlainSelect;
|
||||
import net.sf.jsqlparser.statement.select.Select;
|
||||
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
|
||||
@@ -310,9 +314,9 @@ public class QueryTypeAnalyser {
|
||||
|
||||
@Override
|
||||
public void visit(PlainSelect plainSelect) {
|
||||
ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(result);
|
||||
final ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(result);
|
||||
if (plainSelect.getFromItem() != null) {
|
||||
FromItemVisitor fromItemVisitor = new FromItemVisitor() {
|
||||
final FromItemVisitor fromItemVisitor = new FromItemVisitor() {
|
||||
private void unknownTable() {
|
||||
result.put("-unknown-" + (unknownTableCounter++), null);
|
||||
}
|
||||
@@ -333,7 +337,18 @@ public class QueryTypeAnalyser {
|
||||
|
||||
@Override
|
||||
public void visit(SubJoin subjoin) {
|
||||
unknownTable();
|
||||
subjoin.getLeft().accept(this);
|
||||
if (subjoin.getJoinList() != null) {
|
||||
for (Join join: subjoin.getJoinList()) {
|
||||
join.getRightItem().accept(this);
|
||||
}
|
||||
for (Join join: subjoin.getJoinList()) {
|
||||
expressionAnalyzer.setOuterJoinExpression(join.isOuter() || join.isLeft() || join.isRight());
|
||||
if (join.getOnExpression() != null) {
|
||||
join.getOnExpression().accept(expressionAnalyzer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -364,6 +379,12 @@ public class QueryTypeAnalyser {
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void visit(ParenthesisFromItem parenthesisFromItem) {
|
||||
if (parenthesisFromItem.getFromItem() != null) {
|
||||
parenthesisFromItem.getFromItem().accept(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
plainSelect.getFromItem().accept(fromItemVisitor);
|
||||
if (plainSelect.getJoins() != null) {
|
||||
@@ -424,7 +445,13 @@ public class QueryTypeAnalyser {
|
||||
pkColumns.add(new net.sf.jailer.datamodel.Column(pk, "", 0, -1));
|
||||
}
|
||||
PrimaryKey primaryKey = new PrimaryKeyFactory().createPrimaryKey(pkColumns);
|
||||
Table table = new Table((schemaName == null? "" : schemaName + ".") + tableName, primaryKey, false, false);
|
||||
Table toTable = theTable.getMetaDataSource().toTable(theTable);
|
||||
Table table;
|
||||
if (toTable != null) {
|
||||
table = new Table(toTable.getName(), primaryKey, false, false);
|
||||
} else {
|
||||
table = new Table((schemaName == null? "" : schemaName + ".") + tableName, primaryKey, false, false);
|
||||
}
|
||||
List<net.sf.jailer.datamodel.Column> columns = new ArrayList<net.sf.jailer.datamodel.Column>();
|
||||
for (String pk: columnNames) {
|
||||
columns.add(new net.sf.jailer.datamodel.Column(pk, "", 0, -1));
|
||||
@@ -556,11 +583,6 @@ public class QueryTypeAnalyser {
|
||||
noSubexpression[0] = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WithinGroupExpression wgexpr) {
|
||||
noSubexpression[0] = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AnalyticExpression aexpr) {
|
||||
noSubexpression[0] = false;
|
||||
@@ -775,6 +797,21 @@ public class QueryTypeAnalyser {
|
||||
public void visit(NullValue nullValue) {
|
||||
noSubexpression[0] = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BitwiseRightShift aThis) {
|
||||
noSubexpression[0] = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BitwiseLeftShift aThis) {
|
||||
noSubexpression[0] = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ValueListExpression valueList) {
|
||||
noSubexpression[0] = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -869,6 +906,11 @@ public class QueryTypeAnalyser {
|
||||
public void visit(Upsert upsert) {
|
||||
throw new QueryTooComplexException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UseStatement use) {
|
||||
throw new QueryTooComplexException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.awt.Font;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
@@ -160,6 +161,8 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
private JMenuItem menuItemToggle;
|
||||
private JMenuItem menuItemSubstituteVariables;
|
||||
private JMenuItem menuItemAnalyse;
|
||||
private int initialTabbedPaneSelection = 0;
|
||||
private int initialTabbedPaneSelectionLoc = -1;
|
||||
|
||||
private final String IGNORED_STATEMENTS = "(\\s*/\\s*)";
|
||||
|
||||
@@ -676,7 +679,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
* @param statementStartOffset
|
||||
* @param explain
|
||||
*/
|
||||
private void executeSQL(final String sql, Status status, int statementStartOffset, final boolean explain) {
|
||||
private void executeSQL(final String sql, final Status status, int statementStartOffset, final boolean explain) {
|
||||
Statement statement = null;
|
||||
ResultSet resultSet = null;
|
||||
final Status localStatus = new Status();
|
||||
@@ -688,6 +691,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
localStatus.numStatements++;
|
||||
status.updateView(false);
|
||||
statement = session.getConnection().createStatement();
|
||||
// SqlUtil.limitFetchSize(statement, session);
|
||||
CancellationHandler.begin(statement, SQLConsole.this);
|
||||
long startTime = System.currentTimeMillis();
|
||||
sqlStatement =
|
||||
@@ -723,7 +727,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
hasUpdateCount = false;
|
||||
hasResultSet = false;
|
||||
} else {
|
||||
hasResultSet = statement.execute(sqlStatement);
|
||||
hasResultSet = executeStatementWithLimit(statement, sqlStatement, session);
|
||||
}
|
||||
}
|
||||
if (hasResultSet) {
|
||||
@@ -733,15 +737,15 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
for (int i = 0; i < metaData.getColumnCount(); ++i) {
|
||||
columnLabels[i] = metaData.getColumnLabel(i + 1);
|
||||
}
|
||||
ResultSetRenderer theMetaDataRenderer = null;
|
||||
ResultSet theMetaDataResultSet = null;
|
||||
String resultSetType = null;
|
||||
try {
|
||||
resultSetType = TabContentPanel.toType(metaData, session, executionContext);
|
||||
theMetaDataRenderer = new ResultSetRenderer(TabContentPanel.toMetaDataResultSet(metaData, session, executionContext), null, datamodel.get(), session, executionContext);
|
||||
theMetaDataResultSet = TabContentPanel.toMetaDataResultSet(metaData, session, executionContext);
|
||||
} catch (Throwable e1) {
|
||||
logger.info("error", e1);
|
||||
}
|
||||
final ResultSetRenderer metaDataRenderer = theMetaDataRenderer;
|
||||
final ResultSet metaDataResultSet = theMetaDataResultSet;
|
||||
final String finalResultSetType = resultSetType;
|
||||
final Integer limit = (Integer) limitComboBox.getSelectedItem();
|
||||
final List<Table> resultTypes = explain || sqlPlusResultSet != null? null : QueryTypeAnalyser.getType(sqlStatement, metaDataSource);
|
||||
@@ -803,7 +807,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
@Override
|
||||
public void run() {
|
||||
final BrowserContentPane rb = new ResultContentPane(datamodel.get(), finalResultType, "", session, null, null,
|
||||
null, null, new RowsClosure(), limit, false, false, executionContext);
|
||||
null, null, new RowsClosure(), false, false, executionContext);
|
||||
if (resultTypes != null && resultTypes.size() > 1) {
|
||||
rb.setResultSetType(resultTypes);
|
||||
}
|
||||
@@ -815,6 +819,12 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
loadJob.run();
|
||||
JComponent rTabContainer = rb.getRowsTableContainer();
|
||||
metaDataDetails.reset();
|
||||
JComponent metaDataRenderer = null;
|
||||
try {
|
||||
metaDataRenderer = new ResultSetRenderer(metaDataResultSet, null, datamodel.get(), session, executionContext);
|
||||
} catch (Throwable e1) {
|
||||
logger.info("error", e1);
|
||||
}
|
||||
final TabContentPanel tabContentPanel =
|
||||
new TabContentPanel(rb.rowsCount,
|
||||
metaDataRenderer,
|
||||
@@ -857,9 +867,17 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
rTabContainer = tabContentPanel;
|
||||
final int MAXLENGTH = 30;
|
||||
String title = shortSQL(sqlE, MAXLENGTH);
|
||||
final int loc = status != null && status.location != null? status.location.a : -1;
|
||||
if (initialTabbedPaneSelection >= 0 && initialTabbedPaneSelectionLoc == loc) {
|
||||
if (initialTabbedPaneSelection < tabContentPanel.tabbedPane.getTabCount()) {
|
||||
tabContentPanel.tabbedPane.setSelectedIndex(initialTabbedPaneSelection);
|
||||
}
|
||||
}
|
||||
tabContentPanel.tabbedPane.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
initialTabbedPaneSelection = tabContentPanel.tabbedPane.getSelectedIndex();
|
||||
initialTabbedPaneSelectionLoc = loc;
|
||||
updateColumnsAndTextView(rb, tabContentPanel);
|
||||
}
|
||||
});
|
||||
@@ -886,12 +904,28 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
}
|
||||
List<? extends SortKey> skeys = sorter.getSortKeys();
|
||||
if (!skeys.isEmpty()) {
|
||||
tableSortAndFilterState = tableSortAndFilterState + (tableSortAndFilterState.isEmpty()? "Sorted" : " and sorted")
|
||||
+ " by \"" + rb.rowsTable.getColumnName(skeys.get(0).getColumn()) + "\"";
|
||||
for (int i = 0; i < rb.rowsTable.getColumnCount(); ++i) {
|
||||
if (rb.rowsTable.getColumnModel().getColumn(i).getModelIndex() == skeys.get(0).getColumn()) {
|
||||
tableSortAndFilterState = tableSortAndFilterState + (tableSortAndFilterState.isEmpty()? "Sorted" : " and sorted")
|
||||
+ " by \"" + rb.rowsTable.getColumnName(i) + "\"";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel) {
|
||||
columnsTable = new ColumnsTable(rb.rowsTable);
|
||||
if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel || tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.contentPanel) {
|
||||
Point vp = null;
|
||||
if (columnsTable != null) {
|
||||
if (tabContentPanel.columnsScrollPane.getViewport() != null) {
|
||||
vp = tabContentPanel.columnsScrollPane.getViewport().getViewPosition();
|
||||
}
|
||||
}
|
||||
columnsTable = new ColumnsTable(rb);
|
||||
tabContentPanel.columnsScrollPane.setViewportView(columnsTable);
|
||||
if (vp != null) {
|
||||
if (tabContentPanel.columnsScrollPane.getViewport() != null) {
|
||||
tabContentPanel.columnsScrollPane.getViewport().setViewPosition(vp);
|
||||
}
|
||||
}
|
||||
tabContentPanel.columnsSortedStateLabel.setText(" " + tableSortAndFilterState);
|
||||
tabContentPanel.columnsSortedStateLabel.setVisible(!tableSortAndFilterState.isEmpty());
|
||||
}
|
||||
@@ -989,6 +1023,17 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean executeStatementWithLimit(Statement statement, String sqlStatement, Session session) throws SQLException {
|
||||
if (DBMS.MySQL.equals(session.dbms)) {
|
||||
try {
|
||||
return statement.execute("(" + sqlStatement + "\n) limit " + (1 + (Integer) limitComboBox.getSelectedItem()));
|
||||
} catch (Throwable e) {
|
||||
return statement.execute(sqlStatement);
|
||||
}
|
||||
}
|
||||
return statement.execute(sqlStatement);
|
||||
}
|
||||
|
||||
public void setCaretPosition(int position) {
|
||||
if (editorPane.getDocument().getLength() >= position) {
|
||||
try {
|
||||
@@ -1005,6 +1050,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
}
|
||||
|
||||
private void updateOutline(String sql, int startPosition) {
|
||||
sql = sql.replaceFirst(";\\s*$", "");
|
||||
final int MAX_CONTEXT_LENGTH = 80;
|
||||
final int MAX_TOOLTIP_LENGTH = 100;
|
||||
List<OutlineInfo> outlineInfos = new ArrayList<OutlineInfo>();
|
||||
@@ -1536,6 +1582,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
statusLabel.setText("Canceling...");
|
||||
statusLabel.setForeground(Color.RED);
|
||||
CancellationHandler.cancel(this);
|
||||
cancelButton.setEnabled(false);
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
@@ -1561,10 +1608,10 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
class ResultContentPane extends BrowserContentPane {
|
||||
public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, Row parentRow,
|
||||
List<Row> parentRows, Association association, Frame parentFrame,
|
||||
RowsClosure rowsClosure, Integer limit, Boolean selectDistinct,
|
||||
RowsClosure rowsClosure, Boolean selectDistinct,
|
||||
boolean reload, ExecutionContext executionContext) {
|
||||
super(dataModel, table, condition, session, parentRow, parentRows, association, parentFrame,
|
||||
rowsClosure, limit, selectDistinct, reload, executionContext);
|
||||
rowsClosure, selectDistinct, reload, executionContext);
|
||||
noSingleRowDetailsView = true;
|
||||
rowsTableScrollPane.setWheelScrollingEnabled(true);
|
||||
}
|
||||
@@ -1598,7 +1645,8 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
protected void onContentChange(List<Row> rows, boolean reloadChildren) {
|
||||
}
|
||||
@Override
|
||||
protected void navigateTo(Association association, int rowIndex, Row row) {
|
||||
protected RowBrowser navigateTo(Association association, int rowIndex, Row row) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
protected List<RowBrowser> getTableBrowser() {
|
||||
@@ -1680,6 +1728,9 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
protected SQLConsole getSqlConsole(boolean switchToConsole) {
|
||||
return SQLConsole.this;
|
||||
}
|
||||
@Override
|
||||
protected void deselectChildrenIfNeededWithoutReload() {
|
||||
}
|
||||
};
|
||||
|
||||
private class TitelPanel extends JPanel {
|
||||
@@ -2007,6 +2058,15 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
public boolean isEmpty() {
|
||||
return editorPane.getDocument().getLength() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the row limit.
|
||||
*
|
||||
* @param limit the row limit
|
||||
*/
|
||||
public void setRowLimit(Integer limit) {
|
||||
limitComboBox.setSelectedItem(limit);
|
||||
}
|
||||
|
||||
private int initialContentSize;
|
||||
private int initialContentHash;
|
||||
@@ -2123,4 +2183,5 @@ public abstract class SQLConsole extends javax.swing.JPanel {
|
||||
logger.info("error", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.sf.jailer.ui.graphical_view;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
@@ -16,6 +15,7 @@ import java.util.HashSet;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFileChooser;
|
||||
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
import prefuse.Display;
|
||||
import prefuse.Visualization;
|
||||
import prefuse.util.GraphicsLib;
|
||||
@@ -113,7 +113,7 @@ public class DisplayExporter {
|
||||
String m_group = Visualization.ALL_ITEMS;
|
||||
|
||||
try {
|
||||
display.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
UIUtil.setWaitCursor(display);
|
||||
|
||||
// Now comes the nice part
|
||||
|
||||
@@ -165,7 +165,7 @@ public class DisplayExporter {
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
display.setCursor(Cursor.getDefaultCursor());
|
||||
UIUtil.resetWaitCursor(display);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public class GraphicalDataModelView extends JPanel {
|
||||
/**
|
||||
* Maximum number of tables to make visible during expansion ("expand single table").
|
||||
*/
|
||||
public static final int EXPAND_SINGLE_TABLE_LIMIT = 10;
|
||||
public static final int EXPAND_SINGLE_TABLE_LIMIT = 4;
|
||||
|
||||
/**
|
||||
* The selected association.
|
||||
@@ -362,7 +362,7 @@ public class GraphicalDataModelView extends JPanel {
|
||||
popup.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
if (table != null) {
|
||||
JPopupMenu popup = createPopupMenu(table, true);
|
||||
JPopupMenu popup = createPopupMenu(table, null, true);
|
||||
popup.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
@@ -693,9 +693,10 @@ public class GraphicalDataModelView extends JPanel {
|
||||
* Creates popup menu.
|
||||
*
|
||||
* @param table the table for which the menu pops up
|
||||
* @param findPathMenuItem additional menu item
|
||||
* @return the popup menu
|
||||
*/
|
||||
public JPopupMenu createPopupMenu(final Table table, boolean withNavigation) {
|
||||
public JPopupMenu createPopupMenu(final Table table, JMenuItem findPathMenuItem, boolean withNavigation) {
|
||||
JPopupMenu popup = new JScrollPopupMenu();
|
||||
boolean withModifications = modelEditor.getAdditionalPopupMenuItems().isEmpty();
|
||||
|
||||
@@ -771,7 +772,7 @@ public class GraphicalDataModelView extends JPanel {
|
||||
// modelEditor.select(table);
|
||||
// }
|
||||
// });
|
||||
JMenuItem selectAsRoot = new JMenuItem("Focus " + table.getName());
|
||||
JMenuItem selectAsRoot = new JMenuItem("Focus on " + table.getName());
|
||||
selectAsRoot.addActionListener(new ActionListener () {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -892,6 +893,9 @@ public class GraphicalDataModelView extends JPanel {
|
||||
if (navigateTo != null) {
|
||||
popup.add(navigateTo);
|
||||
}
|
||||
if (findPathMenuItem != null) {
|
||||
popup.add(findPathMenuItem);
|
||||
}
|
||||
if (withModifications){
|
||||
popup.add(dataBrowser);
|
||||
}
|
||||
@@ -1360,10 +1364,12 @@ public class GraphicalDataModelView extends JPanel {
|
||||
* Creates visible node for given table.
|
||||
*/
|
||||
public void showTable(Table source, Table destination) {
|
||||
List<Table> toCheck = new ArrayList<Table>();
|
||||
toCheck.add(destination);
|
||||
addEdges(theGraph, source, null, toCheck, false, new HashSet<Table>(toCheck));
|
||||
checkForExpansion(theGraph, model.getTables(), true);
|
||||
synchronized (visualization) {
|
||||
List<Table> toCheck = new ArrayList<Table>();
|
||||
toCheck.add(destination);
|
||||
addEdges(theGraph, source, null, toCheck, false, new HashSet<Table>(toCheck));
|
||||
checkForExpansion(theGraph, model.getTables(), true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2007 - 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package net.sf.jailer.ui.pathfinder;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Item in the path-history of {@link PathFinderView}.
|
||||
*
|
||||
* @author Ralf Wisser
|
||||
*/
|
||||
public class HistoryItem implements Serializable {
|
||||
private static final long serialVersionUID = -2228012653415732355L;
|
||||
|
||||
public String source;
|
||||
public String destination;
|
||||
public boolean implicit = false;
|
||||
|
||||
public List<String> pathStations;
|
||||
public List<String> path;
|
||||
public Set<String> excludedTables;
|
||||
|
||||
public boolean isValid() {
|
||||
return path != null && pathStations != null && excludedTables != null && source != null && destination != null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="jPanel2">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="History"/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTable" name="historyTable">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
||||
<Table columnCount="4" rowCount="4">
|
||||
<Column editable="true" title="Title 1" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Title 2" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Title 3" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Title 4" type="java.lang.Object"/>
|
||||
</Table>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value=" "/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package net.sf.jailer.ui.pathfinder;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
|
||||
/**
|
||||
* Path History Panel.
|
||||
*
|
||||
* @author Ralf Wisser
|
||||
*/
|
||||
public abstract class HistoryPanel extends javax.swing.JPanel {
|
||||
private static final long serialVersionUID = -482021751302785536L;
|
||||
|
||||
private final DataModel dataModel;
|
||||
private final Table source;
|
||||
|
||||
/**
|
||||
* Creates new form HistoryPanel
|
||||
*/
|
||||
public HistoryPanel(Table source, DataModel dataModel) {
|
||||
this.dataModel = dataModel;
|
||||
this.source = source;
|
||||
initComponents();
|
||||
if (source == null) {
|
||||
setVisible(false);
|
||||
} else {
|
||||
initTable();
|
||||
}
|
||||
}
|
||||
|
||||
private void initTable() {
|
||||
final TableCellRenderer defaultTableCellRenderer = historyTable.getDefaultRenderer(String.class);
|
||||
TableCellRenderer renderer = new TableCellRenderer() {
|
||||
final Color BG1 = new Color(255, 255, 255);
|
||||
final Color BG2 = new Color(242, 255, 242);
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
Component render = defaultTableCellRenderer.getTableCellRendererComponent(table, value, isSelected, false, row, column);
|
||||
if (!isSelected) {
|
||||
render.setBackground((row % 2 == 0) ? BG1 : BG2);
|
||||
}
|
||||
if (render instanceof JLabel) {
|
||||
((JLabel) render).setToolTipText(UIUtil.toHTML(String.valueOf(value), 200));
|
||||
}
|
||||
return render;
|
||||
}
|
||||
};
|
||||
historyTable.getColumnModel().getColumn(0).setCellRenderer(renderer);
|
||||
historyTable.setDefaultRenderer(Object.class, renderer);
|
||||
historyTable.setAutoCreateRowSorter(true);
|
||||
historyTable.setRowSelectionAllowed(true);
|
||||
historyTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
historyTable.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent arg0) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int sr = historyTable.getSelectedRow();
|
||||
if (sr >= 0) {
|
||||
close();
|
||||
apply(source, dests.get(historyTable.getRowSorter().convertRowIndexToModel(sr)));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
historyTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
}
|
||||
});
|
||||
|
||||
DefaultTableModel tableModel = new DefaultTableModel(new String[] { "Destination" }, 0) {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
return column == 0;
|
||||
}
|
||||
};
|
||||
dests = PathFinderView.getHistoricDestinations(source, dataModel);
|
||||
|
||||
for (Table table: dests) {
|
||||
tableModel.addRow(new Object[] { dataModel.getDisplayName(table) });
|
||||
}
|
||||
|
||||
historyTable.setModel(tableModel);
|
||||
|
||||
adjustTableColumnsWidth(historyTable);
|
||||
}
|
||||
|
||||
private List<Table> dests;
|
||||
|
||||
public void adjustTableColumnsWidth(JTable table) {
|
||||
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
|
||||
DefaultTableCellRenderer defaultTableCellRenderer = new DefaultTableCellRenderer();
|
||||
for (int i = 0; i < table.getColumnCount(); i++) {
|
||||
TableColumn column = table.getColumnModel().getColumn(i);
|
||||
Component comp = defaultTableCellRenderer.getTableCellRendererComponent(table, column.getHeaderValue(), false, false, 0, i);
|
||||
int width = 1;
|
||||
width = Math.max(width, comp.getPreferredSize().width);
|
||||
|
||||
int line = 0;
|
||||
for (; line < table.getRowCount(); ++line) {
|
||||
comp = table.getCellRenderer(line, i).getTableCellRendererComponent(table, dtm.getValueAt(line, i), false, false, line, i);
|
||||
width = Math.max(width, comp.getPreferredSize().width);
|
||||
}
|
||||
column.setPreferredWidth(Math.min(width, 400));
|
||||
if (i == 0) {
|
||||
column.setWidth(column.getPreferredWidth());
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
jPanel2 = new javax.swing.JPanel();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
historyTable = new javax.swing.JTable();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
jPanel1.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("History"));
|
||||
jPanel2.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
historyTable.setModel(new javax.swing.table.DefaultTableModel(
|
||||
new Object [][] {
|
||||
{null, null, null, null},
|
||||
{null, null, null, null},
|
||||
{null, null, null, null},
|
||||
{null, null, null, null}
|
||||
},
|
||||
new String [] {
|
||||
"Title 1", "Title 2", "Title 3", "Title 4"
|
||||
}
|
||||
));
|
||||
jScrollPane1.setViewportView(historyTable);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
jPanel2.add(jScrollPane1, gridBagConstraints);
|
||||
|
||||
jLabel1.setText(" ");
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 2;
|
||||
jPanel2.add(jLabel1, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
jPanel1.add(jPanel2, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(jPanel1, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JTable historyTable;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel jPanel2;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
protected abstract void close();
|
||||
protected abstract void apply(Table source, Table destination);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2007 - 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package net.sf.jailer.ui.pathfinder;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Point;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.util.List;
|
||||
|
||||
import org.fife.rsta.ui.EscapableDialog;
|
||||
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
import net.sf.jailer.ui.UIUtil;
|
||||
|
||||
/**
|
||||
* Finds path between two tables.
|
||||
*
|
||||
* @author Ralf Wisser
|
||||
*/
|
||||
public class PathFinder {
|
||||
|
||||
private List<Table> path;
|
||||
private boolean expand;
|
||||
|
||||
public class Result {
|
||||
public List<Table> path;
|
||||
public boolean expand;
|
||||
}
|
||||
|
||||
public Result find(Table source, Table destination, DataModel dataModel, boolean withOpenTablesButton, boolean fromHistory, Frame owner) {
|
||||
final EscapableDialog dialog = new EscapableDialog(owner, "PathFinder", true) {
|
||||
private static final long serialVersionUID = 1L;
|
||||
};
|
||||
|
||||
final PathFinderView view = new PathFinderView(dataModel, source, destination, withOpenTablesButton, fromHistory) {
|
||||
@Override
|
||||
protected void applyPath(List<Table> path, boolean expand) {
|
||||
PathFinder.this.path = path;
|
||||
PathFinder.this.expand = expand;
|
||||
dialog.setVisible(false);
|
||||
}
|
||||
private static final long serialVersionUID = 1L;
|
||||
};
|
||||
|
||||
view.showGraph(true);
|
||||
|
||||
dialog.getContentPane().add(view);
|
||||
dialog.pack();
|
||||
int minWidth = 1200;
|
||||
dialog.setSize(minWidth, Math.min(Math.max(dialog.getHeight() + 20, 440), 600));
|
||||
dialog.addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentShown(ComponentEvent arg0) {
|
||||
view.sepLabel.setVisible(false);
|
||||
}
|
||||
});
|
||||
Point ownerLoc;
|
||||
Dimension ownerSize;
|
||||
if (owner != null) {
|
||||
ownerLoc = owner.getLocation();
|
||||
ownerSize = owner.getSize();
|
||||
} else {
|
||||
ownerLoc = new Point();
|
||||
ownerSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
}
|
||||
int x = (int) (ownerLoc.getX() + ownerSize.getWidth() / 2 - dialog.getWidth() / 2);
|
||||
int y = (int) (ownerLoc.getY() + ownerSize.getHeight() / 2 - dialog.getHeight() / 2);
|
||||
dialog.setLocation(x, y);
|
||||
int h = dialog.getHeight();
|
||||
UIUtil.fit(dialog);
|
||||
if (h > dialog.getHeight()) {
|
||||
dialog.setLocation(x, y - (h - dialog.getHeight()));
|
||||
dialog.setSize(Math.max(minWidth, dialog.getWidth()), Math.min(Math.max(dialog.getHeight() + 20, 400), 600));
|
||||
UIUtil.fit(dialog);
|
||||
}
|
||||
|
||||
dialog.setVisible(true);
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
Result result = new Result();
|
||||
result.path = path;
|
||||
result.expand = expand;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,83,0,0,2,-34"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||
<Properties>
|
||||
<Property name="resizeWeight" type="double" value="1.0"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="jPanel2">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Union of all shortest paths without excluded tables."/>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="ff" green="ff" id="white" palette="1" red="ff" type="palette"/>
|
||||
</Property>
|
||||
<Property name="opaque" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="pathContainerPanel">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="ff" green="ff" id="white" palette="1" red="ff" type="palette"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="okButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Show Path"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="okExpandButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Show Path and open Tables"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okExpandButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="sepLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value=" "/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel2">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="80" green="80" id="gray" palette="1" red="80" type="palette"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Open context menu (right mouse click on table) to define its direct successor."/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel3">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Excluded Tables"/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTable" name="exclusionTable">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
||||
<Table columnCount="4" rowCount="4">
|
||||
<Column editable="true" title="Title 1" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Title 2" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Title 3" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Title 4" type="java.lang.Object"/>
|
||||
</Table>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value=" "/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel4">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="undoButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="jButton1"/>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="undoButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="redoButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="jButton1"/>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="redoButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator2">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="1"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="3" gridY="0" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="0" insetsRight="8" anchor="10" weightX="0.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="historyButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="From History"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Take the previously determined path."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="historyButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator3">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="1"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="5" gridY="0" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="0" insetsRight="8" anchor="10" weightX="0.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="considerRestrictionsCheckbox">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" value="Consider restrictions"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="considerRestrictionsCheckboxActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="10" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="8" anchor="13" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="resetButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Reset"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="resetButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="6" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator1">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright 2007 - 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package net.sf.jailer.ui.pathfinder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sf.jailer.datamodel.Association;
|
||||
import net.sf.jailer.datamodel.DataModel;
|
||||
import net.sf.jailer.datamodel.Table;
|
||||
import net.sf.jailer.util.Pair;
|
||||
|
||||
/**
|
||||
* Union of equi-length paths as directed graph.
|
||||
*
|
||||
* @author Ralf Wisser
|
||||
*/
|
||||
public class PathGraph {
|
||||
|
||||
private final Table source;
|
||||
private final Table destination;
|
||||
|
||||
private Map<Table, Node> nodePerTable = new HashMap<Table, Node>();
|
||||
private Map<Pair<Node, Node>, EdgeType> edgeTypes = new HashMap<Pair<Node, Node>, EdgeType>();
|
||||
private Set<Table> visitedExcludedTables = new HashSet<Table>();
|
||||
|
||||
public enum EdgeType { PARENT, CHILD, ASSOCIATION, IGNORED };
|
||||
|
||||
public class Node {
|
||||
Table table;
|
||||
int column;
|
||||
Set<Node> next = new HashSet<Node>();
|
||||
Set<Node> prev = new HashSet<Node>();
|
||||
|
||||
public String toString() {
|
||||
return table.getName() + ":" + column;
|
||||
}
|
||||
|
||||
public void collectPrevClosure(Set<Table> closure) {
|
||||
if (!closure.contains(table)) {
|
||||
closure.add(table);
|
||||
for (Node p: prev) {
|
||||
p.collectPrevClosure(closure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void collectNextClosure(Set<Table> closure) {
|
||||
if (!closure.contains(table)) {
|
||||
closure.add(table);
|
||||
for (Node p: next) {
|
||||
p.collectNextClosure(closure);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node of a given table.
|
||||
*
|
||||
* @param table the table
|
||||
* @return node representing table
|
||||
*/
|
||||
public Node getNode(Table table) {
|
||||
return nodePerTable.get(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all nodes on a given column.
|
||||
*
|
||||
* @param column the column
|
||||
* @return all nodes on a given column
|
||||
*/
|
||||
public List<Node> getNodes(int column) {
|
||||
List<Node> result = new ArrayList<Node>();
|
||||
for (Entry<Table, Node> e:nodePerTable.entrySet()) {
|
||||
if (e.getValue().column == column) {
|
||||
result.add(e.getValue());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets edge-type of a given edge.
|
||||
*
|
||||
* @param from left node of edge
|
||||
* @param to right node of edge
|
||||
* @return edge type
|
||||
*/
|
||||
public EdgeType getEdgeType(Node from, Node to) {
|
||||
Pair<Node, Node> edgeKey = new Pair<Node, Node>(from, to);
|
||||
return edgeTypes.get(edgeKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the graph to an empty graph.
|
||||
*/
|
||||
private void reset() {
|
||||
nodePerTable.clear();
|
||||
edgeTypes.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this graph is empty.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return nodePerTable.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new Graph.
|
||||
* @param excludedTables
|
||||
* @param pathStations
|
||||
* @param considerRestrictions
|
||||
*/
|
||||
public PathGraph(DataModel dataModel, Table source, Table destination, Set<Table> excludedTables, List<Table> pathStations, boolean considerRestrictions) {
|
||||
this(dataModel, source, destination, excludedTables, pathStations, considerRestrictions, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new Graph.
|
||||
* @param excludedTables
|
||||
* @param pathStations
|
||||
* @param considerRestrictions
|
||||
*/
|
||||
public PathGraph(DataModel dataModel, Table source, Table destination, Set<Table> excludedTables, List<Table> pathStations, boolean considerRestrictions, boolean strict) {
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
|
||||
List<Table> stations = new ArrayList<Table>(pathStations);
|
||||
Node destNode;
|
||||
for (;;) {
|
||||
visitedExcludedTables.clear();
|
||||
createGraph(excludedTables, stations, visitedExcludedTables, considerRestrictions);
|
||||
destNode = nodePerTable.get(this.destination);
|
||||
if (destNode == null) {
|
||||
// retry with shorter path
|
||||
if (!stations.isEmpty() && !strict) {
|
||||
stations.remove(stations.size() - 1);
|
||||
continue;
|
||||
}
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
Set<Table> destClosure = new HashSet<Table>();
|
||||
destNode.collectPrevClosure(destClosure);
|
||||
Set<Table> excluded = new HashSet<Table>(dataModel.getTables());
|
||||
excluded.removeAll(destClosure);
|
||||
excluded.addAll(excludedTables);
|
||||
visitedExcludedTables.clear();
|
||||
createGraph(excluded, stations, visitedExcludedTables, considerRestrictions);
|
||||
visitedExcludedTables.retainAll(excludedTables);
|
||||
}
|
||||
|
||||
private void createGraph(Set<Table> excluded, List<Table> pathStations, Set<Table> visitedExTables, boolean considerRestrictions) {
|
||||
reset();
|
||||
|
||||
Map<Table, Table> forcedSucc = new HashMap<Table, Table>();
|
||||
|
||||
for (int i = 1; i < pathStations.size(); ++i) {
|
||||
Table a = pathStations.get(i - 1);
|
||||
Table b = pathStations.get(i);
|
||||
for (Association as: a.associations) {
|
||||
if (!as.isIgnored() || !considerRestrictions) {
|
||||
if (as.destination.equals(b)) {
|
||||
forcedSucc.put(a, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<Table> currentColumn = new HashSet<Table>();
|
||||
currentColumn.add(source);
|
||||
int column = 0;
|
||||
Node node = new Node();
|
||||
node.table = source;
|
||||
node.column = column;
|
||||
nodePerTable.put(source, node);
|
||||
List<Table> stations = new LinkedList<Table>(pathStations);
|
||||
stations.remove(source);
|
||||
stations.remove(destination);
|
||||
stations.removeAll(excluded);
|
||||
Set<Table> onPath = new HashSet<Table>(pathStations);
|
||||
onPath.add(source);
|
||||
onPath.add(destination);
|
||||
Set<Table> lastVisitedExTables = new HashSet<Table>();
|
||||
do {
|
||||
boolean onStation = false;
|
||||
if (!stations.isEmpty()) {
|
||||
Table nextStat = stations.get(0);
|
||||
if (currentColumn.contains(nextStat)) {
|
||||
currentColumn.clear();
|
||||
currentColumn.add(nextStat);
|
||||
stations.remove(0);
|
||||
onStation = true;
|
||||
}
|
||||
}
|
||||
if (!onStation) {
|
||||
visitedExTables.addAll(lastVisitedExTables);
|
||||
}
|
||||
lastVisitedExTables.clear();
|
||||
Set<Table> nextColumn = new HashSet<Table>();
|
||||
for (Table table: currentColumn) {
|
||||
node = nodePerTable.get(table);
|
||||
for (Association a: table.associations) {
|
||||
if (!a.isIgnored() || !considerRestrictions
|
||||
|| (onPath.contains(a.source) && onPath.contains(a.destination))) {
|
||||
Table dest = a.destination;
|
||||
if (excluded.contains(dest)) {
|
||||
lastVisitedExTables.add(dest);
|
||||
continue;
|
||||
}
|
||||
if (forcedSucc.containsKey(table) && !forcedSucc.get(table).equals(dest)) {
|
||||
continue;
|
||||
}
|
||||
Node newNode = nodePerTable.get(dest);
|
||||
if (newNode != null && newNode.column != column + 1) {
|
||||
continue;
|
||||
}
|
||||
nextColumn.add(dest);
|
||||
EdgeType type;
|
||||
if (a.isIgnored()) {
|
||||
type = EdgeType.IGNORED;
|
||||
} else if (a.isInsertDestinationBeforeSource()) {
|
||||
type = EdgeType.PARENT;
|
||||
} else if (a.isInsertSourceBeforeDestination()) {
|
||||
type = EdgeType.CHILD;
|
||||
} else {
|
||||
type = EdgeType.ASSOCIATION;
|
||||
}
|
||||
if (newNode == null) {
|
||||
newNode = new Node();
|
||||
newNode.table = dest;
|
||||
newNode.column = column + 1;
|
||||
nodePerTable.put(dest, newNode);
|
||||
}
|
||||
Pair<Node, Node> edgeKey = new Pair<Node, Node>(node, newNode);
|
||||
EdgeType oldType = edgeTypes.get(edgeKey);
|
||||
if (oldType != null && !oldType.equals(EdgeType.IGNORED) && !type.equals(oldType)) {
|
||||
type = EdgeType.ASSOCIATION;
|
||||
}
|
||||
edgeTypes.put(edgeKey, type);
|
||||
node.next.add(newNode);
|
||||
newNode.prev.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
++column;
|
||||
currentColumn = nextColumn;
|
||||
} while (!currentColumn.isEmpty());
|
||||
visitedExTables.addAll(lastVisitedExTables);
|
||||
}
|
||||
|
||||
public Set<Table> getVisitedExcludedTables() {
|
||||
return visitedExcludedTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this graph a unique non-empty path?
|
||||
*/
|
||||
public boolean isUnique() {
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (int column = 0; ; ++column) {
|
||||
int n = getNodes(column).size();
|
||||
if (n == 0) {
|
||||
return true;
|
||||
} else if (n > 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 449 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user