First contribution of NoSql entity generation code as per bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=393938.
Also renamed org.eclipse.persistence.tools.gen to org.eclipse.persistence.tools.gen.db and org.eclipse.persistence.tools.gen.db to org.eclipse.persistence.tools.db to align with new naming scheme introduced with the no sql contribution.
Peer review by Neil Hauge.
diff --git a/tools/org.eclipse.persistence.tools.gen/.classpath b/tools/org.eclipse.persistence.tools.db/.classpath
similarity index 78%
rename from tools/org.eclipse.persistence.tools.gen/.classpath
rename to tools/org.eclipse.persistence.tools.db/.classpath
index 32c7e58..0b9079a 100644
--- a/tools/org.eclipse.persistence.tools.gen/.classpath
+++ b/tools/org.eclipse.persistence.tools.db/.classpath
@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="resource/templates/xml_entities"/>
- <classpathentry kind="src" path="resource/property_files"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="owner.project.facets" value="java"/>
diff --git a/tools/org.eclipse.persistence.tools.gen/.project b/tools/org.eclipse.persistence.tools.db/.project
similarity index 95%
rename from tools/org.eclipse.persistence.tools.gen/.project
rename to tools/org.eclipse.persistence.tools.db/.project
index 831ed03..64a9a2a 100644
--- a/tools/org.eclipse.persistence.tools.gen/.project
+++ b/tools/org.eclipse.persistence.tools.db/.project
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
- <name>org.eclipse.persistence.tools.gen</name>
+ <name>org.eclipse.persistence.tools.db</name>
<comment></comment>
<projects>
</projects>
diff --git a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.core.resources.prefs b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.core.resources.prefs
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.core.resources.prefs
rename to tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.core.resources.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.core.runtime.prefs b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.core.runtime.prefs
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.core.runtime.prefs
rename to tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.core.runtime.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.jdt.core.prefs b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.jdt.core.prefs
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.jdt.core.prefs
rename to tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.jdt.core.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs
rename to tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.ltk.core.refactoring.prefs b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.ltk.core.refactoring.prefs
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.ltk.core.refactoring.prefs
rename to tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.ltk.core.refactoring.prefs
diff --git a/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.wst.common.component b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..5bdf470
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+ <wb-module deploy-name="org.eclipse.persistence.tools.db">
+ <wb-resource deploy-path="/" source-path="/src"/>
+ </wb-module>
+</project-modules>
diff --git a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.wst.common.project.facet.core.xml b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.wst.common.project.facet.core.xml
similarity index 99%
rename from tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.wst.common.project.facet.core.xml
rename to tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.wst.common.project.facet.core.xml
index 2d6935f..fd68f7e 100644
--- a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.wst.common.project.facet.core.xml
+++ b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
- <fixed facet="jst.utility"/>
<fixed facet="java"/>
- <installed facet="jst.utility" version="1.0"/>
+ <fixed facet="jst.utility"/>
<installed facet="java" version="1.6"/>
+ <installed facet="jst.utility" version="1.0"/>
</faceted-project>
diff --git a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.xsl.core.prefs b/tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.wst.xsl.core.prefs
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.xsl.core.prefs
rename to tools/org.eclipse.persistence.tools.db/.settings/org.eclipse.wst.xsl.core.prefs
diff --git a/tools/org.eclipse.persistence.tools.db/META-INF/MANIFEST.MF b/tools/org.eclipse.persistence.tools.db/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..7824848
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/META-INF/MANIFEST.MF
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Export-Package: org.eclipse.persistence.tools.db,
+ org.eclipse.persistence.tools.db.driver,
+ org.eclipse.persistence.tools.db.model,
+ org.eclipse.persistence.tools.db.model.handles,
+ org.eclipse.persistence.tools.db.model.platformsmodel,
+ org.eclipse.persistence.tools.db.model.spi,
+ org.eclipse.persistence.tools.db.model.spi.jdbc,
+ platforms
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.persistence.tools.utility;bundle-version="2.5.0",
+ org.eclipse.persistence.tools.gen.db;bundle-version="2.5.0",
+ org.eclipse.persistence.core;bundle-version="2.4.0"
+Bundle-SymbolicName: org.eclipse.persistence.tools.db
+Bundle-Name: EclipseLink Tools Db
+Bundle-Vendor: Eclipse.org - EclipseLink Project
+Bundle-Version: 2.5.0.qualifier
+Bundle-ManifestVersion: 2
+Import-Package: org.w3c.dom;resolution:=optional
diff --git a/tools/org.eclipse.persistence.tools.db/build.properties b/tools/org.eclipse.persistence.tools.db/build.properties
new file mode 100644
index 0000000..b107977
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/build.properties
@@ -0,0 +1,3 @@
+source.. = src/
+bin.includes = META-INF/,\
+ .
diff --git a/tools/org.eclipse.persistence.tools.gen/pom.xml b/tools/org.eclipse.persistence.tools.db/pom.xml
similarity index 86%
copy from tools/org.eclipse.persistence.tools.gen/pom.xml
copy to tools/org.eclipse.persistence.tools.db/pom.xml
index ffc11fc..62d58d4 100644
--- a/tools/org.eclipse.persistence.tools.gen/pom.xml
+++ b/tools/org.eclipse.persistence.tools.db/pom.xml
@@ -3,9 +3,9 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
- <name>EclipseLink Tools Gen</name>
+ <name>EclipseLink Tools Gen DB</name>
<groupId>org.eclipse.persistence</groupId>
- <artifactId>org.eclipse.persistence.tools.gen</artifactId>
+ <artifactId>org.eclipse.persistence.tools.db</artifactId>
<version>2.5.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkColumn.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkColumn.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkColumn.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkColumn.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkColumnPair.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkColumnPair.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkColumnPair.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkColumnPair.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkConnectionProfile.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkConnectionProfile.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkConnectionProfile.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkConnectionProfile.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkDatabase.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkDatabase.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkDatabase.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkDatabase.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkForeignKey.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkForeignKey.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkForeignKey.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkForeignKey.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkSchema.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkSchema.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkSchema.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkSchema.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkTable.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkTable.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/EclipseLinkTable.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/EclipseLinkTable.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/AbstractWorkbenchDriverAdapter.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/AbstractWorkbenchDriverAdapter.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/AbstractWorkbenchDriverAdapter.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/AbstractWorkbenchDriverAdapter.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/CatalogStrategy.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/CatalogStrategy.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/CatalogStrategy.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/CatalogStrategy.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/DB2.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/DB2.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/DB2.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/DB2.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Derby.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Derby.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Derby.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Derby.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/FauxCatalogStrategy.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/FauxCatalogStrategy.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/FauxCatalogStrategy.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/FauxCatalogStrategy.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/FoldingStrategy.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/FoldingStrategy.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/FoldingStrategy.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/FoldingStrategy.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/HSQLDB.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/HSQLDB.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/HSQLDB.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/HSQLDB.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Informix.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Informix.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Informix.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Informix.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/LowerCaseFoldingStrategy.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/LowerCaseFoldingStrategy.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/LowerCaseFoldingStrategy.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/LowerCaseFoldingStrategy.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/MaxDB.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/MaxDB.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/MaxDB.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/MaxDB.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/MySQL.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/MySQL.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/MySQL.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/MySQL.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/NoCatalogStrategy.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/NoCatalogStrategy.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/NoCatalogStrategy.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/NoCatalogStrategy.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/NonFoldingStrategy.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/NonFoldingStrategy.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/NonFoldingStrategy.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/NonFoldingStrategy.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Oracle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Oracle.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Oracle.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Oracle.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/PostgreSQL.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/PostgreSQL.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/PostgreSQL.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/PostgreSQL.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/SQLServer.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/SQLServer.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/SQLServer.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/SQLServer.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/SimpleCatalogStrategy.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/SimpleCatalogStrategy.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/SimpleCatalogStrategy.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/SimpleCatalogStrategy.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Sybase.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Sybase.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Sybase.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Sybase.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Unknown.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Unknown.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/Unknown.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/Unknown.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/UpperCaseFoldingStrategy.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/UpperCaseFoldingStrategy.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/UpperCaseFoldingStrategy.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/UpperCaseFoldingStrategy.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapter.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapter.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapter.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapter.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapterFactory.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapterFactory.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapterFactory.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapterFactory.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapterManager.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapterManager.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapterManager.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/driver/WorkbenchDriverAdapterManager.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/DatabaseTypeHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/DatabaseTypeHandle.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/DatabaseTypeHandle.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/DatabaseTypeHandle.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELColumn.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELColumn.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELColumn.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELColumn.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELColumnPair.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELColumnPair.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELColumnPair.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELColumnPair.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELDatabase.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELDatabase.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELDatabase.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELDatabase.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELLoginSpec.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELLoginSpec.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELLoginSpec.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELLoginSpec.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELLoginSpecHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELLoginSpecHandle.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELLoginSpecHandle.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELLoginSpecHandle.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELModel.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELModel.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELModel.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELModel.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELNode.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELNode.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELNode.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELNode.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELReference.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELReference.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELReference.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELReference.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELTable.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELTable.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/ELTable.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/ELTable.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/NodeModel.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/NodeModel.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/NodeModel.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/NodeModel.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWColumnHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWColumnHandle.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWColumnHandle.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWColumnHandle.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWColumnPairHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWColumnPairHandle.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWColumnPairHandle.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWColumnPairHandle.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWHandle.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWHandle.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWHandle.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWReferenceHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWReferenceHandle.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWReferenceHandle.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWReferenceHandle.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWTableHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWTableHandle.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/handles/MWTableHandle.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/handles/MWTableHandle.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/AbstractJDBCTypeToJavaTypeDeclarationMapping.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/AbstractJDBCTypeToJavaTypeDeclarationMapping.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/AbstractJDBCTypeToJavaTypeDeclarationMapping.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/AbstractJDBCTypeToJavaTypeDeclarationMapping.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/CorruptXMLException.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/CorruptXMLException.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/CorruptXMLException.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/CorruptXMLException.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabasePlatform.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabasePlatform.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabasePlatform.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabasePlatform.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabasePlatformRepository.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabasePlatformRepository.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabasePlatformRepository.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabasePlatformRepository.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabaseType.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabaseType.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabaseType.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/DatabaseType.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCType.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCType.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCType.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCType.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeRepository.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeRepository.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeRepository.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeRepository.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeToDatabaseTypeMapping.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeToDatabaseTypeMapping.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeToDatabaseTypeMapping.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeToDatabaseTypeMapping.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeToJavaTypeDeclarationMapping.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeToJavaTypeDeclarationMapping.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeToJavaTypeDeclarationMapping.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JDBCTypeToJavaTypeDeclarationMapping.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JavaTypeDeclaration.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JavaTypeDeclaration.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JavaTypeDeclaration.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JavaTypeDeclaration.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JavaTypeDeclarationToJDBCTypeMapping.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JavaTypeDeclarationToJDBCTypeMapping.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JavaTypeDeclarationToJDBCTypeMapping.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/platformsmodel/JavaTypeDeclarationToJDBCTypeMapping.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalColumn.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalColumn.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalColumn.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalColumn.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalDatabase.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalDatabase.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalDatabase.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalDatabase.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalDatabaseFactory.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalDatabaseFactory.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalDatabaseFactory.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalDatabaseFactory.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalForeignKey.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalForeignKey.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalForeignKey.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalForeignKey.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalForeignKeyColumnPair.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalForeignKeyColumnPair.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalForeignKeyColumnPair.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalForeignKeyColumnPair.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalTable.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalTable.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalTable.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalTable.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalTableDescription.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalTableDescription.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalTableDescription.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/ExternalTableDescription.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/TableDescription.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/TableDescription.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/TableDescription.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/TableDescription.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalColumn.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalColumn.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalColumn.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalColumn.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalDatabase.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalDatabase.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalDatabase.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalDatabase.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalDatabaseFactory.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalDatabaseFactory.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalDatabaseFactory.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalDatabaseFactory.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalForeignKey.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalForeignKey.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalForeignKey.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalForeignKey.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalForeignKeyColumnPair.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalForeignKeyColumnPair.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalForeignKeyColumnPair.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalForeignKeyColumnPair.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalTable.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalTable.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalTable.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalTable.java
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalTableDescription.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalTableDescription.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalTableDescription.java
rename to tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/model/spi/jdbc/JDBCExternalTableDescription.java
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/DatabaseTypeHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/DatabaseTypeHandle.java
new file mode 100644
index 0000000..2535cee
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/DatabaseTypeHandle.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import org.eclipse.persistence.tools.db.relational.handles.MWHandle;
+import org.eclipse.persistence.tools.db.relational.platformsmodel.DatabaseType;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * This handle is a bit different from the other handles. It references an object that is completely
+ * outside of the project and is only used by database fields.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+final class DatabaseTypeHandle extends MWHandle {
+
+ /**
+ * This is the actual database type.
+ * It is built from the database type name, below.
+ */
+ private volatile DatabaseType databaseType;
+
+ /**
+ * The database type name is transient. It
+ * is used only to hold its value until #postProjectBuild()
+ * is called and we can resolve the actual database type.
+ * We do not keep it in synch with the database type itself because
+ * we cannot know when the database type has been renamed etc.
+ */
+ private volatile String databaseTypeName;
+
+ // ********** constructors **********
+
+ DatabaseTypeHandle(ELColumn parent) {
+ // database types are never removed
+ super(parent, NodeReferenceScrubber.NULL_INSTANCE);
+ }
+
+
+ // ********** instance methods **********
+
+ DatabaseType getDatabaseType() {
+ return this.databaseType;
+ }
+
+ void setDatabaseType(DatabaseType databaseType) {
+ this.databaseType = databaseType;
+ }
+
+ @Override
+ protected Node node() {
+ return getDatabaseType();
+ }
+
+ @Override
+ public void toString(StringBuffer sb) {
+ if (this.databaseType == null) {
+ sb.append("null");
+ } else {
+ this.databaseType.toString(sb);
+ }
+ }
+
+
+ // ********** TopLink methods **********
+
+ String getDatabaseTypeNameForTopLink() {
+ return (this.databaseType == null) ? null : this.databaseType.getName();
+ }
+
+ void setDatabaseTypeNameForTopLink(String name) {
+ this.databaseTypeName = name;
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELColumn.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELColumn.java
new file mode 100644
index 0000000..0fce922
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELColumn.java
@@ -0,0 +1,471 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import java.util.List;
+
+import org.eclipse.persistence.tools.db.relational.platformsmodel.DatabasePlatform;
+import org.eclipse.persistence.tools.db.relational.platformsmodel.DatabaseType;
+import org.eclipse.persistence.tools.db.relational.platformsmodel.JavaTypeDeclaration;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalColumn;
+import org.eclipse.persistence.tools.utility.StringTools;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class ELColumn extends ELModel {
+
+ /** the name should never be null or empty */
+ private volatile String name;
+ public static final String NAME_PROPERTY = "name";
+ public static final String QUALIFIED_NAME_PROPERTY = "qualifiedName";
+
+ /** the database type should never be null */
+ private DatabaseTypeHandle databaseTypeHandle; // pseudo-final
+ public static final String DATABASE_TYPE_PROPERTY = "databaseType";
+
+ private volatile int size;
+ public static final String SIZE_PROPERTY = "size";
+
+ /** sub-size is used for scale on numeric types */
+ private volatile int subSize;
+ public static final String SUB_SIZE_PROPERTY = "subSize";
+
+ private volatile boolean allowsNull;
+ public static final String ALLOWS_NULL_PROPERTY = "allowsNull";
+
+ private volatile boolean unique;
+ public static final String UNIQUE_PROPERTY = "unique";
+
+ /** this is typically short-hand for 'NOT NULL' and 'UNIQUE' */
+ private volatile boolean primaryKey;
+ public static final String PRIMARY_KEY_PROPERTY = "primaryKey";
+
+ /** SQL Server variants allow the IDENTITY clause */
+ private volatile boolean identity;
+ public static final String IDENTITY_PROPERTY = "identity";
+
+ // ********** static methods **********
+
+ /**
+ * Parse the table name from a possibly "qualified" column name:
+ * "ACTG.EMPLOYEE.F_NAME" -> "ACCTG.EMPLOYEE"
+ * "ACTG..F_NAME" -> "ACCTG.."
+ * "EMPLOYEE.F_NAME" -> "EMPLOYEE"
+ * "F_NAME" -> ""
+ */
+ public static String parseTableNameFromQualifiedName(String name) {
+ int index = name.lastIndexOf('.');
+ if (index == -1) {
+ return StringTools.EMPTY_STRING;
+ }
+ return name.substring(0, index);
+ }
+
+ /**
+ * Parse the column name from a possibly "qualified" column name:
+ * "ACCT.EMPLOYEE.F_NAME" -> "F_NAME"
+ * "ACCT..F_NAME" -> "F_NAME"
+ * "EMPLOYEE.F_NAME" -> "F_NAME"
+ * "F_NAME" -> "F_NAME"
+ */
+ public static String parseColumnNameFromQualifiedName(String name) {
+ int index = name.lastIndexOf('.');
+ if (index == -1) {
+ return name;
+ }
+ return name.substring(index + 1);
+ }
+
+ public static boolean nameIsQualified(String columnName) {
+ return columnName.indexOf(".") != -1;
+ }
+
+
+ // ********** constructors **********
+
+ ELColumn(ELTable table, String name) {
+ super(table);
+ this.name = name;
+ }
+
+
+ // ********** initialization **********
+
+ /**
+ * the database type handle is not mapped directly
+ */
+ @Override
+ protected void initialize() {
+ super.initialize();
+ this.databaseTypeHandle = new DatabaseTypeHandle(this);
+ }
+
+ /**
+ * initialize persistent state
+ */
+ @Override
+ protected void initialize(Node parent) {
+ super.initialize(parent);
+ DatabaseType dbType = this.defaultDatabaseType();
+ this.databaseTypeHandle.setDatabaseType(dbType);
+ this.size = dbType.requiresSize() ? dbType.getInitialSize() : 0;
+ this.subSize = 0;
+ this.allowsNull = dbType.allowsNull();
+ this.unique = false;
+ this.primaryKey = false;
+ this.identity = false;
+ }
+
+
+ // ********** accessors **********
+
+ public ELTable getTable() {
+ return this.getParent();
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.getTable().checkColumnName(name);
+ Object old = this.name;
+ this.name = name;
+ if (this.attributeValueHasChanged(old, name)) {
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ this.qualifiedNameChanged();
+ }
+ }
+
+ void qualifiedNameChanged() {
+ String qName = this.qualifiedName();
+ this.firePropertyChanged(QUALIFIED_NAME_PROPERTY, qName);
+ }
+
+ public DatabaseType getDatabaseType() {
+ return this.databaseTypeHandle.getDatabaseType();
+ }
+
+ public void setDatabaseType(DatabaseType databaseType) {
+ if (databaseType == null) {
+ throw new NullPointerException();
+ }
+ Object old = this.databaseTypeHandle.getDatabaseType();
+ this.databaseTypeHandle.setDatabaseType(databaseType);
+ this.firePropertyChanged(DATABASE_TYPE_PROPERTY, old, databaseType);
+ // align various settings with the new database type
+ if (this.attributeValueHasChanged(old, databaseType)) {
+ this.synchronizeWithNewDatabaseType();
+ }
+ }
+
+ public int getSize() {
+ return this.size;
+ }
+
+ public void setSize(int size) {
+ if (( ! this.getDatabaseType().allowsSize()) && (size != 0)) {
+ throw new IllegalArgumentException("size must be 0 when size is not allowed");
+ }
+ int old = this.size;
+ this.size = size;
+ this.firePropertyChanged(SIZE_PROPERTY, old, size);
+ }
+
+ public int getSubSize() {
+ return this.subSize;
+ }
+
+ public void setSubSize(int subSize) {
+ if (( ! this.getDatabaseType().allowsSubSize()) && (subSize != 0)) {
+ throw new IllegalArgumentException("sub-size must be 0 when sub-size is not allowed");
+ }
+ int old = this.subSize;
+ this.subSize = subSize;
+ this.firePropertyChanged(SUB_SIZE_PROPERTY, old, subSize);
+ }
+
+ public boolean allowsNull() {
+ return this.allowsNull;
+ }
+
+ public void setAllowsNull(boolean allowsNull) {
+ if (( ! this.getDatabaseType().allowsNull()) && (allowsNull)) {
+ throw new IllegalArgumentException("allows null must be false when allows null is not allowed");
+ }
+ boolean old = this.allowsNull;
+ this.allowsNull = allowsNull;
+ this.firePropertyChanged(ALLOWS_NULL_PROPERTY, old, allowsNull);
+ if (allowsNull) {
+ this.setPrimaryKey(false);
+ this.setIdentity(false);
+ }
+ }
+
+ public boolean isUnique() {
+ return this.unique;
+ }
+
+ public void setUnique(boolean unique) {
+ boolean old = this.unique;
+ this.unique = unique;
+ this.firePropertyChanged(UNIQUE_PROPERTY, old, unique);
+ if ( ! unique) {
+ this.setPrimaryKey(false);
+ }
+ }
+
+ public boolean isPrimaryKey() {
+ return this.primaryKey;
+ }
+
+ /**
+ * primary key is typically equivalent to
+ * 'NOT NULL' and 'UNIQUE'
+ */
+ public void setPrimaryKey(boolean primaryKey) {
+ boolean old = this.primaryKey;
+ this.primaryKey = primaryKey;
+ this.firePropertyChanged(PRIMARY_KEY_PROPERTY, old, primaryKey);
+ if (primaryKey) {
+ this.setAllowsNull(false);
+ this.setUnique(true);
+ }
+ }
+
+ public boolean isIdentity() {
+ return this.identity;
+ }
+
+ /**
+ * 'IDENTITY' requires 'NOT NULL'
+ */
+ public void setIdentity(boolean identity) {
+ if (( ! this.supportsIdentityClause()) && (identity)) {
+ throw new IllegalArgumentException("the current platform does not support the IDENTITY clause");
+ }
+ boolean old = this.identity;
+ this.identity = identity;
+ this.firePropertyChanged(IDENTITY_PROPERTY, old, identity);
+ if (identity) {
+ this.setAllowsNull(false);
+ }
+ }
+
+
+ // ********** queries **********
+
+ public DatabasePlatform databasePlatform() {
+ return this.getTable().databasePlatform();
+ }
+
+ public String qualifiedName() {
+ return this.getTable().qualifiedName() + '.' + this.getName();
+ }
+
+ /**
+ * this is the initial value of our database type
+ */
+ private DatabaseType defaultDatabaseType() {
+ return this.databasePlatform().defaultDatabaseType();
+ }
+
+ /**
+ * Returns the Java type declaration corresponding to the column's database type;
+ * this is used to generate instance variables from database columns when
+ * generating classes from tables
+ */
+ public JavaTypeDeclaration javaTypeDeclaration() {
+ return this.getDatabaseType().javaTypeDeclaration();
+ }
+
+ /**
+ * Returns whether the column can be defined with an IDENTITY
+ * clause (SQL Server variants only)
+ */
+ public boolean supportsIdentityClause() {
+ return this.getDatabase().supportsIdentityClause();
+ }
+
+
+ // ********** behavior **********
+
+ @Override
+ protected void addChildrenTo(List<Node> children) {
+ super.addChildrenTo(children);
+ children.add(this.databaseTypeHandle);
+ }
+
+ @Override
+ public ELTable getParent() {
+ return (ELTable)super.getParent();
+ }
+
+ public ELDatabase getDatabase() {
+ return getParent().getParent();
+ }
+
+ /**
+ * replace our database type (from our old database platform) with
+ * a database type from our new database platform that is a reasonable
+ * match
+ */
+ void databasePlatformChanged() {
+ this.setDatabaseType(this.databasePlatform().databaseTypeFor(this.getDatabaseType()));
+ }
+
+ private void synchronizeWithNewDatabaseType() {
+ DatabaseType dbType = this.getDatabaseType();
+
+ // synchronize size/sub-size
+ if (dbType.allowsSize()) {
+ if (dbType.allowsSubSize()) {
+ // leave sub-size unchanged - it will be zero unless we are converting
+ // from one numeric type to another numeric type and a "scale" was specified
+ } else {
+ this.setSubSize(0);
+ }
+ if (dbType.requiresSize()) {
+ if (this.size == 0) {
+ this.setSize(dbType.getInitialSize());
+ } else {
+ // take the previously-assigned size
+ }
+ } else {
+ if (this.subSize == 0) {
+ // if size is not required and a sub-size was not specified,
+ // we probably want to clear out size: VARCHAR2(20) => NUMBER
+ this.setSize(0);
+ } else {
+ // we will only get here when converting from one numeric type
+ // to another numeric type and a "scale" was specified - keep
+ // the same size/sub-size combination
+ }
+ }
+ } else {
+ this.setSize(0);
+ this.setSubSize(0);
+ }
+
+ // synchronize allows null
+ if (dbType.allowsNull()) {
+ // leave allows null unchanged
+ } else {
+ this.setAllowsNull(false);
+ }
+
+ // IDENTITY
+ if (dbType.getPlatform().supportsIdentityClause()) {
+ // leave identity unchanged
+ } else {
+ this.setIdentity(false);
+ }
+ }
+
+ void copySettingsFrom(ELColumn original) {
+ this.setDatabaseType(original.getDatabaseType());
+ this.setSize(original.getSize());
+ this.setSubSize(original.getSubSize());
+ this.setAllowsNull(original.allowsNull());
+ this.setUnique(original.isUnique());
+ this.setPrimaryKey(original.isPrimaryKey());
+ this.setIdentity(original.isIdentity());
+ }
+
+ // ********** DataField implementation **********
+
+ /**
+ * used by UI components common to O-R and O-X
+ * (mappings, locking policy, etc.)
+ */
+ public String fieldName() {
+ return this.qualifiedName();
+ }
+
+
+ // ********** importing/refreshing **********
+
+ /**
+ * refresh with the data from the specified "external" column
+ */
+ void refresh(ExternalColumn externalColumn) {
+ this.setDatabaseType(this.databaseTypeFrom(externalColumn));
+ this.setSize(this.sizeFrom(externalColumn));
+ this.setSubSize(this.subSizeFrom(externalColumn));
+ this.setAllowsNull(this.allowsNullFrom(externalColumn));
+ this.setPrimaryKey(externalColumn.isPrimaryKey());
+ // leave 'unique' unchanged - I don't think we can get it from the database
+ // 'primaryKey' will be set later by our parent table
+ }
+
+ /**
+ * first try to get the platform-specific datatype;
+ * if that fails, get the platform-specific datatype most
+ * closely associated with the JDBC type;
+ * if that fails, get the default datatype
+ */
+ private DatabaseType databaseTypeFrom(ExternalColumn externalColumn) {
+ try {
+ return this.databasePlatform().databaseTypeNamed(externalColumn.getTypeName());
+ } catch (IllegalArgumentException ex) {
+ return this.databaseTypeFromJDBCTypeFrom(externalColumn);
+ }
+ }
+
+ private DatabaseType databaseTypeFromJDBCTypeFrom(ExternalColumn externalColumn) {
+ try {
+ return this.databasePlatform().databaseTypeForJDBCTypeCode(externalColumn.getJDBCTypeCode());
+ } catch (Exception ex) {
+ // defensive - when all else fails, use the default type
+ return this.databasePlatform().defaultDatabaseType();
+ }
+ }
+
+ private int sizeFrom(ExternalColumn externalColumn) {
+ if ( ! this.getDatabaseType().allowsSize()) {
+ // ignore the size in the "external" column - it cannot be used in the column's declaration
+ return 0;
+ }
+ return externalColumn.getSize();
+ }
+
+ private int subSizeFrom(ExternalColumn externalColumn) {
+ if ( ! this.getDatabaseType().allowsSubSize()) {
+ // ignore the sub-size in the "external" column - it cannot be used in the column's declaration
+ return 0;
+ }
+ return externalColumn.getScale();
+ }
+
+ private boolean allowsNullFrom(ExternalColumn externalColumn) {
+ if ( ! this.getDatabaseType().allowsNull()) {
+ // ignore the flag in the "external" column - the column cannot be null, given its current datatype
+ return false;
+ }
+ return externalColumn.isNullable();
+ }
+
+ // ********** displaying and printing **********
+
+ @Override
+ public String displayString() {
+ return this.qualifiedName();
+ }
+
+ public void toString(StringBuffer sb) {
+ sb.append(this.qualifiedName());
+ }
+}
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELColumnPair.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELColumnPair.java
new file mode 100644
index 0000000..fe4cb9e
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELColumnPair.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import java.util.List;
+
+import org.eclipse.persistence.tools.db.relational.handles.MWColumnHandle;
+import org.eclipse.persistence.tools.db.relational.handles.MWHandle;
+import org.eclipse.persistence.tools.db.relational.handles.MWHandle.NodeReferenceScrubber;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKeyColumnPair;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * Simple class that pairs a source column and a target column for a reference.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class ELColumnPair extends ELModel {
+
+ private MWColumnHandle sourceColumnHandle;
+ public static final String SOURCE_COLUMN_PROPERTY = "sourceColumn";
+
+ private MWColumnHandle targetColumnHandle;
+ public static final String TARGET_COLUMN_PROPERTY = "targetColumn";
+
+ // ********** constructors **********
+
+ ELColumnPair(ELReference parent, ELColumn sourceColumn, ELColumn targetColumn) {
+ super(parent);
+ this.sourceColumnHandle.setColumn(sourceColumn);
+ this.targetColumnHandle.setColumn(targetColumn);
+ }
+
+
+ // ********** initialization **********
+
+ /**
+ * initialize persistent state
+ */
+ @Override
+ protected void initialize(Node parent) {
+ super.initialize(parent);
+ this.sourceColumnHandle = new MWColumnHandle(this, this.buildSourceColumnScrubber());
+ this.targetColumnHandle = new MWColumnHandle(this, this.buildTargetColumnScrubber());
+ }
+
+
+ // ********** accessors **********
+
+ public ELReference getReference() {
+ return (ELReference) this.getParent();
+ }
+
+ public ELColumn getSourceColumn() {
+ return this.sourceColumnHandle.getColumn();
+ }
+
+ public void setSourceColumn(ELColumn sourceColumn) {
+ if ((sourceColumn != null) && (sourceColumn.getTable() != this.getReference().getSourceTable())) {
+ throw new IllegalArgumentException();
+ }
+ Object old = this.sourceColumnHandle.getColumn();
+ this.sourceColumnHandle.setColumn(sourceColumn);
+ this.firePropertyChanged(SOURCE_COLUMN_PROPERTY, old, sourceColumn);
+ }
+
+ public ELColumn getTargetColumn() {
+ return this.targetColumnHandle.getColumn();
+ }
+
+ public void setTargetColumn(ELColumn targetColumn) {
+ if ((targetColumn != null) && (targetColumn.getTable() != this.getReference().getTargetTable())) {
+ throw new IllegalArgumentException();
+ }
+ Object old = this.targetColumnHandle.getColumn();
+ this.targetColumnHandle.setColumn(targetColumn);
+ this.firePropertyChanged(TARGET_COLUMN_PROPERTY, old, targetColumn);
+ }
+
+
+ // ********** queries **********
+
+ /**
+ * the pair's name is calculated from the two column names
+ */
+ public String getName() {
+ StringBuffer sb = new StringBuffer(200);
+ this.appendColumn(sb, this.getSourceColumn());
+ sb.append('=');
+ this.appendColumn(sb, this.getTargetColumn());
+ return sb.toString();
+ }
+
+ private void appendColumn(StringBuffer sb, ELColumn column) {
+ if (column != null) {
+ sb.append(column.qualifiedName());
+ }
+ }
+
+ /**
+ * Returns whether the column pair matches up the specified columns
+ */
+ boolean pairs(ELColumn sourceColumn, ELColumn targetColumn) {
+ return (this.getSourceColumn() == sourceColumn) &&
+ (this.getTargetColumn() == targetColumn);
+ }
+
+ public ELTable sourceTable() {
+ return this.tableFrom(this.getSourceColumn());
+ }
+
+ public ELTable targetTable() {
+ return this.tableFrom(this.getTargetColumn());
+ }
+
+ private ELTable tableFrom(ELColumn column) {
+ return (column == null) ? null : column.getTable();
+ }
+
+
+ // ********** behavior **********
+
+ public void setSourceAndTargetColumns(ELColumn sourceColumn, ELColumn targetColumn) {
+ this.setSourceColumn(sourceColumn);
+ this.setTargetColumn(targetColumn);
+ }
+
+ // ********** containment hierarchy **********
+
+ @Override
+ protected void addChildrenTo(List<Node> children) {
+ super.addChildrenTo(children);
+ children.add(this.sourceColumnHandle);
+ children.add(this.targetColumnHandle);
+ }
+
+ private NodeReferenceScrubber buildSourceColumnScrubber() {
+ return new NodeReferenceScrubber() {
+ @Override
+ public void nodeReferenceRemoved(Node node, MWHandle handle) {
+ ELColumnPair.this.setSourceColumn(null);
+ }
+ @Override
+ public String toString() {
+ return "MWColumnPair.buildSourceColumnScrubber()";
+ }
+ };
+ }
+
+ private NodeReferenceScrubber buildTargetColumnScrubber() {
+ return new NodeReferenceScrubber() {
+ @Override
+ public void nodeReferenceRemoved(Node node, MWHandle handle) {
+ ELColumnPair.this.setTargetColumn(null);
+ }
+ @Override
+ public String toString() {
+ return "MWColumnPair.buildTargetColumnScrubber()";
+ }
+ };
+ }
+
+
+ // ********** importing/refreshing **********
+
+ /**
+ * Returns whether the column pair corresponds to the specified
+ * "external" column pair;
+ * if the column pair matches an "external" column pair we keep,
+ * otherwise, we remove it from the reference
+ */
+ boolean matches(ExternalForeignKeyColumnPair externalPair) {
+ return (this.getSourceColumn() == this.sourceColumn(externalPair)) &&
+ (this.getTargetColumn() == this.targetColumn(externalPair));
+ }
+
+ /**
+ * Returns the column in the source table with the same name as the
+ * "external" column pair's source column
+ */
+ private ELColumn sourceColumn(ExternalForeignKeyColumnPair externalPair) {
+ return this.getReference().sourceColumn(externalPair);
+ }
+
+ /**
+ * Returns the column in the target table with the same name as the
+ * "external" column pair's target column
+ */
+ private ELColumn targetColumn(ExternalForeignKeyColumnPair externalPair) {
+ return this.getReference().targetColumn(externalPair);
+ }
+
+ // ********** displaying and printing **********
+
+ @Override
+ public String displayString() {
+ return this.getName();
+ }
+
+ public void toString(StringBuffer sb) {
+ this.printColumnNameOn(this.getSourceColumn(), sb);
+ sb.append("=>");
+ this.printColumnNameOn(this.getTargetColumn(), sb);
+ }
+
+ private void printColumnNameOn(ELColumn column, StringBuffer sb) {
+ sb.append((column == null) ? "null" : column.getName());
+ }
+}
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELDatabase.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELDatabase.java
new file mode 100644
index 0000000..d899424
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELDatabase.java
@@ -0,0 +1,914 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+import org.eclipse.persistence.sessions.Connector;
+import org.eclipse.persistence.sessions.DatabaseSession;
+import org.eclipse.persistence.sessions.Project;
+import org.eclipse.persistence.sessions.Session;
+import org.eclipse.persistence.tools.db.relational.handles.MWHandle.NodeReferenceScrubber;
+import org.eclipse.persistence.tools.db.relational.platformsmodel.DatabasePlatform;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalDatabase;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalDatabaseFactory;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription;
+import org.eclipse.persistence.tools.db.relational.spi.jdbc.JDBCExternalDatabaseFactory;
+import org.eclipse.persistence.tools.schemaframework.SchemaManager;
+import org.eclipse.persistence.tools.utility.CollectionTools;
+import org.eclipse.persistence.tools.utility.StringTools;
+import org.eclipse.persistence.tools.utility.iterators.ArrayIterator;
+import org.eclipse.persistence.tools.utility.iterators.CloneIterator;
+import org.eclipse.persistence.tools.utility.iterators.TransformationIterator;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class ELDatabase extends ELModel {
+
+ /** the database platform should never be null */
+ private volatile DatabasePlatform databasePlatform;
+ public static final String DATABASE_PLATFORM_PROPERTY = "databasePlatform" ;
+
+ private Collection<ELLoginSpec> loginSpecs;
+ public static final String LOGIN_SPECS_COLLECTION = "loginSpecs";
+
+ private ELLoginSpecHandle deploymentLoginSpecHandle;
+ public static final String DEPLOYMENT_LOGIN_SPEC_PROPERTY = "deploymentLoginSpec";
+ private ELLoginSpecHandle developmentLoginSpecHandle;
+ public static final String DEVELOPMENT_LOGIN_SPEC_PROPERTY = "developmentLoginSpec";
+
+ private Collection<ELTable> tables;
+ public static final String TABLES_COLLECTION = "tables";
+
+ /**
+ * the "external" database that supplies the
+ * "external" tables used to build MWTables
+ */
+ private volatile ExternalDatabase externalDatabase;
+
+ /**
+ * transient - java.sql.Driver used to connect to the database;
+ * this field is always null when executing under jdev
+ */
+ private volatile Driver driver;
+
+ /**
+ * transient - java.sql.Connection used for collecting meta-data;
+ * this field is always null when executing under jdev
+ */
+ private volatile Connection connection;
+ // virtual property
+ public static final String CONNECTED_PROPERTY = "connected";
+
+ /**
+ * transient - org.eclipse.persistence.tools.schemaframework.SchemaManager
+ * used for generating tables on the database;
+ * this field is always null when executing under jdev
+ */
+ private volatile SchemaManager schemaManager;
+
+ private volatile ExternalDatabaseFactory dbFactory;
+
+ /**
+ * these table names are read in by TopLink and are then
+ * used and managed by the IOManager;
+ * DO NOT use them for anything else ~bjv
+ */
+ private Collection<String> tableNames;
+ private static final String TABLE_NAMES_COLLECTION = "tableNames";
+
+ /** this setting queried reflectively by the I/O Manager; so don't remove it */
+ private static final String SUB_DIRECTORY_NAME = "tables";
+
+ // ********** constructors **********
+
+ public ELDatabase(DatabasePlatform databasePlatform) {
+ super(null);
+ this.databasePlatform = databasePlatform;
+ }
+
+
+ // ********** initialization **********
+
+ @Override
+ protected void checkParent(Node parentNode) {
+ // no-op since db is the root node
+ }
+
+ /**
+ * initialize transient state
+ */
+ @Override
+ public void initialize() {
+ super.initialize();
+ // the tables are not mapped directly
+ this.tables = new Vector<ELTable>();
+ }
+
+ /**
+ * initialize persistent state
+ */
+ @Override
+ protected void initialize(Node parent) {
+ super.initialize(parent);
+ this.loginSpecs = new Vector<ELLoginSpec>();
+ // 'deploymentLoginSpec' and 'developmentLoginSpec'
+ // are handled directly in #loginSpecRemoved(MWLoginSpec)
+ this.deploymentLoginSpecHandle = new ELLoginSpecHandle(this, NodeReferenceScrubber.NULL_INSTANCE);
+ this.developmentLoginSpecHandle = new ELLoginSpecHandle(this, NodeReferenceScrubber.NULL_INSTANCE);
+ this.tableNames = new HashSet<String>();
+ }
+
+ @Override
+ public Validator getValidator() {
+ return new Validator() {
+
+ @Override
+ public void validate() {
+ }
+
+ @Override
+ public void resume() {
+ }
+
+ @Override
+ public void pause() {
+ }
+ };
+ }
+
+
+ // ********** database platform **********
+
+ public DatabasePlatform getDatabasePlatform() {
+ return this.databasePlatform;
+ }
+
+ public void setDatabasePlatform(DatabasePlatform databasePlatform) {
+ if (databasePlatform == null) {
+ throw new NullPointerException();
+ }
+ Object old = this.databasePlatform;
+ this.databasePlatform = databasePlatform;
+ this.firePropertyChanged(DATABASE_PLATFORM_PROPERTY, old, databasePlatform);
+ if (this.attributeValueHasChanged(old, databasePlatform)) {
+ this.databasePlatformChanged();
+ }
+ }
+
+ /**
+ * cascade to the database fields so they can update their types
+ */
+ private void databasePlatformChanged() {
+ synchronized (this.tables) {
+ for (ELTable table : this.tables) {
+ table.databasePlatformChanged();
+ }
+ }
+ }
+
+
+ // ********** login specs **********
+
+ public Iterator<ELLoginSpec> loginSpecs() {
+ return new CloneIterator<ELLoginSpec>(this.loginSpecs) {
+ @Override
+ protected void remove(ELLoginSpec current) {
+ ELDatabase.this.removeLoginSpec(current);
+ }
+ };
+ }
+
+ public int loginSpecsSize() {
+ return this.loginSpecs.size();
+ }
+
+ public ELLoginSpec addLoginSpec(String loginSpecName) {
+ this.checkLoginSpecName(loginSpecName);
+ return this.addLoginSpec(new ELLoginSpec(this, loginSpecName));
+ }
+
+ private ELLoginSpec addLoginSpec(ELLoginSpec loginSpec) {
+ this.addItemToCollection(loginSpec, this.loginSpecs, LOGIN_SPECS_COLLECTION);
+ if (this.loginSpecs.size() == 1) {
+ this.setDeploymentLoginSpec(loginSpec);
+ this.setDevelopmentLoginSpec(loginSpec);
+ }
+ return loginSpec;
+ }
+
+ public void removeLoginSpec(ELLoginSpec loginSpec) {
+ if (this.removeItemFromCollection(loginSpec, this.loginSpecs, LOGIN_SPECS_COLLECTION)) {
+ this.loginSpecRemoved(loginSpec);
+ }
+ }
+
+ public boolean containsLoginSpecNamed(String loginSpecName) {
+ return this.loginSpecNamed(loginSpecName) != null;
+ }
+
+ public ELLoginSpec loginSpecNamed(String loginSpecName) {
+ synchronized (this.loginSpecs) {
+ for (ELLoginSpec spec : this.loginSpecs) {
+ if (spec.getName().equals(loginSpecName)) {
+ return spec;
+ }
+ }
+ }
+ return null;
+ }
+
+ public Iterator<String> loginSpecNames() {
+ return new TransformationIterator<String, ELLoginSpec>(this.loginSpecs()) {
+ @Override
+ protected String transform(ELLoginSpec next) {
+ return next.getName();
+ }
+ };
+ }
+
+
+ // ********** deployment login spec **********
+
+ public ELLoginSpec getDeploymentLoginSpec() {
+ return this.deploymentLoginSpecHandle.getLoginSpec();
+ }
+
+ public void setDeploymentLoginSpec(ELLoginSpec loginSpec) {
+ Object old = this.deploymentLoginSpecHandle.getLoginSpec();
+ this.deploymentLoginSpecHandle.setLoginSpec(loginSpec);
+ this.firePropertyChanged(DEPLOYMENT_LOGIN_SPEC_PROPERTY, old, loginSpec);
+ }
+
+
+ // ********** development login spec **********
+
+ public ELLoginSpec getDevelopmentLoginSpec() {
+ return this.developmentLoginSpecHandle.getLoginSpec();
+ }
+
+ public void setDevelopmentLoginSpec(ELLoginSpec loginSpec) {
+ Object old = this.developmentLoginSpecHandle.getLoginSpec();
+ this.developmentLoginSpecHandle.setLoginSpec(loginSpec);
+ this.firePropertyChanged(DEVELOPMENT_LOGIN_SPEC_PROPERTY, old, loginSpec);
+ }
+
+
+ // ********** tables **********
+
+ public Iterator<ELTable> tables() {
+ return new CloneIterator<ELTable>(this.tables) {
+ @Override
+ protected void remove(ELTable current) {
+ ELDatabase.this.removeTable(current);
+ }
+ };
+ }
+
+ public int tablesSize() {
+ return this.tables.size();
+ }
+
+ public ELTable addTable(String shortName) {
+ return this.addTable(null, shortName);
+ }
+
+ public ELTable addTable(String schema, String shortName) {
+ return this.addTable(null, schema, shortName);
+ }
+
+ public ELTable addTable(String catalog, String schema, String shortName) {
+ this.checkTableName(catalog, schema, shortName, null);
+ return this.addTable(new ELTable(this, catalog, schema, shortName));
+ }
+
+ public ELTable addTableWithFullyQualifiedName(String fullyQualifiedName) {
+ Collection<String> strings = CollectionTools.collection(fullyQualifiedName.split("\\."));
+ CollectionTools.removeAllOccurrences(strings, StringTools.EMPTY_STRING);
+ String[] parsedName = strings.toArray(new String[strings.size()]);
+ if (parsedName.length == 3) {
+ return addTable(parsedName[0], parsedName[1], parsedName[2]);
+ }
+ else if (parsedName.length == 2) {
+ return addTable(parsedName[0], parsedName[1]);
+ }
+ else {
+ return addTable(parsedName[0]);
+ }
+ }
+
+ private ELTable addTable(ELTable table) {
+ this.addItemToCollection(table, this.tables, TABLES_COLLECTION);
+ return table;
+ }
+
+ public void removeTable(ELTable table) {
+ this.removeNodeFromCollection(table, this.tables, TABLES_COLLECTION);
+ }
+
+ public boolean containsTableNamed(String catalog, String schema, String shortName) {
+ return this.tableNamed(catalog, schema, shortName) != null;
+ }
+
+ public ELTable tableNamed(String catalog, String schema, String shortName) {
+ synchronized (this.tables) {
+ for (ELTable table : this.tables) {
+ if (table.nameMatches(catalog, schema, shortName)) {
+ return table;
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean containsTableNamedIgnoreCase(String catalog, String schema, String shortName) {
+ return this.tableNamedIgnoreCase(catalog, schema, shortName) != null;
+ }
+
+ public ELTable tableNamedIgnoreCase(String catalog, String schema, String shortName) {
+ synchronized (this.tables) {
+ for (ELTable table : this.tables) {
+ if (table.nameMatchesIgnoreCase(catalog, schema, shortName)) {
+ return table;
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean containsTableNamed(String qualifiedName) {
+ return this.tableNamed(qualifiedName) != null;
+ }
+
+ public ELTable tableNamed(String qualifiedName) {
+ synchronized (this.tables) {
+ for (ELTable table : this.tables) {
+ if (table.qualifiedName().equals(qualifiedName)) {
+ return table;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * used to prevent adding a duplicate table
+ */
+ public Iterator<String> tableNames() {
+ return new TransformationIterator<String, ELTable>(this.tables()) {
+ @Override
+ protected String transform(ELTable next) {
+ return next.getName();
+ }
+ };
+ }
+
+ public ELColumn columnNamed(String qualifiedName) {
+ ELTable table = this.tableNamed(ELColumn.parseTableNameFromQualifiedName(qualifiedName));
+ if (table == null) {
+ return null;
+ }
+ return table.columnNamed(ELColumn.parseColumnNameFromQualifiedName(qualifiedName));
+ }
+
+
+ // ********** external database **********
+
+ /**
+ * PRIVATE - no one should need direct access to the external database
+ */
+ public ExternalDatabase getExternalDatabase() {
+ if (this.externalDatabase == null) {
+ this.externalDatabase = this.buildExternalDatabase();
+ }
+ return this.externalDatabase;
+ }
+
+ private ExternalDatabase buildExternalDatabase() {
+ // when executing under jdev, the connection will be null
+ return this.externalDatabaseFactory().buildDatabase(this.connection);
+ }
+
+ private ExternalDatabaseFactory getExternalDatabaseFactory() {
+ if (this.dbFactory == null) {
+ this.dbFactory = new JDBCExternalDatabaseFactory();
+ }
+
+ return this.dbFactory;
+ }
+
+
+ // ********** connection **********
+
+ /**
+ * this method is not called when executing under jdev
+ */
+ public boolean isConnected() {
+ return this.connection != null;
+ }
+
+
+ // ********** schema manager **********
+
+ /**
+ * call #isConnected()/#login() before calling this method or you
+ * might get an IllegalStateException;
+ * this method is not called when executing under jdev
+ */
+ private SchemaManager getSchemaManager() {
+ if (this.schemaManager == null) {
+ throw new IllegalStateException("not connected");
+ }
+ return this.schemaManager;
+ }
+
+
+ // ********** queries **********
+
+ /**
+ * the external database factory is supplied by client code
+ */
+ private ExternalDatabaseFactory externalDatabaseFactory() {
+ return getExternalDatabaseFactory();
+ }
+
+ boolean supportsIdentityClause() {
+ return this.databasePlatform.supportsIdentityClause();
+ }
+
+
+ // ********** miscellaneous behavior **********
+
+ /**
+ * 'connected' is a virtual property
+ */
+ @Override
+ protected void addTransientAspectNamesTo(Set<String> transientAspectNames) {
+ super.addTransientAspectNamesTo(transientAspectNames);
+ transientAspectNames.add(CONNECTED_PROPERTY);
+ }
+
+ /**
+ * disallow duplicate login info names
+ */
+ void checkLoginSpecName(String loginSpecName) {
+ if ((loginSpecName == null) || (loginSpecName.length() == 0)) {
+ throw new IllegalArgumentException();
+ }
+ if (this.containsLoginSpecNamed(loginSpecName)) {
+ throw new IllegalArgumentException("duplicate login spec name: " + loginSpecName);
+ }
+ }
+
+ /**
+ * disallow duplicate table names
+ */
+ void checkTableName(String catalog, String schema, String shortName, ELTable table) {
+ this.checkTableNameQualifier(catalog);
+ this.checkTableNameQualifier(schema);
+ if ((shortName == null) || (shortName.length() == 0)) {
+ throw new IllegalArgumentException();
+ }
+ ELTable match = this.tableNamed(catalog, schema, shortName);
+ if (match != null) {
+ throw new IllegalArgumentException("duplicate table name: " + match.qualifiedName());
+ }
+ ELTable matchIgnoreCase = this.tableNamedIgnoreCase(catalog, schema, shortName);
+ if ((matchIgnoreCase != null) && (matchIgnoreCase != table)) {
+ throw new IllegalArgumentException("duplicate table name: " + matchIgnoreCase.qualifiedName());
+ }
+ }
+
+ /**
+ * table qualifiers must be null or non-empty
+ */
+ private void checkTableNameQualifier(String qualifier) {
+ if (qualifier == null) {
+ return;
+ }
+ if (qualifier.length() == 0) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+
+ // ********** model synchronization **********
+
+ @Override
+ protected void addChildrenTo(List<Node> children) {
+ super.addChildrenTo(children);
+ synchronized (this.loginSpecs) { children.addAll(this.loginSpecs); }
+ children.add(this.deploymentLoginSpecHandle);
+ children.add(this.developmentLoginSpecHandle);
+ synchronized (this.tables) { children.addAll(this.tables); }
+ }
+
+ private void loginSpecRemoved(ELLoginSpec loginSpec) {
+ if (this.getDeploymentLoginSpec() == loginSpec) {
+ this.setDeploymentLoginSpec(null);
+ }
+ if (this.getDevelopmentLoginSpec() == loginSpec) {
+ this.setDevelopmentLoginSpec(null);
+ }
+ }
+
+ /**
+ * performance tuning: override this method and assume
+ * the database's descendants have NO references (handles)
+ * to any models other than other descendants of the database
+ */
+ @Override
+ public void nodeRemoved(Node node) {
+ if (node.isDescendantOf(this)) {
+ super.nodeRemoved(node);
+ }
+ }
+
+ /**
+ * performance tuning: override this method and assume
+ * the database's descendants have NO references (handles)
+ * to any models other than other descendants of the database
+ */
+ @Override
+ public void nodeRenamed(Node node) {
+ if (node.isDescendantOf(this)) {
+ super.nodeRenamed(node);
+ // we handle a renamed table directly in #tableRenamed()
+ }
+ }
+
+ // ********** login/logout **********
+
+ /**
+ * you must log in before accessing the connection or
+ * schema manager;
+ * we instantiate and connect the JDBC Driver manually, ignoring
+ * the stupid JDBC DriverManager;
+ * this method is not called when executing under jdev
+ */
+ public void login() throws SQLException, ClassNotFoundException {
+ if (this.isConnected()) {
+ throw new IllegalStateException("already connected");
+ }
+ ELLoginSpec loginSpec = this.getDevelopmentLoginSpec();
+ if (loginSpec == null) {
+ throw new IllegalStateException("missing development login spec");
+ }
+
+ try {
+ this.driver = loginSpec.buildDriver();
+ } catch (InstantiationException ex) {
+ throw new RuntimeException(ex);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex);
+ }
+
+ String url = loginSpec.getURL();
+ if ((url == null) || (url.length() == 0)) {
+ throw new IllegalStateException("missing database URL");
+ }
+
+ // store the user name and password in a dictionary
+ Properties props = new Properties();
+ String userName = loginSpec.getUserName();
+ if (userName != null) {
+ props.put("user", userName);
+ }
+ String password = loginSpec.getPassword();
+ if (password != null) {
+ props.put("password", password);
+ }
+
+ this.connection = this.driver.connect(url, props);
+
+ // once we are connected we can build the schema manager
+ this.schemaManager = this.buildSchemaManager();
+ this.firePropertyChanged(CONNECTED_PROPERTY, false, true);
+ }
+
+ /**
+ * disconnect from the database and clear out any state that relies
+ * on the connection;
+ * this method is not called when executing under jdev
+ */
+ public void logout() throws SQLException {
+ if ( ! this.isConnected()) {
+ throw new IllegalStateException("not connected");
+ }
+ this.connection.close();
+ this.schemaManager = null;
+ this.connection = null;
+ this.driver = null;
+ this.externalDatabase = null;
+ this.firePropertyChanged(CONNECTED_PROPERTY, true, false);
+ }
+
+ private SchemaManager buildSchemaManager() {
+ return new SchemaManager(this.buildRuntimeDatabaseSession());
+ }
+
+ /**
+ * this db session will use the *development* login spec;
+ * this method is not called when executing under jdev
+ */
+ private DatabaseSession buildRuntimeDatabaseSession() {
+ DatabaseSession session = this.buildRuntimeProject().createDatabaseSession();
+ session.dontLogMessages();
+ session.login();
+ return session;
+ }
+
+ /**
+ * this project will use the *development* login spec
+ * this method is not called when executing under jdev
+ */
+ private Project buildRuntimeProject() {
+ return new Project(this.getDevelopmentLoginSpec().buildDevelopmentRuntimeDatabaseLogin());
+ }
+
+ /**
+ * build a connector that will use the database's connection;
+ * this method is not called when executing under jdev
+ */
+ Connector buildRuntimeConnector() {
+ return new LocalConnectorAdapter(this.connection);
+ }
+
+
+ // ********** table importing/refreshing **********
+
+ /**
+ * Returns the "catalog" names from the current database.
+ * @see java.sql.DatabaseMetaData#getCatalogs()
+ */
+ public Iterator<String> catalogNames() {
+ return new ArrayIterator<String>(this.getExternalDatabase().getCatalogNames());
+ }
+
+ /**
+ * Returns the "schema" names from the current database.
+ * @see java.sql.DatabaseMetaData#getSchemas()
+ */
+ public Iterator<String> schemaNames() {
+ if (!getDatabasePlatform().getName().equals("MySQL")) {
+ return new ArrayIterator<String>(this.getExternalDatabase().getSchemaNames());
+ } else {
+ return new ArrayIterator<String>(this.getExternalDatabase().getCatalogNames());
+ }
+ }
+
+ /**
+ * Returns the "table type" names from the current database.
+ * @see java.sql.DatabaseMetaData#getTableTypes()
+ */
+ public Iterator<String> tableTypeNames() {
+ return new ArrayIterator<String>(this.getExternalDatabase().getTableTypeNames());
+ }
+
+ /**
+ * Returns the "external" table descriptions corresponding to the specified
+ * search criteria; these can then be used to import and/or refresh tables
+ * @see #externalTableDescriptions()
+ * @see #importQualifiedTablesFor(java.util.Collection)
+ * @see #importUnqualifiedTablesFor(java.util.Collection)
+ * @see #refreshQualifiedTablesFor(java.util.Collection)
+ * @see java.sql.DatabaseMetaData#getTables(String, String, String, String[])
+ */
+ public Iterator<ExternalTableDescription> externalTableDescriptions(String catalog, String schemaPattern, String tableNamePattern, String[] types) {
+ return new ArrayIterator<ExternalTableDescription>(
+ this.getExternalDatabase().getTableDescriptions(catalog, schemaPattern, tableNamePattern, types)
+ );
+ }
+
+ /**
+ * Returns the all the "external" table descriptions;
+ * these can then be used to import and/or refresh tables
+ * @see #externalTableDescriptions(String, String, String, String[])
+ * @see #importQualifiedTablesFor(java.util.Collection)
+ * @see #importUnqualifiedTablesFor(java.util.Collection)
+ * @see #refreshQualifiedTablesFor(java.util.Collection)
+ */
+ public Iterator<ExternalTableDescription> externalTableDescriptions() {
+ return new ArrayIterator<ExternalTableDescription>(
+ this.getExternalDatabase().getTableDescriptions()
+ );
+ }
+
+ /**
+ * import the tables corresponding to the specified
+ * "external" table descriptions, using their fully-qualified names;
+ * this is a two-step process: all the fields must be in place before
+ * we can build or refresh the references
+ */
+ public void importQualifiedTablesFor(Collection<ExternalTableDescription> externalTableDescriptions) {
+ for (Iterator<ExternalTableDescription> stream = externalTableDescriptions.iterator(); stream.hasNext(); ) {
+ ExternalTableDescription externalTableDescription = stream.next();
+ this.qualifiedTableFor(externalTableDescription).refreshColumns(externalTableDescription.getTable());
+ }
+ for (Iterator<ExternalTableDescription> stream = externalTableDescriptions.iterator(); stream.hasNext(); ) {
+ ExternalTableDescription externalTableDescription = stream.next();
+ this.qualifiedTableFor(externalTableDescription).refreshReferences(externalTableDescription.getTable());
+ }
+ }
+
+ /**
+ * refresh the tables corresponding to the specified "external" table descriptions, using their fully
+ * qualified names; this is a two-step process: all the fields must be in place before
+ * we can refresh the references;
+ * we want different behavior here because we don't want to
+ * create them if they don't exist and we must handle unqualified tables
+ */
+ public void refreshQualifiedTablesFor(Collection<ExternalTableDescription> externalTableDescriptions) {
+ for (Iterator<ExternalTableDescription> stream = externalTableDescriptions.iterator(); stream.hasNext(); ) {
+ ExternalTableDescription externalTableDescription = stream.next();
+ ELTable tableToRefresh = this.tableNamed(externalTableDescription.getQualifiedName());
+ if (tableToRefresh == null) {
+ // the table's name may be unqualified
+ tableToRefresh = this.tableNamed(externalTableDescription.getName());
+ }
+ if (tableToRefresh != null) {
+ tableToRefresh.refreshColumns(externalTableDescription.getTable());
+ }
+ }
+ for (Iterator<ExternalTableDescription> stream = externalTableDescriptions.iterator(); stream.hasNext(); ) {
+ ExternalTableDescription externalTableDescription = stream.next();
+ ELTable tableToRefresh = this.tableNamed(externalTableDescription.getQualifiedName());
+ if (tableToRefresh == null) {
+ // the table's name may be unqualified
+ tableToRefresh = this.tableNamed(externalTableDescription.getName());
+ }
+ if (tableToRefresh != null) {
+ tableToRefresh.refreshReferences(externalTableDescription.getTable());
+ }
+ }
+ }
+
+ /**
+ * Returns the table corresponding to the specified "external" table description,
+ * creating it if necessary; use the table's fully-qualified name
+ */
+ private ELTable qualifiedTableFor(ExternalTableDescription externalTableDescription) {
+ if (getDatabasePlatform().getName().equals("MySQL")) {
+ return this.tableNamedForImport(null, externalTableDescription.getCatalogName(), externalTableDescription.getName());
+ } else {
+ return this.tableNamedForImport(externalTableDescription.getCatalogName(), externalTableDescription.getSchemaName(), externalTableDescription.getName());
+ }
+ }
+
+ /**
+ * Returns the requested table, creating it if necessary
+ */
+ private ELTable tableNamedForImport(String catalog, String schema, String shortName) {
+ ELTable table = this.tableNamed(catalog, schema, shortName);
+ if (table == null) {
+ table = this.addTable(catalog, schema, shortName);
+ }
+ return table;
+ }
+
+ /**
+ * import and/or refresh the tables corresponding to the specified
+ * "external" table descriptions, using their "short" names;
+ * this is a two-step process: all the fields must be in place before
+ * we can build or refresh the references
+ */
+ public void importUnqualifiedTablesFor(Collection<ExternalTableDescription> externalTableDescriptions) {
+ for (Iterator<ExternalTableDescription> stream = externalTableDescriptions.iterator(); stream.hasNext(); ) {
+ ExternalTableDescription externalTableDescription = stream.next();
+ this.unqualifiedTableFor(externalTableDescription).refreshColumns(externalTableDescription.getTable());
+ }
+ for (Iterator<ExternalTableDescription> stream = externalTableDescriptions.iterator(); stream.hasNext(); ) {
+ ExternalTableDescription externalTableDescription = stream.next();
+ this.unqualifiedTableFor(externalTableDescription).refreshReferences(externalTableDescription.getTable());
+ }
+ }
+
+ /**
+ * Returns the table corresponding to the specified "external" table description,
+ * creating it if necessary; use the table's "short" name
+ */
+ private ELTable unqualifiedTableFor(ExternalTableDescription externalTableDescription) {
+ return this.tableNamedForImport(null, null, externalTableDescription.getName());
+ }
+
+ // ********** printing and displaying **********
+
+ public void toString(StringBuffer sb) {
+ sb.append(this.getDatabasePlatform().getName());
+ sb.append(" : ");
+ sb.append(this.tables.size());
+ sb.append(" tables");
+ }
+
+ @Override
+ public String displayString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Database (");
+ sb.append(this.getDatabasePlatform().getName());
+ sb.append(")");
+ return sb.toString();
+ }
+
+
+ // ********** SubComponentContainer implementation **********
+
+ public Iterator projectSubFileComponents() {
+ return this.tables();
+ }
+
+ public void setProjectSubFileComponents(Collection subComponents) {
+ this.tables = subComponents;
+ }
+
+ public Iterator originalProjectSubFileComponentNames() {
+ return this.tableNames.iterator();
+ }
+
+ public void setOriginalProjectSubFileComponentNames(Collection originalSubComponentNames) {
+ this.tableNames = originalSubComponentNames;
+ }
+
+ public boolean hasChangedMainProjectSaveFile() {
+ if (this.isDirty()) {
+ // the database itself is dirty
+ return true;
+ }
+ for (Iterator stream = this.children(); stream.hasNext(); ) {
+ if (this.childHasChangedTheProjectSaveFile(stream.next())) {
+ return true;
+ }
+ }
+ // the tables might be dirty
+ return false;
+ }
+
+ /**
+ * Returns whether the specified child of the database is dirty AND
+ * is written to the .mwp file
+ */
+ private boolean childHasChangedTheProjectSaveFile(Object child) {
+ if (this.tables.contains(child)) {
+ // tables are written to separate files
+ return false;
+ }
+ // the child is NOT a table,
+ // so all of its state is written to the .mwp file
+ return ((Node) child).isDirtyBranch();
+ }
+
+ // ********** inner classes **********
+
+ /**
+ * Adapt the database to the TopLink run-time Connector interface.
+ */
+ private static class LocalConnectorAdapter implements Connector {
+ private Connection connection;
+ LocalConnectorAdapter(Connection connection) {
+ super();
+ this.connection = connection;
+ }
+ /** this is the only method of note */
+ @Override
+ public Connection connect(Properties properties, Session session) {
+ return this.connection;
+ }
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException ex) {
+ throw new InternalError();
+ }
+ }
+ @Override
+ public String getConnectionDetails() {
+ return "MWDatabase.LocalConnectorAdapter";
+ }
+ @Override
+ public void toString(PrintWriter writer) {
+ writer.print(this.getConnectionDetails());
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELLoginSpec.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELLoginSpec.java
new file mode 100644
index 0000000..c633983
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELLoginSpec.java
@@ -0,0 +1,557 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Properties;
+import java.util.Vector;
+import org.eclipse.persistence.exceptions.DatabaseException;
+import org.eclipse.persistence.internal.security.JCEEncryptor;
+import org.eclipse.persistence.sessions.Connector;
+import org.eclipse.persistence.sessions.DatabaseLogin;
+import org.eclipse.persistence.sessions.Session;
+import org.eclipse.persistence.tools.db.relational.platformsmodel.DatabasePlatform;
+import org.eclipse.persistence.tools.utility.CollectionTools;
+import org.eclipse.persistence.tools.utility.StringTools;
+import org.eclipse.persistence.tools.utility.iterators.ArrayIterator;
+import org.eclipse.persistence.tools.utility.iterators.CloneListIterator;
+import org.eclipse.persistence.tools.utility.iterators.EmptyIterator;
+import org.eclipse.persistence.tools.utility.iterators.TransformationIterator;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class ELLoginSpec extends ELModel {
+
+ /** the name should never be null or empty */
+ private volatile String name;
+ public static final String NAME_PROPERTY = "name";
+
+ private volatile String driverClassName;
+ public static final String DRIVER_CLASS_NAME_PROPERTY = "driverClassName";
+ // virtual collection
+ public static final String CANDIDATE_URLS_COLLECTION = "candidateURLs";
+
+ private volatile String url;
+ public static final String URL_PROPERTY = "url";
+
+ private volatile String userName;
+ public static final String USER_NAME_PROPERTY = "userName";
+
+ private volatile String password;
+ public static final String PASSWORD_PROPERTY = "password";
+
+ private volatile boolean savePassword;
+ public static final String SAVE_PASSWORD_PROPERTY = "savePassword";
+
+ private List<String> driverClasspathEntries;
+ public static final String DRIVER_CLASSPATH_ENTRIES_LIST = "driverClasspathEntries";
+
+ /** the JDBC drivers we know about and their URLs */
+ private static Collection<DriverSpec> driverSpecs;
+
+ /** cache this - it's expensive to instantiate */
+ private static JCEEncryptor encryptor;
+
+ /** preferences */
+ public static final String DB_DRIVER_CLASS_PREFERENCE = "database driver class";
+
+ public static final String DB_CONNECTION_URL_PREFERENCE = "database connection url";
+
+ // ********** static methods **********
+
+ /**
+ * Returns the driver class names we know about
+ */
+ public static Iterator<String> commonDriverClassNames() {
+ return new TransformationIterator<String, DriverSpec>(driverSpecs()) {
+ @Override
+ protected String transform(DriverSpec next) {
+ return next.getDriverClassName();
+ }
+ };
+ }
+
+ public static int commonDriverClassNamesSize() {
+ return getDriverSpecs().size();
+ }
+
+ /**
+ * Returns the URLs typically associated with the specified
+ * driver class name
+ */
+ private static Iterator<String> urlsForDriverClassNamed(String driverClassName) {
+ DriverSpec ds = driverSpecFor(driverClassName);
+ return (ds == null) ? EmptyIterator.<String>instance() : ds.urls();
+ }
+
+ private static int urlsForDriverClassNamedSize(String driverClassName) {
+ DriverSpec ds = driverSpecFor(driverClassName);
+ return (ds == null) ? 0 : ds.urlsSize();
+ }
+
+ private static boolean urlsForDriverClassNamedContains(String driverClassName, String url) {
+ DriverSpec ds = driverSpecFor(driverClassName);
+ return (ds == null) ? false : ds.containsURL(url);
+ }
+
+ /**
+ * Returns the URL most commonly used with the specified
+ * driver class name
+ */
+ private static String defaultURLForDriverClassNamed(String driverClassName) {
+ DriverSpec ds = driverSpecFor(driverClassName);
+ return (ds == null) ? null : ds.defaultURL();
+ }
+
+ private static DriverSpec driverSpecFor(String driverClassName) {
+ for (Iterator<DriverSpec> stream = driverSpecs(); stream.hasNext(); ) {
+ DriverSpec ds = stream.next();
+ if (ds.getDriverClassName().equals(driverClassName)) {
+ return ds;
+ }
+ }
+ return null;
+ }
+
+ private static Iterator<DriverSpec> driverSpecs() {
+ return getDriverSpecs().iterator();
+ }
+
+ private synchronized static Collection<DriverSpec> getDriverSpecs() {
+ if (driverSpecs == null) {
+ driverSpecs = buildDriverSpecs();
+ }
+ return driverSpecs;
+ }
+
+ // TODO move to DatabasePlatform and store in its XML file?
+ private static Collection<DriverSpec> buildDriverSpecs() {
+ Collection<DriverSpec> specs = new ArrayList<DriverSpec>(30);
+ specs.add(new DriverSpec("com.neon.jdbc.Driver", "jdbc:neon:"));
+ specs.add(new DriverSpec("com.pointbase.jdbc.jdbcUniversalDriver", "jdbc:pointbase:"));
+ specs.add(new DriverSpec("com.sybase.jdbc3.jdbc.SybDriver", "jdbc:sybase:Tds:"));
+ specs.add(new DriverSpec("com.sybase.jdbc2.jdbc.SybDriver", "jdbc:sybase:Tds:"));
+ specs.add(new DriverSpec("com.sybase.jdbc.SybDriver", "jdbc:sybase:Tds:"));
+ specs.add(new DriverSpec("COM.ibm.db2.jdbc.app.DB2Driver", "jdbc:db2:"));
+ specs.add(new DriverSpec("COM.ibm.db2.jdbc.net.DB2Driver", "jdbc:db2:"));
+ specs.add(new DriverSpec("com.ibm.db2.jcc.DB2Driver", "jdbc:db2://"));
+ specs.add(new DriverSpec("com.mysql.jdbc.Driver", "jdbc:mysql://"));
+ specs.add(new DriverSpec("borland.jdbc.Bridge.LocalDriver", "jdbc:BorlandBridge:"));
+ specs.add(new DriverSpec("borland.jdbc.Broker.RemoteDriver", "jdbc:BorlandBridge:"));
+ specs.add(new DriverSpec("intersolv.jdbc.sequelink.SequeLinkDriver", "jdbc:sequelink:"));
+ String[] oracleURLs =
+ new String[] {
+ "jdbc:oracle:thin:@<HOST>:<PORT>:<SID>",
+ "jdbc:oracle:oci:@<HOST>:<PORT>:<SID>",
+ "jdbc:oracle:oci7:@<HOST>:<PORT>:<SID>",
+ "jdbc:oracle:oci8:@<HOST>:<PORT>:<SID>"
+ };
+ specs.add(new DriverSpec("oracle.jdbc.OracleDriver", oracleURLs));
+ specs.add(new DriverSpec("oracle.jdbc.driver.OracleDriver", oracleURLs));
+ specs.add(new DriverSpec("com.oracle.ias.jdbc.db2.DB2Driver", "jdbc:oracle:db2://"));
+ specs.add(new DriverSpec("com.oracle.ias.jdbc.sqlserver.SQLServerDriver", "jdbc:oracle:sqlserver://"));
+ specs.add(new DriverSpec("com.oracle.ias.jdbc.sybase.SybaseDriver", "jdbc:oracle:sybase://"));
+ specs.add(new DriverSpec("org.hsqldb.jdbcDriver", "jdbc:hsqldb:"));
+ specs.add(new DriverSpec("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:"));
+ specs.add(new DriverSpec("weblogic.jdbc.oci.Driver", "jdbc:weblogic:oracle:"));
+ specs.add(new DriverSpec("weblogic.jdbc.dblib.Driver", new String[] { "jdbc:weblogic:mssqlserver:", "jdbc:weblogic:sybase" }));
+ specs.add(new DriverSpec("weblogic.jdbc.informix4.Driver", "jdbc:weblogic:informix4:"));
+ specs.add(new DriverSpec("weblogic.jdbc.jts.Driver", "jdbc:weblogic:jts:"));
+ specs.add(new DriverSpec("weblogic.jdbc.mssqlserver4.Driver", "jdbc:weblogic:mssqlserver4:"));
+ specs.add(new DriverSpec("weblogic.jdbc.pool.Driver", "jdbc:weblogic:pool:"));
+ specs.add(new DriverSpec("weblogic.jdbc.t3client.Driver", "jdbc:weblogic:t3Client:"));
+ specs.add(new DriverSpec("weblogic.jdbc.t3.Driver", "jdbc:weblogic:t3:"));
+ specs.add(new DriverSpec("com.timesten.jdbc.TimesTenDriver", "jdbc:timesten:direct:<SID>"));
+ return specs;
+ }
+
+ private static JCEEncryptor getEncryptor() {
+ if (encryptor == null) {
+ try {
+ encryptor = new JCEEncryptor();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ return encryptor;
+ }
+
+
+ // ********** constructors **********
+
+ ELLoginSpec(ELDatabase database, String name) {
+ super(database);
+ this.name = name;
+ }
+
+
+ // ********** initialization **********
+
+ /**
+ * initialize persistent state
+ */
+ @Override
+ protected void initialize(Node parent) {
+ super.initialize(parent);
+ this.savePassword = false;
+ this.driverClasspathEntries = new Vector<String>();
+ }
+
+
+ // ********** accessors **********
+
+ @Override
+ public final ELDatabase getParent() {
+ return (ELDatabase)super.getParent();
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ Object old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+ public String getDriverClassName() {
+ return this.driverClassName;
+ }
+
+ public void setDriverClassName(String driverClassName) {
+ String old = this.driverClassName;
+ this.driverClassName = driverClassName;
+ this.firePropertyChanged(DRIVER_CLASS_NAME_PROPERTY, old, driverClassName);
+ if (this.attributeValueHasChanged(old, driverClassName)) {
+ // only change the URL if it is easy to re-create
+ if ((this.url == null) || urlsForDriverClassNamedContains(old, this.url)) {
+ this.setURL(defaultURLForDriverClassNamed(driverClassName));
+ }
+ }
+ }
+
+ public String getURL() {
+ return this.url;
+ }
+
+ public void setURL(String url) {
+ Object old = this.url;
+ this.url = url;
+ this.firePropertyChanged(URL_PROPERTY, old, url);
+ }
+
+ public String getUserName() {
+ return this.userName;
+ }
+
+ public void setUserName(String userName) {
+ Object old = this.userName;
+ this.userName = userName;
+ this.firePropertyChanged(USER_NAME_PROPERTY, old, userName);
+ }
+
+ public String getPassword() {
+ return this.password;
+ }
+
+ public void setPassword(String password) {
+ Object old = this.password;
+ this.password = password;
+ this.firePropertyChanged(PASSWORD_PROPERTY, old, password);
+ }
+
+ public boolean isSavePassword() {
+ return this.savePassword;
+ }
+
+ public void setSavePassword(boolean savePassword) {
+ boolean old = this.savePassword;
+ this.savePassword = savePassword;
+ this.firePropertyChanged(SAVE_PASSWORD_PROPERTY, old, savePassword);
+ }
+
+
+ /* NOTE: Driver classpath entries are Strings */
+
+ public ListIterator<String> driverClasspathEntries() {
+ return new CloneListIterator<String>(this.driverClasspathEntries);
+ }
+
+ public int driverClasspathEntriesSize() {
+ return this.driverClasspathEntries.size();
+ }
+
+ public String getDriverClasspathEntry(int index) {
+ return this.driverClasspathEntries.get(index);
+ }
+
+ public void addDriverClasspathEntry(int index, String entry) {
+ this.addItemToList(index, entry, this.driverClasspathEntries, DRIVER_CLASSPATH_ENTRIES_LIST);
+ }
+
+ public void addDriverClasspathEntry(String entry) {
+ this.addDriverClasspathEntry(this.driverClasspathEntriesSize(), entry);
+ }
+
+ public void addDriverClasspathEntries(int index, List<String> entries) {
+ this.addItemsToList(index, entries, this.driverClasspathEntries, DRIVER_CLASSPATH_ENTRIES_LIST);
+ }
+
+ public void addDriverClasspathEntries(List<String> entries) {
+ this.addDriverClasspathEntries(this.driverClasspathEntriesSize(), entries);
+ }
+
+ public void addDriverClasspathEntries(ListIterator<String> entries) {
+ this.addDriverClasspathEntries(CollectionTools.list(entries));
+ }
+
+ public String removeDriverClasspathEntry(int index) {
+ return this.removeItemFromList(index, this.driverClasspathEntries, DRIVER_CLASSPATH_ENTRIES_LIST);
+ }
+
+ public List<String> removeDriverClasspathEntries(int index, int length) {
+ return this.removeItemsFromList(index, length, this.driverClasspathEntries, DRIVER_CLASSPATH_ENTRIES_LIST);
+ }
+
+ public String replaceDriverClasspathEntry(int index, String newEntry) {
+ return this.setItemInList(index, newEntry, this.driverClasspathEntries, DRIVER_CLASSPATH_ENTRIES_LIST);
+ }
+
+
+ // ********** queries **********
+
+ public String defaultURL() {
+ return defaultURLForDriverClassNamed(this.driverClassName);
+ }
+
+ public Iterator<String> candidateURLs() {
+ return urlsForDriverClassNamed(this.driverClassName);
+ }
+
+ public int candidateURLsSize() {
+ return urlsForDriverClassNamedSize(this.driverClassName);
+ }
+
+ // ********** behavior **********
+
+ Driver buildDriver() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ if ((this.driverClassName == null) || (this.driverClassName.length() == 0)) {
+ throw new IllegalStateException("missing database driver class name");
+ }
+ // we should be able to load the driver with only a minimum classpath
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ Class<?> driverClass = Class.forName(this.driverClassName, true, classLoader);
+ return (Driver) driverClass.newInstance();
+ }
+
+ /**
+ * Returns a TopLink runtime connector for the spec's driver.
+ */
+ public Connector buildConnector() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ return new MWConnector(this.buildDriver(), this.getURL());
+ }
+
+
+ // ********** runtime conversion **********
+
+ private DatabasePlatform databasePlatform() {
+ return this.getParent().getDatabasePlatform();
+ }
+
+ /**
+ * this is used to log in to the database in the UI
+ */
+ DatabaseLogin buildDevelopmentRuntimeDatabaseLogin() {
+ DatabaseLogin login = this.buildRuntimeDatabaseLogin();
+ login.setConnector(this.getParent().buildRuntimeConnector());
+ return login;
+ }
+
+ /**
+ * this is used to generate deployment XML
+ */
+ DatabaseLogin buildDeploymentRuntimeDatabaseLogin() {
+ DatabaseLogin login = this.buildRuntimeDatabaseLogin();
+ if ( ! this.savePassword) {
+ login.setPassword(null);
+ }
+ return login;
+ }
+
+ private DatabaseLogin buildRuntimeDatabaseLogin() {
+ DatabaseLogin login = new DatabaseLogin();
+
+ login.setDriverClassName(this.driverClassName);
+ login.setDriverURLHeader(StringTools.EMPTY_STRING);
+ login.setDatabaseURL(this.url);
+ login.setUserName(this.userName);
+ login.setPassword(this.password);
+
+ login.setPlatformClassName(this.databasePlatform().getRuntimePlatformClassName());
+
+ return login;
+ }
+
+
+ // ********** displaying and printing **********
+
+ public void toString(StringBuffer sb) {
+ sb.append(this.name);
+ }
+
+ @Override
+ public String displayString() {
+ return this.name;
+ }
+
+
+ // ********** TopLink methods **********
+ @SuppressWarnings("unused")
+ private String getPasswordForTopLink() {
+ return (this.savePassword) ? this.encryptedPassword() : null;
+ }
+
+ private String encryptedPassword() {
+ return (this.password == null) ? null : getEncryptor().encryptPassword(password);
+ }
+
+ @SuppressWarnings("unused")
+ private void setPasswordForTopLink(String password) {
+ this.password = (password == null) ? null : getEncryptor().decryptPassword(password);
+ }
+
+ /**
+ * passwords were not encrypted in 4.5 and earlier
+ */
+ @SuppressWarnings("unused")
+ private void legacySetPasswordForTopLink(String password) {
+ this.password = password;
+ }
+
+ /**
+ * Pair popular JDBC drivers with the typical URLs used
+ * with them.
+ */
+ // TODO need a better class name
+ private static final class DriverSpec {
+ private String driverClassName;
+ private String[] urls;
+
+ DriverSpec(String driverClassName, String[] urls) {
+ super();
+ if ((driverClassName == null) || (driverClassName.length() == 0)) {
+ throw new IllegalArgumentException();
+ }
+ this.driverClassName = driverClassName;
+ if ((urls == null) || (urls.length == 0)) {
+ throw new IllegalArgumentException();
+ }
+ this.urls = urls;
+ }
+
+ DriverSpec(String driverClassName, String url) {
+ this(driverClassName, new String[] {url});
+ }
+
+ public String getDriverClassName() {
+ return this.driverClassName;
+ }
+
+ public Iterator<String> urls() {
+ return new ArrayIterator<String>(this.urls);
+ }
+
+ public int urlsSize() {
+ return this.urls.length;
+ }
+
+ public boolean containsURL(String url) {
+ for (int i = this.urls.length; i-- > 0; ) {
+ if (this.urls[i].equals(url)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String defaultURL() {
+ return this.urls[0];
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.driverClassName);
+ }
+ }
+
+ /**
+ * Implement a TopLink runtime Connector that ignores the JDBC
+ * DriverManager and uses a specified JDBC Driver. This allows us
+ * to load Drivers dynamically without worrying about which class
+ * loader loaded the driver and whether it is the same class loader
+ * that loaded the driver's client.
+ *
+ * @see java.sql.DriverManager
+ */
+ private static class MWConnector implements Connector {
+ private Driver driver;
+ private String url;
+
+ public MWConnector(Driver driver, String url) {
+ super();
+ this.driver = driver;
+ this.url = url;
+ }
+
+ @Override
+ public Connection connect(Properties properties, Session session) {
+ try {
+ return this.driver.connect(this.url, properties);
+ } catch (SQLException ex) {
+ throw DatabaseException.sqlException(ex);
+ }
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ }
+ catch (Exception exception) {
+ throw new InternalError("clone failed");
+ }
+ }
+
+ @Override
+ public String getConnectionDetails() {
+ return "MWConnector: " + this.url;
+ }
+
+ @Override
+ public void toString(PrintWriter writer) {
+ writer.println(this.getConnectionDetails());
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELLoginSpecHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELLoginSpecHandle.java
new file mode 100644
index 0000000..649d4da
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELLoginSpecHandle.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import org.eclipse.persistence.tools.db.relational.handles.MWHandle;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * <code>ELLoginSpecHandle</code> is used to isolate the painful bits of code necessary to correctly
+ * handle references to {@link ELLoginSpec} objects. Since a {@link ELLoginSpec} is nested within
+ * the XML file for a MWDatabase, we need to store a reference to a particular login spec as
+ * - the name of the login spec
+ * <p>
+ * This causes no end of pain when dealing with TopLink, property change listeners, backward-
+ * compatibility, etc.
+ * <p>
+ * NB: Currently this class is only used by MWDatabase. The model synchronization is performed
+ * locally by that class since it holds the child collection of login specs ('loginSpecs') as well
+ * as thereferences to them ('deploymentLoginSpec' and 'developmentLoginSpec'). If this handle is
+ * ever used in another place in the model, the model synchronization will need to cascade to all
+ * model objects
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class ELLoginSpecHandle extends MWHandle {
+
+ /**
+ * This is the actual login spec.
+ * It is built from the login spec name, below.
+ */
+ private volatile ELLoginSpec loginSpec;
+
+ /**
+ * The login spec name is transient. It is used only to hold its value
+ * until #postProjectBuild() is called and we can resolve
+ * the actual login spec. We do not keep it in synch with the login spec
+ * itself because we cannot know when the login spec has been renamed etc.
+ */
+ private volatile String loginSpecName;
+
+ // ********** constructors **********
+
+ /**
+ * default constructor - for TopLink use only
+ */
+ @SuppressWarnings("unused")
+ private ELLoginSpecHandle() {
+ super();
+ }
+
+ ELLoginSpecHandle(ELDatabase parent, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ }
+
+ ELLoginSpecHandle(ELDatabase parent, ELLoginSpec loginSpec, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ this.loginSpec = loginSpec;
+ }
+
+
+ // ********** instance methods **********
+
+ ELLoginSpec getLoginSpec() {
+ return this.loginSpec;
+ }
+
+ void setLoginSpec(ELLoginSpec loginSpec) {
+ this.loginSpec = loginSpec;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Node node() {
+ return getLoginSpec();
+ }
+
+ public ELLoginSpecHandle setScrubber(NodeReferenceScrubber scrubber) {
+ this.setScrubberInternal(scrubber);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void toString(StringBuffer sb) {
+ if (this.loginSpec == null) {
+ sb.append("null");
+ } else {
+ this.loginSpec.toString(sb);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELModel.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELModel.java
new file mode 100644
index 0000000..d950547
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELModel.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.persistence.tools.utility.CollectionTools;
+import org.eclipse.persistence.tools.utility.node.AbstractNode;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * @version 2.5
+ */
+public abstract class ELModel extends AbstractNode
+ implements ELNode {
+
+ // ********** constructors **********
+
+ /**
+ * Every object (except MWProject) must have a parent.
+ * Use this constructor to create a new object - the default
+ * constructor should only be used by TopLink.
+ * @see #initialize(Node)
+ */
+ protected ELModel(ELNode parent) {
+ super(parent);
+ }
+
+
+ // ********** convenience methods **********
+
+ /**
+ * Returns the object's parent in the containment hierarchy.
+ * Every object except the MWProject will have a parent.
+ */
+ // TODO this can be renamed to getParent() when we move to jdk 1.5
+ @Override
+ public final ELNode getMWParent() {
+ return (ELNode) getParent();
+ }
+
+ // ********** model synchronization support **********
+
+ /**
+ * Convenience method.
+ * Remove the specified node from the specified bound collection,
+ * firing the appropriate change event if necessary and
+ * launching the cascading #nodeRemoved() mechanism.
+ * Returns true if the collection changed - @see java.util.Collection.remove(Object).
+ */
+ protected boolean removeNodeFromCollection(Node node, Collection collection, String collectionName) {
+ boolean changed = this.removeItemFromCollection(node, collection, collectionName);
+ return changed;
+ }
+
+ /**
+ * Convenience method.
+ * Remove the specified node from the specified collection
+ * and launch the cascading #nodeRemoved() mechanism.
+ * No change event is fired.
+ * Returns true if the collection changed - @see java.util.Collection.remove(Object).
+ */
+ protected boolean removeNodeFromCollection(Node node, Collection collection) {
+ boolean changed = collection.remove(node);
+ return changed;
+ }
+
+ /**
+ * Convenience method.
+ * Remove the specified nodes from the specified bound collection,
+ * firing the appropriate change event if necessary and
+ * launching the cascading #nodeRemoved() mechanism.
+ * Returns true if the collection changed - @see java.util.Collection.remove(Object).
+ */
+ protected boolean removeNodesFromCollection(Collection nodes, Collection collection, String collectionName) {
+ return this.removeNodesFromCollection(nodes.iterator(), collection, collectionName);
+ }
+
+ /**
+ * Convenience method.
+ * Remove the specified nodes from the specified bound collection,
+ * firing the appropriate change event if necessary,
+ * and launch the cascading #nodeRemoved() mechanism.
+ * Returns true if the collection changed - @see java.util.Collection.remove(Object).
+ */
+ protected boolean removeNodesFromCollection(Iterator nodes, Collection collection, String collectionName) {
+ Collection removedNodes = CollectionTools.collection(nodes);
+ removedNodes.retainAll(collection);
+ boolean changed = this.removeItemsFromCollection(nodes, collection, collectionName);
+ return changed;
+ }
+
+ /**
+ * Convenience method.
+ * Remove the specified nodes from the specified collection
+ * and launch the cascading #nodeRemoved() mechanism.
+ * No change event is fired.
+ * Returns true if the collection changed - @see java.util.Collection.remove(Object).
+ */
+ protected boolean removeNodesFromCollection(Collection nodes, Collection collection) {
+ return this.removeNodesFromCollection(nodes.iterator(), collection);
+ }
+
+ /**
+ * Convenience method.
+ * Remove the specified nodes from the specified collection
+ * and launch the cascading #nodeRemoved() mechanism.
+ * No change event is fired.
+ * Returns true if the collection changed - @see java.util.Collection.remove(Object).
+ */
+ protected boolean removeNodesFromCollection(Iterator nodes, Collection collection) {
+ Collection removedNodes = CollectionTools.collection(nodes);
+ removedNodes.retainAll(collection);
+ boolean changed = collection.removeAll(removedNodes);
+ return changed;
+ }
+
+ /**
+ * Convenience method.
+ * Clear the specified collection, firing the appropriate change event
+ * if necessary and launching the cascading #nodeRemoved() mechanism.
+ */
+ protected void clearNodeCollection(Collection nodeCollection, String collectionName) {
+ Collection removedNodes = new ArrayList(nodeCollection);
+ this.clearCollection(nodeCollection, collectionName);
+ }
+
+ /**
+ * Convenience method.
+ * Clear the specified collection and launch the cascading #nodeRemoved()
+ * mechanism.
+ * No change event is fired.
+ */
+ protected void clearNodeCollection(Collection nodeCollection) {
+ Collection removedNodes = new ArrayList(nodeCollection);
+ nodeCollection.clear();
+ }
+
+ /**
+ * Convenience method.
+ * Remove the node specified by index from the specified bound list,
+ * firing the appropriate change event if necessary and
+ * launching the cascading #nodeRemoved() mechanism.
+ * Returns the removed object - @see java.util.List.remove(int).
+ */
+ protected Object removeNodeFromList(int index, List nodeList, String listName) {
+ Node removedNode = (Node) this.removeItemFromList(index, nodeList, listName);
+ return removedNode;
+ }
+
+ /**
+ * Convenience method.
+ * Remove the node specified by index from the specified list
+ * and launch the cascading #nodeRemoved() mechanism.
+ * No change event is fired.
+ * Returns the removed object - @see java.util.List.remove(int).
+ */
+ protected Object removeNodeFromList(int index, List list) {
+ Node removedNode = (Node) list.remove(index);
+ return removedNode;
+ }
+
+ /**
+ * Convenience method.
+ * Clear the specified list, firing the appropriate change event if necessary
+ * and launching the cascading #nodeRemoved() mechanism.
+ */
+ protected void clearNodeList(List nodeList, String listName) {
+ Collection removedNodes = new ArrayList(nodeList);
+ this.clearList(nodeList, listName);
+ }
+
+ /**
+ * Convenience method.
+ * Clear the specified list and launch the cascading #nodeRemoved() mechanism.
+ * No change event is fired.
+ */
+ protected void clearNodeList(List nodeList) {
+ // since no events thrown, same as for collection
+ this.clearNodeCollection(nodeList);
+ }
+
+ // ********** display methods **********
+
+ /**
+ * Returns something useful for the UI.
+ */
+ @Override
+ public String displayString() {
+ // the default is to use the developer-friendly string...
+ return this.toString();
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELNode.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELNode.java
new file mode 100644
index 0000000..ce3da52
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELNode.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ *
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @version 2.5
+ */
+public interface ELNode extends Node {
+
+ ELNode getMWParent();
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELReference.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELReference.java
new file mode 100644
index 0000000..5941071
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELReference.java
@@ -0,0 +1,365 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.persistence.tools.db.relational.handles.MWHandle;
+import org.eclipse.persistence.tools.db.relational.handles.MWTableHandle;
+import org.eclipse.persistence.tools.db.relational.handles.MWHandle.NodeReferenceScrubber;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKey;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKeyColumnPair;
+import org.eclipse.persistence.tools.utility.CollectionTools;
+import org.eclipse.persistence.tools.utility.iterators.CloneIterator;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * A reference describes a foreign-key relationship from a "source" table (the reference's "parent")
+ * to a "target" table. The foreign-key constraint can either be real ("on database") or virtual
+ * (only implied by the joins performed by TopLink).
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class ELReference extends ELModel {
+
+ /** the name should never be null or empty */
+ private volatile String name;
+ public static final String NAME_PROPERTY = "name";
+
+ private MWTableHandle targetTableHandle;
+ public static final String TARGET_TABLE_PROPERTY = "targetTable";
+
+ private Collection<ELColumnPair> columnPairs;
+ public static final String COLUMN_PAIRS_COLLECTION = "columnPairs";
+
+ /**
+ * indicate whether the reference is an actual database constraint or
+ * only used by TopLink for joining
+ */
+ private volatile boolean onDatabase;
+ public static final String ON_DATABASE_PROPERTY = "onDatabase";
+
+ // ********** constructors **********
+
+ ELReference(ELTable parent, String name, ELTable targetTable) {
+ super(parent);
+ this.name = name;
+ this.targetTableHandle.setTable(targetTable);
+ }
+
+
+ // ********** initialization **********
+
+ /**
+ * initialize persistent state
+ */
+ @Override
+ protected void initialize(Node parent) {
+ super.initialize(parent);
+ this.targetTableHandle = new MWTableHandle(this, this.buildTargetTableScrubber());
+ this.columnPairs = new Vector<ELColumnPair>();
+ this.onDatabase = false;
+ }
+
+
+ // ********** accessors **********
+
+ public ELTable getSourceTable() {
+ return (ELTable) this.getParent();
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.getSourceTable().checkReferenceName(name);
+ Object old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+ public ELTable getTargetTable() {
+ return this.targetTableHandle.getTable();
+ }
+
+ /**
+ * if the target table changes, we clear out all the
+ * column pairs, because they are now invalid
+ */
+ public void setTargetTable(ELTable targetTable) {
+ Object old = this.targetTableHandle.getTable();
+ this.targetTableHandle.setTable(targetTable);
+ this.firePropertyChanged(TARGET_TABLE_PROPERTY, old, targetTable);
+ if (this.attributeValueHasChanged(old, targetTable)) {
+ this.clearColumnPairs();
+ }
+ }
+
+ public boolean isOnDatabase() {
+ return this.onDatabase;
+ }
+
+ public void setOnDatabase(boolean onDatabase) {
+ boolean old = this.onDatabase;
+ this.onDatabase = onDatabase;
+ this.firePropertyChanged(ON_DATABASE_PROPERTY, old, onDatabase);
+ }
+
+ // ********** column pairs
+ public Iterator<ELColumnPair> columnPairs() {
+ return new CloneIterator<ELColumnPair>(this.columnPairs) {
+ @Override
+ protected void remove(ELColumnPair current) {
+ ELReference.this.removeColumnPair(current);
+ }
+ };
+ }
+
+ public int columnPairsSize() {
+ return this.columnPairs.size();
+ }
+
+ public ELColumnPair addColumnPair(ELColumn sourceColumn, ELColumn targetColumn) {
+ if (sourceColumn.getTable() != this.getSourceTable()) {
+ throw new IllegalArgumentException("invalid source column: " + sourceColumn);
+ }
+ if (targetColumn.getTable() != this.getTargetTable()) {
+ throw new IllegalArgumentException("invalid target column: " + targetColumn);
+ }
+ return this.addColumnPair(new ELColumnPair(this, sourceColumn, targetColumn));
+ }
+
+ private ELColumnPair addColumnPair(ELColumnPair columnPair) {
+ this.addItemToCollection(columnPair, this.columnPairs, COLUMN_PAIRS_COLLECTION);
+ return columnPair;
+ }
+
+ public void removeColumnPair(ELColumnPair columnPair) {
+ this.removeItemFromCollection(columnPair, this.columnPairs, COLUMN_PAIRS_COLLECTION);
+ }
+
+ public void removeColumnPairs(Iterator pairs) {
+ while (pairs.hasNext()) {
+ this.removeColumnPair((ELColumnPair) pairs.next());
+ }
+ }
+
+ public void removeColumnPairs(Collection pairs) {
+ this.removeColumnPairs(pairs.iterator());
+ }
+
+ private void clearColumnPairs() {
+ for (Iterator stream = this.columnPairs(); stream.hasNext(); ) {
+ stream.next();
+ stream.remove();
+ }
+ }
+
+ /**
+ * used by MWColumnPairHandle
+ */
+ public ELColumnPair columnPairNamed(String columnPairName) {
+ synchronized (this.columnPairs) {
+ for (Iterator stream = this.columnPairs.iterator(); stream.hasNext(); ) {
+ ELColumnPair pair = (ELColumnPair) stream.next();
+ if (pair.getName().equals(columnPairName)) {
+ return pair;
+ }
+ }
+ }
+ return null;
+ }
+
+ public ELColumnPair columnPairFor(ELColumn sourceColumn, ELColumn targetColumn) {
+ synchronized (this.columnPairs) {
+ for (Iterator stream = this.columnPairs.iterator(); stream.hasNext(); ) {
+ ELColumnPair pair = (ELColumnPair) stream.next();
+ if (pair.pairs(sourceColumn, targetColumn)) {
+ return pair;
+ }
+ }
+ }
+ return null;
+ }
+
+
+ // ********** queries **********
+
+ /**
+ * this test is not entirely accurate, but it's close enough...
+ */
+ public boolean isForeignKeyReference() {
+ return ! this.isPrimaryKeyReference();
+ }
+
+ /**
+ * Returns whether the reference is a JOIN between the
+ * primary keys on the source table with the primary keys
+ * on the target table
+ */
+ public boolean isPrimaryKeyReference() {
+ Collection sourcePrimaryKeys = CollectionTools.collection(this.getSourceTable().primaryKeyColumns());
+ if (sourcePrimaryKeys.size() != this.columnPairs.size()) {
+ return false;
+ }
+
+ Collection targetPrimaryKeys = CollectionTools.collection(this.getTargetTable().primaryKeyColumns());
+ if (targetPrimaryKeys.size() != this.columnPairs.size()) {
+ return false;
+ }
+
+ synchronized (this.columnPairs) {
+ for (Iterator stream = this.columnPairs.iterator(); stream.hasNext(); ) {
+ ELColumnPair pair = (ELColumnPair) stream.next();
+ if ( ! sourcePrimaryKeys.remove(pair.getSourceColumn())) {
+ return false;
+ }
+ if ( ! targetPrimaryKeys.remove(pair.getTargetColumn())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+
+ // ********** model synchronization support **********
+
+ @Override
+ protected void addChildrenTo(List children) {
+ super.addChildrenTo(children);
+ children.add(this.targetTableHandle);
+ synchronized (this.columnPairs) { children.addAll(this.columnPairs); }
+ }
+
+ private NodeReferenceScrubber buildTargetTableScrubber() {
+ return new NodeReferenceScrubber() {
+ @Override
+ public void nodeReferenceRemoved(Node node, MWHandle handle) {
+ ELReference.this.setTargetTable(null);
+ }
+ @Override
+ public String toString() {
+ return "MWReference.buildTargetTableScrubber()";
+ }
+ };
+ }
+
+
+ // ********** importing/refreshing **********
+
+ /**
+ * the reference has the same name as the specified "external" foreign key,
+ * synchronize the reference's column pairs with the "external" foreign key's column pairs
+ */
+ void refreshColumnPairs(ExternalForeignKey externalForeignKey) {
+ // after we have looped through the "external" column pairs,
+ // 'removedColumnPairs' will be left with the column pairs that need to be removed
+ Collection removedColumnPairs;
+ synchronized (this.columnPairs) {
+ removedColumnPairs = new HashSet(this.columnPairs);
+ }
+ ExternalForeignKeyColumnPair[] externalPairs = externalForeignKey.getColumnPairs();
+ for (int i = externalPairs.length; i-- > 0; ) {
+ this.refreshColumnPair(externalPairs[i], removedColumnPairs);
+ }
+ this.removeColumnPairs(removedColumnPairs);
+ }
+
+ private void refreshColumnPair(ExternalForeignKeyColumnPair externalPair, Collection removedColumnPairs) {
+ for (Iterator stream = removedColumnPairs.iterator(); stream.hasNext(); ) {
+ if (((ELColumnPair) stream.next()).matches(externalPair)) {
+ stream.remove();
+ return;
+ }
+ }
+ this.addColumnPair(this.sourceColumn(externalPair), this.targetColumn(externalPair));
+ }
+
+ /**
+ * Returns the column in the source table with the same name as the
+ * "external" column pair's source column
+ */
+ ELColumn sourceColumn(ExternalForeignKeyColumnPair externalPair) {
+ return this.getSourceTable().column(externalPair.getSourceColumn());
+ }
+
+ /**
+ * Returns the column in the target table with the same name as the
+ * "external" column pair's target column
+ */
+ ELColumn targetColumn(ExternalForeignKeyColumnPair externalPair) {
+ return this.getTargetTable().column(externalPair.getTargetColumn());
+ }
+
+ /**
+ * Returns whether the reference has the same column pairs as
+ * the specified "external" foreign key;
+ * we compare column pairs because some references have system-
+ * generated names that can change over the life of the reference
+ * and we don't want to remove a reference simply because its
+ * name changes - this would force the user to rebuild any objects
+ * that referenced the [mistakenly] removed reference, e.g. mappings
+ */
+ boolean matchesColumnPairs(ExternalForeignKey externalForeignKey) {
+ ExternalForeignKeyColumnPair[] externalPairs = externalForeignKey.getColumnPairs();
+ int externalPairsLength = externalPairs.length;
+ if (this.columnPairs.size() != externalPairsLength) {
+ return false;
+ }
+ Collection columnPairsCopy;
+ synchronized (this.columnPairs) {
+ columnPairsCopy = new HashSet(this.columnPairs);
+ }
+ for (int i = externalPairsLength; i-- > 0; ) {
+ ExternalForeignKeyColumnPair externalPair = externalPairs[i];
+ boolean match = false;
+ for (Iterator stream = columnPairsCopy.iterator(); stream.hasNext(); ) {
+ if (((ELColumnPair) stream.next()).matches(externalPair)) {
+ stream.remove();
+ match = true;
+ break;
+ }
+ }
+ if ( ! match) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // ********** displaying and printing **********
+
+ @Override
+ public String displayString() {
+ return this.name;
+ }
+
+ public void toString(StringBuffer sb) {
+ sb.append(this.name);
+ sb.append(" : ");
+ this.printTableNameOn(this.getSourceTable(), sb);
+ sb.append("=>");
+ this.printTableNameOn(this.getTargetTable(), sb);
+ }
+
+ private void printTableNameOn(ELTable table, StringBuffer sb) {
+ sb.append((table == null) ? "null" : table.getName());
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELTable.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELTable.java
new file mode 100644
index 0000000..ef0479f
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/ELTable.java
@@ -0,0 +1,702 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.persistence.tools.db.relational.platformsmodel.DatabasePlatform;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalColumn;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKey;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKeyColumnPair;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalTable;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription;
+import org.eclipse.persistence.tools.utility.NameTools;
+import org.eclipse.persistence.tools.utility.StringTools;
+import org.eclipse.persistence.tools.utility.iterators.CloneIterator;
+import org.eclipse.persistence.tools.utility.iterators.CompositeIterator;
+import org.eclipse.persistence.tools.utility.iterators.FilteringIterator;
+import org.eclipse.persistence.tools.utility.iterators.TransformationIterator;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class ELTable extends ELModel {
+
+ /** the catalog should never be empty - it can be null, but not empty */
+ private volatile String catalog;
+ public static final String CATALOG_PROPERTY = "catalog";
+
+ /** the schema should never be empty - it can be null, but not empty */
+ private volatile String schema;
+ public static final String SCHEMA_PROPERTY = "schema";
+
+ /** the short name should never be null OR empty */
+ private volatile String shortName;
+ public static final String SHORT_NAME_PROPERTY = "shortName";
+
+ public static final String QUALIFIED_NAME_PROPERTY = "qualifiedName";
+
+ /** this will be null if it is not known */
+ private Date lastRefreshTimestamp;
+ public static final String LAST_REFRESH_TIMESTAMP_PROPERTY = "lastRefreshTimestamp";
+
+ private Collection<ELColumn> columns;
+ public static final String COLUMNS_COLLECTION = "columns";
+
+ private Collection<ELReference> references;
+ public static final String REFERENCES_COLLECTION = "references";
+
+ private boolean legacyIsFullyQualified;
+
+ // ********** constructors **********
+
+ ELTable(ELDatabase database, String catalog, String schema, String shortName) {
+ super(database);
+ this.catalog = catalog;
+ this.schema = schema;
+ this.shortName = shortName;
+ }
+
+
+ // ********** initialization **********
+
+ /**
+ * initialize persistent state
+ */
+ @Override
+ protected void initialize(Node parent) {
+ super.initialize(parent);
+ this.lastRefreshTimestamp = null; // if the table is built by hand, this is left null
+ this.columns = new Vector<ELColumn>();
+ this.references = new Vector<ELReference>();
+ }
+
+
+ // ********** name: catalog, schema, shortName **********
+
+ public String getCatalog() {
+ return this.catalog;
+ }
+
+ /**
+ * private - @see #rename(String, String, String)
+ */
+ private void setCatalog(String catalog) {
+ Object old = this.catalog;
+ this.catalog = catalog;
+ if (this.attributeValueHasChanged(old, catalog)) {
+ this.firePropertyChanged(CATALOG_PROPERTY, old, catalog);
+ this.qualifiedNameChanged();
+ }
+ }
+
+ public String getSchema() {
+ return this.schema;
+ }
+
+ /**
+ * private - @see #rename(String, String, String)
+ */
+ private void setSchema(String schema) {
+ Object old = this.schema;
+ this.schema = schema;
+ if (this.attributeValueHasChanged(old, schema)) {
+ this.firePropertyChanged(SCHEMA_PROPERTY, old, schema);
+ this.qualifiedNameChanged();
+ }
+ }
+
+ public String getShortName() {
+ return this.shortName;
+ }
+
+ /**
+ * private - @see #rename(String, String, String)
+ */
+ private void setShortName(String shortName) {
+ Object old = this.shortName;
+ this.shortName = shortName;
+ if (this.attributeValueHasChanged(old, shortName)) {
+ this.firePropertyChanged(SHORT_NAME_PROPERTY, old, shortName);
+ this.qualifiedNameChanged();
+ }
+ }
+
+ private void qualifiedNameChanged() {
+ this.firePropertyChanged(QUALIFIED_NAME_PROPERTY, this.qualifiedName());
+ this.getParent().nodeRenamed(this);
+ for (Iterator<ELColumn> stream = this.columns(); stream.hasNext(); ) {
+ stream.next().qualifiedNameChanged();
+ }
+ }
+
+
+ // ********** columns **********
+
+ /**
+ * this will be null if it is not known
+ */
+ public Date getLastRefreshTimestamp() {
+ return this.lastRefreshTimestamp;
+ }
+
+ /**
+ * PRIVATE - this can only be set internally
+ */
+ private void setLastRefreshTimestamp(Date lastRefreshTimestamp) {
+ Object old = this.lastRefreshTimestamp;
+ this.lastRefreshTimestamp = lastRefreshTimestamp;
+ this.firePropertyChanged(LAST_REFRESH_TIMESTAMP_PROPERTY, old, lastRefreshTimestamp);
+ }
+
+
+ // ********** columns **********
+
+ public Iterator<ELColumn> columns() {
+ return new CloneIterator<ELColumn>(this.columns) {
+ @Override
+ protected void remove(ELColumn current) {
+ ELTable.this.removeColumn(current);
+ }
+ };
+ }
+
+ public int columnsSize() {
+ return this.columns.size();
+ }
+
+ public ELColumn addColumn(String name) {
+ this.checkColumnName(name);
+ return this.addColumn(new ELColumn(this, name));
+ }
+
+ private ELColumn addColumn(ELColumn column) {
+ this.addItemToCollection(column, this.columns, COLUMNS_COLLECTION);
+ return column;
+ }
+
+ public void removeColumn(ELColumn column) {
+ this.removeNodeFromCollection(column, this.columns, COLUMNS_COLLECTION);
+ }
+
+ public void removeColumns(Iterator<ELColumn> cols) {
+ while (cols.hasNext()) {
+ this.removeColumn(cols.next());
+ }
+ }
+
+ public void removeColumns(Collection<ELColumn> cols) {
+ this.removeColumns(cols.iterator());
+ }
+
+ public boolean containsColumnNamed(String columnName) {
+ return this.columnNamed(columnName) != null;
+ }
+
+ /**
+ * only used for unqualified column names
+ * @see #columnWithQualifiedName(String qualifiedName)
+ */
+ public ELColumn columnNamed(String unqualifiedColumnName) {
+ synchronized (this.columns) {
+ for (Iterator<ELColumn> stream = this.columns.iterator(); stream.hasNext(); ) {
+ ELColumn column = stream.next();
+ if (column.getName().equals(unqualifiedColumnName)) {
+ return column;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the column with the specified "qualified" name
+ */
+ public ELColumn columnWithQualifiedName(String name) {
+ if ( ! ELColumn.parseTableNameFromQualifiedName(name).equals(this.getName())) {
+ throw new IllegalArgumentException();
+ }
+ return this.columnNamed(ELColumn.parseColumnNameFromQualifiedName(name));
+ }
+
+ public Iterator<String> columnNames() {
+ return new TransformationIterator<String, ELColumn>(this.columns()) {
+ @Override
+ protected String transform(ELColumn next) {
+ return next.getName();
+ }
+ };
+ }
+
+ public int primaryKeyColumnsSize() {
+ int size = 0;
+ synchronized (this.columns) {
+ for (ELColumn column : this.columns) {
+ if (column.isPrimaryKey()) {
+ size++;
+ }
+ }
+ }
+ return size;
+ }
+
+ public Iterator<ELColumn> primaryKeyColumns() {
+ return new FilteringIterator<ELColumn>(this.columns()) {
+ @Override
+ protected boolean accept(ELColumn o) {
+ return o.isPrimaryKey();
+ }
+ };
+ }
+
+ public Iterator<String> primaryKeyColumnNames() {
+ return new TransformationIterator<String, ELColumn>(this.primaryKeyColumns()) {
+ @Override
+ protected String transform(ELColumn next) {
+ return next.getName();
+ }
+ };
+ }
+
+ public Iterator<ELColumn> nonPrimaryKeyColumns() {
+ return new FilteringIterator<ELColumn>(this.columns()) {
+ @Override
+ protected boolean accept(ELColumn o) {
+ return ! o.isPrimaryKey();
+ }
+ };
+ }
+
+ /**
+ * used by table generation
+ */
+ public ELColumn addColumnLike(ELColumn original) {
+ ELColumn copy = this.addColumn(original.getName());
+ copy.copySettingsFrom(original);
+ return copy;
+ }
+
+
+ // ********** references **********
+
+ public Iterator<ELReference> references() {
+ return new CloneIterator<ELReference>(this.references) {
+ @Override
+ protected void remove(ELReference current) {
+ ELTable.this.removeReference(current);
+ }
+ };
+ }
+
+ public int referencesSize() {
+ return this.references.size();
+ }
+
+ public ELReference addReference(String name, ELTable targetTable) {
+ this.checkReferenceName(name);
+ return this.addReference(new ELReference(this, name, targetTable));
+ }
+
+ private ELReference addReference(ELReference reference) {
+ this.addItemToCollection(reference, this.references, REFERENCES_COLLECTION);
+ return reference;
+ }
+
+ public void removeReference(ELReference reference) {
+ this.removeNodeFromCollection(reference, this.references, REFERENCES_COLLECTION);
+ }
+
+ public void removeReferences(Iterator<ELReference> refs) {
+ while (refs.hasNext()) {
+ this.removeReference(refs.next());
+ }
+ }
+
+ public void removeReferences(Collection<ELReference> refs) {
+ this.removeReferences(refs.iterator());
+ }
+
+ /**
+ * remove only the references among those specified
+ * that are defined on the database; leave any "virtual"
+ * user-defined references
+ */
+ private void removeDatabaseReferences(Iterator<ELReference> refs) {
+ while (refs.hasNext()) {
+ ELReference ref = refs.next();
+ if (ref.isOnDatabase()) {
+ this.removeReference(ref);
+ }
+ }
+ }
+
+ /**
+ * remove only the references among those specified
+ * that are defined on the database; leave any "virtual"
+ * user-defined references
+ */
+ private void removeDatabaseReferences(Collection<ELReference> refs) {
+ this.removeDatabaseReferences(refs.iterator());
+ }
+
+ public boolean containsReferenceNamed(String referenceName) {
+ return this.referenceNamed(referenceName) != null;
+ }
+
+ public ELReference referenceNamed(String referenceName) {
+ synchronized (this.references) {
+ for (Iterator<ELReference> stream = this.references.iterator(); stream.hasNext(); ) {
+ ELReference reference = stream.next();
+ if (reference.getName().equals(referenceName)) {
+ return reference;
+ }
+ }
+ return null;
+ }
+ }
+
+ public Iterator<String> referenceNames(){
+ return new TransformationIterator<String, ELReference>(this.references()) {
+ @Override
+ protected String transform(ELReference next) {
+ return next.getName();
+ }
+ };
+ }
+
+ /**
+ * Returns the references that are actually present
+ * as constraints on the database
+ */
+ public Iterator<ELReference> databaseReferences() {
+ return new FilteringIterator<ELReference>(this.references()) {
+ @Override
+ protected boolean accept(ELReference o) {
+ return o.isOnDatabase();
+ }
+ };
+ }
+
+ /**
+ * Returns all the references between the table and the
+ * specified table (either table can be the source and/or target)
+ */
+ @SuppressWarnings("unchecked")
+ public Iterator<ELReference> referencesBetween(ELTable table) {
+ return new CompositeIterator<ELReference>(
+ this.referencesTo(table),
+ table.referencesTo(this)
+ );
+ }
+
+ /**
+ * Returns all the references with the table as the source and the
+ * specified table as the target
+ */
+ public Iterator<ELReference> referencesTo(final ELTable targetTable) {
+ return new FilteringIterator<ELReference>(this.references()) {
+ @Override
+ protected boolean accept(ELReference o) {
+ return o.getTargetTable() == targetTable;
+ }
+ };
+ }
+
+
+ // ********** Nominative implementation **********
+
+ /**
+ * Returns the appropriately-qualified name
+ */
+ public String getName() {
+ return this.qualifiedName();
+ }
+
+ // ********** queries **********
+
+ public DatabasePlatform databasePlatform() {
+ return this.getParent().getDatabasePlatform();
+ }
+
+ boolean nameMatches(String cat, String sch, String sn) {
+ return this.valuesAreEqual(this.catalog, cat) &&
+ this.valuesAreEqual(this.schema, sch) &&
+ this.valuesAreEqual(this.shortName, sn);
+ }
+
+ boolean nameMatchesIgnoreCase(String cat, String sch, String sn) {
+ return StringTools.stringsAreEqualIgnoreCase(this.catalog, cat) &&
+ StringTools.stringsAreEqualIgnoreCase(this.schema, sch) &&
+ StringTools.stringsAreEqualIgnoreCase(this.shortName, sn);
+ }
+
+ /**
+ * if either the 'catalog' or 'schema' are specified,
+ * the table's name is "qualified"
+ */
+ public boolean nameIsQualified() {
+ if (this.catalog != null) {
+ return true;
+ }
+ if (this.schema != null) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean nameIsUnqualified() {
+ return ! this.nameIsQualified();
+ }
+
+ public String qualifiedName() {
+ return NameTools.buildQualifiedDatabaseObjectName(this.catalog, this.schema, this.shortName);
+ }
+
+ public String unqualifiedName() {
+ return this.shortName;
+ }
+
+ /**
+ * used for table generation:
+ * catalog.schema
+ * catalog.
+ * schema
+ */
+ private String qualifier() {
+ if (this.nameIsUnqualified()) {
+ return StringTools.EMPTY_STRING;
+ }
+ StringBuffer sb = new StringBuffer(100);
+ if (this.catalog != null) {
+ sb.append(this.catalog);
+ }
+ if (this.schema != null) {
+ if (this.catalog != null) {
+ sb.append('.');
+ }
+ sb.append(this.schema);
+ }
+ return sb.toString();
+ }
+
+
+ // ********** miscellaneous behavior **********
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ELDatabase getParent() {
+ return (ELDatabase)super.getParent();
+ }
+
+ @Override
+ protected void addChildrenTo(List<Node> children) {
+ super.addChildrenTo(children);
+ synchronized (this.columns) { children.addAll(this.columns); }
+ synchronized (this.references) { children.addAll(this.references); }
+ }
+
+ public void rename(String newCatalog, String newSchema, String newShortName) {
+ if (this.nameMatches(newCatalog, newSchema, newShortName)) {
+ // if someone is tryng to rename a table to its existing name, ignore it
+ return;
+ }
+ this.getParent().checkTableName(newCatalog, newSchema, newShortName, this);
+ this.setCatalog(newCatalog);
+ this.setSchema(newSchema);
+ this.setShortName(newShortName);
+ }
+
+ /**
+ * disallow duplicate column names
+ */
+ void checkColumnName(String columnName) {
+ if ((columnName == null) || (columnName.length() == 0)) {
+ throw new IllegalArgumentException();
+ }
+ if (this.containsColumnNamed(columnName)) {
+ throw new IllegalArgumentException("duplicate column name: " + columnName);
+ }
+ }
+
+ /**
+ * disallow duplicate reference names
+ */
+ void checkReferenceName(String referenceName) {
+ if ((referenceName == null) || (referenceName.length() == 0)) {
+ throw new IllegalArgumentException();
+ }
+ if (this.containsReferenceNamed(referenceName)) {
+ throw new IllegalArgumentException("duplicate reference name: " + referenceName);
+ }
+ }
+
+ void databasePlatformChanged() {
+ synchronized (this.columns) {
+ for (Iterator<ELColumn> stream = this.columns.iterator(); stream.hasNext(); ) {
+ stream.next().databasePlatformChanged();
+ }
+ }
+ }
+
+
+ // ********** importing/refreshing **********
+
+ /**
+ * Returns the "external" table descriptions that share the table's name;
+ * Returns multiple entries only when the table's name
+ * is unqualified
+ */
+ public Iterator<ExternalTableDescription> matchingExternalTableDescriptions() {
+ return this.getParent().externalTableDescriptions(this.catalog, this.schema, this.shortName, null);
+ }
+
+ /**
+ * refresh the table's columns (but not the table's references - that
+ * must be performed separately);
+ */
+ void refreshColumns(ExternalTable externalTable) {
+ // after we have looped through the external columns,
+ // 'removedColumns' will be left with the columns that need to be removed
+ Collection<ELColumn> removedColumns;
+ synchronized (this.columns) {
+ removedColumns = new HashSet<ELColumn>(this.columns);
+ }
+ ExternalColumn[] externalColumns = externalTable.getColumns();
+ for (int i = externalColumns.length; i-- > 0; ) {
+ this.refreshColumn(externalColumns[i], removedColumns);
+ }
+ this.removeColumns(removedColumns);
+ this.setLastRefreshTimestamp(new Date());
+ }
+
+ /**
+ * refresh the column corresponding to the specified "external" column
+ */
+ private void refreshColumn(ExternalColumn externalColumn, Collection<ELColumn> removedColumns) {
+ ELColumn existingColumn = this.columnNamed(externalColumn.getName());
+ if (existingColumn == null) {
+ // we have a new column
+ existingColumn = this.addColumn(externalColumn.getName());
+ } else {
+ // retain the existing column
+ removedColumns.remove(existingColumn);
+ }
+ existingColumn.refresh(externalColumn);
+ }
+
+ /**
+ * refresh the table's references - this should be called after
+ * the table's columns have been refreshed and any target tables
+ * have had their columns refreshed - this will allow us to build
+ * the references properly
+ */
+ void refreshReferences(ExternalTable externalTable) {
+ // after we have looped through the foreign keys,
+ // 'removedReferences' will be left with the references that need to be removed
+ Collection<ELReference> removedReferences;
+ synchronized (this.references) {
+ removedReferences = new HashSet<ELReference>(this.references);
+ }
+ ExternalForeignKey[] externalForeignKeys = externalTable.getForeignKeys();
+ for (int i = externalForeignKeys.length; i-- > 0; ) {
+ this.refreshReference(externalForeignKeys[i], removedReferences);
+ }
+
+ // remove *only* the remaining references that were originally defined on the database;
+ // leave the "virtual" user-defined references intact
+ this.removeDatabaseReferences(removedReferences);
+ }
+
+ /**
+ * refresh the reference corresponding to the specified "external" foreign key;
+ * search the 'removedReferences' so that we don't ever
+ * refresh the same reference twice; first search for a match based
+ * on name, then search for a match based on the column pairs - this
+ * should prevent us from getting a match based on columns that has
+ * the same name as another reference with different columns that
+ * is further down the list
+ */
+ private void refreshReference(ExternalForeignKey externalForeignKey, Collection<ELReference> removedReferences) {
+ // first, find the target table
+ ExternalTableDescription ttd = externalForeignKey.getTargetTableDescription();
+ ELTable targetTable = this.getParent().tableNamed(ttd.getCatalogName(), ttd.getSchemaName(), ttd.getName());
+ if (targetTable == null) {
+ // the target table may have been imported without
+ // a fully-qualified name, so try that also
+ targetTable = this.getParent().tableNamed(null, null, ttd.getName());
+ }
+ // if we don't have the target table, we can't build a reference to it
+ if (targetTable == null) {
+ return;
+ }
+
+ // look for a match based on name
+ for (Iterator<ELReference> stream = removedReferences.iterator(); stream.hasNext(); ) {
+ ELReference ref = stream.next();
+ if (ref.getName().equals(externalForeignKey.getName())) {
+ ref.setTargetTable(targetTable);
+ ref.refreshColumnPairs(externalForeignKey);
+ ref.setOnDatabase(true);
+ removedReferences.remove(ref);
+ return;
+ }
+ }
+
+ // look for a match based on column pairs
+ for (Iterator<ELReference> stream = removedReferences.iterator(); stream.hasNext(); ) {
+ ELReference ref = stream.next();
+ if (ref.matchesColumnPairs(externalForeignKey)) {
+ ref.setName(externalForeignKey.getName());
+ ref.setTargetTable(targetTable);
+ ref.setOnDatabase(true);
+ removedReferences.remove(ref);
+ return;
+ }
+ }
+
+ // no match - we have a new reference
+ ELReference ref = this.addReference(externalForeignKey.getName(), targetTable);
+ ExternalForeignKeyColumnPair[] pairs = externalForeignKey.getColumnPairs();
+ for (int i = pairs.length; i-- > 0; ) {
+ ref.addColumnPair(this.column(pairs[i].getSourceColumn()), targetTable.column(pairs[i].getTargetColumn()));
+ }
+ ref.setOnDatabase(true);
+ }
+
+ /**
+ * Returns the column with the same name as the specified "external" column
+ */
+ ELColumn column(ExternalColumn externalColumn) {
+ return (externalColumn == null) ? null : this.columnNamed(externalColumn.getName());
+ }
+
+ // ********** printing and displaying **********
+
+ public void toString(StringBuffer sb) {
+ sb.append(this.qualifiedName());
+ }
+
+ @Override
+ public String displayString() {
+ return this.qualifiedName();
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/NodeModel.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/NodeModel.java
new file mode 100644
index 0000000..9f12393
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/NodeModel.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational;
+
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * Some nodes are models....
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @version 2.5
+ */
+public interface NodeModel extends Node {
+ // no additional behavior
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWColumnHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWColumnHandle.java
new file mode 100644
index 0000000..49729c7
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWColumnHandle.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.handles;
+
+import org.eclipse.persistence.tools.db.relational.ELColumn;
+import org.eclipse.persistence.tools.db.relational.ELModel;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * MWColumnHandle is used to isolate the painful bits of code
+ * necessary to correctly handle references to MWColumns.
+ * Since a MWColumn is nested within the XML file
+ * for a MWTable, we need to store a reference to a particular
+ * column as a pair of instance variables:
+ * - the name of the containing table
+ * - the name of the column
+ *
+ * This causes no end of pain when dealing with TopLink, property
+ * change listeners, backward-compatibility, etc.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class MWColumnHandle extends MWHandle {
+
+ /**
+ * This is the actual column.
+ * It is built from the table and column names, below.
+ */
+ private volatile ELColumn column;
+
+ /**
+ * The table and column names are transient. They
+ * are used only to hold their values until postProjectBuild()
+ * is called and we can resolve the actual column.
+ * We do not keep these in synch with the column itself because
+ * we cannot know when the column has been renamed etc.
+ */
+ private volatile String columnTableName;
+ private volatile String columnName;
+
+ // ********** constructors **********
+
+ /**
+ * default constructor - for TopLink use only
+ */
+ @SuppressWarnings("unused")
+ private MWColumnHandle() {
+ super();
+ }
+
+ public MWColumnHandle(ELModel parent, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ }
+
+ public MWColumnHandle(ELModel parent, ELColumn column, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ this.column = column;
+ }
+
+
+ // ********** instance methods **********
+
+ public ELColumn getColumn() {
+ return this.column;
+ }
+
+ public void setColumn(ELColumn column) {
+ this.column = column;
+ }
+
+ @Override
+ protected Node node() {
+ return this.getColumn();
+ }
+
+ @Override
+ public void toString(StringBuffer sb) {
+ if (this.column == null) {
+ sb.append("null");
+ } else {
+ this.column.toString(sb);
+ }
+ }
+
+ public MWColumnHandle setScrubber(NodeReferenceScrubber scrubber) {
+ this.setScrubberInternal(scrubber);
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWColumnPairHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWColumnPairHandle.java
new file mode 100644
index 0000000..11b05ca
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWColumnPairHandle.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.handles;
+
+import org.eclipse.persistence.tools.db.relational.ELColumnPair;
+import org.eclipse.persistence.tools.db.relational.ELModel;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * MWColumnPairHandle is used to isolate the painful bits of code
+ * necessary to correctly handle references to MWColumnPairs.
+ * Since a MWColumnPair is nested within the XML file
+ * for a MWTable, we need to store a reference to a particular
+ * column pair as a list of instance variables:
+ * - the name of the containing table
+ * - the name of the containing reference
+ * - the name of the column pair
+ *
+ * This causes no end of pain when dealing with TopLink, property
+ * change listeners, backward-compatibility, etc.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class MWColumnPairHandle extends MWHandle {
+
+ /**
+ * This is the actual column pair.
+ * It is built from the table, reference, and column pair names, below.
+ */
+ private volatile ELColumnPair columnPair;
+
+ /**
+ * The table, reference, and column pair names are transient. They
+ * are used only to hold their values until #postProjectBuild()
+ * is called and we can resolve the actual column pair.
+ * We do not keep these in synch with the column pair itself because
+ * we cannot know when the column pair has been renamed etc.
+ */
+ private volatile String tableName;
+ private volatile String referenceName;
+ private volatile String columnPairName;
+
+ // ********** constructors **********
+
+ /**
+ * default constructor - for TopLink use only
+ */
+ private MWColumnPairHandle() {
+ super();
+ }
+
+ public MWColumnPairHandle(ELModel parent, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ }
+
+ public MWColumnPairHandle(ELModel parent, ELColumnPair columnPair, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ this.columnPair = columnPair;
+ }
+
+
+ // ********** instance methods **********
+
+ public ELColumnPair getColumnPair() {
+ return this.columnPair;
+ }
+
+ public void setColumnPair(ELColumnPair columnPair) {
+ this.columnPair = columnPair;
+ }
+
+ @Override
+ protected Node node() {
+ return this.getColumnPair();
+ }
+
+ @Override
+ public void toString(StringBuffer sb) {
+ if (this.columnPair == null) {
+ sb.append("null");
+ } else {
+ this.columnPair.toString(sb);
+ }
+ }
+
+ public MWColumnPairHandle setScrubber(NodeReferenceScrubber scrubber) {
+ this.setScrubberInternal(scrubber);
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWHandle.java
new file mode 100644
index 0000000..f6e5a02
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWHandle.java
@@ -0,0 +1,462 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.handles;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.persistence.tools.db.relational.ELNode;
+import org.eclipse.persistence.tools.utility.iterators.EmptyIterator;
+import org.eclipse.persistence.tools.utility.model.listener.ChangeListener;
+import org.eclipse.persistence.tools.utility.model.listener.CollectionChangeListener;
+import org.eclipse.persistence.tools.utility.model.listener.ListChangeListener;
+import org.eclipse.persistence.tools.utility.model.listener.PropertyChangeListener;
+import org.eclipse.persistence.tools.utility.model.listener.StateChangeListener;
+import org.eclipse.persistence.tools.utility.model.listener.TreeChangeListener;
+import org.eclipse.persistence.tools.utility.node.Node;
+import org.eclipse.persistence.tools.utility.node.Problem;
+
+/**
+ * Handles are used to isolate the painful bits of code
+ * necessary to correctly handle references to model objects.
+ *
+ * All handles should subclass this abstract class.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public abstract class MWHandle implements ELNode {
+
+
+ /** Containment hierarchy. */
+ private ELNode parent; // pseudo-final
+
+ /** This is used to synchronize the model when a node is removed. */
+ private NodeReferenceScrubber scrubber; // pseudo-final
+
+ /** A handle is dirty when the path to its node changes. */
+ private volatile boolean dirty;
+
+ // ********** constructors **********
+
+ /**
+ * default constructor - for TopLink use only
+ */
+ protected MWHandle() {
+ super();
+ // a new object is dirty, by definition
+ this.dirty = true;
+ }
+
+ protected MWHandle(ELNode parent, NodeReferenceScrubber scrubber) {
+ this();
+ this.setParent(parent);
+ this.setScrubberInternal(scrubber);
+ }
+
+
+ // ********** containment hierarchy (parent/children) **********
+
+ @Override
+ public final Node getParent() {
+ return this.parent;
+ }
+
+ /**
+ * Set the object's parent in the containment hierarchy.
+ * Most objects must have a parent.
+ */
+ public final void setParent(Node parent) {
+ if (parent == null) {
+ throw new NullPointerException();
+ }
+ this.parent = (ELNode) parent;
+ }
+
+ // handles do not have children
+ @Override
+ public final Iterator<Node> children() {
+ return EmptyIterator.instance();
+ }
+
+ // handles do not have children
+ public final void setChildBackpointers() {
+ // do nothing
+ }
+
+ @Override
+ public final boolean isDescendantOf(Node node) {
+ return (this == node) || this.parent.isDescendantOf(node);
+ }
+
+ @Override
+ public final void addBranchReferencesTo(Collection branchReferences) {
+ Node node = this.node();
+ if (node != null) {
+ branchReferences.add(new SimpleReference(this, node));
+ }
+ }
+
+ // handles do not have children
+ @Override
+ public final void addAllNodesTo(Collection nodes) {
+ nodes.add(this);
+ }
+
+
+ // ********** dirty flag support **********
+
+ @Override
+ public final boolean isDirtyBranch() {
+ return this.dirty;
+ }
+
+ @Override
+ public final void markBranchDirty() {
+ throw new IllegalStateException("handles shouldn't have children");
+ }
+
+ @Override
+ public final void markEntireBranchDirty() {
+ this.markDirty();
+ }
+
+ @Override
+ public final void cascadeMarkEntireBranchClean() {
+ this.dirty = false;
+ }
+
+ @Override
+ public final void markBranchCleanIfPossible() {
+ throw new IllegalStateException("handles shouldn't have children");
+ }
+
+ private void markDirty() {
+ this.dirty = true;
+ this.parent.markBranchDirty();
+ }
+
+
+ // ********** convenience methods **********
+
+ @Override
+ public final ELNode getMWParent() {
+ return this.parent;
+ }
+
+ // ********** model synchronization support **********
+
+ /**
+ * Returns the node referenced by the handle.
+ */
+ protected abstract Node node();
+
+ /**
+ * If the handle's node has been renamed, or it is a descendant of
+ * a node that has been renamed, the handle must mark its branch
+ * dirty so that the handle is saved with the new name.
+ */
+ @Override
+ public void nodeRenamed(Node node) {
+ if ((this.node() != null) && this.node().isDescendantOf(node)) {
+ this.markDirty();
+ }
+ }
+
+ /**
+ * If the handle's node has been removed, or it is a descendant of
+ * a node that has been removed, notify the scrubber.
+ */
+ @Override
+ public final void nodeRemoved(Node removedNode) {
+ if ((this.node() != null) && this.node().isDescendantOf(removedNode)) {
+ this.scrubber.nodeReferenceRemoved(this.node(), this);
+ }
+ }
+
+ /**
+ * Subclasses will probably implement something like
+ * #setScrubber(NodeReferenceScrubber) that returns 'this'
+ */
+ protected final void setScrubberInternal(NodeReferenceScrubber scrubber) {
+ if (scrubber == null) {
+ throw new NullPointerException();
+ }
+ this.scrubber = scrubber;
+ }
+
+
+ // ********** post-read methods **********
+
+ /**
+ * Override this method if there are objects in the hierarchy
+ * that depend on this handle being resolved before postProjectBuild().
+ * Do not override unless the handle is for a class or class sub-object
+ * (attribute, method, etc.)
+ */
+ public void resolveClassHandles() {
+ // do nothing
+ }
+
+ /**
+ * Override this method if there are objects in the hierarchy
+ * that depend on this handle being resolved before postProjectBuild().
+ * Do not override unless the handle is for a descriptor or descriptor sub-object
+ * (mapping, xml data field, etc.)
+ */
+ public void resolveDescriptorHandles() {
+ // do nothing
+ }
+
+ /**
+ * Override this method if there are objects in the hierarchy
+ * that depend on this handle being resolved before postProjectBuild().
+ * Do not override unless the handle is for a meta data object or sub-object
+ * (field, schema component, etc.)
+ */
+ public void resolveMetadataHandles() {
+ // do nothing
+ }
+
+ /**
+ * Override this method if there are objects in the hierarchy
+ * that depend on this handle being resolved before postProjectBuild().
+ * Do not override unless the handle is for a meta data object or sub-object
+ * (column, schema component, etc.)
+ */
+ public void resolveColumnHandles() {
+ // do nothing
+ }
+
+ /**
+ * Override this method if there are objects in the hierarchy
+ * that depend on this handle being resolved before postProjectBuild().
+ * Do not override unless the handle is for a meta data object or sub-object
+ * (field, schema component, etc.)
+ */
+ public void resolveReferenceHandles() {
+ // do nothing
+ }
+
+ /**
+ * Override this method if there are objects in the hierarchy
+ * that depend on this handle being resolved before postProjectBuild().
+ * Do not override unless the handle is for a meta data object or sub-object
+ * (field, schema component, etc.)
+ */
+ public void resolveMethodHandles() {
+ // do nothing
+ }
+
+ public void postProjectBuild() {
+ if (this.scrubber == null) {
+ throw new NullPointerException("This handle's 'scrubber' should have been set by its parent upon creation.");
+ }
+ }
+
+
+ // ********** display methods **********
+
+ /**
+ * handles are not displayed
+ */
+ @Override
+ public final String displayString() {
+ throw new UnsupportedOperationException();
+ }
+
+ // ********** standard methods **********
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(" (");
+ this.toString(sb);
+ sb.append(')');
+ return sb.toString();
+ }
+
+ public abstract void toString(StringBuffer sb);
+
+ // ************ Abstract, unused behavior *************
+
+ @Override
+ public Node root() {
+ return null;
+ }
+
+ @Override
+ public Validator getValidator() {
+ return null;
+ }
+
+ @Override
+ public void setValidator(Validator validator) {
+
+ }
+
+ @Override
+ public void validateBranch() {
+
+ }
+
+ @Override
+ public boolean validateBranchInternal() {
+ return false;
+ }
+
+ @Override
+ public ListIterator<Problem> branchProblems() {
+ return null;
+ }
+
+ @Override
+ public int branchProblemsSize() {
+ return 0;
+ }
+
+ @Override
+ public boolean hasBranchProblems() {
+ return false;
+ }
+
+ @Override
+ public boolean containsBranchProblem(Problem problem) {
+ return false;
+ }
+
+ @Override
+ public void rebuildBranchProblems() {
+
+ }
+
+ @Override
+ public void addBranchProblemsTo(List<Problem> branchProblems) {
+
+ }
+
+ @Override
+ public void clearAllBranchProblems() {
+
+ }
+
+ @Override
+ public boolean clearAllBranchProblemsInternal() {
+ return false;
+ }
+
+ @Override
+ public String comment() {
+ return null;
+ }
+
+ @Override
+ public void setComment(String comment) {
+
+ }
+
+ @Override
+ public void addChangeListener(ChangeListener listener) {
+
+ }
+
+ @Override
+ public void removeChangeListener(ChangeListener listener) {
+
+ }
+
+ @Override
+ public void addStateChangeListener(StateChangeListener listener) {
+
+ }
+
+ @Override
+ public void removeStateChangeListener(StateChangeListener listener) {
+
+ }
+
+ @Override
+ public void addPropertyChangeListener(String propertyName,
+ PropertyChangeListener listener) {
+
+ }
+
+ @Override
+ public void removePropertyChangeListener(String propertyName,
+ PropertyChangeListener listener) {
+ }
+
+ @Override
+ public void addCollectionChangeListener(String collectionName,
+ CollectionChangeListener listener) {
+
+ }
+
+ @Override
+ public void removeCollectionChangeListener(String collectionName,
+ CollectionChangeListener listener) {
+
+ }
+
+ @Override
+ public void addListChangeListener(String listName,
+ ListChangeListener listener) {
+ }
+
+ @Override
+ public void removeListChangeListener(String listName,
+ ListChangeListener listener) {
+ }
+
+ @Override
+ public void addTreeChangeListener(String treeName,
+ TreeChangeListener listener) {
+ }
+
+ @Override
+ public void removeTreeChangeListener(String treeName,
+ TreeChangeListener listener) {
+ }
+
+ // ********** member interface **********
+
+ /**
+ * This interface defines the method called by a handle when the node the
+ * handle references has been removed from the project. Typically the
+ * handle's parent will implement an adapter that will call the appropriate
+ * method to either remove or clear the handle. The handle itself will
+ * continue to hold the reference node - it is up to the parent to
+ * synchronize appropriately.
+ */
+ public interface NodeReferenceScrubber {
+
+ /**
+ * The specified node is no longer referenced by the specified handle.
+ */
+ void nodeReferenceRemoved(Node node, MWHandle handle);
+
+ NodeReferenceScrubber NULL_INSTANCE = new NodeReferenceScrubber() {
+ @Override
+ public void nodeReferenceRemoved(Node node, MWHandle handle) {
+ // do nothing
+ }
+ @Override
+ public String toString() {
+ return "NullReferenceScrubber";
+ }
+ };
+ }
+
+}
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWReferenceHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWReferenceHandle.java
new file mode 100644
index 0000000..38c4e89
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWReferenceHandle.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.handles;
+
+import org.eclipse.persistence.tools.db.relational.ELModel;
+import org.eclipse.persistence.tools.db.relational.ELReference;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * MWReferenceHandle is used to isolate the painful bits of code
+ * necessary to correctly handle references to MWReferences.
+ * Since a MWReference is nested within the XML file
+ * for a MWTable, we need to store a reference to a particular
+ * reference as a pair of instance variables:
+ * - the name of the containing table
+ * - the name of the reference
+ *
+ * This causes no end of pain when dealing with TopLink, property
+ * change listeners, backward-compatibility, etc.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class MWReferenceHandle extends MWHandle {
+
+ /**
+ * This is the actual reference.
+ * It is built from the table and reference names, below.
+ */
+ private volatile ELReference reference;
+
+ /**
+ * The table and reference names are transient. They
+ * are used only to hold their values until postProjectBuild()
+ * is called and we can resolve the actual reference.
+ * We do not keep these in synch with the reference itself because
+ * we cannot know when the reference has been renamed etc.
+ */
+ private volatile String referenceTableName;
+ private volatile String referenceName;
+
+ // ********** constructors **********
+
+ /**
+ * default constructor - for TopLink use only
+ */
+ @SuppressWarnings("unused")
+ private MWReferenceHandle() {
+ super();
+ }
+
+ public MWReferenceHandle(ELModel parent, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ }
+
+ public MWReferenceHandle(ELModel parent, ELReference reference, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ this.reference = reference;
+ }
+
+
+ // ********** instance methods **********
+
+ public ELReference getReference() {
+ return this.reference;
+ }
+
+ public void setReference(ELReference reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ protected Node node() {
+ return getReference();
+ }
+
+ public MWReferenceHandle setScrubber(NodeReferenceScrubber scrubber) {
+ this.setScrubberInternal(scrubber);
+ return this;
+ }
+
+ @Override
+ public void toString(StringBuffer sb) {
+ if (this.reference == null) {
+ sb.append("null");
+ } else {
+ this.reference.toString(sb);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWTableHandle.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWTableHandle.java
new file mode 100644
index 0000000..38fbe43
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/handles/MWTableHandle.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.handles;
+
+import org.eclipse.persistence.tools.db.relational.ELModel;
+import org.eclipse.persistence.tools.db.relational.ELTable;
+import org.eclipse.persistence.tools.utility.node.Node;
+
+/**
+ * MWTableHandle is used to handle a reference to a MWTable via a table name.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class MWTableHandle extends MWHandle {
+
+ /**
+ * This is the actual table.
+ * It is built from the table name, below.
+ */
+ private volatile ELTable table;
+
+ /**
+ * The table name is transient. It is used only to hold its value
+ * until postProjectBuild() is called and we can resolve
+ * the actual table. We do not keep it in synch with the table
+ * itself because we cannot know when the table has been renamed etc.
+ */
+ private volatile String tableName;
+
+ // ********** constructors **********
+
+ /**
+ * default constructor - for TopLink use only
+ */
+ @SuppressWarnings("unused")
+ private MWTableHandle() {
+ super();
+ }
+
+ public MWTableHandle(ELModel parent, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ }
+
+ public MWTableHandle(ELModel parent, ELTable table, NodeReferenceScrubber scrubber) {
+ super(parent, scrubber);
+ this.table = table;
+ }
+
+
+ // ********** instance methods **********
+
+ public ELTable getTable() {
+ return this.table;
+ }
+
+ public void setTable(ELTable table) {
+ this.table = table;
+ }
+
+ @Override
+ protected Node node() {
+ return getTable();
+ }
+
+ public MWTableHandle setScrubber(NodeReferenceScrubber scrubber) {
+ this.setScrubberInternal(scrubber);
+ return this;
+ }
+
+ @Override
+ public void toString(StringBuffer sb) {
+ if (this.table == null) {
+ sb.append("null");
+ } else {
+ this.table.toString(sb);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/AbstractJDBCTypeToJavaTypeDeclarationMapping.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/AbstractJDBCTypeToJavaTypeDeclarationMapping.java
new file mode 100644
index 0000000..21501ec
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/AbstractJDBCTypeToJavaTypeDeclarationMapping.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import org.eclipse.persistence.tools.utility.XMLTools;
+import org.eclipse.persistence.tools.utility.node.AbstractNode;
+import org.w3c.dom.Node;
+
+/**
+ * Common behavior(?).
+ * Neither instance variable should ever be null.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+abstract class AbstractJDBCTypeToJavaTypeDeclarationMapping extends AbstractNode {
+
+ JDBCType jdbcType;
+ JavaTypeDeclaration javaTypeDeclaration;
+
+ // ********** constructors **********
+
+ /**
+ * this constructor is called when the mapping is read from an XML file
+ */
+ AbstractJDBCTypeToJavaTypeDeclarationMapping(JDBCTypeRepository repository, Node node) throws CorruptXMLException {
+ super(repository);
+ this.read(node);
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new mapping (which shouldn't happen very often,
+ * since all the typical mappings have already been built...)
+ */
+ AbstractJDBCTypeToJavaTypeDeclarationMapping(JDBCTypeRepository repository, JDBCType jdbcType, String javaClassName, int arrayDepth) {
+ super(repository);
+ if (jdbcType == null) {
+ throw new NullPointerException();
+ }
+ this.jdbcType = jdbcType;
+ this.javaTypeDeclaration = new JavaTypeDeclaration(this, javaClassName, arrayDepth);
+ }
+
+
+ // ********** accessors **********
+
+ private JDBCTypeRepository getJDBCTypeRepository() {
+ return (JDBCTypeRepository) this.getParent();
+ }
+
+ public JDBCType getJDBCType() {
+ return this.jdbcType;
+ }
+
+ public JavaTypeDeclaration getJavaTypeDeclaration() {
+ return this.javaTypeDeclaration;
+ }
+
+
+ // ********** queries **********
+
+ private JDBCType jdbcTypeNamed(String jdbcTypeName) {
+ return this.getJDBCTypeRepository().jdbcTypeNamed(jdbcTypeName);
+ }
+
+
+ // ********** i/o **********
+
+ private void read(Node node) throws CorruptXMLException {
+ try {
+ this.jdbcType = this.jdbcTypeNamed(XMLTools.childTextContent(node, "jdbc-type", null));
+ } catch (IllegalArgumentException ex) {
+ throw new CorruptXMLException(ex);
+ }
+ this.javaTypeDeclaration = new JavaTypeDeclaration(this, XMLTools.child(node, "java-type-declaration"));
+ }
+
+ /**
+ * Subclasses decide the order the child nodes are written.
+ */
+ abstract void write(Node node);
+
+ void writeJDBCType(Node node) {
+ XMLTools.addSimpleTextNode(node, "jdbc-type", this.jdbcType.getName());
+ }
+
+ void writeJavaTypeDeclaration(Node node) {
+ this.javaTypeDeclaration.write(node.appendChild(node.getOwnerDocument().createElement("java-type-declaration")));
+ }
+
+ // ********** printing and displaying **********
+
+ public abstract void displayStringOn(StringBuffer sb);
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.utility.Node#displayString()
+ */
+ @Override
+ public String displayString() {
+ StringBuffer sb = new StringBuffer();
+ this.displayStringOn(sb);
+ return sb.toString();
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.utility.model.workbench.utility.AbstractModel#toString(java.lang.StringBuffer)
+ */
+ public void toString(StringBuffer sb) {
+ this.displayStringOn(sb);
+ }
+
+}
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/CorruptXMLException.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/CorruptXMLException.java
new file mode 100644
index 0000000..9553c75
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/CorruptXMLException.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+/**
+ * A CorruptFileException is thrown whenever a "corrupt" XML file is read in.
+ *
+ * @version 2.5
+ */
+public class CorruptXMLException extends Exception {
+
+ /**
+ * Construct an exception with no message.
+ */
+ public CorruptXMLException() {
+ super();
+ }
+
+ /**
+ * Construct an exception with the specified message.
+ */
+ public CorruptXMLException(String message) {
+ super(message);
+ }
+
+ /**
+ * Construct an exception chained to the specified cause.
+ */
+ public CorruptXMLException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Construct an exception with the specified message and
+ * chained to the specified cause.
+ */
+ public CorruptXMLException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/DatabasePlatform.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/DatabasePlatform.java
new file mode 100644
index 0000000..fe4933e
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/DatabasePlatform.java
@@ -0,0 +1,705 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import org.eclipse.persistence.tools.utility.CollectionTools;
+import org.eclipse.persistence.tools.utility.XMLTools;
+import org.eclipse.persistence.tools.utility.iterators.CloneIterator;
+import org.eclipse.persistence.tools.utility.iterators.TransformationIterator;
+import org.eclipse.persistence.tools.utility.node.AbstractNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * A database platform holds all the settings for a specific database platform (e.g. Oracle, MS SQL
+ * Server). This includes whether the platform supports certain features used by TopLink (e.g.
+ * native sequencing) and the various database types and their corresponding JDBC types.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class DatabasePlatform extends AbstractNode {
+
+ /**
+ * a name uniquely identifying the platform within a
+ * database platform repository
+ */
+ private String name;
+ public static final String NAME_PROPERTY = "name";
+
+ /**
+ * this is the short file name - the directory is determined
+ * by the parent repository;
+ * like the name, above, this must also be unique within the repository
+ */
+ private String shortFileName;
+ public static final String SHORT_FILE_NAME_PROPERTY = "shortFileName";
+
+ /**
+ * store this as a string (as opposed to the actual class) because users
+ * can supply their own and it might not be on the classpath
+ */
+ private String runtimePlatformClassName;
+ public static final String RUNTIME_PLATFORM_CLASS_NAME_PROPERTY = "runtimePlatformClassName";
+
+ /**
+ * whether the platform supports "native" sequencing, as opposed to
+ * using a "sequence" table
+ * (Oracle variants have SEQUENCEs; SQL Server variants have
+ * IDENTITY fields; Informix has SERIAL fields)
+ */
+ private boolean supportsNativeSequencing;
+ public static final String SUPPORTS_NATIVE_SEQUENCING_PROPERTY = "supportsNativeSequencing";
+
+ /**
+ * whether the platform supports the IDENTITY clause in a column definition
+ * (SQL Server variants only)
+ */
+ private boolean supportsIdentityClause;
+ public static final String SUPPORTS_IDENTITY_CLAUSE_PROPERTY = "supportsIdentityClause";
+
+ /**
+ * whether the platform supports returning on an update/insert natively
+ */
+ private boolean supportsNativeReturning;
+ public static final String SUPPORTS_NATIVE_RETURNING_PROPERTY = "supportsNativeReturning";
+
+ /**
+ * collection of the database platform-specific datatypes
+ * (e.g. VARCHAR2, NUMBER)
+ */
+ private Collection<DatabaseType> databaseTypes;
+ public static final String DATABASE_TYPES_COLLECTION = "databaseTypes";
+
+ /**
+ * mappings of all the JDBC types to the database platform-specific datatypes
+ * (e.g. java.sql.Types.INTEGER maps to the Oracle NUMBER)
+ */
+ private Collection<JDBCTypeToDatabaseTypeMapping> jdbcTypeToDatabaseTypeMappings;
+ public static final String JDBC_TYPE_TO_DATABASE_TYPE_MAPPINGS_COLLECTION = "jdbcTypeToDatabaseTypeMappings";
+
+ // ********** constructors **********
+
+ /**
+ * this constructor is called when the platform is read from an XML file
+ */
+ DatabasePlatform(DatabasePlatformRepository repository, File file) throws CorruptXMLException {
+ super(repository);
+ this.read(file);
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new platform (which shouldn't happen very often,
+ * since all the typical platforms have already been built and
+ * stored in XML files...)
+ */
+ DatabasePlatform(DatabasePlatformRepository repository, String name, String shortFileName) {
+ super(repository);
+ this.name = name;
+ this.shortFileName = shortFileName;
+ this.initializeJDBCTypeToDatabaseTypeMappings();
+ }
+
+
+ // ********** initialization **********
+
+ /**
+ * @see org.eclipse.persistence.tools.utility.model.workbench.utility.AbstractModel#initialize()
+ */
+ @Override
+ protected void initialize() {
+ super.initialize();
+ this.runtimePlatformClassName = this.defaultRuntimePlatformClassName();
+ this.supportsNativeSequencing = false;
+ this.supportsNativeReturning = false;
+ this.supportsIdentityClause = false;
+ this.databaseTypes = new Vector<DatabaseType>();
+ this.jdbcTypeToDatabaseTypeMappings = new Vector<JDBCTypeToDatabaseTypeMapping>();
+ }
+
+ private String defaultRuntimePlatformClassName() {
+ return "org.eclipse.persistence.platform.database.DatabasePlatform"; // this is the runtime default
+ }
+
+ /**
+ * build an empty mapping for every JDBC type in the JDBC type repository
+ */
+ private void initializeJDBCTypeToDatabaseTypeMappings() {
+ for (Iterator<JDBCType> stream = this.jdbcTypeRepository().jdbcTypes(); stream.hasNext(); ) {
+ this.jdbcTypeToDatabaseTypeMappings.add(new JDBCTypeToDatabaseTypeMapping(this, stream.next()));
+ }
+ }
+
+
+ // ********** accessors **********
+
+ public DatabasePlatformRepository getRepository() {
+ return (DatabasePlatformRepository) this.getParent();
+ }
+
+
+ // ***** name
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ if ((name != null) && name.equals(this.name)) {
+ return;
+ }
+ this.getRepository().checkPlatformName(name);
+ Object old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+
+ // ***** short file name
+ public String getShortFileName() {
+ return this.shortFileName;
+ }
+
+ public void setShortFileName(String shortFileName) {
+ if ((shortFileName != null) && shortFileName.equals(this.shortFileName)) {
+ return;
+ }
+ this.getRepository().checkPlatformShortFileName(shortFileName);
+ Object old = this.shortFileName;
+ this.shortFileName = shortFileName;
+ this.firePropertyChanged(SHORT_FILE_NAME_PROPERTY, old, shortFileName);
+ }
+
+
+ // ***** runtime platform class name
+ public String getRuntimePlatformClassName() {
+ return this.runtimePlatformClassName;
+ }
+
+ public void setRuntimePlatformClassName(String runtimePlatformClassName) {
+ if ((runtimePlatformClassName == null) || (runtimePlatformClassName.length() == 0)) {
+ throw new IllegalArgumentException("run-time platform class name is required");
+ }
+ Object old = runtimePlatformClassName;
+ this.runtimePlatformClassName = runtimePlatformClassName;
+ this.firePropertyChanged(RUNTIME_PLATFORM_CLASS_NAME_PROPERTY, old, runtimePlatformClassName);
+ }
+
+ // ***** supports native returning
+ public boolean supportsNativeReturning() {
+ return this.supportsNativeReturning;
+ }
+
+ public void setSupportsNativeReturning(boolean supportNativeReturning) {
+ boolean old = this.supportsNativeReturning;
+ this.supportsNativeReturning = supportNativeReturning;
+ this.firePropertyChanged(SUPPORTS_NATIVE_RETURNING_PROPERTY, old, supportNativeReturning);
+ }
+
+ // ***** supports native sequencing
+ public boolean supportsNativeSequencing() {
+ return this.supportsNativeSequencing;
+ }
+
+ public void setSupportsNativeSequencing(boolean supportsNativeSequencing) {
+ boolean old = this.supportsNativeSequencing;
+ this.supportsNativeSequencing = supportsNativeSequencing;
+ this.firePropertyChanged(SUPPORTS_NATIVE_SEQUENCING_PROPERTY, old, supportsNativeSequencing);
+
+ // if we don't support "native" sequencing, then we can't support the IDENTITY clause
+ if ( ! supportsNativeSequencing) {
+ this.setSupportsIdentityClause(false);
+ }
+ }
+
+
+ // ***** supports IDENTITY clause
+ public boolean supportsIdentityClause() {
+ return this.supportsIdentityClause;
+ }
+
+ public void setSupportsIdentityClause(boolean supportsIdentityClause) {
+ boolean old = this.supportsIdentityClause;
+ this.supportsIdentityClause = supportsIdentityClause;
+ this.firePropertyChanged(SUPPORTS_IDENTITY_CLAUSE_PROPERTY, old, supportsIdentityClause);
+
+ // if we support the IDENTITY clause, then we must support "native" sequencing
+ if (supportsIdentityClause) {
+ this.setSupportsNativeSequencing(true);
+ }
+ }
+
+
+ // ***** database types
+ public Iterator<DatabaseType> databaseTypes() {
+ return new CloneIterator<DatabaseType>(this.databaseTypes) {
+ @Override
+ protected void remove(DatabaseType current) {
+ DatabasePlatform.this.removeDatabaseType(current);
+ }
+ };
+ }
+
+ public int databaseTypesSize() {
+ return this.databaseTypes.size();
+ }
+
+ public DatabaseType addDatabaseType(String typeName) {
+ this.checkDatabaseTypeName(typeName);
+ return this.addDatabaseType(new DatabaseType(this, typeName));
+ }
+
+ private DatabaseType addDatabaseType(DatabaseType type) {
+ this.addItemToCollection(type, this.databaseTypes, DATABASE_TYPES_COLLECTION);
+ return type;
+ }
+
+ public void removeDatabaseType(DatabaseType type) {
+ this.removeItemFromCollection(type, this.databaseTypes, DATABASE_TYPES_COLLECTION);
+ this.databaseTypeRemoved(type);
+ }
+
+ private void databaseTypeRemoved(DatabaseType removedType) {
+ synchronized (this.jdbcTypeToDatabaseTypeMappings) {
+ for (JDBCTypeToDatabaseTypeMapping mapping : this.jdbcTypeToDatabaseTypeMappings) {
+ if (mapping.getDatabaseType() == removedType) {
+ mapping.setDatabaseType(null);
+ }
+ }
+ }
+ }
+
+ public void removeDatabaseTypes(Collection<DatabaseType> types) {
+ this.removeItemsFromCollection(types, this.databaseTypes, DATABASE_TYPES_COLLECTION);
+ this.databaseTypesRemoved(types);
+ }
+
+ private void databaseTypesRemoved(Collection<DatabaseType> removedTypes) {
+ for (DatabaseType type : removedTypes) {
+ this.databaseTypeRemoved(type);
+ }
+ }
+
+ public void removeDatabaseTypes(Iterator<DatabaseType> types) {
+ this.removeDatabaseTypes(CollectionTools.collection(types));
+ }
+
+
+ // ***** JDBC type to database type mappings
+ public Iterator<JDBCTypeToDatabaseTypeMapping> jdbcTypeToDatabaseTypeMappings() {
+ return new CloneIterator<JDBCTypeToDatabaseTypeMapping>(this.jdbcTypeToDatabaseTypeMappings);
+ }
+
+ public int jdbcTypeToDatabaseTypeMappingsSize() {
+ return this.jdbcTypeToDatabaseTypeMappings.size();
+ }
+
+ /**
+ * adding and removing mappings is PRIVATE;
+ * these are done only in response to changes to the JDBC type repository
+ */
+ private JDBCTypeToDatabaseTypeMapping addJDBCTypeToDatabaseTypeMapping(JDBCType jdbcType) {
+ return this.addJDBCTypeToDatabaseTypeMapping(new JDBCTypeToDatabaseTypeMapping(this, jdbcType));
+ }
+
+ /**
+ * adding and removing mappings is PRIVATE;
+ * these are done only in response to changes to the JDBC type repository
+ */
+ private JDBCTypeToDatabaseTypeMapping addJDBCTypeToDatabaseTypeMapping(JDBCTypeToDatabaseTypeMapping mapping) {
+ this.addItemToCollection(mapping, this.jdbcTypeToDatabaseTypeMappings, JDBC_TYPE_TO_DATABASE_TYPE_MAPPINGS_COLLECTION);
+ return mapping;
+ }
+
+ /**
+ * adding and removing mappings is PRIVATE;
+ * these are done only in response to changes to the JDBC type repository
+ */
+ private Iterator<JDBCTypeToDatabaseTypeMapping> internalJDBCTypeToDatabaseTypeMappings() {
+ return new CloneIterator<JDBCTypeToDatabaseTypeMapping>(this.jdbcTypeToDatabaseTypeMappings) {
+ @Override
+ protected void remove(JDBCTypeToDatabaseTypeMapping current) {
+ DatabasePlatform.this.removeJDBCTypeToDatabaseTypeMapping(current);
+ }
+ };
+ }
+
+ /**
+ * adding and removing mappings is PRIVATE;
+ * these are done only in response to changes to the JDBC type repository
+ */
+ void removeJDBCTypeToDatabaseTypeMapping(JDBCTypeToDatabaseTypeMapping mapping) {
+ this.removeItemFromCollection(mapping, this.jdbcTypeToDatabaseTypeMappings, JDBC_TYPE_TO_DATABASE_TYPE_MAPPINGS_COLLECTION);
+ }
+
+
+ // ********** queries **********
+
+ /**
+ * this is how a database field resolves its database type
+ * when the database field is read in from an XML file
+ */
+ public DatabaseType databaseTypeNamed(String databaseTypeName) {
+ synchronized (this.databaseTypes) {
+ for (DatabaseType databaseType : this.databaseTypes) {
+ if (databaseType.getName().equals(databaseTypeName)) {
+ return databaseType;
+ }
+ }
+ throw new IllegalArgumentException("missing database type named: "
+ + databaseTypeName + " (platform: " + this.name + ")");
+ }
+ }
+
+ public boolean containsDatabaseTypeNamed(String databaseTypeName) {
+ synchronized (this.databaseTypes) {
+ for (DatabaseType databaseType : this.databaseTypes) {
+ if (databaseType.getName().equals(databaseTypeName)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private JDBCTypeRepository jdbcTypeRepository() {
+ return this.getRepository().getJDBCTypeRepository();
+ }
+
+ private JDBCType jdbcTypeForCode(int jdbcTypeCode) {
+ return this.jdbcTypeRepository().jdbcTypeForCode(jdbcTypeCode);
+ }
+
+ JDBCType jdbcTypeNamed(String jdbcTypeName) {
+ return this.jdbcTypeRepository().jdbcTypeNamed(jdbcTypeName);
+ }
+
+ public DatabaseType defaultDatabaseType() {
+ return this.databaseTypeFor(this.jdbcTypeRepository().getDefaultJDBCType());
+ }
+
+ /**
+ * Returns the database type from "this" platform that is a reasonable
+ * facsimile of the specified database type from some "other" platform;
+ * used for converting database tables from one platform to another
+ */
+ public DatabaseType databaseTypeFor(DatabaseType otherType) {
+ // if there is a type on this platform with the exact same name, use it;
+ // the platforms might simply be variants of each other (e.g. Sybase vs. MS SQL Server)
+ try {
+ return this.databaseTypeNamed(otherType.getName());
+ } catch (IllegalArgumentException ex) {
+ // if there is no direct match, convert to a JDBC type then to a database type for this platform
+ return this.databaseTypeFor(otherType.getJDBCType());
+ }
+ }
+
+ private Iterator<String> databaseTypeNames() {
+ return new TransformationIterator<String, DatabaseType>(this.databaseTypes()) {
+ @Override
+ protected String transform(DatabaseType next) {
+ return next.getName();
+ }
+ };
+ }
+
+ /**
+ * this is only used during a read, when we are checking for duplicates
+ */
+ private boolean maps(JDBCType type) {
+ for (JDBCTypeToDatabaseTypeMapping mapping : this.jdbcTypeToDatabaseTypeMappings) {
+ if (mapping.getJDBCType() == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ // * Returns a database type for a given JDBC type or code **********
+
+ /**
+ * every platform will have every JDBC type mapped to a database type
+ */
+ private JDBCTypeToDatabaseTypeMapping jdbcTypeToDatabaseTypeMappingFor(JDBCType jdbcType) {
+ synchronized (this.jdbcTypeToDatabaseTypeMappings) {
+ for (JDBCTypeToDatabaseTypeMapping mapping : this.jdbcTypeToDatabaseTypeMappings) {
+ if (mapping.maps(jdbcType)) {
+ return mapping;
+ }
+ }
+ throw new IllegalStateException("JDBC type to database type mapping is missing: "
+ + jdbcType.getName() + " (platform: " + this.name + ")");
+ }
+ }
+
+ /**
+ * every platform will have every JDBC type mapped to a database type
+ */
+ private DatabaseType databaseTypeFor(JDBCType jdbcType) {
+ return this.jdbcTypeToDatabaseTypeMappingFor(jdbcType).getDatabaseType();
+ }
+
+ /**
+ * every platform will have every JDBC type mapped to a database type
+ */
+ public DatabaseType databaseTypeForJDBCTypeCode(int jdbcTypeCode) {
+ return this.databaseTypeFor(this.jdbcTypeForCode(jdbcTypeCode));
+ }
+
+
+ // * Returns a database type for a given Java type declaration **********
+
+ /**
+ * Returns whether the specified Java type declaration has a corresponding
+ * datatype; this can be used to determine whether a
+ * Java class can be mapped with a direct-to-field mapping
+ * (or a direct collection mapping), as opposed to needing its
+ * own descriptor
+ */
+ public boolean javaTypeDeclarationCanBeMappedToDatabaseType(String javaClassName, int arrayDepth) {
+ // if there is a JDBC type for the Java type declaration, then we have a database type...
+ return this.jdbcTypeRepository().javaTypeDeclarationCanBeMappedToJDBCType(javaClassName, arrayDepth);
+ }
+
+ /**
+ * get the JDBC type for the specified type declaration, then
+ * get the database type for that JDBC type
+ */
+ public DatabaseType databaseTypeForJavaTypeDeclaration(String javaClassName, int arrayDepth) {
+ return this.databaseTypeFor(this.jdbcTypeRepository().jdbcTypeForJavaTypeDeclaration(javaClassName, arrayDepth));
+ }
+
+
+ // ********** behavior **********
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.mappingsmodel.AbstractNodeModel#addChildrenTo(java.util.List)
+ */
+ @Override
+ protected void addChildrenTo(List<org.eclipse.persistence.tools.utility.node.Node> children) {
+ super.addChildrenTo(children);
+ synchronized (this.databaseTypes) { children.addAll(this.databaseTypes); }
+ synchronized (this.jdbcTypeToDatabaseTypeMappings) { children.addAll(this.jdbcTypeToDatabaseTypeMappings); }
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.mappingsmodel.AbstractNodeModel#nodeRemoved(org.eclipse.persistence.tools.workbench.utility.Node)
+ */
+ @Override
+ public void nodeRemoved(org.eclipse.persistence.tools.utility.node.Node node) {
+ super.nodeRemoved(node);
+ for (Iterator<JDBCTypeToDatabaseTypeMapping> stream = this.internalJDBCTypeToDatabaseTypeMappings(); stream.hasNext(); ) {
+ if (stream.next().getJDBCType() == node) {
+ stream.remove();
+ break; // there should be only one...
+ }
+ }
+ }
+
+ void jdbcTypeAdded(JDBCType newJDBCType) {
+ this.addJDBCTypeToDatabaseTypeMapping(newJDBCType);
+ }
+
+ /**
+ * copy all the settings from the original platform
+ * to this, newly-created, platform
+ */
+ void cloneFrom(DatabasePlatform originalPlatform) {
+ // the name and shortFileName have been set by the time we get here
+ this.runtimePlatformClassName = originalPlatform.getRuntimePlatformClassName();
+ this.supportsNativeSequencing = originalPlatform.supportsNativeSequencing();
+ this.supportsNativeReturning = originalPlatform.supportsNativeReturning();
+ this.supportsIdentityClause = originalPlatform.supportsIdentityClause();
+ for (Iterator<DatabaseType> stream = originalPlatform.databaseTypes(); stream.hasNext(); ) {
+ DatabaseType originalType = stream.next();
+ DatabaseType cloneType = this.addDatabaseType(originalType.getName());
+ cloneType.cloneFrom(originalType);
+ }
+ // the JDBC mappings have been pre-built by the time we get here
+ for (Iterator<JDBCTypeToDatabaseTypeMapping> stream = originalPlatform.jdbcTypeToDatabaseTypeMappings(); stream.hasNext(); ) {
+ JDBCTypeToDatabaseTypeMapping originalMapping = stream.next();
+ JDBCTypeToDatabaseTypeMapping cloneMapping = this.jdbcTypeToDatabaseTypeMappingFor(originalMapping.getJDBCType());
+ cloneMapping.cloneFrom(originalMapping);
+ }
+ }
+
+ /**
+ * disallow duplicate type names within a single platform
+ */
+ private void checkDatabaseType(DatabaseType databaseType) {
+ this.checkDatabaseTypeName(databaseType.getName());
+ }
+
+ /**
+ * disallow duplicate type names within a single platform
+ */
+ void checkDatabaseTypeName(String databaseTypeName) {
+ if ((databaseTypeName == null) || (databaseTypeName.length() == 0)) {
+ throw new IllegalArgumentException("database type name is required");
+ }
+ if (CollectionTools.contains(this.databaseTypeNames(), databaseTypeName)) {
+ throw new IllegalArgumentException("duplicate database type name: " + databaseTypeName);
+ }
+ }
+
+
+ // ********** i/o **********
+
+ // ***** read
+ private void read(File file) throws CorruptXMLException {
+ this.shortFileName = file.getName();
+ Document doc = XMLTools.parse(file);
+ Node root = XMLTools.child(doc, "database-platform");
+ if (root == null) {
+ throw new CorruptXMLException("missing root node: database-platform (" + file.getPath() + ")");
+ }
+
+ this.name = XMLTools.childTextContent(root, "name", null);
+ if ((this.name == null) || (this.name.length() == 0)) {
+ throw new CorruptXMLException("name is required (" + file.getPath() + ")");
+ }
+
+ this.runtimePlatformClassName = XMLTools.childTextContent(root, "runtime-platform-class", null);
+ if ((this.runtimePlatformClassName == null) || (this.runtimePlatformClassName.length() == 0)) {
+ throw this.buildCorruptXMLException("run-time platform class name is required");
+ }
+
+ this.supportsNativeSequencing = XMLTools.childBooleanContent(root, "supports-native-sequencing", false);
+ this.supportsNativeReturning = XMLTools.childBooleanContent(root, "supports-native-returning", false);
+ this.supportsIdentityClause = XMLTools.childBooleanContent(root, "supports-identity-clause", false);
+ if (this.supportsIdentityClause && ( ! this.supportsNativeSequencing)) {
+ throw this.buildCorruptXMLException("platform must support native sequencing if it supports the IDENTITY clause");
+ }
+
+ this.readDatabaseTypeNodes(XMLTools.child(root, "database-types"));
+
+ // wait until the database types have been read in before building the JDBC mappings
+ this.readJDBCMappingNodes(XMLTools.child(root, "jdbc-mappings"));
+ }
+
+ private void readDatabaseTypeNodes(Node databaseTypesNode) throws CorruptXMLException {
+ Node[] databaseTypeNodes = XMLTools.children(databaseTypesNode, "database-type");
+ int len = databaseTypeNodes.length;
+ for (int i = 0; i < len; i++) {
+ DatabaseType databaseType = new DatabaseType(this, databaseTypeNodes[i]);
+ try {
+ this.checkDatabaseType(databaseType); // check for duplicates
+ } catch (IllegalArgumentException ex) {
+ throw this.buildCorruptXMLException(ex);
+ }
+ this.databaseTypes.add(databaseType);
+ }
+ }
+
+ private void readJDBCMappingNodes(Node mappingsNode) throws CorruptXMLException {
+ Node[] mappingNodes = XMLTools.children(mappingsNode, "jdbc-mapping");
+ int len = mappingNodes.length;
+ for (int i = 0; i < len; i++) {
+ JDBCTypeToDatabaseTypeMapping mapping = new JDBCTypeToDatabaseTypeMapping(this, mappingNodes[i]);
+ // check for duplicates
+ if (this.maps(mapping.getJDBCType())) {
+ throw this.buildCorruptXMLException("duplicate JDBC to database type mapping: " + mapping);
+ }
+ this.jdbcTypeToDatabaseTypeMappings.add(mapping);
+ }
+ // at this point, the mappings all have legitimate JDBC types and
+ // there are no duplicates; so we just need to make sure *every* JDBC type has been mapped
+ if (this.jdbcTypeToDatabaseTypeMappings.size() != this.jdbcTypeRepository().jdbcTypesSize()) {
+ throw this.buildCorruptXMLException("missing JDBC to database type mappings (number of mappings: " + this.jdbcTypeToDatabaseTypeMappings.size()
+ + " - number of JDBC types: " + this.jdbcTypeRepository().jdbcTypesSize() + ")");
+ }
+ }
+
+ /**
+ * tack the platform on to the message
+ */
+ private CorruptXMLException buildCorruptXMLException(String message) {
+ return new CorruptXMLException(message + " (platform: " + this.name + ")");
+ }
+
+ /**
+ * tack the platform on to the message
+ */
+ private CorruptXMLException buildCorruptXMLException(Throwable t) {
+ return new CorruptXMLException("platform: " + this.name, t);
+ }
+
+ // ***** write
+ void write(File platformsDirectory) {
+ if (this.isCleanBranch()) {
+ return;
+ }
+ Document document = XMLTools.newDocument();
+ Node root = document.createElement("database-platform");
+ document.appendChild(root);
+ XMLTools.addSimpleTextNode(root, "name", this.name);
+ XMLTools.addSimpleTextNode(root, "runtime-platform-class", this.runtimePlatformClassName);
+ XMLTools.addSimpleTextNode(root, "supports-native-sequencing", this.supportsNativeSequencing, false);
+ XMLTools.addSimpleTextNode(root, "supports-native-returning", this.supportsNativeReturning, false);
+ XMLTools.addSimpleTextNode(root, "supports-identity-clause", this.supportsIdentityClause, false);
+
+ this.writeDatabaseTypeNodes(root.appendChild(document.createElement("database-types")));
+ this.writeJDBCMappingNodes(root.appendChild(document.createElement("jdbc-mappings")));
+
+ XMLTools.print(document, new File(platformsDirectory, this.shortFileName));
+ this.markEntireBranchClean();
+ }
+
+ private void writeDatabaseTypeNodes(Node databaseTypesNode) {
+ Document document = databaseTypesNode.getOwnerDocument();
+ synchronized (this.databaseTypes) {
+ for (Iterator<DatabaseType> stream = new TreeSet<DatabaseType>(this.databaseTypes).iterator(); stream.hasNext(); ) {
+ Node databaseTypeNode = document.createElement("database-type");
+ databaseTypesNode.appendChild(databaseTypeNode);
+ stream.next().write(databaseTypeNode);
+ }
+ }
+ }
+
+ private void writeJDBCMappingNodes(Node mappingsNode) {
+ Document document = mappingsNode.getOwnerDocument();
+ synchronized (this.jdbcTypeToDatabaseTypeMappings) {
+ for (Iterator<JDBCTypeToDatabaseTypeMapping> stream = new TreeSet<JDBCTypeToDatabaseTypeMapping>(this.jdbcTypeToDatabaseTypeMappings).iterator(); stream.hasNext(); ) {
+ Node mappingNode = document.createElement("jdbc-mapping");
+ mappingsNode.appendChild(mappingNode);
+ stream.next().write(mappingNode);
+ }
+ }
+ }
+
+
+ // ********** printing and displaying **********
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.utility.Node#displayString()
+ */
+ @Override
+ public String displayString() {
+ return this.name;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.utility.model.workbench.utility.AbstractModel#toString(StringBuffer)
+ */
+ public void toString(StringBuffer sb) {
+ sb.append(this.name);
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/DatabasePlatformRepository.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/DatabasePlatformRepository.java
new file mode 100644
index 0000000..c18d5a1
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/DatabasePlatformRepository.java
@@ -0,0 +1,658 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+import org.eclipse.persistence.tools.utility.CollectionTools;
+import org.eclipse.persistence.tools.utility.FileTools;
+import org.eclipse.persistence.tools.utility.HashBag;
+import org.eclipse.persistence.tools.utility.XMLTools;
+import org.eclipse.persistence.tools.utility.iterators.CloneIterator;
+import org.eclipse.persistence.tools.utility.iterators.TransformationIterator;
+import org.eclipse.persistence.tools.utility.node.AbstractNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * This is a repository of all the database platforms in the platforms resource directory. We also
+ * hold on to the JDBC type repository.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class DatabasePlatformRepository
+ extends AbstractNode
+{
+ /** something worth displaying */
+ private String name;
+ public static final String NAME_PROPERTY = "name";
+
+ /** the file that holds the platform repository settings and the JDBC type repository */
+ private File file;
+ public static final String FILE_PROPERTY = "file";
+
+ /** the database platforms */
+ private Collection<DatabasePlatform> platforms;
+ public static final String PLATFORMS_COLLECTION = "platforms";
+
+ /** the default database platform */
+ private DatabasePlatform defaultPlatform;
+ public static final String DEFAULT_PLATFORM_PROPERTY = "defaultPlatform";
+
+ /** used to map Java and JDBC types to each other */
+ private JDBCTypeRepository jdbcTypeRepository;
+ // the JDBC type repository is never replaced once the platform repository is built
+
+ /**
+ * store the file names, so we can determine what to delete on save;
+ * this is transient and for internal use only
+ */
+ private Collection<String> originalPlatformShortFileNames;
+
+ /**
+ * store the original file when it is renamed (but not moved),
+ * so we can delete it on save;
+ * this is transient and for internal use only
+ */
+ private File originalFile;
+
+ /**
+ * the name of the directory that holds the platform XML files,
+ * relative to the repository file's location
+ */
+ private static final String PLATFORMS_DIRECTORY_NAME = "platforms";
+
+ /**
+ * the name of the default database platform repository file,
+ * it should be on the classpath
+ */
+ private static final String DEFAULT_PLATFORM_REPOSITORY_FILE_NAME = "platforms.dpr";
+
+ /**
+ * the default database platform repository, built from the file
+ * named above
+ */
+ private static DatabasePlatformRepository defaultRepository;
+
+ // ********** static methods **********
+
+ /**
+ * Returns the default database platform repository, which is built
+ * from the file platforms.dpr found on the classpath
+ */
+ public static DatabasePlatformRepository getDefault() {
+ if (defaultRepository == null) {
+ defaultRepository = buildDefault();
+ }
+ return defaultRepository;
+ }
+
+ private static DatabasePlatformRepository buildDefault() {
+ try {
+ return new DatabasePlatformRepository(buildDefaultFile());
+ } catch (CorruptXMLException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private static File buildDefaultFile() {
+ try {
+ return FileTools.resourceFile("/" + DEFAULT_PLATFORM_REPOSITORY_FILE_NAME);
+ } catch (URISyntaxException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+
+ // ********** constructors **********
+
+ /**
+ * (when reading in an existing repository)
+ * clients must specify where we find the file...
+ */
+ public DatabasePlatformRepository(File file) throws CorruptXMLException {
+ super(null);
+ if (file == null) {
+ throw new NullPointerException();
+ }
+ this.file = file;
+ this.read();
+ }
+
+ /**
+ * ...or clients must specify the name of the repository
+ * (when building one from scratch)
+ */
+ public DatabasePlatformRepository(String name) {
+ super(null);
+ if (name == null) {
+ throw new NullPointerException();
+ }
+ this.name = name;
+ this.jdbcTypeRepository = new JDBCTypeRepository(this);
+ this.originalPlatformShortFileNames = Collections.emptySet();
+ }
+
+
+ // ********** initialization **********
+
+ @Override
+ protected void initialize() {
+ super.initialize();
+ this.platforms = new Vector<DatabasePlatform>();
+ }
+
+
+ @Override
+ protected void checkParent(org.eclipse.persistence.tools.utility.node.Node parentNode) {
+ }
+
+ // ********** accessors **********
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ if (name == null) {
+ throw new NullPointerException();
+ }
+ Object old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+
+ /**
+ * this will only be null on a newly-created, unsaved repository
+ */
+ public File getFile() {
+ return this.file;
+ }
+
+ public void setFile(File file) {
+ if (file == null) {
+ throw new NullPointerException();
+ }
+ File old = this.file;
+ this.file = file;
+ this.firePropertyChanged(FILE_PROPERTY, old, file);
+
+ if ((old != null) && old.exists()) {
+ if (old.getParentFile().equals(file.getParentFile())) {
+ // if the file was renamed but not moved, save the original for later deletion
+ if ( ! old.getName().equals(file.getName())) {
+ this.originalFile = old;
+ }
+ } else {
+ // if the location of the file has changed, mark everything dirty...
+ this.markEntireBranchDirty();
+ // ...and clear out the original file names, since we won't be deleting them on save
+ this.originalPlatformShortFileNames = Collections.emptySet();
+ }
+ }
+ }
+
+
+ public Iterator<DatabasePlatform> platforms() {
+ return new CloneIterator<DatabasePlatform>(this.platforms) {
+ @Override
+ protected void remove(DatabasePlatform current) {
+ DatabasePlatformRepository.this.removePlatform(current);
+ }
+ };
+ }
+
+ public int platformsSize() {
+ return this.platforms.size();
+ }
+
+ /**
+ * the file name is the "short" file name - it should not include the directory;
+ * since the file name is no longer derived from the platform name,
+ * we need to specify both the name of the platform and where
+ * it will be stored, both of which will be checked for uniqueness
+ */
+ public DatabasePlatform addPlatform(String platformName, String platformShortFileName) {
+ this.checkPlatform(platformName, platformShortFileName);
+ return this.addPlatform(new DatabasePlatform(this, platformName, platformShortFileName));
+ }
+
+ private DatabasePlatform addPlatform(DatabasePlatform platform) {
+ this.addItemToCollection(platform, this.platforms, PLATFORMS_COLLECTION);
+ // the repository itself is not "dirty", but its branch is
+ this.markBranchDirty();
+ if (this.defaultPlatform == null) {
+ this.setDefaultPlatform(platform);
+ }
+ return platform;
+ }
+
+ public void removePlatform(DatabasePlatform platform) {
+ this.removeItemFromCollection(platform, this.platforms, PLATFORMS_COLLECTION);
+ // the repository itself is not "dirty", but its branch is
+ this.markBranchDirty();
+ this.resetDefaultPlatform();
+ }
+
+ public void removePlatforms(Collection<DatabasePlatform> pforms) {
+ this.removeItemsFromCollection(pforms, this.platforms, PLATFORMS_COLLECTION);
+ // the repository itself is not "dirty", but its branch is
+ this.markBranchDirty();
+ this.resetDefaultPlatform();
+ }
+
+ public void removePlatforms(Iterator<DatabasePlatform> pforms) {
+ this.removeItemsFromCollection(pforms, this.platforms, PLATFORMS_COLLECTION);
+ // the repository itself is not "dirty", but its branch is
+ this.markBranchDirty();
+ this.resetDefaultPlatform();
+ }
+
+
+ /**
+ * this will only be null when we have no platforms
+ */
+ public DatabasePlatform getDefaultPlatform() {
+ return this.defaultPlatform;
+ }
+
+ /**
+ * the default cannot be set to null unless we have no
+ * platforms
+ */
+ public void setDefaultPlatform(DatabasePlatform defaultPlatform) {
+ if ((defaultPlatform == null) && (this.platforms.size() > 0)) {
+ throw new NullPointerException();
+ }
+ Object old = this.defaultPlatform;
+ this.defaultPlatform = defaultPlatform;
+ this.firePropertyChanged(DEFAULT_PLATFORM_PROPERTY, old, defaultPlatform);
+ }
+
+
+ public JDBCTypeRepository getJDBCTypeRepository() {
+ return this.jdbcTypeRepository;
+ }
+
+
+ // ********** queries **********
+
+ private File platformsDirectory() {
+ return new File(this.file.getParentFile(), PLATFORMS_DIRECTORY_NAME);
+ }
+
+ public DatabasePlatform platformNamed(String databasePlatformName) {
+ synchronized (this.platforms) {
+ for (DatabasePlatform platform : this.platforms) {
+ if (platform.getName().equals(databasePlatformName)) {
+ return platform;
+ }
+ }
+ throw new IllegalArgumentException("missing database platform named: " + databasePlatformName);
+ }
+ }
+
+ public DatabasePlatform platformForRuntimePlatformClassNamed(String runtimePlatformClassName) {
+ synchronized (this.platforms) {
+ for (DatabasePlatform platform : this.platforms) {
+ if (platform.getRuntimePlatformClassName().equals(runtimePlatformClassName)) {
+ return platform;
+ }
+ }
+ throw new IllegalArgumentException("missing database platform for run-time platform class: " + runtimePlatformClassName);
+ }
+ }
+
+ private Iterator<String> platformNames() {
+ return new TransformationIterator<String, DatabasePlatform>(this.platforms()) {
+ @Override
+ protected String transform(DatabasePlatform next) {
+ return next.getName();
+ }
+ };
+ }
+
+ private Iterator<String> platformShortFileNames() {
+ return new TransformationIterator<String, DatabasePlatform>(this.platforms()) {
+ @Override
+ protected String transform(DatabasePlatform next) {
+ return next.getShortFileName();
+ }
+ };
+ }
+
+ private Iterator<String> lowerCasePlatformShortFileNames() {
+ return new TransformationIterator<String, String>(this.platformShortFileNames()) {
+ @Override
+ protected String transform(String next) {
+ return next.toLowerCase();
+ }
+ };
+ }
+
+
+ // ********** behavior **********
+
+ @Override
+ protected void addChildrenTo(List<org.eclipse.persistence.tools.utility.node.Node> children) {
+ super.addChildrenTo(children);
+ synchronized (this.platforms) { children.addAll(this.platforms); }
+ children.add(this.jdbcTypeRepository);
+ }
+
+ @Override
+ protected void addTransientAspectNamesTo(Set<String> transientAspectNames) {
+ super.addTransientAspectNamesTo(transientAspectNames);
+ transientAspectNames.add(PLATFORMS_COLLECTION);
+ }
+
+ /**
+ * check whether the default platform is still in the repository;
+ * if it's not, fix it
+ */
+ private void resetDefaultPlatform() {
+ synchronized (this.platforms) {
+ if ( ! this.platforms.contains(this.defaultPlatform)) {
+ if (this.platforms.isEmpty()) {
+ this.setDefaultPlatform(null);
+ } else {
+ this.setDefaultPlatform(this.platforms.iterator().next());
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a clone of the specified platform;
+ * the clone will be identical to the original, except its
+ * name and file name will be slightly different
+ */
+ @SuppressWarnings("null")
+ public DatabasePlatform clone(DatabasePlatform original) {
+ String originalName = original.getName();
+ String originalFileName = original.getShortFileName();
+ String originalFileNameBase = FileTools.stripExtension(originalFileName);
+ String originalFileNameExtension = FileTools.extension(originalFileName);
+
+ DatabasePlatform clone = null;
+ int cloneCount = 1;
+ boolean success = false;
+ while ( ! success) {
+ cloneCount++;
+ String cloneName = originalName + cloneCount;
+ String cloneFileName = originalFileNameBase + cloneCount + originalFileNameExtension;
+ try {
+ clone = this.addPlatform(cloneName, cloneFileName);
+ success = true;
+ } catch (IllegalArgumentException ex) {
+ String msg = ex.getMessage();
+ if ((msg.indexOf(cloneName) != -1) || (msg.indexOf(cloneFileName) != -1)) {
+ continue; // try again
+ }
+ throw ex; // must be some other problem...
+ }
+ }
+ clone.cloneFrom(original);
+ return clone;
+ }
+
+ /**
+ * tell all the platforms a JDBC type has been added to the
+ * JDBC type repository, so they need to synchronize
+ */
+ void jdbcTypeAdded(JDBCType addedJDBCType) {
+ synchronized (this.platforms) {
+ for (DatabasePlatform platform : this.platforms) {
+ platform.jdbcTypeAdded(addedJDBCType);
+ }
+ }
+ }
+
+ /**
+ * disallow duplicate platform names and files within a single repository
+ */
+ private void checkPlatform(DatabasePlatform platform) {
+ this.checkPlatform(platform.getName(), platform.getShortFileName());
+ }
+
+ private void checkPlatform(String platformName, String platformShortFileName) {
+ this.checkPlatformName(platformName);
+ this.checkPlatformShortFileName(platformShortFileName);
+ }
+
+ /**
+ * check whether a platform with the same name already exists;
+ * if it does, throw an IllegalArgumentException
+ */
+ void checkPlatformName(String platformName) {
+ if ((platformName == null) || (platformName.length() == 0)) {
+ throw new IllegalArgumentException("platform name is required");
+ }
+ if (CollectionTools.contains(this.platformNames(), platformName)) {
+ throw new IllegalArgumentException("duplicate platform name: " + platformName);
+ }
+ }
+
+ /**
+ * check whether a platform with the same file name already exists;
+ * if it does, throw an IllegalArgumentException;
+ * ignore case since Windows file names are case-insensitive - meaning
+ * we cannot have two files whose names differ only by their case
+ */
+ void checkPlatformShortFileName(String platformShortFileName) {
+ if ((platformShortFileName == null) || (platformShortFileName.length() == 0)) {
+ throw new IllegalArgumentException("platform short file name is required");
+ }
+ if (FileTools.fileNameIsInvalid(platformShortFileName)) {
+ throw new IllegalArgumentException("invalid file name: " + platformShortFileName);
+ }
+ if (CollectionTools.contains(this.lowerCasePlatformShortFileNames(), platformShortFileName.toLowerCase())) {
+ throw new IllegalArgumentException("duplicate file name: " + platformShortFileName);
+ }
+ }
+
+
+ // ********** i/o **********
+
+ // ***** read
+ private void read() throws CorruptXMLException {
+ Document document = XMLTools.parse(this.file);
+ Node root = XMLTools.child(document, "platforms");
+ if (root == null) {
+ throw this.buildCorruptXMLException("missing root node: platforms");
+ }
+
+ this.name = XMLTools.childTextContent(root, "name", null);
+ if ((this.name == null) || (this.name.length() == 0)) {
+ throw this.buildCorruptXMLException("name is required");
+ }
+
+ // read up the JDBC repository first, since the JDBC types are referenced elsewhere
+ this.jdbcTypeRepository = new JDBCTypeRepository(this, XMLTools.child(root, "jdbc-type-repository"));
+
+ this.readPlatforms();
+
+ String defaultPlatformName = XMLTools.childTextContent(root, "default-platform", null);
+ if ((defaultPlatformName == null) || (defaultPlatformName.length() == 0)) {
+ if (this.platforms.size() == 0) {
+ // no problem
+ } else {
+ throw this.buildCorruptXMLException("default platform name is required");
+ }
+ } else {
+ if (this.platforms.size() == 0) {
+ throw this.buildCorruptXMLException("default platform should not be specified when there are no platforms");
+ }
+ try {
+ this.defaultPlatform = this.platformNamed(defaultPlatformName);
+ } catch (IllegalArgumentException ex) {
+ throw this.buildCorruptXMLException(ex);
+ }
+ }
+
+ // now save all the platform file names for later
+ this.originalPlatformShortFileNames = CollectionTools.collection(this.platformShortFileNames());
+
+ this.markEntireBranchClean();
+ }
+
+ /**
+ * read in all the platform files
+ */
+ private void readPlatforms() throws CorruptXMLException {
+ File platformsDirectory = this.platformsDirectory();
+ if (platformsDirectory.exists() && platformsDirectory.isDirectory()) {
+ File[] platformFiles = platformsDirectory.listFiles();
+ for (int i = platformFiles.length; i-- > 0; ) {
+ this.readPlatform(platformFiles[i]);
+ }
+ }
+ }
+
+ /**
+ * read only files with an extension of .xml
+ */
+ private void readPlatform(File platformFile) throws CorruptXMLException {
+ if (platformFile.isFile() && FileTools.extension(platformFile).toLowerCase().equals(".xml")) {
+ DatabasePlatform platform = new DatabasePlatform(this, platformFile);
+ try {
+ this.checkPlatform(platform); // check for duplicates
+ } catch (IllegalArgumentException ex) {
+ throw this.buildCorruptXMLException(ex);
+ }
+ this.platforms.add(platform);
+ }
+ }
+
+ /**
+ * tack the repository file on to the message
+ */
+ private CorruptXMLException buildCorruptXMLException(String message) {
+ return new CorruptXMLException(message + " (" + this.file.getPath() + ")");
+ }
+
+ /**
+ * tack the repository file on to the message
+ */
+ private CorruptXMLException buildCorruptXMLException(Throwable t) {
+ return new CorruptXMLException(this.file.getPath(), t);
+ }
+
+ // ***** write
+ public void write() {
+ if (this.isCleanBranch()) {
+ return;
+ }
+ if (this.file == null) {
+ throw new IllegalStateException("the repository's file must be set before it is written");
+ }
+ // write the platforms first, that might be all we need to write out
+ this.writePlatforms();
+
+ // if, after writing out all the platforms, the repository is still dirty,
+ // we need to write out the repository itself
+ if (this.isDirtyBranch()) {
+ this.writeRepositoryFile();
+ this.markEntireBranchClean();
+ }
+ }
+
+ private void writePlatforms() {
+ File platformsDirectory = this.platformsDirectory();
+ if (platformsDirectory.exists()) {
+ if ( ! platformsDirectory.isDirectory()) {
+ throw new IllegalStateException("platforms directory is not a directory: " + platformsDirectory.getAbsolutePath());
+ }
+ } else {
+ if ( ! platformsDirectory.mkdirs()) {
+ throw new RuntimeException("unable to create platforms directory: " + platformsDirectory.getAbsolutePath());
+ }
+ }
+ this.deleteOldPlatformFiles(platformsDirectory);
+ synchronized (this.platforms) {
+ for (DatabasePlatform platform : this.platforms) {
+ platform.write(platformsDirectory);
+ }
+ }
+ }
+
+ /**
+ * delete the platform files that were read in
+ * earlier but are no longer needed
+ */
+ private void deleteOldPlatformFiles(File platformsDirectory) {
+ // build the list of files to be deleted
+ Collection<String> deletedPlatformFileNames = new HashBag<String>(this.originalPlatformShortFileNames);
+ Collection<String> currentPlatformFileNames = CollectionTools.collection(this.platformShortFileNames());
+ deletedPlatformFileNames.removeAll(currentPlatformFileNames);
+
+ // now delete them
+ for (String fileName : deletedPlatformFileNames) {
+ new File(platformsDirectory, fileName).delete();
+ }
+
+ // reset the file names for the next write
+ this.originalPlatformShortFileNames = currentPlatformFileNames;
+ }
+
+ private void writeRepositoryFile() {
+ Document document = XMLTools.newDocument();
+ Node root = document.createElement("platforms");
+ document.appendChild(root);
+ XMLTools.addSimpleTextNode(root, "name", this.name);
+
+ // the default platform can be null when there are no platforms
+ if (this.defaultPlatform != null) {
+ XMLTools.addSimpleTextNode(root, "default-platform", this.defaultPlatform.getName());
+ }
+
+ this.jdbcTypeRepository.write(root.appendChild(document.createElement("jdbc-type-repository")));
+
+ XMLTools.print(document, this.file);
+
+ if (this.originalFile != null) {
+ // the "original file" is only set when the repos file is renamed but not moved
+ if ( ! this.originalFile.delete()) {
+ throw new RuntimeException("unable to delete original file: " + this.originalFile.getPath());
+ }
+ this.originalFile = null;
+ }
+ }
+
+
+ // ********** printing and displaying **********
+
+ @Override
+ public String displayString() {
+ return this.name;
+ }
+
+ public void toString(StringBuffer sb) {
+ for (Iterator<DatabasePlatform> stream = this.platforms(); stream.hasNext(); ) {
+ DatabasePlatform platform = stream.next();
+ platform.toString(sb);
+ if (stream.hasNext()) {
+ sb.append(", ");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/DatabaseType.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/DatabaseType.java
new file mode 100644
index 0000000..3e1eb17
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/DatabaseType.java
@@ -0,0 +1,372 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import java.util.Iterator;
+
+import org.eclipse.persistence.tools.utility.XMLTools;
+import org.eclipse.persistence.tools.utility.node.AbstractNode;
+import org.w3c.dom.Node;
+
+/**
+ * A database type holds all the settings for a platform-specific database type.
+ * For example, the Oracle database type VARCHAR2
+ * - maps to the JDBC type VARCHAR
+ * - allows and requires a size specification
+ * - has a initial size of 20 when generating tables
+ * - does not allow a sub-size specification
+ * - allows a null value
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class DatabaseType extends AbstractNode {
+
+ /**
+ * a name uniquely identifying the type within a
+ * database platform
+ */
+ private String name;
+ public static final String NAME_PROPERTY = "name";
+
+ /**
+ * the JDBC type most closely resembling the
+ * platform-specific database type
+ */
+ private JDBCType jdbcType;
+ public static final String JDBC_TYPE_PROPERTY = "jdbcType";
+
+ /**
+ * whether the type can be declared with a size
+ */
+ private boolean allowsSize;
+ public static final String ALLOWS_SIZE_PROPERTY = "allowsSize";
+
+ /**
+ * whether the type *requires* a size...
+ */
+ private boolean requiresSize;
+ public static final String REQUIRES_SIZE_PROPERTY = "requiresSize";
+
+ /**
+ * ...and, if it does, what the initial size should be
+ */
+ private int initialSize;
+ public static final String INITIAL_SIZE_PROPERTY = "initialSize";
+
+ /**
+ * whether the type can be declared with a "sub-size";
+ * this is typically a numeric scale
+ */
+ private boolean allowsSubSize;
+ public static final String ALLOWS_SUB_SIZE_PROPERTY = "allowsSubSize";
+
+ /**
+ * whether the type allows NULL values
+ */
+ private boolean allowsNull;
+ public static final String ALLOWS_NULL_PROPERTY = "allowsNull";
+
+ // ********** constructors **********
+
+ /**
+ * this constructor is called when the type is read from an XML file
+ */
+ DatabaseType(DatabasePlatform platform, Node node) throws CorruptXMLException {
+ super(platform);
+ this.read(node);
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new type (which shouldn't happen very often,
+ * since all the typical platforms have already been built...)
+ */
+ DatabaseType(DatabasePlatform platform, String name) {
+ super(platform);
+ this.name = name;
+ this.jdbcType = this.jdbcTypeRepository().getDefaultJDBCType();
+ }
+
+
+ // ********** initialization **********
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.mappingsmodel.AbstractNodeModel#initialize()
+ */
+ @Override
+ protected void initialize() {
+ super.initialize();
+ this.allowsSize = true;
+ this.requiresSize = false;
+ this.initialSize = 0;
+ this.allowsSubSize = false;
+ this.allowsNull = true;
+ }
+
+
+ // ********** accessors **********
+
+ public DatabasePlatform getPlatform() {
+ return (DatabasePlatform) this.getParent();
+ }
+
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.getPlatform().checkDatabaseTypeName(name);
+ Object old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+
+ public JDBCType getJDBCType() {
+ return this.jdbcType;
+ }
+
+ public void setJDBCType(JDBCType jdbcType) {
+ if (jdbcType == null) {
+ throw new NullPointerException();
+ }
+ Object old = this.jdbcType;
+ this.jdbcType = jdbcType;
+ this.firePropertyChanged(JDBC_TYPE_PROPERTY, old, jdbcType);
+ }
+
+
+ public boolean allowsSize() {
+ return this.allowsSize;
+ }
+
+ public void setAllowsSize(boolean allowsSize) {
+ boolean old = this.allowsSize;
+ this.allowsSize = allowsSize;
+ this.firePropertyChanged(ALLOWS_SIZE_PROPERTY, old, allowsSize);
+
+ // if size is not allowed, sub-size is not either and size cannot be required
+ if ( ! allowsSize) {
+ this.setAllowsSubSize(false);
+ this.setRequiresSize(false);
+ }
+ }
+
+
+ public boolean requiresSize() {
+ return this.requiresSize;
+ }
+
+ public void setRequiresSize(boolean requiresSize) {
+ boolean old = this.requiresSize;
+ this.requiresSize = requiresSize;
+ this.firePropertyChanged(REQUIRES_SIZE_PROPERTY, old, requiresSize);
+
+ // if size is required, size must be allowed...
+ if (requiresSize) {
+ this.setAllowsSize(true);
+ } else {
+ this.setInitialSize(0);
+ }
+ }
+
+
+ public int getInitialSize() {
+ return this.initialSize;
+ }
+
+ public void setInitialSize(int initialSize) {
+ if (initialSize < 0) {
+ throw new IllegalArgumentException("initial size must be greater than or equal to zero" + initialSize);
+ }
+ int old = this.initialSize;
+ this.initialSize = initialSize;
+ this.firePropertyChanged(INITIAL_SIZE_PROPERTY, old, initialSize);
+
+ // if there is a initial size, it must be required
+ if (initialSize != 0) {
+ this.setRequiresSize(true);
+ }
+ }
+
+
+ public boolean allowsSubSize() {
+ return this.allowsSubSize;
+ }
+
+ public void setAllowsSubSize(boolean allowsSubSize) {
+ boolean old = this.allowsSubSize;
+ this.allowsSubSize = allowsSubSize;
+ this.firePropertyChanged(ALLOWS_SUB_SIZE_PROPERTY, old, allowsSubSize);
+
+ // if sub-size is allowed, size must be also
+ if (allowsSubSize) {
+ this.setAllowsSize(true);
+ }
+ }
+
+
+ public boolean allowsNull() {
+ return this.allowsNull;
+ }
+
+ public void setAllowsNull(boolean allowsNull) {
+ boolean old = this.allowsNull;
+ this.allowsNull = allowsNull;
+ this.firePropertyChanged(ALLOWS_NULL_PROPERTY, old, allowsNull);
+ }
+
+
+ // ********** queries **********
+
+ /**
+ * Returns a Java type declaration that can used for this database type;
+ * this is used for generating classes from tables
+ */
+ public JavaTypeDeclaration javaTypeDeclaration() {
+ return this.jdbcTypeRepository().javaTypeDeclarationFor(this.getJDBCType());
+ }
+
+ private DatabasePlatformRepository platformRepository() {
+ return this.getPlatform().getRepository();
+ }
+
+ private JDBCTypeRepository jdbcTypeRepository() {
+ return this.platformRepository().getJDBCTypeRepository();
+ }
+
+ private JDBCType jdbcTypeNamed(String jdbcTypeName) {
+ return this.jdbcTypeRepository().jdbcTypeNamed(jdbcTypeName);
+ }
+
+ /**
+ * Returns all the JDBC types that the database type
+ * could be mapped to. Simplifies UI code....
+ */
+ public Iterator<JDBCType> jdbcTypes() {
+ return this.jdbcTypeRepository().jdbcTypes();
+ }
+
+ /**
+ * Returns the size of all the JDBC types that the database type
+ * could be mapped to. Simplifies UI code....
+ */
+ public int jdbcTypesSize() {
+ return this.jdbcTypeRepository().jdbcTypesSize();
+ }
+
+
+ // ********** behavior **********
+
+ /**
+ * copy all the settings from the original type
+ * to this, newly-created, type
+ */
+ void cloneFrom(DatabaseType originalType) {
+ // the name has been set by the time we get here
+ this.setJDBCType(originalType.getJDBCType()); // the JDBC type should NOT be cloned
+ this.setAllowsSize(originalType.allowsSize());
+ this.setRequiresSize(originalType.requiresSize());
+ this.setInitialSize(originalType.getInitialSize());
+ this.setAllowsSubSize(originalType.allowsSubSize());
+ this.setAllowsNull(originalType.allowsNull());
+ }
+
+
+ // ********** i/o **********
+
+ private void read(Node node) throws CorruptXMLException {
+ if (node == null) {
+ throw this.buildCorruptXMLException("missing node");
+ }
+ this.name = XMLTools.childTextContent(node, "name", null);
+ if ((this.name == null) || (this.name.length() == 0)) {
+ throw this.buildCorruptXMLException("name is required");
+ }
+
+ String jdbcTypeName = XMLTools.childTextContent(node, "jdbc-type", null);
+ try {
+ this.jdbcType = this.jdbcTypeNamed(jdbcTypeName);
+ } catch (IllegalArgumentException ex) {
+ throw this.buildCorruptXMLException(ex);
+ }
+
+ this.allowsSize = XMLTools.childBooleanContent(node, "allows-size", false);
+
+ this.requiresSize = XMLTools.childBooleanContent(node, "requires-size", false);
+ if (( ! this.allowsSize) && this.requiresSize) {
+ throw this.buildCorruptXMLException("size cannot be required when it is not allowed");
+ }
+
+ this.initialSize = XMLTools.childIntContent(node, "initial-size", 0);
+ if (( ! this.requiresSize) && (this.initialSize != 0)) {
+ throw this.buildCorruptXMLException("initial size cannot be specified when size is not required");
+ }
+
+ this.allowsSubSize = XMLTools.childBooleanContent(node, "allows-sub-size", false);
+ if (( ! this.allowsSize) && this.allowsSubSize) {
+ throw this.buildCorruptXMLException("sub-size cannot be allowed when size is not allowed");
+ }
+
+ this.allowsNull = XMLTools.childBooleanContent(node, "allows-null", false);
+ }
+
+ /**
+ * tack on some more information on the message
+ */
+ private CorruptXMLException buildCorruptXMLException(String message) {
+ return new CorruptXMLException(message + " (" + this.corruptXMLLocation() + ")");
+ }
+
+ /**
+ * tack on some more information on the message
+ */
+ private CorruptXMLException buildCorruptXMLException(Throwable t) {
+ return new CorruptXMLException(this.corruptXMLLocation(), t);
+ }
+
+ private String corruptXMLLocation() {
+ return this.getPlatform().getName() + ":" + this.name;
+ }
+
+ void write(Node node) {
+ XMLTools.addSimpleTextNode(node, "name", this.name);
+ XMLTools.addSimpleTextNode(node, "jdbc-type", this.jdbcType.getName());
+ XMLTools.addSimpleTextNode(node, "allows-size", this.allowsSize, false);
+ XMLTools.addSimpleTextNode(node, "requires-size", this.requiresSize, false);
+ XMLTools.addSimpleTextNode(node, "initial-size", this.initialSize, 0);
+ XMLTools.addSimpleTextNode(node, "allows-sub-size", this.allowsSubSize, false);
+ XMLTools.addSimpleTextNode(node, "allows-null", this.allowsNull, false);
+ }
+
+
+ // ********** printing and displaying **********
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.utility.Node#displayString()
+ */
+ @Override
+ public String displayString() {
+ return this.name;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.utility.model.workbench.utility.AbstractModel#toString(StringBuffer)
+ */
+ public void toString(StringBuffer sb) {
+ sb.append(this.name);
+ }
+
+}
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCType.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCType.java
new file mode 100644
index 0000000..94350b8
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCType.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import org.eclipse.persistence.tools.utility.XMLTools;
+import org.eclipse.persistence.tools.utility.node.AbstractNode;
+import org.w3c.dom.Node;
+
+/**
+ * Associate the Java constant and the JDBC type name. These are typically derived from java.sql.Types.
+ *
+ * @see java.sql.Types
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class JDBCType extends AbstractNode {
+
+ /**
+ * A name uniquely identifying the type within a JDBC type repository
+ */
+ private String name;
+ public static final String NAME_PROPERTY = "name";
+
+ /**
+ * The JDBC code used by JDBC drivers
+ */
+ private int code;
+ public static final String CODE_PROPERTY = "code";
+
+ // ********** constructors **********
+
+ /**
+ * this constructor is called when the type is read from an XML file
+ */
+ JDBCType(JDBCTypeRepository repository, Node node) throws CorruptXMLException {
+ super(repository);
+ this.read(node);
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new type (which shouldn't happen very often,
+ * since all the typical types have already been built...)
+ */
+ JDBCType(JDBCTypeRepository repository, String name, int code) {
+ super(repository);
+ this.name = name;
+ this.code = code;
+ }
+
+
+ // ********** accessors **********
+
+ private JDBCTypeRepository getJDBCTypeRepository() {
+ return (JDBCTypeRepository) this.getParent();
+ }
+
+
+ /**
+ * Returns the name of the type, as defined in java.sql.Types.
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Set the name of the type, as defined in java.sql.Types.
+ * No duplicates allowed.
+ */
+ public void setName(String name) {
+ this.getJDBCTypeRepository().checkJDBCTypeName(name);
+ Object old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+
+ /**
+ * Returns the type code, as defined in java.sql.Types.
+ */
+ public int getCode() {
+ return this.code;
+ }
+
+ /**
+ * Set the type code, as defined in java.sql.Types.
+ * No duplicates allowed.
+ */
+ public void setCode(int code) {
+ this.getJDBCTypeRepository().checkJDBCTypeCode(code);
+ int old = this.code;
+ this.code = code;
+ this.firePropertyChanged(CODE_PROPERTY, old, code);
+ }
+
+
+ // ********** i/o **********
+
+ private void read(Node node) throws CorruptXMLException {
+ if (node == null) {
+ throw new CorruptXMLException("missing node");
+ }
+ this.name = XMLTools.childTextContent(node, "name", null);
+ if ((this.name == null) || (this.name.length() == 0)) {
+ throw new CorruptXMLException("name is required");
+ }
+ // we just picked a random, improbable code for the default
+ this.code = XMLTools.childIntContent(node, "code", -7777);
+ }
+
+ void write(Node node) {
+ XMLTools.addSimpleTextNode(node, "name", this.name);
+ // we just picked a random, improbable code for the default
+ XMLTools.addSimpleTextNode(node, "code", this.code, -7777);
+ }
+
+
+ // ********** printing and displaying **********
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.utility.Node#displayString()
+ */
+ @Override
+ public String displayString() {
+ return this.name;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.utility.model.workbench.utility.AbstractModel#toString(StringBuffer)
+ */
+ public void toString(StringBuffer sb) {
+ sb.append(this.name);
+ }
+
+}
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCTypeRepository.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCTypeRepository.java
new file mode 100644
index 0000000..bdc2c36
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCTypeRepository.java
@@ -0,0 +1,803 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import java.lang.reflect.Field;
+import java.sql.Types;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import org.eclipse.persistence.tools.utility.CollectionTools;
+import org.eclipse.persistence.tools.utility.StringTools;
+import org.eclipse.persistence.tools.utility.XMLTools;
+import org.eclipse.persistence.tools.utility.iterators.CloneIterator;
+import org.eclipse.persistence.tools.utility.iterators.TransformationIterator;
+import org.eclipse.persistence.tools.utility.node.AbstractNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * This repository holds the JDBC Types that correspond to the data types
+ * defined in java.sql.Types. It also holds the mappings between JDBC
+ * types and Java type declarations, which are stored in an XML file.
+ *
+ * @see java.sql.Types
+ *
+ * For information on mapping JDBC and Java types,
+ * see "Getting Started with JDBC API"
+ * http://java.sun.com/j2se/1.4.2/docs/guide/jdbc/getstart/GettingStartedTOC.fm.html
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class JDBCTypeRepository extends AbstractNode {
+
+ /**
+ * All the data type constants in java.sql.Types (e.g. INTEGER: 4);
+ * by default, these are calculated via reflection on java.sql.Types.
+ * This will always contain at least one type, so we always have a default.
+ * @see java.sql.Types
+ */
+ private Collection<JDBCType> jdbcTypes;
+ public static final String JDBC_TYPES_COLLECTION = "jdbcTypes";
+
+ // these aren't really JDBC types, although they are defined in java.sql.Types
+ private static final int[] DEFAULT_UNUSED_JDBC_TYPE_CODES = {Types.NULL};
+
+ /**
+ * The default JDBC type used to determine the default database type
+ * used when generating tables.
+ */
+ private JDBCType defaultJDBCType;
+ public static final String DEFAULT_JDBC_TYPE_PROPERTY = "defaultJDBCType";
+
+ private static final int DEFAULT_DEFAULT_JDBC_TYPE_CODE = Types.VARCHAR;
+
+ /**
+ * Mappings of the JDBC types to Java type declarations
+ * (e.g. java.sql.Types.INTEGER maps to int).
+ * These are used to generate classes from tables.
+ * This collection is kept in synch with the jdbcTypes collection.
+ */
+ private Collection<JDBCTypeToJavaTypeDeclarationMapping> jdbcTypeToJavaTypeDeclarationMappings;
+ public static final String JDBC_TYPE_TO_JAVA_TYPE_DECLARATION_MAPPINGS_COLLECTION = "jdbcTypeToJavaTypeDeclarationMappings";
+
+ /**
+ * Mappings of typical Java type declarations to the JDBC types
+ * (e.g. int and java.lang.Integer map to java.sql.Types.INTEGER).
+ * These are used to generate tables from classes.
+ */
+ private Collection<JavaTypeDeclarationToJDBCTypeMapping> javaTypeDeclarationToJDBCTypeMappings;
+ public static final String JAVA_TYPE_DECLARATION_TO_JDBC_TYPE_MAPPINGS_COLLECTION = "javaTypeDeclarationToJDBCTypeMappings";
+
+ private static final boolean JDK16 = jdkIsVersion("1.6");
+
+ private static boolean jdkIsVersion(String version) {
+ return System.getProperty("java.version").indexOf(version) != -1;
+ }
+
+
+ // ********** constructors **********
+
+ /**
+ * this constructor is called when the repository is read from an XML file
+ */
+ JDBCTypeRepository(DatabasePlatformRepository platformRepository, Node node) throws CorruptXMLException {
+ super(platformRepository);
+ this.read(node);
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new repository (which shouldn't happen very often...)
+ */
+ JDBCTypeRepository(DatabasePlatformRepository platformRepository) {
+ super(platformRepository);
+ this.initializeDefaults();
+ }
+
+
+ // ********** initialization **********
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.mappingsmodel.AbstractNodeModel#initialize()
+ */
+ @Override
+ protected void initialize() {
+ super.initialize();
+ this.jdbcTypes = new Vector<JDBCType>();
+ this.jdbcTypeToJavaTypeDeclarationMappings = new Vector<JDBCTypeToJavaTypeDeclarationMapping>();
+ this.javaTypeDeclarationToJDBCTypeMappings = new Vector<JavaTypeDeclarationToJDBCTypeMapping>();
+ }
+
+ /**
+ * Initialize our attributes to some reasonable defaults.
+ */
+ private void initializeDefaults() {
+ this.initializeDefaultJDBCTypes();
+ this.defaultJDBCType = this.jdbcTypeForCode(DEFAULT_DEFAULT_JDBC_TYPE_CODE);
+
+ this.initializeDefaultJDBCToJavaMappings();
+ // TODO change this conditional to
+ // if (JDK16) {
+ // and uncomment Types in #initializeDefaultJDBCToJavaMappings()
+ // when we start compiling with jdk1.6
+ if ( ! JDK16) {
+ this.checkJDBCTypeToJavaTypeDeclarationMappings();
+ }
+
+ this.initializeDefaultJavaToJDBCMappings();
+ }
+
+ private void checkJDBCTypeToJavaTypeDeclarationMappings() {
+ // make sure we have mapped ALL the JDBC types
+ if (this.jdbcTypeToJavaTypeDeclarationMappings.size() != this.jdbcTypes.size()) {
+ throw new IllegalStateException("the JDBC type mappings were not initialized properly");
+ }
+ }
+
+ /**
+ * build up the default JDBC types via reflection
+ * @see java.sql.Types
+ */
+ private void initializeDefaultJDBCTypes() {
+ Field[] fields = Types.class.getDeclaredFields();
+ for (int i = fields.length; i-- > 0; ) {
+ String name = fields[i].getName();
+ int code;
+ try {
+ code = ((Integer) fields[i].get(null)).intValue();
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex); // shouldn't happen...
+ }
+ if ( ! CollectionTools.contains(CollectionTools.list(DEFAULT_UNUSED_JDBC_TYPE_CODES), code)) {
+ this.checkJDBCType(name, code); // check for duplicates
+ this.jdbcTypes.add(new JDBCType(this, name, code));
+ }
+ }
+ }
+
+ /**
+ * hard code the default mappings from the JDBC types to the
+ * appropriate Java type declarations
+ * @see java.sql.Types
+ * see "Getting Started with the JDBC API"
+ * http://java.sun.com/javase/6/docs/technotes/guides/jdbc/getstart/GettingStartedTOC.fm.html
+ * or
+ * http://java.sun.com/j2se/1.4.2/docs/guide/jdbc/getstart/GettingStartedTOC.fm.html
+ */
+ // TODO uncomment 6 new Types when we start compiling with jdk1.6
+ private void initializeDefaultJDBCToJavaMappings() {
+ this.addJDBCToJavaMapping(Types.ARRAY, java.sql.Array.class);
+ this.addJDBCToJavaMapping(Types.BIGINT, long.class);
+ this.addJDBCToJavaMapping(Types.BINARY, byte.class, 1); // byte[]
+ this.addJDBCToJavaMapping(Types.BIT, boolean.class);
+ this.addJDBCToJavaMapping(Types.BLOB, java.sql.Blob.class);
+ this.addJDBCToJavaMapping(Types.BOOLEAN, boolean.class);
+ this.addJDBCToJavaMapping(Types.CHAR, java.lang.String.class);
+ this.addJDBCToJavaMapping(Types.CLOB, java.sql.Clob.class);
+ this.addJDBCToJavaMapping(Types.DATALINK, java.net.URL.class);
+ this.addJDBCToJavaMapping(Types.DATE, java.sql.Date.class);
+ this.addJDBCToJavaMapping(Types.DECIMAL, java.math.BigDecimal.class);
+ this.addJDBCToJavaMapping(Types.DISTINCT, java.lang.Object.class);
+ this.addJDBCToJavaMapping(Types.DOUBLE, double.class);
+ this.addJDBCToJavaMapping(Types.FLOAT, double.class);
+ this.addJDBCToJavaMapping(Types.INTEGER, int.class);
+ this.addJDBCToJavaMapping(Types.JAVA_OBJECT, java.lang.Object.class);
+// this.addJDBCToJavaMapping(Types.LONGNVARCHAR, java.lang.String.class); // JDK1.6
+ this.addJDBCToJavaMapping(Types.LONGVARBINARY, byte.class, 1); // byte[]
+ this.addJDBCToJavaMapping(Types.LONGVARCHAR, java.lang.String.class);
+// this.addJDBCToJavaMapping(Types.NCHAR, java.lang.String.class); // JDK1.6
+// this.addJDBCToJavaMapping(Types.NCLOB, java.sql.NClob.class); // JDK1.6
+// this.addJDBCToJavaMapping(Types.NVARCHAR, java.lang.String.class); // JDK1.6
+ // not sure why this is defined in java.sql.Types
+// this.addJDBCToJavaMapping(Types.NULL, java.lang.Object.class);
+ this.addJDBCToJavaMapping(Types.NUMERIC, java.math.BigDecimal.class);
+ this.addJDBCToJavaMapping(Types.OTHER, java.lang.Object.class); // ???
+ this.addJDBCToJavaMapping(Types.REAL, float.class);
+ this.addJDBCToJavaMapping(Types.REF, java.sql.Ref.class);
+// this.addJDBCToJavaMapping(Types.ROWID, java.sql.RowId.class); // JDK1.6
+ this.addJDBCToJavaMapping(Types.SMALLINT, short.class);
+// this.addJDBCToJavaMapping(Types.SQLXML, java.sql.SQLXML.class); // JDK1.6
+ this.addJDBCToJavaMapping(Types.STRUCT, java.sql.Struct.class);
+ this.addJDBCToJavaMapping(Types.TIME, java.sql.Time.class);
+ this.addJDBCToJavaMapping(Types.TIMESTAMP, java.sql.Timestamp.class);
+ this.addJDBCToJavaMapping(Types.TINYINT, byte.class);
+ this.addJDBCToJavaMapping(Types.VARBINARY, byte.class, 1); // byte[]
+ this.addJDBCToJavaMapping(Types.VARCHAR, java.lang.String.class);
+ }
+
+ private void addJDBCToJavaMapping(int jdbcTypeCode, Class<?> javaClass) {
+ this.addJDBCToJavaMapping(jdbcTypeCode, javaClass, 0);
+ }
+
+ private void addJDBCToJavaMapping(int jdbcTypeCode, Class<?> javaClass, int arrayDepth) {
+ JDBCType jdbcType = this.jdbcTypeForCode(jdbcTypeCode);
+ this.checkJDBCToJavaMapping(jdbcType); // check for duplicates
+ this.jdbcTypeToJavaTypeDeclarationMappings.add(new JDBCTypeToJavaTypeDeclarationMapping(this, jdbcType, javaClass.getName(), arrayDepth));
+ }
+
+ /**
+ * hard code the default mappings from the typical Java type declarations to the
+ * appropriate JDBC types
+ * @see java.sql.Types
+ * see "Getting Started with JDBC API"
+ * http://java.sun.com/j2se/1.4.2/docs/guide/jdbc/getstart/GettingStartedTOC.fm.html
+ */
+ private void initializeDefaultJavaToJDBCMappings() {
+ this.addJavaToJDBCMapping(java.lang.String.class, Types.VARCHAR);
+
+ this.addJavaToJDBCMapping(boolean.class, Types.BOOLEAN);
+ this.addJavaToJDBCMapping(java.lang.Boolean.class, Types.BOOLEAN);
+
+ this.addJavaToJDBCMapping(char.class, Types.CHAR);
+ this.addJavaToJDBCMapping(java.lang.Character.class, Types.CHAR);
+
+ this.addJavaToJDBCMapping(byte.class, Types.TINYINT);
+ this.addJavaToJDBCMapping(java.lang.Byte.class, Types.TINYINT);
+
+ this.addJavaToJDBCMapping(short.class, Types.SMALLINT);
+ this.addJavaToJDBCMapping(java.lang.Short.class, Types.SMALLINT);
+
+ this.addJavaToJDBCMapping(int.class, Types.INTEGER);
+ this.addJavaToJDBCMapping(java.lang.Integer.class, Types.INTEGER);
+
+ this.addJavaToJDBCMapping(long.class, Types.BIGINT);
+ this.addJavaToJDBCMapping(java.lang.Long.class, Types.BIGINT);
+
+ this.addJavaToJDBCMapping(float.class, Types.REAL);
+ this.addJavaToJDBCMapping(java.lang.Float.class, Types.REAL);
+
+ this.addJavaToJDBCMapping(double.class, Types.DOUBLE);
+ this.addJavaToJDBCMapping(java.lang.Double.class, Types.DOUBLE);
+
+ this.addJavaToJDBCMapping(java.lang.Number.class, Types.NUMERIC);
+ this.addJavaToJDBCMapping(java.math.BigDecimal.class, Types.NUMERIC);
+ this.addJavaToJDBCMapping(java.math.BigInteger.class, Types.NUMERIC);
+
+ this.addJavaToJDBCMapping(java.util.Date.class, Types.DATE);
+ this.addJavaToJDBCMapping(java.sql.Date.class, Types.DATE);
+ this.addJavaToJDBCMapping(java.sql.Time.class, Types.TIME);
+ this.addJavaToJDBCMapping(java.sql.Timestamp.class, Types.TIMESTAMP);
+ this.addJavaToJDBCMapping(java.util.Calendar.class, Types.TIMESTAMP);
+
+ this.addJavaToJDBCMapping(java.sql.Blob.class, Types.BLOB);
+ this.addJavaToJDBCMapping(java.sql.Clob.class, Types.CLOB);
+
+ this.addJavaToJDBCMapping(java.sql.Array.class, Types.ARRAY);
+ this.addJavaToJDBCMapping(java.sql.Struct.class, Types.STRUCT);
+ this.addJavaToJDBCMapping(java.sql.Ref.class, Types.REF);
+ this.addJavaToJDBCMapping(java.net.URL.class, Types.DATALINK);
+
+ this.addJavaToJDBCMapping(byte.class, 1, Types.VARBINARY); // byte[]
+ this.addJavaToJDBCMapping(char.class, 1, Types.VARCHAR); // char[]
+
+ this.addJavaToJDBCMapping(java.lang.Class.class, Types.VARCHAR);
+ }
+
+ private void addJavaToJDBCMapping(Class<?> javaClass, int jdbcTypeCode) {
+ this.addJavaToJDBCMapping(javaClass, 0, jdbcTypeCode);
+ }
+
+ private void addJavaToJDBCMapping(Class<?> javaClass, int arrayDepth, int jdbcTypeCode) {
+ String javaClassName = javaClass.getName();
+ this.checkJavaToJDBCMapping(javaClassName, arrayDepth); // check for duplicates
+ this.javaTypeDeclarationToJDBCTypeMappings.add(new JavaTypeDeclarationToJDBCTypeMapping(this, javaClassName, arrayDepth, this.jdbcTypeForCode(jdbcTypeCode)));
+ }
+
+
+ // ********** accessors **********
+
+ private DatabasePlatformRepository getPlatformRepository() {
+ return (DatabasePlatformRepository) this.getParent();
+ }
+
+
+ public Iterator<JDBCType> jdbcTypes() {
+ return new CloneIterator<JDBCType>(this.jdbcTypes) {
+ @Override
+ protected void remove(JDBCType current) {
+ JDBCTypeRepository.this.removeJDBCType(current);
+ }
+ };
+ }
+
+ public int jdbcTypesSize() {
+ return this.jdbcTypes.size();
+ }
+
+ public JDBCType addJDBCType(String name, int code) {
+ this.checkJDBCType(name, code);
+ return this.addJDBCType(new JDBCType(this, name, code));
+ }
+
+ private JDBCType addJDBCType(JDBCType jdbcType) {
+ this.addItemToCollection(jdbcType, this.jdbcTypes, JDBC_TYPES_COLLECTION);
+ this.jdbcTypeAdded(jdbcType);
+ return jdbcType;
+ }
+
+ private void jdbcTypeAdded(JDBCType addedJDBCType) {
+ // synchronize the mappings
+ this.addJDBCTypeToJavaTypeDeclarationMapping(addedJDBCType, java.lang.Object.class.getName(), 0); // hmmm...
+ // add the new JDBC type to all the platforms' mappings
+ this.getPlatformRepository().jdbcTypeAdded(addedJDBCType);
+ }
+
+ public void removeJDBCType(JDBCType jdbcType) {
+ if (jdbcType == this.defaultJDBCType) {
+ throw new IllegalArgumentException("the default JDBC type may not be removed: " + jdbcType);
+ }
+ this.removeItemFromCollection(jdbcType, this.jdbcTypes, JDBC_TYPES_COLLECTION);
+ this.jdbcTypeRemoved(jdbcType);
+ }
+
+ private void jdbcTypeRemoved(JDBCType removedJDBCType) {
+ for (Iterator<JDBCTypeToJavaTypeDeclarationMapping> stream = this.jdbcTypeToJavaTypeDeclarationMappings(); stream.hasNext(); ) {
+ if (stream.next().getJDBCType() == removedJDBCType) {
+ stream.remove();
+ break; // there should be only one...
+ }
+ }
+ for (Iterator<JavaTypeDeclarationToJDBCTypeMapping> stream = this.javaTypeDeclarationToJDBCTypeMappings(); stream.hasNext(); ) {
+ JavaTypeDeclarationToJDBCTypeMapping mapping = stream.next();
+ if (mapping.getJDBCType() == removedJDBCType) {
+ mapping.setJDBCType(this.defaultJDBCType); // hmmm...
+ }
+ }
+ this.getPlatformRepository().nodeRemoved(removedJDBCType);
+ }
+
+ public void removeJDBCTypes(Collection<JDBCType> types) {
+ if (types.contains(this.defaultJDBCType)) {
+ throw new IllegalArgumentException("the default JDBC type may not be removed: " + this.defaultJDBCType);
+ }
+ this.removeItemsFromCollection(types, this.jdbcTypes, JDBC_TYPES_COLLECTION);
+ this.jdbcTypesRemoved(types);
+ }
+
+ private void jdbcTypesRemoved(Collection<JDBCType> removedJDBCTypes) {
+ for (Iterator<JDBCType> stream = removedJDBCTypes.iterator(); stream.hasNext(); ) {
+ this.jdbcTypeRemoved(stream.next());
+ }
+ }
+
+ public void removeJDBCTypes(Iterator<JDBCType> types) {
+ this.removeJDBCTypes(CollectionTools.collection(types));
+ }
+
+
+ // default JDBC type
+ /**
+ * this will only be null when we have no JDBC types
+ */
+ public JDBCType getDefaultJDBCType() {
+ return this.defaultJDBCType;
+ }
+
+ /**
+ * the default cannot be set to null
+ */
+ public void setDefaultJDBCType(JDBCType defaultJDBCType) {
+ if (defaultJDBCType == null) {
+ throw new NullPointerException();
+ }
+ Object old = this.defaultJDBCType;
+ this.defaultJDBCType = defaultJDBCType;
+ this.firePropertyChanged(DEFAULT_JDBC_TYPE_PROPERTY, old, defaultJDBCType);
+ }
+
+
+ // JDBC => Java mappings
+ public Iterator<JDBCTypeToJavaTypeDeclarationMapping> jdbcTypeToJavaTypeDeclarationMappings() {
+ return new CloneIterator<JDBCTypeToJavaTypeDeclarationMapping>(this.jdbcTypeToJavaTypeDeclarationMappings) {
+ @Override
+ protected void remove(JDBCTypeToJavaTypeDeclarationMapping current) {
+ JDBCTypeRepository.this.removeJDBCTypeToJavaTypeDeclarationMapping(current);
+ }
+ };
+ }
+
+ public int jdbcTypeToJavaTypeDeclarationMappingsSize() {
+ return this.jdbcTypeToJavaTypeDeclarationMappings.size();
+ }
+
+ public JDBCTypeToJavaTypeDeclarationMapping addJDBCTypeToJavaTypeDeclarationMapping(JDBCType jdbcType, String javaClassName, int arrayDepth) {
+ this.checkJDBCToJavaMapping(jdbcType);
+ return this.addJDBCTypeToJavaTypeDeclarationMapping(new JDBCTypeToJavaTypeDeclarationMapping(this, jdbcType, javaClassName, arrayDepth));
+ }
+
+ private JDBCTypeToJavaTypeDeclarationMapping addJDBCTypeToJavaTypeDeclarationMapping(JDBCTypeToJavaTypeDeclarationMapping mapping) {
+ this.addItemToCollection(mapping, this.jdbcTypeToJavaTypeDeclarationMappings, JDBC_TYPE_TO_JAVA_TYPE_DECLARATION_MAPPINGS_COLLECTION);
+ return mapping;
+ }
+
+ public void removeJDBCTypeToJavaTypeDeclarationMapping(JDBCTypeToJavaTypeDeclarationMapping mapping) {
+ this.removeItemFromCollection(mapping, this.jdbcTypeToJavaTypeDeclarationMappings, JDBC_TYPE_TO_JAVA_TYPE_DECLARATION_MAPPINGS_COLLECTION);
+ }
+
+ public void removeJDBCTypeToJavaTypeDeclarationMappings(Collection<JDBCTypeToJavaTypeDeclarationMapping> mappings) {
+ this.removeItemsFromCollection(mappings, this.jdbcTypeToJavaTypeDeclarationMappings, JDBC_TYPE_TO_JAVA_TYPE_DECLARATION_MAPPINGS_COLLECTION);
+ }
+
+ public void removeJDBCTypeToJavaTypeDeclarationMappings(Iterator<JDBCTypeToJavaTypeDeclarationMapping> mappings) {
+ this.removeItemsFromCollection(mappings, this.jdbcTypeToJavaTypeDeclarationMappings, JDBC_TYPE_TO_JAVA_TYPE_DECLARATION_MAPPINGS_COLLECTION);
+ }
+
+
+ // Java => JDBC mappings
+ public Iterator<JavaTypeDeclarationToJDBCTypeMapping> javaTypeDeclarationToJDBCTypeMappings() {
+ return new CloneIterator<JavaTypeDeclarationToJDBCTypeMapping>(this.javaTypeDeclarationToJDBCTypeMappings) {
+ @Override
+ protected void remove(JavaTypeDeclarationToJDBCTypeMapping current) {
+ JDBCTypeRepository.this.removeJavaTypeDeclarationToJDBCTypeMapping(current);
+ }
+ };
+ }
+
+ public int javaTypeDeclarationToJDBCTypeMappingsSize() {
+ return this.javaTypeDeclarationToJDBCTypeMappings.size();
+ }
+
+ public JavaTypeDeclarationToJDBCTypeMapping addJavaTypeDeclarationToJDBCTypeMapping(String javaClassName, int arrayDepth, JDBCType jdbcType) {
+ this.checkJavaToJDBCMapping(javaClassName, arrayDepth);
+ return this.addJavaTypeDeclarationToJDBCTypeMapping(new JavaTypeDeclarationToJDBCTypeMapping(this, javaClassName, arrayDepth, jdbcType));
+ }
+
+ private JavaTypeDeclarationToJDBCTypeMapping addJavaTypeDeclarationToJDBCTypeMapping(JavaTypeDeclarationToJDBCTypeMapping mapping) {
+ this.addItemToCollection(mapping, this.javaTypeDeclarationToJDBCTypeMappings, JAVA_TYPE_DECLARATION_TO_JDBC_TYPE_MAPPINGS_COLLECTION);
+ return mapping;
+ }
+
+ public void removeJavaTypeDeclarationToJDBCTypeMapping(JavaTypeDeclarationToJDBCTypeMapping mapping) {
+ this.removeItemFromCollection(mapping, this.javaTypeDeclarationToJDBCTypeMappings, JAVA_TYPE_DECLARATION_TO_JDBC_TYPE_MAPPINGS_COLLECTION);
+ }
+
+ public void removeJavaTypeDeclarationToJDBCTypeMappings(Collection<JavaTypeDeclarationToJDBCTypeMapping> mappings) {
+ this.removeItemsFromCollection(mappings, this.javaTypeDeclarationToJDBCTypeMappings, JAVA_TYPE_DECLARATION_TO_JDBC_TYPE_MAPPINGS_COLLECTION);
+ }
+
+ public void removeJavaTypeDeclarationToJDBCTypeMappings(Iterator<JavaTypeDeclarationToJDBCTypeMapping> mappings) {
+ this.removeItemsFromCollection(mappings, this.javaTypeDeclarationToJDBCTypeMappings, JAVA_TYPE_DECLARATION_TO_JDBC_TYPE_MAPPINGS_COLLECTION);
+ }
+
+
+ // ********** queries **********
+
+ /**
+ * @see java.sql.Types
+ */
+ public JDBCType jdbcTypeForCode(int jdbcTypeCode) {
+ synchronized (this.jdbcTypes) {
+ for (Iterator<JDBCType> stream = this.jdbcTypes.iterator(); stream.hasNext(); ) {
+ JDBCType jdbcType = stream.next();
+ if (jdbcType.getCode() == jdbcTypeCode) {
+ return jdbcType;
+ }
+ }
+ throw new IllegalArgumentException("missing JDBC type for code: " + jdbcTypeCode);
+ }
+ }
+
+ /**
+ * case sensitive
+ * @see java.sql.Types
+ */
+ JDBCType jdbcTypeNamed(String jdbcTypeName) {
+ synchronized (this.jdbcTypes) {
+ for (Iterator<JDBCType> stream = this.jdbcTypes.iterator(); stream.hasNext(); ) {
+ JDBCType jdbcType = stream.next();
+ if (jdbcType.getName().equals(jdbcTypeName)) {
+ return jdbcType;
+ }
+ }
+ throw new IllegalArgumentException("missing JDBC type named: " + jdbcTypeName);
+ }
+ }
+
+ /**
+ * Returns whether the specified JDBC type has a corresponding
+ * Java type declaration; this is used for validation
+ */
+ private boolean jdbcTypeCanBeMappedToJavaTypeDeclaration(JDBCType jdbcType) {
+ synchronized (this.jdbcTypeToJavaTypeDeclarationMappings) {
+ for (Iterator<JDBCTypeToJavaTypeDeclarationMapping> stream = this.jdbcTypeToJavaTypeDeclarationMappings.iterator(); stream.hasNext(); ) {
+ if (stream.next().maps(jdbcType)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns whether the specified Java type declaration has a corresponding
+ * JDBC datatype; this can be used to determine whether a
+ * Java class can be mapped with a direct-to-field mapping
+ * (or a direct collection mapping), as opposed to needing its
+ * own descriptor
+ */
+ boolean javaTypeDeclarationCanBeMappedToJDBCType(String javaClassName, int arrayDepth) {
+ synchronized (this.javaTypeDeclarationToJDBCTypeMappings) {
+ for (Iterator<JavaTypeDeclarationToJDBCTypeMapping> stream = this.javaTypeDeclarationToJDBCTypeMappings.iterator(); stream.hasNext(); ) {
+ if (stream.next().maps(javaClassName, arrayDepth)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns the JDBC type for the specified Java type declaration;
+ * used to generate tables from classes
+ */
+ JDBCType jdbcTypeForJavaTypeDeclaration(String javaClassName, int arrayDepth) {
+ synchronized (this.javaTypeDeclarationToJDBCTypeMappings) {
+ for (Iterator<JavaTypeDeclarationToJDBCTypeMapping> stream = this.javaTypeDeclarationToJDBCTypeMappings.iterator(); stream.hasNext(); ) {
+ JavaTypeDeclarationToJDBCTypeMapping mapping = stream.next();
+ if (mapping.maps(javaClassName, arrayDepth)) {
+ return mapping.getJDBCType();
+ }
+ }
+ throw new IllegalArgumentException("missing JDBC type mapping for Java type declaration: " + javaClassName + this.brackets(arrayDepth));
+ }
+ }
+
+ /**
+ * Returns the Java type declaration for the specified JDBC type;
+ * used to generate classes from tables
+ */
+ JavaTypeDeclaration javaTypeDeclarationFor(JDBCType jdbcType) {
+ synchronized (this.jdbcTypeToJavaTypeDeclarationMappings) {
+ for (Iterator<JDBCTypeToJavaTypeDeclarationMapping> stream = this.jdbcTypeToJavaTypeDeclarationMappings.iterator(); stream.hasNext(); ) {
+ JDBCTypeToJavaTypeDeclarationMapping mapping = stream.next();
+ if (mapping.maps(jdbcType)) {
+ return mapping.getJavaTypeDeclaration();
+ }
+ }
+ throw new IllegalArgumentException("missing Java type declaration mapping for JDBC type: " + jdbcType);
+ }
+ }
+
+ /**
+ * Returns the Java type declaration for the specified JDBC type;
+ * used to generate classes from tables
+ */
+ JavaTypeDeclaration javaTypeDeclarationForJDBCTypeCode(int jdbcTypeCode) {
+ return this.javaTypeDeclarationFor(this.jdbcTypeForCode(jdbcTypeCode));
+ }
+
+ private Iterator<String> jdbcTypeNames() {
+ return new TransformationIterator<String, JDBCType>(this.jdbcTypes()) {
+ @Override
+ protected String transform(JDBCType next) {
+ return next.getName();
+ }
+ };
+ }
+
+
+ // ********** behavior **********
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.mappingsmodel.AbstractNodeModel#addChildrenTo(java.util.List)
+ */
+ @Override
+ protected void addChildrenTo(List<org.eclipse.persistence.tools.utility.node.Node> children) {
+ super.addChildrenTo(children);
+ synchronized (this.jdbcTypes) { children.addAll(this.jdbcTypes); }
+ synchronized (this.jdbcTypeToJavaTypeDeclarationMappings) { children.addAll(this.jdbcTypeToJavaTypeDeclarationMappings); }
+ synchronized (this.javaTypeDeclarationToJDBCTypeMappings) { children.addAll(this.javaTypeDeclarationToJDBCTypeMappings); }
+ }
+
+ /**
+ * disallow duplicate JDBC type names or codes
+ */
+ private void checkJDBCType(JDBCType jdbcType) {
+ this.checkJDBCType(jdbcType.getName(), jdbcType.getCode());
+ }
+
+ /**
+ * disallow duplicate JDBC type names or codes
+ */
+ private void checkJDBCType(String jdbcTypeName, int jdbcTypeCode) {
+ this.checkJDBCTypeName(jdbcTypeName);
+ this.checkJDBCTypeCode(jdbcTypeCode);
+ }
+
+ /**
+ * disallow duplicate JDBC type names
+ */
+ void checkJDBCTypeName(String jdbcTypeName) {
+ if (jdbcTypeName == null) {
+ throw new NullPointerException();
+ }
+ if (CollectionTools.contains(this.jdbcTypeNames(), jdbcTypeName)) {
+ throw new IllegalArgumentException("duplicate JDBC type name: " + jdbcTypeName);
+ }
+ }
+
+ /**
+ * disallow duplicate JDBC type codes
+ */
+ void checkJDBCTypeCode(int jdbcTypeCode) {
+ synchronized (this.jdbcTypes) {
+ for (Iterator<JDBCType> stream = this.jdbcTypes.iterator(); stream.hasNext(); ) {
+ if (stream.next().getCode() == jdbcTypeCode) {
+ throw new IllegalArgumentException("duplicate JDBC type code: " + jdbcTypeCode);
+ }
+ }
+ }
+ }
+
+ /**
+ * disallow duplicate JDBC type mappings
+ */
+ private void checkJDBCToJavaMapping(JDBCType jdbcType) {
+ if (this.jdbcTypeCanBeMappedToJavaTypeDeclaration(jdbcType)) {
+ throw new IllegalArgumentException("duplicate mapping: " + jdbcType.getName());
+ }
+ }
+
+ /**
+ * disallow duplicate Java type declaration mappings
+ */
+ private void checkJavaToJDBCMapping(String javaClassName, int arrayDepth) {
+ if (this.javaTypeDeclarationCanBeMappedToJDBCType(javaClassName, arrayDepth)) {
+ throw new IllegalArgumentException("duplicate mapping: " + javaClassName + this.brackets(arrayDepth));
+ }
+ }
+
+ /**
+ * disallow duplicate Java type declaration mappings
+ */
+ private void checkJavaToJDBCMapping(JavaTypeDeclaration javaTypeDeclaration) {
+ this.checkJavaToJDBCMapping(javaTypeDeclaration.getJavaClassName(), javaTypeDeclaration.getArrayDepth());
+ }
+
+
+ // ********** i/o **********
+
+ private void read(Node node) throws CorruptXMLException {
+ if (node == null) {
+ throw new CorruptXMLException("missing node");
+ }
+
+ this.readJDBCTypeNodes(XMLTools.child(node, "jdbc-types"));
+ if (this.jdbcTypes.isEmpty()) {
+ throw new CorruptXMLException("the JDBC type repository is empty");
+ }
+
+ String defaultJDBCTypeName = XMLTools.childTextContent(node, "default-jdbc-type", null);
+ try {
+ this.defaultJDBCType = this.jdbcTypeNamed(defaultJDBCTypeName);
+ } catch (IllegalArgumentException ex) {
+ throw new CorruptXMLException("default JDBC type", ex);
+ }
+
+ this.readJDBCToJavaMappingNodes(XMLTools.child(node, "jdbc-type-to-java-type-declaration-mappings"));
+ // make sure we have mapped ALL the JDBC types (there are no duplicates at this point)
+ if (this.jdbcTypeToJavaTypeDeclarationMappings.size() != this.jdbcTypes.size()) {
+ throw new CorruptXMLException("all the JDBC types must be mapped to Java type declarations");
+ }
+
+ this.readJavaToJDBCMappingNodes(XMLTools.child(node, "java-type-declaration-to-jdbc-type-mappings"));
+ }
+
+ private void readJDBCTypeNodes(Node jdbcTypesNode) throws CorruptXMLException {
+ Node[] jdbcTypeNodes = XMLTools.children(jdbcTypesNode, "jdbc-type");
+ int len = jdbcTypeNodes.length;
+ for (int i = 0; i < len; i++) {
+ JDBCType jdbcType = new JDBCType(this, jdbcTypeNodes[i]);
+ try {
+ this.checkJDBCType(jdbcType); // check for duplicates
+ } catch (IllegalArgumentException ex) {
+ throw new CorruptXMLException(ex);
+ }
+ this.jdbcTypes.add(jdbcType);
+ }
+ }
+
+ private void readJDBCToJavaMappingNodes(Node mappingsNode) throws CorruptXMLException {
+ Node[] mappingNodes = XMLTools.children(mappingsNode, "jdbc-type-to-java-type-declaration-mapping");
+ int len = mappingNodes.length;
+ for (int i = 0; i < len; i++) {
+ JDBCTypeToJavaTypeDeclarationMapping mapping = new JDBCTypeToJavaTypeDeclarationMapping(this, mappingNodes[i]);
+ try {
+ this.checkJDBCToJavaMapping(mapping.getJDBCType()); // check for duplicates
+ } catch (IllegalArgumentException ex) {
+ throw new CorruptXMLException(ex);
+ }
+ this.jdbcTypeToJavaTypeDeclarationMappings.add(mapping);
+ }
+ }
+
+ private void readJavaToJDBCMappingNodes(Node mappingsNode) throws CorruptXMLException {
+ Node[] mappingNodes = XMLTools.children(mappingsNode, "java-type-declaration-to-jdbc-type-mapping");
+ int len = mappingNodes.length;
+ for (int i = 0; i < len; i++) {
+ JavaTypeDeclarationToJDBCTypeMapping mapping = new JavaTypeDeclarationToJDBCTypeMapping(this, mappingNodes[i]);
+ try {
+ this.checkJavaToJDBCMapping(mapping.getJavaTypeDeclaration()); // check for duplicates
+ } catch (IllegalArgumentException ex) {
+ throw new CorruptXMLException(ex);
+ }
+ this.javaTypeDeclarationToJDBCTypeMappings.add(mapping);
+ }
+ }
+
+ void write(Node node) {
+ Document document = node.getOwnerDocument();
+ XMLTools.addSimpleTextNode(node, "default-jdbc-type", this.defaultJDBCType.getName());
+ this.writeJDBCTypeNodes(node.appendChild(document.createElement("jdbc-types")));
+ this.writeJDBCToJavaMappingNodes(node.appendChild(document.createElement("jdbc-type-to-java-type-declaration-mappings")));
+ this.writeJavaToJDBCMappingNodes(node.appendChild(document.createElement("java-type-declaration-to-jdbc-type-mappings")));
+ }
+
+ private void writeJDBCTypeNodes(Node jdbcTypesNode) {
+ Document document = jdbcTypesNode.getOwnerDocument();
+ synchronized (this.jdbcTypes) {
+ for (Iterator<JDBCType> stream = new TreeSet<JDBCType>(this.jdbcTypes).iterator(); stream.hasNext(); ) {
+ Node jdbcTypeNode = document.createElement("jdbc-type");
+ jdbcTypesNode.appendChild(jdbcTypeNode);
+ stream.next().write(jdbcTypeNode);
+ }
+ }
+ }
+
+ private void writeJDBCToJavaMappingNodes(Node mappingsNode) {
+ Document document = mappingsNode.getOwnerDocument();
+ synchronized (this.jdbcTypeToJavaTypeDeclarationMappings) {
+ for (Iterator<JDBCTypeToJavaTypeDeclarationMapping> stream = new TreeSet<JDBCTypeToJavaTypeDeclarationMapping>(this.jdbcTypeToJavaTypeDeclarationMappings).iterator(); stream.hasNext(); ) {
+ Node mappingNode = document.createElement("jdbc-type-to-java-type-declaration-mapping");
+ mappingsNode.appendChild(mappingNode);
+ stream.next().write(mappingNode);
+ }
+ }
+ }
+
+ private void writeJavaToJDBCMappingNodes(Node mappingsNode) {
+ Document document = mappingsNode.getOwnerDocument();
+ synchronized (this.javaTypeDeclarationToJDBCTypeMappings) {
+ for (Iterator<JavaTypeDeclarationToJDBCTypeMapping> stream = new TreeSet<JavaTypeDeclarationToJDBCTypeMapping>(this.javaTypeDeclarationToJDBCTypeMappings).iterator(); stream.hasNext(); ) {
+ Node mappingNode = document.createElement("java-type-declaration-to-jdbc-type-mapping");
+ mappingsNode.appendChild(mappingNode);
+ stream.next().write(mappingNode);
+ }
+ }
+ }
+
+
+ // ********** printing and displaying **********
+
+ private String brackets(int arrayDepth) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < arrayDepth; i++) {
+ sb.append("[]");
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public String displayString() {
+ return StringTools.EMPTY_STRING;
+ }
+
+ public void toString(StringBuffer sb) {
+ sb.append(this.jdbcTypes.size() + " JDBC types");
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCTypeToDatabaseTypeMapping.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCTypeToDatabaseTypeMapping.java
new file mode 100644
index 0000000..42f48e5
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCTypeToDatabaseTypeMapping.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import org.eclipse.persistence.tools.utility.XMLTools;
+import org.eclipse.persistence.tools.utility.node.AbstractNode;
+import org.w3c.dom.Node;
+
+/**
+ * Map a JDBC type to the appropriate platform-specific database type. Every platform must specify a
+ * database type for every possible JDBC type. The JDBC type cannot be changed.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class JDBCTypeToDatabaseTypeMapping extends AbstractNode {
+
+ /** The JDBC type is set upon construction and is immutable. */
+ private JDBCType jdbcType;
+
+ /** The platform-specific database type corresponding to the JDBC type. */
+ private DatabaseType databaseType;
+ public static final String DATABASE_TYPE_PROPERTY = "databaseType";
+
+ // ********** constructors **********
+
+ /**
+ * this constructor is called when the mapping is read from an XML file
+ */
+ JDBCTypeToDatabaseTypeMapping(DatabasePlatform platform, Node node) throws CorruptXMLException {
+ super(platform);
+ this.read(node);
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new mapping (which shouldn't happen very often,
+ * since all the typical mappings have already been built...)
+ */
+ JDBCTypeToDatabaseTypeMapping(DatabasePlatform platform, JDBCType jdbcType) {
+ super(platform);
+ if (jdbcType == null) {
+ throw new NullPointerException();
+ }
+ this.jdbcType = jdbcType;
+ }
+
+
+ // ********** accessors **********
+
+ private DatabasePlatform getPlatform() {
+ return (DatabasePlatform) this.getParent();
+ }
+
+ public JDBCType getJDBCType() {
+ return this.jdbcType;
+ }
+
+ public DatabaseType getDatabaseType() {
+ return this.databaseType;
+ }
+
+ public void setDatabaseType(DatabaseType databaseType) {
+ Object old = this.databaseType;
+ this.databaseType = databaseType;
+ this.firePropertyChanged(DATABASE_TYPE_PROPERTY, old, databaseType);
+ }
+
+
+ // ********** queries **********
+
+ boolean maps(JDBCType type) {
+ return this.jdbcType == type;
+ }
+
+ boolean maps(int jdbcTypeCode) {
+ return this.jdbcType.getCode() == jdbcTypeCode;
+ }
+
+ private JDBCType jdbcTypeNamed(String jdbcTypeName) {
+ return this.getPlatform().jdbcTypeNamed(jdbcTypeName);
+ }
+
+ private DatabaseType databaseTypeNamed(String databaseTypeName) {
+ return this.getPlatform().databaseTypeNamed(databaseTypeName);
+ }
+
+
+ // ********** behavior **********
+
+ /**
+ * copy all the settings from the original platform
+ * to this, newly-created, platform
+ */
+ void cloneFrom(JDBCTypeToDatabaseTypeMapping originalMapping) {
+ // the jdbcType has been set by the time we get here
+ DatabaseType originalDatabaseType = originalMapping.getDatabaseType();
+ if (originalDatabaseType != null) {
+ this.databaseType = this.databaseTypeNamed(originalDatabaseType.getName());
+ }
+ }
+
+
+ // ********** i/o **********
+
+ private void read(Node node) throws CorruptXMLException {
+ try {
+ this.jdbcType = this.jdbcTypeNamed(XMLTools.childTextContent(node, "jdbc-type", null));
+ } catch (IllegalArgumentException ex) {
+ throw new CorruptXMLException("platform: " + this.getPlatform().getName(), ex);
+ }
+ String databaseTypeName = XMLTools.childTextContent(node, "database-type", null);
+ if (databaseTypeName != null) {
+ try {
+ this.databaseType = this.databaseTypeNamed(databaseTypeName);
+ } catch (IllegalArgumentException ex) {
+ throw new CorruptXMLException(ex);
+ }
+ }
+ }
+
+ void write(Node node) {
+ XMLTools.addSimpleTextNode(node, "jdbc-type", this.jdbcType.getName());
+ if (this.databaseType != null) {
+ XMLTools.addSimpleTextNode(node, "database-type", this.databaseType.getName());
+ }
+ }
+
+
+ // ********** printing and displaying **********
+
+ private void displayStringOn(StringBuffer sb) {
+ sb.append(this.jdbcType.getName());
+ sb.append(" => ");
+ sb.append(this.databaseType == null ? "null" : this.databaseType.getName());
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.utility.Node#displayString()
+ */
+ @Override
+ public String displayString() {
+ StringBuffer sb = new StringBuffer();
+ this.displayStringOn(sb);
+ return sb.toString();
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.utility.model.workbench.utility.AbstractModel#toString(StringBuffer)
+ */
+ public void toString(StringBuffer sb) {
+ this.displayStringOn(sb);
+ }
+
+}
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCTypeToJavaTypeDeclarationMapping.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCTypeToJavaTypeDeclarationMapping.java
new file mode 100644
index 0000000..f0dfd75
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JDBCTypeToJavaTypeDeclarationMapping.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import org.w3c.dom.Node;
+
+/**
+ * Map a JDBC type to the appropriate Java type declaration. These are used to generate classes from
+ * tables. The JDBC type cannot be changed.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class JDBCTypeToJavaTypeDeclarationMapping extends AbstractJDBCTypeToJavaTypeDeclarationMapping {
+
+ // the JDBC type can never be replaced once the mapping is built
+ public static final String JAVA_TYPE_DECLARATION_PROPERTY = "javaTypeDeclaration";
+
+ // ********** constructors **********
+
+ /**
+ * this constructor is called when the mapping is read from an XML file
+ */
+ JDBCTypeToJavaTypeDeclarationMapping(JDBCTypeRepository repository, Node node) throws CorruptXMLException {
+ super(repository, node);
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new mapping (which shouldn't happen very often,
+ * since all the typical mappings have already been built...)
+ */
+ JDBCTypeToJavaTypeDeclarationMapping(JDBCTypeRepository repository, JDBCType jdbcType, String javaClassName, int arrayDepth) {
+ super(repository, jdbcType, javaClassName, arrayDepth);
+ }
+
+
+ // ********** accessors **********
+
+ /**
+ * Set the Java type declaration corresponding to the JDBC type.
+ */
+ public void setJavaTypeDeclaration(String javaClassName, int arrayDepth) {
+ Object old = this.javaTypeDeclaration;
+ this.javaTypeDeclaration = new JavaTypeDeclaration(this, javaClassName, arrayDepth);
+ this.firePropertyChanged(JAVA_TYPE_DECLARATION_PROPERTY, old, this.javaTypeDeclaration);
+ }
+
+
+ // ********** queries **********
+
+ boolean maps(int jdbcTypeCode) {
+ return this.jdbcType.getCode() == jdbcTypeCode;
+ }
+
+ boolean maps(JDBCType type) {
+ return this.jdbcType == type;
+ }
+
+
+ // ********** i/o **********
+
+ @Override
+ void write(Node node) {
+ this.writeJDBCType(node);
+ this.writeJavaTypeDeclaration(node);
+ }
+
+
+ // ********** printing and displaying **********
+
+ /**
+ * @see AbstractJDBCTypeToJavaTypeDeclarationMapping#displayStringOn(StringBuffer)
+ */
+ @Override
+ public void displayStringOn(StringBuffer sb) {
+ sb.append(this.jdbcType.getName());
+ sb.append(" => ");
+ this.javaTypeDeclaration.displayStringOn(sb);
+ }
+
+}
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JavaTypeDeclaration.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JavaTypeDeclaration.java
new file mode 100644
index 0000000..01cb2d8
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JavaTypeDeclaration.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import org.eclipse.persistence.tools.utility.XMLTools;
+import org.eclipse.persistence.tools.utility.node.AbstractNode;
+import org.w3c.dom.Node;
+
+/**
+ * This class describes a Java type declaration; i.e. a type declaration's
+ * Java class and its array depth. The Java class is referenced by name,
+ * allowing us to reference classes that are not (or cannot be) loaded.
+ *
+ * This class's state is immutable - once an instance is built, its state
+ * cannot be changed. If you want a different declaration, you will need
+ * to build another instance, which isn't all that painful.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class JavaTypeDeclaration extends AbstractNode {
+
+ /**
+ * store the class as a name, so we can reference classes
+ * that are not loaded
+ */
+ private String javaClassName;
+
+ /**
+ * non-array classes have an array depth of zero
+ */
+ private int arrayDepth;
+
+ // ********** constructors **********
+
+ /**
+ * this constructor is called when the type declaration is read from an XML file
+ */
+ JavaTypeDeclaration(AbstractNode parent, Node node) throws CorruptXMLException {
+ super(parent);
+ this.read(node);
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new type declaration
+ */
+ JavaTypeDeclaration(AbstractNode parent, String javaClassName, int arrayDepth) {
+ super(parent);
+ this.javaClassName = javaClassName;
+ this.arrayDepth = arrayDepth;
+ this.checkState();
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new type declaration with an array depth of zero
+ */
+ JavaTypeDeclaration(AbstractNode parent, String javaClassName) {
+ this(parent, javaClassName, 0);
+ }
+
+
+ // ********** accessors **********
+
+ /**
+ * Returns the "element" name of the Java type declaration.
+ */
+ public String getJavaClassName() {
+ return this.javaClassName;
+ }
+
+ /**
+ * Returns the "array depth" of the Java type declaration.
+ */
+ public int getArrayDepth() {
+ return this.arrayDepth;
+ }
+
+
+ // ********** queries **********
+
+ /**
+ * there can be multiple instances of the same Java type
+ * declaration, so provide some way of comparing them
+ */
+ boolean equals(String otherJavaClassName, int otherArrayDepth) {
+ return this.javaClassName.equals(otherJavaClassName)
+ && this.arrayDepth == otherArrayDepth;
+ }
+
+ /**
+ * there can be multiple instances of the same Java type
+ * declaration, so provide some way of comparing them
+ */
+ boolean equals(JavaTypeDeclaration other) {
+ return this.equals(other.javaClassName, other.arrayDepth);
+ }
+
+
+ // ********** behavior **********
+
+ private void checkState() {
+ if ((this.javaClassName == null) || (this.javaClassName.length() == 0)) {
+ throw new IllegalStateException("Java class name is required");
+ }
+
+ if (this.arrayDepth < 0) {
+ throw new IllegalStateException("array depth must be greater than or equal to zero: " + this.arrayDepth);
+ }
+ if (this.javaClassName.equals(void.class.getName()) && (this.arrayDepth != 0)) {
+ throw new IllegalStateException("'void' must have an array depth of zero: " + this.arrayDepth);
+ }
+ }
+
+
+ // ********** i/o **********
+
+ private void read(Node node) throws CorruptXMLException {
+ if (node == null) {
+ throw new CorruptXMLException("missing node");
+ }
+ this.javaClassName = XMLTools.childTextContent(node, "java-class-name", null);
+ this.arrayDepth = XMLTools.childIntContent(node, "array-depth", 0);
+ try {
+ this.checkState();
+ } catch (IllegalStateException ex) {
+ throw new CorruptXMLException("illegal state: " + this, ex);
+ }
+ }
+
+ void write(Node node) {
+ XMLTools.addSimpleTextNode(node, "java-class-name", this.javaClassName);
+ XMLTools.addSimpleTextNode(node, "array-depth", this.arrayDepth, 0);
+ }
+
+
+ // ********** printing and displaying **********
+
+ /**
+ * @see org.eclipse.persistence.tools.workbench.utility.Node#displayString()
+ */
+ @Override
+ public String displayString() {
+ StringBuffer sb = new StringBuffer();
+ this.displayStringOn(sb);
+ return sb.toString();
+ }
+
+ public void displayStringOn(StringBuffer sb) {
+ sb.append(this.javaClassName);
+ for (int i = this.arrayDepth; i-- > 0; ) {
+ sb.append("[]");
+ }
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.utility.model.workbench.utility.AbstractModel#toString(StringBuffer)
+ */
+ public void toString(StringBuffer sb) {
+ this.displayStringOn(sb);
+ }
+
+}
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JavaTypeDeclarationToJDBCTypeMapping.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JavaTypeDeclarationToJDBCTypeMapping.java
new file mode 100644
index 0000000..74b6c98
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/platformsmodel/JavaTypeDeclarationToJDBCTypeMapping.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.platformsmodel;
+
+import org.w3c.dom.Node;
+
+/**
+ * Map a Java type declaration to the appropriate JDBC type.
+ * These are used to generate tables from classes.
+ * The Java type declaration cannot be changed.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class JavaTypeDeclarationToJDBCTypeMapping extends AbstractJDBCTypeToJavaTypeDeclarationMapping {
+
+ // the Java type declaration can never be replaced once the mapping is built
+ public static final String JDBC_TYPE_PROPERTY = "jdbcType";
+
+ // ********** constructors **********
+
+ /**
+ * this constructor is called when the mapping is read from an XML file
+ */
+ JavaTypeDeclarationToJDBCTypeMapping(JDBCTypeRepository repository, Node node) throws CorruptXMLException {
+ super(repository, node);
+ }
+
+ /**
+ * this constructor is called when the user (or a test case)
+ * creates a new mapping (which shouldn't happen very often,
+ * since all the typical mappings have already been built...)
+ */
+ JavaTypeDeclarationToJDBCTypeMapping(JDBCTypeRepository repository, String javaClassName, int arrayDepth, JDBCType jdbcType) {
+ super(repository, jdbcType, javaClassName, arrayDepth);
+ }
+
+
+ // ********** accessors **********
+
+ /**
+ * Set the JDBC type corresponding to the Java type declaration.
+ */
+ public void setJDBCType(JDBCType jdbcType) {
+ if (jdbcType == null) {
+ throw new NullPointerException();
+ }
+ Object old = this.jdbcType;
+ this.jdbcType = jdbcType;
+ this.firePropertyChanged(JDBC_TYPE_PROPERTY, old, jdbcType);
+ }
+
+
+ // ********** queries **********
+
+ boolean maps(String javaClassName, int arrayDepth) {
+ return this.javaTypeDeclaration.equals(javaClassName, arrayDepth);
+ }
+
+
+ // ********** i/o **********
+
+ @Override
+ void write(Node node) {
+ this.writeJavaTypeDeclaration(node);
+ this.writeJDBCType(node);
+ }
+
+
+ // ********** printing and displaying **********
+
+ /**
+ * @see AbstractJDBCTypeToJavaTypeDeclarationMapping#displayStringOn(StringBuffer)
+ */
+ @Override
+ public void displayStringOn(StringBuffer sb) {
+ this.javaTypeDeclaration.displayStringOn(sb);
+ sb.append(" => ");
+ sb.append(this.jdbcType.getName());
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalColumn.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalColumn.java
new file mode 100644
index 0000000..d57eccd
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalColumn.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi;
+
+/**
+ * Interface describing the meta-data describing a database column.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @see ExternalTable
+ * @version 2.5
+ */
+public interface ExternalColumn {
+
+ /**
+ * Returns the JDBC type code for the column's datatype
+ * (e.g. java.sql.Types.VARCHAR).
+ */
+ int getJDBCTypeCode();
+
+ /**
+ * Returns the column's unqualified name.
+ */
+ String getName();
+
+ /**
+ * Returns the column's scale. If the column does not have a scale
+ * Returns zero. Typically a column defined as a decimal numeric
+ * datatype will have a scale.
+ */
+ int getScale();
+
+ /**
+ * Returns the column's size. If the column does not have a size
+ * Returns zero.
+ */
+ int getSize();
+
+ /**
+ * Returns the name of the column's platform-specific datatype
+ * (e.g. "VARCHAR2").
+ */
+ String getTypeName();
+
+ /**
+ * Returns whether the column allows null.
+ */
+ boolean isNullable();
+
+ /**
+ * Returns whether the column is part of the table's primary key.
+ */
+ boolean isPrimaryKey();
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalDatabase.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalDatabase.java
new file mode 100644
index 0000000..cb1808f
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalDatabase.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi;
+
+/**
+ * Interface for an external database that can be queried for metadata.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @see ExternalDatabaseFactory
+ * @version 2.5
+ */
+public interface ExternalDatabase {
+
+ /**
+ * Returns the database's catalog names.
+ * What connotes a "catalog" is typically platform-dependent.
+ */
+ String[] getCatalogNames();
+
+ /**
+ * Returns the database's schema names.
+ * What connotes a "schema" is typically platform-dependent.
+ */
+ String[] getSchemaNames();
+
+ /**
+ * Returns all the database's table descriptions.
+ * Depending on the implementation and/or runtime configuration, clients
+ * will use this method or #getTableDescriptions(String, String, String, String[]).
+ */
+ ExternalTableDescription[] getTableDescriptions();
+
+ /**
+ * Returns the database's table descriptions corresponding to the specified
+ * search criteria.
+ * Depending on the implementation and/or runtime configuration, clients
+ * will use this method or #getTableDescriptions().
+ * @see java.sql.DatabaseMetaData#getTables(String, String, String, String[])
+ */
+ ExternalTableDescription[] getTableDescriptions(String catalogName, String schemaNamePattern, String tableNamePattern, String[] tableTypeNames);
+
+ /**
+ * Returns the database's table types.
+ * What connotes a "table type" is typically platform-dependent.
+ */
+ String[] getTableTypeNames();
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalDatabaseFactory.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalDatabaseFactory.java
new file mode 100644
index 0000000..7da8d0f
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalDatabaseFactory.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi;
+
+import java.sql.Connection;
+
+/**
+ * Simple factory interface for building external databases.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @version 2.5
+ */
+public interface ExternalDatabaseFactory {
+
+ /**
+ * Returns an {@link ExternalDatabase} for the specified connection. The connection will be <code>null</code>
+ * if a connection to a database has not been established or is inappropriate. The connection can
+ * be ignored, as appropriate.
+ */
+ ExternalDatabase buildDatabase(Connection connection);
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalForeignKey.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalForeignKey.java
new file mode 100644
index 0000000..543cdf2
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalForeignKey.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi;
+
+/**
+ * Interface describing the meta-data describing a database foreign key.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @see ExternalTable
+ * @version 2.5
+ */
+public interface ExternalForeignKey {
+
+ /**
+ * Returns an array of the foreign key's column pairs. These pairs match up a foreign key column
+ * on the source table with a primary key column on the target table.
+ */
+ ExternalForeignKeyColumnPair[] getColumnPairs();
+
+ /**
+ * Returns the foreign key's name. Often this name is system-generated.
+ */
+ String getName();
+
+ /**
+ * Returns a description of the foreign key's target table.
+ */
+ ExternalTableDescription getTargetTableDescription();
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalForeignKeyColumnPair.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalForeignKeyColumnPair.java
new file mode 100644
index 0000000..e29bb9b
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalForeignKeyColumnPair.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi;
+
+/**
+ * Interface describing the meta-data describing a database foreign key.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @see ExternalForeignKey
+ * @version 2.5
+ */
+public interface ExternalForeignKeyColumnPair {
+
+ /**
+ * Returns the "source" half of the column pair. This is the column on the source table that must
+ * contain a value that matches the value in the target column.
+ */
+ ExternalColumn getSourceColumn();
+
+ /**
+ * Returns the "target" half of the column pair. This is typically a column that is part of the
+ * target table's primary key.
+ */
+ ExternalColumn getTargetColumn();
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalTable.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalTable.java
new file mode 100644
index 0000000..d13f945
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalTable.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi;
+
+/**
+ * Interface defining the table meta-data.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @see ExternalTableDescription
+ * @version 2.5
+ */
+public interface ExternalTable {
+
+ /**
+ * Returns an array of the table's columns.
+ */
+ ExternalColumn[] getColumns();
+
+ /**
+ * Returns an array of the table's foreign keys.
+ */
+ ExternalForeignKey[] getForeignKeys();
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalTableDescription.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalTableDescription.java
new file mode 100644
index 0000000..4c4d61f
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/ExternalTableDescription.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi;
+
+/**
+ * Interface defining a lightweight wrapper around the database metadata.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @see ExternalDatabase
+ * @version 2.5
+ */
+public interface ExternalTableDescription extends TableDescription {
+
+ /**
+ * Returns the ExternalTable object corresponding to this {@link ExternalTableDescription} object.
+ * This allows this <code>ExternalTableDescription</code> to postpone loading extra meta-data
+ * until it is actually needed. The name and description are required beforehand because they are
+ * used by the user to select an {@link ExternalTable} to load.
+ */
+ ExternalTable getTable();
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/TableDescription.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/TableDescription.java
new file mode 100644
index 0000000..9ba81af
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/TableDescription.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi;
+
+/**
+ * This defines a common interface for all the tables (internal, external, and user-defined)
+ * so they can be consolidated whenever necessary (e.g. in the UI choosers).
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @version 2.5
+ */
+public interface TableDescription {
+
+ /**
+ * Returns any additional information about the table represented by this <code>TableDescription</code>,
+ * as a string. This information can be used to differentiate among <code>TableDescription</code>
+ * objects that might have the same name.
+ */
+ String getAdditionalInfo();
+
+ /**
+ * Returns the table's "catalog" name.
+ */
+ String getCatalogName();
+
+ /**
+ * Returns the table's unqualified name.
+ */
+ String getName();
+
+ /**
+ * Returns the table's fully-qualified name, typically in the form "catalog.schema.name".
+ */
+ String getQualifiedName();
+
+ /**
+ * Returns the table's "schema" name.
+ */
+ String getSchemaName();
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalColumn.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalColumn.java
new file mode 100644
index 0000000..4b4fb4a
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalColumn.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.eclipse.persistence.tools.db.relational.spi.ExternalColumn;
+import org.eclipse.persistence.tools.utility.StringTools;
+
+/**
+ * @see comment about defensive programming at JDBCExternalDatabase
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+final class JDBCExternalColumn implements ExternalColumn {
+ private final String name;
+ private final String typeName;
+ private final int jdbcTypeCode;
+ private final int size;
+ private final int scale; // used by fixed point numbers only
+ private final boolean nullable;
+ private boolean primaryKey; // pseudo-final
+
+
+ // ********** constructor/initialization **********
+
+ /**
+ * Construct an external column with the data from the current
+ * row of the specified result set.
+ * @see java.sql.DatabaseMetaData#getColumns(String, String, String, String)
+ */
+ JDBCExternalColumn(ResultSet resultSet) throws SQLException {
+ super();
+
+ // the name is required, the other settings can be fudged
+ this.name = resultSet.getString(4).trim(); // COLUMN_NAME
+ if (this.name.length() == 0) {
+ throw new IllegalStateException("empty column name");
+ }
+
+ this.typeName = this.typeNameFrom(resultSet);
+ this.jdbcTypeCode = this.jdbcTypeCodeFrom(resultSet);
+ this.size = this.sizeFrom(resultSet);
+ this.scale = this.scaleFrom(resultSet);
+ this.nullable = this.nullableFrom(resultSet);
+
+ // 'primaryKey' will be set later by the table
+ }
+
+ private String typeNameFrom(ResultSet resultSet) {
+ try {
+ return this.trim(resultSet.getString(6)); // TYPE_NAME
+ } catch (SQLException ex) {
+ // * Returns null if TYPE_NAME is not supported by the driver
+ return null;
+ }
+ }
+
+ private int jdbcTypeCodeFrom(ResultSet resultSet) {
+ try {
+ return resultSet.getInt(5); // DATA_TYPE
+ } catch (SQLException ex) {
+ // * Returns NULL(?) if DATA_TYPE is not supported by the driver
+ return Types.NULL;
+ }
+ }
+
+ private int sizeFrom(ResultSet resultSet) {
+ try {
+ return resultSet.getInt(7); // COLUMN_SIZE
+ } catch (SQLException ex) {
+ // * Returns 0 if COLUMN_SIZE is not supported by the driver
+ return 0;
+ }
+ }
+
+ private int scaleFrom(ResultSet resultSet) {
+ try {
+ return resultSet.getInt(9); // DECIMAL_DIGITS
+ } catch (SQLException ex) {
+ // * Returns 0 if DECIMAL_DIGITS is not supported by the driver
+ return 0;
+ }
+ }
+
+ /**
+ * use IS_NULLABLE, since NULLABLE is pretty much useless;
+ * confusing... see the JDK JavaDocs...
+ */
+ private boolean nullableFrom(ResultSet resultSet) {
+ String jdbc_IS_NULLABLE = null;
+ try {
+ jdbc_IS_NULLABLE = resultSet.getString(18); // IS_NULLABLE
+ } catch (SQLException ex) {
+ // defensive - continue with 'null' if IS_NULLABLE is not supported by the driver
+ }
+
+ // * Returns fixed-length strings
+ // if this is "NO", the column is *definitely* required (NOT NULL);
+ // * Returns true
+ if ((jdbc_IS_NULLABLE != null) && jdbc_IS_NULLABLE.trim().toUpperCase().equals("NO")) {
+ return false;
+ }
+
+ // NULLABLE (column 11) cannot tell us anything *definite* except that
+ // * Returns true
+ return true;
+ }
+
+ /**
+ * trim down the specified string, to null if necessary
+ */
+ private String trim(String s) {
+ if (s == null) {
+ return null;
+ }
+ s = s.trim();
+ return (s.length() == 0) ? null : s;
+ }
+
+
+ // ********** ExternalColumn implementation **********
+
+ /**
+ * the name should never be null or empty
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalColumn#getName()
+ */
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * the type name can be null if we have problems reading the result set
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalColumn#getTypeName()
+ */
+ @Override
+ public String getTypeName() {
+ return this.typeName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getJDBCTypeCode() {
+ return this.jdbcTypeCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getSize() {
+ return this.size;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getScale() {
+ return this.scale;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isNullable() {
+ return this.nullable;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isPrimaryKey() {
+ return this.primaryKey;
+ }
+
+
+ // ********** queries **********
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.name);
+ }
+
+
+ // ********** behavior **********
+
+ /**
+ * the primary key flag is set by the table soon after construction
+ */
+ void setPrimaryKey(boolean primaryKey) {
+ this.primaryKey = primaryKey;
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalDatabase.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalDatabase.java
new file mode 100644
index 0000000..0773b47
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalDatabase.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi.jdbc;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+import org.eclipse.persistence.tools.db.relational.spi.ExternalDatabase;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription;
+import org.eclipse.persistence.tools.utility.CollectionTools;
+import org.eclipse.persistence.tools.utility.StringTools;
+import org.eclipse.persistence.tools.utility.iterators.ResultSetIterator;
+
+/**
+ * This external database derives all of its metadata from a client-supplied JDBC connection.
+ *
+ * All the JDBC implementation classes have an embarassing
+ * preponderance of "defensive" programming that allow us to
+ * work with even the most misbehaved of JDBC drivers. This is
+ * because most of the exceptions encountered are the result
+ * of bugs in the wide variety of JDBC drivers we interact with,
+ * not bugs in Workbench code. (At least that's the hope....)
+ * An alternative to the various bits of defensive programming,
+ * we could pass in a listener whenever there is the possibility
+ * of an (SQL) exception. The listener would be notified of any
+ * exceptions, but we would continue processing with pre-
+ * determined defaults.
+ * ~bjv
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+final class JDBCExternalDatabase implements ExternalDatabase {
+ private final Connection connection;
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ /**
+ *
+ */
+ JDBCExternalDatabase(Connection connection) {
+ super();
+ this.connection = connection;
+ }
+
+
+ // ********** ExternalDatabase implementation **********
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalDatabase#getCatalogNames()
+ */
+ @Override
+ public String[] getCatalogNames() {
+ ResultSet resultSet;
+ try {
+ resultSet = this.metaData().getCatalogs();
+ } catch (SQLException ex) {
+ return EMPTY_STRING_ARRAY; // defensive - this is not fatal if unsupported by driver
+ }
+ return this.buildStringArray(resultSet);
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalDatabase#getSchemaNames()
+ */
+ @Override
+ public String[] getSchemaNames() {
+ ResultSet resultSet;
+ try {
+ resultSet = this.metaData().getSchemas();
+ } catch (SQLException ex) {
+ return EMPTY_STRING_ARRAY; // defensive - this is not fatal if unsupported by driver
+ }
+ return this.buildStringArray(resultSet);
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalDatabase#getTableTypeNames()
+ */
+ @Override
+ public String[] getTableTypeNames() {
+ ResultSet resultSet;
+ try {
+ resultSet = this.metaData().getTableTypes();
+ } catch (SQLException ex) {
+ return EMPTY_STRING_ARRAY; // defensive - this is not fatal if unsupported by driver
+ }
+ return this.buildStringArray(resultSet);
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalDatabase#getTableDescriptions(String, String, String, String[])
+ */
+ @Override
+ public ExternalTableDescription[] getTableDescriptions(String catalogName, String schemaNamePattern, String tableNamePattern, String[] tableTypeNames) {
+ // #setCatalog(String) is used by Sybase, MS SQL Server, and others(?)
+ // to set a "local context" for later interactions with the server;
+ // "If the driver does not support catalogs, it will silently ignore this request."
+ if (catalogName != null) {
+ try {
+ this.getConnection().setCatalog(catalogName);
+ } catch (SQLException ex) {
+ // see comment above...
+ throw new RuntimeException(ex);
+ }
+ }
+
+ ResultSet resultSet;
+ try {
+ resultSet = this.metaData().getTables(catalogName, schemaNamePattern, tableNamePattern, tableTypeNames);
+ } catch (SQLException ex) {
+ // if #getTables() does not work, there's not much we can do...
+ throw new RuntimeException(ex);
+ }
+ List<ExternalTableDescription> tableDescriptions = CollectionTools.list(new ResultSetIterator<ExternalTableDescription>(
+ resultSet,
+ new ExternalTableDescriptionResultSetAdapter())
+ );
+ return tableDescriptions.toArray(new ExternalTableDescription[tableDescriptions.size()]);
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalDatabase#getTableDescriptions()
+ */
+ @Override
+ public ExternalTableDescription[] getTableDescriptions() {
+ // query for *all* the tables on the database - could be painful...
+ return this.getTableDescriptions(null, null, "%", null);
+ }
+
+
+ // ********** queries **********
+
+ private Connection getConnection() {
+ if (this.connection == null) {
+ throw new IllegalStateException("not connected");
+ }
+ return this.connection;
+ }
+
+ DatabaseMetaData metaData() {
+ try {
+ return this.getConnection().getMetaData();
+ } catch (SQLException ex) {
+ // if we can't get meta-data, there's not much we can do...
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+
+
+ // ********** behavior **********
+
+ /**
+ * convert the specified single-column result set to an array of strings
+ */
+ private String[] buildStringArray(ResultSet resultSet) {
+ List<String> strings = CollectionTools.list(new ResultSetIterator<String>(resultSet, new StringResultSetAdapter()));
+ return strings.toArray(new String[strings.size()]);
+ }
+
+
+ // ********** inner classes **********
+
+ /**
+ * Trim a single-column result set of strings.
+ */
+ private static class StringResultSetAdapter implements ResultSetIterator.Adapter<String> {
+ @Override
+ public String buildNext(ResultSet rs) throws SQLException {
+ // result set column indexes are 1-based
+ String string = rs.getString(1);
+ // * Returns fixed-length strings
+ return (string == null) ? null : string.trim();
+ }
+ }
+
+ /**
+ * Convert the rows into external table descriptions.
+ * @see java.sql.DatabaseMetaData#getTables(String, String, String, String[])
+ */
+ private class ExternalTableDescriptionResultSetAdapter implements ResultSetIterator.Adapter<ExternalTableDescription> {
+ @Override
+ public ExternalTableDescription buildNext(ResultSet rs) throws SQLException {
+ return new JDBCExternalTableDescription(rs, JDBCExternalDatabase.this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalDatabaseFactory.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalDatabaseFactory.java
new file mode 100644
index 0000000..dc560f1
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalDatabaseFactory.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi.jdbc;
+
+import java.sql.Connection;
+
+import org.eclipse.persistence.tools.db.relational.spi.ExternalDatabase;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalDatabaseFactory;
+import org.eclipse.persistence.tools.utility.StringTools;
+
+/**
+ * Not much to say here: This is a factory for generating instances of
+ * the "JDBC" implementation of ExternalDatabase, which uses a
+ * java.sql.Connection ExternalTables etc.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+public final class JDBCExternalDatabaseFactory implements ExternalDatabaseFactory {
+
+ /** the singleton */
+ private static ExternalDatabaseFactory INSTANCE;
+
+ /**
+ * Singleton support.
+ */
+ public static synchronized ExternalDatabaseFactory instance() {
+ if (INSTANCE == null) {
+ INSTANCE = new JDBCExternalDatabaseFactory();
+ }
+ return INSTANCE;
+ }
+
+ /**
+ * Private constructor - use the singleton.
+ */
+ public JDBCExternalDatabaseFactory() {
+ super();
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalDatabaseFactory#buildDatabase(java.sql.Connection)
+ */
+ @Override
+ public ExternalDatabase buildDatabase(Connection connection) {
+ return new JDBCExternalDatabase(connection);
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, "singleton");
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalForeignKey.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalForeignKey.java
new file mode 100644
index 0000000..67c73d7
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalForeignKey.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKey;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKeyColumnPair;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription;
+import org.eclipse.persistence.tools.utility.StringTools;
+
+/**
+ *
+ * @version 2.5
+ */
+final class JDBCExternalForeignKey implements ExternalForeignKey {
+ private final JDBCExternalTable table;
+ private final String name;
+ private final ExternalTableDescription targetTableDescription;
+ private ExternalForeignKeyColumnPair[] columnPairs; // pseudo-final
+
+
+ // ********** constructor/initialization **********
+
+ /**
+ * Construct a "skeleton" external foreign key with the data from the current
+ * row of the specified result set. The column pairs will be added later.
+ * @see java.sql.DatabaseMetaData#getImportedKeys(String, String, String)
+ */
+ JDBCExternalForeignKey(JDBCExternalTable table, String name, ResultSet resultSet) {
+ super();
+ this.table = table;
+ this.name = name;
+ this.targetTableDescription = new JDBCExternalTableDescription(
+ this.stringFrom(resultSet, 1), // PKTABLE_CAT
+ this.stringFrom(resultSet, 2), // PKTABLE_SCHEM
+ this.stringFrom(resultSet, 3), // PKTABLE_NAME
+ this.database()
+ );
+ // the column pairs will be added by the table, momentarily
+ }
+
+ private String stringFrom(ResultSet resultSet, int colIndex) {
+ try {
+ return this.trim(resultSet.getString(colIndex));
+ } catch (SQLException ex) {
+ // * Returns null if the requested column is not supported by the driver
+ return null;
+ }
+ }
+
+ /**
+ * trim down the specified string, to null if necessary
+ */
+ private String trim(String s) {
+ if (s == null) {
+ return null;
+ }
+ s = s.trim();
+ return (s.length() == 0) ? null : s;
+ }
+
+
+ // ********** ExternalForeignKey implementation **********
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKey#getName()
+ */
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKey#getColumnPairs()
+ */
+ @Override
+ public ExternalForeignKeyColumnPair[] getColumnPairs() {
+ return this.columnPairs;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKey#getTargetTableDescription()
+ */
+ @Override
+ public ExternalTableDescription getTargetTableDescription() {
+ return this.targetTableDescription;
+ }
+
+
+ // ********** behavior **********
+
+ void addColumnPair(ResultSet resultSet) {
+ int len = (this.columnPairs == null) ? 0 : this.columnPairs.length;
+ JDBCExternalForeignKeyColumnPair[] temp = new JDBCExternalForeignKeyColumnPair[len + 1];
+ if (len != 0) {
+ System.arraycopy(this.columnPairs, 0, temp, 0, len);
+ }
+ temp[len] = new JDBCExternalForeignKeyColumnPair(this, resultSet);
+ this.columnPairs = temp;
+ }
+
+
+ // ********** queries **********
+
+ JDBCExternalColumn columnNamed(String columnName) {
+ return this.table.columnNamed(columnName);
+ }
+
+ private JDBCExternalDatabase database() {
+ return this.table.database();
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.name);
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalForeignKeyColumnPair.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalForeignKeyColumnPair.java
new file mode 100644
index 0000000..11ea660
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalForeignKeyColumnPair.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.eclipse.persistence.tools.db.relational.spi.ExternalColumn;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKeyColumnPair;
+import org.eclipse.persistence.tools.utility.StringTools;
+
+/**
+ * Associate a pair of columns from a foreign key that is made
+ * up of, possibly, multiple pairs of columns.
+ * Either column can be null if we have any problems gathering
+ * up the meta-data.
+ *
+ * @version 2.5
+ */
+@SuppressWarnings("nls")
+final class JDBCExternalForeignKeyColumnPair implements ExternalForeignKeyColumnPair {
+ private final JDBCExternalForeignKey foreignKey;
+ private final ExternalColumn sourceColumn;
+ private final ExternalColumn targetColumn;
+
+ // ********** constructor/initialization **********
+
+ /**
+ *
+ * @see java.sql.DatabaseMetaData#getImportedKeys(String, String, String)
+ */
+ JDBCExternalForeignKeyColumnPair(JDBCExternalForeignKey foreignKey, ResultSet resultSet) {
+ super();
+ this.foreignKey = foreignKey;
+ this.sourceColumn = this.columnNamed(this.stringFrom(resultSet, 8)); // FKCOLUMN_NAME
+ this.targetColumn = this.buildLocalColumn(this.stringFrom(resultSet, 4)); // PKCOLUMN_NAME
+ }
+
+ private String stringFrom(ResultSet resultSet, int colIndex) {
+ try {
+ return this.trim(resultSet.getString(colIndex));
+ } catch (SQLException ex) {
+ // * Returns null if the requested column is not supported by the driver
+ return null;
+ }
+ }
+
+ /**
+ * trim down the specified string, to null if necessary
+ */
+ private String trim(String s) {
+ if (s == null) {
+ return null;
+ }
+ s = s.trim();
+ return (s.length() == 0) ? null : s;
+ }
+
+
+ // ********** ExternalForeignKeyColumnPair implementation **********
+
+ /**
+ * the source column can be null if we have problems reading the result set
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKeyColumnPair#getSourceColumn()
+ */
+ @Override
+ public ExternalColumn getSourceColumn() {
+ return this.sourceColumn;
+ }
+
+ /**
+ * the target column can be null if we have problems reading the result set
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKeyColumnPair#getTargetColumn()
+ */
+ @Override
+ public ExternalColumn getTargetColumn() {
+ return this.targetColumn;
+ }
+
+
+ // ********** queries **********
+
+ private JDBCExternalColumn columnNamed(String columnName) {
+ return this.foreignKey.columnNamed(columnName);
+ }
+
+ private ExternalColumn buildLocalColumn(String columnName) {
+ return (columnName == null) ? null : new TargetColumn(columnName);
+ }
+
+ private String sourceColumnName() {
+ return (this.sourceColumn == null) ? null : this.sourceColumn.getName();
+ }
+
+ private String targetColumnName() {
+ return (this.targetColumn == null) ? null : this.targetColumn.getName();
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.sourceColumnName() + "=>" + this.targetColumnName());
+ }
+
+
+ // ********** member class **********
+
+ /**
+ * Returns its name;
+ * all other operations are unsupported
+ */
+ private static class TargetColumn implements ExternalColumn {
+ private final String name;
+ TargetColumn(String name) {
+ super();
+ if (name == null) {
+ throw new NullPointerException();
+ }
+ this.name = name;
+ }
+ @Override
+ public String getName() {
+ return this.name;
+ }
+ @Override
+ public int getJDBCTypeCode() {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public String getTypeName() {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public int getSize() {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public int getScale() {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean isNullable() {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean isPrimaryKey() {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.name);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalTable.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalTable.java
new file mode 100644
index 0000000..9dd734b
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalTable.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi.jdbc;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+import org.eclipse.persistence.tools.db.relational.spi.ExternalColumn;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKey;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalTable;
+import org.eclipse.persistence.tools.utility.StringTools;
+
+/**
+ * see comment about defensive programming at JDBCExternalDatabase
+ *
+ * @version 2.5
+ */
+final class JDBCExternalTable implements ExternalTable {
+ private final JDBCExternalTableDescription tableDescription;
+ private final JDBCExternalColumn[] columns;
+ private final ExternalForeignKey[] foreignKeys;
+
+ private static final JDBCExternalForeignKey[] EMPTY_FOREIGN_KEYS = new JDBCExternalForeignKey[0];
+
+ // ********** constructor/initialization **********
+
+ /**
+ *
+ */
+ JDBCExternalTable(JDBCExternalTableDescription tableDescription) throws SQLException {
+ super();
+ this.tableDescription = tableDescription;
+ this.columns = this.buildColumns();
+ this.markPrimaryKeyColumns();
+ this.foreignKeys = this.buildForeignKeys();
+ }
+
+ /**
+ * query the database for the table's columns
+ * @see java.sql.DatabaseMetaData#getColumns(String, String, String, String)
+ */
+ private JDBCExternalColumn[] buildColumns() throws SQLException {
+ Collection<JDBCExternalColumn> cols = new ArrayList<JDBCExternalColumn>();
+ ResultSet resultSet = this.metaData().getColumns(
+ this.tableDescription.getCatalogName(),
+ this.tableDescription.getSchemaName(),
+ this.tableDescription.getName(),
+ null
+ );
+ while (resultSet.next()) {
+ cols.add(new JDBCExternalColumn(resultSet));
+ }
+ resultSet.close();
+ return cols.toArray(new JDBCExternalColumn[cols.size()]);
+ }
+
+ private void markPrimaryKeyColumns() {
+ Collection<String> pkColNames = this.primaryKeyColumnNames();
+ for (int i = this.columns.length; i-- > 0; ) {
+ JDBCExternalColumn column = this.columns[i];
+ column.setPrimaryKey(pkColNames.contains(column.getName()));
+ }
+ }
+
+ /**
+ * defensive wrapper
+ */
+ private Collection<String> primaryKeyColumnNames() {
+ try {
+ return this.primaryKeyColumnNames2();
+ } catch (SQLException ex) {
+ // defensive - this is not fatal if unsupported by driver
+ }
+ return Collections.emptySet();
+ }
+
+ /**
+ * Returns the names of the table's primary key columns
+ * @see java.sql.DatabaseMetaData#getPrimaryKeys(String, String, String)
+ */
+ private Collection<String> primaryKeyColumnNames2() throws SQLException {
+ Collection<String> names = new HashSet<String>();
+ ResultSet resultSet = this.metaData().getPrimaryKeys(
+ this.tableDescription.getCatalogName(),
+ this.tableDescription.getSchemaName(),
+ this.tableDescription.getName()
+ );
+ while (resultSet.next()) {
+ // * Returns fixed-length strings
+ names.add(resultSet.getString(4).trim()); // COLUMN_NAME
+ }
+ resultSet.close();
+ return names;
+ }
+
+ /**
+ * defensive wrapper
+ */
+ private JDBCExternalForeignKey[] buildForeignKeys() {
+ try {
+ return this.buildForeignKeys2();
+ } catch (SQLException ex) {
+ // defensive - this is not fatal if unsupported by driver
+ }
+ return EMPTY_FOREIGN_KEYS;
+ }
+
+ /**
+ * query the database for the table's foreign keys
+ * @see java.sql.DatabaseMetaData#getImportedKeys(String, String, String)
+ */
+ private JDBCExternalForeignKey[] buildForeignKeys2() throws SQLException {
+ Collection<JDBCExternalForeignKey> fKeys = new ArrayList<JDBCExternalForeignKey>();
+ ResultSet resultSet = this.metaData().getImportedKeys(
+ this.tableDescription.getCatalogName(),
+ this.tableDescription.getSchemaName(),
+ this.tableDescription.getName()
+ );
+ while (resultSet.next()) {
+ String fKeyName = resultSet.getString(12).trim(); // FK_NAME
+ JDBCExternalForeignKey fKey = this.foreignKeyNamed(fKeyName, fKeys);
+ if (fKey == null) {
+ fKey = new JDBCExternalForeignKey(this, fKeyName, resultSet);
+ fKeys.add(fKey);
+ }
+ fKey.addColumnPair(resultSet);
+ }
+ resultSet.close();
+ return fKeys.toArray(new JDBCExternalForeignKey[fKeys.size()]);
+ }
+
+ /**
+ * search the specified collection of foreign keys for the foreign
+ * key with the specified name; assume(?) that foreign keys with
+ * the same name have the same target table
+ */
+ private JDBCExternalForeignKey foreignKeyNamed(String fKeyName, Collection<JDBCExternalForeignKey> fKeys) {
+ for (JDBCExternalForeignKey fKey : fKeys) {
+ if (fKey.getName().equals(fKeyName)) {
+ return fKey;
+ }
+ }
+ return null;
+ }
+
+
+ // ********** ExternalTable implementation **********
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ExternalColumn[] getColumns() {
+ return this.columns;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ExternalForeignKey[] getForeignKeys() {
+ return this.foreignKeys;
+ }
+
+
+ // ********** queries **********
+
+ private DatabaseMetaData metaData() {
+ return this.tableDescription.metaData();
+ }
+
+ JDBCExternalDatabase database() {
+ return this.tableDescription.getDatabase();
+ }
+
+ JDBCExternalColumn columnNamed(String columnName) {
+ for (int i = this.columns.length; i-- > 0; ) {
+ JDBCExternalColumn column = this.columns[i];
+ if (column.getName().equals(columnName)) {
+ return column;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.tableDescription.getQualifiedName());
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalTableDescription.java b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalTableDescription.java
new file mode 100644
index 0000000..51831d3
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.db/src/org/eclipse/persistence/tools/db/relational/spi/jdbc/JDBCExternalTableDescription.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation from Oracle TopLink
+******************************************************************************/
+package org.eclipse.persistence.tools.db.relational.spi.jdbc;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.eclipse.persistence.tools.db.relational.spi.ExternalTable;
+import org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription;
+import org.eclipse.persistence.tools.utility.NameTools;
+import org.eclipse.persistence.tools.utility.StringTools;
+
+/**
+ * @version 2.5
+ */
+final class JDBCExternalTableDescription implements ExternalTableDescription {
+ private final JDBCExternalDatabase database;
+ private final String catalogName;
+ private final String schemaName;
+ private final String name;
+ private final String qualifiedName; // cache the qualified name, since it will not change
+ private ExternalTable externalTable; // pseudo-final
+
+
+ // ********** constructor/initialization **********
+
+ /**
+ * Construct an external table description from the current row
+ * in the specified result set. The result set corresponds to the
+ * result set returned from DatabaseMetaData#getTables(String, String, String, String[]).
+ * @see java.sql.DatabaseMetaData#getTables(String, String, String, String[])
+ */
+ JDBCExternalTableDescription(ResultSet resultSet, JDBCExternalDatabase database) throws SQLException {
+ this(
+ // * Returns fixed-length strings;
+ // these calls *shouldn't* throw any SQL exceptions...
+ trim(resultSet.getString(1)), // TABLE_CAT
+ trim(resultSet.getString(2)), // TABLE_SCHEM
+ trim(resultSet.getString(3)), // TABLE_NAME
+ database
+ );
+ }
+
+ JDBCExternalTableDescription(String catalogName, String schemaName, String name, JDBCExternalDatabase database) {
+ super();
+ this.catalogName = catalogName;
+ this.schemaName = schemaName;
+ this.name = name;
+ this.qualifiedName = this.buildQualifiedName();
+ this.database = database;
+ }
+
+ /**
+ * trim down the specified string, to null if necessary
+ */
+ private static String trim(String s) {
+ if (s == null) {
+ return null;
+ }
+ s = s.trim();
+ return (s.length() == 0) ? null : s;
+ }
+
+ private String buildQualifiedName() {
+ return NameTools.buildQualifiedDatabaseObjectName(this.catalogName, this.schemaName, this.name);
+ }
+
+
+ // ********** ExternalTableDescription implementation **********
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription#getCatalogName()
+ */
+ @Override
+ public String getCatalogName() {
+ return this.catalogName;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription#getSchemaName()
+ */
+ @Override
+ public String getSchemaName() {
+ return this.schemaName;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription#getName()
+ */
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription#getQualifiedName()
+ */
+ @Override
+ public String getQualifiedName() {
+ return this.qualifiedName;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription#getTable()
+ */
+ @Override
+ public ExternalTable getTable() {
+ if (this.externalTable == null) {
+ this.externalTable = this.buildExternalTable();
+ }
+ return this.externalTable;
+ }
+
+ /**
+ * @see org.eclipse.persistence.tools.db.relational.spi.TableDescription#getAdditionalInfo()
+ */
+ @Override
+ public String getAdditionalInfo() {
+ try {
+ return this.metaData().getURL();
+ } catch (SQLException ex) {
+ return null;
+ }
+ }
+
+
+ // ********** behavior **********
+
+ private ExternalTable buildExternalTable() {
+ try {
+ return new JDBCExternalTable(this);
+ } catch (SQLException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+
+ // ********** queries **********
+
+ DatabaseMetaData metaData() {
+ return this.database.metaData();
+ }
+
+ JDBCExternalDatabase getDatabase() {
+ return this.database;
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.qualifiedName);
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms.dpr b/tools/org.eclipse.persistence.tools.db/src/platforms.dpr
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms.dpr
rename to tools/org.eclipse.persistence.tools.db/src/platforms.dpr
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/attunity.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/attunity.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/attunity.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/attunity.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/cloudscape.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/cloudscape.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/cloudscape.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/cloudscape.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/db2.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/db2.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/db2.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/db2.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/dbase.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/dbase.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/dbase.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/dbase.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/derby.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/derby.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/derby.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/derby.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/hsql.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/hsql.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/hsql.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/hsql.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/informix.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/informix.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/informix.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/informix.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/javadb.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/javadb.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/javadb.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/javadb.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/msaccess.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/msaccess.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/msaccess.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/msaccess.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/mysql.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/mysql.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/mysql.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/mysql.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/mysql4.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/mysql4.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/mysql4.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/mysql4.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/oracle.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/oracle.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle10g.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/oracle10g.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle10g.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/oracle10g.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle11.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/oracle11.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle11.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/oracle11.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle8i.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/oracle8i.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle8i.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/oracle8i.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle9i.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/oracle9i.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/oracle9i.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/oracle9i.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/other.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/other.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/other.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/other.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/pointbase.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/pointbase.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/pointbase.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/pointbase.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/postgresql.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/postgresql.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/postgresql.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/postgresql.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/sqlanywhere.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/sqlanywhere.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/sqlanywhere.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/sqlanywhere.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/sqlserver.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/sqlserver.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/sqlserver.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/sqlserver.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/sybase.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/sybase.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/sybase.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/sybase.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/timesten.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/timesten.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/timesten.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/timesten.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/src/platforms/timesten7.xml b/tools/org.eclipse.persistence.tools.db/src/platforms/timesten7.xml
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen.db/src/platforms/timesten7.xml
rename to tools/org.eclipse.persistence.tools.db/src/platforms/timesten7.xml
diff --git a/tools/org.eclipse.persistence.tools.gen.db/.classpath b/tools/org.eclipse.persistence.tools.gen.db/.classpath
index 0b9079a..32c7e58 100644
--- a/tools/org.eclipse.persistence.tools.gen.db/.classpath
+++ b/tools/org.eclipse.persistence.tools.gen.db/.classpath
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="resource/templates/xml_entities"/>
+ <classpathentry kind="src" path="resource/property_files"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="owner.project.facets" value="java"/>
diff --git a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.common.component b/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.common.component
index fe564e6..771a706 100644
--- a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.common.component
+++ b/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.common.component
@@ -2,5 +2,7 @@
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="org.eclipse.persistence.tools.gen.db">
<wb-resource deploy-path="/" source-path="/src"/>
+ <wb-resource deploy-path="/" source-path="/resource/templates/xml_entities"/>
+ <wb-resource deploy-path="/" source-path="/resource/property_files"/>
</wb-module>
</project-modules>
diff --git a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.common.project.facet.core.xml b/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.common.project.facet.core.xml
index fd68f7e..2d6935f 100644
--- a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.common.project.facet.core.xml
+++ b/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
- <fixed facet="java"/>
<fixed facet="jst.utility"/>
- <installed facet="java" version="1.6"/>
+ <fixed facet="java"/>
<installed facet="jst.utility" version="1.0"/>
+ <installed facet="java" version="1.6"/>
</faceted-project>
diff --git a/tools/org.eclipse.persistence.tools.gen.db/META-INF/MANIFEST.MF b/tools/org.eclipse.persistence.tools.gen.db/META-INF/MANIFEST.MF
index 8c08d4e..39549bc 100644
--- a/tools/org.eclipse.persistence.tools.gen.db/META-INF/MANIFEST.MF
+++ b/tools/org.eclipse.persistence.tools.gen.db/META-INF/MANIFEST.MF
@@ -1,19 +1,16 @@
Manifest-Version: 1.0
-Export-Package: org.eclipse.persistence.tools.db,
- org.eclipse.persistence.tools.db.driver,
- org.eclipse.persistence.tools.db.model,
- org.eclipse.persistence.tools.db.model.handles,
- org.eclipse.persistence.tools.db.model.platformsmodel,
- org.eclipse.persistence.tools.db.model.spi,
- org.eclipse.persistence.tools.db.model.spi.jdbc,
- platforms
+Export-Package: org.eclipse.persistence.tools.gen,
+ org.eclipse.persistence.tools.gen.db,
+ org.eclipse.persistence.tools.gen.internal,
+ org.eclipse.persistence.tools.gen.internal.util
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Require-Bundle: org.eclipse.persistence.tools.utility;bundle-version="2.5.0",
- org.eclipse.persistence.tools.gen;bundle-version="2.5.0",
- org.eclipse.persistence.core;bundle-version="2.4.0"
+Require-Bundle: org.apache.velocity;bundle-version="1.5.0",
+ org.apache.commons.collections;bundle-version="3.2.0",
+ org.jdom;bundle-version="1.1.1",
+ org.apache.commons.lang;bundle-version="2.1.0",
+ org.eclipse.persistence.tools.utility;bundle-version="2.5.0"
Bundle-SymbolicName: org.eclipse.persistence.tools.gen.db
-Bundle-Name: EclipseLink Tools Db
+Bundle-Name: EclipseLink Tools Gen
Bundle-Vendor: Eclipse.org - EclipseLink Project
Bundle-Version: 2.5.0.qualifier
Bundle-ManifestVersion: 2
-Import-Package: org.w3c.dom;resolution:=optional
diff --git a/tools/org.eclipse.persistence.tools.gen.db/build.properties b/tools/org.eclipse.persistence.tools.gen.db/build.properties
index b107977..4cc0ed9 100644
--- a/tools/org.eclipse.persistence.tools.gen.db/build.properties
+++ b/tools/org.eclipse.persistence.tools.gen.db/build.properties
@@ -1,3 +1,5 @@
-source.. = src/
+source.. = src/,\
+ resource/templates/xml_entities/,\
+ resource/property_files/
bin.includes = META-INF/,\
.
diff --git a/tools/org.eclipse.persistence.tools.gen.db/pom.xml b/tools/org.eclipse.persistence.tools.gen.db/pom.xml
index 3e72258..96af76b 100644
--- a/tools/org.eclipse.persistence.tools.gen.db/pom.xml
+++ b/tools/org.eclipse.persistence.tools.gen.db/pom.xml
@@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
- <name>EclipseLink Tools Gen DB</name>
+ <name>EclipseLink Tools Gen</name>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.tools.gen.db</artifactId>
<version>2.5.0-SNAPSHOT</version>
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/property_files/jpt_gen.properties b/tools/org.eclipse.persistence.tools.gen.db/resource/property_files/jpt_gen.properties
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/property_files/jpt_gen.properties
rename to tools/org.eclipse.persistence.tools.gen.db/resource/property_files/jpt_gen.properties
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/basic.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/basic.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/basic.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/basic.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/column.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/column.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/column.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/column.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/embeddable.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/embeddable.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/embeddable.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/embeddable.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/embeddedBasic.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/embeddedBasic.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/embeddedBasic.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/embeddedBasic.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/footer.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/footer.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/footer.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/footer.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/header.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/header.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/header.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/header.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/id.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/id.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/id.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/id.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/join.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/join.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/join.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/join.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/main.xml.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/main.xml.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/main.xml.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/main.xml.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/manyToMany.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/manyToMany.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/manyToMany.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/manyToMany.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/manyToOne.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/manyToOne.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/manyToOne.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/manyToOne.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/namedQuery.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/namedQuery.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/namedQuery.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/namedQuery.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/oneToMany.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/oneToMany.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/oneToMany.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/oneToMany.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/version.vm b/tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/version.vm
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/resource/templates/xml_entities/version.vm
rename to tools/org.eclipse.persistence.tools.gen.db/resource/templates/xml_entities/version.vm
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/DatabaseType.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/DatabaseType.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/DatabaseType.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/DatabaseType.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/DynamicEntityGenerator.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/DynamicEntityGenerator.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/DynamicEntityGenerator.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/DynamicEntityGenerator.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Catalog.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Catalog.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Catalog.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Catalog.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Column.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Column.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Column.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Column.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionAdapter.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionAdapter.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionAdapter.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionAdapter.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionListener.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionListener.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionListener.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionListener.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionProfile.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionProfile.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionProfile.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionProfile.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileAdapter.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileAdapter.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileAdapter.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileAdapter.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileFactory.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileFactory.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileFactory.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileFactory.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileListener.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileListener.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileListener.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ConnectionProfileListener.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Database.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Database.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Database.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Database.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/DatabaseIdentifierAdapter.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/DatabaseIdentifierAdapter.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/DatabaseIdentifierAdapter.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/DatabaseIdentifierAdapter.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/DatabaseObject.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/DatabaseObject.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/DatabaseObject.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/DatabaseObject.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ForeignKey.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ForeignKey.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/ForeignKey.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/ForeignKey.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Schema.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Schema.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Schema.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Schema.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/SchemaContainer.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/SchemaContainer.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/SchemaContainer.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/SchemaContainer.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Sequence.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Sequence.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Sequence.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Sequence.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Table.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Table.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/db/Table.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/db/Table.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/Association.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/Association.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/Association.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/Association.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/AssociationRole.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/AssociationRole.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/AssociationRole.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/AssociationRole.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/BaseEntityGenCustomizer.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/BaseEntityGenCustomizer.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/BaseEntityGenCustomizer.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/BaseEntityGenCustomizer.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/DatabaseAnnotationNameBuilder.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/DatabaseAnnotationNameBuilder.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/DatabaseAnnotationNameBuilder.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/DatabaseAnnotationNameBuilder.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/EntityGeneratorDatabaseAnnotationNameBuilder.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/EntityGeneratorDatabaseAnnotationNameBuilder.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/EntityGeneratorDatabaseAnnotationNameBuilder.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/EntityGeneratorDatabaseAnnotationNameBuilder.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/GenericEntityGeneratorDatabaseAnnotationNameBuilder.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/GenericEntityGeneratorDatabaseAnnotationNameBuilder.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/GenericEntityGeneratorDatabaseAnnotationNameBuilder.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/GenericEntityGeneratorDatabaseAnnotationNameBuilder.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/JptGenMessages.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/JptGenMessages.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/JptGenMessages.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/JptGenMessages.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/MappingFileGenerator.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/MappingFileGenerator.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/MappingFileGenerator.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/MappingFileGenerator.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/ORMGenColumn.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/ORMGenColumn.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/ORMGenColumn.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/ORMGenColumn.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/ORMGenCustomizer.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/ORMGenCustomizer.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/ORMGenCustomizer.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/ORMGenCustomizer.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/ORMGenTable.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/ORMGenTable.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/ORMGenTable.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/ORMGenTable.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/OverwriteConfirmer.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/OverwriteConfirmer.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/OverwriteConfirmer.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/OverwriteConfirmer.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/TagNames.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/TagNames.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/TagNames.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/TagNames.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/DBUtil.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/DBUtil.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/DBUtil.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/DBUtil.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/EntityGenTools.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/EntityGenTools.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/EntityGenTools.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/EntityGenTools.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/FileUtil.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/FileUtil.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/FileUtil.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/FileUtil.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/ForeignKeyInfo.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/ForeignKeyInfo.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/ForeignKeyInfo.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/ForeignKeyInfo.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/StringUtil.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/StringUtil.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/StringUtil.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/StringUtil.java
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/UrlUtil.java b/tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/UrlUtil.java
similarity index 100%
rename from tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/UrlUtil.java
rename to tools/org.eclipse.persistence.tools.gen.db/src/org/eclipse/persistence/tools/gen/internal/util/UrlUtil.java
diff --git a/tools/org.eclipse.persistence.tools.gen/.classpath b/tools/org.eclipse.persistence.tools.gen.nosql/.classpath
similarity index 78%
copy from tools/org.eclipse.persistence.tools.gen/.classpath
copy to tools/org.eclipse.persistence.tools.gen.nosql/.classpath
index 32c7e58..0b9079a 100644
--- a/tools/org.eclipse.persistence.tools.gen/.classpath
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/.classpath
@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="resource/templates/xml_entities"/>
- <classpathentry kind="src" path="resource/property_files"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="owner.project.facets" value="java"/>
diff --git a/tools/org.eclipse.persistence.tools.gen/.project b/tools/org.eclipse.persistence.tools.gen.nosql/.project
similarity index 94%
copy from tools/org.eclipse.persistence.tools.gen/.project
copy to tools/org.eclipse.persistence.tools.gen.nosql/.project
index 831ed03..fdfea59 100644
--- a/tools/org.eclipse.persistence.tools.gen/.project
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/.project
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
- <name>org.eclipse.persistence.tools.gen</name>
+ <name>org.eclipse.persistence.tools.gen.nosql</name>
<comment></comment>
<projects>
</projects>
diff --git a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.core.resources.prefs b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.core.resources.prefs
similarity index 100%
copy from tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.core.resources.prefs
copy to tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.core.resources.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.core.runtime.prefs b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.core.runtime.prefs
similarity index 100%
copy from tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.core.runtime.prefs
copy to tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.core.runtime.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.jdt.core.prefs b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.jdt.core.prefs
similarity index 100%
copy from tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.jdt.core.prefs
copy to tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.jdt.core.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs
similarity index 100%
copy from tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs
copy to tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.ltk.core.refactoring.prefs b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.ltk.core.refactoring.prefs
similarity index 100%
copy from tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.ltk.core.refactoring.prefs
copy to tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.ltk.core.refactoring.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.wst.common.component b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..fe564e6
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+ <wb-module deploy-name="org.eclipse.persistence.tools.gen.db">
+ <wb-resource deploy-path="/" source-path="/src"/>
+ </wb-module>
+</project-modules>
diff --git a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.wst.common.project.facet.core.xml b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.wst.common.project.facet.core.xml
similarity index 99%
copy from tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.wst.common.project.facet.core.xml
copy to tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.wst.common.project.facet.core.xml
index 2d6935f..fd68f7e 100644
--- a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.wst.common.project.facet.core.xml
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
- <fixed facet="jst.utility"/>
<fixed facet="java"/>
- <installed facet="jst.utility" version="1.0"/>
+ <fixed facet="jst.utility"/>
<installed facet="java" version="1.6"/>
+ <installed facet="jst.utility" version="1.0"/>
</faceted-project>
diff --git a/tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.xsl.core.prefs b/tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.wst.xsl.core.prefs
similarity index 100%
copy from tools/org.eclipse.persistence.tools.gen.db/.settings/org.eclipse.wst.xsl.core.prefs
copy to tools/org.eclipse.persistence.tools.gen.nosql/.settings/org.eclipse.wst.xsl.core.prefs
diff --git a/tools/org.eclipse.persistence.tools.gen.nosql/META-INF/MANIFEST.MF b/tools/org.eclipse.persistence.tools.gen.nosql/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..df4abe3
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Export-Package:
+ org.eclipse.persistence.tools.gen.nosql.mongo
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.persistence.tools.utility;bundle-version="2.5.0",
+ org.eclipse.persistence.tools.mapping;bundle-version="2.5.0"
+Bundle-SymbolicName: org.eclipse.persistence.tools.gen.nosql
+Bundle-Name: EclipseLink Tools NoSql
+Bundle-Vendor: Eclipse.org - EclipseLink Project
+Bundle-Version: 2.5.0.qualifier
+Bundle-ManifestVersion: 2
+Import-Package: com.mongodb;resolution:=optional,
+ org.bson;resolution:=optional
diff --git a/tools/org.eclipse.persistence.tools.gen.nosql/build.properties b/tools/org.eclipse.persistence.tools.gen.nosql/build.properties
new file mode 100644
index 0000000..b107977
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/build.properties
@@ -0,0 +1,3 @@
+source.. = src/
+bin.includes = META-INF/,\
+ .
diff --git a/tools/org.eclipse.persistence.tools.gen/pom.xml b/tools/org.eclipse.persistence.tools.gen.nosql/pom.xml
similarity index 86%
rename from tools/org.eclipse.persistence.tools.gen/pom.xml
rename to tools/org.eclipse.persistence.tools.gen.nosql/pom.xml
index ffc11fc..7b47290 100644
--- a/tools/org.eclipse.persistence.tools.gen/pom.xml
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/pom.xml
@@ -3,9 +3,9 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
- <name>EclipseLink Tools Gen</name>
+ <name>EclipseLink Tools Gen DB</name>
<groupId>org.eclipse.persistence</groupId>
- <artifactId>org.eclipse.persistence.tools.gen</artifactId>
+ <artifactId>org.eclipse.persistence.tools.gen.nosql</artifactId>
<version>2.5.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
diff --git a/tools/org.eclipse.persistence.tools.gen.nosql/src/META-INF/persistence.xml b/tools/org.eclipse.persistence.tools.gen.nosql/src/META-INF/persistence.xml
new file mode 100644
index 0000000..92e3288
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/src/META-INF/persistence.xml
@@ -0,0 +1,14 @@
+<persistence-unit name="mongo-example" transaction-type="RESOURCE_LOCAL">
+ <provider>
+ org.eclipse.persistence.jpa.PersistenceProvider
+ </provider>
+ <mapping-file>META-INF/test.xml</mapping-file>
+ <properties>
+ <property name="eclipselink.target-database" value="org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform"/>
+ <property name="eclipselink.nosql.connection-spec" value="org.eclipse.persistence.nosql.adapters.mongo.MongoConnectionSpec"/>
+ <property name="eclipselink.nosql.property.mongo.port" value="27017"/>
+ <property name="eclipselink.nosql.property.mongo.host" value="localhost"/>
+ <property name="eclipselink.nosql.property.mongo.db" value="scratch"/>
+ <property name="eclipselink.logging.level" value="FINEST"/>
+ </properties>
+</persistence-unit>
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/MongoDynamicEntityGenerator.java b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/MongoDynamicEntityGenerator.java
new file mode 100644
index 0000000..6288e14
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/MongoDynamicEntityGenerator.java
@@ -0,0 +1,431 @@
+package org.eclipse.persistence.tools.gen.nosql.mongo;
+
+/*******************************************************************************
+ * Copyright (c) 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+import java.net.UnknownHostException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+import org.eclipse.persistence.tools.gen.nosql.mongo.meta.CollectionDescriptor;
+import org.eclipse.persistence.tools.gen.nosql.mongo.meta.ColumnDescriptor;
+import org.eclipse.persistence.tools.gen.nosql.mongo.meta.LeafColumnDescriptor;
+import org.eclipse.persistence.tools.gen.nosql.mongo.meta.NestedColumnDescriptor;
+import org.eclipse.persistence.tools.mapping.orm.DataFormatType;
+import org.eclipse.persistence.tools.mapping.orm.ExternalColumnMapping;
+import org.eclipse.persistence.tools.mapping.orm.ExternalElementCollectionMapping;
+import org.eclipse.persistence.tools.mapping.orm.ExternalEmbeddableEntity;
+import org.eclipse.persistence.tools.mapping.orm.ExternalEmbeddedMapping;
+import org.eclipse.persistence.tools.mapping.orm.ExternalEntity;
+import org.eclipse.persistence.tools.mapping.orm.ExternalNamedQuery;
+import org.eclipse.persistence.tools.mapping.orm.ExternalNoSql;
+import org.eclipse.persistence.tools.mapping.orm.ExternalORMConfiguration;
+import org.eclipse.persistence.tools.mapping.orm.ORMDocumentType;
+import org.eclipse.persistence.tools.mapping.orm.dom.ORMRepository;
+import org.eclipse.persistence.tools.utility.NameTools;
+
+import com.mongodb.BasicDBList;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.DBCursor;
+import com.mongodb.DBObject;
+import com.mongodb.Mongo;
+import com.mongodb.MongoException;
+import com.mongodb.ServerAddress;
+
+/**
+ * This class is an entry point for dynamic entity generation for MongoDB.
+ * It provides API for discovering metadata (table names, etc) and generating
+ * EclipseLink JPA, NoSql, mapping files.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @author John Bracken
+ * @version 2.5
+ */
+public class MongoDynamicEntityGenerator {
+
+ /** Mongo database connection to use in generation. */
+ private Mongo connection;
+
+ /** Mongo database instance to use in generation. */
+ private DB database;
+
+ /** Number of rows in each collection to sample during generation. */
+ private int rowSampleSize;
+
+ /**
+ * Constructs a new {@link MongoDynamicEntityGenerator} based on the provided
+ * db connection information.
+ *
+ * @param host the MongoDB network host.
+ * @param port the port of the Mongo database.
+ * @param dbName the name of the Mongo database.
+ * @param rowSampleSize number of rows in each collection to sample to determine the
+ * table structure. Since not all rows may have all possible values explicitly
+ * defined, it's important to use a sufficient sample size.
+ *
+ * @throws MongoException
+ * @throws UnknownHostException
+ */
+ public MongoDynamicEntityGenerator(String host, int port, String dbName, int rowSampleSize)
+ throws MongoException, UnknownHostException {
+ super();
+ this.rowSampleSize = rowSampleSize;
+ this.connection = new Mongo(new ServerAddress(host, port));
+ this.database = this.connection.getDB(dbName);
+ }
+
+ /**
+ * Builds a list of {@link CollectionDescriptor}s that describe the collection and associated
+ * column metadata of the Mongo collections named in <code>collectionNames</code>.
+ *
+ * @param collectionNames names of the Mongo collections to build descriptors for.
+ *
+ * @return {@link List} of {@link CollectionDescriptor}s.
+ */
+ private List<CollectionDescriptor> buildCollectionDescriptors(Collection<String> collectionNames) {
+ List<CollectionDescriptor> collectionDescriptors = new LinkedList<CollectionDescriptor>();
+
+ for (String collectionName : collectionNames) {
+ CollectionDescriptor collectionDescriptor = new CollectionDescriptor(collectionName);
+ collectionDescriptors.add(collectionDescriptor);
+ updateColumnDescriptors(collectionDescriptor);
+ }
+
+ return collectionDescriptors;
+ }
+
+ /**
+ * Updates the {@link CollectionDescriptor}s associated with the provided
+ * {@link CollectionDescriptor}.
+ *
+ * @param collectionDescriptor the {@link CollectionDescriptor} to update.
+ */
+ private void updateColumnDescriptors(CollectionDescriptor collectionDescriptor) {
+ // Read the collection from the database
+ DBCollection collection = this.database.getCollection(collectionDescriptor.getName());
+
+ // Read a sampling of the rows to determine the super set of column keys
+ // that are in the collection.
+ DBCursor cursor = collection.find().limit(this.rowSampleSize);
+ for ( ;cursor.hasNext();) {
+ DBObject row = cursor.next();
+ updateCollectionDescriptor(collectionDescriptor, row);
+ }
+
+ }
+
+ /**
+ * Creates an eclipselink-orm.xml descriptor mapping the provided <code>collectionNames</code>
+ * as EclipseLink dynamic entities.
+ *
+ * @param collectionNames
+ * @return a {@link String} representation of the eclipselink-orm.xml.
+ */
+ public String generate(Collection<String> collectionNames) {
+ // Create metadata descriptors for the specified collections.
+ List<CollectionDescriptor> collectionDescriptors = buildCollectionDescriptors(collectionNames);
+
+ // Generate an eclpselink-orm.xml from the collection descriptors
+ return generateORMConfig(collectionDescriptors);
+ }
+
+ /**
+ * Generates and adds to the specified entity a mapping for the leaf mapping described by the
+ * {@link CollectionDescriptor}.
+ *
+ * @param exEntity entity to add the mapping to.
+ * @param column the column to generate the mapping from.
+ * @param columnName the name of the column.
+ * @param javaColumnName the java identifier name to use for the column.
+ */
+ private void generateLeafMapping(ExternalEmbeddableEntity exEntity, LeafColumnDescriptor column,
+ String columnName, String javaColumnName) {
+ ExternalColumnMapping mapping;
+ // If this is a list-type column, then a collection based mapping is required.
+ if (column.isList()) {
+ mapping = exEntity.addElementCollectionMapping(columnName);
+ ((ExternalElementCollectionMapping)mapping).
+ setTargetClassName(column.getColumnType().getName());
+ mapping.setAttributeType(Vector.class.getName());
+ } else {
+ // special case where _id is reserved as a pk name in mongo.
+ // this is always intended to be an ID mapping.
+ if (columnName.equals("_id")) {
+ mapping = exEntity.addIdMapping(javaColumnName);
+ } else {
+ mapping = exEntity.addBasicMapping(javaColumnName);
+ }
+ mapping.setAttributeType(column.getColumnType().getName());
+ }
+ mapping.setNoSqlField(columnName);
+ }
+
+ /**
+ * Generates mappings for the provided mapped class ({@link ExternalEmbeddableEntity}) based on
+ * the columns enumerated in the provided {@link CollectionDescriptor}.
+ *
+ * @param exEntity the entity to generate mappings on.
+ * @param collection the Mongo DB collection descriptor to derive rows from.
+ * @param config the orm configuration.
+ * @param allEntityNames a {@link Set} of all of the entity names already in use.
+ */
+ private void generateMappings(ExternalEmbeddableEntity exEntity, CollectionDescriptor collection,
+ ExternalORMConfiguration config, Set<String> allEntityNames) {
+ for (ColumnDescriptor column : collection.columns()) {
+ String columnName = column.getColumnName();
+ String javaColumnName = NameTools.javaNameFromDatabaseName(columnName);
+ if (column instanceof LeafColumnDescriptor) {
+ generateLeafMapping(exEntity, (LeafColumnDescriptor)column,
+ columnName, javaColumnName);
+ } else if (column instanceof NestedColumnDescriptor) {
+ generateNestedMapping(exEntity, config, allEntityNames,
+ (NestedColumnDescriptor)column, columnName, javaColumnName);
+ }
+ }
+ }
+
+ /**
+ * Generates a mapping on the provided mapped class that represents the nested mapping. This will
+ * also involved generating an {@link Embeddable} to represent the nested value.
+ *
+ * @param exEntity the entity to generate the mapping on.
+ * @param config the {@link ExternalORMConfiguration} that the entity is associated with.
+ * @param allEntityNames the existing used namespace for all mapped classes.
+ * @param column the nested column to generate the mapping for.
+ * @param columnName the name of the column.
+ * @param javaColumnName the java identifier name for the column.
+ */
+ private void generateNestedMapping(ExternalEmbeddableEntity exEntity,ExternalORMConfiguration config,
+ Set<String> allEntityNames, NestedColumnDescriptor column, String columnName, String javaColumnName) {
+ // Create the embeddable for the nested value
+ String embeddableName = NameTools.javaNameFromDatabaseName(columnName, true);
+ embeddableName = NameTools.uniqueNameFor(embeddableName, allEntityNames);
+ allEntityNames.add(embeddableName);
+ ExternalEmbeddableEntity embeddable = config.addEmbeddableEntity(embeddableName);
+ embeddable.addNoSql().setDataFormat(DataFormatType.MAPPED);
+ embeddable.setAccessType("VIRTUAL");
+ // generate mappings for the embeddable
+ generateMappings(embeddable, column.getColumnDescriptor(), config, allEntityNames);
+
+ // if a collection, generate an Element Collection
+ if (column.isList()) {
+ ExternalElementCollectionMapping mapping = exEntity.addElementCollectionMapping(javaColumnName);
+ mapping.setNoSqlField(columnName);
+ mapping.setAttributeType(Vector.class.getName());
+ mapping.setTargetClassName(embeddableName);
+ }
+ // otherwise, just an embedded mapping.
+ else {
+ ExternalEmbeddedMapping mapping = exEntity.addEmbeddedMapping(javaColumnName);
+ mapping.setNoSqlField(columnName);
+ mapping.setAttributeType(embeddableName);
+ }
+ }
+
+ /**
+ * Generates a {@link String} representation of an eclipselink-orm.xml descriptor based
+ * on the provided MongoDB {@link CollectionDescriptor} definitions.
+ *
+ * @param collectionDescriptors the MongoDB collections to generate entities from.
+ *
+ * @return a {@link String} representation of the eclipselink-orm.xml.
+ */
+ private String generateORMConfig(List<CollectionDescriptor> collectionDescriptors) {
+ // Create a new orm.xml metadata model.
+ ExternalORMConfiguration config = new ORMRepository().buildORMConfiguration(ORMDocumentType.ECLIPELINK_2_4);
+ // track all entity names being used.
+ Set<String> allEntityNames = new HashSet<String>();
+ // Iterate over all collection descriptors and create an entity and associated mapping for them.
+ for (CollectionDescriptor collection : collectionDescriptors) {
+ // add an entity with a unique name
+ String collectionName = collection.getName();
+ String entityName = NameTools.javaNameFromDatabaseName(collectionName, true);
+ entityName = NameTools.uniqueNameFor(entityName, allEntityNames);
+ allEntityNames.add(entityName);
+ ExternalEntity exEntity = config.addEntity(entityName);
+ // access type is virtual
+ exEntity.setAccessType("VIRTUAL");
+ // Configure NoSql settings
+ ExternalNoSql noSqlDesc = exEntity.addNoSql();
+ noSqlDesc.setDataFormat(DataFormatType.MAPPED);
+ noSqlDesc.setDataType(collectionName);
+ // add mappings
+ generateMappings(exEntity, collection, config, allEntityNames);
+ }
+
+ // Generate a default, read all query for all entities
+ generateQueries(config);
+
+ return config.getXML();
+ }
+
+ /**
+ * Generates and adds a root level named query for each entity
+ * enumerate in the {@link ExternalORMConfiguration}.
+ *
+ * @param config the configuration to generate and add queries from.
+ */
+ private void generateQueries(ExternalORMConfiguration config) {
+ for (ExternalEntity entity : config.entities()) {
+ String entityName = entity.getClassName();
+ ExternalNamedQuery query = config.addNamedQuery(entityName + ".findAll");
+ char identifier = Character.toLowerCase(entityName.charAt(0));
+ query.setQuery("select " + identifier + " from " + entityName + " " + identifier);
+
+ }
+ }
+
+ /**
+ * Updates the give {@link CollectionDescriptor} with the leaf column information defined
+ * by row value.
+ *
+ * @param collectionDescriptor the {@link CollectionDescriptor} to update.
+ * @param columnName the name of the column.
+ * @param value the row value of the column.
+ */
+ private void handleLeafColumn(CollectionDescriptor collectionDescriptor,
+ String columnName, Object value) {
+ LeafColumnDescriptor columnDescriptor = (LeafColumnDescriptor)collectionDescriptor.getColumn(columnName);
+ if (columnDescriptor == null) {
+ columnDescriptor = collectionDescriptor.addLeafColumn(columnName);
+ }
+ Class<?> valueClass = value.getClass();
+ // Special case for an id-type column. If one is not explicitly defined,
+ // Mongo auto-generates one and uses the noted class for the type. This
+ // should be considered a String in java.
+ valueClass = valueClass.getName().equals("org.bson.types.ObjectId") ? String.class : valueClass;
+ // if the column type isn't consistent, just use Object as the type.
+ if (columnDescriptor.getColumnType() == null) {
+ columnDescriptor.setColumnType(valueClass);
+ } else if (columnDescriptor.getColumnType() != valueClass) {
+ columnDescriptor.setColumnType(Object.class);
+ }
+ }
+
+ /**
+ * Updates the given {@link CollectionDescriptor} with the a column representing
+ * the list-type value.
+ *
+ * @param collectionDescriptor the {@link CollectionDescriptor} to update.
+ * @param columnName the name of the column to update.
+ * @param value the row value, or in this case the list value row.
+ */
+ private void handleListColumn(CollectionDescriptor collectionDescriptor, String columnName,
+ Object value) {
+ ColumnDescriptor columnDescriptor = collectionDescriptor.getColumn(columnName);
+ BasicDBList listValue = (BasicDBList)value;
+ if (listValue.size() > 0) {
+ Iterator<?> listValues = listValue.listIterator();
+ Object valueFromList = listValues.next();
+ // Handle nested list
+ if (valueFromList instanceof BasicDBObject) {
+ NestedColumnDescriptor nestedColumnDesc;
+ if (columnDescriptor == null) {
+ nestedColumnDesc = collectionDescriptor.addNestedColumn(columnName);
+ } else {
+ nestedColumnDesc = (NestedColumnDescriptor)columnDescriptor;
+ }
+ nestedColumnDesc.setList(true);
+ updateCollectionDescriptor(nestedColumnDesc.getColumnDescriptor(), (DBObject)valueFromList);
+ // Iterate over subsequent nested values to ensure the superset of all columns keys
+ // are included
+ for (;listValues.hasNext();) {
+ valueFromList = listValues.next();
+ updateCollectionDescriptor(nestedColumnDesc.getColumnDescriptor(), (DBObject)valueFromList);
+ }
+
+ }
+ // Handle leaf list
+ else {
+ LeafColumnDescriptor leafColumnDescriptor;
+ if (columnDescriptor == null) {
+ leafColumnDescriptor = collectionDescriptor.addLeafColumn(columnName);
+ } else {
+ leafColumnDescriptor = (LeafColumnDescriptor)columnDescriptor;
+ }
+
+ leafColumnDescriptor.setList(true);
+ leafColumnDescriptor.setColumnType(valueFromList.getClass());
+ // Iterate over subsequent elements. If the element type isn't the same as the last, default to Object
+ // and break.
+ for (;listValues.hasNext();) {
+ valueFromList = listValues.next();
+ if (leafColumnDescriptor.getColumnType() != valueFromList.getClass()) {
+ leafColumnDescriptor.setColumnType(Object.class);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates the given {@link CollectionDescriptor} with the nested column information
+ * derived from the provided row value.
+ *
+ * @param collectionDescriptor the {@link CollectionDescriptor} to update.
+ * @param columnName name of the column.
+ * @param value row value of the column, or in this case the nest row.
+ */
+ private void handleNestedColumn(CollectionDescriptor collectionDescriptor,
+ String columnName, Object value) {
+ NestedColumnDescriptor columnDescriptor =
+ (NestedColumnDescriptor)collectionDescriptor.getColumn(columnName);
+
+ if (columnDescriptor == null) {
+ columnDescriptor = collectionDescriptor.addNestedColumn(columnName);
+ }
+
+ updateCollectionDescriptor(columnDescriptor.getColumnDescriptor(), (DBObject)value);
+ }
+
+ /**
+ * Updates the given {@link CollectionDescriptor} with columns implied by the provided row
+ * or {@link DBObject}.
+ *
+ * @param collectionDescriptor the {@link CollectionDescriptor} to update.
+ * @param dbObject the row to infer columns from.
+ */
+ private void updateCollectionDescriptor(CollectionDescriptor collectionDescriptor, DBObject dbObject) {
+ // iterate over all of the available names in the row.
+ for (String columnName : dbObject.keySet()) {
+ Object value = dbObject.get(columnName);
+ // if a column does not yet exist in our descriptor, add one.
+ if (value != null) {
+ // List type
+ if (value instanceof BasicDBList) {
+ handleListColumn(collectionDescriptor, columnName, value);
+ }
+ // Single Nested
+ else if (value instanceof BasicDBObject) {
+ handleNestedColumn(collectionDescriptor, columnName, value);
+ }
+ // Leaf Value
+ else {
+ handleLeafColumn(collectionDescriptor, columnName, value);
+ }
+ }
+ }
+ }
+}
diff --git a/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/CollectionDescriptor.java b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/CollectionDescriptor.java
new file mode 100644
index 0000000..0609267
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/CollectionDescriptor.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.persistence.tools.gen.nosql.mongo.meta;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Metadata class that describes a NoSql table which may also be referred
+ * to as a Collection or Map depending on the database type.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @author John Bracken
+ * @version 2.5
+ */
+public final class CollectionDescriptor {
+
+ /** Column descriptors associated with this collection */
+ private Map<String, ColumnDescriptor> columnDescriptors;
+
+ /** Name of this collection. */
+ private String name;
+
+ /**
+ * Constructor.
+ *
+ * @param name name of the Mondgo collection
+ */
+ public CollectionDescriptor(String name) {
+ super();
+ this.name = name;
+ this.columnDescriptors = new HashMap<String, ColumnDescriptor>();
+ }
+
+ /**
+ * Adds a new {@link LeafColumnDescriptor} with the provided name.
+ *
+ * @param name name of the column to add.
+ * @return the new {@link LeafColumnDescriptor}.
+ */
+ public LeafColumnDescriptor addLeafColumn(String name) {
+ LeafColumnDescriptor column = new LeafColumnDescriptor(name);
+ this.columnDescriptors.put(name, column);
+
+ return column;
+ }
+
+ /**
+ * Adds a new {@link NestedColumnDescriptor} with the provided name.
+ *
+ * @param name name of the column to add.
+ * @return the new {@link NestedColumnDescriptor}.
+ */
+ public NestedColumnDescriptor addNestedColumn(String name) {
+ NestedColumnDescriptor column = new NestedColumnDescriptor(name);
+ this.columnDescriptors.put(name, column);
+
+ return column;
+ }
+
+ /**
+ * Returns the {@link ColumnDescriptor}s associated with this
+ * collection.
+ *
+ * @return the {@link CollectionDescriptor}s associated with
+ * this collection.
+ */
+ public Iterable<? extends ColumnDescriptor> columns() {
+ return this.columnDescriptors.values();
+ }
+
+
+ /**
+ * Returns the {@link ColumnDescriptor} with the given name.
+ *
+ * @param name the name of the {@link ColumnDescriptor}.
+ * @return the {@link ColumnDescriptor}.
+ */
+ public ColumnDescriptor getColumn(String name) {
+ return this.columnDescriptors.get(name);
+ }
+
+ /**
+ * Returns the name of the Mongo collection represented by
+ * this descriptor.
+ *
+ * @return the name of this collection descriptor.
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Removes the provided {@link ColumnDescriptor} from this
+ * collection.
+ *
+ * @param columnDescriptor the column descriptor associated with
+ * this collection.
+ */
+ public void removeColumn(ColumnDescriptor columnDescriptor) {
+ this.columnDescriptors.remove(columnDescriptor.getColumnName());
+ }
+}
diff --git a/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/ColumnDescriptor.java b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/ColumnDescriptor.java
new file mode 100644
index 0000000..a74777a
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/ColumnDescriptor.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.persistence.tools.gen.nosql.mongo.meta;
+
+/**
+ * This class describes the metadata of an abstract representation of a MongoDB
+ * column.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @author John Bracken
+ * @version 2.5
+ */
+public abstract class ColumnDescriptor {
+
+ /** Name of the column */
+ private String columnName;
+
+ /** Defines whether this column is a list type */
+ private boolean isList;
+
+ /**
+ * Constructor.
+ *
+ * @param columName name of the column.
+ */
+ public ColumnDescriptor(String columName) {
+ super();
+ this.columnName = columName;
+ }
+
+ /**
+ * Returns the name of the column.
+ *
+ * @return the name of the column.
+ */
+ public String getColumnName() {
+ return columnName;
+ }
+
+ /**
+ * Indicates whether this column is a list
+ * type (e.g. has multiple elements in it's value).
+ *
+ * @return whether this column is a list.
+ */
+ public boolean isList() {
+ return this.isList;
+ }
+
+ /**
+ * Sets whether this column is a list
+ * type (e.g. has multiple elements in it's value).
+ *
+ * @param isList is this column a list type.
+ */
+ public void setList(boolean isList) {
+ this.isList = isList;
+ }
+}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/LeafColumnDescriptor.java b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/LeafColumnDescriptor.java
new file mode 100644
index 0000000..84c6c36
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/LeafColumnDescriptor.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.persistence.tools.gen.nosql.mongo.meta;
+
+/**
+ * This class describes the metadata of MongoDB column that is a leaf
+ * value (non-nested).
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @author John Bracken
+ * @version 2.5
+ */
+public final class LeafColumnDescriptor extends ColumnDescriptor {
+
+ /** The type of the column. */
+ private Class<?> columnType;
+
+ /**
+ * Constructor.
+ *
+ * @param columName name of the column.
+ */
+ public LeafColumnDescriptor(String columName) {
+ super(columName);
+ }
+
+ /**
+ * Returns the Java type of the column.
+ *
+ * @return the Java type of the column.
+ */
+ public Class<?> getColumnType() {
+ return this.columnType;
+ }
+
+ /**
+ * Sets the Java type of the column.
+ *
+ * @param columnType the Java type of the column.
+ */
+ public void setColumnType(Class<?> columnType) {
+ this.columnType = columnType;
+ }
+}
diff --git a/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/NestedColumnDescriptor.java b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/NestedColumnDescriptor.java
new file mode 100644
index 0000000..1a4fd3b
--- /dev/null
+++ b/tools/org.eclipse.persistence.tools.gen.nosql/src/org/eclipse/persistence/tools/gen/nosql/mongo/meta/NestedColumnDescriptor.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.persistence.tools.gen.nosql.mongo.meta;
+
+/**
+ * This class describes the metadata of MongoDB column that is a nested
+ * value (non-nested). A nested value is a column where the value metadata
+ * can be described by a {@link CollectionDescriptor}.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under development and
+ * expected to change significantly before reaching stability. It is available at this early stage
+ * to solicit feedback from pioneering adopters on the understanding that any code that uses this
+ * API will almost certainly be broken (repeatedly) as the API evolves.<p>
+ *
+ * @author John Bracken
+ * @version 2.5
+ */
+public final class NestedColumnDescriptor extends ColumnDescriptor{
+
+ /** The column descriptor that describes this columns value. */
+ private CollectionDescriptor columnDescriptor;
+
+ /**
+ * Constructor.
+ *
+ * @param columName name of the column.
+ */
+ public NestedColumnDescriptor(String columName) {
+ super(columName);
+ this.columnDescriptor = new CollectionDescriptor(columName);
+ }
+
+ /**
+ * The column descriptor that describe the structure of
+ * this column's nested value.
+ */
+ public CollectionDescriptor getColumnDescriptor() {
+ return this.columnDescriptor;
+ }
+}
diff --git a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.wst.common.component b/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.wst.common.component
deleted file mode 100644
index 88616f2..0000000
--- a/tools/org.eclipse.persistence.tools.gen/.settings/org.eclipse.wst.common.component
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project-modules id="moduleCoreId" project-version="1.5.0">
- <wb-module deploy-name="org.eclipse.persistence.tools.gen">
- <wb-resource deploy-path="/" source-path="/src"/>
- <wb-resource deploy-path="/" source-path="/resource/templates/xml_entities"/>
- <wb-resource deploy-path="/" source-path="/resource/property_files"/>
- </wb-module>
-</project-modules>
diff --git a/tools/org.eclipse.persistence.tools.gen/META-INF/MANIFEST.MF b/tools/org.eclipse.persistence.tools.gen/META-INF/MANIFEST.MF
deleted file mode 100644
index 5c532f8..0000000
--- a/tools/org.eclipse.persistence.tools.gen/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,16 +0,0 @@
-Manifest-Version: 1.0
-Export-Package: org.eclipse.persistence.tools.gen,
- org.eclipse.persistence.tools.gen.db,
- org.eclipse.persistence.tools.gen.internal,
- org.eclipse.persistence.tools.gen.internal.util
-Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Require-Bundle: org.apache.velocity;bundle-version="1.5.0",
- org.apache.commons.collections;bundle-version="3.2.0",
- org.jdom;bundle-version="1.1.1",
- org.apache.commons.lang;bundle-version="2.1.0",
- org.eclipse.persistence.tools.utility;bundle-version="2.5.0"
-Bundle-SymbolicName: org.eclipse.persistence.tools.gen
-Bundle-Name: EclipseLink Tools Gen
-Bundle-Vendor: Eclipse.org - EclipseLink Project
-Bundle-Version: 2.5.0.qualifier
-Bundle-ManifestVersion: 2
diff --git a/tools/org.eclipse.persistence.tools.gen/build.properties b/tools/org.eclipse.persistence.tools.gen/build.properties
deleted file mode 100644
index 4cc0ed9..0000000
--- a/tools/org.eclipse.persistence.tools.gen/build.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-source.. = src/,\
- resource/templates/xml_entities/,\
- resource/property_files/
-bin.includes = META-INF/,\
- .
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/NoSqlType.java b/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/NoSqlType.java
deleted file mode 100644
index 0bf647a..0000000
--- a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/NoSqlType.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 Oracle. All rights reserved.
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
- * which accompanies this distribution.
- * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *
- * Contributors:
- * Oracle - initial API and implementation
- *
- ******************************************************************************/
-package org.eclipse.persistence.tools.gen;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This enumeration defines the NoSQL data source type supported by dynamic entity generation.
- * <p>
- * Provisional API: This interface is part of an interim API that is still under development and
- * expected to change significantly before reaching stability. It is available at this early stage
- * to solicit feedback from pioneering adopters on the understanding that any code that uses this
- * API will almost certainly be broken (repeatedly) as the API evolves.<p>
- *
- * @version 2.5
- */
-@SuppressWarnings("nls")
-public enum NoSqlType {
-
- /**
- * The constant for Mongo database driver.
- */
- Mongo("Mongo", "com.mongodb.Mongo");
-
- /**
- * The fully qualified class name of the driver.
- */
- private String driver;
-
- /**
- * Database type identifier.
- */
- private String typeName;
-
- /**
- * Creates a new <code>NoSqlType</code>.
- */
- private NoSqlType(String typeName, String driver) {
- this.typeName = typeName;
- this.driver = driver;
- }
-
- /**
- * Returns the list of all NoSQL databases.
- *
- * @return The list of unique constants
- */
- public static Iterable<NoSqlType> types() {
- List<NoSqlType> types = new ArrayList<NoSqlType>();
- types.add(Mongo);
- return types;
- }
-
- /**
- * Retrieves the enumeration constant for the given value. If the value is not known, then
- * <code>null</code> will be returned.
- *
- * @param value The value to retrieve its constant version
- * @return The constant version of the given value
- */
- public static NoSqlType value(String value) {
- for (NoSqlType type : values()) {
- if (type.typeName.equals(value)) {
- return type;
- }
- }
- return null;
- }
-
- /**
- * Returns the driver class specific to this NoSQL type.
- *
- * @return The driver class for this database type
- */
- public String getDatabaseDriver() {
- return driver;
- }
-
- /**
- * Returns the type name of the NoSQL database.
- *
- * @return The name of the NoSQL database
- */
- public String getName() {
- return this.typeName;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- return this.typeName;
- }
-}
\ No newline at end of file
diff --git a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/DBUtil.java~HEAD b/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/DBUtil.java~HEAD
deleted file mode 100644
index 385569c..0000000
--- a/tools/org.eclipse.persistence.tools.gen/src/org/eclipse/persistence/tools/gen/internal/util/DBUtil.java~HEAD
+++ /dev/null
@@ -1,80 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2011 Oracle. All rights reserved.
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0, which accompanies this distribution
- * and is available at http://www.eclipse.org/legal/epl-v10.html.
- *
- * Contributors:
- * Oracle - initial API and implementation
- ******************************************************************************/
-package org.eclipse.jpt.jpa.gen.internal.util;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.jpt.jpa.db.Column;
-import org.eclipse.jpt.jpa.db.ForeignKey;
-import org.eclipse.jpt.jpa.db.Schema;
-import org.eclipse.jpt.jpa.db.Table;
-import org.eclipse.jpt.jpa.db.ForeignKey.ColumnPair;
-
-/**
- * Collection of utility methods to access DTP and other jpt.db APIs
- *
- */
-public class DBUtil {
-
- public static boolean isAutoIncrement(Column c){
- //@ TODO
- //Blocked by DTP bug
- //https://bugs.eclipse.org/bugs/show_bug.cgi?id=250023
- //The Dali bug is
- //https://bugs.eclipse.org/bugs/show_bug.cgi?id=249658
- //
- return false;
- }
-
- /**
- * Return list of fk
- * @param dbTable
- * @return
- */
- public static List<ForeignKeyInfo> getForeignKeys(Table dbTable) {
- List<ForeignKeyInfo> ret = new ArrayList<ForeignKeyInfo>();
- if(dbTable!=null){
- for (ForeignKey fk : dbTable.getForeignKeys()) {
- Iterator<ColumnPair> columnPaires = fk.getColumnPairs().iterator();
- ForeignKeyInfo fkInfo = null;
- while( columnPaires.hasNext() ){
- ColumnPair columnPair = columnPaires.next();
- if( fkInfo == null){
- String tableName = dbTable.getName();
- String referencedTableName = "";
- Table referencedTable = fk.getReferencedTable();
- referencedTableName = referencedTable.getName();
- fkInfo = new ForeignKeyInfo(fk, tableName, referencedTableName );
- }
- String baseColName = columnPair.getBaseColumn().getName();
- String referencedColName = columnPair.getReferencedColumn().getName();
- fkInfo.addColumnMapping( baseColName, referencedColName );
- }
- if( fkInfo !=null )
- ret.add( fkInfo );
- }
- }
- return ret;
- }
-
- public static String getJavaType(Column dbColumn) {
- return dbColumn.isPartOfPrimaryKey() ?
- dbColumn.getPrimaryKeyJavaTypeDeclaration() :
- dbColumn.getJavaTypeDeclaration();
- }
-
- public static boolean isDefaultSchema(Table dbTable){
- String schemaName = dbTable.getSchema().getName();
- Schema defaultSchema = dbTable.getSchema().getDatabase().getDefaultSchema();
- return defaultSchema.getName() == schemaName;
- }
-}
diff --git a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalEmbeddableEntity.java b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalEmbeddableEntity.java
index 3697794..5f1b434 100644
--- a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalEmbeddableEntity.java
+++ b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalEmbeddableEntity.java
@@ -77,9 +77,15 @@
/**
* Adds an embeddable mapping with the given name.
*/
- ExternalMapping addEmbeddedMapping(String name);
+ ExternalEmbeddedMapping addEmbeddedMapping(String name);
/**
+ * Adds an id mapping with the given name.
+ */
+ ExternalIDMapping addIdMapping(String name);
+
+
+ /**
* Adds instantiation copy policy to this entity
*/
ExternalInstantiationCopyPolicy addInstantiationCopyPolicy();
@@ -150,9 +156,9 @@
ExternalAccessMethods getAccessMethods();
/**
- * Returns the {@link AccessType} to be used in this entity.
+ * Returns the to be used in this entity.
*/
- AccessType getAccessType();
+ String getAccessType();
/**
* Returns the change tracking type for this entity
@@ -331,9 +337,10 @@
void removeTypeConverter(int index);
/**
- * Sets the {@link AccessType} to be used for this entity.
+ * Sets the {@link AccessType} to be used for this entity. String
+ * value used to support "VIRTUAL".
*/
- void setAccessType(AccessType type);
+ void setAccessType(String type);
/**
* Sets the change tracking type for this entity.
diff --git a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalMappedSuperClassEntity.java b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalMappedSuperClassEntity.java
index 82ecfa5..48469a3 100644
--- a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalMappedSuperClassEntity.java
+++ b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalMappedSuperClassEntity.java
@@ -52,11 +52,6 @@
ExternalFetchGroup addFetchGroup(int index, String name);
/**
- * Adds an id mapping with the given name.
- */
- ExternalIDMapping addIdMapping(String name);
-
- /**
* Adds multitenancy
*/
ExternalMultitenancyPolicy addMultitenancy();
diff --git a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalORMConfiguration.java b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalORMConfiguration.java
index 6c9da81..beebe9c 100644
--- a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalORMConfiguration.java
+++ b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/ExternalORMConfiguration.java
@@ -40,6 +40,11 @@
* Adds a new converter.
*/
ExternalConverter addConverter(int index);
+
+ /**
+ * Adds a embedded entity with the given name.
+ */
+ ExternalEmbeddableEntity addEmbeddableEntity(String embeddableClassName);
/**
* Adds a embedded entity with the given name.
diff --git a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/EmbeddableEntity.java b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/EmbeddableEntity.java
index 884dcf7..5a54028 100644
--- a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/EmbeddableEntity.java
+++ b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/EmbeddableEntity.java
@@ -16,7 +16,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import javax.persistence.AccessType;
+
import org.eclipse.persistence.annotations.ChangeTrackingType;
import org.eclipse.persistence.tools.mapping.orm.ExternalAccessMethods;
import org.eclipse.persistence.tools.mapping.orm.ExternalBasicCollectionMapping;
@@ -27,6 +27,7 @@
import org.eclipse.persistence.tools.mapping.orm.ExternalCopyPolicy;
import org.eclipse.persistence.tools.mapping.orm.ExternalElementCollectionMapping;
import org.eclipse.persistence.tools.mapping.orm.ExternalEmbeddableEntity;
+import org.eclipse.persistence.tools.mapping.orm.ExternalEmbeddedMapping;
import org.eclipse.persistence.tools.mapping.orm.ExternalIDMapping;
import org.eclipse.persistence.tools.mapping.orm.ExternalInstantiationCopyPolicy;
import org.eclipse.persistence.tools.mapping.orm.ExternalManyToManyMapping;
@@ -213,7 +214,7 @@
* {@inheritDoc}
*/
@Override
- public final ExternalMapping addEmbeddedMapping(String name) {
+ public final ExternalEmbeddedMapping addEmbeddedMapping(String name) {
EmbeddedMapping mapping = buildEmbeddedMapping(mappingsSize());
mapping.addSelf();
mapping.setName(name);
@@ -221,6 +222,18 @@
}
/**
+ * Embeddables don't currently support ID, but the implementation
+ * is here for convenience.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public ExternalIDMapping addIdMapping(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -580,8 +593,8 @@
* {@inheritDoc}
*/
@Override
- public final AccessType getAccessType() {
- return getEnumAttribute(ACCESS, AccessType.class);
+ public final String getAccessType() {
+ return getAttribute(ACCESS);
}
/**
@@ -1045,7 +1058,7 @@
* {@inheritDoc}
*/
@Override
- public final void setAccessType(AccessType type) {
+ public final void setAccessType(String type) {
setAttribute(ACCESS, type);
}
diff --git a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/IdMapping.java b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/IdMapping.java
index 2c550af..831859f 100644
--- a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/IdMapping.java
+++ b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/IdMapping.java
@@ -272,7 +272,6 @@
* {@inheritDoc}
*/
@Override
- @SuppressWarnings("null")
public void setColumn(String columnName) {
AbstractColumn column = getColumn();
diff --git a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/ORMConfiguration.java b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/ORMConfiguration.java
index dd60604..9db77d7 100644
--- a/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/ORMConfiguration.java
+++ b/tools/org.eclipse.persistence.tools.mapping/src/org/eclipse/persistence/tools/mapping/orm/dom/ORMConfiguration.java
@@ -134,6 +134,18 @@
entity.addSelf();
entity.setClassName(className);
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ExternalEmbeddableEntity addEmbeddableEntity(String className) {
+ EmbeddableEntity entity = buildEmbeddableEntity(embeddableEntitiesSize());
+ entity.addSelf();
+ entity.setClassName(className);
+
+ return entity;
+ }
/**
* {@inheritDoc}
diff --git a/tools/org.eclipse.persistence.tools.parent/pom.xml b/tools/org.eclipse.persistence.tools.parent/pom.xml
index faec476..98c88f8 100644
--- a/tools/org.eclipse.persistence.tools.parent/pom.xml
+++ b/tools/org.eclipse.persistence.tools.parent/pom.xml
@@ -38,9 +38,10 @@
<modules>
<module>../org.eclipse.persistence.tools.utility</module>
- <module>../org.eclipse.persistence.tools.gen</module>
+ <module>../org.eclipse.persistence.tools.db</module>
<module>../org.eclipse.persistence.tools.gen.db</module>
<module>../org.eclipse.persistence.tools.mapping</module>
+ <module>../org.eclipse.persistence.tools.gen.nosql</module>
<!-- module>../org.eclipse.persistence.tools.utility.tests</module -->
</modules>
diff --git a/tools/org.eclipse.persistence.tools.utility/src/org/eclipse/persistence/tools/utility/NameTools.java b/tools/org.eclipse.persistence.tools.utility/src/org/eclipse/persistence/tools/utility/NameTools.java
index 9f7703e..82c8d81 100644
--- a/tools/org.eclipse.persistence.tools.utility/src/org/eclipse/persistence/tools/utility/NameTools.java
+++ b/tools/org.eclipse.persistence.tools.utility/src/org/eclipse/persistence/tools/utility/NameTools.java
@@ -19,6 +19,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.SortedSet;
+import java.util.regex.Pattern;
import org.eclipse.persistence.tools.utility.iterators.ArrayIterator;
@@ -128,6 +129,9 @@
return sb.toString();
}
+ /** regex used to replace characters in a database identifier that are invalid in java identifiers */
+ private static final Pattern DB_IDENTIFIER_EXCLUSIONS = Pattern.compile("[@$# .]");
+
/**
* The set of reserved words in the Java programming language.
* These words cannot be used as identifiers (i.e. names).
@@ -198,6 +202,36 @@
Collections.unmodifiableSortedSet(CollectionTools.sortedSet(JAVA_RESERVED_WORDS));
/**
+ * Generates a Java identifier name based on the provided database name.
+ * Camel-cases the Java identifier on _ characters and on characters that
+ * are valid in DB identifiers but not Java identifiers (the @ symbol, for
+ * example). Does not capitalize the first letter of the generated
+ * identifier.
+ *
+ * @param databaseName - <code>String</code> representing the database
+ * identifier that should be used to produce a Java identifier.
+ */
+ public static String javaNameFromDatabaseName(String databaseName) {
+ return javaNameFromDatabaseName(databaseName, false);
+ }
+
+ /**
+ * Generates a Java identifier name based on the provided database name.
+ * Camel-cases the Java identifier on _ characters and on characters that are
+ * valid in DB identifiers but not Java identifiers (the @ symbol, for
+ * example).
+ * @param databaseName - <code>String</code> representing the database
+ * identifier that should be used to produce a Java identifier.
+ *
+ * @param capitalizeFirstLetter - <code>boolean</code> indicating whether
+ * the first letter of the identifier should be capitalized.
+ */
+ public static String javaNameFromDatabaseName(String databaseName, boolean capitalizeFirstLetter) {
+ return StringTools.convertAllCapsToCamelBack(normalizeJavaIdentifier(DB_IDENTIFIER_EXCLUSIONS.matcher(databaseName).replaceAll("_")),
+ capitalizeFirstLetter);
+ }
+
+ /**
* Returns the set of Java programming language reserved words.
* These words cannot be used as identifiers (i.e. names).
* http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html
@@ -207,6 +241,42 @@
}
/**
+ * Normalizes the specified candidate string as a valid Java identifier.
+ * Defaults the delimitor character for replacement as '_'.
+ *
+ * @see StringTools#normalizeJavaIdentifier(String, char)
+ */
+ public static String normalizeJavaIdentifier(String candidateString)
+ {
+ return normalizeJavaIdentifier(candidateString, '_');
+ }
+
+ /**
+ * Normalizes the specified candidate string as a valid Java identifier
+ * by replacing any invalid characters with the specified delimitor
+ * character.
+ */
+ public static String normalizeJavaIdentifier(String candidateString, char delimitor)
+ {
+ StringBuffer normalizedString = new StringBuffer();
+ for(int i=0; i<candidateString.length(); i++)
+ {
+ char currentChar = candidateString.charAt(i);
+ if ((i==0 && Character.isJavaIdentifierStart(currentChar)) ||
+ Character.isJavaIdentifierPart(currentChar))
+ {
+ normalizedString.append(currentChar);
+ }
+ else
+ {
+ normalizedString.append(delimitor);
+ }
+ }
+
+ return normalizedString.toString();
+ }
+
+ /**
* Returns whether the specified string consists of Java identifier
* characters (but may be a reserved word).
*/
diff --git a/tools/org.eclipse.persistence.tools.utility/src/org/eclipse/persistence/tools/utility/StringTools.java b/tools/org.eclipse.persistence.tools.utility/src/org/eclipse/persistence/tools/utility/StringTools.java
index c56f258..6462f73 100644
--- a/tools/org.eclipse.persistence.tools.utility/src/org/eclipse/persistence/tools/utility/StringTools.java
+++ b/tools/org.eclipse.persistence.tools.utility/src/org/eclipse/persistence/tools/utility/StringTools.java
@@ -4284,6 +4284,53 @@
return string.equals(string.toLowerCase());
}
+ // ********** convert all caps to cable back **********
+
+ /**
+ * Convert the specified "all caps" string to a "camel back" string:
+ * "LARGE_PROJECT" -> "largeProject"
+ * Optionally capitalize the first letter.
+ */
+ public static String convertAllCapsToCamelBack(String allCapsString, boolean capitalizeFirstLetter) {
+ return convertAllCapsToCamelBack(allCapsString, '_', capitalizeFirstLetter);
+ }
+
+ /**
+ * Convert the specified "all caps" string to a "camel back" string:
+ * "LARGE_PROJECT" -> "largeProject"
+ * Optionally capitalize the first letter.
+ */
+ public static String convertAllCapsToCamelBack(String allCapsString, char delimitor, boolean capitalizeFirstLetter) {
+ int len = allCapsString.length();
+ if (len == 0) {
+ return EMPTY_STRING;
+ }
+ char prev = 0;
+ char c = 0;
+ StringBuilder sb = new StringBuilder(len);
+ for (int i = 0; i < len; i++) { // NB: start at 1
+ prev = c;
+ c = allCapsString.charAt(i);
+ if (c == delimitor) {
+ continue;
+ }
+ if (sb.length() == 0) {
+ if (capitalizeFirstLetter) {
+ sb.append(Character.toUpperCase(c));
+ } else {
+ sb.append(Character.toLowerCase(c));
+ }
+ } else {
+ if (prev == delimitor) {
+ sb.append(Character.toUpperCase(c));
+ } else {
+ sb.append(Character.toLowerCase(c));
+ }
+ }
+ }
+ return sb.toString();
+ }
+
// ********** convert camel case to all caps **********