Skip to main content
summaryrefslogtreecommitdiffstats
path: root/jpa
diff options
context:
space:
mode:
authorpfullbright2007-04-25 20:25:44 +0000
committerpfullbright2007-04-25 20:25:44 +0000
commitfb5519ce98bfc917d4f3eec2668a3c74f07f49eb (patch)
tree42d4b9367bfc7281fd09fe28c2f828945e144ca2 /jpa
parentaa104ed609e52f19bd20b90f841d34dde10497cd (diff)
downloadwebtools.dali-fb5519ce98bfc917d4f3eec2668a3c74f07f49eb.tar.gz
webtools.dali-fb5519ce98bfc917d4f3eec2668a3c74f07f49eb.tar.xz
webtools.dali-fb5519ce98bfc917d4f3eec2668a3c74f07f49eb.zip
renamed
Diffstat (limited to 'jpa')
-rw-r--r--jpa/plugins/org.eclipse.jpt.db.ui/.classpath7
-rw-r--r--jpa/plugins/org.eclipse.jpt.db.ui/.cvsignore3
-rw-r--r--jpa/plugins/org.eclipse.jpt.db.ui/.project28
-rw-r--r--jpa/plugins/org.eclipse.jpt.db.ui/META-INF/MANIFEST.MF15
-rw-r--r--jpa/plugins/org.eclipse.jpt.db.ui/build.properties16
-rw-r--r--jpa/plugins/org.eclipse.jpt.db.ui/component.xml1
-rw-r--r--jpa/plugins/org.eclipse.jpt.db.ui/plugin.properties25
-rw-r--r--jpa/plugins/org.eclipse.jpt.db.ui/src/org/eclipse/jpt/db/ui/internal/DTPUiTools.java99
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/.classpath7
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/.cvsignore3
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/.project28
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF16
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/build.properties16
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/component.xml1
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/plugin.properties14
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenerator.java1433
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenScope.java175
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenTable.java342
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToManyRelation.java104
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToOneRelation.java61
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/OneToManyRelation.java37
-rw-r--r--jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/PackageGenerator.java91
22 files changed, 2522 insertions, 0 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.db.ui/.classpath b/jpa/plugins/org.eclipse.jpt.db.ui/.classpath
new file mode 100644
index 0000000000..751c8f2e50
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.db.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/jpa/plugins/org.eclipse.jpt.db.ui/.cvsignore b/jpa/plugins/org.eclipse.jpt.db.ui/.cvsignore
new file mode 100644
index 0000000000..814c6a80a6
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.db.ui/.cvsignore
@@ -0,0 +1,3 @@
+bin
+build.xml
+javaCompiler...args \ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.db.ui/.project b/jpa/plugins/org.eclipse.jpt.db.ui/.project
new file mode 100644
index 0000000000..88ea5da610
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.db.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.jpt.db.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/jpa/plugins/org.eclipse.jpt.db.ui/META-INF/MANIFEST.MF b/jpa/plugins/org.eclipse.jpt.db.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..e1b6566ff9
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.db.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-SymbolicName: org.eclipse.jpt.db.ui
+Bundle-Version: 1.0.0.qualifier
+Bundle-ClassPath: .
+Bundle-Localization: plugin
+Eclipse-AutoStart: true
+Export-Package: org.eclipse.jpt.db.ui.internal
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.jpt.db,
+ org.eclipse.datatools.connectivity.ui,
+ org.eclipse.datatools.sqltools.editor.core
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/jpa/plugins/org.eclipse.jpt.db.ui/build.properties b/jpa/plugins/org.eclipse.jpt.db.ui/build.properties
new file mode 100644
index 0000000000..acb8fd859a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.db.ui/build.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2006 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
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = .,\
+ META-INF/,\
+ plugin.properties
+jars.compile.order = .
diff --git a/jpa/plugins/org.eclipse.jpt.db.ui/component.xml b/jpa/plugins/org.eclipse.jpt.db.ui/component.xml
new file mode 100644
index 0000000000..bf648aaa4f
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.db.ui/component.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><component xmlns="http://eclipse.org/wtp/releng/tools/component-model" name="org.eclipse.jpt.db.ui"><description url=""></description><component-depends unrestricted="true"></component-depends><plugin id="org.eclipse.jpt.db.ui" fragment="false"/></component> \ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.db.ui/plugin.properties b/jpa/plugins/org.eclipse.jpt.db.ui/plugin.properties
new file mode 100644
index 0000000000..2b0e5835b1
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.db.ui/plugin.properties
@@ -0,0 +1,25 @@
+###############################################################################
+# Copyright (c) 2006 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
+###############################################################################
+# ====================================================================
+# To code developer:
+# Do NOT change the properties between this line and the
+# "%%% END OF TRANSLATED PROPERTIES %%%" line.
+# Make a new property name, append to the end of the file and change
+# the code to use the new property.
+# ====================================================================
+
+# ====================================================================
+# %%% END OF TRANSLATED PROPERTIES %%%
+# ====================================================================
+
+pluginName = Java Persistence API Tools - DB UI
+providerName = Eclipse.org
+
diff --git a/jpa/plugins/org.eclipse.jpt.db.ui/src/org/eclipse/jpt/db/ui/internal/DTPUiTools.java b/jpa/plugins/org.eclipse.jpt.db.ui/src/org/eclipse/jpt/db/ui/internal/DTPUiTools.java
new file mode 100644
index 0000000000..632fe81411
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.db.ui/src/org/eclipse/jpt/db/ui/internal/DTPUiTools.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+* Copyright (c) 2007 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.db.ui.internal;
+
+import org.eclipse.datatools.connectivity.ICategory;
+import org.eclipse.datatools.connectivity.IConnectionProfile;
+import org.eclipse.datatools.connectivity.IProfileListener;
+import org.eclipse.datatools.connectivity.ProfileManager;
+import org.eclipse.datatools.connectivity.internal.ConnectionProfileManager;
+import org.eclipse.datatools.connectivity.internal.ui.wizards.CPWizardNode;
+import org.eclipse.datatools.connectivity.internal.ui.wizards.NewCPWizard;
+import org.eclipse.datatools.connectivity.internal.ui.wizards.ProfileWizardProvider;
+import org.eclipse.datatools.connectivity.ui.wizards.IWizardCategoryProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jpt.db.internal.ConnectionProfileRepository;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * ConnectionProfileUiTools
+ */
+public class DTPUiTools {
+
+ /**
+ * Launch the DTP New Connection Profile wizard to create a new database connection profile.
+ *
+ * Returns the name of the added profile, or null if the wizard is cancelled. ConnectionProfileRepository
+ * can be used to retrieve the added connection profile.
+ */
+ public static String createNewProfile() {
+ NewCPWizard wizard;
+ WizardDialog wizardDialog;
+
+ // Filter datasource category
+ ViewerFilter viewerFilter = new ViewerFilter() {
+
+ public boolean select( Viewer viewer, Object parentElement, Object element) {
+
+ CPWizardNode wizardNode = ( CPWizardNode) element;
+ if( !( wizardNode.getProvider() instanceof IWizardCategoryProvider)) {
+ ICategory cat = ConnectionProfileManager.getInstance().getProvider(
+ (( ProfileWizardProvider) wizardNode.getProvider()).getProfile()).getCategory();
+
+ // Only display wizards belong to database category
+ while( cat != null) {
+ if( cat.getId().equals( ConnectionProfileRepository.DATABASE_CATEGORY_ID))
+ return true;
+ else
+ cat = cat.getParent();
+ }
+ }
+ return false;
+ }
+ };
+ wizard = new NewCPWizard( viewerFilter, null);
+ Shell currentShell = Display.getCurrent().getActiveShell();
+ wizardDialog = new WizardDialog( currentShell, wizard);
+ wizardDialog.setBlockOnOpen( true);
+
+ LocalProfileListener listener = new LocalProfileListener();
+ ProfileManager.getInstance().addProfileListener( listener);
+
+ if( wizardDialog.open() == Window.CANCEL) {
+ ProfileManager.getInstance().removeProfileListener( listener);
+ return null;
+ }
+ IConnectionProfile addedProfile = listener.addedProfile;
+ ProfileManager.getInstance().removeProfileListener( listener);
+
+ return addedProfile.getName();
+ }
+
+ private static class LocalProfileListener implements IProfileListener {
+ IConnectionProfile addedProfile;
+
+ public void profileAdded( IConnectionProfile profile) {
+ addedProfile = profile;
+ }
+
+ public void profileChanged( IConnectionProfile profile) {
+ // do nothing
+ }
+
+ public void profileDeleted( IConnectionProfile profile) {
+ // do nothing
+ }
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/.classpath b/jpa/plugins/org.eclipse.jpt.gen/.classpath
new file mode 100644
index 0000000000..751c8f2e50
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/jpa/plugins/org.eclipse.jpt.gen/.cvsignore b/jpa/plugins/org.eclipse.jpt.gen/.cvsignore
new file mode 100644
index 0000000000..2d14989f69
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/.cvsignore
@@ -0,0 +1,3 @@
+bin
+@dot
+build.xml
diff --git a/jpa/plugins/org.eclipse.jpt.gen/.project b/jpa/plugins/org.eclipse.jpt.gen/.project
new file mode 100644
index 0000000000..ef2d5088ee
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.jpt.gen</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF b/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..4035383419
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-SymbolicName: org.eclipse.jpt.gen
+Bundle-Version: 1.0.0.qualifier
+Bundle-ClassPath: .
+Bundle-Localization: plugin
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.jpt.gen.internal
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.jdt.core,
+ org.eclipse.jpt.core,
+ org.eclipse.jpt.db,
+ org.eclipse.jpt.utility
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/jpa/plugins/org.eclipse.jpt.gen/build.properties b/jpa/plugins/org.eclipse.jpt.gen/build.properties
new file mode 100644
index 0000000000..9cce53a029
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/build.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2007 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
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = .,\
+ META-INF/,\
+ plugin.properties
+jars.compile.order = .
diff --git a/jpa/plugins/org.eclipse.jpt.gen/component.xml b/jpa/plugins/org.eclipse.jpt.gen/component.xml
new file mode 100644
index 0000000000..7a4e04e21f
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/component.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><component xmlns="http://eclipse.org/wtp/releng/tools/component-model" name="org.eclipse.jpt.gen"><description url=""></description><component-depends unrestricted="true"></component-depends><plugin id="org.eclipse.jpt.gen" fragment="false"/></component> \ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/plugin.properties b/jpa/plugins/org.eclipse.jpt.gen/plugin.properties
new file mode 100644
index 0000000000..89b8a72b12
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/plugin.properties
@@ -0,0 +1,14 @@
+# ====================================================================
+# To code developer:
+# Do NOT change the properties between this line and the
+# "%%% END OF TRANSLATED PROPERTIES %%%" line.
+# Make a new property name, append to the end of the file and change
+# the code to use the new property.
+# ====================================================================
+
+# ====================================================================
+# %%% END OF TRANSLATED PROPERTIES %%%
+# ====================================================================
+
+pluginName = Java Persistence API Tools - Entity Gen
+providerName = Eclipse.org
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenerator.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenerator.java
new file mode 100644
index 0000000000..f7919ffd9f
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenerator.java
@@ -0,0 +1,1433 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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.gen.internal;
+
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.lang.reflect.Modifier;
+import java.text.Collator;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jpt.core.internal.content.java.mappings.JPA;
+import org.eclipse.jpt.db.internal.Column;
+import org.eclipse.jpt.db.internal.ForeignKey;
+import org.eclipse.jpt.db.internal.Table;
+import org.eclipse.jpt.utility.internal.IndentingPrintWriter;
+import org.eclipse.jpt.utility.internal.JavaType;
+import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
+
+// TODO handle table names that are illegal class names
+// TODO handle table names that are illegal file names
+// TODO handle column names that are illegal field/method names
+// TODO format code per preferences
+// TODO organize imports per preferences
+// TODO prompt user to overwrite existing classes
+/**
+ * This generator will generate an entity for a table.
+ */
+public class EntityGenerator {
+ final Config config;
+ private final IPackageFragment packageFragment;
+ private final GenTable genTable;
+ private final String entityClassName;
+ private final OverwriteConfirmer overwriteConfirmer;
+ private final IProgressMonitor monitor;
+
+
+ // ********** public API **********
+
+ public static void generateEntity(Config config, IPackageFragment packageFragment, GenTable genTable, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) {
+ if ((config == null) || (packageFragment == null) || (genTable == null)) {
+ throw new NullPointerException();
+ }
+ new EntityGenerator(config, packageFragment, genTable, overwriteConfirmer, monitor).generateEntity();
+ }
+
+
+ // ********** constructor/initialization **********
+
+ private EntityGenerator(Config config, IPackageFragment packageFragment, GenTable genTable, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) {
+ super();
+ this.config = config;
+ this.packageFragment = packageFragment;
+ this.genTable = genTable;
+ this.entityClassName = this.fullyQualify(this.entityName());
+ this.overwriteConfirmer = overwriteConfirmer;
+ this.monitor = monitor;
+ }
+
+
+ // ********** code gen **********
+
+ private void generateEntity() {
+ try {
+ this.generateEntity_();
+ } catch (JavaModelException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private void generateEntity_() throws JavaModelException {
+ String fileName = this.entityName() + ".java";
+ String source = this.buildSource();
+ try {
+ this.packageFragment.createCompilationUnit(fileName, source, false, this.monitor);
+ } catch (JavaModelException ex) {
+ if (ex.getJavaModelStatus().getCode() == IJavaModelStatusConstants.NAME_COLLISION) {
+ if (this.overwriteConfirmer.overwrite(this.entityClassName)) {
+ this.packageFragment.createCompilationUnit(fileName, source, true, this.monitor);
+ }
+ } else {
+ throw ex;
+ }
+ }
+ }
+
+ /**
+ * build the "body" source first; then build the "package" and "imports" source
+ * and concatenate the "body" source to it
+ */
+ private String buildSource() {
+ // build the body source first so we can gather up the import statements
+ BodySource bodySource = this.buildBodySource();
+
+ StringWriter sw = new StringWriter(bodySource.length() + 1000);
+ PrintWriter pw = new PrintWriter(sw);
+ this.printPackageAndImportsOn(pw, bodySource);
+ pw.print(bodySource.source());
+ return sw.toString();
+ }
+
+ private BodySource buildBodySource() {
+ EntitySourceWriter pw = new EntitySourceWriter(this.packageName(), this.entityClassName);
+ this.printBodySourceOn(pw);
+ return pw;
+ }
+
+ private void printBodySourceOn(EntitySourceWriter pw) {
+ this.printClassDeclarationOn(pw);
+
+ pw.indent();
+ this.printEntityPrimaryKeyFieldsOn(pw);
+ this.printEntityNonPrimaryKeyBasicFieldsOn(pw);
+ this.printEntityManyToOneFieldsOn(pw);
+ this.printEntityOneToManyFieldsOn(pw);
+ this.printEntityOwnedManyToManyFieldsOn(pw);
+ this.printEntityNonOwnedManyToManyFieldsOn(pw);
+ this.printSerialVersionUID(pw);
+ pw.println();
+
+ this.printZeroArgumentConstructorOn(this.entityName(), this.config.methodVisibility(), pw);
+ if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) {
+ this.printEntityPrimaryKeyGettersAndSettersOn(pw);
+ this.printEntityNonPrimaryKeyBasicGettersAndSettersOn(pw);
+ this.printEntityManyToOneGettersAndSettersOn(pw);
+ this.printEntityOneToManyGettersAndSettersOn(pw);
+ this.printEntityOwnedManyToManyGettersAndSettersOn(pw);
+ this.printEntityNonOwnedManyToManyGettersAndSettersOn(pw);
+ }
+
+ this.printPrimaryKeyClassOn(pw);
+ pw.undent();
+
+ pw.print('}');
+ pw.println();
+ }
+
+ private void printClassDeclarationOn(EntitySourceWriter pw) {
+ this.printEntityAnnotationOn(pw);
+ this.printTableAnnotationOn(pw);
+ this.printIdClassAnnotationOn(pw);
+
+ pw.print("public class ");
+ pw.printTypeDeclaration(this.entityClassName);
+ if (config.serializable()) {
+ pw.print(" implements ");
+ pw.printTypeDeclaration(Serializable.class.getName());
+ }
+ pw.print(" {");
+ pw.println();
+ }
+
+ private void printEntityAnnotationOn(EntitySourceWriter pw) {
+ pw.printAnnotation(JPA.ENTITY);
+ pw.println();
+ }
+
+ private void printTableAnnotationOn(EntitySourceWriter pw) {
+ if ( ! this.table().matchesShortJavaClassName(this.entityName())) {
+ pw.printAnnotation(JPA.TABLE);
+ pw.print("(name=\"");
+ pw.print(this.table().getName());
+ pw.print("\")");
+ pw.println();
+ }
+ }
+
+ private void printIdClassAnnotationOn(EntitySourceWriter pw) {
+ if ((this.table().primaryKeyColumnsSize() > 1) && this.config.generateIdClassForCompoundPK()) {
+ pw.printAnnotation(JPA.ID_CLASS);
+ pw.print('(');
+ pw.printTypeDeclaration(this.entityClassName + ".PK");
+ pw.print(".class)");
+ pw.println();
+ }
+ }
+
+ private void printEntityPrimaryKeyFieldsOn(EntitySourceWriter pw) {
+ if ((this.table().primaryKeyColumnsSize() > 1) && this.config.generateEmbeddedIdForCompoundPK()) {
+ this.printEntityEmbeddedIdPrimaryKeyFieldOn(pw);
+ } else {
+ this.printEntityReadOnlyPrimaryKeyFieldsOn(pw);
+ this.printEntityWritablePrimaryKeyFieldsOn(pw);
+ }
+ }
+
+ private void printEntityEmbeddedIdPrimaryKeyFieldOn(EntitySourceWriter pw) {
+ if (this.config.fieldAccessType()) {
+ pw.printAnnotation(JPA.EMBEDDED_ID);
+ pw.println();
+ }
+ pw.printVisibility(this.config.fieldVisibility());
+ pw.printTypeDeclaration(this.entityClassName + ".PK");
+ pw.print(' ');
+ pw.print(this.genTable.fieldNameForEmbeddedId());
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ private void printEntityReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw) {
+ for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) {
+ this.printEntityReadOnlyPrimaryKeyFieldOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityReadOnlyPrimaryKeyFieldOn(Column column, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(column);
+ if (this.config.fieldAccessType()) {
+ pw.printAnnotation(JPA.ID);
+ pw.println();
+ if (column.matchesJavaFieldName(fieldName)) {
+ this.printReadOnlyColumnAnnotationOn(pw); // no Column name needed
+ } else {
+ this.printReadOnlyColumnAnnotationOn(column.getName(), pw);
+ }
+ }
+ pw.printVisibility(this.config.fieldVisibility());
+ pw.printTypeDeclaration(column.javaTypeDeclaration());
+ pw.print(' ');
+ pw.print(fieldName);
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ private void printReadOnlyColumnAnnotationOn(String columnName, EntitySourceWriter pw) {
+ pw.printAnnotation(JPA.COLUMN);
+ pw.print("(name=\"");
+ pw.print(columnName);
+ pw.print("\", insertable=false, updatable=false)");
+ pw.println();
+ }
+
+ private void printReadOnlyColumnAnnotationOn(EntitySourceWriter pw) {
+ pw.printAnnotation(JPA.COLUMN);
+ pw.print("(insertable=false, updatable=false)");
+ pw.println();
+ }
+
+ private void printEntityWritablePrimaryKeyFieldsOn(EntitySourceWriter pw) {
+ for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) {
+ this.printEntityWritablePrimaryKeyFieldOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityWritablePrimaryKeyFieldOn(Column column, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(column);
+ if (this.config.fieldAccessType()) {
+ pw.printAnnotation(JPA.ID);
+ pw.println();
+ if ( ! column.matchesJavaFieldName(fieldName)) {
+ this.printColumnAnnotationOn(column.getName(), pw);
+ }
+ }
+ pw.printVisibility(this.config.fieldVisibility());
+ pw.printTypeDeclaration(column.javaTypeDeclaration());
+ pw.print(' ');
+ pw.print(fieldName);
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ private void printEntityNonPrimaryKeyBasicFieldsOn(EntitySourceWriter pw) {
+ for (Iterator<Column> stream = this.genTable.nonPrimaryKeyBasicColumns(); stream.hasNext(); ) {
+ this.printEntityNonPrimaryKeyBasicFieldOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityNonPrimaryKeyBasicFieldOn(Column column, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(column);
+ if (this.config.fieldAccessType()) {
+ if ( ! column.matchesJavaFieldName(fieldName)) {
+ this.printColumnAnnotationOn(column.getName(), pw);
+ }
+ }
+ pw.printVisibility(this.config.fieldVisibility());
+ pw.printTypeDeclaration(column.javaTypeDeclaration());
+ pw.print(' ');
+ pw.print(fieldName);
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ private void printColumnAnnotationOn(String columnName, EntitySourceWriter pw) {
+ pw.printAnnotation(JPA.COLUMN);
+ pw.print("(name=\"");
+ pw.print(columnName);
+ pw.print("\")");
+ pw.println();
+ }
+
+ private void printEntityManyToOneFieldsOn(EntitySourceWriter pw) {
+ for (Iterator<ManyToOneRelation> stream = this.genTable.manyToOneRelations(); stream.hasNext(); ) {
+ this.printEntityManyToOneFieldOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityManyToOneFieldOn(ManyToOneRelation relation, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(relation);
+ if (this.config.fieldAccessType()) {
+ this.printManyToOneAnnotationOn(fieldName, relation, pw);
+ }
+ pw.printVisibility(this.config.fieldVisibility());
+ pw.printTypeDeclaration(this.fullyQualify(relation.referencedEntityName()));
+ pw.print(' ');
+ pw.print(fieldName);
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ private void printManyToOneAnnotationOn(String fieldName, ManyToOneRelation relation, EntitySourceWriter pw) {
+ pw.printAnnotation(JPA.MANY_TO_ONE);
+ pw.println();
+ ForeignKey fk = relation.getForeignKey();
+ if (fk.matchesJavaFieldName(fieldName)) {
+ return; // no JoinColumn annotation needed
+ }
+ if (fk.referencesSingleColumnPrimaryKey()) {
+ pw.printAnnotation(JPA.JOIN_COLUMN);
+ pw.print("(name=\"");
+ pw.print(fk.columnPairs().next().getBaseColumn().getName());
+ pw.print("\")");
+ } else {
+ if (fk.columnPairsSize() > 1) {
+ pw.printAnnotation(JPA.JOIN_COLUMNS);
+ pw.print("({");
+ pw.println();
+ pw.indent();
+ }
+ this.printJoinColumnAnnotationsOn(fk, pw);
+ if (fk.columnPairsSize() > 1) {
+ pw.undent();
+ pw.println();
+ pw.print("})");
+ }
+ }
+ pw.println();
+ }
+
+ private void printJoinColumnAnnotationsOn(ForeignKey foreignKey, EntitySourceWriter pw) {
+ for (Iterator<ForeignKey.ColumnPair> stream = foreignKey.columnPairs(); stream.hasNext(); ) {
+ this.printJoinColumnAnnotationOn(stream.next(), pw);
+ if (stream.hasNext()) {
+ pw.println(',');
+ }
+ }
+ }
+
+ private void printJoinColumnAnnotationOn(ForeignKey.ColumnPair columnPair, EntitySourceWriter pw) {
+ this.printJoinColumnAnnotationOn(columnPair.getBaseColumn().getName(), columnPair.getReferencedColumn().getName(), pw);
+ }
+
+ /**
+ * assume that at least one of the two names is not null
+ */
+ private void printJoinColumnAnnotationOn(String baseColumnName, String referencedColumnName, EntitySourceWriter pw) {
+ pw.printAnnotation(JPA.JOIN_COLUMN);
+ pw.print('(');
+ if (baseColumnName != null) {
+ pw.print("name=\"");
+ pw.print(baseColumnName);
+ }
+ if (referencedColumnName != null) {
+ if (baseColumnName != null) {
+ pw.print("\", ");
+ }
+ pw.print("referencedColumnName=\"");
+ pw.print(referencedColumnName);
+ }
+ pw.print("\")");
+ }
+
+ private void printEntityOneToManyFieldsOn(EntitySourceWriter pw) {
+ for (Iterator<OneToManyRelation> stream = this.genTable.oneToManyRelations(); stream.hasNext(); ) {
+ this.printEntityOneToManyFieldOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityOneToManyFieldOn(OneToManyRelation relation, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(relation);
+ if (this.config.fieldAccessType()) {
+ this.printOneToManyAnnotationOn(fieldName, relation, pw);
+ }
+ pw.printVisibility(this.config.fieldVisibility());
+ pw.printTypeDeclaration(this.config.getCollectionTypeName());
+ pw.print('<');
+ pw.printTypeDeclaration(this.fullyQualify(relation.referencedEntityName()));
+ pw.print('>');
+ pw.print(' ');
+ pw.print(fieldName);
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ private void printOneToManyAnnotationOn(String fieldName, OneToManyRelation relation, EntitySourceWriter pw) {
+ pw.printAnnotation(JPA.ONE_TO_MANY);
+ pw.print("(mappedBy=\"");
+ pw.print(relation.mappedBy());
+ pw.print("\")");
+ pw.println();
+ }
+
+ private void printEntityOwnedManyToManyFieldsOn(EntitySourceWriter pw) {
+ for (Iterator<ManyToManyRelation> stream = this.genTable.ownedManyToManyRelations(); stream.hasNext(); ) {
+ this.printEntityOwnedManyToManyFieldOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityOwnedManyToManyFieldOn(ManyToManyRelation relation, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(relation);
+ if (this.config.fieldAccessType()) {
+ this.printOwnedManyToManyAnnotationOn(fieldName, relation, pw);
+ }
+ pw.printVisibility(this.config.fieldVisibility());
+ pw.printTypeDeclaration(this.config.getCollectionTypeName());
+ pw.print('<');
+ pw.printTypeDeclaration(this.fullyQualify(relation.nonOwningEntityName()));
+ pw.print('>');
+ pw.print(' ');
+ pw.print(fieldName);
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ /**
+ * I guess you could build a state machine for all this crap,
+ * but that seems like overkill...
+ */
+ private void printOwnedManyToManyAnnotationOn(String fieldName, ManyToManyRelation relation, EntitySourceWriter pw) {
+ pw.printAnnotation(JPA.MANY_TO_MANY);
+ pw.println();
+ boolean first = true;
+ boolean comma = false;
+ if ( ! relation.joinTableNameIsDefault()) {
+ if (first) {
+ first = false;
+ pw.printAnnotation(JPA.JOIN_TABLE);
+ pw.print('(');
+ }
+ pw.print("name=\"");
+ pw.print(relation.getJoinTable().name());
+ pw.print('\"');
+ comma = true;
+ }
+ if ( ! relation.joinColumnsIsDefaultFor(fieldName)) {
+ if (first) {
+ first = false;
+ pw.printAnnotation(JPA.JOIN_TABLE);
+ pw.print('(');
+ } else if (comma) {
+ pw.print(',');
+ }
+ pw.println();
+ pw.indent();
+ this.printJoinTableJoinColumnsOn("joinColumns", fieldName, relation.getOwningForeignKey(), pw);
+ pw.undent();
+ comma = true;
+ }
+ String inverseFieldName = relation.getNonOwningTable().fieldNameFor(relation);
+ if ( ! relation.inverseJoinColumnsIsDefaultFor(inverseFieldName)) {
+ if (first) {
+ first = false;
+ pw.printAnnotation(JPA.JOIN_TABLE);
+ pw.print('(');
+ } else if (comma) {
+ pw.print(',');
+ }
+ pw.println();
+ pw.indent();
+ this.printJoinTableJoinColumnsOn("inverseJoinColumns", inverseFieldName, relation.getNonOwningForeignKey(), pw);
+ pw.undent();
+ comma = true;
+ }
+ if ( ! first) {
+ pw.print(')');
+ }
+ pw.println();
+ }
+
+ private void printJoinTableJoinColumnsOn(String elementName, String fieldName, ForeignKey foreignKey, EntitySourceWriter pw) {
+ if (foreignKey.columnPairsSize() != 1) {
+ this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw);
+ } else if (foreignKey.getReferencedTable().primaryKeyColumnsSize() != 1) {
+ // if the referenced table has a composite primary key, neither of the columns can be a default
+ // since both of the defaults require a single-column primary key
+ this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw);
+ } else {
+ ForeignKey.ColumnPair columnPair = foreignKey.columnPairs().next();
+ Column pkColumn = foreignKey.getReferencedTable().primaryKeyColumns().next();
+ if (columnPair.getBaseColumn().matchesJavaFieldName(fieldName + "_" + pkColumn.getName())) {
+ if (columnPair.getReferencedColumn() == pkColumn) {
+ // we shouldn't get here...
+ } else {
+ pw.print(elementName);
+ pw.print('=');
+ this.printJoinColumnAnnotationOn(null, columnPair.getReferencedColumn().getName(), pw);
+ }
+ } else {
+ if (columnPair.getReferencedColumn() == pkColumn) {
+ pw.print(elementName);
+ pw.print('=');
+ this.printJoinColumnAnnotationOn(columnPair.getBaseColumn().getName(), null, pw);
+ } else {
+ this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw);
+ }
+ }
+ }
+ }
+
+ private void printJoinTableJoinColumnsOn(String elementName, ForeignKey foreignKey, EntitySourceWriter pw) {
+ pw.print(elementName);
+ pw.print('=');
+ if (foreignKey.columnPairsSize() > 1) {
+ pw.print('{');
+ pw.println();
+ pw.indent();
+ }
+ this.printJoinColumnAnnotationsOn(foreignKey, pw);
+ if (foreignKey.columnPairsSize() > 1) {
+ pw.undent();
+ pw.println();
+ pw.print('}');
+ pw.println();
+ }
+ }
+
+ private void printEntityNonOwnedManyToManyFieldsOn(EntitySourceWriter pw) {
+ for (Iterator<ManyToManyRelation> stream = this.genTable.nonOwnedManyToManyRelations(); stream.hasNext(); ) {
+ this.printEntityNonOwnedManyToManyFieldOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityNonOwnedManyToManyFieldOn(ManyToManyRelation relation, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(relation);
+ if (this.config.fieldAccessType()) {
+ this.printNonOwnedManyToManyAnnotationOn(fieldName, relation, pw);
+ }
+ pw.printVisibility(this.config.fieldVisibility());
+ pw.printTypeDeclaration(this.config.getCollectionTypeName());
+ pw.print('<');
+ pw.printTypeDeclaration(this.fullyQualify(relation.owningEntityName()));
+ pw.print('>');
+ pw.print(' ');
+ pw.print(fieldName);
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ private void printNonOwnedManyToManyAnnotationOn(String fieldName, ManyToManyRelation relation, EntitySourceWriter pw) {
+ pw.printAnnotation(JPA.MANY_TO_MANY);
+ pw.print("(mappedBy=\"");
+ pw.print(relation.getMappedBy());
+ pw.print("\")");
+ pw.println();
+ }
+
+ private String fullyQualify(String shortClassName) {
+ String pkg = this.packageName();
+ return (pkg.length() == 0) ? shortClassName : pkg + '.' + shortClassName;
+ }
+
+ private void printSerialVersionUID(EntitySourceWriter pw) {
+ if (this.config.generateSerialVersionUID()) {
+ pw.print("private static final long serialVersionUID = 1L;");
+ pw.println();
+ }
+ }
+
+ private void printZeroArgumentConstructorOn(String ctorName, String visibility, EntitySourceWriter pw) {
+ if (this.config.generateDefaultConstructor()) {
+ pw.printVisibility(visibility);
+ pw.print(ctorName);
+ pw.print("() {");
+ pw.println();
+ pw.indent();
+ pw.println("super();");
+ pw.undent();
+ pw.print('}');
+ pw.println();
+ pw.println();
+ }
+ }
+
+ private void printEntityPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
+ if ((this.table().primaryKeyColumnsSize() > 1) && this.config.generateEmbeddedIdForCompoundPK()) {
+ this.printEntityEmbeddedIdPrimaryKeyGetterAndSetterOn(pw);
+ } else {
+ this.printEntityReadOnlyPrimaryKeyGettersAndSettersOn(pw);
+ this.printEntityWritablePrimaryKeyGettersAndSettersOn(pw);
+ }
+ }
+
+ private void printEntityEmbeddedIdPrimaryKeyGetterAndSetterOn(EntitySourceWriter pw) {
+ if (this.config.propertyAccessType()) {
+ pw.printAnnotation(JPA.EMBEDDED_ID);
+ pw.println();
+ }
+ pw.printGetterAndSetter(this.genTable.fieldNameForEmbeddedId(), this.entityClassName + ".PK", this.config.methodVisibility());
+ }
+
+ private void printEntityReadOnlyPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
+ for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) {
+ this.printEntityReadOnlyPrimaryKeyGetterAndSetterOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityReadOnlyPrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw) {
+ String propertyName = this.genTable.fieldNameFor(column);
+ if (this.config.propertyAccessType()) {
+ pw.printAnnotation(JPA.ID);
+ pw.println();
+ if (column.matchesJavaFieldName(propertyName)) {
+ this.printReadOnlyColumnAnnotationOn(pw); // no Column name needed
+ } else {
+ this.printReadOnlyColumnAnnotationOn(column.getName(), pw);
+ }
+ }
+
+ pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility());
+ }
+
+ private void printEntityWritablePrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
+ for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) {
+ this.printEntityWritablePrimaryKeyGetterAndSetterOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityWritablePrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw) {
+ String propertyName = this.genTable.fieldNameFor(column);
+ if (this.config.propertyAccessType()) {
+ pw.printAnnotation(JPA.ID);
+ pw.println();
+ if ( ! column.matchesJavaFieldName(propertyName)) {
+ this.printColumnAnnotationOn(column.getName(), pw);
+ }
+ }
+
+ pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility());
+ }
+
+ private void printEntityNonPrimaryKeyBasicGettersAndSettersOn(EntitySourceWriter pw) {
+ for (Iterator<Column> stream = this.genTable.nonPrimaryKeyBasicColumns(); stream.hasNext(); ) {
+ this.printEntityNonPrimaryKeyBasicGetterAndSetterOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityNonPrimaryKeyBasicGetterAndSetterOn(Column column, EntitySourceWriter pw) {
+ String propertyName = this.genTable.fieldNameFor(column);
+ if (this.config.propertyAccessType()) {
+ if ( ! column.matchesJavaFieldName(propertyName)) {
+ this.printColumnAnnotationOn(column.getName(), pw);
+ }
+ }
+
+ pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility());
+ }
+
+ private void printEntityManyToOneGettersAndSettersOn(EntitySourceWriter pw) {
+ for (Iterator<ManyToOneRelation> stream = this.genTable.manyToOneRelations(); stream.hasNext(); ) {
+ this.printEntityManyToOneGetterAndSetterOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityManyToOneGetterAndSetterOn(ManyToOneRelation relation, EntitySourceWriter pw) {
+ String propertyName = this.genTable.fieldNameFor(relation);
+ if (this.config.propertyAccessType()) {
+ this.printManyToOneAnnotationOn(propertyName, relation, pw);
+ }
+
+ String typeDeclaration = this.fullyQualify(relation.referencedEntityName());
+ pw.printGetterAndSetter(propertyName, typeDeclaration, this.config.methodVisibility());
+ }
+
+ private void printEntityOneToManyGettersAndSettersOn(EntitySourceWriter pw) {
+ for (Iterator<OneToManyRelation> stream = this.genTable.oneToManyRelations(); stream.hasNext(); ) {
+ this.printEntityOneToManyGetterAndSetterOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityOneToManyGetterAndSetterOn(OneToManyRelation relation, EntitySourceWriter pw) {
+ String propertyName = this.genTable.fieldNameFor(relation);
+ if (this.config.propertyAccessType()) {
+ this.printOneToManyAnnotationOn(propertyName, relation, pw);
+ }
+
+ String elementTypeDeclaration = this.fullyQualify(relation.referencedEntityName());
+ pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility());
+ }
+
+ private void printEntityOwnedManyToManyGettersAndSettersOn(EntitySourceWriter pw) {
+ for (Iterator<ManyToManyRelation> stream = this.genTable.ownedManyToManyRelations(); stream.hasNext(); ) {
+ this.printEntityOwnedManyToManyGetterAndSetterOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityOwnedManyToManyGetterAndSetterOn(ManyToManyRelation relation, EntitySourceWriter pw) {
+ String propertyName = this.genTable.fieldNameFor(relation);
+ if (this.config.propertyAccessType()) {
+ this.printOwnedManyToManyAnnotationOn(propertyName, relation, pw);
+ }
+
+ String elementTypeDeclaration = this.fullyQualify(relation.nonOwningEntityName());
+ pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility());
+ }
+
+ private void printEntityNonOwnedManyToManyGettersAndSettersOn(EntitySourceWriter pw) {
+ for (Iterator<ManyToManyRelation> stream = this.genTable.nonOwnedManyToManyRelations(); stream.hasNext(); ) {
+ this.printEntityNonOwnedManyToManyGetterAndSetterOn(stream.next(), pw);
+ }
+ }
+
+ private void printEntityNonOwnedManyToManyGetterAndSetterOn(ManyToManyRelation relation, EntitySourceWriter pw) {
+ String propertyName = this.genTable.fieldNameFor(relation);
+ if (this.config.propertyAccessType()) {
+ this.printNonOwnedManyToManyAnnotationOn(propertyName, relation, pw);
+ }
+
+ String elementTypeDeclaration = this.fullyQualify(relation.owningEntityName());
+ pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility());
+ }
+
+ private void printPrimaryKeyClassOn(EntitySourceWriter pw) {
+ if (this.table().primaryKeyColumnsSize() <= 1) {
+ return;
+ }
+ pw.println();
+ if (this.config.generateEmbeddedIdForCompoundPK()) {
+ pw.printAnnotation(JPA.EMBEDDABLE);
+ pw.println();
+ }
+ pw.print("public static class PK implements ");
+ pw.printTypeDeclaration(Serializable.class.getName());
+ pw.print(" {");
+ pw.println();
+
+ pw.indent();
+ this.printIdFieldsOn(pw);
+ this.printSerialVersionUID(pw);
+ pw.println();
+ this.printZeroArgumentConstructorOn("PK", "public", pw);
+
+ if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) {
+ this.printIdGettersAndSettersOn(pw);
+ }
+
+ this.printEqualsMethodOn("PK", this.table().primaryKeyColumns(), pw);
+ this.printHashCodeMethodOn(this.table().primaryKeyColumns(), pw);
+ pw.undent();
+
+ pw.print('}');
+ pw.println();
+ pw.println();
+ }
+
+ private void printIdFieldsOn(EntitySourceWriter pw) {
+ for (Iterator<Column> stream = this.table().primaryKeyColumns(); stream.hasNext(); ) {
+ this.printIdFieldOn(stream.next(), pw);
+ }
+ }
+
+ private void printIdFieldOn(Column column, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(column);
+ pw.printVisibility(this.config.fieldVisibility());
+ pw.printTypeDeclaration(column.javaTypeDeclaration());
+ pw.print(' ');
+ pw.print(fieldName);
+ pw.print(';');
+ pw.println();
+ }
+
+ private void printIdGettersAndSettersOn(EntitySourceWriter pw) {
+ for (Iterator<Column> stream = this.table().primaryKeyColumns(); stream.hasNext(); ) {
+ this.printIdGetterAndSetterOn(stream.next(), pw);
+ }
+ }
+
+ private void printIdGetterAndSetterOn(Column column, EntitySourceWriter pw) {
+ String propertyName = this.genTable.fieldNameFor(column);
+ pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility());
+ }
+
+ private void printEqualsMethodOn(String className, Iterator<Column> columns, EntitySourceWriter pw) {
+ pw.printAnnotation("java.lang.Override");
+ pw.println();
+
+ pw.println("public boolean equals(Object o) {");
+ pw.indent();
+ pw.println("if (o == this) {");
+ pw.indent();
+ pw.println("return true;");
+ pw.undent();
+ pw.print('}');
+ pw.println();
+
+ pw.print("if ( ! (o instanceof ");
+ pw.print(className);
+ pw.print(")) {");
+ pw.println();
+ pw.indent();
+ pw.println("return false;");
+ pw.undent();
+ pw.print('}');
+ pw.println();
+
+ pw.print(className);
+ pw.print(" other = (");
+ pw.print(className);
+ pw.print(") o;");
+ pw.println();
+
+ pw.print("return ");
+ pw.indent();
+ while (columns.hasNext()) {
+ this.printEqualsClauseOn(columns.next(), pw);
+ if (columns.hasNext()) {
+ pw.println();
+ pw.print("&& ");
+ }
+ }
+ pw.print(';');
+ pw.println();
+ pw.undent();
+ pw.undent();
+ pw.print('}');
+ pw.println();
+ pw.println();
+ }
+
+ private void printEqualsClauseOn(Column column, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(column);
+ JavaType javaType = column.javaType();
+ if (javaType.isPrimitive()) {
+ this.printPrimitiveEqualsClauseOn(fieldName, pw);
+ } else {
+ this.printReferenceEqualsClauseOn(fieldName, pw);
+ }
+ }
+
+ private void printPrimitiveEqualsClauseOn(String fieldName, EntitySourceWriter pw) {
+ pw.print("(this.");
+ pw.print(fieldName);
+ pw.print(" == other.");
+ pw.print(fieldName);
+ pw.print(')');
+ }
+
+ private void printReferenceEqualsClauseOn(String fieldName, EntitySourceWriter pw) {
+ pw.print("this.");
+ pw.print(fieldName);
+ pw.print(".equals(other.");
+ pw.print(fieldName);
+ pw.print(')');
+ }
+
+ private void printHashCodeMethodOn(Iterator<Column> columns, EntitySourceWriter pw) {
+ pw.printAnnotation("java.lang.Override");
+ pw.println();
+
+ pw.println("public int hashCode() {");
+ pw.indent();
+ pw.print("return ");
+ pw.indent();
+ while (columns.hasNext()) {
+ this.printHashCodeClauseOn(columns.next(), pw);
+ if (columns.hasNext()) {
+ pw.println();
+ pw.print("^ ");
+ }
+ }
+ pw.print(';');
+ pw.println();
+ pw.undent();
+ pw.undent();
+ pw.print('}');
+ pw.println();
+ pw.println();
+ }
+
+ private void printHashCodeClauseOn(Column column, EntitySourceWriter pw) {
+ String fieldName = this.genTable.fieldNameFor(column);
+ JavaType javaType = column.javaType();
+ if (javaType.isPrimitive()) {
+ this.printPrimitiveHashCodeClauseOn(javaType.getElementTypeName(), fieldName, pw);
+ } else {
+ this.printReferenceHashCodeClauseOn(fieldName, pw);
+ }
+ }
+
+ private void printPrimitiveHashCodeClauseOn(String primitiveName, String fieldName, EntitySourceWriter pw) {
+ if (primitiveName.equals("int") || primitiveName.equals("short") || primitiveName.equals("byte") || primitiveName.equals("char")) {
+ pw.print("this.");
+ pw.print(fieldName);
+ } else if (primitiveName.equals("long")) { // cribbed from Long#hashCode()
+ // ((int) (this.value ^ (this.value >>> 32)))
+ pw.print("((int) (this.");
+ pw.print(fieldName);
+ pw.print(" ^ (this.");
+ pw.print(fieldName);
+ pw.print(" >>> 32)))");
+ } else if (primitiveName.equals("double")) { // cribbed from Double#hashCode()
+ // ((int) (java.lang.Double.doubleToLongBits(this.value) ^ (java.lang.Double.doubleToLongBits(this.value) >>> 32)))
+ pw.print("((int) (");
+ pw.printTypeDeclaration("java.lang.Double");
+ pw.print(".doubleToLongBits(this.");
+ pw.print(fieldName);
+ pw.print(") ^ (");
+ pw.printTypeDeclaration("java.lang.Double");
+ pw.print(".doubleToLongBits(this.");
+ pw.print(fieldName);
+ pw.print(") >>> 32)))");
+ } else if (primitiveName.equals("float")) { // cribbed from Float#hashCode()
+ // java.lang.Float.floatToIntBits(this.value)
+ pw.printTypeDeclaration("java.lang.Float");
+ pw.print(".floatToIntBits(this.");
+ pw.print(fieldName);
+ pw.print(')');
+ } else if (primitiveName.equals("boolean")) { // cribbed from Boolean#hashCode()
+ // (this.value ? 1231 : 1237)
+ pw.print("(this.");
+ pw.print(fieldName);
+ pw.print(" ? 1231 : 1237)");
+ } else {
+ throw new IllegalArgumentException(primitiveName);
+ }
+ }
+
+ private void printReferenceHashCodeClauseOn(String fieldName, EntitySourceWriter pw) {
+ pw.print("this.");
+ pw.print(fieldName);
+ pw.print(".hashCode()");
+ }
+
+ private void printPackageAndImportsOn(PrintWriter pw, BodySource bodySource) {
+ if (this.packageName().length() != 0) {
+ pw.print("package ");
+ pw.print(this.packageName());
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ for (Iterator<Map.Entry<String, String>> stream = bodySource.importEntries(); stream.hasNext(); ) {
+ Map.Entry<String, String> entry = stream.next();
+ pw.print("import ");
+ pw.print(entry.getValue()); // package
+ pw.print('.');
+ pw.print(entry.getKey()); // short class name
+ pw.print(';');
+ pw.println();
+ }
+ pw.println();
+ }
+
+
+ // ********** convenience methods **********
+
+ private String packageName() {
+ return this.packageFragment.getElementName();
+ }
+
+ private Table table() {
+ return this.genTable.getTable();
+ }
+
+ private String entityName() {
+ return this.genTable.getEntityName();
+ }
+
+
+ // ********** writer **********
+
+ private interface BodySource {
+
+ /**
+ * return a sorted set of map entries; the key is the short class name,
+ * the value is the package name
+ */
+ Iterator<Map.Entry<String, String>> importEntries();
+
+ /**
+ * return the body source code
+ */
+ String source();
+
+ /**
+ * return the length of the body source code
+ */
+ int length();
+
+ }
+
+ /**
+ * Extend IndentingPrintWriter with some methods that facilitate building
+ * entity source code.
+ */
+ private static class EntitySourceWriter extends IndentingPrintWriter implements BodySource {
+ final String packageName;
+ final String entityClassName;
+ // key = short class name; value = package name
+ private final Map<String, String> imports = new HashMap<String, String>();
+
+ EntitySourceWriter(String packageName, String entityClassName) {
+ super(new StringWriter(20000));
+ this.packageName = packageName;
+ this.entityClassName = entityClassName;
+ }
+
+ void printVisibility(String visibilityModifier) {
+ if (visibilityModifier.length() != 0) {
+ this.print(visibilityModifier);
+ this.print(' ');
+ }
+ }
+
+ void printAnnotation(String annotationName) {
+ this.print('@');
+ this.printTypeDeclaration(annotationName);
+ }
+
+ void printTypeDeclaration(String typeDeclaration) {
+ this.print(this.importedTypeDeclaration(typeDeclaration));
+ }
+
+ /**
+ * Return the specified class's "imported" name.
+ * The class declaration must be of the form:
+ * "int"
+ * "int[]" (not "[I")
+ * "java.lang.Object"
+ * "java.lang.Object[]" (not "[Ljava.lang.Object;")
+ * "java.util.Map.Entry" (not "java.util.Map$Entry")
+ * "java.util.Map.Entry[][]" (not "[[Ljava.util.Map$Entry;")
+ */
+ private String importedTypeDeclaration(String typeDeclaration) {
+ if (this.typeDeclarationIsMemberClass(typeDeclaration)) {
+ // no need for an import, just return the partially-qualified name
+ return this.memberClassTypeDeclaration(typeDeclaration);
+ }
+ int last = typeDeclaration.lastIndexOf('.');
+ String pkg = (last == -1) ? "" : typeDeclaration.substring(0, last);
+ String shortTypeDeclaration = typeDeclaration.substring(last + 1);
+ String shortElementTypeName = shortTypeDeclaration;
+ while (shortElementTypeName.endsWith("[]")) {
+ shortElementTypeName = shortElementTypeName.substring(0, shortElementTypeName.length() - 2);
+ }
+ String prev = this.imports.get(shortElementTypeName);
+ if (prev == null) {
+ // this is the first class with this short element type name
+ this.imports.put(shortElementTypeName, pkg);
+ return shortTypeDeclaration;
+ }
+ if (prev.equals(pkg)) {
+ // this element type has already been imported
+ return shortTypeDeclaration;
+ }
+ // another class with the same short element type name has been
+ // previously imported, so this one must be used fully-qualified
+ return typeDeclaration;
+ }
+
+ /**
+ * e.g. "foo.bar.Employee.PK" will return true
+ */
+ private boolean typeDeclarationIsMemberClass(String typeDeclaration) {
+ return (typeDeclaration.length() > this.entityClassName.length())
+ && typeDeclaration.startsWith(this.entityClassName)
+ && (typeDeclaration.charAt(this.entityClassName.length()) == '.');
+ }
+
+ /**
+ * e.g. "foo.bar.Employee.PK" will return "Employee.PK"
+ * this prevents collisions with other imported classes (e.g. "joo.jar.PK")
+ */
+ private String memberClassTypeDeclaration(String typeDeclaration) {
+ int index = this.packageName.length();
+ if (index != 0) {
+ index++; // bump past the '.'
+ }
+ return typeDeclaration.substring(index);
+ }
+
+ public Iterator<Map.Entry<String, String>> importEntries() {
+ return new FilteringIterator<Map.Entry<String, String>>(this.sortedImportEntries()) {
+ @Override
+ @SuppressWarnings("unchecked")
+ protected boolean accept(Object next) {
+ String pkg = ((Map.Entry<String, String>) next).getValue();
+ if (pkg.equals("")
+ || pkg.equals("java.lang")
+ || pkg.equals(EntitySourceWriter.this.packageName)) {
+ return false;
+ }
+ return true;
+ }
+ };
+ }
+
+ private Iterator<Map.Entry<String, String>> sortedImportEntries() {
+ TreeSet<Map.Entry<String, String>> sortedImports = new TreeSet<Map.Entry<String, String>>(this.buildImportEntriesComparator());
+ sortedImports.addAll(this.imports.entrySet());
+ return sortedImports.iterator();
+ }
+
+ private Comparator<Map.Entry<String, String>> buildImportEntriesComparator() {
+ return new Comparator<Map.Entry<String, String>>() {
+ public int compare(Map.Entry<String, String> e1, Map.Entry<String, String> e2) {
+ Collator collator = Collator.getInstance();
+ int pkg = collator.compare(e1.getValue(), e2.getValue());
+ return (pkg == 0) ? collator.compare(e1.getKey(), e2.getKey()) : pkg;
+ }
+ };
+ }
+
+ void printGetterAndSetter(String propertyName, String typeDeclaration, String visibility) {
+ this.printGetter(propertyName, typeDeclaration, visibility);
+ this.println();
+ this.println();
+
+ this.printSetter(propertyName, typeDeclaration, visibility);
+ this.println();
+ this.println();
+ }
+
+ private void printGetter(String propertyName, String typeDeclaration, String visibility) {
+ this.printVisibility(visibility);
+ this.printTypeDeclaration(typeDeclaration);
+ this.print(' ');
+ this.print(typeDeclaration.equals("boolean") ? "is" : "get");
+ this.print(StringTools.capitalize(propertyName));
+ this.print("() {");
+ this.println();
+
+ this.indent();
+ this.print("return this.");
+ this.print(propertyName);
+ this.print(';');
+ this.println();
+ this.undent();
+
+ this.print('}');
+ }
+
+ private void printSetter(String propertyName, String typeDeclaration, String visibility) {
+ this.printVisibility(visibility);
+ this.print("void set");
+ this.print(StringTools.capitalize(propertyName));
+ this.print('(');
+ this.printTypeDeclaration(typeDeclaration);
+ this.print(' ');
+ this.print(propertyName);
+ this.print(") {");
+ this.println();
+
+ this.indent();
+ this.print("this.");
+ this.print(propertyName);
+ this.print(" = ");
+ this.print(propertyName);
+ this.print(';');
+ this.println();
+ this.undent();
+
+ this.print('}');
+ }
+
+ void printCollectionGetterAndSetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) {
+ this.printCollectionGetter(propertyName, collectionTypeDeclaration, elementTypeDeclaration, visibility);
+ this.println();
+ this.println();
+
+ this.printCollectionSetter(propertyName, collectionTypeDeclaration, elementTypeDeclaration, visibility);
+ this.println();
+ this.println();
+ }
+
+ private void printCollectionGetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) {
+ this.printVisibility(visibility);
+ this.printTypeDeclaration(collectionTypeDeclaration);
+ this.print('<');
+ this.printTypeDeclaration(elementTypeDeclaration);
+ this.print("> get");
+ this.print(StringTools.capitalize(propertyName));
+ this.print("() {");
+ this.println();
+
+ this.indent();
+ this.print("return this.");
+ this.print(propertyName);
+ this.print(';');
+ this.println();
+ this.undent();
+
+ this.print('}');
+ }
+
+ private void printCollectionSetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) {
+ this.printVisibility(visibility);
+ this.print("void set");
+ this.print(StringTools.capitalize(propertyName));
+ this.print('(');
+ this.printTypeDeclaration(collectionTypeDeclaration);
+ this.print('<');
+ this.printTypeDeclaration(elementTypeDeclaration);
+ this.print('>');
+ this.print(' ');
+ this.print(propertyName);
+ this.print(") {");
+ this.println();
+
+ this.indent();
+ this.print("this.");
+ this.print(propertyName);
+ this.print(" = ");
+ this.print(propertyName);
+ this.print(';');
+ this.println();
+ this.undent();
+
+ this.print('}');
+ }
+
+ public String source() {
+ return this.out.toString();
+ }
+
+ public int length() {
+ return ((StringWriter) this.out).getBuffer().length();
+ }
+
+ }
+
+
+ // ********** config **********
+
+ public static class Config {
+ private boolean convertToCamelCase = true;
+ private boolean propertyAccessType = false; // as opposed to "field"
+ private String collectionTypeName = Set.class.getName();
+ private int fieldVisibility = Modifier.PRIVATE;
+ private int methodVisibility = Modifier.PUBLIC;
+ private boolean generateGettersAndSetters = true;
+ private boolean generateDefaultConstructor = true;
+ private boolean serializable = true;
+ private boolean generateSerialVersionUID = true;
+ private boolean generateEmbeddedIdForCompoundPK = true; // as opposed to IdClass
+ private Map<Table, String> overrideEntityNames = new HashMap<Table, String>();
+
+ public static final int PRIVATE = 0;
+ public static final int PACKAGE = 1;
+ public static final int PROTECTED = 2;
+ public static final int PUBLIC = 3;
+
+
+ public boolean convertToCamelCase() {
+ return this.convertToCamelCase;
+ }
+ public void setConvertToCamelCase(boolean convertToCamelCase) {
+ this.convertToCamelCase = convertToCamelCase;
+ }
+
+ public boolean propertyAccessType() {
+ return this.propertyAccessType;
+ }
+ public void setPropertyAccessType(boolean propertyAccessType) {
+ this.propertyAccessType = propertyAccessType;
+ }
+
+ public boolean fieldAccessType() {
+ return ! this.propertyAccessType;
+ }
+ public void setFieldAccessType(boolean fieldAccessType) {
+ this.propertyAccessType = ! fieldAccessType;
+ }
+
+ public String getCollectionTypeName() {
+ return this.collectionTypeName;
+ }
+ public void setCollectionTypeName(String collectionTypeName) {
+ this.collectionTypeName = collectionTypeName;
+ }
+
+ public int getFieldVisibility() {
+ return this.fieldVisibility;
+ }
+ /** entity fields cannot be 'public' */
+ public void setFieldVisibility(int fieldVisibility) {
+ switch (fieldVisibility) {
+ case PRIVATE:
+ case PACKAGE:
+ case PROTECTED:
+ this.fieldVisibility = fieldVisibility;
+ break;
+ default:
+ throw new IllegalArgumentException("invalid field visibility: " + fieldVisibility);
+ }
+ }
+ String fieldVisibility() {
+ switch (this.fieldVisibility) {
+ case PRIVATE:
+ return "private";
+ case PACKAGE:
+ return "";
+ case PROTECTED:
+ return "protected";
+ default:
+ throw new IllegalStateException("invalid field visibility: " + this.fieldVisibility);
+ }
+ }
+
+ public int getMethodVisibility() {
+ return this.methodVisibility;
+ }
+ /** entity properties must be 'public' or 'protected' */
+ public void setMethodVisibility(int methodVisibility) {
+ switch (methodVisibility) {
+ case PROTECTED:
+ case PUBLIC:
+ this.methodVisibility = methodVisibility;
+ break;
+ default:
+ throw new IllegalArgumentException("invalid method visibility: " + methodVisibility);
+ }
+ }
+ String methodVisibility() {
+ switch (this.methodVisibility) {
+ case PROTECTED:
+ return "protected";
+ case PUBLIC:
+ return "public";
+ default:
+ throw new IllegalStateException("invalid method visibility: " + this.methodVisibility);
+ }
+ }
+
+ public boolean generateGettersAndSetters() {
+ return this.generateGettersAndSetters;
+ }
+ public void setGenerateGettersAndSetters(boolean generateGettersAndSetters) {
+ this.generateGettersAndSetters = generateGettersAndSetters;
+ }
+
+ public boolean generateDefaultConstructor() {
+ return this.generateDefaultConstructor;
+ }
+ public void setGenerateDefaultConstructor(boolean generateDefaultConstructor) {
+ this.generateDefaultConstructor = generateDefaultConstructor;
+ }
+
+ public boolean serializable() {
+ return this.serializable;
+ }
+ public void setSerializable(boolean serializable) {
+ this.serializable = serializable;
+ }
+
+ public boolean generateSerialVersionUID() {
+ return this.generateSerialVersionUID;
+ }
+ public void setGenerateSerialVersionUID(boolean generateSerialVersionUID) {
+ this.generateSerialVersionUID = generateSerialVersionUID;
+ }
+
+ public boolean generateEmbeddedIdForCompoundPK() {
+ return this.generateEmbeddedIdForCompoundPK;
+ }
+ public void setGenerateEmbeddedIdForCompoundPK(boolean generateEmbeddedIdForCompoundPK) {
+ this.generateEmbeddedIdForCompoundPK = generateEmbeddedIdForCompoundPK;
+ }
+
+ public boolean generateIdClassForCompoundPK() {
+ return ! this.generateEmbeddedIdForCompoundPK;
+ }
+ public void setGenerateIdClassForCompoundPK(boolean generateIdClassForCompoundPK) {
+ this.generateEmbeddedIdForCompoundPK = ! generateIdClassForCompoundPK;
+ }
+
+ /**
+ * key = table
+ * value = user-supplied override entity name
+ */
+ public String getOverrideEntityName(Table table) {
+ return this.overrideEntityNames.get(table);
+ }
+ public void setOverrideEntityName(Table table, String overrideEntityName) {
+ this.overrideEntityNames.put(table, overrideEntityName);
+ }
+ public void clearOverrideEntityNames() {
+ this.overrideEntityNames.clear();
+ }
+ public void setOverrideEntityNames(Map<Table, String> overrideEntityNames) {
+ this.clearOverrideEntityNames();
+ for (Map.Entry<Table, String> entry : overrideEntityNames.entrySet()) {
+ this.setOverrideEntityName(entry.getKey(), entry.getValue());
+ }
+ }
+
+ }
+
+
+ // ********** config **********
+
+ public static interface OverwriteConfirmer {
+ /**
+ * Return whether the entity generator should overwrite the specified
+ * file.
+ */
+ boolean overwrite(String className);
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenScope.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenScope.java
new file mode 100644
index 0000000000..ee9db7fa8d
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenScope.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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.gen.internal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jpt.db.internal.Table;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
+
+class GenScope {
+ private final Map<Table, GenTable> genTables = new HashMap<Table, GenTable>();
+
+ private IProgressMonitor progressMonitor;
+
+ // ********** construction/initialization **********
+
+ GenScope(Collection<Table> tables, EntityGenerator.Config entityConfig, IProgressMonitor progressMonitor) {
+ super();
+ this.initialize(tables, entityConfig, progressMonitor);
+ }
+
+ private void checkCanceled() {
+ if (this.progressMonitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ }
+
+ private void initialize(Collection<Table> tables, EntityGenerator.Config entityConfig, IProgressMonitor monitor) {
+ this.progressMonitor = monitor;
+ this.buildGenTables(tables, entityConfig);
+ checkCanceled();
+ this.configureManyToManyRelations();
+ checkCanceled();
+ this.configureManyToOneRelations();
+ checkCanceled();
+ this.configureFieldNames();
+ checkCanceled();
+ }
+
+ private void buildGenTables(Collection<Table> tables, EntityGenerator.Config entityConfig) {
+ int size = tables.size();
+ // pass around a growing list of the entity names so we can avoid duplicates
+ Set<String> entityNames = new HashSet<String>(size);
+ for (Table table : tables) {
+ this.buildGenTable(table, entityConfig, entityNames);
+ this.progressMonitor.worked(40/size);
+ }
+ }
+
+ private void buildGenTable(Table table, EntityGenerator.Config entityConfig, Collection<String> entityNames) {
+ this.genTables.put(table, new GenTable(this, table, entityConfig, entityNames));
+ }
+
+ /**
+ * find all the "join" tables
+ */
+ private void configureManyToManyRelations() {
+ int tablesSize = CollectionTools.size(this.tables());
+
+ //first time takes the longest, should we take that into account?
+ for (Iterator<GenTable> stream = this.tables(); stream.hasNext(); ) {
+ checkCanceled();
+ stream.next().configureManyToManyRelations();
+ this.progressMonitor.worked(730/tablesSize);
+ }
+ // revert any "join" table that is referenced by another table back to an "entity" table
+ Set<GenTable> referencedTables = this.buildReferencedTables();
+ tablesSize = CollectionTools.size(this.joinTables());
+ for (Iterator<GenTable> stream = this.joinTables(); stream.hasNext(); ) {
+ GenTable joinGenTable = stream.next();
+ if (referencedTables.contains(joinGenTable)) {
+ joinGenTable.clearJoinTableRelation();
+ }
+ this.progressMonitor.worked(40/tablesSize);
+ }
+ }
+
+ /**
+ * find all the many-to-one and one-to-many relations
+ */
+ private void configureManyToOneRelations() {
+ int tablesSize = CollectionTools.size(this.entityTables());
+ for (Iterator<GenTable> stream = this.entityTables(); stream.hasNext(); ) {
+ stream.next().configureManyToOneRelations();
+ this.progressMonitor.worked(50/tablesSize);
+ }
+ }
+
+ /**
+ * determine all the Java field names up-front because we will
+ * need them for things like 'mappedBy' annotation elements
+ */
+ private void configureFieldNames() {
+ int tablesSize = CollectionTools.size(this.entityTables());
+ for (Iterator<GenTable> stream = this.entityTables(); stream.hasNext(); ) {
+ stream.next().configureFieldNames();
+ this.progressMonitor.worked(50/tablesSize);
+ }
+ }
+
+
+ // ********** package API **********
+
+ /**
+ * return only the gen tables that are suitable for generating
+ * entities (i.e. exclude the "join" tables)
+ */
+ Iterator<GenTable> entityTables() {
+ return new FilteringIterator<GenTable>(this.tables()) {
+ @Override
+ protected boolean accept(Object next) {
+ return ! ((GenTable) next).isJoinTable();
+ }
+ };
+ }
+
+ int numEntityTables() {
+ return CollectionTools.size(entityTables());
+ }
+
+ /**
+ * return the gen table corresponding to the specified table
+ */
+ GenTable genTable(Table table) {
+ return this.genTables.get(table);
+ }
+
+
+ // ********** internal API **********
+
+ private Iterator<GenTable> tables() {
+ return this.genTables.values().iterator();
+ }
+
+ /**
+ * return only the "join" gen tables
+ */
+ private Iterator<GenTable> joinTables() {
+ return new FilteringIterator<GenTable>(this.tables()) {
+ @Override
+ protected boolean accept(Object next) {
+ return ((GenTable) next).isJoinTable();
+ }
+ };
+ }
+
+ /**
+ * build a set of the tables that are referenced by other tables
+ * in the scope
+ */
+ private Set<GenTable> buildReferencedTables() {
+ int size = CollectionTools.size(this.tables());
+ Set<GenTable> referencedTables = new HashSet<GenTable>(this.genTables.size());
+ for (Iterator<GenTable> stream = this.tables(); stream.hasNext(); ) {
+ stream.next().addReferencedTablesTo(referencedTables);
+ this.progressMonitor.worked(20/size);
+ }
+ return referencedTables;
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenTable.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenTable.java
new file mode 100644
index 0000000000..ea7fd3d3c9
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenTable.java
@@ -0,0 +1,342 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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.gen.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.eclipse.jpt.db.internal.Column;
+import org.eclipse.jpt.db.internal.ForeignKey;
+import org.eclipse.jpt.db.internal.Table;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.jpt.utility.internal.NameTools;
+import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
+
+/**
+ * associate a table with the various relations that will be used when
+ * generating the entity
+ */
+class GenTable {
+ private final GenScope scope;
+ private final Table table;
+ private final EntityGenerator.Config entityConfig;
+ private final String entityName;
+ private ManyToManyRelation joinTableRelation;
+ private Collection<ManyToManyRelation> ownedManyToManyRelations = new ArrayList<ManyToManyRelation>();
+ private Collection<ManyToManyRelation> nonOwnedManyToManyRelations = new ArrayList<ManyToManyRelation>();
+ private Collection<ManyToOneRelation> manyToOneRelations = new ArrayList<ManyToOneRelation>();
+ private Collection<OneToManyRelation> oneToManyRelations = new ArrayList<OneToManyRelation>();
+ private Set<Column> foreignKeyColumns = new HashSet<Column>();
+
+ // key=column/relation; value=name
+ private final Map<Object, String> fieldNames = new HashMap<Object, String>();
+
+ private static final Object EMBEDDED_ID_VIRTUAL_COLUMN = new Object();
+
+
+ // ********** construction/initialization **********
+
+ GenTable(GenScope scope, Table table, EntityGenerator.Config entityConfig, Collection<String> entityNames) {
+ super();
+ this.scope = scope;
+ this.table = table;
+ this.entityConfig = entityConfig;
+ this.entityName = this.buildEntityName(entityNames);
+ }
+
+ private String buildEntityName(Collection<String> entityNames) {
+ String name = this.table.shortJavaClassName();
+ String overrideEntityName = this.entityConfig.getOverrideEntityName(this.table);
+ if (overrideEntityName == null) {
+ if (this.entityConfig.convertToCamelCase()) {
+ name = StringTools.convertUnderscoresToCamelCase(name);
+ }
+ } else {
+ name = overrideEntityName;
+ }
+ name = NameTools.uniqueNameForIgnoreCase(name, entityNames);
+ entityNames.add(name);
+ return name;
+ }
+
+
+ // ********** package API **********
+
+ /**
+ * determine whether the table is a "join" table within the table's scope
+ */
+ void configureManyToManyRelations() {
+ if (this.table.foreignKeysSize() != 2) {
+ // the table must have exactly 2 foreign keys
+ return;
+ }
+ for (Iterator<Column> stream = this.table.columns(); stream.hasNext(); ) {
+ if ( ! this.table.foreignKeyColumnsContains(stream.next())) {
+ // all the table's columns must belong to one (or both) of the 2 foreign keys
+ return;
+ }
+ }
+ Iterator<ForeignKey> fKeys = this.table.foreignKeys();
+ ForeignKey owningFK = fKeys.next();
+ ForeignKey nonOwningFK = fKeys.next();
+ GenTable owningTable = this.scope.genTable(owningFK.getReferencedTable());
+ GenTable nonOwningTable = this.scope.genTable(nonOwningFK.getReferencedTable());
+ if ((owningTable == null) || (nonOwningTable == null)) {
+ // both tables must be in the scope
+ return;
+ }
+ this.joinTableRelation = new ManyToManyRelation(this, owningFK, owningTable, nonOwningFK, nonOwningTable);
+ }
+
+ void addReferencedTablesTo(Set<GenTable> referencedTables) {
+ for (Iterator<ForeignKey> stream = this.table.foreignKeys(); stream.hasNext(); ) {
+ ForeignKey fk = stream.next();
+ GenTable genTable = this.scope.genTable(fk.getReferencedTable());
+ if (genTable != null) {
+ referencedTables.add(genTable);
+ }
+ }
+ }
+
+ void clearJoinTableRelation() {
+ this.joinTableRelation.clear();
+ this.joinTableRelation = null;
+ }
+
+ /**
+ * find "in-scope" foreign keys
+ */
+ void configureManyToOneRelations() {
+ for (Iterator<ForeignKey> stream = this.table.foreignKeys(); stream.hasNext(); ) {
+ ForeignKey fk = stream.next();
+ GenTable referencedtable = this.scope.genTable(fk.getReferencedTable());
+ if (referencedtable == null) {
+ continue; // skip to next FK
+ }
+ this.manyToOneRelations.add(new ManyToOneRelation(this, fk, referencedtable));
+ }
+ }
+
+ /**
+ * now that all the relations are in place, we can configure the Java
+ * field names
+ */
+ void configureFieldNames() {
+ Set<Column> columns = CollectionTools.set(this.table.columns());
+ if ((this.table.primaryKeyColumnsSize() > 1) && this.entityConfig.generateEmbeddedIdForCompoundPK()) {
+ // if we are going to generate an EmbeddedId field, add it to
+ // 'fieldNames' so we don't collide with it later, when generating
+ // field names for the columns etc.
+ this.configureFieldName(EMBEDDED_ID_VIRTUAL_COLUMN, "pk");
+ }
+ this.configureManyToOneFieldNames(columns);
+ this.configureBasicFieldNames(columns);
+ this.configureOneToManyFieldNames();
+ this.configureOwnedManyToManyFieldNames();
+ this.configureNonOwnedManyToManyFieldNames();
+ }
+
+ /**
+ * return the columns that are part of the table's primary key
+ * but are also part of an "in-scope" foreign key
+ */
+ public Iterator<Column> readOnlyPrimaryKeyColumns() {
+ return new FilteringIterator<Column>(this.table.primaryKeyColumns()) {
+ @Override
+ protected boolean accept(Object column) {
+ return GenTable.this.foreignKeyColumnsContains((Column) column);
+ }
+ };
+ }
+
+ /**
+ * return the columns that are part of the table's primary key
+ * but are NOT part of any "in-scope" foreign key
+ */
+ Iterator<Column> writablePrimaryKeyColumns() {
+ return new FilteringIterator<Column>(this.table.primaryKeyColumns()) {
+ @Override
+ protected boolean accept(Object column) {
+ return ! GenTable.this.foreignKeyColumnsContains((Column) column);
+ }
+ };
+ }
+
+ /**
+ * return the columns that NEITHER part of the table's primary key
+ * NOR part of any foreign key
+ */
+ public Iterator<Column> nonPrimaryKeyBasicColumns() {
+ return new FilteringIterator<Column>(this.table.columns()) {
+ @Override
+ protected boolean accept(Object column) {
+ return ! (GenTable.this.primaryKeyColumnsContains((Column) column)
+ || GenTable.this.foreignKeyColumnsContains((Column) column));
+ }
+ };
+ }
+
+ Table getTable() {
+ return this.table;
+ }
+
+ String getEntityName() {
+ return this.entityName;
+ }
+
+ boolean isJoinTable() {
+ return this.joinTableRelation != null;
+ }
+
+ void addOwnedManyToManyRelation(ManyToManyRelation relation) {
+ this.ownedManyToManyRelations.add(relation);
+ }
+
+ void removeOwnedManyToManyRelation(ManyToManyRelation relation) {
+ this.ownedManyToManyRelations.remove(relation);
+ }
+
+ void addNonOwnedManyToManyRelation(ManyToManyRelation relation) {
+ this.nonOwnedManyToManyRelations.add(relation);
+ }
+
+ void removeNonOwnedManyToManyRelation(ManyToManyRelation relation) {
+ this.nonOwnedManyToManyRelations.remove(relation);
+ }
+
+ void addOneToManyRelation(OneToManyRelation relation) {
+ this.oneToManyRelations.add(relation);
+ }
+
+ String javaFieldName() {
+ return this.table.javaFieldName();
+ }
+
+ Iterator<ManyToOneRelation> manyToOneRelations() {
+ return this.manyToOneRelations.iterator();
+ }
+
+ Iterator<OneToManyRelation> oneToManyRelations() {
+ return this.oneToManyRelations.iterator();
+ }
+
+ Iterator<ManyToManyRelation> ownedManyToManyRelations() {
+ return this.ownedManyToManyRelations.iterator();
+ }
+
+ Iterator<ManyToManyRelation> nonOwnedManyToManyRelations() {
+ return this.nonOwnedManyToManyRelations.iterator();
+ }
+
+ /**
+ * the key can be a column or relation
+ */
+ private String fieldNameForInternal(Object o) {
+ return this.fieldNames.get(o);
+ }
+
+ /**
+ * this will return null if we don't want an embedded id field
+ */
+ String fieldNameForEmbeddedId() {
+ return this.fieldNameForInternal(EMBEDDED_ID_VIRTUAL_COLUMN);
+ }
+
+ String fieldNameFor(Column column) {
+ return this.fieldNameForInternal(column);
+ }
+
+ String fieldNameFor(ManyToOneRelation relation) {
+ return this.fieldNameForInternal(relation);
+ }
+
+ String fieldNameFor(OneToManyRelation relation) {
+ return this.fieldNameForInternal(relation);
+ }
+
+ String fieldNameFor(ManyToManyRelation relation) {
+ return this.fieldNameForInternal(relation);
+ }
+
+ String name() {
+ return this.table.getName();
+ }
+
+
+ // ********** internal API **********
+
+ /**
+ * while we are figuring out the names for the m:1 fields, remove from the
+ * specified set of columns the columns that are only part of the foreign keys
+ */
+ private void configureManyToOneFieldNames(Set<Column> columns) {
+ for (ManyToOneRelation relation : this.manyToOneRelations) {
+ CollectionTools.removeAll(columns, relation.getForeignKey().nonPrimaryKeyBaseColumns());
+ CollectionTools.addAll(this.foreignKeyColumns, relation.getForeignKey().baseColumns());
+ relation.setMappedBy(this.configureFieldName(relation, relation.javaFieldName()));
+ }
+ }
+
+ private String configureFieldName(Object o, String fieldName) {
+ fieldName = this.camelCase(fieldName);
+ fieldName = NameTools.uniqueNameFor(fieldName, this.fieldNames.values());
+ this.fieldNames.put(o, fieldName);
+ return fieldName;
+ }
+
+ private String camelCase(String name) {
+ return this.entityConfig.convertToCamelCase() ?
+ StringTools.convertUnderscoresToCamelCase(name, false) // false = don't capitalize first letter
+ :
+ name;
+ }
+
+ /**
+ * build a unique field name for the specified "basic" columns,
+ * checking for name collisions
+ */
+ private void configureBasicFieldNames(Set<Column> columns) {
+ for (Column column : columns) {
+ this.configureFieldName(column, column.javaFieldName());
+ }
+ }
+
+ private void configureOneToManyFieldNames() {
+ for (OneToManyRelation relation : this.oneToManyRelations) {
+ this.configureFieldName(relation, relation.javaFieldName());
+ }
+ }
+
+ private void configureOwnedManyToManyFieldNames() {
+ for (ManyToManyRelation relation : this.ownedManyToManyRelations) {
+ relation.setMappedBy(this.configureFieldName(relation, relation.javaFieldNameFor(this)));
+ }
+ }
+
+ private void configureNonOwnedManyToManyFieldNames() {
+ for (ManyToManyRelation relation : this.nonOwnedManyToManyRelations) {
+ this.configureFieldName(relation, relation.javaFieldNameFor(this));
+ }
+ }
+
+ boolean foreignKeyColumnsContains(Column column) {
+ return this.foreignKeyColumns.contains(column);
+ }
+
+ boolean primaryKeyColumnsContains(Column column) {
+ return this.table.primaryKeyColumnsContains(column);
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToManyRelation.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToManyRelation.java
new file mode 100644
index 0000000000..d87608715a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToManyRelation.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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.gen.internal;
+
+import org.eclipse.jpt.db.internal.ForeignKey;
+
+/**
+ * This object is shared by the two gen tables that make up the relation.
+ * Upon construction, 'mappedBy' will be 'null'. The first gen table to be
+ * used to generate an entity will fill in 'mappedBy' with the appropriate
+ * field/property name.
+ */
+class ManyToManyRelation {
+ private final GenTable joinTable;
+ private final ForeignKey owningForeignKey;
+ private final GenTable owningTable;
+ private final ForeignKey nonOwningForeignKey;
+ private final GenTable nonOwningTable;
+ private String mappedBy;
+
+
+ ManyToManyRelation(GenTable joinTable, ForeignKey owningForeignKey, GenTable owningTable, ForeignKey nonOwningForeignKey, GenTable nonOwningTable) {
+ super();
+ this.joinTable = joinTable;
+
+ this.owningForeignKey = owningForeignKey;
+ this.owningTable = owningTable;
+ owningTable.addOwnedManyToManyRelation(this);
+
+ this.nonOwningForeignKey = nonOwningForeignKey;
+ this.nonOwningTable = nonOwningTable;
+ nonOwningTable.addNonOwnedManyToManyRelation(this);
+ }
+
+ GenTable getJoinTable() {
+ return this.joinTable;
+ }
+
+ ForeignKey getOwningForeignKey() {
+ return this.owningForeignKey;
+ }
+
+ GenTable getOwningTable() {
+ return this.owningTable;
+ }
+
+ ForeignKey getNonOwningForeignKey() {
+ return this.nonOwningForeignKey;
+ }
+
+ GenTable getNonOwningTable() {
+ return this.nonOwningTable;
+ }
+
+ private GenTable otherTable(GenTable table) {
+ return (table == this.owningTable) ? this.nonOwningTable : this.owningTable;
+ }
+
+ String javaFieldNameFor(GenTable table) {
+ // TODO i18n?
+ return this.otherTable(table).javaFieldName() + "_collection";
+ }
+
+ void clear() {
+ this.owningTable.removeOwnedManyToManyRelation(this);
+ this.nonOwningTable.removeNonOwnedManyToManyRelation(this);
+ }
+
+ String getMappedBy() {
+ return this.mappedBy;
+ }
+
+ void setMappedBy(String mappedBy) {
+ this.mappedBy = mappedBy;
+ }
+
+ String owningEntityName() {
+ return this.owningTable.getEntityName();
+ }
+
+ String nonOwningEntityName() {
+ return this.nonOwningTable.getEntityName();
+ }
+
+ boolean joinTableNameIsDefault() {
+ return this.joinTable.name().equals(this.getOwningTable().name() + "_" + this.getNonOwningTable().name());
+ }
+
+ boolean joinColumnsIsDefaultFor(String javaFieldName) {
+ return this.owningForeignKey.isDefaultFor(javaFieldName);
+ }
+
+ boolean inverseJoinColumnsIsDefaultFor(String javaFieldName) {
+ return this.nonOwningForeignKey.isDefaultFor(javaFieldName);
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToOneRelation.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToOneRelation.java
new file mode 100644
index 0000000000..333018d3e6
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToOneRelation.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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.gen.internal;
+
+import org.eclipse.jpt.db.internal.ForeignKey;
+
+class ManyToOneRelation {
+ private final GenTable baseTable; // the "many" side
+ private final ForeignKey foreignKey;
+ private final GenTable referencedTable; // the "one" side
+ private String mappedBy;
+
+
+ ManyToOneRelation(GenTable baseTable, ForeignKey foreignKey, GenTable referencedTable) {
+ super();
+ this.baseTable = baseTable;
+ this.foreignKey = foreignKey;
+ this.referencedTable = referencedTable;
+ referencedTable.addOneToManyRelation(new OneToManyRelation(this));
+ }
+
+ GenTable getBaseTable() {
+ return this.baseTable;
+ }
+
+ ForeignKey getForeignKey() {
+ return this.foreignKey;
+ }
+
+ GenTable getReferencedTable() {
+ return this.referencedTable;
+ }
+
+ String javaFieldName() {
+ return this.foreignKey.javaFieldName();
+ }
+
+ String getMappedBy() {
+ return this.mappedBy;
+ }
+
+ void setMappedBy(String mappedBy) {
+ this.mappedBy = mappedBy;
+ }
+
+ String baseEntityName() {
+ return this.baseTable.getEntityName();
+ }
+
+ String referencedEntityName() {
+ return this.referencedTable.getEntityName();
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/OneToManyRelation.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/OneToManyRelation.java
new file mode 100644
index 0000000000..4656d00c12
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/OneToManyRelation.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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.gen.internal;
+
+class OneToManyRelation {
+ private final ManyToOneRelation manyToOneRelation;
+
+ OneToManyRelation(ManyToOneRelation manyToOneRelation) {
+ super();
+ this.manyToOneRelation = manyToOneRelation;
+ }
+
+ ManyToOneRelation getManyToOneRelation() {
+ return this.manyToOneRelation;
+ }
+
+ String javaFieldName() {
+ // TODO i18n?
+ return this.manyToOneRelation.getBaseTable().javaFieldName() + "_collection";
+ }
+
+ String mappedBy() {
+ return this.manyToOneRelation.getMappedBy();
+ }
+
+ String referencedEntityName() {
+ return this.manyToOneRelation.baseEntityName();
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/PackageGenerator.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/PackageGenerator.java
new file mode 100644
index 0000000000..bce0da3063
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/PackageGenerator.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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.gen.internal;
+
+import java.util.Collection;
+import java.util.Iterator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jpt.db.internal.Table;
+import org.eclipse.jpt.gen.internal.EntityGenerator.OverwriteConfirmer;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+
+/**
+ * This generator will generate a package of entities for a set of tables.
+ */
+public class PackageGenerator {
+ private final Config config;
+ private final EntityGenerator.Config entityConfig;
+ private final GenScope scope;
+ private final OverwriteConfirmer overwriteConfirmer;
+ private final IProgressMonitor monitor;
+
+
+ // ********** public API **********
+
+ public static void generateEntities(Config config, EntityGenerator.Config entityConfig, Collection<Table> tables, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) {
+ if ((config == null) || (entityConfig == null) || (tables == null)) {
+ throw new NullPointerException();
+ }
+ new PackageGenerator(config, entityConfig, tables, overwriteConfirmer, monitor).generateEntities();
+ }
+
+
+ // ********** construction/initialization **********
+
+ private PackageGenerator(Config config, EntityGenerator.Config entityConfig, Collection<Table> tables, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) {
+ super();
+ this.config = config;
+ this.entityConfig = entityConfig;
+ this.scope = new GenScope(tables, entityConfig, monitor);
+ this.overwriteConfirmer = overwriteConfirmer;
+ this.monitor = monitor;
+ }
+
+
+ // ********** generation **********
+
+ private void generateEntities() {
+ int size = CollectionTools.size(this.scope.entityTables());
+ for (Iterator<GenTable> stream = this.scope.entityTables(); stream.hasNext(); ) {
+ checkCanceled();
+ this.buildEntity(stream.next());
+ this.monitor.worked(50/size);
+ }
+ }
+
+ private void checkCanceled() {
+ if (this.monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ }
+
+
+ private void buildEntity(GenTable genTable) {
+ EntityGenerator.generateEntity(this.entityConfig, this.config.getPackageFragment(), genTable, overwriteConfirmer, this.monitor);
+ }
+
+
+ // ********** config **********
+
+ public static class Config {
+ private IPackageFragment packageFragment;
+
+ public IPackageFragment getPackageFragment() {
+ return this.packageFragment;
+ }
+ public void setPackageFragment(IPackageFragment packageFragment) {
+ this.packageFragment = packageFragment;
+ }
+
+ }
+
+}

Back to the top