[251293] Initial check-in for entity generation contribution.  Added dependency on apache commons, commons.lang, and oro from orbit  Temporarily added local dependency on velocity-1.5 until it is also included in orbit.
diff --git a/jpa/features/org.eclipse.jpt.feature/feature.xml b/jpa/features/org.eclipse.jpt.feature/feature.xml
index 4288ecf..509f764 100644
--- a/jpa/features/org.eclipse.jpt.feature/feature.xml
+++ b/jpa/features/org.eclipse.jpt.feature/feature.xml
@@ -73,4 +73,25 @@
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.apache.commons.collections"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.apache.commons.lang"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.apache.oro"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
diff --git a/jpa/plugins/org.eclipse.jpt.gen/.classpath b/jpa/plugins/org.eclipse.jpt.gen/.classpath
index 8f25741..731b00f 100644
--- a/jpa/plugins/org.eclipse.jpt.gen/.classpath
+++ b/jpa/plugins/org.eclipse.jpt.gen/.classpath
@@ -2,6 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="property_files"/>
+	<classpathentry exported="true" kind="lib" path="lib/velocity-1.5.jar"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF b/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF
index b6698a3..ee9c80a 100644
--- a/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF
+++ b/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF
@@ -3,12 +3,20 @@
 Bundle-Name: %pluginName
 Bundle-Vendor: %providerName
 Bundle-SymbolicName: org.eclipse.jpt.gen
-Bundle-Version: 1.2.100.qualifier
-Bundle-ClassPath: .
+Bundle-Version: 1.3.0.qualifier
+Bundle-ClassPath: .,
+ lib/velocity-1.5.jar
 Bundle-Localization: plugin
-Export-Package: org.eclipse.jpt.gen.internal; x-friends:="org.eclipse.jpt.ui"
+Export-Package: org.eclipse.jpt.gen.internal;x-friends:="org.eclipse.jpt.ui",
+ org.eclipse.jpt.gen.internal2,
+ org.eclipse.jpt.gen.internal2.util
 Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
  org.eclipse.jdt.core;bundle-version="[3.4.0,4.0.0)",
  org.eclipse.jpt.utility;bundle-version="[1.2.0,2.0.0)",
- org.eclipse.jpt.db;bundle-version="[1.2.0,2.0.0)"
+ org.eclipse.jpt.db;bundle-version="[1.2.0,2.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.jface.text;bundle-version="[3.4.0,4.0.0)",
+ org.apache.commons.collections;bundle-version="3.2.0",
+ org.apache.commons.lang;bundle-version="2.1.0",
+ org.apache.oro;bundle-version="2.0.8"
 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
index a1fd5b8..038c63b 100644
--- a/jpa/plugins/org.eclipse.jpt.gen/build.properties
+++ b/jpa/plugins/org.eclipse.jpt.gen/build.properties
@@ -13,5 +13,6 @@
 bin.includes = .,\
                META-INF/,\
                about.html,\
-               plugin.properties
+               plugin.properties,\
+               lib/velocity-1.5.jar
 jars.compile.order = .
diff --git a/jpa/plugins/org.eclipse.jpt.gen/lib/velocity-1.5.jar b/jpa/plugins/org.eclipse.jpt.gen/lib/velocity-1.5.jar
new file mode 100644
index 0000000..7c7f2c4
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/lib/velocity-1.5.jar
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.gen/property_files/jpt_gen.properties b/jpa/plugins/org.eclipse.jpt.gen/property_files/jpt_gen.properties
index 03e8908..3427be1 100644
--- a/jpa/plugins/org.eclipse.jpt.gen/property_files/jpt_gen.properties
+++ b/jpa/plugins/org.eclipse.jpt.gen/property_files/jpt_gen.properties
@@ -11,3 +11,6 @@
 PackageGenerator_taskName=Generate Entities
 GenScope_taskName=Build Database Model
 EntityGenerator_taskName=Generate Entity: {0}
+Error_Generating_Entities = Error Generating Entities; 
+
+Templates_notFound = Unable to find JPA entities generation templates in plugin
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JptGenMessages.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JptGenMessages.java
index bc3bbf0..b765abd 100644
--- a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JptGenMessages.java
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JptGenMessages.java
@@ -19,6 +19,7 @@
 	public static String PackageGenerator_taskName;
 	public static String GenScope_taskName;
 	public static String EntityGenerator_taskName;
+	public static String Templates_notFound;
 
 	private static final String BUNDLE_NAME = "jpt_gen"; //$NON-NLS-1$
 	private static final Class<?> BUNDLE_CLASS = JptGenMessages.class;
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/Association.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/Association.java
new file mode 100644
index 0000000..aef08c4
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/Association.java
@@ -0,0 +1,387 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2;
+
+import java.util.List;
+
+import org.eclipse.jpt.db.ForeignKey;
+import org.eclipse.jpt.gen.internal2.util.StringUtil;
+
+/**
+ * Represents an ORM association.
+ * There are two types of associations:
+ * <ul><li>simple association: An association between two database tables.
+ * The <em>referrer</code> table is the one containing the foreign key
+ * , the <em>referenced</code> table is the other party.<br>
+ * 
+ * <li>many to many association: An association between two tables joined by 
+ * a <em>join table</em>.
+ * In the example AUTHOR, BOOK, AUTHOR_BOOK, The referrer and referenced are 
+ * AUTHOR and  BOOK, and the join table is AUTHOR_BOOK.
+ * </ul>
+ * 
+ */
+public class Association implements java.io.Serializable
+{
+	private final static long serialVersionUID = 2;
+
+	public static final String MANY_TO_ONE = "many-to-one";
+	public static final String MANY_TO_MANY = "many-to-many";
+	public static final String ONE_TO_ONE = "one-to-one";
+	public static final String ONE_TO_MANY = "one-to-many";
+	
+	public static final String BI_DI = "bi-di";
+	public static final String NORMAL_DI = "normal-di"; //referrer->referenced
+	public static final String OPPOSITE_DI = "opposite-di"; //referenced->referrer
+	
+	private transient ORMGenCustomizer mCustomizer;
+	private String mReferrerTableName;
+	private String mReferencedTableName;
+	private String mJoinTableName;
+
+	private List<String> mReferrerColNames; /*String objects*/
+	private List<String> mReferencedColNames; /*String objects*/
+	private List<String> mReferrerJoinColNames; /*String objects*/
+	private List<String> mReferencedJoinColNames; /*String objects*/
+
+	private transient List<ORMGenColumn> mReferrerCols; /*ORMGenColumn objects*/
+	private transient List<ORMGenColumn> mReferencedCols; /*ORMGenColumn objects*/
+	private transient List<ORMGenColumn> mReferrerJoinCols; /*ORMGenColumn objects*/
+	private transient List<ORMGenColumn> mReferencedJoinCols; /*ORMGenColumn objects*/
+	
+	private String mCardinality;
+	private String mDirectionality;
+	private byte mFlags = GENERATED;
+	
+	private AssociationRole mReferrerRole;
+	private AssociationRole mReferencedRole;
+
+	private transient ForeignKey mForeignKey;	
+	
+	/*constants for mFlags*/
+	/*whether the association should be generated*/
+	private static final byte GENERATED = 1 << 0;
+	/*whether the association is custom (i.e is not auto computed from foreign keys relationships).*/
+	private static final byte CUSTOM = 1 << 1;
+	
+	/**
+	 * The simple association constructor.
+	 * The 2 tables are joined when the values of each column in
+	 * referrerColNames match its corresponding column in referencedColNames.
+	 * 
+	 * @param referrerTableName The "foreign key" table.
+	 * @param referrerColNames The column names in the referrer table.
+	 * @param referencedTableName The "primary key" table.
+	 * @param referencedColNames The column names in the referenced table.
+	 */
+	public Association(ORMGenCustomizer customizer, String referrerTableName, List<String> referrerColNames
+			, String referencedTableName, List<String> referencedColNames)  {
+		super();
+		
+		mCustomizer = customizer;
+		mReferrerTableName = referrerTableName;
+		mReferencedTableName = referencedTableName;
+		mReferrerColNames = referrerColNames;
+		mReferencedColNames = referencedColNames;
+		
+		mCardinality = MANY_TO_ONE;
+		mDirectionality = BI_DI;
+		
+		setCustom(true);
+	}
+	/**
+	 * The many to many constructor.
+	 * The 2 tables are joined when the values of each column in
+	 * referrerColNames match its corresponding column in referrerJoinColNames
+	 * , and each column in referencedColNames match its corresponding column in referencedJoinColNames.
+	 *
+	 */
+	public Association(ORMGenCustomizer customizer, String referrerTableName, List<String> referrerColNames
+			, String referencedTableName, List<String> referencedColNames
+			, String joinTableName, List<String> referrerJoinColNames, List<String> referencedJoinColNames) {
+		super();
+		
+		mCustomizer = customizer;
+		mReferrerTableName = referrerTableName;
+		mReferencedTableName = referencedTableName;
+		mReferrerColNames = referrerColNames;
+		mReferencedColNames = referencedColNames;
+		mJoinTableName = joinTableName;
+		mReferrerJoinColNames = referrerJoinColNames;
+		mReferencedJoinColNames = referencedJoinColNames;
+		
+		mCardinality = MANY_TO_MANY;	
+		mDirectionality = BI_DI;
+		
+		setCustom(true);
+	}
+	/**
+	 * Empty constructor needed by the deserialization (should not be used otherwise).
+	 */
+	public Association() {
+	}
+	/**
+	 * Computes the cardinality basedon the forign key definitions.
+	 */
+	public void computeCardinality()  {
+		/*by default the association is many-to-one unless the foreign key 
+		 * is also the primary key, in which case it is a one-to-one.*/
+		mCardinality = MANY_TO_ONE;
+		
+		List<ORMGenColumn> referrerCols = getReferrerColumns();
+		List<ORMGenColumn> pkCols = getReferrerTable().getPrimaryKeyColumns();
+		if (pkCols.size() == referrerCols.size()) {
+			boolean isFkPk = true;
+			for (int i = 0, n = pkCols.size(); i < n; ++i) {
+				if (!((ORMGenColumn)pkCols.get(i)).getName().equals(((ORMGenColumn)referrerCols.get(i)).getName())) {
+					isFkPk = false;
+					break;
+				}
+			}
+			if (isFkPk) {
+				mCardinality = ONE_TO_ONE;
+			}
+		}
+		
+		setCustom(false);
+	}
+	/**
+	 * Called after the asscociations are deserialized to attach 
+	 * the customizer object.
+	 */
+	protected void restore(ORMGenCustomizer customizer) {
+		mCustomizer = customizer;
+		
+		if (mReferrerRole != null) {
+			mReferrerRole.restore(this);
+		}
+		if (mReferencedRole != null) {
+			mReferencedRole.restore(this);
+		}
+	}
+	public ORMGenTable getReferrerTable()  {
+		return mCustomizer.getTable(mReferrerTableName);
+	}
+	public String getReferrerTableName() {
+		return mReferrerTableName;
+	}
+	public ORMGenTable getReferencedTable()  {
+		return mCustomizer.getTable(mReferencedTableName);
+	}
+	public String getReferencedTableName() {
+		return mReferencedTableName;
+	}
+	public ORMGenTable getJoinTable()  {
+		return mCustomizer.getTable(mJoinTableName);
+	}
+	public String getJoinTableName() {
+		return mJoinTableName;
+	}
+	/**
+	 * Returns the <code>ORMGenColumn</code> objects for the referrer
+	 * columns.
+	 */
+	public List<ORMGenColumn> getReferrerColumns() {
+		if (mReferrerCols == null) {
+			mReferrerCols = getReferrerTable().getColumnsByNames(mReferrerColNames);
+		}
+		return mReferrerCols;
+	}
+	public List<String> getReferrerColumnNames() {
+		return mReferrerColNames;
+	}
+	/**
+	 * Returns the <code>ORMGenColumn</code> objects for the referenced
+	 * columns.
+	 */
+	public List<ORMGenColumn> getReferencedColumns() {
+		if (mReferencedCols == null) {
+			mReferencedCols = getReferencedTable().getColumnsByNames(mReferencedColNames);
+		}
+		return mReferencedCols;
+	}
+	public List<String> getReferencedColumnNames() {
+		return mReferencedColNames;
+	}
+	public List<ORMGenColumn> getReferrerJoinColumns() {
+		if (mReferrerJoinCols == null) {
+			mReferrerJoinCols = getJoinTable().getColumnsByNames(mReferrerJoinColNames);
+		}
+		return mReferrerJoinCols;
+	}
+	public List<String> getReferrerJoinColumnNames() {
+		return mReferrerJoinColNames;
+	}
+	public List<ORMGenColumn> getReferencedJoinColumns()  {
+		if (mReferencedJoinCols == null) {
+			mReferencedJoinCols = getJoinTable().getColumnsByNames(mReferencedJoinColNames);
+		}
+		return mReferencedJoinCols;
+	}
+	public List<String> getReferencedJoinColumnNames() {
+		return mReferencedJoinColNames;
+	}
+	/**
+	 * Returns the association cardinality, one of {@link #MANY_TO_ONE}|{@link #MANY_TO_MANY}
+	 * |{@link #ONE_TO_ONE}|{@link #ONE_TO_MANY}
+	 */
+	public String getCardinality() {
+		return mCardinality;
+	}
+	public void setCardinality(String cardinality) {
+		assert(cardinality.equals(MANY_TO_ONE) || cardinality.equals(MANY_TO_MANY) || cardinality.equals(ONE_TO_ONE) || cardinality.equals(ONE_TO_MANY));
+		mCardinality = cardinality;
+	}
+	/**
+	 * Returns the association directionality, one of {@link #BI_DI}|{@link #NORMAL_DI}
+	 * |{@link #OPPOSITE_DI}
+	 */
+	public String getDirectionality() {
+		return mDirectionality;
+	}
+	public void setDirectionality(String dir) {
+		assert(dir.equals(BI_DI) || dir.equals(NORMAL_DI) || dir.equals(OPPOSITE_DI));
+		if (!dir.equals(mDirectionality)) {
+			mDirectionality = dir;
+			
+			if (dir.equals(NORMAL_DI)) {
+				mReferencedRole = null;
+			} else if (dir.equals(OPPOSITE_DI)) {
+				mReferrerRole = null;
+			}
+		}
+	}
+	
+	/**
+	 * Tests whether this association is bidirectional.
+	 * This is a shortcut for <code>getDirectionality().equals(BI_DI)</code>.
+	 */
+	public boolean isBidirectional() {
+		return mDirectionality.equals(BI_DI);
+	}
+	/**
+	 * Returns true of this association should be generated. 
+	 */
+	public boolean isGenerated() {
+		return (mFlags & GENERATED) != 0;
+	}
+	public void setGenerated(boolean generated) {
+		if (generated != isGenerated()) {
+			if (generated) {
+				mFlags |= GENERATED;
+			} else {
+				mFlags &= ~GENERATED;
+			}
+			mReferrerRole = mReferencedRole = null;
+		}
+	}
+	/**
+	 * Returns true of this association is custom (i.e is not auto computed from foreign keys relationships). 
+	 */
+	public boolean isCustom() {
+		return (mFlags & CUSTOM) != 0;
+	}
+	public void setCustom(boolean custom) {
+		if (custom) {
+			mFlags |= CUSTOM;
+		} else {
+			mFlags &= ~CUSTOM;
+		}
+	}
+	/**
+	 * Returns the association role for the referrer side, or null 
+	 * if none (i.e if the directionality does not include it).
+	 */
+	public AssociationRole getReferrerRole() {
+		if (mReferrerRole == null && isGenerated()) {
+			if (!getDirectionality().equals(OPPOSITE_DI)) { //BI_DI or NORMAL_DI
+				mReferrerRole = new AssociationRole(this, true/*isReferrerEnd*/);
+			}
+		}
+		return mReferrerRole;
+	}
+	/**
+	 * Returns the association role for the referenced side, or null 
+	 * if none (i.e if the directionality does not include it).
+	 */
+	public AssociationRole getReferencedRole() {
+		if (mReferencedRole == null && isGenerated()) {
+			if (!getDirectionality().equals(Association.NORMAL_DI)) { //BI_DI or OPPOSITE_DI
+				mReferencedRole = new AssociationRole(this, false/*isReferrerEnd*/);
+			}
+		}
+		return mReferencedRole;
+	}
+	/**
+	 * Tests whether this association is valid (valid table and column names).
+	 */
+	protected boolean isValid(){
+		if (!isValidTableAndColumns(mReferrerTableName, mReferrerColNames)
+				|| !isValidTableAndColumns(mReferencedTableName, mReferencedColNames)) {
+			return false;
+		}
+		if (mJoinTableName != null) {
+			if (!isValidTableAndColumns(mJoinTableName, mReferrerJoinColNames)
+					|| !isValidTableAndColumns(mJoinTableName, mReferencedJoinColNames)) {
+				return false;
+			}			
+		}
+		return true;
+	}
+	private boolean isValidTableAndColumns(String tableName, List<String> columnNames) {
+		ORMGenTable table = mCustomizer.getTable(tableName);
+		if (table == null) {
+			return false;
+		}
+		for (int i = 0, n = columnNames.size(); i < n; ++i) {
+			String colName = (String)columnNames.get(i);
+			if (table.getColumnByName(colName) == null) {
+				return false;
+			}
+		}
+		return true;
+	}
+	
+	public void setForeignKey(ForeignKey foreignKey) {
+		this.mForeignKey = foreignKey;
+		
+	}
+	public ForeignKey getForeignKey(){
+		return this.mForeignKey;
+	};	
+	public boolean equals(Object obj) {
+		if( this == obj )
+			return true;
+		if( obj instanceof Association ){
+			Association association2 = (Association)obj;
+			if (!this.getReferrerTableName().equals(association2.getReferrerTableName())
+					|| !this.getReferencedTableName().equals(association2.getReferencedTableName())
+					|| !StringUtil.equalObjects(this.getJoinTableName(), association2.getJoinTableName())
+					|| !this.getReferrerColumnNames().equals(association2.getReferrerColumnNames())
+					|| !this.getReferencedColumnNames().equals(association2.getReferencedColumnNames())
+					) {
+				return false;
+			}					
+			/*the 2 association have the same referrer, referenced and join table*/
+			//If MTO or OTM association
+			if (this.getJoinTableName() == null) {
+				return true;
+			}
+			if (this.getReferrerJoinColumnNames().equals(association2.getReferrerJoinColumnNames())
+					&& this.getReferencedJoinColumnNames().equals(association2.getReferencedJoinColumnNames())) {
+				return true;
+			}
+		}
+		return false;
+	}	
+	public String toString(){
+		return mReferrerTableName + " " + mCardinality + " " + mReferencedTableName ;
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/AssociationRole.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/AssociationRole.java
new file mode 100644
index 0000000..458edfd
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/AssociationRole.java
@@ -0,0 +1,251 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Represents an association role (the referrer or referenced role).
+ * 
+ */
+public class AssociationRole implements java.io.Serializable
+{
+	private transient Association mAssociation; //transient: see restore
+	private boolean mIsReferrerRole;
+	private String mPropertyName;
+	private String mCascade;
+	
+	private final static long serialVersionUID = 1;
+		
+	AssociationRole(Association association, boolean isReferrerRole) {
+		super();
+		
+		mAssociation = association;
+		mIsReferrerRole = isReferrerRole;
+	}
+	/**
+	 * Empty constructor needed by the deserialization (should not be used otherwise).
+	 */
+	public AssociationRole() {
+	}
+	/**
+	 * Called after the asscociations are deserialized to attach 
+	 * the customizer object.
+	 */
+	protected void restore(Association association) {
+		mAssociation = association;
+	}
+	public Association getAssociation() {
+		return mAssociation;
+	}
+	public boolean isReferrerRole() {
+		return mIsReferrerRole;
+	}
+	/**
+	 * Returns the opposite role or null if the association 
+	 * is not bi directional.
+	 */
+	public AssociationRole getOppositeRole() {
+		Association association = getAssociation();
+		if (!association.getDirectionality().equals(Association.BI_DI)) {
+			return null;
+		}
+		if (isReferrerRole()) {
+			return association.getReferencedRole();
+		} else {
+			return association.getReferrerRole();
+		}
+	}
+	/**
+	 * Returns the association cardinality, one of {@link #MANY_TO_ONE}|{@link #MANY_TO_MANY}
+	 * |{@link #ONE_TO_ONE}|{@link #ONE_TO_MANY}
+	 */
+	public String getCardinality() {
+		String type = mAssociation.getCardinality();
+		if (!mIsReferrerRole) {
+			if (type.equals(Association.ONE_TO_MANY)) {
+				type = Association.MANY_TO_ONE;
+			} else if (type.equals(Association.MANY_TO_ONE)) {
+				type = Association.ONE_TO_MANY;
+			}
+		}
+		return type;
+	}
+	public ORMGenTable getReferrerTable() {
+		if (mIsReferrerRole) {
+			return mAssociation.getReferrerTable();
+		} else {
+			return mAssociation.getReferencedTable();
+		}
+	}
+	public List<ORMGenColumn> getReferrerColumns(){
+		if (mIsReferrerRole) {
+			return mAssociation.getReferrerColumns();
+		} else {
+			return mAssociation.getReferencedColumns();
+		}
+	}
+	/**
+	 * Returns the referenced column corresponding to a referrer column.
+	 */
+	public ORMGenColumn getReferencedColumn(String referrerColumn)  {
+		boolean hasJoinTable = mAssociation.getJoinTable() != null;
+		List<ORMGenColumn> referrerColumns = getReferrerColumns();
+		for (int i = 0, n = referrerColumns.size(); i < n; ++i) {
+			ORMGenColumn column = (ORMGenColumn)referrerColumns.get(i);
+			if (column.getName().equals(referrerColumn)) {
+				if (hasJoinTable) {
+					return (ORMGenColumn)getReferrerJoinColumns().get(i);
+				} else {
+					return (ORMGenColumn)getReferencedColumns().get(i);
+				}
+			}
+		}
+		assert(false);
+		return null;
+	}
+	/**
+	 * Returns the referrer column corresponding to a referenced column.
+	 */
+	public ORMGenColumn getReferrerColumn(String referencedColumn)  {
+		boolean hasJoinTable = mAssociation.getJoinTable() != null;
+		List<ORMGenColumn> referencedColumns = getReferencedColumns();
+		for (int i = 0, n = referencedColumns.size(); i < n; ++i) {
+			ORMGenColumn column = (ORMGenColumn)referencedColumns.get(i);
+			if (column.getName().equals(referencedColumn)) {
+				if (hasJoinTable) {
+					return (ORMGenColumn)getReferencedJoinColumns().get(i);
+				} else {
+					return (ORMGenColumn)getReferrerColumns().get(i);
+				}
+			}
+		}
+		assert(false);
+		return null;
+	}
+	public ORMGenTable getReferencedTable()  {
+		if (mIsReferrerRole) {
+			return mAssociation.getReferencedTable();
+		} else {
+			return mAssociation.getReferrerTable();
+		}
+	}
+	public List<ORMGenColumn> getReferencedColumns()  {
+		if (mIsReferrerRole) {
+			return mAssociation.getReferencedColumns();
+		} else {
+			return mAssociation.getReferrerColumns();
+		}
+	}
+	public List<ORMGenColumn> getReferrerJoinColumns()  {
+		if (mIsReferrerRole) {
+			return mAssociation.getReferrerJoinColumns();
+		} else {
+			return mAssociation.getReferencedJoinColumns();
+		}
+	}
+	public List<ORMGenColumn> getReferencedJoinColumns()  {
+		if (mIsReferrerRole) {
+			return mAssociation.getReferencedJoinColumns();
+		} else {
+			return mAssociation.getReferrerJoinColumns();
+		}
+	}
+	
+	/**
+	 * Returns the name that should be used by the generator for 
+	 * the property corresponding to this role.
+	 */
+	public String getPropertyName()   {
+		if (mPropertyName != null) { //if the user explicitly set it then don't be too smart
+			return mPropertyName;
+		}
+		String propName ="";
+		ORMGenTable referrerTable = getReferrerTable();
+		ORMGenTable referencedTable = getReferencedTable();
+
+		boolean isSingular = isSingular();
+		propName = referencedTable.getVarName(isSingular);
+		
+		List<AssociationRole> clashingRoles = new java.util.ArrayList<AssociationRole>(); //roles with our same referrer and referenced tables (i.e would yield the same property name in the same bean)
+		/*make sure there is no role with the same name.*/
+		for (Iterator<AssociationRole> iter = referrerTable.getAssociationRoles().iterator(); iter.hasNext(); ) {
+			AssociationRole role = (AssociationRole)iter.next();
+			if (role.getReferrerTable().getName().equals(referrerTable.getName())
+					&& role.getReferencedTable().getName().equals(referencedTable.getName())
+					&& role.isSingular() == isSingular) {
+				clashingRoles.add(role);
+			}
+		}
+		if (clashingRoles.size() > 1) {
+			int index = clashingRoles.indexOf(this);
+			assert(index >= 0);
+			propName += index+1;
+		}
+		
+		/*make sure there is no column with the same name.*/
+		for (Iterator<ORMGenColumn> iter = referrerTable.getColumns().iterator(); iter.hasNext(); ) {
+			ORMGenColumn column = (ORMGenColumn)iter.next();
+			if (column.getPropertyName().equals(propName)) {
+				String prefix = isSingular ? "Bean" : "Set";
+				propName += prefix;
+				break;
+			}
+		}
+		
+		return propName;
+	}
+	private boolean isSingular() {
+		String cardinality = getCardinality();
+		return cardinality.equals(Association.ONE_TO_ONE) || cardinality.equals(Association.MANY_TO_ONE);
+	}
+	/**
+	 * Changes the name that should be used by the generator for 
+	 * the property corresponding to this role.
+	 * If the argument name is null or empty string then the 
+	 * default computed name is used.
+	 */
+	public void setPropertyName(String name)  {
+		if (name != null && name.length() == 0) {
+			name = null;
+		}
+		if (name != null && name.equals(getPropertyName())) {
+			name = null;
+		}
+		mPropertyName = name;
+	}
+	/**
+	 * Returns the cascade value for this role, or null if none.
+	 */
+	public String getCascade() {
+		return mCascade;
+	}
+	public void setCascade(String cascade) {
+		if (cascade != null && cascade.length() == 0) {
+			cascade = null;
+		}
+		mCascade = cascade;
+	}
+	/**
+	 * Returns a descriptive string used in a comment in the generated 
+	 * file (from the Velocity template).
+	 */
+	public String getDescription()  {
+		//<!-- $directionality $cardinality association to $referencedClassName -->
+		String directionality;
+		if (getAssociation().getDirectionality().equals(Association.BI_DI)) {
+			directionality = "bi-directional";
+		} else {
+			directionality = "uni-directional";
+		}
+		return directionality + " " + getAssociation().getCardinality() + " association to " + getReferencedTable().getClassName();
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/BaseEntityGenCustomizer.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/BaseEntityGenCustomizer.java
new file mode 100644
index 0000000..8b6191c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/BaseEntityGenCustomizer.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jpt.db.Column;
+import org.eclipse.jpt.db.Schema;
+import org.eclipse.jpt.gen.internal2.util.DTPUtil;
+import org.eclipse.jpt.gen.internal2.util.StringUtil;
+
+/**
+ * Default implementation of ORMGenCustomizer according to JPA specification 
+ * for entity generation.
+ * 
+ * This is used to retrieve/change the properties from the wizard
+ * and is also passed as a context object to Velocity.
+ */
+public class BaseEntityGenCustomizer extends ORMGenCustomizer implements java.io.Serializable
+{
+	private final static long serialVersionUID = 1;
+
+	/*mapping kinds*/
+	private static final String BASIC_MAPPING_KIND = "basic";
+	private static final String ID_MAPPING_KIND = "id";
+	private static final String VERSION_MAPPING_KIND = "version";
+
+	
+	/*the strings for generator names. These appear in a combo box 
+	 * and used by the Velocity template processing.*/
+	private static final String AUTO_GENERATOR = "auto";
+	private static final String NONE_GENERATOR = "none";
+	private static final String IDENTITY_GENERATOR = "identity";
+	private static final String SEQUENCE_GENERATOR = "sequence";
+	private static final String TABLE_GENERATOR = "table";
+	
+	public BaseEntityGenCustomizer(){}
+	
+	public void init(File file, Schema schema) {
+		super.init(file, schema);
+	}
+	
+	//-----------------------------------------
+	//------ ORMGenCustomizer methods
+	//-----------------------------------------
+	public List<String> getAllIdGenerators() {
+		List<String> result = new java.util.ArrayList<String>(5);
+		/*add in the order in which they would appear in the combo*/
+		result.add(AUTO_GENERATOR);
+		result.add(IDENTITY_GENERATOR);
+		result.add(SEQUENCE_GENERATOR);
+		result.add(TABLE_GENERATOR);
+		result.add(NONE_GENERATOR);
+		return result;
+	}
+	public String getNoIdGenerator() {
+		return NONE_GENERATOR;
+	}
+	public String getIdentityIdGenerator() {
+		return IDENTITY_GENERATOR;
+	}
+	public Set<String> getSequenceIdGenerators() {
+		Set<String> result = new java.util.HashSet<String>(3);
+		result.add(AUTO_GENERATOR); 
+		result.add(SEQUENCE_GENERATOR);
+		
+		return result;
+	}
+	public String getPropertyTypeFromColumn( Column column) {
+		return DTPUtil.getJavaType( getSchema(), column );
+	}
+	public String[] getAllPropertyTypes() {
+		/*
+		 * Java primitive types, wrapper of the primitive types
+		 * , java.lang.String, java.math.BigInteger,
+		 * java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date,
+		 * java.sql.Time, java.sql.Timestamp, byte[], Byte[], char[], Character[],
+		 * enums, and any other type that implements Serializable.
+		 * */
+		//return in the order that will be used in the combo
+		return new String[] {
+				"boolean"
+				, "Boolean"
+				, "byte"
+				, "Byte"
+				, "byte[]"
+				, "char"
+				, "char[]"
+				, "Character"
+				, "Character[]"
+				, "double"
+				, "Double"
+				, "float"
+				, "Float"
+				, "int"
+				, "Integer"
+				, "long"
+				, "Long"
+				, "Object"
+				, "short"
+				, "Short"
+				, "String"
+				
+				, java.math.BigDecimal.class.getName()
+				, java.math.BigInteger.class.getName()
+				, java.util.Calendar.class.getName()
+				, java.util.Date.class.getName()
+				, java.sql.Date.class.getName()
+				, java.sql.Time.class.getName()
+				, java.sql.Timestamp.class.getName()				
+				};
+	}
+	public String[] getAllMappingKinds() {
+		return new String[] {
+				BASIC_MAPPING_KIND
+				, ID_MAPPING_KIND
+				, VERSION_MAPPING_KIND
+		};
+	}
+	/* (non-Javadoc)
+	 */
+	public String getBasicMappingKind() {
+		return BASIC_MAPPING_KIND;
+	}
+	/* (non-Javadoc)
+	 */
+	public String getIdMappingKind() {
+		return ID_MAPPING_KIND;
+	}
+	public boolean editCascade(AssociationRole role) {
+		return false;
+	}
+
+	protected boolean manySideIsAssociationOwner() {
+		return true;
+	}
+
+	//-----------------------------------------
+	//---- Velocity templates methods
+	//-----------------------------------------
+	/**
+	 * Returns the cascades annotation member value, or empty string 
+	 * if none.
+	 * Empty string is returned instead of null because Velocity does not like null 
+	 * when used in #set.
+	 */
+	public String genCascades(AssociationRole role) {
+		List<String> cascades = StringUtil.strToList(role.getCascade(), ',', true/*trim*/);
+		if (cascades == null) {
+			return "";
+		}
+		StringBuffer buffer = new StringBuffer("{");
+		for (int i = 0, n = cascades.size(); i < n; ++i) {
+			String cascade = (String)cascades.get(i);
+			String enumStr;
+			if (cascade.equals(TagNames.ALL_CASCADE)) {
+				enumStr = "CascadeType.ALL";
+			} else if (cascade.equals(TagNames.PERSIST_CASCADE)) {
+				enumStr = "CascadeType.PERSIST";
+			} else if (cascade.equals(TagNames.MERGE_CASCADE)) {
+				enumStr = "CascadeType.MERGE";
+			} else if (cascade.equals(TagNames.REMOVE_CASCADE)) {
+				enumStr = "CascadeType.REMOVE";
+			} else {
+				assert(cascade.equals(TagNames.REFRESH_CASCADE));
+				enumStr = "CascadeType.REFRESH";
+			}
+			if (i != 0) {
+				buffer.append(", ");
+			}
+			buffer.append(enumStr);
+		}
+		buffer.append('}');
+		return buffer.toString();
+	}
+	/**
+	 * Returns the fetch type annotation member value, or empty string 
+	 * if none.
+	 * Empty string is returned instead of null because Velocity does not like null 
+	 * when used in #set.
+	 */
+	public String genFetch(ORMGenTable table) {
+		String fetch = table.getDefaultFetch();
+		if (fetch == null) {
+			return "";
+		} else if (fetch.equals(ORMGenTable.LAZY_FETCH)) {
+			return "FetchType.LAZY";
+		} else {
+			return "FetchType.EAGER";
+		}
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/DatabaseAnnotationNameBuilder.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/DatabaseAnnotationNameBuilder.java
new file mode 100644
index 0000000..ce93f82
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/DatabaseAnnotationNameBuilder.java
@@ -0,0 +1,96 @@
+package org.eclipse.jpt.gen.internal2;
+
+import org.eclipse.jpt.db.Column;
+import org.eclipse.jpt.db.ForeignKey;
+import org.eclipse.jpt.db.Table;
+
+
+/**
+ * Provide a pluggable way to determine whether and how the entity generator
+ * prints the names of various database objects.
+ */
+public interface DatabaseAnnotationNameBuilder {
+
+	/**
+	 * Given the name of an entity and the table to which it is mapped,
+	 * build and return a string to be used as the value for the entity's
+	 * Table annotation's 'name' element. Return null if the entity
+	 * maps to the table by default.
+	 */
+	String buildTableAnnotationName(String entityName, Table table);
+
+	/**
+	 * Given the name of an attribute (field or property) and the column
+	 * to which it is mapped,
+	 * build and return a string to be used as the value for the attribute's
+	 * Column annotation's 'name' element. Return null if the attribute
+	 * maps to the column by default.
+	 */
+	String buildColumnAnnotationName(String attributeName, Column column);
+
+	/**
+	 * Given the name of an attribute (field or property) and the
+	 * many-to-one or many-to-many foreign key to which it is mapped,
+	 * build and return a string to be used as the value for the attribute's
+	 * JoinColumn annotation's 'name' element. Return null if the attribute
+	 * maps to the join column by default.
+	 * The specified foreign key consists of a single column pair whose
+	 * referenced column is the single-column primary key of the foreign
+	 * key's referenced table.
+	 */
+	String buildJoinColumnAnnotationName(String attributeName, ForeignKey foreignKey);
+
+	/**
+	 * Build and return a string to be used as the value for a JoinColumn
+	 * annotation's 'name' or 'referencedColumnName' element.
+	 * This is called for many-to-one and many-to-many mappings when
+	 * the default join column name and/or referenced column name are/is
+	 * not applicable.
+	 * @see buildJoinColumnAnnotationName(String, ForeignKey)
+	 */
+	String buildJoinColumnAnnotationName(Column column);
+
+	/**
+	 * Build and return a string to be used as the value for a JoinTable
+	 * annotation's 'name' element.
+	 * This is called for many-to-many mappings when the default
+	 * join table name is not applicable.
+	 */
+	String buildJoinTableAnnotationName(Table table);
+
+
+	/**
+	 * The default implementation simple returns the database object's name,
+	 * unaltered.
+	 */
+	final class Default implements DatabaseAnnotationNameBuilder {
+		public static final DatabaseAnnotationNameBuilder INSTANCE = new Default();
+		public static DatabaseAnnotationNameBuilder instance() {
+			return INSTANCE;
+		}
+		// ensure single instance
+		private Default() {
+			super();
+		}
+		public String buildTableAnnotationName(String entityName, Table table) {
+			return table.getName();
+		}
+		public String buildColumnAnnotationName(String attributeName, Column column) {
+			return column.getName();
+		}
+		public String buildJoinColumnAnnotationName(String attributeName, ForeignKey foreignKey) {
+			return foreignKey.getColumnPair().getBaseColumn().getName();
+		}
+		public String buildJoinColumnAnnotationName(Column column) {
+			return column.getName();
+		}
+		public String buildJoinTableAnnotationName(Table table) {
+			return table.getName();
+		}
+		@Override
+		public String toString() {
+			return "DatabaseAnnotationNameBuilder.Default";  //$NON-NLS-1$
+		}
+	}
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ForeignKeyInfo.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ForeignKeyInfo.java
new file mode 100644
index 0000000..e904809
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ForeignKeyInfo.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2;
+
+import java.util.List;
+
+import org.eclipse.jpt.db.ForeignKey;
+
+/**
+ * Represents the metadata for a particular foreign key relationship 
+ * in a relational database schema.
+ * <p/>
+ * The referrer column is one which actually contains a foreign 
+ * key constraint, and is equivalent to the "foreign key" column.
+ * <p/>
+ * The referenced column is one which a referrer or foreign key 
+ * column references, and is equivalent to the "primary key" column.
+ * 
+ */
+public class ForeignKeyInfo
+{
+	private transient ForeignKey mForeignKey ;
+    private String mName;
+    private String mReferrerTableName;
+    private String mReferencedTableName;
+    private List<String> mReferrerColNames = new java.util.ArrayList<String>();
+    private List<String> mReferencedColNames = new java.util.ArrayList<String>();
+    
+    /**
+     * @param fk The name of the constraint backing 
+     * this foreign key metadata instance.
+     */
+    public ForeignKeyInfo(ForeignKey fk, String referrerTableName, String referencedTableName) {
+    	mForeignKey = fk;
+    	mName = fk.getName();
+    	mReferrerTableName = referrerTableName;
+    	mReferencedTableName = referencedTableName;
+	}
+    /**
+     * Obtain the constraint name for this foreign key specification.
+     * The name for a Foreign Key may, as per the JDBC specification,
+     * be <code>null</code> where the constraint is not named.
+     * In addition, it may be hardly recognizable to the user,
+     * particularly for DB/2 constraints.
+     * 
+     * @return The name of the constraint backing
+     *         this foreign key metadata instance.
+     */
+    public String getName()
+    {
+        return mName;
+    }
+    
+    public ForeignKey getForeignKey(){
+    	return mForeignKey;
+    }
+    /**
+     * Add another pair of foreign key mappings for this foreign key
+     * definition.
+     * 
+     * @param referrerColumn The referrer column name for this mapping.
+     * 
+     * @param referencedColumn The referenced column name for this mapping.
+     */
+    public void addColumnMapping(String referrerColName, String referencedColName) {
+    	mReferrerColNames.add(referrerColName);
+    	mReferencedColNames.add(referencedColName);
+    }
+    /**
+     * Returns the referrer table name of this foreign key
+     * relationship.
+     */
+    public String getReferrerTableName() {
+        return mReferrerTableName;
+    }
+    /**
+     * Returns the referrer column names for this
+     * foreign key.
+     * The size of this list is always the same as the size of 
+     * the list retured from <code>getReferencedColumnNames</code>
+     */
+    public List<String> getReferrerColumnNames() {
+        return mReferrerColNames;
+    }
+    /**
+     * Returns the referenced table name of this foreign key
+     * relationship.
+     */
+    public String getReferencedTableName() {
+    	 return mReferencedTableName;
+    }
+    /**
+     * Returns the referenced column names for this
+     * foreign key.
+     * The size of this list is always the same as the size of 
+     * the list retured from <code>getReferrerColumnNames</code>
+     */
+    public List<String> getReferencedColumnNames() {
+        return mReferencedColNames;
+    }
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+    	return "name=" + mName
+		+ ", referrerTable=" + mReferrerTableName
+		+ ", referencedTable=" + mReferencedTableName
+		+ ", referrerColumns=" + mReferrerColNames
+		+ ", referencedColumns=" + mReferencedColNames
+			;
+    }
+}
+
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenMessages.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenMessages.java
new file mode 100644
index 0000000..25fc02e
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenMessages.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.internal2;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Localized messages used by Dali entity generation.
+ */
+class JptGenMessages {
+
+	public static String PackageGenerator_taskName;
+	public static String GenScope_taskName;
+	public static String EntityGenerator_taskName;
+	public static String Templates_notFound;
+	public static String Error_Generating_Entities;
+
+	private static final String BUNDLE_NAME = "jpt_gen"; //$NON-NLS-1$
+	private static final Class<?> BUNDLE_CLASS = JptGenMessages.class;
+	static {
+		NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS);
+	}
+	
+	private JptGenMessages() {
+		throw new UnsupportedOperationException();
+	}
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenPlugin.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenPlugin.java
new file mode 100644
index 0000000..aec0b82
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenPlugin.java
@@ -0,0 +1,24 @@
+package org.eclipse.jpt.gen.internal2;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+
+public class JptGenPlugin {
+	public static final String PLUGIN_ID = "org.eclipse.jpt.gen";
+	public static void logException ( String msg, Throwable e ) {
+		Bundle bundle = Platform.getBundle(PLUGIN_ID);
+		ILog log = Platform.getLog(bundle);
+		log.log(new Status(IStatus.ERROR, PLUGIN_ID, msg, e ));		
+	}
+	
+	public static void logException( CoreException ce ) {
+		IStatus status = ce.getStatus();
+		Bundle bundle = Platform.getBundle(PLUGIN_ID);
+		ILog log = Platform.getLog(bundle);
+		log.log(new Status(IStatus.ERROR, PLUGIN_ID, status.getMessage(), ce));		
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenColumn.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenColumn.java
new file mode 100644
index 0000000..24d4211
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenColumn.java
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2;
+
+import org.eclipse.jpt.db.Column;
+import org.eclipse.jpt.db.Table;
+import org.eclipse.jpt.gen.internal2.util.DTPUtil;
+import org.eclipse.jpt.gen.internal2.util.StringUtil;
+
+
+/**
+ * Represents the ORM generation properties for a database 
+ * column.
+ * 
+ * <p>This is designed to be created/changed by the generation wizard,
+ * and generated using Velocity templates.
+ * The modified properties (if any) are persisted/retrieved using 
+ * <code>ORMGenCustomizer</code>.
+ * 
+ */
+public class ORMGenColumn
+{
+	private Table mTable;
+	private Column mDbColumn;
+	private ORMGenCustomizer mCustomizer;
+	private static String JAVA_LANG_PACKAGE = "java.lang.";
+	
+	public ORMGenColumn(Column dbColumn, ORMGenCustomizer customizer) {
+		super();
+		
+		mDbColumn = dbColumn;
+		mCustomizer = customizer;
+		mTable = dbColumn.getTable() ;
+	}
+	public ORMGenCustomizer getCustomizer() {
+		return mCustomizer;
+	}
+	
+	protected String customized(String propName) {
+		return getCustomizer().getProperty(propName, mTable.getName(), getName());
+	}
+	protected boolean customizedBoolean(String propName) {
+		return getCustomizer().getBooleanProperty(propName, mTable.getName(), getName());
+	}
+	protected void setCustomized(String propName, String value) {
+		if (value != null && value.length() == 0) {
+			value = null;
+		}
+		getCustomizer().setProperty(propName, value, mTable.getName(), getName());
+	}
+	protected void setCustomizedBoolean(String propName, boolean value, boolean defaultValue) {
+		if (defaultValue == value) {
+			setCustomized(propName, null); //remove the property
+		} else {
+			getCustomizer().setBooleanProperty(propName, value, mTable.getName(), getName());
+		}
+	}
+	
+	/**
+	 * Returns the column name.
+	 */
+	public String getName() {
+		String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder().
+			buildColumnAnnotationName(mDbColumn.getName(), mDbColumn);
+		return annotationName!=null ? annotationName : mDbColumn.getName();
+	}
+
+	public String getJoinColumnName(){
+		String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder().
+			buildJoinColumnAnnotationName(mDbColumn);
+		return annotationName!=null ? annotationName : mDbColumn.getName();
+	}
+	
+	public Column getDbColumn(){
+		return this.mDbColumn;
+	}
+	
+	/**
+	 * Returns the generated bean property name for the given column.
+	 * Does not return null.
+	 */
+	public String getPropertyName() {
+		String name = customized(PROPERTY_NAME);
+		if (name == null) {
+			name = StringUtil.columnNameToVarName(getName());
+		}
+		return name;
+	}
+	public void setPropertyName(String name) {
+		if (!StringUtil.equalObjects(name, getPropertyName())) {
+			setCustomized(PROPERTY_NAME, name);
+		}
+	}
+	
+	/**
+	 * Return true if the values of name element in the @Column is default
+	 * so we can skip generating the annotation
+	 * 
+	 * @return true
+	 */
+	public boolean isDefault(){
+		return isDefaultname() && isUpdateable() && isInsertable();
+	}
+	
+	/**
+	 * Return true if the values of name element in the @Column is default
+	 * so we can skip generating the annotation
+	 * 
+	 * @return true
+	 */
+	public boolean isDefaultname(){
+		String propName = getPropertyName();
+		String dbColumnName = getName();
+		return propName.equalsIgnoreCase( dbColumnName );
+	}
+
+	
+	/**
+	 * Returns the column type.
+	 * Does not return null.
+	 */
+	public String getPropertyType()  {
+		String type = customized(PROPERTY_TYPE);
+		if (type == null) {
+			type = getCustomizer().getPropertyTypeFromColumn( this.mDbColumn );
+		}
+		if( type.startsWith(JAVA_LANG_PACKAGE) ){
+			type = type.substring( JAVA_LANG_PACKAGE.length() );
+		}
+		return type;
+	}
+	public void setPropertyType(String type)  {
+		if (!StringUtil.equalObjects(type, getPropertyType())) {
+			setCustomized(PROPERTY_TYPE, type);
+		}
+	}
+	/**
+	 * Returns true if the column type is numeric.
+	 */
+	public boolean isNumeric() {
+		boolean ret = this.mDbColumn.isNumeric() ;
+		return ret;
+		
+	}
+	/**
+	 * Returns the mapping kind, one of {@link #PROPERTY_MAPPING_KIND}|{@link #ID_MAPPING_KIND}
+	 * |{@link #VERSION_MAPPING_KIND}|{@link #TIMESTAMP_MAPPING_KIND}.
+	 * 
+	 * This method does not return null (defaults to basic property type).
+	 */
+	public String getMappingKind() {
+		String kind = customized(MAPPING_KIND);
+		if (kind == null) {
+			kind = getCustomizer().getBasicMappingKind();
+			
+			if ( this.mDbColumn.isPartOfPrimaryKey() 
+				 && DTPUtil.getPrimaryKeyColumnNames( this.mDbColumn.getTable() ).size() == 1) {
+				kind = getCustomizer().getIdMappingKind();
+			}
+		}
+		return kind;
+	}
+	public void setMappingKind(String mappingKind)  {
+		if (!StringUtil.equalObjects(mappingKind, getMappingKind())) {
+			setCustomized(MAPPING_KIND, mappingKind);
+		}
+	}
+	public boolean isNullable() {
+		return this.mDbColumn.isNullable();
+	}
+
+	public int getSize() {
+		if( this.mDbColumn.isNumeric()){
+			return mDbColumn.getPrecision();
+		}
+		return mDbColumn.getLength();
+	}
+
+	public int getDecimalDigits() {
+		if( this.mDbColumn.isNumeric() ){
+			return mDbColumn.getScale();
+		}
+		return -1;
+	}
+	
+	public boolean isPrimaryKey(){
+		return this.mDbColumn.isPartOfPrimaryKey() ;
+	}
+	public boolean isForeignKey()  {
+		return this.mDbColumn.isPartOfForeignKey() ;
+	}
+	public boolean isUnique()  {
+		return this.mDbColumn.isPartOfUniqueConstraint() ;
+	}
+	public String getPropertyDescription() {
+		return customized(PROPERTY_DESC);
+	}
+	
+	public boolean isDataTypeLOB(){
+		return this.mDbColumn.isLOB();
+	}	
+
+	public boolean isNeedMapTemporalType(){
+		String propertyType = this.getPropertyType();
+		return ( propertyType.equals("java.util.Date") || propertyType.equals("java.util.Calendar") ); 
+	}	
+	
+	public String getTemporalType(){
+		String defaultType = getCustomizer().getPropertyTypeFromColumn( this.mDbColumn );
+		if( defaultType.equals("java.sql.Date")){
+			return "DATE";
+		}else if( defaultType.equals("java.sql.Time")){
+			return "TIME";
+		}else {
+			return "TIMESTAMP";
+		}
+	}	
+	
+	/**
+	 * Returns the generated property getter scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE}
+	 * |{@link #PRIVATE_SCOPE}.
+	 * This method never returns null (defaults to public).
+	 */
+	public String getPropertyGetScope() {
+		String scope = customized(PROPERTY_GET_SCOPE);
+		if (scope == null) {
+			scope = PUBLIC_SCOPE;
+		}
+		return scope;
+	}
+	public void setPropertyGetScope(String scope) {
+		if (!StringUtil.equalObjects(scope, getPropertyGetScope())) {
+			setCustomized(PROPERTY_GET_SCOPE, scope);
+		}
+	}
+	/**
+	 * Returns the generated property setter scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE}
+	 * |{@link #PRIVATE_SCOPE}.
+	 * This method never returns null (defaults to public).
+	 */
+	public String getPropertySetScope() {
+		String scope = customized(PROPERTY_SET_SCOPE);
+		if (scope == null) {
+			scope = PUBLIC_SCOPE;
+		}
+		return scope;
+	}
+	public void setPropertySetScope(String scope) {
+		if (!StringUtil.equalObjects(scope, getPropertySetScope())) {
+			setCustomized(PROPERTY_SET_SCOPE, scope);
+		}
+	}
+	/**
+	 * Returns the generated field member scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE}
+	 * |{@link #PRIVATE_SCOPE}.
+	 * This method never returns null (defaults to private).
+	 */
+	public String getFieldScope() {
+		String scope = customized(FIELD_SCOPE);
+		if (scope == null) {
+			scope = PRIVATE_SCOPE;
+		}
+		return scope;
+	}
+	/**
+	 * Returns true if this column should be used in the 
+	 * <code>equals</code> method implementation.
+	 */
+	public boolean isUseInEquals()  {
+		return customizedBoolean(USE_IN_EQUALS) || isPrimaryKey();
+	}
+	public void setUseInEquals(boolean value) {
+		setCustomizedBoolean(USE_IN_EQUALS, value, false);
+	}
+	/**
+	 * Returns true if this column should be used in the 
+	 * <code>toString</code> method implementation.
+	 */
+	public boolean isUseInToString()  {
+		return customizedBoolean(USE_IN_TO_STRING) || isPrimaryKey();
+	}
+	public void setUseInToString(boolean value) {
+		setCustomizedBoolean(USE_IN_TO_STRING, value, false);
+	}
+	public boolean isUpdateable() {
+		return !"false".equals(customized(UPDATEABLE)); //defaults to true
+	}
+	public void setUpdateable(boolean value) {
+		setCustomizedBoolean(UPDATEABLE, value, true);
+	}
+	public boolean isInsertable() {
+		return !"false".equals(customized(INSERTABLE)); //defaults to true
+	}
+	public void setInsertable(boolean value) {
+		setCustomizedBoolean(INSERTABLE, value, true);
+	}
+	public boolean isGenerated() {
+		return !"false".equals(customized(GENERATED)); //defaults to true
+	}
+	public void setGenerated(boolean value) {
+		setCustomizedBoolean(GENERATED, value, true);
+	}
+	
+	/*get/set and field scopes*/
+	public static final String PUBLIC_SCOPE = "public";
+	public static final String PROTECTED_SCOPE = "protected";
+	public static final String PRIVATE_SCOPE = "private";
+
+	/*customization properties*/
+	private static final String PROPERTY_NAME = "propertyName";
+	protected static final String PROPERTY_TYPE = "propertyType";
+	protected static final String MAPPING_KIND = "mappingKind";
+	private static final String PROPERTY_DESC = "propertyDesc";
+	private static final String PROPERTY_GET_SCOPE = "propertyGetScope";
+	private static final String PROPERTY_SET_SCOPE = "propertySetScope";
+	private static final String FIELD_SCOPE = "fieldScope";
+	private static final String USE_IN_EQUALS = "useInEquals";
+	private static final String USE_IN_TO_STRING = "useInToString";
+	private static final String UPDATEABLE = "updateable";
+	private static final String INSERTABLE = "insertable";
+	private static final String GENERATED = "genProperty";
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenCustomizer.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenCustomizer.java
new file mode 100644
index 0000000..32496eb
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenCustomizer.java
@@ -0,0 +1,752 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jpt.db.Column;
+import org.eclipse.jpt.db.Schema;
+import org.eclipse.jpt.db.Table;
+import org.eclipse.jpt.gen.internal2.util.DTPUtil;
+import org.eclipse.jpt.gen.internal2.util.FileUtil;
+import org.eclipse.jpt.gen.internal2.util.StringUtil;
+
+/**
+ * Contains the information used to customize the database schema to ORM entity 
+ * generation.
+ * 
+ * <p>The customization settings are mainly exposed in the form of 
+ * properties. There are no assumptions in this class about the meaning of the 
+ * property names. Properties can be associated to specific tables and table 
+ * columns, or globally for any table and/or column.
+ * 
+ * <p>Subclass can implement the sets of abstract methods to provide ORM vendor
+ * specific properties.
+ * 
+ */
+public abstract class ORMGenCustomizer implements java.io.Serializable
+{
+	private final static long serialVersionUID = 1;
+
+	/**
+	 * A value passed for the table name argument to get/setProperty 
+	 * indicating that the value applies to any table.
+	 */
+	public static final String ANY_TABLE = "__anyTable__";
+	/*the string used in the property name in mProps to indicate 
+	 * a null table value.*/
+	private static final String NULL_TABLE = "";
+	/*the string used in the property name in mProps to indicate 
+	 * a null column value.*/
+	private static final String NULL_COLUMN = "";
+	
+	/*This version number is written in the header of the customization stream
+	 * and read at de-serialization time, if it is different then the file is invalidated.
+	 */
+	private static final int FILE_VERSION = 2;
+	
+	private static final String UPDATE_CONFIG_FILE = "updateConfigFile";
+
+	private transient Schema mSchema;
+	private transient File mFile;
+	
+	private List<String> mTableNames;
+	/*key: table name, value: ORMGenTable object.*/
+	private transient Map<String , ORMGenTable> mTables;
+	/*the <code>Association</code> objects sorted by their "from" 
+	 * table name. Includes all association derived from foreign keys 
+	 * in user selected tables. Since some of the foreign keys may point to table
+	 * user does not select, this list may be different from  mValidAssociations
+	 **/
+	private List<Association> mAssociations;
+	/*
+	 * List of valid associations within the user selected tables  
+	 * */
+	private transient List<Association> mValidAssociations;
+	private transient boolean mInvalidForeignAssociations;
+	
+	/*the property name is in the form $tableName.$columnName.$propertyName.
+	 * Where tableName could be NULL_TABLE or ANY_TABLE
+	 * and columnName could be NULL_COLUMN*/
+	private Map<String, String> mProps = new java.util.HashMap<String, String>();
+
+	private transient DatabaseAnnotationNameBuilder databaseAnnotationNameBuilder = DatabaseAnnotationNameBuilder.Default.INSTANCE;
+	
+	//-----------------------------------------
+	//---- abstract methods
+	//-----------------------------------------
+	/**
+	 * Returns all the primary key generator schemes.
+	 * This can return any strings as far as the Velocity template 
+	 * processor understand them.
+	 */
+	public abstract List<String> getAllIdGenerators();
+	/**
+	 * Returns the string representing the developer-assigned id generator.
+	 * This can return any strings as far as the Velocity template 
+	 * processor understand them.
+	 */
+	public abstract String getNoIdGenerator();
+	/**
+	 * Returns the string representing the identity id generator.
+	 * This can return any strings as far as the Velocity template 
+	 * processor understand them.
+	 */
+	public abstract String getIdentityIdGenerator();
+	/**
+	 * Returns the strings representing the sequence generators.
+	 * This can return any strings as far as the Velocity template 
+	 * processor understand them.
+	 */
+	public abstract Set<String> getSequenceIdGenerators();
+	/**
+	 * Returns a property type from the given database column.
+	 * This can return any strings as far as the Velocity template 
+	 * processor understand them.
+	 */
+	public abstract String getPropertyTypeFromColumn(Column column) ;
+	/**
+	 * Returns all the strings representing property types.
+	 * This can return any strings as far as the Velocity template 
+	 * processor understand them.
+	 */
+	public abstract String[] getAllPropertyTypes();
+	/**
+	 * Returns all the strings representing property mapping kinds.
+	 * This can return any strings as far as the Velocity template 
+	 * processor understand them.
+	 */
+	public abstract String[] getAllMappingKinds();
+	/**
+	 * Returns the basic (default) property mapping kind.
+	 * This can return any strings as far as the Velocity template 
+	 * processor understand them.
+	 */
+	public abstract String getBasicMappingKind();
+	/**
+	 * Returns the id (primary key) property mapping kind.
+	 * This can return any strings as far as the Velocity template 
+	 * processor understand them.
+	 */
+	public abstract String getIdMappingKind();
+	/**
+	 * Interacts with the user to edit the cascade of the given 
+	 * role.
+	 * This method should also call <code>AssociationRole.setCascade</code>.
+	 * 
+	 * @return false if the user interaction is cancelled.
+	 */
+	public abstract boolean editCascade(AssociationRole role);
+	
+	//-----------------------------------------
+	//-----------------------------------------
+
+	/**
+	 * @param file The file that contains the customization settings.
+	 * The file is created if necessary when the <code>save</code> 
+	 * method is called.
+	 */
+	public void init( File file, Schema schema) {
+		this.mSchema = schema;
+		mFile = file;
+		
+		if (!file.exists()) {
+			/*A hack to set the default to eager so thet app does not throw at runtime for new apps
+			 * (in case a lazy strategy is not developed yet). This is done instead of in ORMGenTable.getDefaultFetch 
+			 * for backward compatibility.*/
+			setProperty(ORMGenTable.DEFAULT_FETCH, ORMGenTable.EAGER_FETCH, ORMGenCustomizer.ANY_TABLE, null);
+			return;
+		}
+		InputStream istream = null;
+		ObjectInputStream ois = null;
+		try 
+		{
+			//read it in a file first to speedup deserialization
+			byte[] bytes = FileUtil.readFile(file);
+			istream = new ByteArrayInputStream(bytes);
+			ois = new ObjectInputStream(istream);
+			
+			FileHeader header = (FileHeader)ois.readObject();
+			if (header.mVersion == FILE_VERSION) {
+				ORMGenCustomizer customizer = (ORMGenCustomizer)ois.readObject();
+				restore(customizer);
+			}
+		} catch (Exception ex) {
+			System.out.println("***ORMGenCustomizer.load failed "+file+": " + ex);				
+		}
+		finally 
+		{
+			if (ois != null)
+			{
+				try 
+				{
+					ois.close();
+				} catch (IOException e) {
+				}
+			}
+			
+			if (istream != null)
+			{
+				try 
+				{
+					istream.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+	}
+	
+	public void setSchema(Schema schema){
+		this.mSchema = schema;
+	}
+
+	public Schema getSchema(){
+		return mSchema;
+	}
+	
+	/**
+	 * Empty constructor needed by the deserialization.
+	 */
+	public ORMGenCustomizer() {
+		super();
+	}
+
+	/**
+	 * Saves the customization file.
+	 * The file is created if necessary.
+	 */
+	public void save() throws IOException {
+		//System.out.println("---ORMGenCustomizer.save: " + mFile);
+		if (!mFile.exists() && !mFile.createNewFile()) {
+			return;
+		}
+		java.io.FileOutputStream fos = null;
+		java.io.ObjectOutputStream oos = null;
+		boolean deleteIt = true;
+		try {
+			fos = new java.io.FileOutputStream(mFile);
+			oos = new java.io.ObjectOutputStream(fos);
+			FileHeader header = new FileHeader();
+			oos.writeObject(header);
+			oos.writeObject(this);
+			deleteIt = false;
+		} catch (Exception ex) {
+			//deleteIt is true, so the cache is not saved.
+			CoreException ce = new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID,
+					"Unable to save the ORMGenCustomizer file: "+mFile,ex));
+			JptGenPlugin.logException( ce );
+		} finally {
+			try {
+				if (oos!=null) oos.close();
+				if (fos!=null) fos.close();
+				if (deleteIt) {
+					mFile.delete();
+				}
+			} catch (java.io.IOException ex2) {}	
+		}
+	}
+	
+	public DatabaseAnnotationNameBuilder getDatabaseAnnotationNameBuilder() {
+		return this.databaseAnnotationNameBuilder;
+	}
+	public void setDatabaseAnnotationNameBuilder(DatabaseAnnotationNameBuilder databaseAnnotationNameBuilder) {
+		if (databaseAnnotationNameBuilder == null) {
+			throw new NullPointerException("database annotation name builder is required");  //$NON-NLS-1$
+		}
+		this.databaseAnnotationNameBuilder = databaseAnnotationNameBuilder;
+	}	
+
+	/**
+	 * Returns a property value.
+	 */
+	public String getProperty(String propertyName, String tableName, String colName) {
+		String key = getPropKey(propertyName, tableName, colName);
+		String value = (String)mProps.get(key);
+		/*if the key does not exist and it is a table property then 
+		 * get the default table property.*/
+		if (value == null && tableName != null && colName == null && !tableName.equals(ANY_TABLE)) {
+			value = getProperty(propertyName, ANY_TABLE, colName);
+		}
+		return value;
+	}
+	/**
+	 * Changes a property value.
+	 * 
+	 * @param value The new value, could be null.
+	 */
+	public void setProperty(String propertyName, String value, String tableName, String colName) {
+		String key = getPropKey(propertyName, tableName, colName);
+		if (value != null) {
+			mProps.put(key, value);
+		} else {
+			mProps.remove(key);
+		}
+	}
+	/**
+	 * Same as {@link #getProperty(String, String, String)} but 
+	 * converts the value to boolean.
+	 */
+	public boolean getBooleanProperty(String propertyName, String tableName, String colName) {
+		String value = getProperty(propertyName, tableName, colName);
+		return "true".equals(value);
+	}
+	/**
+	 * Changes a table boolean property value.
+	 */
+	public void setBooleanProperty(String propertyName, boolean value, String tableName, String colName) {
+		setProperty(propertyName, value ? "true" : "false", tableName, colName);
+	}
+	/**
+	 * Returns the names of the tables to generate.
+	 */
+	@SuppressWarnings("unchecked")
+	public List<String> getTableNames() {
+		return mTableNames != null ? mTableNames : java.util.Collections.EMPTY_LIST;
+	}
+	/**
+	 * Called when the table user selection is changed in the 
+	 * generation wizard.
+	 */
+	public void setTableNames(List<String> tableNames) {
+		mTableNames = tableNames;
+		mTables = null;
+		mValidAssociations = null; //recompute
+		mInvalidForeignAssociations = true; //make sure foreign associations from newly added tables are computed.
+	}
+	/**
+	 * Returns the table names to be generated.
+	 * This might be different from <code>getTableNames</code> if there 
+	 * are many-to-many join tables and are not contributing 
+	 * in any other associations.
+	 */
+	public List<String> getGenTableNames()  {
+		List<String> names = getTableNames();
+		List<String> result = new java.util.ArrayList<String>(names.size());
+		
+		/*filter out join tables*/
+		List<Association> associations = getAssociations();
+		for (Iterator<String> tableNamesIter = names.iterator(); tableNamesIter.hasNext(); ) {
+			String tableName = (String)tableNamesIter.next();
+			boolean isValid = true;
+			
+			for (Iterator<Association> assocIter = associations.iterator(); assocIter.hasNext(); ) {
+				Association association = (Association)assocIter.next();
+				if (!association.isGenerated()) {
+					continue;
+				}
+				if (tableName.equals(association.getReferrerTableName())
+						|| tableName.equals(association.getReferencedTableName())) {
+					isValid = true;
+					break;
+				}
+				if (tableName.equals(association.getJoinTableName())) {
+					isValid = false;
+				}
+			}
+			if (isValid) {
+				result.add(tableName);
+			}
+		}
+		return result;
+	}
+	/**
+	 * Returns an <code>ORMGenTable</code> object given its name, or 
+	 * null if none.
+	 */
+	public ORMGenTable getTable(String tableName)  {
+		if (mTables == null) {
+			mTables = new java.util.HashMap<String, ORMGenTable>(mTableNames.size());
+		}
+		
+		if(mTableNames!=null && mSchema!=null){
+			for (Iterator<String> iter = mTableNames.iterator(); iter.hasNext(); ) {
+				String name = (String)iter.next();
+				Table dbTable = mSchema.getTableNamed( name );
+				if (dbTable != null) {
+					mTables.put(name, createGenTable(dbTable));
+				}
+			}
+		}
+		return (ORMGenTable)mTables.get(tableName);
+	}
+	/**
+	 * Returns the <code>Association</code> objects sorted by their "from" 
+	 * table name.
+	 */
+	public List<Association> getAssociations(){
+		return getAssociations(true/*validOnly*/);
+	}
+	/**
+	 * Adds the given association.
+	 */
+	public void addAssociation(Association association)  {
+		getAssociations(false/*validOnly*/).add(association);
+		if (mValidAssociations != null) {
+			mValidAssociations.add(association);
+		}
+		
+	}
+	/**
+	 * Deletes the given association.
+	 */
+	public void deleteAssociation(Association association)  {
+		boolean removed = getAssociations(false/*validOnly*/).remove(association);
+		assert(removed);
+		
+		if (mValidAssociations != null) {
+			removed = mValidAssociations.remove(association);
+			assert(removed);
+		}
+	}
+	/**
+	 * Returns true if an association similar to the given association 
+	 * already exists.
+	 * This is decided based only on the association tables and columns.
+	 */
+	public boolean similarAssociationExists(Association association) {
+		try {
+			for (Iterator<Association> iter = getAssociations(false/*validOnly*/).iterator(); iter.hasNext(); ) {
+				Association association2 = (Association)iter.next();
+				if (!association.getReferrerTableName().equals(association2.getReferrerTableName())
+						|| !association.getReferencedTableName().equals(association2.getReferencedTableName())
+						|| !StringUtil.equalObjects(association.getJoinTableName(), association2.getJoinTableName())
+						|| !association.getReferrerColumnNames().equals(association2.getReferrerColumnNames())
+						|| !association.getReferencedColumnNames().equals(association2.getReferencedColumnNames())
+						) {
+					continue;
+				}					
+				/*the 2 association have the same referrer, referenced and join table*/
+				if (association.getJoinTableName() == null) {
+					return true;
+				}
+				if (association.getReferrerJoinColumnNames().equals(association2.getReferrerJoinColumnNames())
+						&& association.getReferencedJoinColumnNames().equals(association2.getReferencedJoinColumnNames())) {
+					return true;
+				}
+			}
+		} catch (Exception e) {
+			return false;
+		}
+		return false;
+	}
+	/**
+	 * Creates the <code>ORMGenTable</code> instance. 
+	 */
+	public ORMGenTable createGenTable(Table dbTable) {
+		return new ORMGenTable(dbTable, this);
+	}
+	/**
+	 * Creates the <code>ORMGenColumn</code> instance.
+	 */
+	protected ORMGenColumn createGenColumn(Column dbCol) {
+		return new ORMGenColumn(dbCol, this);
+	}
+	/**
+	 * Returns true of the underlying persistence specs require the "many" side 
+	 * of an association to be the owner (like EJB3).
+	 */
+	protected boolean manySideIsAssociationOwner() {
+		return false;
+	}
+	public boolean isUpdateConfigFile() {
+		return !"false".equals(getProperty(UPDATE_CONFIG_FILE, null, null)); //defaults to true
+	}
+	public void setUpdateConfigFile(boolean value) {
+		if (value) { //default is true
+			setProperty(UPDATE_CONFIG_FILE, null, null, null); //remove it
+		} else {
+			setBooleanProperty(UPDATE_CONFIG_FILE, value, null, null);
+		}
+	}
+
+	//-----------------------------------------
+	//---- Velocity templates methods
+	//-----------------------------------------
+	/**
+	 * Returns a getter method name given a property name.
+	 */
+	public String propertyGetter(String propertyName) {
+		return "get"+StringUtil.initUpper(propertyName);
+	}
+	/**
+	 * Returns a setter method name given a property name.
+	 */
+	public String propertySetter(String propertyName) {
+		return "set"+StringUtil.initUpper(propertyName);
+	}
+	public String quote(String s) {
+		return StringUtil.quote(s, '"');
+	}
+	public String quote(boolean b) {
+		return quote(String.valueOf(b));
+	}
+	public String quote(int i) {
+		return quote(String.valueOf(i));
+	}
+	/**
+	 * Appends an annotation member name and value to an existing annotation.
+	 * 
+	 * @param s The annotation members string.
+	 *
+	 * @param memberValue The member value, if null or empty strings then 
+	 * nothing is appened.
+	 * 
+	 * @param whether to double quote the member value.
+	 */
+	public String appendAnnotation(String s, String memberName, String memberValue, boolean quote) {
+		if (memberValue == null || memberValue.length() == 0) {
+			return s;
+		}
+		StringBuffer buffer = new StringBuffer(s);
+		if (buffer.length() != 0) {
+			buffer.append(", ");
+		}
+		buffer.append(memberName);
+		buffer.append('=');
+		if (quote) {
+			buffer.append('"');
+		}
+		buffer.append(memberValue);
+		if (quote) {
+			buffer.append('"');
+		}
+		return buffer.toString();
+	}
+	public boolean isJDK1_5() {
+		return true;
+	}
+	
+	//-----------------------------------------
+	//---- private methods
+	//-----------------------------------------
+	/**
+	 * Restores the customization settings from the given 
+	 * (persisted) customizer.
+	 */
+	private void restore(ORMGenCustomizer customizer)  {
+		mTableNames = customizer.mTableNames;
+		mAssociations = customizer.mAssociations;
+		mProps = customizer.mProps;
+		if( mSchema == null )
+			return;
+		
+		/*remove invalid table names*/
+		for (int i = mTableNames.size()-1; i >= 0; --i) {
+			String tableName = (String)mTableNames.get(i);
+			if (mSchema.getTableNamed( tableName) == null) {
+				mTableNames.remove(i);
+			}
+		}
+		if( mAssociations!=null ){
+			/*restore the associations*/
+			for (Iterator<Association> iter = mAssociations.iterator(); iter.hasNext(); ) {
+				Association association = (Association)iter.next();
+				association.restore(this);
+			}
+			/*add the foreign keys associations just in case the tables changed since 
+			 * the last time the state was persisted. Pass checkExisting true so that the 
+			 * associations restored above are not overwritten.*/
+			addForeignKeyAssociations(true/*checkExisting*/);
+		}
+	}
+	/**
+	 * Returns the key in mProps corresponding to the specified 
+	 * propertyName, table and column.
+	 */
+	private String getPropKey(String propertyName, String tableName, String colName) {
+		if (tableName == null) {
+			tableName = NULL_TABLE;
+		}
+		if (colName == null) {
+			colName = NULL_COLUMN;
+		}
+		return tableName + '.' + colName + '.' + propertyName;
+	}
+	/**
+	 * Returns the associations that are valid for the 
+	 * current tables.
+	 */
+	private List<Association> getAssociations(boolean validOnly){
+		if (mAssociations == null) {
+			mAssociations = new java.util.ArrayList<Association>();
+			
+			addForeignKeyAssociations(false/*checkExisting*/);
+		} else if (mInvalidForeignAssociations) {
+			mInvalidForeignAssociations = false;
+			
+			addForeignKeyAssociations(true/*checkExisting*/);
+		}
+		List<Association> associations;
+		if (validOnly) {
+			if (mValidAssociations == null) {
+				/*filter out the invalid associations*/
+				mValidAssociations = new ArrayList<Association>(mAssociations.size());
+				for (int i = 0, n = mAssociations.size(); i < n; ++i) {
+					Association association = (Association)mAssociations.get(i);
+					if (association.isValid()) {
+						mValidAssociations.add(association);
+					}
+				}
+			}
+			associations = mValidAssociations;
+		} else {
+			associations = mAssociations;
+		}
+		return associations;
+	}
+	private void addForeignKeyAssociations(boolean checkExisting) {
+		List<String> tableNames = getTableNames();
+		for (Iterator<String> iter = tableNames.iterator(); iter.hasNext(); ) {
+			ORMGenTable table = getTable((String)iter.next());
+			addForeignKeyAssociations(table, checkExisting);
+		}
+	}
+	private void addForeignKeyAssociations(ORMGenTable table, boolean checkExisting) {
+		if(table==null)
+			return;
+		
+		
+		List<ForeignKeyInfo> fKeys = null;
+		
+		try{
+			fKeys = DTPUtil.getForeignKeys(table.getDbTable());
+		}catch(Exception ise){
+			//workaround Dali bug for now
+			return;
+		}
+		
+		if( fKeys.size()==0 )
+			return;
+		
+		List<Association> addedAssociations = new java.util.ArrayList<Association>();
+		for (Iterator<ForeignKeyInfo> iter = fKeys.iterator(); iter.hasNext(); ) {
+			ForeignKeyInfo fki = (ForeignKeyInfo)iter.next();
+			ORMGenTable referencedTable = getTable(fki.getReferencedTableName());
+			if (referencedTable == null) {
+				continue;
+			}
+			Association association = new Association(this, table.getName(), fki.getReferrerColumnNames()
+						, referencedTable.getName(), fki.getReferencedColumnNames());
+			association.computeCardinality();
+			//Defer the check of similarAssociationExists after computeManyToMany()
+			//otherwise the MTM association will not computed correctly in some cases.
+			//if (checkExisting && similarAssociationExists(association)) {
+			//	continue;
+			//}
+			addedAssociations.add(association);
+		}
+		
+		Association m2m = computeManyToMany(table, addedAssociations);
+		if (m2m != null) {
+			/*do not generate the 2 many-to-one*/
+			for (int i = 0; i < addedAssociations.size(); ++i) {
+				Association association = (Association)addedAssociations.get(i);
+				association.setGenerated(false);
+			}
+			addedAssociations.add(0, m2m);
+		}
+		//remove the association if already existing
+		Iterator<Association> it =  addedAssociations.iterator(); 
+		while( it.hasNext() ){
+			Association newAssociation = it.next();
+			for( Association association : mAssociations ){
+				if( newAssociation.equals( association )){
+					//If the association is existing, don't add.
+					//only copy the generated flag
+					association.setGenerated( newAssociation.isGenerated() );
+					it.remove();
+				}
+			}
+		}
+		mAssociations.addAll(addedAssociations);
+	}
+	private Association computeManyToMany(ORMGenTable table, List<Association> addedAssociations) {
+		/*many-to-many associations if:
+		 * -addedAssociations contains 2 many-to-one associations to 2 different tables t1 and t2.
+		 * -<code>table</code> contains only the primary key columns.
+		 * -the primary key of <code>table</code> is the concatenation of its foreign 
+		 * 	keys to t1 and t2.*/
+		
+		if (addedAssociations.size() != 2) {
+			return null;
+		}
+		
+		//Assume MTM table should have only two columns that are foreign keys
+		if( table.getColumns().size() != 2 ){
+			return null;
+		}
+		
+		Association assoc1 = (Association)addedAssociations.get(0);
+		Association assoc2 = (Association)addedAssociations.get(1);
+		if (assoc1.getCardinality() != Association.MANY_TO_ONE
+				|| assoc2.getCardinality() != Association.MANY_TO_ONE) {
+			return null;
+		}
+		ORMGenTable t1 = assoc1.getReferencedTable();
+		ORMGenTable t2 = assoc2.getReferencedTable();
+
+//Commented out because the assumption is too restrictive: 
+//this check will prevent generating table MTM to itself		
+//		if (t1.getName().equals(t2.getName()) || 
+//				t1.getName().equals(table.getName()) || t2.getName().equals(table.getName())) {
+		if( t1.getName().equals(table.getName()) || t2.getName().equals(table.getName()) ) {
+			return null;
+		}
+		
+//Commented out because the assumption is too restrictive: 
+//this check will prevent generating MTM mapping table not having 
+//primary key defined 		
+//		List pkNames = DTPUtil.getPrimaryKeyColumnNames(table.getDbTable());
+//		if (pkNames.size() != table.getColumnNames().size()) {
+//			return null;
+//		}
+//		List fkNames = new java.util.ArrayList(assoc1.getReferrerColumnNames()); //clone because we modify by addAll below
+//		fkNames.addAll(assoc2.getReferrerColumnNames());
+//		if (!CollectionUtil.equalsIgnoreOrder(pkNames, fkNames)) {
+//			return null;
+//		}
+		Association m2m = new Association(this, t1.getName()/*referrerTableName*/, assoc1.getReferencedColumnNames()/*referrerColNames*/
+				, t2.getName()/*referencedTableName*/, assoc2.getReferencedColumnNames()/*referencedColNames*/
+				, table.getName(), assoc1.getReferrerColumnNames()/*referrerJoinColNames*/, assoc2.getReferrerColumnNames()/*referencedJoinColNames*/);
+		m2m.setCustom(false);
+		return m2m;
+	}
+
+	//---------------------------------------------------
+	//---- FileHeader class -----------------------------
+	//---------------------------------------------------
+	/**
+	 * The header of the customization file.
+	 */
+	private static class FileHeader implements java.io.Serializable
+	{
+		private static final long serialVersionUID = 1L;
+		/**
+		 * Should be argument-less because it is used in 
+		 * the de-serialization process.
+		 */
+		public FileHeader() {
+			mVersion = FILE_VERSION;
+		}
+		int mVersion;
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenTable.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenTable.java
new file mode 100644
index 0000000..11ab29a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenTable.java
@@ -0,0 +1,828 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jpt.db.Column;
+import org.eclipse.jpt.db.Table;
+import org.eclipse.jpt.gen.internal2.util.DTPUtil;
+import org.eclipse.jpt.gen.internal2.util.StringUtil;
+import org.eclipse.jpt.utility.JavaType;
+
+/**
+ * Represents the ORM generation properties for a database 
+ * table.
+ * 
+ * <p>This is designed to be created/changed by the generation wizard,
+ * and generated using Velocity templates.
+ * The modified properties (if any) are persisted/retrieved using 
+ * <code>ORMGenCustomizer</code>.
+ * 
+ */
+public class ORMGenTable
+{
+	private ORMGenCustomizer mCustomizer;
+	private List<ORMGenColumn> mColumns;
+	private Table mDbTable;
+	
+	/**
+	 * @param table The database table or null if this table is used 
+	 * to get/set the default table properties (properties that apply to all tables unless overriden).
+	 */
+	public ORMGenTable(Table table, ORMGenCustomizer customizer) {
+		super();
+		
+		mDbTable = table;
+		mCustomizer = customizer;
+	}
+	public ORMGenCustomizer getCustomizer() {
+		return mCustomizer;
+	}
+	/**
+	 * Returns true if this table is is used to get/set the default 
+	 * table properties.
+	 */
+	public boolean isDefaultsTable() {
+		return mDbTable == null;
+	}
+	
+	protected String customized(String propName) {
+		return getCustomizer().getProperty(propName, getName(), null);
+	}
+	protected boolean customizedBoolean(String propName) {
+		return getCustomizer().getBooleanProperty(propName, getName(), null);
+	}
+	protected void setCustomized(String propName, String value) {
+		if (value != null && value.length() == 0) {
+			value = null;
+		}
+		getCustomizer().setProperty(propName, value, getName(), null);
+	}
+	protected void setCustomizedBoolean(String propName, boolean value, boolean defaultValue) {
+		if (defaultValue == value) {
+			setCustomized(propName, null); //remove the property
+		} else {
+			getCustomizer().setBooleanProperty(propName, value, getName(), null);
+		}
+	}
+	public Table getDbTable() {
+		return mDbTable;
+	}
+	/**
+	 * Returns the table name.
+	 */
+	public String getName() {
+		if( mDbTable == null )
+			return ORMGenCustomizer.ANY_TABLE;
+		String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder().
+			buildTableAnnotationName(mDbTable.getName(), mDbTable);
+		return annotationName != null ? annotationName : mDbTable.getName();
+	}
+	
+	public String getJoinTableAnnotationName(){
+		if( mDbTable == null )
+			return ORMGenCustomizer.ANY_TABLE;
+		String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder().
+			buildJoinTableAnnotationName( mDbTable);
+		return annotationName != null ? annotationName : mDbTable.getName();
+	}
+	
+	/**
+	 * Returns the database schema containing the table.
+	 */
+	public String getSchema() {
+		if( DTPUtil.isDefaultSchema( mDbTable ))
+			return "";
+		String schemaName = mDbTable.getSchema().getName();
+		
+		return schemaName;
+	}
+	/**
+	 * Sets the package for the generated class (empty string for the default package)
+	 */
+	public void setPackage(String srcFolder, String pkg) {
+		setCustomized(SRC_FOLDER, srcFolder);
+		
+		getCustomizer().setProperty(PACKAGE, pkg, getName(), null); //not calling setCustomized so that empty strings do not get nulled out.
+	}
+	/**
+	 * Returns the Java package (empty string for the default package).
+	 */
+	public String getPackage() {
+		return customized(PACKAGE);
+	}
+
+	/**
+	 * Returns the generated Java class name (not qualified).
+	 */
+	public String getClassName() {
+		String name = customized(CLASS_NAME);
+		if (name == null) {
+			name = StringUtil.tableNameToVarName(getName());
+			name = StringUtil.initUpper(name);
+			name = StringUtil.singularise(name);
+		}
+		return name;
+	}
+	public void setClassName(String className) {
+		/*if the class name is the same as the (possibly computed) class name 
+		 * then nothing to do*/
+		if (!StringUtil.equalObjects(className, getClassName())) {
+			setCustomized(CLASS_NAME, className);
+		}
+	}
+	/**
+	 * Returns a name suitable to be used as a variable or class name.
+	 * This is computed based on the table name.
+	 * 
+	 * @param singular Whether the name should be singular or plural.
+	 */
+	public String getVarName(boolean singular) {
+		String name = StringUtil.tableNameToVarName(getName());
+		if (singular) {
+			name = StringUtil.singularise(name);
+		} else {
+			name = StringUtil.pluralise(name);
+		}
+		return name;
+	}
+	/**
+	 * Returns the fully qualified generated Java class name.
+	 */
+	public String getQualifiedClassName() {
+		return qualify(getClassName());
+	}
+	/**
+	 * Returns the composite key Java class name (not qualified).
+	 */
+	public String getCompositeKeyClassName() {
+		String name = customized(COMPOSITE_KEY_CLASS_NAME);
+		if (name == null) {
+			name = getClassName() + "PK";
+		}
+		return name;
+	}
+	/**
+	 * Returns the fully qualified composite key Java class name.
+	 */
+	public String getQualifiedCompositeKeyClassName() {
+		return qualify(getCompositeKeyClassName());
+	}
+	/**
+	 * Returns the composite key property name.
+	 */
+	public String getCompositeKeyPropertyName() {
+		return "compId";
+	}
+	/**
+	 * Returns the <code>ORMGenColumn</code> objects to be 
+	 * generated for this table.
+	 */
+	public List<ORMGenColumn> getColumns() {
+		if (mColumns == null) {
+			mColumns = new ArrayList<ORMGenColumn>(); 
+			Iterator<Column> cols = mDbTable.columns();
+			while (cols.hasNext() ) {
+				Column c = cols.next();
+				ORMGenColumn genColumn = getCustomizer().createGenColumn( c );
+				mColumns.add( genColumn );
+			}
+		}
+		return mColumns;
+	}
+	public List<String> getColumnNames() {
+		Iterator<Column> cols = mDbTable.columns();
+		List<String> ret = new ArrayList<String>();
+		while (cols.hasNext() ) {
+			Column c = cols.next(); 
+			ret.add(c.getName());
+		}
+		return ret;
+	}
+	/**
+	 * Returns the <code>ORMGenColumn</code> objects representing 
+	 * the table's primary key.
+	 */
+	public List<ORMGenColumn> getPrimaryKeyColumns()  {
+		List<Column> dbCols = DTPUtil.getPrimaryKeyColumns( mDbTable);
+		List<ORMGenColumn> ret = new ArrayList<ORMGenColumn>();
+		for(Column dbCol : dbCols ){
+			ret.add(new ORMGenColumn(dbCol, this.mCustomizer));
+		}
+		return ret;
+	}
+	/**
+	 * Returns the primary key column or null if there is 
+	 * no or many primary key columns.
+	 */
+	public ORMGenColumn getPrimaryKeyColumn() {
+		ORMGenColumn pkCol = null;
+		List<ORMGenColumn> pkColumns = getPrimaryKeyColumns();
+		if (pkColumns.size() == 1) {
+			//Column dbCol = (Column)pkColumns.get(0);
+			pkCol = pkColumns.get(0); //(ORMGenColumn) mCustomizer.createGenColumn(dbCol);
+		} else {
+			/*if no pk column then look for the first column with id 
+			 * mapping kind. This is so that the wizard can be used with tables 
+			 * not having primary keys. */
+			List<ORMGenColumn> columns = getColumns();
+			for (int i = 0, n = columns.size(); i < n; ++i) {
+				ORMGenColumn column = (ORMGenColumn)columns.get(i);
+				if (column.getMappingKind().equals(mCustomizer.getIdMappingKind())) {
+					pkCol = column;
+					break;
+				}
+			}	
+		}
+		return pkCol;
+	}
+	/**
+	 * Returns true if there is more than 1 pk column.
+	 */
+	public boolean isCompositeKey() {
+		return DTPUtil.getPrimaryKeyColumnNames( mDbTable ).size() > 1;
+	}
+	/**
+	 * Returns the <code>ORMGenColumn</code> objects for the 
+	 * the columns that are not part of any association.
+	 * 
+	 * @param genOnly Whether to include only the columns marked for generation.
+	 * 
+	 * @param includePk Whether to include the primary kley column(s).
+	 * 
+	 * @param includeInherited Whether to include the columns associated 
+	 * with Java properties that exist in the super class (if any).
+	 */
+	public List<ORMGenColumn> getSimpleColumns(boolean genOnly, boolean includePk, boolean includeInherited){
+		List<ORMGenColumn> result = new java.util.ArrayList<ORMGenColumn>();
+		
+		List<ORMGenColumn> columns = getColumns();
+		List<AssociationRole> roles = getAssociationRoles();
+		for (int i = 0, n = columns.size(); i < n; ++i) {
+			ORMGenColumn column = (ORMGenColumn)columns.get(i);
+			if (genOnly && !column.isGenerated()) {
+				continue;
+			}
+			if (column.isPrimaryKey()) {
+				if (!includePk || isCompositeKey()) {
+					continue;
+				}
+			} else if (isColumnInAsscociation(column, roles)) {
+				continue;
+			}
+			
+			result.add(column);
+		}
+		return result;
+		
+	}
+	public List<ORMGenColumn> getSimpleColumns() {
+		return getSimpleColumns(true/*genOnly*/, true/*includePk*/, true/*includeInherited*/);
+	}
+	/**
+	 * Returns false if the given column should be generated with 
+	 * false updatable/insertable.
+	 * This is the case when the column is mapped more than once, this 
+	 * usually happen with columns in composite keys and many-to-one 
+	 * associations.
+	 * 
+	 * <br>Note that for Hibernate the column param is null because 
+	 * the insert/update attributes are specified for the many-to-one tag itself 
+	 * instead of the nested column tags (bogus obviously).
+	 */
+	public boolean isColumnUpdateInsert(AssociationRole role, ORMGenColumn column)  {
+		if (column == null) {
+			for (Iterator<ORMGenColumn> iter = role.getReferrerColumns().iterator(); iter.hasNext(); ) {
+				ORMGenColumn c = (ORMGenColumn)iter.next();
+				if (!isColumnUpdateInsert(role, c)) {
+					return false;
+				}
+			}
+			return true;
+		}
+		
+		if (column.isPrimaryKey()) {
+			return false;
+		}
+		/*should look if there are multiple associations using the same column 
+		 * and return false, but this is probably an unusual case.*/
+		
+		return true;
+	}
+	/**
+	 * Returns the <code>ORMGenColumn</code> objects corresponding 
+	 * to the given column names.
+	 */
+	public List<ORMGenColumn> getColumnsByNames(List<String> names){
+		List<ORMGenColumn> result = new java.util.ArrayList<ORMGenColumn>();
+		for( String name :  names  ){
+			ORMGenColumn column = getColumnByName(name);
+			assert(column != null);
+			if (column != null) {
+				result.add(column);
+			}
+		}
+		return result;
+	}
+	/**
+	 * Returns the columns having the given name, or null if none.
+	 */
+	public ORMGenColumn getColumnByName(String name) {
+		List<ORMGenColumn> columns = getColumns();
+		for (int i = 0, n = columns.size(); i < n; ++i) {
+			ORMGenColumn column = (ORMGenColumn)columns.get(i);
+			if (column.getName().equals(name)) {
+				return column;
+			}
+		}
+		return null;
+	}
+	/**
+	 * Returns the <code>AssociationRole</code> objects for this table.
+	 * Only the association marked for generation are returned.
+	 */
+	public List<AssociationRole> getAssociationRoles(){
+		/*this is not cached intentionally because invalidating the 
+		 * cache with wizard changes is kinda tricky.*/
+		List<AssociationRole> associationRoles = new ArrayList<AssociationRole>();
+		
+		String name = getName();
+		List<Association> associations = mCustomizer.getAssociations();
+		for (Iterator<Association> iter = associations.iterator(); iter.hasNext(); ) {
+			Association association = (Association)iter.next();
+			if (!association.isGenerated()) {
+				continue;
+			}
+			/*check both referrer *and* referenced because an association could be 
+			 * from-to the same table (employee/manager)*/
+			if (association.getReferrerTable().getName().equals(name)) {
+				AssociationRole role = association.getReferrerRole();
+				if (role != null) {
+					associationRoles.add(role);
+				}
+			}
+			if (association.getReferencedTable().getName().equals(name)) {
+				AssociationRole role = association.getReferencedRole();
+				if (role != null) {
+					associationRoles.add(role);
+				}
+			}
+		}
+		return associationRoles;
+	}
+	public String getClassDescription() {
+		return customized(CLASS_DESC);
+	}
+	/**
+	 * Returns the generated class scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE}
+	 * |{@link #PRIVATE_SCOPE}.
+	 * This method never returns null (defaults to public).
+	 */
+	public String getClassScope() {
+		String scope = customized(CLASS_SCOPE);
+		if (scope == null) {
+			scope = PUBLIC_SCOPE;
+		}
+		return scope;
+	}
+	public String getExtends() {
+		return customized(EXTENDS);
+	}
+	public void setExtends(String baseClass) {
+		setCustomized(EXTENDS, baseClass);
+	}
+	public List<String> getImplements() {
+		String str = customized(IMPLEMENTS);
+		List<String> result = StringUtil.strToList(str, ',', true/*trim*/);
+		if (result == null) {
+			result = Collections.emptyList();
+		}
+		return result;
+	}
+	public void setImplements(List<String> interfaces) {
+		setCustomized(IMPLEMENTS, StringUtil.listToStr(interfaces, ','));
+	}
+	/**
+	 * Returns the string that should be generated in the Java class 
+	 * for extends and implements.
+	 */
+	public String generateExtendsImplements() {
+		StringBuffer buffer = new StringBuffer();
+		
+		String extendsClass = getExtends();
+		if (extendsClass != null && !extendsClass.equals("java.lang.Object") && !extendsClass.equals("Object")) {
+			buffer.append("extends " + simplifyClassName(extendsClass));
+		}
+		
+		buffer.append(" implements Serializable"); //assuming that the Java file template imports the java.io.Serializable
+		
+		for (Iterator<String> iter = getImplements().iterator(); iter.hasNext(); ) {
+			buffer.append(", " + simplifyClassName((String)iter.next())); 
+		}
+		
+		return buffer.toString();
+	}
+	private String simplifyClassName(String fullClassName) {
+		final String JAVA_LANG = "java.lang.";
+		if (fullClassName.startsWith(JAVA_LANG)) {
+			return fullClassName.substring(JAVA_LANG.length());
+		}
+		String pkg = StringUtil.getPackageName(fullClassName);
+		if (pkg != null && StringUtil.equalObjects(pkg, getPackage())) {
+			 return StringUtil.getClassName(fullClassName);
+		}
+		return fullClassName;
+	}
+	/**
+	 * Returns the id generator scheme (assigned, sequence, etc).
+	 * Does not return null, defaults to "assigned" or "identity" depending on whether 
+	 * the table has an identity column.
+	 */
+	public String getIdGenerator()  {
+		String generator = customized(ID_GENERATOR);
+		String noneGenerator = getCustomizer().getNoIdGenerator();
+		if (!isDefaultsTable()) {
+			/*This is done mainly because there might be cases where some tables have autoinctement pk 
+			 * and others are assigned. In this case this makes it so that it is possible to have 
+			 * a "none" default value that is interpreted depending on the case. */
+			if (generator == null || generator.equals(noneGenerator)) {
+				ORMGenColumn pkColumn = getPrimaryKeyColumn();
+				if (pkColumn != null && DTPUtil.isAutoIncrement( pkColumn.getDbColumn() )) {
+					generator = getCustomizer().getIdentityIdGenerator();
+				}
+			}
+		}
+		if (generator == null) {
+			generator = noneGenerator;
+		}
+		return generator;
+	}
+	/**
+	 * Changes the id generator scheme (assigned, sequence, etc).
+	 */
+	public void setIdGenerator(String scheme) {
+		setCustomized(ID_GENERATOR, scheme);
+	}
+	/**
+	 * Returns the sequence name for the given table, or null if none (makes
+	 * sense only when the scheme is native, sequence, ..).
+	 */
+	public String getSequence() {
+		return customized(SEQUENCE);
+	}
+	public void setSeqence(String name) {
+		setCustomized(SEQUENCE, name);
+	}
+	/**
+	 * Returns the sequence name after replacing the ${table} and ${pk} 
+	 * by their values, or null if none.
+	 */
+	public String getFormattedSequence()  {
+		String sequence = getSequence();
+		if (sequence != null) {
+			/*resolve the ${table} and ${pk} patterns*/
+			sequence = StringUtil.strReplace(sequence, TABLE_SEQ_PATTERN, getName());
+			
+			if (sequence.indexOf(PK_SEQ_PATTERN) >= 0) {
+				 List<String> pkNames = DTPUtil.getPrimaryKeyColumnNames( getDbTable() );
+				 String pkName = null;
+				 if (pkNames.size()>0 ) {
+				 	pkName = (String)pkNames.get(0);
+				 }
+				 sequence = StringUtil.strReplace(sequence, PK_SEQ_PATTERN, pkName);
+			}
+		}
+		return sequence!=null?sequence.toUpperCase():"";
+	}
+	public boolean isImplementEquals() {
+		return !"true".equals(customized(IMPLEMENT_EQUALS)); //defaults to false
+	}
+	public void setImplementEquals(boolean value) {
+		setCustomizedBoolean(IMPLEMENT_EQUALS, value, true);
+	}
+	
+	/**
+	 * Returns true if there is any column participating in equals/hashcode.
+	 */
+	public boolean hasColumnsInEquals()  {
+		List<ORMGenColumn> columns = getSimpleColumns();
+		for (int i = 0, n = columns.size(); i < n; ++i) {
+			ORMGenColumn column = (ORMGenColumn)columns.get(i);
+			if (column.isUseInEquals()) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * Returns {@link #GENERATE_DDL_ANNOTATION}  indicating whether
+	 * the optional DDL parameters like length, nullable, unqiue, etc should be generated 
+	 * in @Column annotation.
+	 * defaults to false.
+	 */
+	public boolean isGenerateDDLAnnotations() {
+		return "true".equals(customized(GENERATE_DDL_ANNOTATION)); //defaults to false
+	}
+	
+	public void setGenerateDDLAnnotations(boolean generate) {
+		setCustomizedBoolean(GENERATE_DDL_ANNOTATION, generate, false);		
+	}
+
+	/**
+	 * Returns one of {@link #PROPERTY_ACCESS}|{@link #FIELD_ACCESS} indicating how 
+	 * the entity properties are mapped.
+	 * Does not return null (defaults to {@link #FIELD_ACCESS}).
+	 */
+	public String getAccess() {
+		String name = customized(ACCESS);
+		if (name == null) {
+			name = FIELD_ACCESS;
+		}
+		return name;
+	}
+	public void setAccess(String access) {
+		assert(access == null || access.equals(PROPERTY_ACCESS) || access.equals(FIELD_ACCESS));
+		if (!StringUtil.equalObjects(access, getAccess())) {
+			setCustomized(ACCESS, access);
+		}
+	}
+	/**
+	 * Returns one of {@link #LAZY_FETCH}|{@link #EAGER_FETCH} indicating how 
+	 * the table associations are feched.
+	 * Returns null if the provider defaults should be used.
+	 */
+	public String getDefaultFetch() {
+		return customized(DEFAULT_FETCH);
+	}
+	public void setDefaultFetch(String fetch) {
+		assert(fetch == null || fetch.equals(LAZY_FETCH) || fetch.equals(EAGER_FETCH));
+		setCustomized(DEFAULT_FETCH, fetch);
+	}
+	public String[] getSupportedCollectionTypes() {
+		return new String[] {SET_COLLECTION_TYPE, LIST_COLLECTION_TYPE};
+	}
+	/**
+	 * Returns one of {@link #LIST_COLLECTION_TYPE}|{@link #SET_COLLECTION_TYPE} indicating  
+	 * the Java type (full class name) used for properties of collection types.
+	 * This does not return null (defaults to list).
+	 */
+	public String getDefaultCollectionType() {
+		String cType = customized(DEFAULT_COLLECTION_TYPE);
+		if (cType == null) {
+			cType = SET_COLLECTION_TYPE;
+		}
+		return cType;
+	}
+	public void setDefaultCollectionType(String cType) {
+		assert(cType.equals(LIST_COLLECTION_TYPE) || cType.equals(SET_COLLECTION_TYPE));
+		setCustomized(DEFAULT_COLLECTION_TYPE, cType);
+	}
+	/**
+	 * Returns true if the primary key is compound and any of its 
+	 * columns should be included in the <code>equals</code> method 
+	 * implementation.
+	 */
+	public boolean isCompoundKeyUseInEquals()  {
+		if (isCompositeKey()) {
+			for (Iterator<ORMGenColumn> iter = getPrimaryKeyColumns().iterator(); iter.hasNext();) {
+				ORMGenColumn column = (ORMGenColumn) iter.next();
+				if (column.isUseInEquals()) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	public boolean isRoleUseInEquals(AssociationRole role)  {
+		for (Iterator<ORMGenColumn> iter = role.getReferrerColumns().iterator(); iter.hasNext();) {
+			ORMGenColumn column = (ORMGenColumn) iter.next();
+			if (column.isUseInEquals()) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	
+	/**
+	 * Return true if the values of name element in the @Table is default
+	 * so we can skip generating the annotation
+	 * 
+	 * @return true
+	 */
+	public boolean isDefaultname(){
+		String className = this.getClassName();
+		String tableName = this.getDbTable().getName();
+		return className.equalsIgnoreCase( tableName) ;
+	}
+	
+	/**
+	 * Qualifies a class name if there is a package.
+	 */
+	private String qualify(String className) {
+		String pkg = getPackage();
+		if (pkg != null && pkg.length() != 0) {
+			className = pkg + '.' + className;
+		}
+		return className;
+	}
+	/**
+	 * Returns true if the given column is part of any association.
+	 */
+	private boolean isColumnInAsscociation(ORMGenColumn column, List<AssociationRole> roles) {
+		for (int i = 0, n = roles.size(); i < n; ++i) {
+			AssociationRole role = (AssociationRole)roles.get(i);
+			List<ORMGenColumn> cols = role.getReferrerColumns();
+			for( ORMGenColumn col : cols ){
+				if (col.getName().equals( column.getName() )) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * Print the clause to be used in the generated equals() method
+	 * @return String
+	 */
+	public String getPrimaryKeyEqualsClause() {
+		StringBuilder buf = new StringBuilder();
+		Iterator<ORMGenColumn> columns = this.getPrimaryKeyColumns().iterator();
+		while (columns.hasNext()) {
+			this.printPrimaryKeyEqualsClauseOn(columns.next(), buf);
+			if (columns.hasNext()) {
+				buf.append("\n");
+				buf.append("\t\t\t");
+				buf.append("&& ");
+			}
+		}
+		buf.append(";");
+		return buf.toString();
+	}
+	
+	private void printPrimaryKeyEqualsClauseOn(ORMGenColumn column, StringBuilder buf) {
+		String fieldName = column.getPropertyName();
+		JavaType javaType = column.getDbColumn().getPrimaryKeyJavaType();
+		if (javaType.isPrimitive()) {
+			this.printPrimitiveEqualsClauseOn(fieldName, buf);
+		} else {
+			this.printReferenceEqualsClauseOn(fieldName, buf);
+		}
+	}
+
+	private void printPrimitiveEqualsClauseOn(String fieldName, StringBuilder buf)  {
+		buf.append("(this.");
+		buf.append(fieldName);
+		buf.append(" == castOther.");
+		buf.append(fieldName);
+		buf.append(')');
+	}
+
+	private void printReferenceEqualsClauseOn(String fieldName, StringBuilder buf)  {
+		buf.append("this.");
+		buf.append(fieldName);
+		buf.append(".equals(castOther.");
+		buf.append(fieldName);
+		buf.append(')');
+	}
+	
+	/**
+	 * Print the clause to be used in the generated hasCode() method
+	 * @return String
+	 */
+	public String getPrimaryKeyHashCodeClause() {
+		StringBuilder buf = new StringBuilder();
+		Iterator<ORMGenColumn> columns = this.getPrimaryKeyColumns().iterator();
+		while (columns.hasNext()) {
+			buf.append("hash = hash * prime + ");
+			this.printPrimaryKeyHashCodeClauseOn(columns.next(), buf);
+			buf.append(';');
+			buf.append('\n');
+			buf.append("\t\t");
+		}
+		return buf.toString();
+	}
+	
+	private void printPrimaryKeyHashCodeClauseOn(ORMGenColumn column, StringBuilder buf) {
+		String fieldName = column.getPropertyName();
+		JavaType javaType = column.getDbColumn().getPrimaryKeyJavaType();
+		if (javaType.isPrimitive()) {
+			this.printPrimitiveHashCodeClauseOn(javaType.getElementTypeName(), fieldName, buf);
+		} else {
+			this.printReferenceHashCodeClauseOn(fieldName, buf);
+		}
+	}	
+	
+	private void printPrimitiveHashCodeClauseOn(String primitiveName, String fieldName, StringBuilder buf) {
+		if (primitiveName.equals("int")) {
+			// this.value
+			buf.append("this.");
+			buf.append(fieldName);
+		} else if (primitiveName.equals("short") || primitiveName.equals("byte") || primitiveName.equals("char")) {  // explicit cast
+			// ((int) this.value)
+			buf.append("((int) this.");
+			buf.append(fieldName);
+			buf.append(')');
+		} else if (primitiveName.equals("long")) {  // cribbed from Long#hashCode()
+			// ((int) (this.value ^ (this.value >>> 32)))
+			buf.append("((int) (this.");
+			buf.append(fieldName);
+			buf.append(" ^ (this.");
+			buf.append(fieldName);
+			buf.append(" >>> 32)))");
+		} else if (primitiveName.equals("float")) {  // cribbed from Float#hashCode()
+			// java.lang.Float.floatToIntBits(this.value)
+			buf.append("java.lang.Float");
+			buf.append(".floatToIntBits(this.");
+			buf.append(fieldName);
+			buf.append(')');
+		} else if (primitiveName.equals("double")) {  // cribbed from Double#hashCode()
+			//	((int) (java.lang.Double.doubleToLongBits(this.value) ^ (java.lang.Double.doubleToLongBits(this.value) >>> 32)))
+			buf.append("((int) (");
+			buf.append("java.lang.Double");
+			buf.append(".doubleToLongBits(this.");
+			buf.append(fieldName);
+			buf.append(") ^ (");
+			buf.append("java.lang.Double");
+			buf.append(".doubleToLongBits(this.");
+			buf.append(fieldName);
+			buf.append(") >>> 32)))");
+		} else if (primitiveName.equals("boolean")) {
+			// (this.value ? 1 : 0)
+			buf.append("(this.");
+			buf.append(fieldName);
+			buf.append(" ? 1 : 0)");
+		} else {
+			throw new IllegalArgumentException(primitiveName);
+		}
+	}
+
+	private void printReferenceHashCodeClauseOn(String fieldName, StringBuilder buf)  {
+		buf.append("this.");
+		buf.append(fieldName);
+		buf.append(".hashCode()");
+	}
+	
+	public String toString(){
+		return "name="+ this.getName() + "; columns=" + Arrays.toString( this.getColumnNames().toArray()) ;
+	}
+	
+	/*class scopes*/
+	public static final String PUBLIC_SCOPE = "public";
+	public static final String PROTECTED_SCOPE = "protected";
+	public static final String PRIVATE_SCOPE = "private";
+	
+	/*access constants. Note that these strings are used in the ui*/
+	public static final String PROPERTY_ACCESS = "property";
+	public static final String FIELD_ACCESS = "field";
+	
+	/*default fech constants. Note that these strings are used in the gen velocity templates.*/
+	public static final String LAZY_FETCH = "lazy";
+	public static final String EAGER_FETCH = "eager";
+	
+	/*default collection type constants. Note that these strings are used in the gen velocity templates.*/
+	public static final String LIST_COLLECTION_TYPE = "java.util.List";
+	public static final String SET_COLLECTION_TYPE = "java.util.Set";
+	
+	/**
+	 * The pattern replaced by the table name in the id generator 
+	 * sequence name param.
+	 */
+	public static final String TABLE_SEQ_PATTERN = "$table";
+	/**
+	 * The pattern replaced by the primary key in the id generator 
+	 * sequence name param.
+	 */
+	public static final String PK_SEQ_PATTERN = "$pk";
+
+	/*customization properties*/
+	private static final String PACKAGE = "package";
+	private static final String SRC_FOLDER = "srcFolder";
+	private static final String CLASS_NAME = "className";
+	private static final String CLASS_DESC = "classDesc";
+	private static final String CLASS_SCOPE = "classScope";
+	private static final String EXTENDS = "extends";
+	private static final String IMPLEMENTS = "implements";
+	private static final String ID_GENERATOR = "idGenerator";
+	private static final String SEQUENCE = "sequence";
+	private static final String COMPOSITE_KEY_CLASS_NAME = "compositeKeyClassName";
+	private static final String IMPLEMENT_EQUALS = "implementEquals";
+	private static final String GENERATE_DDL_ANNOTATION = "generateDDLAnnotations";
+	private static final String ACCESS = "access";
+	static final String DEFAULT_FETCH = "defaultFetch";
+	private static final String DEFAULT_COLLECTION_TYPE = "defaultCollectionType";
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/OverwriteConfirmer.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/OverwriteConfirmer.java
new file mode 100644
index 0000000..105174c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/OverwriteConfirmer.java
@@ -0,0 +1,50 @@
+package org.eclipse.jpt.gen.internal2;
+
+public interface OverwriteConfirmer {
+	/**
+	 * Return whether the entity generator should overwrite the specified
+	 * file.
+	 */
+	boolean overwrite(String className);
+
+
+	final class Always implements OverwriteConfirmer {
+		public static final OverwriteConfirmer INSTANCE = new Always();
+		public static OverwriteConfirmer instance() {
+			return INSTANCE;
+		}
+		// ensure single instance
+		private Always() {
+			super();
+		}
+		// everything will be overwritten
+		public boolean overwrite(String arg0) {
+			return true;
+		}
+		@Override
+		public String toString() {
+			return "OverwriteConfirmer.Always";  //$NON-NLS-1$
+		}
+	}
+
+
+	final class Never implements OverwriteConfirmer {
+		public static final OverwriteConfirmer INSTANCE = new Never();
+		public static OverwriteConfirmer instance() {
+			return INSTANCE;
+		}
+		// ensure single instance
+		private Never() {
+			super();
+		}
+		// nothing will be overwritten
+		public boolean overwrite(String arg0) {
+			return false;
+		}
+		@Override
+		public String toString() {
+			return "OverwriteConfirmer.Never";  //$NON-NLS-1$
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/PackageGenerator2.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/PackageGenerator2.java
new file mode 100644
index 0000000..3b85b09
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/PackageGenerator2.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jpt.gen.internal2.util.CompilationUnitModifier;
+import org.eclipse.jpt.gen.internal2.util.FileUtil;
+import org.eclipse.jpt.gen.internal2.util.UrlUtil;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.Bundle;
+
+/**
+ * This generator will generate a package of entities for a set of tables.
+ */
+public class PackageGenerator2 { 
+
+	private IJavaProject javaProject;
+	private ORMGenCustomizer customizer ; 
+
+	/**
+	 * @param customizer
+	 * @param synchronizePersistenceXml
+	 * @param copyJdbcDrive
+	 * @throws Exception 
+	 */
+	static public void generate(IJavaProject jpaProject, ORMGenCustomizer customizer, IProgressMonitor monitor ) throws CoreException {
+		PackageGenerator2 generator = new PackageGenerator2();
+		generator.setProject(jpaProject);
+		generator.setCustomizer(customizer);
+		
+		try {
+			generator.doGenerate(  monitor);
+		} catch (Exception e) {
+			throw new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID, JptGenMessages.Error_Generating_Entities, e));
+		}
+	}
+	
+	private Object getCustomizer() {
+		return this.customizer;
+	}
+
+	private void setCustomizer(ORMGenCustomizer customizer2) {
+		this.customizer = customizer2;
+	}
+	
+	private void setProject(IJavaProject proj ){
+		this.javaProject = proj;
+	}
+	
+	protected void doGenerate(  IProgressMonitor monitor ) throws Exception {
+		generateInternal( monitor );
+	}
+
+	protected void generateInternal( IProgressMonitor progress) throws Exception {
+		File templDir = prepareTemplatesFolder();
+
+		List<String> genClasses = new java.util.ArrayList<String>();
+		List<String> tableNames = customizer.getGenTableNames();
+
+		/* .java per table, persistence.xml, refresh package folder */
+		String taskName = NLS.bind(JptGenMessages.EntityGenerator_taskName, "Total "+ tableNames.size() + 2);//$NON-NLS-1$
+		progress.beginTask(taskName, tableNames.size() + 2);
+
+
+		for (Iterator<String> iter = tableNames.iterator(); iter.hasNext();) {
+			String tableName = (String) iter.next();
+			ORMGenTable table = (ORMGenTable) customizer.getTable(tableName);
+
+			generateClass(table, templDir.getAbsolutePath(), progress);
+			progress.worked(1);
+
+			genClasses.add(table.getQualifiedClassName());
+			/*
+			 * add the composite key class to persistence.xml because some 
+			 * JPA provider(e.g. Kodo) requires it. Hibernate doesn't seem to care). 
+			 */
+			if (table.isCompositeKey()) {
+				genClasses.add(table.getQualifiedCompositeKeyClassName());
+			}
+		}
+		progress.done();
+	}
+
+	private File prepareTemplatesFolder() throws IOException, Exception,
+			CoreException {
+		//Prepare the Velocity template folder:
+		//If the plug-in is packaged as a JAR, we need extract the template 
+		//folder into the plug-in state location. This is required by Velocity
+		//since we use included templates.
+		Bundle bundle = Platform.getBundle(JptGenPlugin.PLUGIN_ID);
+		String templatesPath = "templates/entities/";  //$NON-NLS-1$
+		Path path = new Path( templatesPath);
+		URL url = FileLocator.find(bundle, path, null);
+		if ( url ==null  ) {
+			throw new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID,  JptGenMessages.Templates_notFound + " "+  JptGenPlugin.PLUGIN_ID + "/" + templatesPath) );//$NON-NLS-1$
+		}		
+		URL templUrl = FileLocator.resolve(url);
+		
+		//Have this check so that the code would work in both PDE and JARed plug-in at runtime
+		File templDir = null;
+		if( UrlUtil.isJarUrl(templUrl) ){
+			templDir = FileUtil.extractFilesFromBundle( templUrl, bundle, templatesPath );
+		}else{
+			templDir = UrlUtil.getUrlFile(templUrl);
+		}
+		
+
+		if (templDir==null || !templDir.exists()) {
+			throw new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID,  JptGenMessages.Templates_notFound + " "+  JptGenPlugin.PLUGIN_ID ) );//$NON-NLS-1$
+		}
+		return templDir;
+	}
+	
+	/**
+	 * Saves/Creates the .java file corresponding to a database table 
+	 * with the given content.
+	 * 
+	 * @param templDir The velocity template file directory. It is assumed 
+	 * that this directory contains the 2 files <em>main.java.vm</em> 
+	 * and <em>pk.java.vm</em> 
+	 * @param progress 
+	 */
+	protected void generateClass(ORMGenTable table, String templateDirPath, IProgressMonitor monitor) throws Exception {
+
+		String subTaskName = NLS.bind(JptGenMessages.EntityGenerator_taskName, table.getName());
+		SubMonitor sm = SubMonitor.convert(monitor, subTaskName, 100);
+
+		try{
+			IFolder javaPackageFolder = getJavaPackageFolder(table, monitor);
+			IFile javaFile = javaPackageFolder.getFile( table.getClassName() + ".java"); //$NON-NLS-1$
+			
+			Properties vep = new Properties();
+			vep.setProperty("file.resource.loader.path", templateDirPath); //$NON-NLS-1$
+			VelocityEngine ve = new VelocityEngine();
+		    ve.init(vep);
+		    sm.worked(20);
+		    
+		    generateJavaFile(table, javaFile, ve, "main.java.vm", true/*isDomainClass*/, monitor); //$NON-NLS-1$
+		    sm.worked(80);
+		    
+		    if (table.isCompositeKey()) {
+		    	IFile compositeKeyFile = javaPackageFolder.getFile( table.getCompositeKeyClassName()+".java"); //$NON-NLS-1$
+		    	generateJavaFile(table, compositeKeyFile, ve, "pk.java.vm", false/*isDomainClass*/, monitor ); //$NON-NLS-1$
+		    }
+		    
+			javaFile.refreshLocal(1, new NullProgressMonitor());
+			
+		} catch(Throwable e){
+			CoreException ce = new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID, JptGenMessages.Templates_notFound + "" + JptGenPlugin.PLUGIN_ID , e) );//$NON-NLS-1$
+			JptGenPlugin.logException( ce );
+		}
+		sm.setWorkRemaining(0);
+	}
+	
+	private void generateJavaFile(ORMGenTable table, IFile javaFile, VelocityEngine ve
+			, String templateName, boolean isDomainClass, IProgressMonitor monitor) throws Exception {
+		VelocityContext context = new VelocityContext();
+        context.put("table", table); //$NON-NLS-1$
+        context.put("customizer", getCustomizer()); //$NON-NLS-1$
+        
+		StringWriter w = new StringWriter();
+		ve.mergeTemplate(templateName, context, w);
+		
+		String fileContent = w.toString();
+		if (javaFile.exists()) {
+			if (isDomainClass) {
+				updateExistingDomainClass(table.getQualifiedClassName(), javaFile, fileContent);
+			} else {
+				javaFile.setContents(new ByteArrayInputStream(fileContent.getBytes()), true, true, monitor );
+			}
+		} else {
+			createFile(javaFile, new ByteArrayInputStream(fileContent.getBytes()));
+		}		
+	}
+	
+	
+	/**
+	 * Updates the (existing) Java file corresponding to the given class.
+	 * 
+	 * @param className The qualified class name.
+	 * 
+	 * @param javaFile The existing Java file of the class to update.
+	 * 
+	 * @param fileContent The new file content.
+	 */
+	protected void updateExistingDomainClass(String className, IFile javaFile, String fileContent) throws Exception {
+		/*use CompilationUnitModifier instead of calling WideEnv.getEnv().setFileContent 
+		 * so that if the unit is up to date if it is used before file change 
+		 * notifications are delivered (see EJB3ImportSchemaWizard.updateExistingDomainClass for example)*/
+		IJavaProject project = javaProject.getJavaProject();
+		CompilationUnitModifier modifier = new CompilationUnitModifier(project, className);
+		modifier.setJavaSource(fileContent);
+		modifier.save();
+	}
+	
+	public void createFile(IFile file, java.io.InputStream contents) throws CoreException {		
+		file.create(contents, false, null/*monitor*/);
+	}
+	
+	public IFolder getJavaPackageFolder(ORMGenTable table, IProgressMonitor monitor) throws CoreException {
+		IPackageFragmentRoot root = getDefaultJavaSrouceLocation ( javaProject ) ;
+		String packageName = table.getPackage();
+		if( packageName==null ) packageName ="";
+		IPackageFragment packageFragment = root.getPackageFragment(packageName);
+		if( !packageFragment.exists()){
+			root.createPackageFragment(packageName, true, monitor);
+		}		
+		return (IFolder)packageFragment.getResource();
+	}
+	
+	private IPackageFragmentRoot getDefaultJavaSrouceLocation(IJavaProject jproject){
+		if (jproject != null) {
+			try {
+				if (jproject.exists()) {
+					IPackageFragmentRoot[] roots = jproject.getPackageFragmentRoots();
+					for (int i= 0; i < roots.length; i++) {
+						if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
+							return roots[i] ; 
+						}
+					}							
+				}
+			} catch (JavaModelException e) {
+				JptGenPlugin.logException(e);
+			}
+		}
+		return null;
+	}
+
+	
+	// ********** annotation name builder **********
+
+	
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/TagNames.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/TagNames.java
new file mode 100644
index 0000000..92a60fe
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/TagNames.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2;
+
+/**
+ * TODO: merge with JPA class ?
+ * The JPA mapping tag and attribute names.
+ * 
+ */
+public class TagNames
+{
+	public static final String BASIC_TAG = "basic";
+	public static final String CASCADE_TAG = "cascade";
+	public static final String COLUMN_TAG = "column";
+	public static final String EMBEDDED_TAG = "embedded";
+	public static final String EMBEDDED_ID_TAG = "embedded-id";
+	public static final String GENERATED_VALUE_TAG = "generated-value";
+	public static final String ID_TAG = "id";
+	public static final String ID_CLASS_TAG = "id";
+	public static final String JOIN_COLUMN_TAG = "join-column";
+	public static final String INVERSE_JOIN_COLUMN_TAG = "inverse-join-column";
+	public static final String LOB_TAG = "lob";
+	public static final String MANY_TO_MANY_TAG = "many-to-many";
+	public static final String MANY_TO_ONE_TAG = "many-to-one";
+	public static final String MAPPED_BY_TAG = "mapped-by";
+	public static final String ONE_TO_MANY_TAG = "one-to-many";
+	public static final String ONE_TO_ONE_TAG = "one-to-one";
+	public static final String PK_JOIN_COLUMN_TAG = "primary-key-join-column";
+	public static final String TABLE_TAG = "table";
+	public static final String VERSION_TAG = "version";
+	public static final String JOIN_TABLE_TAG = "join-table";
+
+	/*cascade tags*/
+	public static final String ALL_CASCADE = "all";
+	public static final String PERSIST_CASCADE = "persist";
+	public static final String MERGE_CASCADE = "merge";
+	public static final String REMOVE_CASCADE = "remove";
+	public static final String REFRESH_CASCADE = "refresh";
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/CompilationUnitModifier.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/CompilationUnitModifier.java
new file mode 100644
index 0000000..a238b79
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/CompilationUnitModifier.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2.util;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jface.text.Document;
+import org.eclipse.text.edits.TextEdit;
+
+
+/**
+ * Performs the grunt work needed for modifying a compilation 
+ * unit and performs the modified compilation unit save.
+ * 
+ * The typical usage is as follows:
+ * <ol><li>Create an instance.
+ * 
+ * <li>Modify the compilation unit using AST operations performed 
+ * 	on the node returned by {@link #getCompilationUnitNode()}.
+ *  Alternatively you can call <code>setJavaSource</code> to change the entire source code. 
+ * 
+ * <li>Call the {@link #save()} method.
+ * 
+ */
+public class CompilationUnitModifier
+{
+	private IJavaProject mProject;
+	private ICompilationUnit mCompilationUnit;
+	private CompilationUnit mCompilationUnitNode;
+	private Document mDocument;
+	
+	public CompilationUnitModifier(IJavaProject project, String className) throws Exception {
+		super();
+		
+		mProject = project;
+		
+		IType type = project.findType(className);
+		if (type == null) {
+			throw new Exception("The class " + className + " does not exist.");
+		}
+		mCompilationUnit = type.getCompilationUnit();
+		if (mCompilationUnit == null) {
+			throw new Exception("The source code for " + className + " does not exist.");
+		}
+	}
+	public CompilationUnitModifier(IJavaProject project, ICompilationUnit cu) throws Exception {
+		super();
+		
+		mProject = project;
+		mCompilationUnit = cu;
+	}
+	public CompilationUnitModifier(IJavaProject project, ICompilationUnit cu, CompilationUnit cuNode) throws Exception {
+		super();
+		
+		mProject = project;
+		mCompilationUnit = cu;
+		mCompilationUnitNode = cuNode;
+		
+		getCompilationUnitNode(); //to create mDocument (the caller in this case does not have to call getCompilationUnitNode)
+	}
+	public ICompilationUnit getCompilationUnit() {
+		return mCompilationUnit;
+	}
+	/**
+	 * Returns the compilation unit node that should be used for 
+	 * tyhe modification AST operations.
+	 */
+	public CompilationUnit getCompilationUnitNode() {
+		if (mCompilationUnitNode == null) {
+			ASTParser c = ASTParser.newParser(AST.JLS3);
+			c.setSource(mCompilationUnit);
+			c.setResolveBindings(true);
+			mCompilationUnitNode = (CompilationUnit)c.createAST(null);
+		}
+		if (mDocument == null) {
+			try {
+				mDocument = new Document(mCompilationUnit.getBuffer().getContents());
+			} catch (JavaModelException e) {
+				e.printStackTrace();
+			}
+			
+			mCompilationUnitNode.recordModifications();
+		}
+		
+		return mCompilationUnitNode;
+	}
+	/**
+	 * Changes the entire Java source code of the compilation unit.
+	 */
+	public void setJavaSource(String newSource) {
+		try {
+			mCompilationUnit.getBuffer().setContents(newSource);
+		} catch (JavaModelException e) {
+			e.printStackTrace();
+		}
+	}
+	/**
+	 * Saves the compilation unit modifications.
+	 */
+	public void save() throws Exception {
+		if (mCompilationUnitNode != null) {
+			assert(mDocument != null); //see getCompilationUnitNode
+			
+			//computation of the text edits
+			TextEdit edits = mCompilationUnitNode.rewrite(mDocument, mProject.getOptions(true));
+			//computation of the new source code
+			edits.apply(mDocument);
+			String newSource = mDocument.get();
+			// update of the compilation unit
+			mCompilationUnit.getBuffer().setContents(newSource);
+		}
+		
+		if (mCompilationUnit.isWorkingCopy()) {
+			mCompilationUnit.commitWorkingCopy(true/*force*/, null/*monitor*/);
+		} else {
+			mCompilationUnit.save(null/*monitor*/, true/*force*/);
+		}
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/DTPUtil.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/DTPUtil.java
new file mode 100644
index 0000000..dcf3ef9
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/DTPUtil.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jpt.db.Column;
+import org.eclipse.jpt.db.ForeignKey;
+import org.eclipse.jpt.db.Schema;
+import org.eclipse.jpt.db.Table;
+import org.eclipse.jpt.db.ForeignKey.ColumnPair;
+import org.eclipse.jpt.gen.internal2.ForeignKeyInfo;
+
+/**
+ * Collection of utility methods to access DTP and other jpt.db APIs 
+ *
+ */
+public class DTPUtil {
+
+	/**
+	 * Return list of the pk names
+	 * @param dbTable
+	 * @return
+	 */
+	public static List<String> getPrimaryKeyColumnNames(Table dbTable ) {
+		Iterator<Column> pkColumns = dbTable.primaryKeyColumns();
+		ArrayList<String> ret = new ArrayList<String>();
+		while( pkColumns.hasNext() ){
+			ret.add( pkColumns.next().getName() );
+		}
+		return ret;
+	}
+
+	/**
+	 * 
+	 * @param dbTable
+	 * @return
+	 */
+	public static List<Column> getPrimaryKeyColumns(Table dbTable ) {
+		Iterator<Column> pkColumns = dbTable.primaryKeyColumns();
+		ArrayList<Column> ret = new ArrayList<Column>();
+		while( pkColumns.hasNext() ){
+			ret.add( pkColumns.next() );
+		}
+		return ret;
+	}
+	
+	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){
+			Iterator<ForeignKey> fks = dbTable.foreignKeys();
+			while( fks.hasNext() ){
+				ForeignKey fk  = fks.next();
+				ColumnPair columnPair = fk.getColumnPair();
+
+				String tableName = dbTable.getName();
+				String referencedTableName = "";
+				Table referencedTable = fk.getReferencedTable();
+				referencedTableName = referencedTable.getName();
+				ForeignKeyInfo fkInfo = new ForeignKeyInfo(fk, tableName, referencedTableName );
+				String baseColName = columnPair.getBaseColumn().getName();
+				String referencedColName = columnPair.getReferencedColumn().getName();
+				fkInfo.addColumnMapping( baseColName,  referencedColName );
+				ret.add( fkInfo );
+			}
+		}
+		return ret;
+	}
+
+	public static String getJavaType(Schema schema, Column dbColumn) {
+		if( isPrimaryKey(dbColumn) )
+			return dbColumn.getPrimaryKeyJavaTypeDeclaration();
+		return dbColumn.getJavaTypeDeclaration();
+	}
+
+	public static boolean isPrimaryKey(Column dbColumn){
+		Table dbTable = dbColumn.getTable();
+		Iterator<Column> pkColumns = dbTable.primaryKeyColumns();		
+		while( pkColumns.hasNext() ){
+			if( pkColumns.next().equals( dbColumn )){
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	public static boolean isDefaultSchema(Table dbTable){
+		String schemaName = dbTable.getSchema().getName();
+		Schema defaultSchema = dbTable.getSchema().getConnectionProfile().getDatabase().getDefaultSchema();
+		return defaultSchema.getName() == schemaName;
+	}	
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/FileUtil.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/FileUtil.java
new file mode 100644
index 0000000..1235d6a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/FileUtil.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.osgi.framework.Bundle;
+
+/**
+ * Collections of utility methods handling files.
+ * 
+ */
+public class FileUtil
+{
+	
+	private static String DELETE_FOLDER_ERR = "The directory %s could not be deleted.";
+	private static String DELETE_FILE_ERR = "The file %s could not be deleted.";
+	private static String FILE_READONLY_ERR = "The file %s could not be modified because write access is denied.\nPlease make sure that the file is not marked as readonly in the file system.";
+
+	public static void deleteFolder(File folder)
+		throws IOException
+	{
+		File[] files = folder.listFiles();
+		//empty the folder first (java.io.file.delete requires it empty)
+		if (files != null) {
+			for (int i = 0; i < files.length; ++i) {
+				File f = files[i];
+				if (f.isDirectory())
+					deleteFolder(f);
+				else
+					deletePath(f);
+			}
+		}
+		deletePath(folder);
+	}
+
+	public static void deletePath(File f)
+		throws IOException
+	{
+		if (!f.delete()) {
+			String msgId = f.isDirectory() ?  DELETE_FOLDER_ERR :  DELETE_FILE_ERR;
+			throw new IOException( String.format(msgId,f.getPath()));
+		}
+	}
+	
+	public static byte[] readFile(File src)
+		throws IOException
+	{
+		java.io.FileInputStream fin = new java.io.FileInputStream(src);
+		try {
+			long fileLen = src.length();
+			if (fileLen > Integer.MAX_VALUE)
+				throw new IOException("file length too big to be read by FileUtil.readFile: " + fileLen);
+		
+			byte[] bytes = new byte[(int)fileLen];
+			fin.read(bytes);
+			return bytes;
+		}
+		finally {
+			fin.close();
+		}
+	}
+
+	public static void writeFile(File dest, byte[] bytes)
+		throws IOException
+	{
+		if (dest.exists() && !dest.canWrite())
+			throw new IOException( FILE_READONLY_ERR );  //throw with a clear error because otherwise FileOutputStream throws FileNotFoundException!
+		java.io.FileOutputStream fout = new java.io.FileOutputStream(dest.getPath(), false/*append*/);
+		try {
+			fout.write(bytes);
+		}
+		finally {
+			fout.flush();
+			fout.close();
+		}
+	}
+
+	/**
+	 * Returns the url for a file.
+	 * This basically the same as file.toUrl() but without the non-sense exception.
+	 */
+	public static URL getFileUrl(File file) {
+		try {
+			return file.toURI().toURL();
+		} catch (MalformedURLException e) {
+			return null; //should not happen as file.toURL() does not really throw an exception
+		}
+	}
+
+	public static void setFileContent(File file, java.io.InputStream contents) throws java.io.IOException {
+		Path path = new Path(file.getAbsolutePath());
+		try {
+			IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
+			if (iFile == null) {
+				throw new IOException("The path " + file + " does not seem to be a valid file path.");
+			}
+			iFile.setContents(contents, true/*force*/, true/*keepHistory*/, null/*monitor*/);
+		} catch (CoreException ex) {
+			throw new IOException(ex.getMessage());
+		}
+	}	
+	
+    /**
+     * Extract the contents of a Jar archive to the specified destination.
+     */
+    public static void unjar(InputStream in, File dest) throws IOException {
+        if (!dest.exists()) {
+            dest.mkdirs();
+        }
+        if (!dest.isDirectory()) {
+            throw new IOException("Destination must be a directory.");//$NON-NLS-1$
+        }
+        JarInputStream jin = new JarInputStream(in);
+        byte[] buffer = new byte[1024];
+
+        ZipEntry entry = jin.getNextEntry();
+        while (entry != null) {
+            String fileName = entry.getName();
+            if (fileName.charAt(fileName.length() - 1) == '/') {
+                fileName = fileName.substring(0, fileName.length() - 1);
+            }
+            if (fileName.charAt(0) == '/') {
+                fileName = fileName.substring(1);
+            }
+            if (File.separatorChar != '/') {
+                fileName = fileName.replace('/', File.separatorChar);
+            }
+            File file = new File(dest, fileName);
+            if (entry.isDirectory()) {
+                // make sure the directory exists
+                file.mkdirs();
+                jin.closeEntry();
+            } else {
+                // make sure the directory exists
+                File parent = file.getParentFile();
+                if (parent != null && !parent.exists()) {
+                    parent.mkdirs();
+                }
+
+                // dump the file
+                OutputStream out = new FileOutputStream(file);
+                int len = 0;
+                while ((len = jin.read(buffer, 0, buffer.length)) != -1) {
+                    out.write(buffer, 0, len);
+                }
+                out.flush();
+                out.close();
+                jin.closeEntry();
+                file.setLastModified(entry.getTime());
+            }
+            entry = jin.getNextEntry();
+        }
+        /* Explicitly write out the META-INF/MANIFEST.MF so that any headers such
+         as the Class-Path are seen for the unpackaged jar
+         */
+        Manifest mf = jin.getManifest();
+        if (mf != null) {
+            File file = new File(dest, "META-INF/MANIFEST.MF");//$NON-NLS-1$
+            File parent = file.getParentFile();
+            if (parent.exists() == false) {
+                parent.mkdirs();
+            }
+            OutputStream out = new FileOutputStream(file);
+            mf.write(out);
+            out.flush();
+            out.close();
+        }
+        jin.close();
+    }
+    
+	//Used to Unzip the a specific folder packed inside a plug-in bundle to the plug-in state location
+	public static File extractFilesFromBundle( URL url, Bundle bundle, String path ) throws Exception {
+		URL jarUrl = UrlUtil.getJarFileUrl(url);
+		File jarFile = new File(jarUrl.getFile() );
+		Location configLocation = Platform.getConfigurationLocation();
+		String pluginId = bundle.getSymbolicName();
+		File configFolder = new File( configLocation.getURL().getFile(), pluginId);
+		File templDir = new File( configFolder, path );
+		if( !templDir.exists() ){
+			FileUtil.unjar( new FileInputStream( jarFile ), configFolder );
+			//Delete un-related files and folders
+			File[] files = configFolder.listFiles();
+			for( File f : files ){
+				if( f.isFile() )
+					f.delete();
+				else if(  templDir.getPath().indexOf( f.getPath() ) !=0  ){
+					FileUtil.deleteFolder(f);
+				}
+			}
+		}
+		return templDir ;
+	}	
+}
+
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/StringUtil.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/StringUtil.java
new file mode 100644
index 0000000..45efe13
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/StringUtil.java
@@ -0,0 +1,648 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2.util;
+
+import java.beans.Introspector;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+public class StringUtil
+{
+	/**
+	 * Pads a string by adding a sequence of an arbitrary character at the beginning.
+	 * @param padChar The character to be used for padding.
+	 * @param len The desired length after padding.
+	 * @return The padded string. For example if <code>str</code> is "f4e" and <code>padChar</code> is '0' 
+	 * and <code>len</code> is 6 then this method returns "000f4e"
+	 */
+	public static String padLeft(String str, char padChar, int len) {
+		if(str == null) {
+			return null;
+		}
+		int strLen = str.length();
+		if (strLen < len) {
+			StringBuffer buffer = new StringBuffer(len);
+			int count = len-strLen;
+			for (int i = 0; i < count; ++i)
+				buffer.append(padChar);
+			buffer.append(str);
+			str = buffer.toString();
+		}
+		return str;
+	}
+	/**
+	 * Inserts a given character at the beginning and at the end of the specified string.
+	 * For example if the string is <tt>extreme</tt> and the char is <tt>'</tt> then 
+	 * the returned string is <tt>'exterme'</tt>.
+	 */
+	public static String quote(String str, char c) {
+		assert(str != null);
+		StringBuffer buffer = new StringBuffer(str.length()+2);
+		buffer.append(c);
+		buffer.append(str);
+		buffer.append(c);
+		return buffer.toString();
+	}
+	public static String doubleQuote(String str) {
+		return quote(str, '"');
+	}
+	/**
+	 * Removes the first and last single or double quotes (if they exist).
+	 */
+	public static String unquote(String quoted) {
+		if (quoted != null && quoted.length() >= 2){
+			int len = quoted.length();
+			char firstChar = quoted.charAt(0);
+			char lastChar = quoted.charAt(len-1);
+			if (firstChar == lastChar && (firstChar == '\'' || firstChar == '"')) {
+				return quoted.substring(1, len-1);
+			}
+		}
+		return quoted;
+	}
+	/**
+	 * Truncates a string and adds "..." in the result string.
+	 * If the string length is less or equal to the max len then 
+	 * the original string is returned.
+	 */
+	public static String truncate(String s, int maxLen) {
+		if (s == null) {
+			return null;
+		}
+		int len = s.length();
+		if (len > maxLen) {
+			int segmentLen = maxLen/2;
+			s = s.substring(0, segmentLen) + "..." + s.substring(len-segmentLen);
+		}
+		return s;
+	}
+	/**
+	 * Returns a string containing the same character repeated.
+	 */
+	public static String repeat(char c, int count) {
+		StringBuffer buffer = new StringBuffer(count);
+		for (int i = 0; i < count; ++i) {
+			buffer.append(c);
+		}
+		return buffer.toString();
+	}
+	/**
+	 * Returns the given string unless it is emtpty where it returns null.
+	 */
+	public static String nullIfEmpty(String s) {
+		if (s != null && s.length() == 0) {
+			s = null;
+		}
+		return s;
+	}
+	/**
+     * Returns a string containing the same characters as the argument string 
+	 * except that the control characters are replaced by the their hex code.
+	 * For example if the string is "ab\nc" the returned string is "ab{0xA}c".
+	 */
+	public static String getVisibleString(String s) {
+		if (s == null)
+			return null;
+		int len = s.length();
+		StringBuffer buffer = new StringBuffer();
+		for (int i = 0; i < len; ++i) {
+			char c = s.charAt(i);
+			if (c <= 0x1F || (c == 0x20 && (i == 0 || i == len-1))) {
+				buffer.append("(0x" + Integer.toHexString((int)c).toUpperCase() + ")");
+			}
+			else buffer.append(c);
+		}
+		return buffer.toString();
+	}
+	/**
+	 * Replaces a portion of string.
+	 * @param str The original string.
+	 * @param offset The offset in the original string where the replace starts
+	 * @param len The replace length the original string
+	 * @param replaceStr The replacement string
+	 */
+	public static String strReplace(String str, int offset, int len, String replaceStr) {
+		StringBuffer buffer = new StringBuffer(str.length()-len+replaceStr.length());
+		buffer.append(str.substring(0, offset));
+		buffer.append(replaceStr);
+		buffer.append(str.substring(offset+len));
+		
+		return buffer.toString();
+	}
+	public static String strReplace(String str, String pattern, String replaceStr)
+	{
+		if(str == null) {
+			return null;
+		}
+		if(pattern == null || pattern.equals("")) {
+			return str;
+		}
+		int index = str.indexOf(pattern);
+		if (index < 0)
+			return str;
+		
+		if (replaceStr == null)
+			replaceStr = "";
+		return str.substring(0, index) + replaceStr + str.substring(index + pattern.length());
+	}
+	public static String strReplaceAll(String str, String pattern, String replaceStr)
+	{
+		if(str == null) {
+			return null;
+		}
+		if (replaceStr == null)
+			replaceStr = "";
+		if(pattern == null || pattern.equals("")) {
+			return str;
+		}
+		int index = str.indexOf(pattern);
+		while (index >= 0) {
+			str = str.substring(0, index) + replaceStr + str.substring(index + pattern.length());
+			index = str.indexOf(pattern, index+replaceStr.length());
+		}
+		return str;
+	}
+	public static String strInsert(String str, int index, String insertStr)
+	{
+		return str.substring(0, index)
+				+ insertStr
+				+ str.substring(index);
+	}
+    /**
+     * Tokenize the specified string into a <code>List</code> of
+     * words.
+     * If the string specified is <code>null</code> or empty, this
+     * method will return <code>null</code>.
+     * 
+     * @param s      The string to tokenize into a <code>List</code>.
+     * @param sep    The separator character to use to split
+     *               the string.
+     * @param trim   If <code>true</code>, run <code>trim</code> on
+     *               each element in the result <code>List</code>.
+     * 
+     * @return A <code>List</code> containing all tokenized words
+     *         in the parameter string.
+     *         Each element is of type <code>String</code>.
+     */
+	public static List<String> strToList(String s, char sep, boolean trim)
+	{
+	//ex: if sep is ';' then s should be someting like "Red;Black"
+		if (s == null || s.length() == 0)
+			return null;
+			
+		ArrayList<String> result = new ArrayList<String>();
+		
+		char delimiters[] = {sep};
+		java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(s, new String(delimiters), true/*returnDelimiters*/);
+		String lastTok=null;
+		while (tokenizer.hasMoreTokens()) {
+			String tok = tokenizer.nextToken();
+			if (tok.length()==1 && tok.charAt(0)==sep){//delimiter
+			    if (tok.equals(lastTok)||lastTok==null/*first element is empty*/)
+			        result.add("");
+			}
+			else{
+			    if (trim)
+			        tok = tok.trim();
+			    result.add(tok);
+			}
+			lastTok=tok;
+		}
+		if(lastTok.length()==1 && lastTok.charAt(0)==sep)//last element is empty
+		    result.add("");
+		result.trimToSize();
+		return result;
+	}
+	public static List<String> strToList(String s, char sep)
+	{
+		return strToList(s, sep, false/*trim*/);
+	}
+	
+	@SuppressWarnings("unchecked")
+	public static String listToStr(Collection a, char sep)
+	{
+		return listToStr(a, String.valueOf(sep));
+	}
+	
+	public static String listToStr(Collection<Object> a, String sep) {
+		//reverse of strToList
+		if (a == null)
+			return null;
+		int count = a.size();
+		if (count == 0)
+			return null;
+		
+		StringBuffer buffer = null;
+		for (Iterator<Object> iter = a.iterator(); iter.hasNext(); )
+		{
+			Object obj = iter.next();
+			if (obj == null)
+				continue;
+			
+			if (buffer == null)
+				buffer = new StringBuffer();
+			else
+				buffer.append(sep);
+			if (obj instanceof String)
+				buffer.append((String)obj);
+			else
+				buffer.append(obj);
+		}
+		return (buffer != null) ? buffer.toString() : null;
+	}
+	/**
+	 * Convert the text of a String into a Map of Strings, where each
+	 * key and value in the Map is of type String.
+	 * 
+	 * @param s      The string to be converted to a Map.
+	 * @param sep1   The separator between keys and their
+	 *               values.
+	 * @param sep2   The separator between key-value pairs.
+	 * 
+	 * @return The string converted to a Map.
+	 */
+	public static java.util.Map<String, String> strToMap(String s, char sep1, char sep2)
+	{
+		return strToMap(s, sep1, sep2, false/*lowercaseKeys*/);
+	}
+	/**
+	 * Convert the text of a String into a Map of Strings, where each
+	 * key and value in the Map is of type String.
+	 * This form also allows you to specify that all keys will be
+	 * converted to lower-case before adding to the Map.
+	 * 
+	 * @param s      The string to be converted to a Map.
+	 * @param sep1   The separator between keys and their
+	 *               values.
+	 * @param sep2   The separator between key-value pairs.
+	 * @param lowercaseKeys
+	 *               Whether to convert keys to lower case
+	 *               before adding to the Map.
+	 * 
+	 * @return The string converted to a Map.
+	 */
+	public static java.util.Map<String, String> strToMap(String s, char sep1, char sep2, boolean lowercaseKeys)
+	{
+		//ex: if sep1 is ':' and sep2 is ',' then s should be something like "color:Red,size:XL"
+		
+		if (s == null || s.length() == 0) {
+			return Collections.emptyMap();
+		}
+			
+		java.util.List<String> a = strToList(s, sep2);
+		if (a == null) {
+			return Collections.emptyMap();
+		}
+		
+		java.util.HashMap<String, String> hm = new java.util.HashMap<String, String>();
+		int count = a.size();
+		for (int i = 0; i < count; ++i)
+		{
+			String s2 = (String)a.get(i); //ex: color:Red
+			int pos = s2.indexOf(sep1);
+			if (pos >= 0)
+			{
+				String name = s2.substring(0, pos);
+				String val = s2.substring(pos+1);
+				if (lowercaseKeys)
+					name = name.toLowerCase();
+				hm.put(name, val);
+			}
+		}
+		return hm;
+	}
+	
+	@SuppressWarnings("unchecked")
+	public static String mapToStr(java.util.Map hm, char sep1, char sep2)
+	//reverse of strToMap
+	{
+		if (hm == null || hm.isEmpty())
+			return null;
+		
+		StringBuffer buffer = new StringBuffer();
+		java.util.Iterator<java.util.Map.Entry> iter = hm.entrySet().iterator();
+		while (iter.hasNext()) {
+			java.util.Map.Entry entry = (java.util.Map.Entry)iter.next();
+			buffer.append(entry.getKey());
+			buffer.append(sep1);
+			buffer.append(entry.getValue());
+			if (iter.hasNext()) {
+				buffer.append(sep2);
+			}
+		}
+		return buffer.toString();
+	}
+    /**
+     * Perform a <em>case insensitive</em> comparison between
+     * the string representations of two objects.
+     * 
+     * @param obj1   The first object to compare.
+     * @param obj2   The second object to compare.
+     * 
+     * @return <code>true</code> if both objects have the
+     *         same case-insensitive string representation.
+     */
+	public static boolean compareAsStrings(Object obj1, Object obj2)
+	{	
+		if (obj1 == null || obj2 == null)
+			return obj1 == obj2;
+		
+		String s1, s2;
+		if (obj1 instanceof String) {
+			s1 = (String)obj1;
+        } else {
+			s1 = obj1.toString();
+        }
+		if (obj2 instanceof String) {
+			s2 = (String)obj2;
+        }
+        else {
+			s2 = obj2.toString();
+        }
+		
+		return s1.equalsIgnoreCase(s2);
+	}
+	/**
+	 * Tests whether a string starts with any of a list of strings.
+	 */
+	public static boolean startsWithAny(String s, List<String> prefixes) {
+		int count = prefixes.size();
+		for (int i = 0; i < count; ++i) {
+			if (s.startsWith((String)prefixes.get(i))) {
+				return true;
+			}
+		}
+		return false;
+	}
+	/**
+	 * Returns the argument string with the first char upper-case.
+	 */
+	public static String initUpper(String str) {
+		if (str == null || str.length() == 0) {
+			return str;
+		}
+		return Character.toUpperCase(str.charAt(0)) + str.substring(1);
+	}
+	/**
+	 * Returns the argument string with the first char lower-case.
+	 */
+	public static String initLower(String str) {
+		if (str == null || str.length() == 0) {
+			return str;
+		}
+		return Character.toLowerCase(str.charAt(0)) + str.substring(1);
+	}
+	/**
+	 * Tests whether all characters in the given string are upper
+	 * case.
+	 */
+	public static boolean isUpperCase(String s) {
+		return s.toUpperCase().equals(s);
+	}
+	/**
+	 * Returns the first non-white char index starting from the 
+	 * specified index.
+	 */
+	public static int skipWhiteSpaces(String str, int index) {
+		int len = str.length();
+		while (index < len) {
+			if (!Character.isWhitespace(str.charAt(index))) {
+				break;
+			}
+			++index;
+		}
+		return index;
+	}
+	/**
+	 * Collapses consecutive white spaces into one space.
+	 */
+	public static String collapseWhiteSpaces(String str){
+	    String result=null;
+	    if (str!=null){
+	        StringBuffer buffer=new StringBuffer();
+	        boolean isInWhiteSpace=false;
+	        for (int i=0;i<str.length();i++){
+	            char c=str.charAt(i);
+	            if (Character.isWhitespace(c)){
+	                isInWhiteSpace=true;
+	            }
+	            else {
+	                if (isInWhiteSpace)
+	                    buffer.append(" ");
+	                isInWhiteSpace=false;   
+	                buffer.append(c);
+	            }
+	        }
+	        result=buffer.toString();
+	    }
+	    return result;
+	}
+	
+	/**
+	 * Utility methods used to convert DB object names to  
+	 * appropriate Java type and field name 
+	 */
+	public static String pluralise(String name) {
+		String result = name;
+		if (name.length() == 1) {
+			result += 's';
+		} else if (!seemsPluralised(name)) {
+			String lower = name.toLowerCase();
+			if (!lower.endsWith("data")) { //orderData --> orderDatas is dumb
+				char secondLast = lower.charAt(name.length() - 2);
+				if (!isVowel(secondLast) && lower.endsWith("y")) {
+					// city, body etc --> cities, bodies
+					result = name.substring(0, name.length() - 1) + "ies";
+				} else if (lower.endsWith("ch") || lower.endsWith("s")) {
+					// switch --> switches  or bus --> buses
+					result = name + "es";
+				} else {
+					result = name + "s";
+				}
+			}
+		}
+		return result;
+	}
+
+	public static String singularise(String name) {
+		String result = name;
+		if (seemsPluralised(name)) {
+			String lower = name.toLowerCase();
+			if (lower.endsWith("ies")) {
+				// cities --> city
+				result = name.substring(0, name.length() - 3) + "y";
+			} else if (lower.endsWith("ches") || lower.endsWith("ses")) {
+				// switches --> switch or buses --> bus
+				result = name.substring(0, name.length() - 2);
+			} else if (lower.endsWith("s")) {
+				// customers --> customer
+				result = name.substring(0, name.length() - 1);
+			}
+		}
+		return result;
+	}
+	private final static boolean isVowel(char c) {
+		boolean vowel = false;
+		vowel |= c == 'a';
+		vowel |= c == 'e';
+		vowel |= c == 'i';
+		vowel |= c == 'o';
+		vowel |= c == 'u';
+		vowel |= c == 'y';
+		return vowel;
+	}
+	private static boolean seemsPluralised(String name) {
+		name = name.toLowerCase();
+		boolean pluralised = false;
+		pluralised |= name.endsWith("es");
+		pluralised |= name.endsWith("s");
+		pluralised &= !(name.endsWith("ss") || name.endsWith("us"));
+		return pluralised;
+	}
+	
+	/**
+	 * Returns the package name of a class name.
+	 * For example if given <code>oracle.util.ObjectUtil</code> it would return 
+	 * <code>oracle.util</code>. If the class is not in a package then null is returned.
+	 */
+	public static String getPackageName(String className) {
+		if(className == null) {
+			return null;
+		}
+		int lastDotIndex = className.lastIndexOf('.');
+		if (lastDotIndex < 0)
+			return null;
+		return className.substring(0, lastDotIndex);
+	}
+	/**
+	 * Returns the class name given a full class name.
+	 * For example if given <code>oracle.util.ObjectUtil</code> it would return 
+	 * <code>ObjectUtil</code>
+	 */
+	public static String getClassName(String fullClassName) {
+		if(fullClassName == null) {
+			return null;
+		}
+		int lastDotIndex = fullClassName.lastIndexOf('.');
+		if (lastDotIndex < 0)
+			return fullClassName;
+		return fullClassName.substring(lastDotIndex+1);
+	}
+
+	
+	/**
+	 * Converts a database column name to a Java variable name (<em>first letter
+	 * not capitalized</em>).
+	 */
+	public static String columnNameToVarName(String columnName) {
+		return dbNameToVarName(columnName);
+	}
+	/**
+	 * Converts a database table name to a Java variable name (<em>first letter
+	 * not capitalized</em>).
+	 */
+	public static String tableNameToVarName(String tableName) {
+		return dbNameToVarName(tableName);
+	}
+	/**
+	 * Converts a database name (table or column) to a java name (<em>first letter
+	 * not capitalized</em>). employee_name or employee-name -> employeeName
+	 */
+	private static String dbNameToVarName(String s) {
+		if ("".equals(s)) {
+			return s;
+		}
+		StringBuffer result = new StringBuffer();
+
+		boolean capitalize = true;
+		boolean lastCapital = false;
+		boolean lastDecapitalized = false;
+		String p = null;
+		for (int i = 0; i < s.length(); i++) {
+			String c = s.substring(i, i + 1);
+			if ("_".equals(c) || " ".equals(c)) {
+				capitalize = true;
+				continue;
+			}
+
+			if (c.toUpperCase().equals(c)) {
+				if (lastDecapitalized && !lastCapital) {
+					capitalize = true;
+				}
+				lastCapital = true;
+			} else {
+				lastCapital = false;
+			}
+
+			if (capitalize) {
+				if (p == null || !p.equals("_")) {
+					result.append(c.toUpperCase());
+					capitalize = false;
+					p = c;
+				} else {
+					result.append(c.toLowerCase());
+					capitalize = false;
+					p = c;
+				}
+			} else {
+				result.append(c.toLowerCase());
+				lastDecapitalized = true;
+				p = c;
+			}
+
+		}
+		/*this was using StringUtil.initLower. Changed to Introspector.decapitalize so that 
+		 * it returns the correct bean property name when called from columnNameToVarName.
+		 * This is necessary because otherwise URL would be uRL which would cause 
+		 * an "The property uRL is undefined for the type xx" error because 
+		 * Introspector.getBeanInfo (used by JavaTypeIntrospector) returns 
+		 * the property name as URL.*/
+		String resultStr = Introspector.decapitalize(result.toString());
+		if (resultStr.equals("class")) {
+			// "class" is illegal becauseOf Object.getClass() clash
+			resultStr = "clazz";
+		}
+		return resultStr;
+	}
+	
+	/**
+	 * Compare two objects. If both String, ignore case
+	 * @param o1
+	 * @param o2
+	 * @param ignoreCaseIfStr
+	 * @return
+	 */
+	public static boolean equalObjects(Object o1, Object o2, boolean ignoreCaseIfStr)
+	{
+		if (o1 == o2) {
+			return true;
+		}
+	    boolean result;
+	    if (o1 == null || o2 == null) {
+	    	return false; //we already checked o1 == o2 above
+	    }
+	    if (ignoreCaseIfStr && o1 instanceof String && o2 instanceof String)
+	        result = ((String)o1).equalsIgnoreCase((String)o2);
+	    else
+	        result = o1.equals(o2);
+	
+	    return result;
+	}
+
+	public static boolean equalObjects(Object o1, Object o2)
+	{
+	    return equalObjects(o1, o2, false/*ignoreCaseIfStr*/);
+	}
+	
+}
+
diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/UrlUtil.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/UrlUtil.java
new file mode 100644
index 0000000..f6b5276
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/UrlUtil.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.internal2.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+
+/**
+ * Collections of utility methods handling URLs.
+ * 
+ */
+public class UrlUtil
+{
+	/**
+	 * The <code>file</code> string indicating a url file protocol.
+	 */
+	public static final String FILE_PROTOCOL = "file";
+	/**
+	 * The <code>file</code> string indicating a url http protocol.
+	 */
+	public static final String HTTP_PROTOCOL = "http";
+	/**
+	 * The <code>file</code> string indicating a url http protocol.
+	 */
+	public static final String HTTPS_PROTOCOL = "https";
+	/**
+	 * The <code>file</code> string indicating a url file protocol.
+	 */
+	public static final String JAR_PROTOCOL = "jar";
+
+	
+	/**
+	 * Returns true if the specified url is to a file, i.e its protocol is <code>file</code>.
+	 */
+	public static boolean isFileUrl(URL url) {
+		return url != null && FILE_PROTOCOL.equals(url.getProtocol());
+	}
+	/**
+	 * Returns true if the specified url is to a jar, i.e its protocol is <code>jar</code>.
+	 * For example <code>jar:file:/C:/testapps/example/WEB-INF/lib/struts.jar!/META-INF/tlds/struts-bean.tld</code>.
+	 */
+	public static boolean isJarUrl(URL url) {
+		return url != null && JAR_PROTOCOL.equals(url.getProtocol());
+	}
+	/**
+	 * Returns true if the specified url protocol is http.
+	 */
+	public static boolean isHttpUrl(URL url) {
+		String protocol =  url.getProtocol();
+		return url != null && (HTTP_PROTOCOL.equals(protocol) || HTTPS_PROTOCOL.equals(protocol));
+	}
+	/**
+	 * Returns the <code>File</code> corresponding to a url, or null if the url 
+	 * protocol is not file.
+	 */
+	public static java.io.File getUrlFile(URL url) {
+		if (isFileUrl(url) && !isJarUrl( url ) ){
+			File ret = new java.io.File(url.getFile());
+			return ret ;
+		}
+		return null;
+ 	}
+
+	
+	/**
+	 * Returns the url to a jar file given a url to a file inside 
+	 * the jar.
+	 * For example if given 
+	 * <code>jar:file:/C:/testapps/example/WEB-INF/lib/struts.jar!/META-INF/tlds/struts-bean.tld</code>
+	 * this method returns <code>file:/C:/testapps/example/WEB-INF/lib/struts.jar</code>.
+	 * 
+	 * <p>Returns null if the given url is not recognized as a url to a file 
+	 * inside a jar.
+	 */
+	public static URL getJarFileUrl(URL url) {
+		if (!isJarUrl(url)) {
+			return null;
+		}
+		String file = url.getFile(); //file:/C:/testapps/example/WEB-INF/lib/struts.jar!/META-INF/tlds/struts-bean.tld
+		int index = file.indexOf('!');
+		if (index < 0) {
+			return null;
+		}
+		String jarFileUrlStr = file.substring(0, index);
+		try {
+			return new URL(jarFileUrlStr);
+		} catch (MalformedURLException e) {
+			return null;
+		}
+	}
+	
+	public static boolean isRemote(String url){
+		return url.startsWith("http:")||url.startsWith("https:")||url.startsWith("www.");
+	}
+	
+	public static File getTemplateFolder(String plugId , String strPath ){
+		Bundle bundle = Platform.getBundle( plugId );
+		Path path = new Path( strPath );
+		URL url = FileLocator.find(bundle, path, null);
+		try {
+			URL templUrl;
+			templUrl = FileLocator.resolve(url);
+			File templDir = UrlUtil.getUrlFile(templUrl);
+			return templDir ;
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/column.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/column.vm
new file mode 100644
index 0000000..8bb4910
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/column.vm
@@ -0,0 +1,52 @@
+##included template. Generates the @Column annotation.
+##Assumes that the context has a "column" and a "table" object
+##generate annotation only the parameters for the column NOT default
+##and the generateDLLAnnotation property is not set on the table
+###------------------------------------------------
+#macro( append $members $parameters )
+#if( $members == "")
+#set( $members = $parameters )
+#else
+#set( $members = "$members, $parameters" ) 
+#end	
+#end
+###------------------------------------------------
+#if ( $column.dataTypeLOB)
+    @Lob()
+#end
+#if ( $column.needMapTemporalType)
+    @Temporal( TemporalType.$column.temporalType)
+#end
+#set ($members = "")
+#if ( !$column.default || $table.generateDDLAnnotations )
+#set ($members = "name=$customizer.quote($column.name)")
+#if (!$column.insertable)
+#set ($members = "$members, insertable=false")
+#end
+#if (!$column.updateable)
+#set ($members = "$members, updatable=false")
+#end
+#end
+#if( $table.generateDDLAnnotations )
+#if ($column.unique)
+#append($members  "unique=true")
+#end
+#if (!$column.nullable)
+#append($members  "nullable=false")
+#end
+#if ($column.size > 0)
+#if ($column.numeric)
+#append($members "precision=$column.size")
+#if ($column.decimalDigits != 0 && $column.decimalDigits != -1)
+#append($members "scale=$column.decimalDigits")
+#end
+#else
+#if ( !$column.dataTypeLOB)
+#append($members "length=$column.size")
+#end
+#end
+#end
+#end
+#if( $members !="" )
+	@Column($members)
+#end
diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/join.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/join.vm
new file mode 100644
index 0000000..ece3ff4
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/join.vm
@@ -0,0 +1,61 @@
+##included template. Generates the @JoinTable, @JoinColumn or @JoinColumns annotation.
+##Assumes that the context has a "role" object representing the generated AssociationRole
+##
+##macro joinColumn uses $column, $referencedColumn
+#macro (joinColumn $column $referencedColumn)
+#set ($members = "name=$customizer.quote($column.joinColumnName)")
+#if( !$referencedColumn.primaryKey )
+#set ($members = "$members, referencedColumnName=$customizer.quote($referencedColumn.name)")
+#end
+#if( $table.generateDDLAnnotations )
+#if ($column.unique && !$column.primaryKey)
+#set ($members = "$members, unique=true")
+#end
+#if (!$column.nullable)
+#set ($members = "$members, nullable=false")
+#end
+#end
+#if (!$role.association.joinTable && !$role.referrerTable.isColumnUpdateInsert($role, $column))
+#set ($members = "$members, insertable=false, updatable=false")
+#end
+@JoinColumn($members)#end
+##
+##
+##
+#if ($role.association.joinTable)
+#set ($joinTable = $role.association.joinTable)
+	@JoinTable(
+		name="${joinTable.joinTableAnnotationName}"
+#if ($joinTable.schema!="")
+		, schema="${joinTable.schema}"
+#end
+		, joinColumns={
+#foreach ($column in $role.referrerColumns)
+#set ($referencedColumn = $role.getReferencedColumn(${column.name}))
+##$referencedColumn is the column in the join table
+			#joinColumn($referencedColumn $column),
+#end
+			}
+		, inverseJoinColumns={
+#foreach ($column in $role.referencedColumns)
+#set ($referencedColumn = $role.getReferrerColumn(${column.name}))
+##$referencedColumn is the column in the join table
+			#joinColumn($referencedColumn $column),
+#end
+			}
+		)
+#else
+#if ($role.referrerColumns.size() == 1)
+#set ($column = $role.referrerColumns.get(0))
+#set ($referencedColumn = $role.getReferencedColumn(${column.name}))
+	#joinColumn($column $referencedColumn)
+
+#else
+	@JoinColumns({
+#foreach ($column in $role.referrerColumns)
+#set ($referencedColumn = $role.getReferencedColumn(${column.name}))
+		#joinColumn($column $referencedColumn),
+#end		
+		})
+#end
+#end
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/main.java.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/main.java.vm
new file mode 100644
index 0000000..28c861c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/main.java.vm
@@ -0,0 +1,129 @@
+#if ($table.package != "")
+package ${table.package};
+#end
+import java.io.Serializable;
+import javax.persistence.*;
+
+/**
+ * The persistent class for the ${table.name} database table.
+ * 
+ */
+@Entity
+@Table(name="${table.name}")
+public class ${table.className} ${table.generateExtendsImplements()} {
+	private static final long serialVersionUID = 1L;
+#####
+##### fields
+#####
+#if ($table.compositeKey)
+#if ($table.access == "field")
+
+	@EmbeddedId
+#end
+	private ${table.compositeKeyClassName} ${table.compositeKeyPropertyName};
+#end
+#foreach ($column in $table.getSimpleColumns(true, true, false))
+#if ($table.access == "field")
+
+#parse("mappingKind.vm")
+#parse("column.vm")
+#end
+	${column.fieldScope} ${column.propertyType} ${column.propertyName};
+#end
+#foreach ($role in $table.associationRoles)
+#####
+##### field annotations
+#####
+#if ($table.access == "field")
+
+	//${role.description}
+#if ($role.cardinality == "many-to-one")
+#parse("manyToOne.vm")
+#elseif ($role.cardinality == "many-to-many")
+#parse("manyToMany.vm")
+#elseif ($role.cardinality == "one-to-many")
+#parse("oneToMany.vm")
+#elseif ($role.cardinality == "one-to-one")
+#parse("oneToOne.vm")
+#end
+#end
+#####
+##### field declaration
+#####
+#if ($role.cardinality == "many-to-one" || $role.cardinality == "one-to-one")
+#set ($propertyType = ${role.referencedTable.className})
+#elseif ($role.cardinality == "many-to-many" || $role.cardinality == "one-to-many")
+#set ($propertyType = "${role.referencedTable.defaultCollectionType}<${role.referencedTable.className}>")
+#end
+	private $propertyType $role.propertyName;
+#end
+
+    public ${table.className}() {
+    }
+#####
+##### simple properties getters and setters
+#####
+#if ($table.compositeKey)
+#if ($table.access == "property")
+
+	@EmbeddedId
+#end
+	public $table.compositeKeyClassName $customizer.propertyGetter($table.compositeKeyPropertyName)() {
+		return this.${table.compositeKeyPropertyName};
+	}
+
+	public void $customizer.propertySetter($table.compositeKeyPropertyName)($table.compositeKeyClassName $table.compositeKeyPropertyName) {
+		this.${table.compositeKeyPropertyName} = ${table.compositeKeyPropertyName};
+	}
+	
+#end
+#foreach ($column in $table.getSimpleColumns(true, true, false))
+#if ($table.access == "property")
+
+#parse("mappingKind.vm")
+#parse("column.vm")
+#end
+	$column.propertyGetScope $column.propertyType $customizer.propertyGetter($column.propertyName)() {
+		return this.${column.propertyName};
+	}
+
+	$column.propertySetScope void $customizer.propertySetter($column.propertyName)($column.propertyType $column.propertyName) {
+		this.${column.propertyName} = ${column.propertyName};
+	}
+
+#end
+#####
+##### associations getters and setters
+#####
+#foreach ($role in $table.associationRoles)
+#if ($table.access == "property")
+
+	//${role.description}
+#if ($role.cardinality == "many-to-one")
+#parse("manyToOne.vm")
+#elseif ($role.cardinality == "many-to-many")
+#parse("manyToMany.vm")
+#elseif ($role.cardinality == "one-to-many")
+#parse("oneToMany.vm")
+#elseif ($role.cardinality == "one-to-one")
+#parse("oneToOne.vm")
+#end
+#end
+##
+#if ($role.cardinality == "many-to-one" || $role.cardinality == "one-to-one")
+#set ($propertyType = $role.referencedTable.className)
+#elseif ($role.cardinality == "many-to-many" || $role.cardinality == "one-to-many")
+#set ($propertyType = "${role.referencedTable.defaultCollectionType}<${role.referencedTable.className}>")
+#end
+	public $propertyType $customizer.propertyGetter($role.propertyName)() {
+		return this.${role.propertyName};
+	}
+
+	public void ${customizer.propertySetter($role.propertyName)}($propertyType $role.propertyName) {
+		this.${role.propertyName} = $role.propertyName;
+	}
+	
+##
+#end
+##
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToMany.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToMany.vm
new file mode 100644
index 0000000..fe3bfed
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToMany.vm
@@ -0,0 +1,14 @@
+##included template. Generates the @ManyToMany annotation.
+##Assumes that the context has a "role" object representing the generated AssociationRole
+##
+#if ($role.association.bidirectional && !$role.isReferrerRole())##the owning side (either side for many-to-many)
+#set ($members = $customizer.appendAnnotation("", "mappedBy", $role.oppositeRole.propertyName, true))
+#set ($members = $customizer.appendAnnotation($members, "cascade", $customizer.genCascades($role), false))
+#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false))
+	@ManyToMany($members)
+#else
+#set ($members = $customizer.appendAnnotation("", "cascade", $customizer.genCascades($role), false))
+#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false))
+	@ManyToMany($members)
+#parse("join.vm")
+#end
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToOne.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToOne.vm
new file mode 100644
index 0000000..8253462
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToOne.vm
@@ -0,0 +1,7 @@
+##included template. Generates the @ManyToOne annotation.
+##Assumes that the context has a "role" object representing the generated AssociationRole
+##
+#set ($members = $customizer.appendAnnotation("", "cascade", $customizer.genCascades($role), false))
+#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false))
+	@ManyToOne($members)
+#parse("join.vm")
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/mappingKind.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/mappingKind.vm
new file mode 100644
index 0000000..4bc9538
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/mappingKind.vm
@@ -0,0 +1,30 @@
+##included template. Generates the @Basic, @Id, @Version annotations.
+##Assumes that the context has a "column" object
+##
+#set ($mappingKind = $column.mappingKind)
+#if ($mappingKind == "id")
+	@Id
+#set ($idGenerator = $table.idGenerator)
+#if ($idGenerator == "auto")
+#set ($generationType = "GenerationType.AUTO")
+#elseif ($idGenerator == "identity")
+#set ($generationType = "GenerationType.IDENTITY")
+#elseif ($idGenerator == "sequence")
+#set ($generationType = "GenerationType.SEQUENCE")
+#elseif ($idGenerator == "table")
+#set ($generationType = "GenerationType.TABLE")
+#else
+#set ($generationType = "")
+#end
+#if ($idGenerator == "sequence" || ($idGenerator == "auto" && $table.sequence))
+#set ($generatorName = "${table.name.toUpperCase()}_${column.propertyName.toUpperCase()}_GENERATOR")
+	@SequenceGenerator(name="$generatorName", sequenceName="$table.formattedSequence")
+	@GeneratedValue(strategy=$generationType, generator="$generatorName")
+#elseif ($generationType != "")
+	@GeneratedValue(strategy=$generationType)
+#end      
+#elseif ($mappingKind == "version")
+	@Version()
+#else
+##DEFAULT is @Basic(), no need to generate
+#end
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToMany.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToMany.vm
new file mode 100644
index 0000000..bb89d5b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToMany.vm
@@ -0,0 +1,14 @@
+##included template. Generates the @OneToMany annotation.
+##Assumes that the context has a "role" object representing the generated AssociationRole
+##
+#if ($role.association.bidirectional)
+#set ($members = $customizer.appendAnnotation("", "mappedBy", $role.oppositeRole.propertyName, true))
+#set ($members = $customizer.appendAnnotation($members, "cascade", $customizer.genCascades($role), false))
+#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false))
+	@OneToMany($members)
+#else
+#set ($members = $customizer.appendAnnotation("", "cascade", $customizer.genCascades($role), false))
+#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false))
+	@OneToMany($members)
+#parse("join.vm")
+#end
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToOne.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToOne.vm
new file mode 100644
index 0000000..862c967
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToOne.vm
@@ -0,0 +1,14 @@
+##included template. Generates the @OneToOne annotation.
+##Assumes that the context has a "role" object representing the generated AssociationRole
+##
+#if ($role.association.bidirectional && !$role.isReferrerRole())##the owning side (either side for one-to-one)
+#set ($members = $customizer.appendAnnotation("", "mappedBy", $role.oppositeRole.propertyName, true))
+#set ($members = $customizer.appendAnnotation($members, "cascade", $customizer.genCascades($role), false))
+#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false))
+	@OneToOne($members)
+#else
+#set ($members = $customizer.appendAnnotation("", "cascade", $customizer.genCascades($role), false))
+#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false))
+	@OneToOne($members)
+#parse("join.vm")
+#end
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/pk.java.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/pk.java.vm
new file mode 100644
index 0000000..780037e
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/pk.java.vm
@@ -0,0 +1,65 @@
+#if ($table.package != "")
+package ${table.package};
+#end
+import java.io.Serializable;
+import javax.persistence.*;
+
+/**
+ * The primary key class for the ${table.name} database table.
+ * 
+ */
+@Embeddable()
+public class ${table.compositeKeyClassName} implements Serializable {
+	//default serial version id, required for serializable classes.
+	private static final long serialVersionUID = 1L;
+#####
+##### fields
+#####
+#foreach ($column in $table.primaryKeyColumns)
+#if ($table.access == "field")
+
+#parse("column.vm")
+#end
+	${column.fieldScope} ${column.propertyType} ${column.propertyName};
+#end
+
+    public ${table.compositeKeyClassName}() {
+    }
+#####
+##### simple properties getters and setters
+#####
+#foreach ($column in $table.primaryKeyColumns)
+#if ($table.access == "property")
+
+#parse("column.vm")
+#end
+	$column.propertyGetScope $column.propertyType $customizer.propertyGetter($column.propertyName)() {
+		return this.${column.propertyName};
+	}
+	$column.propertySetScope void $customizer.propertySetter($column.propertyName)($column.propertyType $column.propertyName) {
+		this.${column.propertyName} = ${column.propertyName};
+	}
+#end
+##
+## equals/hashCode
+
+	public boolean equals(Object other) {
+		if (this == other) {
+			return true;
+		}
+		if (!(other instanceof ${table.compositeKeyClassName})) {
+			return false;
+		}
+		${table.compositeKeyClassName} castOther = (${table.compositeKeyClassName})other;
+		return 
+			${table.primaryKeyEqualsClause}
+
+    }
+    
+	public int hashCode() {
+		final int prime = 31;
+		int hash = 17;
+		${table.primaryKeyHashCodeClause}
+		return hash;
+    }
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.ui/META-INF/MANIFEST.MF b/jpa/plugins/org.eclipse.jpt.ui/META-INF/MANIFEST.MF
index fc22487..d1585a5 100644
--- a/jpa/plugins/org.eclipse.jpt.ui/META-INF/MANIFEST.MF
+++ b/jpa/plugins/org.eclipse.jpt.ui/META-INF/MANIFEST.MF
@@ -43,7 +43,8 @@
  org.eclipse.wst.common.project.facet.core;bundle-version="[1.3.0,2.0.0)",
  org.eclipse.wst.common.project.facet.ui;bundle-version="[1.3.0,2.0.0)",
  org.eclipse.wst.sse.ui;bundle-version="[1.1.0,1.2.0)",
- org.eclipse.wst.web.ui;bundle-version="[1.1.200,2.0.0)"
+ org.eclipse.wst.web.ui;bundle-version="[1.1.200,2.0.0)",
+ org.eclipse.gef;bundle-version="[3.5.0,4.0.0)"
 Export-Package: org.eclipse.jpt.ui,
  org.eclipse.jpt.ui.details,
  org.eclipse.jpt.ui.internal;x-internal:=true,
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add-connection.gif b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add-connection.gif
new file mode 100644
index 0000000..864034f
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add-connection.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add.png
new file mode 100644
index 0000000..6bd3486
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse-mini.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse-mini.png
new file mode 100644
index 0000000..1f64f24
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse-mini.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse.png
new file mode 100644
index 0000000..8081fd9
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/collapse-all.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/collapse-all.png
new file mode 100644
index 0000000..3582d18
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/collapse-all.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/delete.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/delete.png
new file mode 100644
index 0000000..afba8b4
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/delete.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/deselect-all.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/deselect-all.png
new file mode 100644
index 0000000..49544f5
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/deselect-all.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/dot.gif b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/dot.gif
new file mode 100644
index 0000000..57a514d
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/dot.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/edit.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/edit.png
new file mode 100644
index 0000000..306d6a1
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/edit.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/expand-all.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/expand-all.png
new file mode 100644
index 0000000..db729a3
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/expand-all.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/list-of-values.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/list-of-values.png
new file mode 100644
index 0000000..8081fd9
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/list-of-values.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-down.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-down.png
new file mode 100644
index 0000000..f6e5281
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-down.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-up.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-up.png
new file mode 100644
index 0000000..7c8b1cc
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-up.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/reconnect.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/reconnect.png
new file mode 100644
index 0000000..df00946
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/reconnect.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/restore-defaults.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/restore-defaults.png
new file mode 100644
index 0000000..2d74ae4
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/restore-defaults.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/select-all.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/select-all.png
new file mode 100644
index 0000000..4eaff2b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/select-all.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/warningstd.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/warningstd.png
new file mode 100644
index 0000000..a7b471c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/warningstd.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img-hover.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img-hover.png
new file mode 100644
index 0000000..0751b32
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img-hover.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img.png
new file mode 100644
index 0000000..5fb4dc2
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_left_bg.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_left_bg.png
new file mode 100644
index 0000000..abfffe4
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_left_bg.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_mid_bg.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_mid_bg.png
new file mode 100644
index 0000000..caa828d
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_mid_bg.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_right_bg.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_right_bg.png
new file mode 100644
index 0000000..bd74144
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_right_bg.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print-hover.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print-hover.png
new file mode 100644
index 0000000..468a09b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print-hover.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print.png
new file mode 100644
index 0000000..ee15ba1
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-bottom.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-bottom.png
new file mode 100644
index 0000000..d84b339
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-bottom.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-left.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-left.png
new file mode 100644
index 0000000..fa25df3
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-left.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-right.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-right.png
new file mode 100644
index 0000000..a58c953
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-right.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-side.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-side.png
new file mode 100644
index 0000000..585ed6a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-side.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-upper-right.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-upper-right.png
new file mode 100644
index 0000000..ccabb96
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-upper-right.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/toolbar_bg.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/toolbar_bg.png
new file mode 100644
index 0000000..c483a49
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/toolbar_bg.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/column.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/column.gif
new file mode 100644
index 0000000..5f1551b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/column.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/columnKey.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/columnKey.gif
new file mode 100644
index 0000000..4f38515
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/columnKey.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/file.png b/jpa/plugins/org.eclipse.jpt.ui/images/objects/file.png
new file mode 100644
index 0000000..f5c1810
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/file.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/folder.png b/jpa/plugins/org.eclipse.jpt.ui/images/objects/folder.png
new file mode 100644
index 0000000..9759da4
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/folder.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/forward.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/forward.gif
new file mode 100644
index 0000000..562bd70
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/forward.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/moveRight.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/moveRight.gif
new file mode 100644
index 0000000..7a1511d
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/moveRight.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/package.png b/jpa/plugins/org.eclipse.jpt.ui/images/objects/package.png
new file mode 100644
index 0000000..471cc43
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/package.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/table.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/table.gif
new file mode 100644
index 0000000..a99388a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/table.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/table_obj.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/table_obj.gif
new file mode 100644
index 0000000..e2ccabb
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/table_obj.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/overlays/error.gif b/jpa/plugins/org.eclipse.jpt.ui/images/overlays/error.gif
new file mode 100644
index 0000000..119dccc
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/overlays/error.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/overlays/warning.png b/jpa/plugins/org.eclipse.jpt.ui/images/overlays/warning.png
new file mode 100644
index 0000000..8c1e86c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/overlays/warning.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/save-image-16.png b/jpa/plugins/org.eclipse.jpt.ui/images/save-image-16.png
new file mode 100644
index 0000000..eca4774
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/images/save-image-16.png
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.ui/plugin.properties b/jpa/plugins/org.eclipse.jpt.ui/plugin.properties
index 377baee..18ce474 100644
--- a/jpa/plugins/org.eclipse.jpt.ui/plugin.properties
+++ b/jpa/plugins/org.eclipse.jpt.ui/plugin.properties
@@ -33,6 +33,8 @@
 newJpaEntityWizardDesc = Create a JPA Entity 
 newJpaMappingFileWizardName = Mapping File
 newJpaMappingFileWizardDesc = Create a JPA Mapping File
+newJpaEntityFromTableWizardName = Entities From Tables
+newJpaEntityFromTableWizardDesc = Create JPA Entities from database tables 
 
 jpaStructureViewCommandCategory = JPA Structure View
 addPersistentClass = Add Class ...
diff --git a/jpa/plugins/org.eclipse.jpt.ui/plugin.xml b/jpa/plugins/org.eclipse.jpt.ui/plugin.xml
index 3d6f7ab..597cb1b 100644
--- a/jpa/plugins/org.eclipse.jpt.ui/plugin.xml
+++ b/jpa/plugins/org.eclipse.jpt.ui/plugin.xml
@@ -541,6 +541,30 @@
 			
 			-->
 			
+			<commonWizard
+				menuGroupId="org.eclipse.jpt.ui"
+				type="new"
+				wizardId="org.eclipse.jpt.ui.wizard.newEntitiesFromTables">
+				<enablement>
+					<and>
+						<or>
+							<instanceof
+								value="org.eclipse.core.resources.IProject"/>
+							<instanceof
+								value="org.eclipse.jdt.core.IPackageFragment"/>
+							<instanceof
+								value="org.eclipse.jdt.core.IPackageFragmentRoot"/>
+						</or>
+						<adapt type="org.eclipse.core.resources.IResource">
+							<test 
+								forcePluginActivation="true"
+								property="org.eclipse.wst.common.project.facet.core.projectFacet"
+								value="jpt.jpa" />
+						</adapt>
+					</and>
+				</enablement>
+			</commonWizard>			
+			
 		</navigatorContent>
 		
 	</extension>
@@ -581,6 +605,16 @@
 		</wizard>
 		
 		<wizard
+	        category="org.eclipse.jpt"
+	        class="org.eclipse.jpt.ui.internal.wizards.gen.GenerateEntitiesFromSchemaWizard"
+	        icon="platform:/plugin/org.eclipse.jpt.ui/icons/full/etool16/new_entity_wiz.gif"
+	        id="org.eclipse.jpt.ui.wizard.newEntitiesFromTables"
+	        name="%newJpaEntityFromTableWizardName">
+	 			<description>%newJpaEntityFromTableWizardDesc</description>
+           <selection class="org.eclipse.core.resources.IResource"/> 
+        </wizard>		
+		
+		<wizard
             id="org.eclipse.jpt.ui.wizard.newMappingFile"
 			name="%newJpaMappingFileWizardName"
 			icon="icons/full/etool16/new_jpa_file_wiz.gif"
diff --git a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_entity_gen.properties b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_entity_gen.properties
new file mode 100644
index 0000000..9b8c42a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_entity_gen.properties
@@ -0,0 +1,128 @@
+###############################################################################
+# Copyright (c) 2006, 2008 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
+############################################################################### 
+
+cardinality=Car&dinality:
+property=P&roperty:
+cascade=&Cascade:
+databaseSettings=Database Settings
+connection=&Connection:
+schema=&Schema:
+schemaInfo=(Note: You must have an active connection to select schema.)
+addConnectionLink=Add connections...
+reconnectLink=Reconnect...
+connectLink=Connect
+connectingMessage=Connecting...
+manyToOne=&Many to one
+manyToMany=Man&y to many
+oneToMany=&One to many
+oneToOne=&One to one
+manyToOneDesc=Each %s has many %s.
+oneToOneDesc=There is one %s per %s.
+manyToManyDesc=Each %s has many %s, and each %s has many %s.
+
+add=&Add
+remove=&Remove
+browse=B&rowse...
+
+showInSchemaViewer=Show in Schema Viewer
+showInEntityEditor=Show in Entity Relationship Editor
+
+GenerateEntitiesWizard_generateEntities=Generate Custom Entities
+
+GenerateEntitiesWizard_selectJPAProject=JPA Project Selection
+GenerateEntitiesWizard_selectJPAProject_msg=Select a JPA project.
+GenerateEntitiesWizard_selectJPAProject_label=JPA projects in the workspace:
+
+GenerateEntitiesWizard_tableSelectPage_selectTable=Select Tables
+GenerateEntitiesWizard_tableSelectPage_chooseEntityTable=Select tables to generate entities from.
+GenerateEntitiesWizard_tableSelectPage_synchronizeClasses=Synchronize classes listed in persistence.xml
+GenerateEntitiesWizard_tableSelectPage_copyJdbcDrive = Add JDBC driver to project classpath
+GenerateEntitiesWizard_tableSelectPage_tables=&Tables:
+GenerateEntitiesWizard_tableSelectPage_tableColumn=Table
+
+GenerateEntitiesWizard_assocPage_title=Table Associations
+GenerateEntitiesWizard_assocPage_label=Table &associations
+GenerateEntitiesWizard_assocPage_desc=Edit a table association by selecting it and modifying the controls in the editing panel.
+GenerateEntitiesWizard_assocPage_newAssoc=New Association
+GenerateEntitiesWizard_assocPage_delAssoc=Delete Selected Association
+
+
+GenerateEntitiesWizard_defaultTablePage_title=Customize Default Entity Generation
+GenerateEntitiesWizard_defaultTablePage_tableMapping=Table Mapping
+GenerateEntitiesWizard_defaultTablePage_domainJavaClass=Domain Java Class
+
+GenerateEntitiesWizard_defaultTablePage_desc=Optionally customize aspects of entities that will be generated by default from database tables. A Java package should be specified.
+GenerateEntitiesWizard_defaultTablePage_access=Entity &access:
+GenerateEntitiesWizard_defaultTablePage_fetch=Associations &fetch:
+GenerateEntitiesWizard_defaultTablePage_collType=Collection properties &type:
+GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations = Always generate optional JPA annotations and DDL parameters
+GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations_desc =  Generate optional JPA annotations and DDL parameters like 'unique', 'nullable', 'length', 'precision' and 'scale', which are optional and only used by automatic table creation to specify table creation data.
+GenerateEntitiesWizard_defaultTablePage_keyGen=Key &generator:
+GenerateEntitiesWizard_defaultTablePage_sequence=Sequence &name:
+GenerateEntitiesWizard_defaultTablePage_sequenceNote=You can use the patterns %s and/or %s in the sequence name.\n\
+			These patterns will be replaced by the table name and the primary key \n\
+			column name when a table mapping is generated.
+GenerateEntitiesWizard_defaultTablePage_package=Java Package *:
+GenerateEntitiesWizard_defaultTablePage_baseClass=Base Class:
+GenerateEntitiesWizard_defaultTablePage_interfaces=Interfaces:
+GenerateEntitiesWizard_defaultTablePage_chooseInterfaces=Choose Class Interfaces
+
+GenerateEntitiesWizard_tablesAndColumnsPage_title=Customize Individual Entities
+GenerateEntitiesWizard_tablesAndColumnsPage_desc=Customize detail of individual entities by selecting the associated tables or columns and changing values in the editing panel.
+GenerateEntitiesWizard_tablesAndColumnsPage_labelTableAndColumns=&Tables and columns
+GenerateEntitiesWizard_tablesAndColumnsPage_tableMapping=Table Mapping
+GenerateEntitiesWizard_tablesAndColumnsPage_columnMapping=Column Mapping
+
+GenerateEntitiesWizard_tablePanel_className=&Class name:
+GenerateEntitiesWizard_tablePanel_implementEq=Implement equals/hashCode
+GenerateEntitiesWizard_colPanel_genProp=Generate this property
+GenerateEntitiesWizard_colPanel_colMapping=Column mapping
+GenerateEntitiesWizard_colPanel_propName=Property &name:
+GenerateEntitiesWizard_colPanel_propType=Mapping t&ype:
+GenerateEntitiesWizard_colPanel_mapKind=Mapping &kind:
+GenerateEntitiesWizard_colPanel_beanProp=Domain Java Class
+GenerateEntitiesWizard_colPanel_getterScope=Getter Scope:
+GenerateEntitiesWizard_colPanel_setterScope=Setter Scope:
+GenerateEntitiesWizard_colPanel_colUpdateable=Column is &updatable
+GenerateEntitiesWizard_colPanel_colInsertable=Column is &insertable
+GenerateEntitiesWizard_colPanel_useInToString=Use in toString
+GenerateEntitiesWizard_colPanel_useInEquals=Use in equals/hashCode
+
+GenerateEntitiesWizard_newAssoc_title=Create New Association
+GenerateEntitiesWizard_newAssoc_exists=A similar association between %s and %s already exists.
+
+GenerateEntitiesWizard_newAssoc_tablesPage_title=Association Tables
+GenerateEntitiesWizard_newAssoc_tablesPage_desc=Specify the association tables.
+GenerateEntitiesWizard_tablesSelPage_newConn=New...
+GenerateEntitiesWizard_newAssoc_tablesPage_assocKind=Association Kind
+GenerateEntitiesWizard_newAssoc_tablesPage_assocTables=Association &tables:
+GenerateEntitiesWizard_newAssoc_tablesPage_table1=Table &1:
+GenerateEntitiesWizard_newAssoc_tablesPage_table2=Table &2:
+GenerateEntitiesWizard_newAssoc_tablesPage_intermediateTable=Join Table:
+GenerateEntitiesWizard_newAssoc_tablesPage_simpleAssoc=&Simple association
+GenerateEntitiesWizard_newAssoc_tablesPage_m2mAssoc=&Many to many association
+
+GenerateEntitiesWizard_newAssoc_cardinalityPage_title=Association Cardinality
+GenerateEntitiesWizard_newAssoc_cardinalityPage_desc=Specify the association cardinality.
+
+GenerateEntitiesWizard_newAssoc_colsPage_title=Join Columns
+GenerateEntitiesWizard_newAssoc_colsPage_desc=Specify the join columns.
+GenerateEntitiesWizard_newAssoc_colsPage_label=Specify the join columns between the %s and %s tables:
+
+GenerateEntitiesWizard_assocEditor_entityRef=Generate a reference to %s in %s
+GenerateEntitiesWizard_assocEditor_setRef=Generate a reference to a collection of %s in %s
+GenerateEntitiesWizard_assocEditor_tableJoin=Table &join:
+GenerateEntitiesWizard_assocEditor_joinedWhen=The table rows are joined when:\n%s
+GenerateEntitiesWizard_assocEditor_genAssoc=Generate &this association
+GenerateEntitiesWizard_fileWillBeOverwritten = Note that the generated .java files will *overwrite* existing files with the same name.
+GenerateEntitiesWizard_doNotShowWarning = Don't show me this warning again
+
+GenerateEntitiesWizard_inconsistentConn=The selected connection url is different than the connection url specified in the "%s" file .
+
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/CommonImages.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/CommonImages.java
new file mode 100644
index 0000000..a0980ff
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/CommonImages.java
@@ -0,0 +1,101 @@
+package org.eclipse.jpt.ui;
+
+import static org.eclipse.jpt.ui.JptUiPlugin.PLUGIN_ID;
+import static org.eclipse.ui.plugin.AbstractUIPlugin.imageDescriptorFromPlugin;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+
+public final class CommonImages
+{
+    public static final ImageDescriptor DESC_OVERLAY_ERROR
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/overlays/error.gif" ); //$NON-NLS-1$
+
+    public static final ImageDescriptor DESC_OVERLAY_WARNING
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/overlays/warning.png" ); //$NON-NLS-1$
+
+    public static final ImageDescriptor DESC_BUTTON_ADD 
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/add.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_EDIT 
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/edit.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_DELETE 
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/delete.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_MOVE_UP 
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/move-up.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_MOVE_DOWN 
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/move-down.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_EXPAND_ALL 
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/expand-all.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_COLLAPSE_ALL 
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/collapse-all.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_RESTORE_DEFAULTS 
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/restore-defaults.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_BROWSE
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/browse.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_BROWSE_MINI
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/browse-mini.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_BUTTON_SELECT_ALL
+    	= imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/select-all.png" ); //$NON-NLS-1$
+
+    public static final ImageDescriptor DESC_BUTTON_DESELECT_ALL
+		= imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/deselect-all.png" ); //$NON-NLS-1$
+
+    public static final ImageDescriptor DESC_OBJECT_FILE
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/file.png" ); //$NON-NLS-1$
+
+    public static final ImageDescriptor DESC_OBJECT_FOLDER
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/folder.png" ); //$NON-NLS-1$
+    
+    public static final ImageDescriptor DESC_OBJECT_PACKAGE
+        = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/package.png" ); //$NON-NLS-1$
+
+    private static Map<ImageDescriptor,Image> cache = new HashMap<ImageDescriptor,Image>();
+
+	public static ImageDescriptor ADD_CONNECTION_IMAGE
+    	= imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/add-connection.gif" ); //$NON-NLS-1$
+
+	public static ImageDescriptor RECONNECT_IMAGE
+		= imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/reconnect.png" ); //$NON-NLS-1$
+
+	public static ImageDescriptor TABLE_IMAGE
+		= imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/table.gif" ); //$NON-NLS-1$
+    
+	public static ImageDescriptor TABLE_OBJ_IMAGE
+		= imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/table_obj.gif" ); //$NON-NLS-1$
+
+	public static ImageDescriptor COLUMN_IMAGE
+		= imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/column.gif" ); //$NON-NLS-1$
+	
+	public static ImageDescriptor COLUMN_KEY_IMAGE
+		= imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/columnKey.gif" ); //$NON-NLS-1$
+	
+    public static Image createImage( final ImageDescriptor descriptor )
+    {
+        synchronized( cache )
+        {
+            Image image = cache.get( descriptor );
+            
+            if( image == null )
+            {
+                image = descriptor.createImage();
+                cache.put( descriptor, image );
+            }
+            
+            return image;
+        }
+    }
+    
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/TestJunk.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/TestJunk.java
new file mode 100644
index 0000000..3014877
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/TestJunk.java
@@ -0,0 +1,59 @@
+package org.eclipse.jpt.ui;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.core.MappingKeys;
+import org.eclipse.jpt.core.context.PersistentType;
+import org.eclipse.jpt.core.context.persistence.ClassRef;
+import org.eclipse.jpt.core.context.persistence.PersistenceUnit;
+import org.eclipse.jpt.core.internal.context.GenericRootContextNode;
+
+public class TestJunk {
+	
+//	 public static List<PersistentType> entities(JpaProject jpaProject) {
+//	       List<PersistentType> entities = new ArrayList<PersistentType>();
+//	       //this is a place where our provisional api needs to change, I
+//	//had to cast to an internal class.
+//	     
+//	       //You'll want null checks in here in cases of persistence.xml
+//	//file not being complete
+//	       //Also, we only support 1 persistenceUnit in the implementation,
+//	//you should verify there is at least one
+//	       PersistenceUnit persistenceUnit =
+//	rootContext.persistenceXml().getPersistence().persistenceUnits().next();
+//	     
+//	       for (Iterator<ClassRef> classRefs = persistenceUnit.classRefs();
+//	classRefs.hasNext();) {
+//	           ClassRef classRef = classRefs.next();
+//	           if (classRef.getJavaPersistentType() != null) { //null if
+////	there is no java class with this name)
+//	               if (classRef.getJavaPersistentType().mappingKey() ==
+//	MappingKeys.ENTITY_TYPE_MAPPING_KEY) {
+//	                   entities.add(classRef.getJavaPersistentType());
+//	               }
+//	           }
+//	       }
+//	       //to get entities from orm.xml files
+////	        for (Iterator<MappingFileRef> mappingFiles =
+////	persistenceUnit.mappingFileRefs(); mappingFiles.hasNext();) {
+////	            MappingFileRef mappingFileRef = mappingFiles.next();
+////	            //null checks needed here for OrmXml as well as EntityMappings
+////	            EntityMappings entityMappings =
+////	mappingFileRef.getOrmXml().getEntityMappings();
+////	            for (Iterator<OrmPersistentType> persistentTypes =
+////	entityMappings.ormPersistentTypes(); persistentTypes.hasNext();) {
+////	                OrmPersistentType ormPersistentType =
+////	persistentTypes.next();
+////	                if (ormPersistentType.mappingKey() ==
+////	MappingKeys.ENTITY_TYPE_MAPPING_KEY) {
+////	                    entities.add(ormPersistentType);
+////	                }
+////	            }
+////	        }
+//	     
+//	       return entities;
+//	   }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/BaseJpaPlatformUi.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/BaseJpaPlatformUi.java
index 20bd1c2..4b024f6 100644
--- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/BaseJpaPlatformUi.java
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/BaseJpaPlatformUi.java
@@ -284,7 +284,8 @@
 	// ********** entity generation **********
 
 	public void generateEntities(JpaProject project, IStructuredSelection selection) {
-		EntitiesGenerator.generate(project, selection);
+		//EntitiesGenerator.generate(project, selection);
+		EntitiesGenerator2.generate(project, selection);
 	}
 
 
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator2.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator2.java
new file mode 100644
index 0000000..5eb9f0e
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator2.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.platform.base;
+
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.ui.internal.JptUiMessages;
+import org.eclipse.jpt.ui.internal.wizards.gen.GenerateEntitiesFromSchemaWizard;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ *  EntitiesGenerator
+ */
+public class EntitiesGenerator2 {
+	private JpaProject project;
+	private IStructuredSelection selection;
+
+	public static void generate(JpaProject project, IStructuredSelection selection) {
+		new EntitiesGenerator2(project, selection).generate();
+	}
+	
+	private EntitiesGenerator2(JpaProject project, IStructuredSelection selection) {
+		super();
+		if (project == null) {
+			throw new NullPointerException();
+		}
+		this.project = project;
+		this.selection = selection;
+	}
+
+
+	// ********** generate **********
+
+	/**
+	 * prompt the user with a wizard;
+	 * schedule a job to generate the entities;
+	 * optionally schedule a job to synchronize persistence.xml to
+	 * run afterwards
+	 */
+	protected void generate() {
+		GenerateEntitiesFromSchemaWizard wizard = new GenerateEntitiesFromSchemaWizard(this.project, this.selection);
+		WizardDialog dialog = new WizardDialog(this.getCurrentShell(), wizard);
+		dialog.create();
+		int returnCode = dialog.open();
+		if (returnCode != Window.OK) {
+			return;
+		}
+		//Entities generation happens in the GenerateEntitiesFromSchemaWizard.performFinish()
+		//method
+	}
+	
+	private Shell getCurrentShell() {
+	    return Display.getCurrent().getActiveShell();
+	}
+
+	// ********** overwrite confirmer **********
+
+	static class OverwriteConfirmer implements org.eclipse.jpt.gen.internal2.OverwriteConfirmer {
+		private Shell shell;
+		private boolean overwriteAll = false;
+		private boolean skipAll = false;
+
+		OverwriteConfirmer(Shell shell) {
+			super();
+			this.shell = shell;
+		}
+
+		public boolean overwrite(final String className) {
+			if (this.overwriteAll) {
+				return true;
+			}
+			if (this.skipAll) {
+				return false;
+			}
+			return this.promptUser(className);
+		}
+
+		private boolean promptUser(String className) {
+			final OverwriteConfirmerDialog dialog = new OverwriteConfirmerDialog(this.shell, className);
+			// get on the UI thread synchronously, need feedback before continuing
+			this.shell.getDisplay().syncExec(new Runnable() {
+				public void run() {
+					dialog.open();
+				}
+			});
+			if (dialog.getReturnCode() == Window.CANCEL) {
+				throw new OperationCanceledException();
+			}
+			if (dialog.yes()) {
+				return true;
+			}
+			if (dialog.yesToAll()) {
+				this.overwriteAll = true;
+				return true;
+			}
+			if (dialog.no()) {
+				return false;
+			}
+			if (dialog.noToAll()) {
+				this.skipAll = true;
+				return false;
+			}
+			throw new IllegalStateException();
+		}
+
+	}
+
+
+	// ********** overwrite dialog **********
+
+	static class OverwriteConfirmerDialog extends Dialog {
+		private final String className;
+		private boolean yes = false;
+		private boolean yesToAll = false;
+		private boolean no = false;
+		private boolean noToAll = false;
+
+		OverwriteConfirmerDialog(Shell parent, String className) {
+			super(parent);
+			this.className = className;
+		}
+
+		@Override
+		protected void configureShell(Shell shell) {
+			super.configureShell(shell);
+			shell.setText(JptUiMessages.OverwriteConfirmerDialog_title);
+		}
+
+		@Override
+		protected Control createDialogArea(Composite parent) {
+			Composite composite = (Composite) super.createDialogArea(parent);
+			GridLayout gridLayout = (GridLayout) composite.getLayout();
+			gridLayout.numColumns = 2;
+
+			Label text = new Label(composite, SWT.LEFT);
+			text.setText(NLS.bind(JptUiMessages.OverwriteConfirmerDialog_text, this.className));
+			text.setLayoutData(new GridData());
+			
+			return composite;
+		}
+
+		@Override
+		protected void createButtonsForButtonBar(Composite parent) {
+			this.createButton(parent, IDialogConstants.YES_ID, IDialogConstants.YES_LABEL, false);
+			this.createButton(parent, IDialogConstants.YES_TO_ALL_ID, IDialogConstants.YES_TO_ALL_LABEL, false);
+			this.createButton(parent, IDialogConstants.NO_ID, IDialogConstants.NO_LABEL, true);
+			this.createButton(parent, IDialogConstants.NO_TO_ALL_ID, IDialogConstants.NO_TO_ALL_LABEL, false);
+			this.createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+		}
+
+		@Override
+		protected void buttonPressed(int buttonId) {
+			switch (buttonId) {
+				case IDialogConstants.YES_ID :
+					this.yesPressed();
+					break;
+				case IDialogConstants.YES_TO_ALL_ID :
+					this.yesToAllPressed();
+					break;
+				case IDialogConstants.NO_ID :
+					this.noPressed();
+					break;
+				case IDialogConstants.NO_TO_ALL_ID :
+					this.noToAllPressed();
+					break;
+				case IDialogConstants.CANCEL_ID :
+					this.cancelPressed();
+					break;
+				default :
+					break;
+			}
+		}
+
+		private void yesPressed() {
+			this.yes = true;
+			this.setReturnCode(OK);
+			this.close();
+		}
+
+		private void yesToAllPressed() {
+			this.yesToAll = true;
+			this.setReturnCode(OK);
+			this.close();
+		}
+
+		private void noPressed() {
+			this.no = true;
+			this.setReturnCode(OK);
+			this.close();
+		}
+
+		private void noToAllPressed() {
+			this.noToAll = true;
+			this.setReturnCode(OK);
+			this.close();
+		}
+
+		boolean yes() {
+			return this.yes;
+		}
+
+		boolean yesToAll() {
+			return this.yesToAll;
+		}
+
+		boolean no() {
+			return this.no;
+		}
+
+		boolean noToAll() {
+			return this.noToAll;
+		}
+	}
+
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationFigure.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationFigure.java
new file mode 100644
index 0000000..7c3ecba
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationFigure.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import org.eclipse.draw2d.Button;
+import org.eclipse.draw2d.ChopboxAnchor;
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.ConnectionEndpointLocator;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.PolygonDecoration;
+import org.eclipse.draw2d.PolylineConnection;
+import org.eclipse.draw2d.XYLayout;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.jpt.gen.internal2.Association;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+
+
+class AssociationFigure extends Button {
+	
+	Color enabledColor = new Color( null, 14,66,115);
+	Color disabledLineColor = new Color( null, 192,215,231);
+	Color selectedColor = new Color( null, 232,232,232 );
+
+	Color selectedBorderColor = new Color( null, 14,66,115 );
+	LineBorder selectedBorder = new LineBorder( selectedBorderColor, 2 );
+	LineBorder unselectedBorder = new LineBorder( ColorConstants.lightGray, 1 );
+	Font descriptionFont = new Font(null, "Arial", 8, SWT.NONE);
+	
+	/**
+	 * The model behind the the view object
+	 */
+	Association association;
+	TableFigure tableFig1;
+	TableFigure tableFig2;
+	PolylineConnection connection ;
+	
+	PolygonDecoration referrerDecoration ;	
+	PolygonDecoration referencedDecoration ;
+
+	Label referencedLabel ;
+	Label referrerLabel ;
+	Label descriptionLabel ;
+	
+	AssociationFigure(Association association) {
+		this.association = association;
+		
+		XYLayout contentsLayout = new XYLayout();
+		setLayoutManager(contentsLayout);
+		setBorder( unselectedBorder );
+
+		//Create the figures for referrer table and referenced table
+		tableFig1 = new TableFigure( association.getReferrerTable().getName() ); 
+		tableFig2 = new TableFigure( association.getReferencedTable().getName() ); 
+		
+		contentsLayout.setConstraint(tableFig1, new Rectangle(10,10,150,20));
+		contentsLayout.setConstraint(tableFig2, new Rectangle(280, 10, 150, 20));
+
+		connection = drawConnection(tableFig1, tableFig2);
+
+		add(tableFig1);
+		add(tableFig2);
+		add(connection);
+		
+
+		descriptionLabel = new Label("");
+		contentsLayout.setConstraint(descriptionLabel, new Rectangle(10,30,-1,-1));
+		descriptionLabel.setFont( descriptionFont ); 
+		add(descriptionLabel);
+
+		//set white background
+		this.setBackgroundColor(ColorConstants.white);
+		
+		update();
+		
+	}
+
+	private PolylineConnection drawConnection(TableFigure tableFig1,
+			TableFigure tableFig2) {
+		/* Creating the connection */
+		PolylineConnection connection = new PolylineConnection();
+		ChopboxAnchor sourceAnchor = new ChopboxAnchor(tableFig1);
+		ChopboxAnchor targetAnchor = new ChopboxAnchor(tableFig2);
+		connection.setSourceAnchor(sourceAnchor);
+		connection.setTargetAnchor(targetAnchor);
+		
+		/* Creating the decoration */
+		referrerDecoration = new SmoothPolygonDecoration();
+		connection.setSourceDecoration(referrerDecoration);
+
+		referencedDecoration = new SmoothPolygonDecoration();
+		connection.setTargetDecoration(referencedDecoration);
+		
+		
+		/* Adding labels to the connection */
+		ConnectionEndpointLocator sourceEndpointLocator = 
+			new ConnectionEndpointLocator(connection, false);
+		sourceEndpointLocator.setVDistance(-5);
+		referrerLabel = new Label("");
+		connection.add(referrerLabel, sourceEndpointLocator);
+
+		ConnectionEndpointLocator targetEndpointLocator = 
+		        new ConnectionEndpointLocator(connection, true);
+		targetEndpointLocator.setVDistance(-5);
+		referencedLabel = new Label("");
+		connection.add(referencedLabel, targetEndpointLocator);
+
+		ConnectionEndpointLocator relationshipLocator = 
+			new ConnectionEndpointLocator(connection,true);
+		relationshipLocator.setUDistance(10);
+		relationshipLocator.setVDistance(-20);
+		Label relationshipLabel = new Label("contains");
+		connection.add(relationshipLabel,relationshipLocator);
+		return connection;
+	}
+
+	public Association getAssociation() {
+		return this.association;
+	} 
+	
+	public void setSelected ( boolean isSelected ){
+		this.setBackgroundColor( isSelected ? selectedColor : ColorConstants.white );
+		this.setBorder(isSelected? selectedBorder : unselectedBorder);
+	}
+	
+	/**
+	 * Update the view with the changes user made on the model
+	 */
+	public void update(){
+		boolean isGenerated = association.isGenerated();
+		
+		connection.setForegroundColor( isGenerated? enabledColor: disabledLineColor );
+		
+		tableFig1.setEnabled(isGenerated);
+		tableFig2.setEnabled(isGenerated);
+		descriptionLabel.setForegroundColor(isGenerated? enabledColor: disabledLineColor);
+
+		//paintDirectionalityAndCardinality 
+		String cardinalityStr;
+		String directionality = association.getDirectionality();
+		String cardinality = association.getCardinality();
+		//Draw referrerRole
+		if (cardinality.equals(Association.MANY_TO_ONE) || cardinality.equals(Association.MANY_TO_MANY)) {
+			cardinalityStr = "*";
+		} else {
+			cardinalityStr = "1";
+		}
+		if (directionality.equals(Association.BI_DI) || directionality.equals(Association.OPPOSITE_DI)) {
+			connection.setSourceDecoration(this.referrerDecoration);
+		}else{
+			connection.setSourceDecoration(null);
+		}
+		
+		this.referrerLabel.setText( cardinalityStr );
+			
+		//Draw referencedRole
+		if (cardinality.equals(Association.MANY_TO_ONE) || cardinality.equals(Association.ONE_TO_ONE)) {
+			cardinalityStr = "1";
+		} else {
+			cardinalityStr = "*";
+		}
+		if (directionality.equals(Association.BI_DI) || directionality.equals(Association.NORMAL_DI)) {
+			connection.setTargetDecoration(this.referencedDecoration);
+		}else{
+			connection.setTargetDecoration(null);
+		}
+		this.referencedLabel.setText(cardinalityStr);
+		
+		String text = "";
+		String referrerTableName = association.getReferrerTableName();
+		String referencedTable = association.getReferencedTableName();
+		if( cardinality.equals(Association.MANY_TO_ONE ) ){
+			text = String.format( JptUiEntityGenMessages.manyToOneDesc, referencedTable , referrerTableName ); 
+		}else if( cardinality.equals(Association.ONE_TO_ONE ) ){
+			text = String.format( JptUiEntityGenMessages.oneToOneDesc, referrerTableName, referencedTable );
+		}else if( cardinality.equals(Association.MANY_TO_MANY) ){
+			text = String.format( JptUiEntityGenMessages.manyToManyDesc, referrerTableName, referencedTable, referencedTable, referrerTableName );			
+		}
+		
+		if( association.isCustom() ){
+			connection.setLineStyle( SWT.LINE_DOT);
+		}
+		
+		this.descriptionLabel.setText(text);
+		
+	}
+	
+	public class SmoothPolygonDecoration extends PolygonDecoration
+	{
+		public SmoothPolygonDecoration()
+		{
+			super();
+		}
+		
+		@Override
+		public void paintFigure(Graphics graphics)
+		{
+			int savedAntialias = graphics.getAntialias();
+			graphics.setAntialias(SWT.ON);
+			super.paintFigure(graphics);
+			graphics.setAntialias(savedAntialias);
+		}
+	}
+} 
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationTablesPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationTablesPage.java
new file mode 100644
index 0000000..e4d690d
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationTablesPage.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.createButton;
+import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.createLabel;
+import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.createText;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jpt.gen.internal2.Association;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+import org.eclipse.jpt.ui.CommonImages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Text;
+
+
+
+public class AssociationTablesPage extends NewAssociationWizardPage {
+
+	private Button simpleAssoBtn;
+	private Button mtmAssoBtn; 
+	private Text table1TextField ;
+	private Text table2TextField ;
+	private Text joinTableTextField; 
+	private Button joinTableBrowse;
+	
+	public AssociationTablesPage(ORMGenCustomizer customizer) {
+		super(customizer,  "AssociationTablesPage");
+		setTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_title);
+		setDescription(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_desc);
+	}
+
+	public void createControl(Composite composite) {
+		initializeDialogUnits(composite);
+		Composite parent = new Composite(composite, SWT.NONE);
+		parent.setLayout(new GridLayout(1, true));
+		
+		Group assocKindGroup = new Group(parent, SWT.NULL);
+		int nColumns= 3 ;
+		GridLayout layout = new GridLayout();
+		layout.numColumns = nColumns;
+		assocKindGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		assocKindGroup.setLayout(layout);
+		//PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES);
+		assocKindGroup.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_assocKind);
+
+		simpleAssoBtn = createButton(assocKindGroup, 3, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_simpleAssoc, SWT.RADIO);
+		mtmAssoBtn = createButton(assocKindGroup, 3, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_m2mAssoc, SWT.RADIO);
+
+		
+		Group assocTablesGroup = new Group(parent, SWT.NULL);
+		nColumns= 3 ;
+		layout = new GridLayout();
+		layout.numColumns = nColumns;
+		assocTablesGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		assocTablesGroup.setLayout(layout);
+		
+		
+		assocTablesGroup.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_assocTables );
+		
+		createLabel(assocTablesGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_table1);
+		table1TextField = createText(assocTablesGroup, 1);
+		
+		Button browser1 = createButton(assocTablesGroup, 1, "", SWT.NONE);
+		browser1.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE )); 
+
+		browser1.addSelectionListener(new SelectionListener(){
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				SelectTableDialog dlg = new SelectTableDialog( Display.getDefault().getActiveShell(), customizer.getTableNames() );
+				if( dlg.open() ==Dialog.OK ){
+					table1TextField.setText( dlg.getSelectedTable() );
+					getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_REFERRER_TABLE, table1TextField.getText());
+					getWizard().getContainer().updateButtons();
+					((NewAssociationWizard)getWizard()).updateTableNames();
+				}
+			}
+		});
+
+		createLabel(assocTablesGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_table2);
+		table2TextField = createText(assocTablesGroup, 1);
+		
+		Button browser2 = createButton(assocTablesGroup, 1, "", SWT.NONE);
+		browser2.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE )); 
+
+		browser2.addSelectionListener(new SelectionListener(){
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				SelectTableDialog dlg = new SelectTableDialog( Display.getDefault().getActiveShell(), customizer.getSchema() );
+				if( dlg.open() == Dialog.OK){
+					table2TextField.setText( dlg.getSelectedTable() );
+					getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_REFERENCED_TABLE, table2TextField.getText());
+					((NewAssociationWizard)getWizard()).updateTableNames();
+				}
+				updatePageComplete();
+			}
+		});
+		
+		createLabel(assocTablesGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_assocTables );
+		joinTableTextField = createText(assocTablesGroup, 1);
+		joinTableTextField.setEnabled(false);
+
+		joinTableBrowse = createButton(assocTablesGroup, 1, "", SWT.NONE);
+		joinTableBrowse.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE )); 
+		joinTableBrowse.setEnabled(false);
+		
+		joinTableBrowse.addSelectionListener(new SelectionListener(){
+			public void widgetDefaultSelected(SelectionEvent e) {}
+
+			public void widgetSelected(SelectionEvent e) {
+				SelectTableDialog dlg = new SelectTableDialog( Display.getDefault().getActiveShell(), customizer.getSchema() );
+				if( dlg.open() == Dialog.OK){
+					joinTableTextField.setText( dlg.getSelectedTable() );
+					getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_JOIN_TABLE, joinTableTextField.getText() );
+					((NewAssociationWizard)getWizard()).updateTableNames();
+					getWizard().getContainer().updateButtons();
+				}
+				updatePageComplete();
+			}
+		});
+		
+		setControl(parent);
+
+		simpleAssoBtn.addSelectionListener(new SelectionListener(){
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				joinTableTextField.setEnabled(false);
+				joinTableTextField.clearSelection();
+				joinTableTextField.setText("");
+				joinTableBrowse.setEnabled(false);
+				getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_ONE);
+				getWizardDataModel().remove( NewAssociationWizard.ASSOCIATION_JOIN_TABLE );
+				((NewAssociationWizard)getWizard()).updateTableNames();
+				updatePageComplete();
+			}
+			
+		});
+
+		mtmAssoBtn.addSelectionListener(new SelectionListener(){
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				joinTableTextField.setEnabled(true);
+				joinTableBrowse.setEnabled(true);
+				getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_MANY);
+				((NewAssociationWizard)getWizard()).updateTableNames();
+				updatePageComplete();
+			}
+		});		
+		
+		this.setPageComplete( false);
+		table1TextField.setFocus(); 
+	}
+
+	public boolean canFlipToNextPage() {
+		return isPageComplete();
+	}
+	
+	public void updatePageComplete() {
+		if( this.table1TextField.getText().length() <= 0){
+			setPageComplete(false);
+			return;
+		}
+		if( mtmAssoBtn.getSelection() ){
+			if( this.joinTableTextField.getText().length() <= 0 ){
+				setPageComplete(false);
+				return;
+			}
+		}
+		setPageComplete(true);
+	}
+	
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationsListComposite.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationsListComposite.java
new file mode 100644
index 0000000..ca06c33
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationsListComposite.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.List;
+
+import org.eclipse.draw2d.ActionEvent;
+import org.eclipse.draw2d.ActionListener;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.ToolbarLayout;
+import org.eclipse.jpt.gen.internal2.Association;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A Draw2d figure representing list of associations between two database tables
+ *
+ */
+public class AssociationsListComposite extends FigureCanvas {
+
+	List<Association> associations;  
+	AssociationToggleSelectionListener listener ;
+	TableAssociationsWizardPage tableAssociationsWizardPage; //the parent wizard page
+	AssociationFigure selectedAssociationFigure ;
+	
+	public AssociationsListComposite(Composite parent, TableAssociationsWizardPage tableAssociationsWizardPage){
+		super(parent);
+		this.tableAssociationsWizardPage = tableAssociationsWizardPage;
+
+		setBounds(10, 10 , 500, 200);
+		setBackground( new Color(Display.getDefault(), 255,255,255));
+		
+		Figure figure = new Figure();
+		figure.setLayoutManager(new ToolbarLayout());
+		figure.setBorder(new LineBorder(1));
+		this.listener = new AssociationToggleSelectionListener(); 
+		
+		this.setContents(figure);
+	}
+
+	@SuppressWarnings("unchecked")
+	public void updateAssociations(List<Association> associations){
+		Figure figure = (Figure)this.getContents();
+		List<AssociationFigure> associationFigures = (List<AssociationFigure>) figure.getChildren();
+		for(AssociationFigure assocFig : associationFigures){
+			assocFig.removeActionListener(listener);
+		}
+		figure.removeAll();
+		this.selectedAssociationFigure = null;
+		
+		this.associations = associations;
+		if( associations != null ){
+			for( int i = 0; i <associations.size(); i ++ ){
+				Association association = associations.get(i);
+				//Hide the association from individual table to MTM tables
+				if( !association.isCustom() && !association.isGenerated()){
+					continue;
+				}
+				AssociationFigure assocFigure = new AssociationFigure(associations.get(i));
+				assocFigure.addActionListener( listener );
+				figure.add(assocFigure);
+			}
+		}
+	}
+	
+	public Association getSelectedAssociation(){
+		return this.selectedAssociationFigure.getAssociation();
+	}
+
+	@SuppressWarnings("unchecked")
+	public void updateSelectedAssociation(){
+		Figure figure = (Figure)this.getContents();
+		List<AssociationFigure> associationFigures = (List<AssociationFigure>) figure.getChildren();
+		for(AssociationFigure assocFig : associationFigures){
+			if( assocFig == this.selectedAssociationFigure){
+				assocFig.update(); 
+			}
+		}
+	}
+	
+	/**
+	 * Get the association just before the selected one in UI
+	 * @return
+	 */
+	@SuppressWarnings("unchecked")
+	public Association getPreviousAssociation(){
+		Figure figure = (Figure)this.getContents();
+		List<AssociationFigure> associationFigures = (List<AssociationFigure>) figure.getChildren();
+		AssociationFigure ret = null;
+		for(AssociationFigure assocFig : associationFigures){
+			if( assocFig.isSelected() ){
+				break; 
+			}
+			ret = assocFig;
+		}
+		return ret==null?null:ret.getAssociation();
+	}
+	
+	class AssociationToggleSelectionListener implements ActionListener {
+		public void actionPerformed(ActionEvent event) {
+			AssociationFigure figure = (AssociationFigure )event.getSource() ;
+			figure.setSelected(true);
+			Association association = figure.getAssociation();
+			tableAssociationsWizardPage.updateAssociationEditPanel(association);
+			//un-select the previous selected
+			if( selectedAssociationFigure != null  && selectedAssociationFigure!= figure ){
+				selectedAssociationFigure.setSelected( false );
+			}
+			//Highlight new selection
+			selectedAssociationFigure = figure;
+			selectedAssociationFigure.setSelected( true );
+			
+		}
+		
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CardinalityPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CardinalityPage.java
new file mode 100644
index 0000000..af68218
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CardinalityPage.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import org.eclipse.jpt.gen.internal2.Association;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+
+public class CardinalityPage extends NewAssociationWizardPage {
+
+	private Label mtoDescLabel;
+	private Label otmDescLabel;
+	private Label otoDescLabel;
+	private Label mtmDescLabel;
+	
+	private Button[] cardinalityButtons = new Button[4];
+	
+	protected CardinalityPage(ORMGenCustomizer customizer) {
+		super( customizer , "CardinalityPage" );
+		setTitle(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_cardinalityPage_title);
+		setDescription( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_cardinalityPage_desc);
+	}
+
+	public void createControl(Composite parent) {
+		initializeDialogUnits(parent);
+		
+		Composite composite = new Composite(parent, SWT.NULL);
+		int nColumns= 1 ;
+		GridLayout layout = new GridLayout();
+		layout.numColumns = nColumns;
+		composite.setLayout(layout);
+		//PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES);
+
+		CardinalitySelectionListener selectionListener = new CardinalitySelectionListener();
+		cardinalityButtons[0] = createRadioButton( composite, 1, JptUiEntityGenMessages.manyToOne);
+		cardinalityButtons[0].addSelectionListener( selectionListener );
+		//Default cardinality is MTO
+		cardinalityButtons[0].setSelection(true);
+		getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_ONE);		
+
+		mtoDescLabel = createLabel(composite,1, JptUiEntityGenMessages.manyToOneDesc);
+		
+		cardinalityButtons[1] = createRadioButton( composite, 1, JptUiEntityGenMessages.oneToMany);
+		cardinalityButtons[1].addSelectionListener( selectionListener );
+		
+		otmDescLabel = createLabel(composite,1, JptUiEntityGenMessages.manyToOneDesc);
+
+		cardinalityButtons[2] = createRadioButton( composite, 1, JptUiEntityGenMessages.oneToOne);
+		cardinalityButtons[2].addSelectionListener( selectionListener );
+
+		otoDescLabel = createLabel(composite,1, JptUiEntityGenMessages.oneToOneDesc);
+
+		cardinalityButtons[3] = createRadioButton( composite, 1, JptUiEntityGenMessages.manyToMany);
+		mtmDescLabel= createLabel(composite,1, JptUiEntityGenMessages.manyToManyDesc);
+		
+		setControl(composite);
+		this.setPageComplete( true );
+
+		cardinalityButtons[0].setFocus();
+
+	}
+
+	public void updateWithNewTables() {
+		String s1 = getReferrerTableName() ;
+		String s2 = getReferencedTableName() ;
+		String joinTableName = getJoinTableName();
+		if( s1 == null || s2 == null )
+			return ;
+		
+		updateDescriptionText(s1, s2);
+		if( joinTableName == null ){
+			cardinalityButtons[0].setEnabled(true);
+			cardinalityButtons[1].setEnabled(true);
+			cardinalityButtons[2].setEnabled(true);
+			cardinalityButtons[3].setEnabled(false);
+			mtmDescLabel.setEnabled(false);
+		}else{
+			cardinalityButtons[0].setEnabled(false);
+			cardinalityButtons[1].setEnabled(false);
+			cardinalityButtons[2].setEnabled(false);
+			cardinalityButtons[3].setEnabled(true);
+			cardinalityButtons[3].setSelection(true);
+			mtmDescLabel.setEnabled(true);
+		}
+		((Composite)this.getControl()).layout() ;
+	}
+
+	private void updateDescriptionText(String s1, String s2) {
+		//MTO
+		String msg = String.format(JptUiEntityGenMessages.manyToOneDesc, s2, s1);
+		mtoDescLabel.setText( msg );
+		//OTM
+		msg = String.format(JptUiEntityGenMessages.manyToOneDesc, s1, s2);
+		otmDescLabel.setText( msg );
+		msg = String.format(JptUiEntityGenMessages.oneToOneDesc, s1, s2);
+		otoDescLabel.setText( msg );
+		msg = String.format(JptUiEntityGenMessages.manyToManyDesc, s1, s2, s2, s1);
+		mtmDescLabel.setText( msg );
+	}
+
+	public boolean canFlipToNextPage() {
+		return false;
+	}
+	
+	private Label createLabel(Composite container, int span, String text) {
+		Label label = new Label(container, SWT.NONE);
+		label.setText(text);
+		GridData gd = new GridData();
+		gd.horizontalSpan = span;
+		gd.horizontalIndent = 30;
+		label.setLayoutData(gd);
+		return label;
+	}
+	
+	
+	private Button createRadioButton(Composite container, int span, String text ) {
+		Button btn = new Button(container, SWT.RADIO );
+		btn.setText(text);
+		GridData gd = new GridData();
+		gd.horizontalSpan = span;
+		btn.setLayoutData(gd);
+		return btn;
+	}
+	
+
+	private class CardinalitySelectionListener implements SelectionListener {
+		public void widgetDefaultSelected(SelectionEvent e) {}
+	
+		public void widgetSelected(SelectionEvent e) {
+			if( e.getSource() == cardinalityButtons[0]){
+				getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_ONE);
+			}else if( e.getSource() == cardinalityButtons[1]){
+				getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.ONE_TO_MANY );
+			}else if( e.getSource() == cardinalityButtons[2]){
+				getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.ONE_TO_ONE);
+			}else{
+				getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_MANY);
+			}
+			CardinalityPage.this.setPageComplete(true);
+			
+		}
+	}
+	
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CascadeDialog.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CascadeDialog.java
new file mode 100644
index 0000000..e8e76c1
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CascadeDialog.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jpt.gen.internal2.AssociationRole;
+import org.eclipse.jpt.gen.internal2.util.StringUtil;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Simple dialog allows user to set the cascade property of an associationRole.
+ * The value of cascade can be "all", or any combination of other selections.
+ * 
+ */
+public class CascadeDialog extends TrayDialog {
+
+	private static String[] ALL_CASCADES = new String[] {TagNames.ALL_CASCADE, TagNames.PERSIST_CASCADE, TagNames.MERGE_CASCADE
+			, TagNames.REMOVE_CASCADE, TagNames.REFRESH_CASCADE};
+
+	private static String[] ALL_CASCADES_LABELS 
+		= new String[] { "&all", 		//$NON-NLS-1$
+						"&persist",		//$NON-NLS-1$
+						"&merge",		//$NON-NLS-1$
+						"&remove",		//$NON-NLS-1$
+						"r&efresh"};	//$NON-NLS-1$
+
+	
+	private Button[] allButtons = new Button[ALL_CASCADES.length];
+
+	private AssociationRole associationRole;
+	private List<String> cascades;
+	
+	protected CascadeDialog(Shell parentShell) {
+		super(parentShell);
+	}
+
+	public static CascadeDialog create(AssociationRole role) {
+		CascadeDialog dlg = new CascadeDialog(Display.getDefault().getActiveShell() );
+		dlg.setAssociationRole(role);
+		return dlg;
+	}
+
+    /*
+     * (non-Javadoc) Method declared on Window.
+     */
+    protected void configureShell(Shell newShell) {
+        super.configureShell(newShell);
+        newShell.setText(JptUiEntityGenMessages.selectCascadeDlgTitle);
+    }
+	
+	private void setAssociationRole(AssociationRole role) {
+		this.associationRole = role;
+		List<String> list = StringUtil.strToList(associationRole.getCascade(), ',', true/*trim*/); //role.getCascade() contains the comma separed cascades (see below)
+		if (list == null) {
+			list = Collections.emptyList();
+		}
+		cascades = list;
+		
+	}
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+	
+	protected Control createDialogArea(Composite parent) {
+		Composite container = (Composite) super.createDialogArea(parent);
+		createCascadeTypesGroup(container);
+		Dialog.applyDialogFont(container);
+		return container;
+	}
+
+	private void createCascadeTypesGroup(Composite parent) {
+		Group group = new Group(parent, SWT.NONE);
+		group.setLayout(new GridLayout());
+		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.widthHint = 275;
+		group.setLayoutData(gd);
+		group.setText(JptUiEntityGenMessages.cascade);
+
+		for( int i=0; i< ALL_CASCADES.length; i ++ ){
+			Button checkbox = new Button(group, SWT.CHECK);
+			checkbox.setText( ALL_CASCADES_LABELS[i] );
+			checkbox.setSelection( isInList(ALL_CASCADES[i]) ); //$NON-NLS-1$
+			checkbox.setData(ALL_CASCADES[i]);
+			allButtons[i] = checkbox;
+			/*if <code>all</code> is selected then deselect all others*/
+			checkbox.addSelectionListener( new SelectionListener(){
+				public void widgetDefaultSelected(SelectionEvent e) {}
+				public void widgetSelected(SelectionEvent e) {
+					Button b = (Button)e.getSource();
+					if( b.getSelection() ){
+						if( b == allButtons[0] ){
+							for( Button btn : allButtons ){
+								if( btn != e.getSource() ) btn.setSelection(false);
+							}
+						}else{
+							allButtons[0].setSelection(false); 
+						}
+					}
+				}
+			});
+		}
+	}
+
+	protected void okPressed() {
+		StringBuilder builder = new StringBuilder();
+		for( Button b : allButtons ){
+			if( b.getSelection() ){
+				if( builder.length()>0 ){
+					builder.append( ',');
+				}
+				builder.append( b.getData() );
+			}
+		}
+		this.associationRole.setCascade( builder.toString() );
+		super.okPressed();
+	}	
+
+	private boolean isInList(String cascade) {
+		for( String s : cascades ){
+			if( s.equals(cascade )){
+				return true;
+			}
+		}
+		return false;
+	}
+
+}
+
+class TagNames
+{
+	public static final String BASIC_TAG = "basic";
+	public static final String CASCADE_TAG = "cascade";
+	public static final String COLUMN_TAG = "column";
+	public static final String EMBEDDED_TAG = "embedded";
+	public static final String EMBEDDED_ID_TAG = "embedded-id";
+	public static final String GENERATED_VALUE_TAG = "generated-value";
+	public static final String ID_TAG = "id";
+	public static final String ID_CLASS_TAG = "id";
+	public static final String JOIN_COLUMN_TAG = "join-column";
+	public static final String INVERSE_JOIN_COLUMN_TAG = "inverse-join-column";
+	public static final String LOB_TAG = "lob";
+	public static final String MANY_TO_MANY_TAG = "many-to-many";
+	public static final String MANY_TO_ONE_TAG = "many-to-one";
+	public static final String MAPPED_BY_TAG = "mapped-by";
+	public static final String ONE_TO_MANY_TAG = "one-to-many";
+	public static final String ONE_TO_ONE_TAG = "one-to-one";
+	public static final String PK_JOIN_COLUMN_TAG = "primary-key-join-column";
+	public static final String TABLE_TAG = "table";
+	public static final String VERSION_TAG = "version";
+	public static final String JOIN_TABLE_TAG = "join-table";
+
+	/*cascade tags*/
+	public static final String ALL_CASCADE = "all";
+	public static final String PERSIST_CASCADE = "persist";
+	public static final String MERGE_CASCADE = "merge";
+	public static final String REMOVE_CASCADE = "remove";
+	public static final String REFRESH_CASCADE = "refresh";
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/ColumnGenPanel.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/ColumnGenPanel.java
new file mode 100644
index 0000000..4784496
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/ColumnGenPanel.java
@@ -0,0 +1,353 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.jpt.gen.internal2.ORMGenColumn;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+import org.eclipse.jpt.ui.JptUiPlugin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * The panel used in the <code>TablesAndColumnsPage</code> wizard page 
+ * to edit the column generation properties.
+ * An instance of this class is created by the <code>ORMGenWizard</code> 
+ * implementation.
+
+ */
+public class ColumnGenPanel 
+{
+	WizardPage wizardPage ; 
+	Composite parent;	//parent control with grid layout
+	int columns; 		//total columns in the parent composite
+	
+	ORMGenCustomizer customizer;
+	
+	private ORMGenColumn mColumn;
+	private boolean mPanelInited;
+	private boolean mIsUpdatingControls;
+	
+	private Group columnMappingGroup;
+	private Button mGeneratedCheckbox;
+	private Text mPropNameField;
+	private Combo mMappingKindCombo;
+	private Combo mPropTypeCombo;
+	private Button mUpdateableCheckBox;
+	private Button mInsertableCheckBox;
+	
+	private Group domainClassGroup ;
+	private ScopePanel mPropGetScopePanel;
+	private ScopePanel mPropSetScopePanel;
+	
+	public ColumnGenPanel(Composite parent, int columns, ORMGenCustomizer customizer, WizardPage wizardPage ) {
+		this.wizardPage = wizardPage;
+		this.customizer = customizer;
+		this.parent =parent;
+		this.columns = columns;
+		
+		initPanel();
+	}
+	/**
+	 * Changes the table edited by the panel.
+	 * This is supposed to update the panel editing controls 
+	 * using the column values.
+	 */
+	public void setColumn(ORMGenColumn column) {
+		mColumn = column;
+		
+		/*lazy init panel because it uses mColumn*/
+		if (!mPanelInited) {
+			initPanel();
+			mPanelInited = true;
+		}
+		
+		updateControls();
+	}
+	private void updateControls() {
+		if (mIsUpdatingControls) {
+			return;
+		}
+		
+		mIsUpdatingControls = true;
+		boolean isGenerated = mColumn.isGenerated();
+		mGeneratedCheckbox.setSelection( isGenerated);
+
+		enableControls(isGenerated);
+		try {
+			mPropNameField.setText(mColumn.getPropertyName());
+
+			mPropTypeCombo.setText( mColumn.getPropertyType());
+			
+			mMappingKindCombo.setText( mColumn.getMappingKind());
+			
+			mUpdateableCheckBox.setSelection( mColumn.isUpdateable());
+			
+			mInsertableCheckBox.setSelection(mColumn.isInsertable());
+			
+			mPropGetScopePanel.enableComponents(isGenerated);
+			mPropGetScopePanel.setScope(mColumn.getPropertyGetScope());
+			
+			mPropSetScopePanel.enableComponents( isGenerated );
+			mPropSetScopePanel.setScope(mColumn.getPropertySetScope());
+		} catch (Exception e) {
+			JptUiPlugin.log(e);
+		}
+
+		mIsUpdatingControls = false;
+	}
+	private void enableControls(boolean isGenerated) {
+		Control[] controls = this.domainClassGroup.getChildren();
+		for( Control c: controls){
+			c.setEnabled( isGenerated );
+		}
+
+		controls = this.columnMappingGroup.getChildren();
+		for( Control c: controls){
+			c.setEnabled( isGenerated );
+		}
+	}
+	/**
+	 * Initializes the panel by adding the editing controls.
+	 * @param columns 
+	 * @param parent 
+	 */
+	protected void initPanel() {
+		createControls(parent, columns);
+		this.mPanelInited = true;
+	}
+	
+	//-------------------------------------------
+	//----- ScopePanel class --------------------
+	//-------------------------------------------
+	/**
+	 * A panel containing 3 radios (public, protected, private)
+	 */
+	private class ScopePanel 
+	{
+		private Button mPublicRadio;
+		private Button mProtectedRadio;
+		private Button mPrivateRadio;
+		
+		public ScopePanel(Composite comp, SelectionListener listener) {
+			//super(3, 20/*hspacing*/, 0/*vspacing*/);
+			
+			Composite radioGroup = new Composite( comp, SWT.NONE);
+			radioGroup.setLayout(new GridLayout(3, true));
+			GridData gd = new GridData();
+			gd.horizontalSpan = 3;
+			radioGroup.setLayoutData(gd);
+			
+			/*string not localized intentionally, they are used as the actual 
+			 * scope value (see getText() usage)*/
+			mPublicRadio = new Button( radioGroup, SWT.RADIO );
+			mPublicRadio.setText( "public");
+			mPublicRadio.setLayoutData(new GridData());
+			mProtectedRadio = new Button( radioGroup, SWT.RADIO );
+			mProtectedRadio.setText("protected");
+			mProtectedRadio.setLayoutData(new GridData());
+			mPrivateRadio = new Button(radioGroup, SWT.RADIO );
+			mPrivateRadio.setText( "private");
+			mPrivateRadio.setLayoutData(new GridData());
+			
+			mPublicRadio.addSelectionListener(listener);
+			mProtectedRadio.addSelectionListener(listener);
+			mPrivateRadio.addSelectionListener(listener);
+				
+		}
+		public void enableComponents(boolean b) {
+			mPublicRadio.setEnabled(b);
+			mProtectedRadio.setEnabled(b);
+			mPrivateRadio.setEnabled(b);
+		}
+		/**
+		 * Returns the currently selected scope.
+		 */
+		public String getScope() {
+			Button radio = null;
+			if (mPublicRadio.getSelection()) {
+				radio = mPublicRadio;
+			} else if (mProtectedRadio.getSelection() ) {
+				radio = mProtectedRadio;
+			} else if (mPrivateRadio.getSelection() ) {
+				radio = mPrivateRadio;
+			}
+			return radio != null ? radio.getText() : null;
+		}
+		public void setScope(String scope) {
+			mPublicRadio.setSelection(false);
+			mProtectedRadio.setSelection(false);
+			mPrivateRadio.setSelection(false);
+			if( scope == null )
+				return;
+			if (scope.equals(ORMGenColumn.PUBLIC_SCOPE)) {
+				mPublicRadio.setSelection(true);
+			} else if (scope.equals(ORMGenColumn.PROTECTED_SCOPE)) {
+				mProtectedRadio.setSelection(true);
+			} else if (scope.equals(ORMGenColumn.PRIVATE_SCOPE)) {
+				mPrivateRadio.setSelection(true);
+			}
+		}
+	}
+	
+	//-------------------------------------------
+	//----- private methods ---------------------
+	//-------------------------------------------
+	private void createControls(Composite composite, int columns) {
+		mGeneratedCheckbox = new Button(composite, SWT.CHECK);
+		mGeneratedCheckbox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_genProp);
+		mGeneratedCheckbox.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				if (!mIsUpdatingControls) {
+					mColumn.setGenerated(mGeneratedCheckbox.getSelection() );
+					updateControls();
+				}
+			}});
+		SWTUtil.fillColumns(mGeneratedCheckbox, columns);
+		
+		columnMappingGroup = new Group( composite, SWT.NONE);
+		columnMappingGroup.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_colMapping);
+		columnMappingGroup.setLayout(new GridLayout(columns, false));
+		GridData layoutData = new GridData();
+		layoutData.horizontalSpan = columns;
+		layoutData.verticalAlignment = SWT.FILL;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = true;
+		layoutData.grabExcessVerticalSpace = false;
+		layoutData.horizontalIndent = 20 ;
+		columnMappingGroup.setLayoutData(layoutData);
+		
+		SWTUtil.createLabel(columnMappingGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_propName );
+		mPropNameField = new Text(columnMappingGroup, SWT.BORDER | SWT.SINGLE );
+		mPropNameField.addModifyListener(new ModifyListener(){
+			@SuppressWarnings("restriction")
+			public void modifyText(ModifyEvent e) {
+				if (!mIsUpdatingControls) {
+					String fldName = mPropNameField.getText();
+					IStatus status = JavaConventions.validateIdentifier( fldName, 
+							CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3 );
+					if( !status.matches(IStatus.ERROR)){
+						mColumn.setPropertyName(fldName);
+						wizardPage.setErrorMessage(null);
+					}else{
+						wizardPage.setErrorMessage(status.getMessage());
+					}
+				}
+			}			
+		});
+		SWTUtil.fillColumns(mPropNameField ,3);
+		
+		SWTUtil.createLabel(columnMappingGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_propType );
+		mPropTypeCombo = new Combo(columnMappingGroup, SWT.SINGLE | SWT.READ_ONLY);
+		mPropTypeCombo.setItems( this.customizer.getAllPropertyTypes());
+		mPropTypeCombo.addModifyListener( new ModifyListener(){
+			public void modifyText(ModifyEvent e) {
+				if (!mIsUpdatingControls) {
+					mColumn.setPropertyType(mPropTypeCombo.getText());
+				}
+			}
+		});
+		SWTUtil.fillColumns(mPropTypeCombo,3);
+		
+		SWTUtil.createLabel(columnMappingGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_mapKind );
+		mMappingKindCombo = new Combo(columnMappingGroup, SWT.SINGLE | SWT.READ_ONLY);
+		mMappingKindCombo.setItems( this.customizer.getAllMappingKinds());
+		mMappingKindCombo.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				if (!mIsUpdatingControls) {
+					mColumn.setMappingKind((String)mMappingKindCombo.getText());
+				}
+				
+			}});
+		SWTUtil.fillColumns(mMappingKindCombo ,3);
+		
+		mUpdateableCheckBox = new Button(columnMappingGroup, SWT.CHECK);
+		mUpdateableCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_colUpdateable);
+		mUpdateableCheckBox.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				if (!mIsUpdatingControls) {
+					mColumn.setUpdateable(mUpdateableCheckBox.getSelection() );
+				}
+			}});
+		SWTUtil.fillColumns(mUpdateableCheckBox ,4);
+		
+		mInsertableCheckBox = new Button(columnMappingGroup, SWT.CHECK);
+		mInsertableCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_colInsertable);
+		mInsertableCheckBox.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				if (!mIsUpdatingControls) {
+					mColumn.setInsertable(mInsertableCheckBox.getSelection());
+				}
+			}});
+		SWTUtil.fillColumns(mInsertableCheckBox ,4);
+		
+		SWTUtil.createLabel(composite, 4,""); 
+		
+		createJavaBeanPropertyControls(composite, columns);
+	}
+	
+	void createJavaBeanPropertyControls(Composite composite, int columns){
+		//Java class generation properties 
+		domainClassGroup = new Group(composite, SWT.NONE);
+		domainClassGroup.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_beanProp );
+		domainClassGroup.setLayout(new GridLayout(columns, false));
+		GridData layoutData = new GridData();
+		layoutData.horizontalSpan = columns;
+		layoutData.verticalAlignment = SWT.FILL;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = true;
+		layoutData.grabExcessVerticalSpace = false;
+		layoutData.horizontalIndent = 20;
+		domainClassGroup.setLayoutData(layoutData);
+
+		SWTUtil.createLabel(domainClassGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_getterScope );
+		mPropGetScopePanel = new ScopePanel(domainClassGroup, new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+
+			public void widgetSelected(SelectionEvent e) {
+				if (!mIsUpdatingControls) {
+					if( ((Button)e.getSource()).getSelection() )
+						mColumn.setPropertyGetScope(mPropGetScopePanel.getScope());
+				}
+				
+			}});
+		
+		SWTUtil.createLabel(domainClassGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_setterScope );
+		mPropSetScopePanel = new ScopePanel(domainClassGroup, new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+
+			public void widgetSelected(SelectionEvent e) {
+				if (!mIsUpdatingControls) {
+					if( ((Button)e.getSource()).getSelection() )
+						mColumn.setPropertySetScope(mPropSetScopePanel.getScope());
+				}
+			}});
+		
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DatabaseGroup.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DatabaseGroup.java
new file mode 100644
index 0000000..3a52bee
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DatabaseGroup.java
@@ -0,0 +1,521 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.SortedSet;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.wizard.IWizardContainer;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.db.ConnectionAdapter;
+import org.eclipse.jpt.db.ConnectionListener;
+import org.eclipse.jpt.db.ConnectionProfile;
+import org.eclipse.jpt.db.JptDbPlugin;
+import org.eclipse.jpt.db.Schema;
+import org.eclipse.jpt.db.SchemaContainer;
+import org.eclipse.jpt.db.ui.internal.DTPUiTools;
+import org.eclipse.jpt.ui.CommonImages;
+import org.eclipse.jpt.ui.JptUiPlugin;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.jpt.utility.internal.iterators.CloneIterator;
+import org.eclipse.jpt.utility.internal.iterators.EmptyIterator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * A composite used to connect to database, includes following UI controls:
+ * - connection combo-box
+ * - schema combo-box
+ * - add connection button
+ * - reconnect button
+ */
+public class DatabaseGroup
+{
+	private final JpaProject jpaProject;
+	private final Set<Listener> listeners = Collections.synchronizedSet(new HashSet<Listener>());
+
+	// these are kept in synch with the selection
+	private ConnectionProfile selectedConnectionProfile;
+	private Schema selectedSchema;
+
+	private final Combo connectionComboBox;
+
+	private final Combo schemaComboBox;
+
+	private final Button reconnectButton;
+
+	private final ConnectionListener connectionListener;
+
+	private IWizardContainer wizardContainer;
+
+	// ********** construction **********
+
+	DatabaseGroup(IWizardContainer wizardContainer, JpaProject jpaProject, Composite parent, int widthHint) 
+	{
+		super();
+		this.wizardContainer = wizardContainer;
+		this.jpaProject = jpaProject;
+
+		// connection combo-box
+		this.buildLabel(parent, 1, JptUiEntityGenMessages.connection);
+		this.connectionComboBox = this.buildComboBox(parent, widthHint, this.buildConnectionComboBoxSelectionListener());
+
+		// add connection button
+		this.buildButton(parent, JptUiEntityGenMessages.addConnectionLink, CommonImages.createImage( CommonImages.ADD_CONNECTION_IMAGE ), this.buildAddConnectionLinkSelectionListener());
+
+		// A composite holds the reconnect button & text
+		this.buildLabel(parent, 1, "");
+		Composite comp = new Composite( parent , SWT.NONE );
+		GridData gd = new GridData();
+		gd.grabExcessHorizontalSpace = true ;
+		gd.horizontalSpan = 2;
+		comp.setLayoutData( gd );
+		GridLayout gl = new GridLayout(2, false);
+		// Make the reconnect button to be closer to the connection combo.
+		gl.marginTop = -5;
+		comp.setLayout(gl);
+		this.reconnectButton = this.buildButton(comp, JptUiEntityGenMessages.connectLink, CommonImages.createImage( CommonImages.RECONNECT_IMAGE ),  this.buildReconnectLinkSelectionListener());
+		this.buildLabel(comp, 1, JptUiEntityGenMessages.schemaInfo);
+
+		// schema combo-box
+		this.buildLabel(parent, 1, JptUiEntityGenMessages.schema);
+		this.schemaComboBox = new Combo(parent, SWT.BORDER | SWT.READ_ONLY);
+		GridData data = new GridData(SWT.BEGINNING, SWT.CENTER, true, false);
+		data.horizontalAlignment = SWT.FILL;
+		data.horizontalSpan = 1;
+		data.grabExcessHorizontalSpace = true ;
+		this.schemaComboBox.setLayoutData(data);
+		this.schemaComboBox.addSelectionListener(this.buildSchemaComboBoxSelectionListener());
+		// filler
+		new Label(parent, SWT.NULL);
+
+		this.connectionListener = this.buildConnectionListener();
+	}
+
+
+	public void init()
+	{
+		// initialize state, based on JPA project
+		this.selectedConnectionProfile = this.getJpaProjectConnectionProfile();
+		this.selectedSchema = this.getDefaultSchema();
+
+		if (this.selectedSchema != null) {
+			this.fireSchemaChanged(this.selectedSchema);
+		}
+		if (this.selectedConnectionProfile != null) {
+			this.selectedConnectionProfile.addConnectionListener(this.connectionListener);
+			this.fireConnectionProfileChanged(this.selectedConnectionProfile);
+		}
+
+		this.updateConnectionComboBox();
+		this.updateSchemaComboBox();
+		this.updateReconnectLink();
+
+	}
+	// ********** intra-wizard methods **********
+
+	ConnectionProfile getSelectedConnectionProfile() {
+		return this.selectedConnectionProfile;
+	}
+
+	Schema getSelectedSchema() {
+		return this.selectedSchema;
+	}
+
+	void dispose() {
+		if (this.selectedConnectionProfile != null) {
+			this.selectedConnectionProfile.removeConnectionListener(this.connectionListener);
+		}
+	}
+
+
+	// ********** internal methods **********
+
+	/**
+	 * this can return null;
+	 * called at start-up and when the selected connection profile changes
+	 */
+	private ConnectionProfile getJpaProjectConnectionProfile() {
+		return this.jpaProject.getConnectionProfile();
+	}
+
+	/**
+	 * this can return null;
+	 * called at start-up and when the selected connection profile changes
+	 */
+	private Schema getDefaultSchema() {
+		try{
+		return (this.selectedConnectionProfile == this.getJpaProjectConnectionProfile()) ?
+						jpaProject.getDefaultDbSchema()	: null;
+		}catch(Exception e ){
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * the connection combo-box is updated at start-up and when the user
+	 * adds a connection profile
+	 */
+	private void updateConnectionComboBox() {
+		this.connectionComboBox.removeAll();
+		for (String cpName : this.buildSortedConnectionProfileNames()) {
+			this.connectionComboBox.add(cpName);
+		}
+		if (this.selectedConnectionProfile != null) {
+			this.connectionComboBox.select(this.connectionComboBox.indexOf(this.selectedConnectionProfile.getName()));
+		}
+	}
+
+	private SortedSet<String> buildSortedConnectionProfileNames() {
+		return CollectionTools.sortedSet(JptDbPlugin.instance().getConnectionProfileFactory().connectionProfileNames());
+	}
+
+	/**
+	 * called at start-up and when the selected connection profile changes
+	 */
+	private void updateReconnectLink() {
+		this.reconnectButton.setEnabled(this.reconnectLinkCanBeEnabled());
+	}
+
+	private boolean reconnectLinkCanBeEnabled() {
+		return (this.selectedConnectionProfile != null) && !(this.selectedConnectionProfile.isActive());
+	}
+
+	/**
+	 * the schema combo-box is updated at start-up and
+	 * when the selected connection profile changes
+	 */
+	private void updateSchemaComboBox() {
+		this.schemaComboBox.removeAll();
+		for (Iterator<String> stream = this.getSchemata(); stream.hasNext(); ) {
+			this.schemaComboBox.add(stream.next());
+		}
+		// the current schema *should* be in the current connection profile
+		if (this.selectedSchema != null) {
+			this.schemaComboBox.select(this.schemaComboBox.indexOf(this.selectedSchema.getName()));
+		}
+	}
+
+	private Iterator<String> getSchemata() {
+		SchemaContainer sc = jpaProject.getDefaultDbSchemaContainer();
+		return (sc == null) ? EmptyIterator.<String>instance() : sc.sortedSchemaIdentifiers();
+	}
+
+	/**
+	 * If the specified name matches the name of the JPA project's
+	 * connection profile, return it; otherwise, build a new connection
+	 * profile.
+	 */
+	private ConnectionProfile checkJpaProjectConnectionProfile(String cpName) {
+		ConnectionProfile cp = this.getJpaProjectConnectionProfile();
+		if ((cp != null) && cp.getName().equals(cpName)) {
+			return cp;
+		}
+		return this.buildConnectionProfile(cpName);
+	}
+
+	private ConnectionProfile buildConnectionProfile(String name) {
+		return JptDbPlugin.instance().getConnectionProfileFactory().buildConnectionProfile(name);
+	}
+
+
+	// ********** listener callbacks **********
+
+	void selectedConnectionChanged() {
+		String text = this.connectionComboBox.getText();
+		if (text.length() == 0) {
+			if (this.selectedConnectionProfile == null) {
+				return;  // no change
+			}
+			this.selectedConnectionProfile.removeConnectionListener(this.connectionListener);
+			this.selectedConnectionProfile = null;
+		} else {
+			if (this.selectedConnectionProfile == null) {
+				this.selectedConnectionProfile = this.checkJpaProjectConnectionProfile(text);
+			} else {
+				if (text.equals(this.selectedConnectionProfile.getName())) {
+					return;  // no change
+				}
+				this.selectedConnectionProfile.removeConnectionListener(this.connectionListener);
+				this.selectedConnectionProfile = this.checkJpaProjectConnectionProfile(text);
+			}
+			this.selectedConnectionProfile.addConnectionListener(this.connectionListener);
+		}
+		this.fireConnectionProfileChanged(this.selectedConnectionProfile);
+		this.connectionChanged();
+	}
+
+	void selectedSchemaChanged() {
+		Schema old = this.selectedSchema;
+		this.selectedSchema = this.selectedConnectionProfile.getDatabase().getSchemaForIdentifier(this.schemaComboBox.getText());
+		if (this.selectedSchema != old) {
+			fireSchemaChanged(this.selectedSchema);
+		}
+	}
+
+	/**
+	 * Open the DTP New Connection Profile wizard.
+	 * If the user creates a new connection profile, start using it and
+	 * connect it
+	 */
+	void addConnection() {
+		String addedProfileName = DTPUiTools.createNewConnectionProfile();
+		if (addedProfileName == null) {
+			return;  // user pressed "Cancel"
+		}
+		if (this.selectedConnectionProfile != null) {
+			this.selectedConnectionProfile.removeConnectionListener(this.connectionListener);
+		}
+		this.selectedConnectionProfile = this.buildConnectionProfile(addedProfileName);
+		this.selectedConnectionProfile.addConnectionListener(this.connectionListener);
+		this.updateConnectionComboBox();
+		this.selectedConnectionProfile.connect();
+		this.updateSchemaComboBox();
+		// everything else should be synchronized when we get the resulting open event
+		this.fireConnectionProfileChanged(this.selectedConnectionProfile);
+	}
+
+	void reconnect() {
+		try {
+			wizardContainer.run(true, true, new IRunnableWithProgress(){
+				public void run( final IProgressMonitor monitor ) 
+			    	throws InvocationTargetException, InterruptedException
+			    {
+					monitor.beginTask("Connecting to database", 10);
+					final boolean[] isConnected= new boolean[1];
+					isConnected[0]=false;
+					Thread t= new Thread(){
+						public void run() {
+							selectedConnectionProfile.connect();
+							isConnected[0]=true;
+						}						
+					};
+					t.start();
+					while( !isConnected[0]){
+						Thread.sleep(1000);
+						monitor.worked(1);
+					}
+			        // everything should be synchronized when we get the resulting open event
+					monitor.done();
+			    }
+			});
+		} catch (Exception e) {
+			JptUiPlugin.log(e);
+		}
+	}
+
+	/**
+	 * called when
+	 *     - the user selects a new connection
+	 *     - the connection was opened
+	 *     - the connection was closed (never happens?)
+	 * we need to update the schema stuff and the reconnect link
+	 */
+	void connectionChanged() {
+		Schema old = this.selectedSchema;
+		this.selectedSchema = this.getDefaultSchema();
+		if (this.selectedSchema != old) {
+			this.fireSchemaChanged(this.selectedSchema);
+		}
+		this.updateSchemaComboBox();
+		this.updateReconnectLink();
+	}
+
+
+	// ********** listeners **********
+
+	private SelectionListener buildConnectionComboBoxSelectionListener() {
+		return new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent event) {
+				// nothing special for "default" (double-click?)
+				this.widgetSelected(event);
+			}
+			public void widgetSelected(SelectionEvent event) {
+				DatabaseGroup.this.selectedConnectionChanged();
+			}
+			@Override
+			public String toString() {
+				return "DatabaseConnectionWizardPage connection combo-box selection listener"; //$NON-NLS-1$
+			}
+		};
+	}
+
+	private SelectionListener buildSchemaComboBoxSelectionListener() {
+		return new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent event) {
+				// nothing special for "default" (double-click?)
+				this.widgetSelected(event);
+			}
+			public void widgetSelected(SelectionEvent event) {
+				DatabaseGroup.this.selectedSchemaChanged();
+			}
+			@Override
+			public String toString() {
+				return "DatabaseConnectionWizardPage schema combo-box selection listener"; //$NON-NLS-1$
+			}
+		};
+	}
+
+	private SelectionListener buildAddConnectionLinkSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent event) {
+				DatabaseGroup.this.addConnection();
+			}
+			@Override
+			public String toString() {
+				return "DatabaseConnectionWizardPage add connection link selection listener"; //$NON-NLS-1$
+			}
+		};
+	}
+
+	private SelectionListener buildReconnectLinkSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent event) {
+				DatabaseGroup.this.reconnect();
+			}
+			@Override
+			public String toString() {
+				return "DatabaseConnectionWizardPage reconnect link selection listener"; //$NON-NLS-1$
+			}
+		};
+	}
+
+	private ConnectionListener buildConnectionListener() {
+		return new ConnectionAdapter() {
+			@Override
+			public void opened(ConnectionProfile cp) {
+				this.connectionChanged();
+			}
+			@Override  // this probably won't ever get called...
+			public void closed(ConnectionProfile cp) {
+				this.connectionChanged();
+			}
+			private void connectionChanged() {
+				Display.getDefault().asyncExec(
+					new Runnable() {
+						public void run() {
+							DatabaseGroup.this.connectionChanged();
+						}
+					}
+				);
+			}
+			@Override
+			public String toString() {
+				return "DatabaseConnectionWizardPage connection listener"; //$NON-NLS-1$
+			}
+		};
+	}
+
+
+	// ********** listeners **********
+
+	public void addListener(Listener listener) {
+		if ( ! this.listeners.add(listener)) {
+			throw new IllegalArgumentException("duplicate listener: " + listener); //$NON-NLS-1$
+		}
+	}
+
+	public void removeListener(Listener listener) {
+		if ( ! this.listeners.remove(listener)) {
+			throw new IllegalArgumentException("missing listener: " + listener); //$NON-NLS-1$
+		}
+	}
+
+	private Iterator<Listener> listeners() {
+		return new CloneIterator<Listener>(this.listeners);
+	}
+
+	void fireConnectionProfileChanged(ConnectionProfile connectionProfile) {
+		for (Iterator<Listener> stream = this.listeners(); stream.hasNext(); ) {
+			stream.next().selectedConnectionProfileChanged(connectionProfile);
+		}
+	}
+
+	void fireSchemaChanged(Schema schema) {
+		for (Iterator<Listener> stream = this.listeners(); stream.hasNext(); ) {
+			stream.next().selectedSchemaChanged(schema);
+		}
+	}
+
+	// ********** UI components **********
+
+	/**
+	 * build and return a label
+	 */
+	private Label buildLabel(Composite parent, int span, String text) {
+		Label label = new Label(parent, SWT.NONE);
+		label.setText(text);
+		GridData gd = new GridData();
+		gd.horizontalSpan = span;
+		label.setLayoutData(gd);
+		return label;
+	}
+
+	/**
+	 * build and return a combo-box
+	 */
+	private Combo buildComboBox(Composite parent, int widthHint, SelectionListener listener) {
+		Combo combo = new Combo(parent, SWT.BORDER | SWT.READ_ONLY);
+		combo.addSelectionListener(listener);
+		GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false);
+		//data.grabExcessHorizontalSpace = true ;
+		data.widthHint = widthHint;
+		combo.setLayoutData(data);
+		return combo;
+	}
+
+	/**
+	 * build and return a link
+	 */
+	private Button buildButton(Composite parent, String toolTipText, Image image, SelectionListener listener) {
+		Button button = new Button(parent, SWT.NONE);
+		GridData data = new GridData(GridData.END, GridData.CENTER, false, false);
+		data.horizontalSpan = 1;
+		button.setLayoutData(data);
+		button.setImage( image );
+		button.setToolTipText( toolTipText);
+		button.addSelectionListener(listener);
+		return button;
+	}
+
+	// ********** listener interface **********
+
+	/**
+	 * Allows clients to listen for changes to the selected connection profile
+	 * and schema.
+	 */
+	public interface Listener extends EventListener
+	{
+		void selectedConnectionProfileChanged(ConnectionProfile connectionProfile);
+		void selectedSchemaChanged(Schema schema);
+	}
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DefaultTableGenerationWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DefaultTableGenerationWizardPage.java
new file mode 100644
index 0000000..23c60e3
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DefaultTableGenerationWizardPage.java
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.ui.wizards.NewTypeWizardPage;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+import org.eclipse.jpt.gen.internal2.ORMGenTable;
+import org.eclipse.jpt.ui.JptUiPlugin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * A wizard page allowing the entry of the default table generation 
+ * properties (Java classes package, base class, etc).
+ * These properties apply to all tables unless explicitly overridden (in the table generation page).
+ * 
+ * @author Danny Ju
+ */
+public class DefaultTableGenerationWizardPage extends NewTypeWizardPage {
+
+	private JpaProject jpaProject;
+
+	/*the instance used to get/set the default properties.*/
+	private ORMGenTable defaultsTable;
+
+	private ORMGenCustomizer customizer;
+	
+	private TableGenPanel defaultTableGenPanel ;
+
+	protected DefaultTableGenerationWizardPage(JpaProject jpaProject) {
+		super(true, "DefaultTableGenerationWizardPage"); //$NON-NLS-1$
+		this.jpaProject = jpaProject;
+		setTitle(JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_title);
+		setDescription( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_desc);
+	}
+	
+	
+	// -------- Initialization ---------
+	/**
+	 * The wizard owning this page is responsible for calling this method with the
+	 * current selection. The selection is used to initialize the fields of the wizard 
+	 * page.
+	 * 
+	 * @param selection used to initialize the fields
+	 */
+	void init(IStructuredSelection selection) {
+		if( jpaProject != null ){
+			IJavaElement jelem = this.jpaProject.getJavaProject();
+			initContainerPage(jelem);
+			initTypePage(jelem);
+		}
+	}
+	
+	public void createControl(Composite parent) {
+		initializeDialogUnits(parent);
+		Composite composite = new Composite(parent, SWT.NULL);
+		int nColumns= 4		;
+		GridLayout layout = new GridLayout();
+		layout.numColumns = nColumns;
+		composite.setLayout(layout);
+		//PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES);
+
+		//Create entity access, collection type, etc 
+		defaultTableGenPanel = new TableGenPanel(composite, 4, true , this);
+		
+		createDomainJavaClassesPropertiesGroup(composite, 4);
+		setControl(composite);
+
+		
+		this.setPageComplete( true );
+		
+	}
+
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if(visible){
+			ORMGenCustomizer customizer = getCustomizer();
+			//If user changed the connection or schema
+			if( this.customizer != customizer ){
+				this.customizer = customizer; 
+				ORMGenTable newTable;
+				newTable = getCustomizer().createGenTable(null);
+				this.defaultsTable = newTable;
+				defaultTableGenPanel.setORMGenTable(newTable);
+
+				//set the super class and implemented interfaces value
+				String baseClass = defaultsTable.getExtends()==null?"":defaultsTable.getExtends();
+				setSuperClass(baseClass, true);
+				setSuperInterfaces(defaultsTable.getImplements(), true);
+				
+				setPackageName( defaultsTable.getPackage() );
+				
+
+			}
+		}
+	}	
+	
+	private void setPackageName(String packageName) {
+		if( packageName==null )
+			return;
+		// Copied from org.eclipse.pde.internal.ui.editor.plugin.JavaAttributeWizardPage
+		try {
+			IPackageFragmentRoot srcEntryDft = null;
+			IJavaProject javaProject = jpaProject.getJavaProject();
+			IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
+			for (int i = 0; i < roots.length; i++) {
+				if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
+					srcEntryDft = roots[i];
+					break;
+				}
+			}
+			IPackageFragmentRoot packageFragmentRoot;
+			if (srcEntryDft != null)
+				packageFragmentRoot = srcEntryDft;
+			else {
+				packageFragmentRoot = javaProject.getPackageFragmentRoot(javaProject.getResource());
+			}
+			IFolder packageFolder = javaProject.getProject().getFolder(packageName);
+			IPackageFragment packageFragment = packageFragmentRoot.getPackageFragment(packageFolder.getProjectRelativePath().toOSString());
+			setPackageFragment(packageFragment, true/*canBeModified*/);
+		} catch (CoreException e) {
+			JptUiPlugin.log(e);
+		}
+	}
+
+
+	protected void createDomainJavaClassesPropertiesGroup(Composite composite, int columns) {
+		Group parent = new Group( composite, SWT.NONE);
+		parent.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_domainJavaClass);
+		parent.setLayout(new GridLayout( columns, false));
+		GridData layoutData = new GridData();
+		layoutData.horizontalSpan = columns;
+		layoutData.verticalAlignment = SWT.FILL;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = true;
+		layoutData.grabExcessVerticalSpace = true;
+		parent.setLayoutData(layoutData);
+		
+		//default Java package name only available for default table generation
+		createPackageControls(parent, columns);
+		createSuperClassControls(parent, columns);
+		createSuperInterfacesControls(parent, columns);
+
+	}
+	
+	protected IStatus packageChanged() {
+		IStatus status = super.packageChanged(); 
+		IPackageFragment packageFragment = getPackageFragment();
+		String srcFolder = packageFragment.getPath().toPortableString();
+		if(defaultsTable!=null && !status.matches(IStatus.ERROR)){
+			defaultsTable.setPackage(srcFolder, packageFragment.getElementName());
+		}
+		return status;
+	}	
+
+	protected IStatus superClassChanged() {
+		IStatus status = super.superClassChanged();
+		String baseClass = getSuperClass();
+		if(baseClass!=null && defaultsTable!=null && !status.matches(IStatus.ERROR)){
+			String oldBaseClass = defaultsTable.getExtends();
+			if( !baseClass.equals(oldBaseClass))
+				defaultsTable.setExtends(baseClass);
+		}
+		return status; 
+	}	
+	
+	protected void handleFieldChanged(String fieldName) {
+		super.handleFieldChanged(fieldName);
+		if( this.fPackageStatus.matches(IStatus.ERROR) ){
+			updateStatus(fPackageStatus);
+		}else if( this.fSuperClassStatus.matches(IStatus.ERROR)){
+			updateStatus(fSuperClassStatus);
+		}else{
+			setMessage("", IMessageProvider.NONE);
+			setErrorMessage(null);
+			updateStatus(fPackageStatus);
+		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	protected IStatus superInterfacesChanged() {
+		IStatus ret = super.superInterfacesChanged();
+		if( ret.isOK() ){
+			List interfaces = getSuperInterfaces();
+			if(defaultsTable!=null)
+				defaultsTable.setImplements(interfaces);
+		}
+		return ret;
+	}	
+
+	private ORMGenCustomizer getCustomizer(){
+		GenerateEntitiesFromSchemaWizard wizard = (GenerateEntitiesFromSchemaWizard) this.getWizard();
+		return wizard.getCustomizer();
+	}	
+
+    @Override
+    public final void performHelp() 
+    {
+        PlatformUI.getWorkbench().getHelpSystem().displayHelp( GenerateEntitiesFromSchemaWizard.HELP_CONTEXT_ID );
+    }
+}
+
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/GenerateEntitiesFromSchemaWizard.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/GenerateEntitiesFromSchemaWizard.java
new file mode 100644
index 0000000..65713b2
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/GenerateEntitiesFromSchemaWizard.java
@@ -0,0 +1,416 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.eclipse.core.internal.runtime.AdapterManager;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jpt.core.EntityGeneratorDatabaseAnnotationNameBuilder;
+import org.eclipse.jpt.core.JpaPlatform;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.core.JptCorePlugin;
+import org.eclipse.jpt.core.context.persistence.PersistenceXml;
+import org.eclipse.jpt.core.internal.synch.SynchronizeClassesJob;
+import org.eclipse.jpt.db.Column;
+import org.eclipse.jpt.db.ConnectionProfile;
+import org.eclipse.jpt.db.ForeignKey;
+import org.eclipse.jpt.db.Schema;
+import org.eclipse.jpt.db.Table;
+import org.eclipse.jpt.gen.internal2.BaseEntityGenCustomizer;
+import org.eclipse.jpt.gen.internal2.DatabaseAnnotationNameBuilder;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+import org.eclipse.jpt.gen.internal2.PackageGenerator2;
+import org.eclipse.jpt.ui.JptUiPlugin;
+import org.eclipse.jpt.ui.internal.JptUiIcons;
+import org.eclipse.jpt.ui.internal.JptUiMessages;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+
+@SuppressWarnings("restriction")
+public class GenerateEntitiesFromSchemaWizard extends Wizard 
+	implements INewWizard  {	
+	
+	public static final String HELP_CONTEXT_ID = JptUiPlugin.PLUGIN_ID + ".GenerateEntitiesFromSchemaWizard"; //$NON-NLS-1$
+
+	private JpaProject jpaProject;
+
+	private IStructuredSelection selection;
+
+	private ORMGenCustomizer customizer = null;	
+
+	private boolean synchronizePersistenceXml;
+
+	private PromptJPAProjectWizardPage projectPage;	
+
+	private TablesSelectorWizardPage tablesSelectorPage;
+
+	private TableAssociationsWizardPage tableAssociationsPage;
+	
+	private DefaultTableGenerationWizardPage defaultTableGenerationPage;
+	
+	private TablesAndColumnsCustomizationWizardPage tablesAndColumnsCustomizationPage;
+	
+	public GenerateEntitiesFromSchemaWizard() {
+		this.setWindowTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_generateEntities);
+	}
+	
+	public GenerateEntitiesFromSchemaWizard( JpaProject jpaProject, IStructuredSelection selection) {
+		super();
+		this.jpaProject = jpaProject;
+		this.selection = selection;
+		this.setWindowTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_generateEntities);
+	}
+	
+	public Image getDefaultPageImage() {
+		return JptUiPlugin.getImage( JptUiIcons.ENTITY_WIZ_BANNER ) ;
+	}	
+	
+	public void addPages() {
+		super.addPages();
+
+		setForcePreviousAndNextButtons(true);
+		
+		//If this.jpaProject is not initialized because user didn't select a JPA project
+		if( this.jpaProject == null ){
+			projectPage = new PromptJPAProjectWizardPage( HELP_CONTEXT_ID );
+			this.addPage(projectPage);
+			return;
+		}
+		addMainPages();
+	}
+
+	private void addMainPages()
+	{
+		this.tablesSelectorPage = new TablesSelectorWizardPage( this.jpaProject );
+		this.addPage(tablesSelectorPage);
+		
+		this.tableAssociationsPage = new TableAssociationsWizardPage( this.jpaProject  );
+		this.addPage(tableAssociationsPage);
+
+		this.defaultTableGenerationPage = new DefaultTableGenerationWizardPage( this.jpaProject);
+		this.addPage(defaultTableGenerationPage);
+		this.defaultTableGenerationPage.init(this.selection);
+		
+		this.tablesAndColumnsCustomizationPage = new TablesAndColumnsCustomizationWizardPage( this.jpaProject );
+		this.addPage(tablesAndColumnsCustomizationPage);
+		this.tablesAndColumnsCustomizationPage.init(selection);		
+	}
+	
+	public ORMGenCustomizer getORMGenCustomizer(){
+		return this.customizer;
+	}
+
+	/**
+	 * Create the ORMGenCustomizer when user selects a new connection profile and schema 
+	 * 
+	 * JpaPlatform implementor can provide a custom ORMGenCustomizer specific to a platform
+	 * with AdapterFactory through Eclipse org.eclipse.core.runtime.adapters extension point:
+	 * <pre> 
+	 *  
+	 *<extension
+     *    point="org.eclipse.core.runtime.adapters">
+     * <factory
+     *       adaptableType="org.eclipse.jpt.eclipselink.core.internal.EclipseLinkPlatform"
+     *       class="oracle.eclipse.tools.orm.internal.EclipseLinkORMGenCustomizerAdapterFactory">
+     *    <adapter
+     *          type="oracle.eclipse.tools.orm.internal.ORMGenCustomizer">
+     *    </adapter>
+     * </factory>
+     *</extension>
+	 *</pre> 
+	 * 
+	 * @param schema 
+	 */
+	public ORMGenCustomizer createORMGenCustomizer(Schema schema){
+		JpaPlatform jpaPlatform = this.jpaProject.getJpaPlatform();
+		Object obj = AdapterManager.getDefault().getAdapter( jpaPlatform, ORMGenCustomizer.class );
+		if( obj != null  ){
+			customizer = (ORMGenCustomizer) obj ; 
+			customizer.init(getCustomizationFile(), schema );  
+		}else{
+			customizer = new BaseEntityGenCustomizer( );
+			customizer.init(getCustomizationFile(), schema );  
+		}
+		return customizer;
+	} 
+	
+	protected String getCustomizationFileName() {
+		ConnectionProfile profile = getProjectConnectionProfile();
+		String connection = profile==null?"":profile.getName();
+		String name = "org.eclipse.jpt.entitygen." + (connection==null?"":connection.replace(' ', '-'));  //$NON-NLS-1$
+		Schema schema = getDefaultSchema();
+		if ( schema!= null  ) {
+			name += "." + schema.getName();//$NON-NLS-1$
+		}
+		return name.toLowerCase();
+	}
+	
+	/**
+	 * Returns the nodes state file. 
+	 */
+	private File getCustomizationFile() {
+		String projectPath = jpaProject.getProject().getLocation().toPortableString();
+		File genDir = new File(projectPath + "/.settings");//$NON-NLS-1$
+        genDir.mkdirs();
+		return new File(genDir, getCustomizationFileName());
+	}
+
+	public boolean performFinish() {
+		if( this.jpaProject == null )
+			return true;
+		
+		try {
+			this.customizer.setDatabaseAnnotationNameBuilder( buildDatabaseAnnotationNameBuilder() );
+			this.customizer.save();
+		} catch (IOException e) {
+			JptUiPlugin.log(e);
+		}
+		
+		this.synchronizePersistenceXml = this.tablesSelectorPage.synchronizePersistenceXml();
+
+		if( WarnOverwriteDialog.shouldShowDialog() ){
+			if( !this.openConfirmDialog() )
+				return false;
+		}
+
+		WorkspaceJob genEntitiesJob = new GenerateEntitiesJob( this.jpaProject,  getCustomizer() );
+		
+		WorkspaceJob synchClassesJob = null;
+		if (synchronizePersistenceXml()) {
+			// we currently only support *one* persistence.xml file per project
+			PersistenceXml persistenceXml = jpaProject.getRootContextNode().getPersistenceXml();
+			if (persistenceXml != null) {
+				// TODO casting to IFile - just trying to get rid of all compiler errors for now
+				synchClassesJob = new SynchronizeClassesJob((IFile) persistenceXml.getResource());
+			}
+		}
+		
+		genEntitiesJob.schedule();
+		if (synchClassesJob != null) {
+			synchClassesJob.schedule();
+		}		
+		
+		return true;
+	}
+	
+	// ********** generate entities job **********
+
+	static class GenerateEntitiesJob extends WorkspaceJob {
+		JpaProject jpaProject ;
+		ORMGenCustomizer customizer;
+		GenerateEntitiesJob(JpaProject jpaProject, ORMGenCustomizer customizer) {
+			super(JptUiMessages.EntitiesGenerator_jobName);
+			this.customizer = customizer;
+			this.jpaProject = jpaProject ;
+			this.setRule(jpaProject.getProject());
+		}
+
+		@Override
+		public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
+			PackageGenerator2.generate(jpaProject.getJavaProject(),this.customizer, monitor);
+			return Status.OK_STATUS;
+		}
+
+	}	
+
+	private DatabaseAnnotationNameBuilder buildDatabaseAnnotationNameBuilder() {
+		return new LocalDatabaseAnnotationNameBuilder(this.jpaProject.getJpaPlatform().getEntityGeneratorDatabaseAnnotationNameBuilder());
+	}
+
+	// ********** name builder adapter **********
+
+	/**
+	 * adapt the JPA platform-supplied builder to the builder interface
+	 * expected by the entity generator
+	 */
+	static class LocalDatabaseAnnotationNameBuilder implements DatabaseAnnotationNameBuilder {
+		private EntityGeneratorDatabaseAnnotationNameBuilder builder;
+		LocalDatabaseAnnotationNameBuilder(EntityGeneratorDatabaseAnnotationNameBuilder builder) {
+			super();
+			this.builder = builder;
+		}
+		public String buildTableAnnotationName(String entityName, Table table) {
+			return this.builder.buildTableAnnotationName(entityName, table);
+		}
+		public String buildColumnAnnotationName(String attributeName, Column column) {
+			return this.builder.buildColumnAnnotationName(attributeName, column);
+		}
+		public String buildJoinColumnAnnotationName(String attributeName, ForeignKey foreignKey) {
+			return this.builder.buildJoinColumnAnnotationName(attributeName, foreignKey);
+		}
+		public String buildJoinColumnAnnotationName(Column column) {
+			return this.builder.buildJoinColumnAnnotationName(column);
+		}
+		public String buildJoinTableAnnotationName(Table table) {
+			return this.builder.buildJoinTableAnnotationName(table);
+		}
+	}
+	
+	@Override
+    public IWizardPage getStartingPage() {
+		if (this.projectPage != null) {
+			if (this.tablesSelectorPage != null)
+				return this.tablesSelectorPage;
+			else
+				return this.projectPage;
+		}
+		else
+			return super.getStartingPage();
+    }
+	
+	public ORMGenCustomizer getCustomizer (){
+		return customizer;
+	} 
+	Collection<Table> getPossibleTables() {
+		if ( this.tablesSelectorPage != null) {
+			return this.tablesSelectorPage.getTables();
+		}
+		return ( this.projectDefaultSchemaExists()) ? CollectionTools.collection( this.getDefaultSchema().tables()) : Collections.<Table>emptyList();
+	}
+	
+	public ConnectionProfile getProjectConnectionProfile() {
+		return this.jpaProject.getConnectionProfile();
+	}
+	
+	public JpaProject getJpaProject(){
+		return this.jpaProject;
+	}
+	
+	public void setJpaProject(JpaProject jpaProject) {
+		if (this.jpaProject == null) {
+			this.jpaProject = jpaProject;
+			IWizardPage currentPage = getContainer().getCurrentPage();
+			if (projectPage != null && currentPage.equals(projectPage)) {
+				addMainPages();
+			}
+		}
+	}
+
+	public Schema getDefaultSchema() {
+		return getJpaProject().getDefaultDbSchema() ;
+	}
+
+	private boolean projectDefaultSchemaExists() {
+		return ( this.getDefaultSchema() != null);
+	}
+
+	public boolean synchronizePersistenceXml() {
+		return this.synchronizePersistenceXml;
+	}
+
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+		
+		Object sel = selection.getFirstElement();
+		if( sel instanceof IResource ){
+			IProject proj = ((IResource) sel).getProject();
+			JpaProject jpaProj = JptCorePlugin.getJpaProject( proj );
+			this.jpaProject = jpaProj;
+		}else if( sel instanceof org.eclipse.jdt.core.IPackageFragmentRoot ){
+			org.eclipse.jdt.core.IPackageFragmentRoot root = (org.eclipse.jdt.core.IPackageFragmentRoot)sel;
+			IProject proj = root.getJavaProject().getProject();
+			JpaProject jpaProj = JptCorePlugin.getJpaProject( proj );
+			this.jpaProject = jpaProj;
+		}else if( sel instanceof org.eclipse.jdt.core.IPackageFragment){
+			org.eclipse.jdt.core.IPackageFragment frag = (org.eclipse.jdt.core.IPackageFragment)sel;
+			IProject proj = frag.getJavaProject().getProject();
+			JpaProject jpaProj = JptCorePlugin.getJpaProject( proj );
+			this.jpaProject = jpaProj;
+		}
+		
+		this.selection = selection;
+		this.setWindowTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_generateEntities);
+		
+	}
+	
+    public boolean openConfirmDialog() {
+    	Shell parent = Display.getDefault().getActiveShell();
+    	String title = JptUiEntityGenMessages.WarningDialogTitle; 
+    	String message = JptUiEntityGenMessages.GenerateEntitiesWizard_fileWillBeOverwritten;
+    	WarnOverwriteDialog dialog = new WarnOverwriteDialog(parent, title, null, // accept
+                // the
+                // default
+                // window
+                // icon
+                message, MessageDialog.QUESTION, new String[] { IDialogConstants.OK_LABEL,
+                        IDialogConstants.CANCEL_LABEL }, 0); // OK is the
+        // default
+        return dialog.open() == 0;
+    }
+
+}
+
+/**
+ * A simple dialog displaying warning message that existing files would be overwritten 
+ */
+class WarnOverwriteDialog extends MessageDialog {
+    static final String DONT_SHOW_OVERWRITE_WARNING = "DONT_SHOW_OVERWRITE_WARNING"; //$NON-NLS-1$
+
+	public WarnOverwriteDialog (Shell parentShell, String dialogTitle,
+            Image dialogTitleImage, String dialogMessage, int dialogImageType,
+            String[] dialogButtonLabels, int defaultIndex) {
+        super(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType,
+        		dialogButtonLabels, defaultIndex);
+    }
+    
+    @Override
+    protected Control createCustomArea(Composite composite) {
+    	final Button checkbox = new Button( composite, SWT.CHECK );
+    	checkbox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_doNotShowWarning );
+    	checkbox.setSelection(false);
+    	final IEclipsePreferences pref = new InstanceScope().getNode( JptUiPlugin.PLUGIN_ID); 
+    	checkbox.setLayoutData( new GridData(GridData.FILL_BOTH) );
+    	checkbox.addSelectionListener(new SelectionListener (){
+    		public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				boolean b = checkbox.getSelection();
+                if( b ){
+                	pref.putBoolean( DONT_SHOW_OVERWRITE_WARNING, true);
+                }
+			}
+    	});
+    	return checkbox;
+    }
+    
+    public static boolean shouldShowDialog(){
+    	IEclipsePreferences pref = new InstanceScope().getNode( JptUiPlugin.PLUGIN_ID); 
+    	boolean ret = ! pref.getBoolean( DONT_SHOW_OVERWRITE_WARNING, true) ;
+    	return( ret );
+    }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JoinColumnsPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JoinColumnsPage.java
new file mode 100644
index 0000000..42a346c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JoinColumnsPage.java
@@ -0,0 +1,605 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeMap;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.dialogs.IPageChangedListener;
+import org.eclipse.jface.dialogs.PageChangedEvent;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ComboBoxCellEditor;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jpt.db.Column;
+import org.eclipse.jpt.db.Schema;
+import org.eclipse.jpt.db.Table;
+import org.eclipse.jpt.gen.internal2.Association;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+import org.eclipse.jpt.ui.internal.util.SWTUtil;
+import org.eclipse.jpt.ui.internal.util.TableLayoutComposite;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+
+public class JoinColumnsPage extends NewAssociationWizardPage {
+
+	private Label joinColumnsDescLabel1;
+	/*the table containing the association columns between table1 and table2
+	 * , or table1 and join table if many to many*/
+	private TableViewer joinColumnsTable1;
+	private ArrayList<SimpleJoin> tableDataModel1 = new ArrayList<SimpleJoin>();  
+	private Composite tablesGroup1;
+	
+	private Label joinColumnsDescLabel2;
+	/*the table containing the association columns between join table and table2
+	 * if many to many*/
+	private TableViewer joinColumnsTable2;
+	private ArrayList<SimpleJoin> tableDataModel2 = new ArrayList<SimpleJoin>();  
+	private Composite tablesGroup2;
+	
+	static final String[] JOINCOLUMNS_TABLE_COLUMN_PROPERTIES = { "referrerColumn", "referencedColumn" };
+	
+	private static final int JOINCOLUMN1_COLUMN_INDEX = 0;
+	private static final int JOINCOLUMN2_COLUMN_INDEX = 1;
+
+	protected JoinColumnsPage(ORMGenCustomizer customizer ) {
+		super(customizer, "JoinColumnsPage");
+		setTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_title);
+		setDescription(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_desc);
+	}
+
+	public void createControl(Composite parent) {
+		initializeDialogUnits(parent);
+		
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		composite.setLayout(layout);
+		
+		tablesGroup1 = new Composite(composite, SWT.SHADOW_ETCHED_IN);
+		tablesGroup1.setLayoutData(new GridData());
+		tablesGroup1.setLayout(new GridLayout(2, false));
+		createJoinColumnsTableControl1(tablesGroup1);
+
+		//createMtmJoinColumnsTable2(composite);
+		
+		setControl(composite);
+		this.setPageComplete( false);
+		
+		((WizardDialog)getContainer()).addPageChangedListener(new IPageChangedListener(){
+			public void pageChanged(PageChangedEvent event) {
+				if( event.getSelectedPage() == JoinColumnsPage.this ){
+					((Composite)JoinColumnsPage.this.getControl()).getParent().layout() ;		
+					
+				}
+			}			
+		});
+	}
+
+	private void createMtmJoinColumnsTable2(Composite composite) {
+		tablesGroup2 = new Composite(composite, SWT.SHADOW_ETCHED_IN);
+		tablesGroup2.setLayoutData(new GridData());
+		tablesGroup2.setLayout(new GridLayout(2, false));
+		createJoinColumnsTableControl2(tablesGroup2);
+	}
+
+	/**
+	 * Update wizard page UI with new table names
+	 */
+	public void updateWithNewTables() {
+		String cardinality = this.getCardinality() ;
+		if( Association.MANY_TO_MANY.equals( cardinality ) ){
+			updateWithMtmTables();
+		}else{
+			updateWithOtmTables();
+		}
+	}
+
+	/**
+	 * Update Wizard UI with a single TableViewer with columns from the two associated database tables
+	 */
+	public void updateWithOtmTables() {
+		TableColumn[] columns = joinColumnsTable1.getTable().getColumns();
+		String table1Name = this.getReferrerTableName() ;
+		String table2Name = this.getReferencedTableName() ;
+		
+		if( table1Name ==null || table2Name == null )
+			return;
+		
+		columns[0].setText( table1Name );
+		columns[1].setText( table2Name );
+
+		//Hide the Join column table 2
+		if( tablesGroup2 !=null )
+			tablesGroup2.setVisible(false);
+		
+		tableDataModel1.clear();
+		joinColumnsTable1.refresh();
+		
+		String msg = String.format(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label, table1Name, table2Name); 
+		joinColumnsDescLabel1.setText(msg);
+		joinColumnsDescLabel1.setToolTipText( msg );
+		tablesGroup1.layout();
+		
+		String[] referrerColumnValues = getTableColumns(table1Name);
+		String[] referencedColumnValues = getTableColumns(table2Name);
+		
+		updateCellEditors(joinColumnsTable1, referrerColumnValues, referencedColumnValues);		
+
+		
+		((Composite)this.getControl()).layout() ;
+	}
+
+	/**
+	 * Update Wizard UI with a two TableViewers with the first with columns from table1 to the MTM join table
+	 * and the second one with columns from the MTM join table to table2
+	 */
+	public void updateWithMtmTables() {
+		TableColumn[] columns = joinColumnsTable1.getTable().getColumns();
+		String table1Name = this.getReferrerTableName() ;
+		String table2Name = this.getReferencedTableName() ;
+		String joinTableName = this.getJoinTableName() ;
+		if( table1Name==null || table2Name==null || joinTableName==null ){
+			return;
+		}
+		if( tablesGroup2 == null ){
+			createMtmJoinColumnsTable2( tablesGroup1.getParent());
+		} 
+
+		columns[0].setText( table1Name==null?"":table1Name );
+		columns[1].setText( table2Name==null?"":joinTableName );
+		
+		//Update join column TableViewer 1
+		tableDataModel1.clear();
+		joinColumnsTable1.refresh();
+		
+		String msg = String.format(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label, table1Name, joinTableName); 
+		joinColumnsDescLabel1.setText(msg);
+		joinColumnsDescLabel1.setToolTipText( msg );
+		String[] referrerColumnValues = getTableColumns(table1Name);
+		String[] referencedColumnValues = getTableColumns(joinTableName);
+		
+		updateCellEditors(joinColumnsTable1, referrerColumnValues, referencedColumnValues );
+
+		//Update join column TableViewer 2
+		columns = joinColumnsTable2.getTable().getColumns();
+		columns[0].setText( joinTableName==null?"":joinTableName );
+		columns[1].setText( table2Name==null?"":table2Name );
+		tablesGroup1.layout();
+
+		tableDataModel2.clear();
+		joinColumnsTable2.refresh();
+		msg = String.format(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label, joinTableName, table2Name); 
+		joinColumnsDescLabel2.setText(msg);
+		joinColumnsDescLabel2.setToolTipText( msg );
+		referrerColumnValues = getTableColumns(joinTableName);
+		referencedColumnValues = getTableColumns(table2Name);
+		updateCellEditors(joinColumnsTable2, referrerColumnValues, referencedColumnValues );
+		
+		tablesGroup2.layout();
+
+		//Show the Join column TableViewer 2
+		tablesGroup2.setVisible(true);
+		
+		
+		((Composite)this.getControl()).layout(new Control[]{this.tablesGroup1, this.tablesGroup2});		
+	}
+	
+	
+	private void createAddRemoveButtonComposite(Composite tablesGroup, final TableViewer joinColumnsTable,  final ArrayList<SimpleJoin> tableDataModel) {
+		//Add and Remove JoinColumns buttons
+		Composite buttonComposite = new Composite(tablesGroup, SWT.NULL);
+		GridLayout buttonLayout = new GridLayout(1, false);
+		buttonComposite.setLayout(buttonLayout);
+		GridData data =  new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		data.verticalAlignment = GridData.BEGINNING;
+		buttonComposite.setLayoutData(data);
+		
+		Button addButton = new Button(buttonComposite, SWT.PUSH);
+		addButton.setText( JptUiEntityGenMessages.add );
+		GridData gridData =  new GridData();
+		gridData.horizontalAlignment = GridData.FILL;
+		addButton.setLayoutData(gridData);
+		addButton.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+		
+			@SuppressWarnings("unchecked")
+			public void widgetSelected(SelectionEvent e) {
+				
+				SimpleJoin join = getDefaultNewJoin(joinColumnsTable);
+				tableDataModel.add(join);
+				joinColumnsTable.refresh();
+				
+				//Update Wizard model
+				TreeMap<String, String> joins = null;
+				if( joinColumnsTable == joinColumnsTable1 ){
+					joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 );
+				}else{
+					joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 );
+				}
+				joins.put( join.foreignKey, join.primaryKey);
+				
+				updatePageComplete();
+			}
+		});
+		
+		Button removeButton = new Button(buttonComposite, SWT.PUSH);
+		removeButton.setText( JptUiEntityGenMessages.remove );
+		gridData =  new GridData();
+		gridData.horizontalAlignment = GridData.FILL;
+		removeButton.setLayoutData(gridData);
+		removeButton.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+		
+			@SuppressWarnings("unchecked")
+			public void widgetSelected(SelectionEvent e) {
+				StructuredSelection selection = (StructuredSelection)joinColumnsTable.getSelection();
+				if( selection.isEmpty())
+					return;
+				SimpleJoin join = (SimpleJoin)selection.getFirstElement();
+
+				//Update TableViewer model
+				tableDataModel.remove( join );
+				//Update Wizard model
+				
+				TreeMap<String, String> joins = null;
+				if( joinColumnsTable == joinColumnsTable1 ){
+					joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 );
+				}else{
+					joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 );
+				}
+				joins.remove(join.foreignKey);
+
+				joinColumnsTable.refresh();
+			}
+		});
+		
+		addButton.setFocus();
+		
+	}
+
+	protected SimpleJoin getDefaultNewJoin(TableViewer joinColumnsTable) {
+		String table1Name = "";
+		String table2Name = "";
+		if( joinColumnsTable == this.joinColumnsTable1 ){
+			if( this.getJoinTableName() == null) {
+				table1Name = this.getReferrerTableName();
+				table2Name = this.getReferencedTableName() ;
+			}else{
+				table1Name = this.getReferrerTableName();
+				table2Name = this.getJoinTableName()  ;
+			}
+		}else{
+			table1Name = this.getJoinTableName();
+			table2Name = this.getReferencedTableName() ;
+		}
+		String[] table1ColumnValues = getTableColumns(table1Name);
+		String[] table2ColumnValues = getTableColumns(table2Name);
+		return new SimpleJoin(table1ColumnValues[0], table2ColumnValues[0]);
+	}
+
+	public boolean canFlipToNextPage() {
+		return isPageComplete();
+	}
+	
+	public void updatePageComplete() {
+		boolean ret = tableDataModel1.size()> 0 ;
+		setPageComplete( ret );
+	}	
+	
+	private Label createLabel(Composite container, int span, String text) {
+		Label label = new Label(container, SWT.NONE);
+		label.setText(text);
+		GridData gd = new GridData();
+		gd.horizontalSpan = span;
+		label.setLayoutData(gd);
+		return label;
+	}
+
+	private void createJoinColumnsTableControl1(Composite tablesGroup) {
+		joinColumnsDescLabel1 = createLabel(tablesGroup, 2, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label );
+		joinColumnsTable1 = createJoinColumnsTableControl(tablesGroup, this.tableDataModel1);
+		createAddRemoveButtonComposite(tablesGroup, joinColumnsTable1, tableDataModel1);
+	}
+	
+	private void createJoinColumnsTableControl2(Composite tablesGroup) {
+		joinColumnsDescLabel2 = createLabel(tablesGroup, 2, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label );
+		joinColumnsTable2 = createJoinColumnsTableControl(tablesGroup, this.tableDataModel2);
+		createAddRemoveButtonComposite(tablesGroup, joinColumnsTable2, tableDataModel2);
+	}
+	
+	private TableViewer createJoinColumnsTableControl(Composite parent, ArrayList<SimpleJoin> tableDataModel ){	
+	
+		TableLayoutComposite layout= new TableLayoutComposite(parent, SWT.NONE);
+		addColumnLayoutData(layout);
+		
+		final org.eclipse.swt.widgets.Table table = new org.eclipse.swt.widgets.Table(layout, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER );
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		
+		TableColumn referrerColumn = new TableColumn(table, SWT.NONE, JOINCOLUMN1_COLUMN_INDEX);
+		referrerColumn.setText("%table1");
+		referrerColumn.setResizable(true);
+
+		TableColumn referencedColumn = new TableColumn(table, SWT.NONE, JOINCOLUMN2_COLUMN_INDEX);
+		referencedColumn.setText("%table2");
+		referencedColumn.setResizable(true);
+		
+		GridData gd= new GridData(GridData.FILL_BOTH);
+		gd.heightHint= SWTUtil.getTableHeightHint(table, 3);
+		gd.widthHint = 300;
+		layout.setLayoutData(gd);
+
+		TableViewer newJoinColumnsTable = new TableViewer(table);
+		newJoinColumnsTable.setUseHashlookup(true);
+		newJoinColumnsTable.setLabelProvider(this.buildTableTableLabelProvider());
+		newJoinColumnsTable.setContentProvider(this.buildTableTableContentProvider());
+		newJoinColumnsTable.setSorter(new ViewerSorter() {
+			public int compare(Viewer viewer, Object e1, Object e2) {
+				return ((SimpleJoin) e1).foreignKey.compareTo(((SimpleJoin) e2).foreignKey);
+			}
+		});
+		
+		newJoinColumnsTable.addPostSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				//handleTablesListSelectionChanged(event);
+			}
+		});
+		populateTableDataModel();
+		newJoinColumnsTable.setInput( tableDataModel );
+		return newJoinColumnsTable;
+	}
+
+	@SuppressWarnings("unchecked")
+	public void populateTableDataModel(){
+		HashMap<String, Object> dataModel = (HashMap<String, Object> )getWizardDataModel();
+		TreeMap<String, String> joinColumns = (TreeMap<String, String>)dataModel.get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1);
+		if( joinColumns!= null ){
+			for( String referrerColumn : joinColumns.keySet() ){
+				tableDataModel1.add(new SimpleJoin(referrerColumn, joinColumns.get(referrerColumn) ));
+			}
+		}
+		
+		TreeMap<String, String> joinColumns2 = (TreeMap<String, String>)dataModel.get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2);
+		if( joinColumns2!= null ){
+			for( String referrerColumn : joinColumns2.keySet() ){
+				tableDataModel2.add(new SimpleJoin(referrerColumn, joinColumns2.get(referrerColumn) ));
+			}
+		}
+		
+	}
+	
+	private IContentProvider buildTableTableContentProvider() {
+		return new JoinColumnsContentProvider();
+	}
+
+	
+	private IBaseLabelProvider buildTableTableLabelProvider() {
+		return new JoinColumnsTableLabelProvider();
+	}
+	
+	
+	private void addColumnLayoutData(TableLayoutComposite layout) {
+		layout.addColumnData(new ColumnWeightData(50, true));
+		layout.addColumnData(new ColumnWeightData(50, true));
+	}
+	
+	
+	private void updateCellEditors(TableViewer joinColumnsTable, String[] referrerColumnValues, String[] referencedColumnValues ){
+		joinColumnsTable.setColumnProperties(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES);
+		ComboBoxCellEditor[] editors = new ComboBoxCellEditor[JOINCOLUMNS_TABLE_COLUMN_PROPERTIES.length];
+
+		editors[JOINCOLUMN1_COLUMN_INDEX]= new ComboBoxCellEditor(joinColumnsTable.getTable(), referrerColumnValues, SWT.SINGLE);
+		editors[JOINCOLUMN2_COLUMN_INDEX]= new ComboBoxCellEditor(joinColumnsTable.getTable(), referencedColumnValues, SWT.SINGLE);
+		
+		joinColumnsTable.setCellEditors(editors);
+		joinColumnsTable.setCellModifier(this.buildTableTableCellModifier(joinColumnsTable, referrerColumnValues, referencedColumnValues ));
+	}
+
+	public String[] getTableColumns(String tableName){
+		Schema schema = (Schema)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_SCHEMA);
+		Table table = schema.getTableNamed(tableName);
+		Iterator<Column> columns = table.columns() ;
+		List<String> list = new ArrayList<String>();
+		while( columns.hasNext() ){
+			list.add(columns.next().getName());
+		}
+		String[] ret = new String[list.size()];
+		list.toArray(ret);
+		return ret;
+	}
+	
+	private ICellModifier buildTableTableCellModifier(TableViewer joinColumnsTable, String[] referrerColumnValues, String[] referencedColumnValues) {
+		return new JoinColumnsCellModifier(joinColumnsTable, referrerColumnValues, referencedColumnValues);
+	}	
+	
+	/**
+	 * A ContentProvider translates the SimpleJoin list into a Collection for display 
+	 *
+	 */
+	private class JoinColumnsContentProvider implements IStructuredContentProvider {
+
+		JoinColumnsContentProvider() {
+			super();
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}	
+		public void dispose() {}
+		public Object[] getElements(Object inputElement) {
+			return ((Collection<?>) inputElement).toArray();
+		}
+	}
+	
+	/**
+	 * Simple value object used as model backing the JFace table 
+	 *
+	 */
+	private class SimpleJoin {
+		public SimpleJoin(String foreignKey, String primaryKey) {
+			this.foreignKey = foreignKey;
+			this.primaryKey = primaryKey; 
+		}
+		public String foreignKey;
+		public String primaryKey;
+		
+		public String toString(){
+			return "["+ this.foreignKey + " = " + this.primaryKey + "]";
+		}
+	}
+	
+	/**
+	 *	A CellModifier to update the join columns in the wizard data model
+	 */
+	private class JoinColumnsCellModifier implements ICellModifier {
+		private TableViewer joinColumnsTable;
+		private String[] referrerColumnValues;
+		private String[] referencedColumnValues;
+		JoinColumnsCellModifier(TableViewer joinColumnsTable, String[] referrerColumnValues, String[] referencedColumnValues) {
+			super();
+			this.joinColumnsTable = joinColumnsTable;
+			this.referrerColumnValues = referrerColumnValues;
+			this.referencedColumnValues = referencedColumnValues;
+		}
+
+		public boolean canModify(Object element, String property) {
+			return true;
+		}
+
+		@SuppressWarnings("unchecked")
+		public Object getValue(Object element, String property) {
+//			SimpleJoin join = (SimpleJoin) element;
+//			if (property.equals(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES[JOINCOLUMN2_COLUMN_INDEX])) {
+//				return join.primaryKey;
+//			}
+//			return join.foreignKey;
+			// returnt the index of the value in the ComboxCellEditor
+			ArrayList<SimpleJoin> tableDataModel = (ArrayList<SimpleJoin>) joinColumnsTable.getInput();
+			for(int i=0; i< tableDataModel.size(); i ++ ){
+				if( tableDataModel.get(i) == element )
+					return new Integer(i);
+			}
+			return new Integer(0);
+			
+		}
+
+		/** 
+		 * element is the selected TableItem
+		 * value is the selected item index in the comboCellEditor 
+		 */
+		@SuppressWarnings("unchecked")
+		public void modify(Object element, String property, Object value) {
+			if ( ! (element instanceof TableItem)) {
+				return;
+			}
+			Integer index = (Integer)value;
+			TableItem item = (TableItem)element;
+			boolean unchanged = false;
+			SimpleJoin join = (SimpleJoin) item.getData();
+			if (property.equals(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES[JOINCOLUMN1_COLUMN_INDEX])) {
+				unchanged = join.foreignKey.equals( referrerColumnValues[ index.intValue() ] );
+				if (! unchanged) {
+					
+					//update the wizard datamodel
+					TreeMap<String, String> joins = null;
+					if( joinColumnsTable == joinColumnsTable1 ){
+						joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 );
+					}else{
+						joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 );
+					}
+					joins.remove(join.foreignKey);
+					joins.put(referrerColumnValues[ index.intValue() ], join.primaryKey);
+
+					//Update the TableViewer model
+					join.foreignKey = referrerColumnValues[ index.intValue()];
+					joinColumnsTable.refresh();
+				}
+				return;
+			}
+			
+			if (property.equals(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES[JOINCOLUMN2_COLUMN_INDEX])) {
+				unchanged = join.primaryKey.equals( referencedColumnValues[ index.intValue()] ) ;
+				if (! unchanged) {
+					//Update the TableViewer model
+					join.primaryKey = referencedColumnValues[ index.intValue()] ;
+					
+					//Update wizard data model
+					TreeMap<String, String> joins = null;
+					if( joinColumnsTable == joinColumnsTable1 ){
+						joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 );
+					}else{
+						joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 );
+					}
+					joins.put(join.foreignKey, join.primaryKey);
+
+					joinColumnsTable.refresh();
+				}
+			}
+			
+			
+		}
+
+	}
+
+	/**
+	 * A table label provider to return the join column names for display
+	 *
+	 */
+	private final class JoinColumnsTableLabelProvider extends LabelProvider implements ITableLabelProvider {
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+		public String getColumnText(Object element, int columnIndex) {
+			if( !(element instanceof SimpleJoin) )
+				return null;
+			switch (columnIndex) {
+	            case 0:
+	            	return ((SimpleJoin)element).foreignKey;
+	            case 1:
+	            	return ((SimpleJoin)element).primaryKey;
+	            default:
+	            	Assert.isTrue(false);
+	            	return null;
+            }
+		}
+		public String getText(Object element) {
+		    return getColumnText(element, 0); // needed to make the sorter work
+		}
+	}
+	
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JptUiEntityGenMessages.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JptUiEntityGenMessages.java
new file mode 100644
index 0000000..4a90b55
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JptUiEntityGenMessages.java
@@ -0,0 +1,112 @@
+package org.eclipse.jpt.ui.internal.wizards.gen;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Localized messages used by Dali UI.
+ *
+ * @version 2.0
+ * @since 2.0
+ */
+public class JptUiEntityGenMessages {
+	private static final String BUNDLE_NAME = "jpt_ui_entity_gen"; //$NON-NLS-1$
+	private static final Class<?> BUNDLE_CLASS = JptUiEntityGenMessages.class;
+	public static String GenerateEntitiesWizard_generateEntities;
+	public static String GenerateEntitiesWizard_fileWillBeOverwritten;
+	public static String WarningDialogTitle;
+	public static String GenerateEntitiesWizard_doNotShowWarning;
+	public static String GenerateEntitiesWizard_selectJPAProject;
+	public static String GenerateEntitiesWizard_selectJPAProject_msg;
+	public static String GenerateEntitiesWizard_tableSelectPage_selectTable;
+	public static String GenerateEntitiesWizard_tableSelectPage_chooseEntityTable;
+	public static String GenerateEntitiesWizard_tableSelectPage_synchronizeClasses;
+	public static String GenerateEntitiesWizard_tableSelectPage_tables;
+	public static String GenerateEntitiesWizard_tableSelectPage_tableColumn;
+	//Database connection group
+	public static String connection;
+	public static String addConnectionLink;
+	public static String connectLink;
+	public static String schemaInfo;
+	public static String schema;
+	
+	//Default table gen properties
+	public static String GenerateEntitiesWizard_defaultTablePage_title;
+	public static String GenerateEntitiesWizard_defaultTablePage_desc;
+	public static String GenerateEntitiesWizard_defaultTablePage_domainJavaClass;
+	public static String GenerateEntitiesWizard_defaultTablePage_tableMapping;
+	public static String GenerateEntitiesWizard_tablePanel_className;
+	public static String GenerateEntitiesWizard_defaultTablePage_fetch;
+	public static String GenerateEntitiesWizard_defaultTablePage_collType;
+	public static String GenerateEntitiesWizard_defaultTablePage_sequence;
+	public static String GenerateEntitiesWizard_defaultTablePage_sequenceNote;
+	public static String GenerateEntitiesWizard_defaultTablePage_access;
+	public static String GenerateEntitiesWizard_defaultTablePage_keyGen;
+	public static String GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations;
+	public static String GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations_desc;
+	
+	//Asso figure
+	public static String manyToOneDesc;
+	public static String oneToOneDesc;
+	public static String manyToManyDesc;
+	//table association wizard page
+	public static String GenerateEntitiesWizard_assocPage_title;
+	public static String GenerateEntitiesWizard_assocPage_desc;
+	public static String GenerateEntitiesWizard_assocPage_label;
+	public static String GenerateEntitiesWizard_assocPage_newAssoc;
+	public static String GenerateEntitiesWizard_assocPage_delAssoc;
+	public static String GenerateEntitiesWizard_assocEditor_genAssoc;
+	public static String GenerateEntitiesWizard_assocEditor_entityRef;
+	public static String property;
+	public static String cascade;
+	public static String GenerateEntitiesWizard_assocEditor_setRef;
+	public static String GenerateEntitiesWizard_assocEditor_joinedWhen;
+	public static String GenerateEntitiesWizard_assocEditor_tableJoin;
+	public static String cardinality;
+	public static String selectCascadeDlgTitle;
+	//new association wizard
+	public static String GenerateEntitiesWizard_newAssoc_title;
+	public static String GenerateEntitiesWizard_newAssoc_tablesPage_title;
+	public static String GenerateEntitiesWizard_newAssoc_tablesPage_desc;
+	public static String GenerateEntitiesWizard_newAssoc_tablesPage_assocKind;
+	public static String GenerateEntitiesWizard_newAssoc_tablesPage_simpleAssoc;
+	public static String GenerateEntitiesWizard_newAssoc_tablesPage_m2mAssoc;
+	public static String GenerateEntitiesWizard_newAssoc_tablesPage_assocTables;
+	public static String GenerateEntitiesWizard_newAssoc_tablesPage_table1;
+	public static String GenerateEntitiesWizard_newAssoc_tablesPage_table2;
+	public static String GenerateEntitiesWizard_newAssoc_colsPage_title;
+	public static String GenerateEntitiesWizard_newAssoc_colsPage_desc;
+	public static String GenerateEntitiesWizard_newAssoc_colsPage_label;
+	public static String add;
+	public static String remove;
+	public static String GenerateEntitiesWizard_newAssoc_cardinalityPage_title;
+	public static String GenerateEntitiesWizard_newAssoc_cardinalityPage_desc;
+	public static String manyToOne;
+	public static String oneToMany;
+	public static String oneToOne;
+	public static String manyToMany;
+	//select table dialog
+	public static String AnnotateJavaClassWizard_classMappingPage_selectTableDlgTitle;
+	public static String AnnotateJavaClassWizard_classMappingPage_selectTableDlgDesc;
+	//individual table and column gen properties
+	public static String GenerateEntitiesWizard_tablesAndColumnsPage_title;
+	public static String GenerateEntitiesWizard_tablesAndColumnsPage_desc;
+	public static String GenerateEntitiesWizard_tablesAndColumnsPage_labelTableAndColumns;
+	public static String GenerateEntitiesWizard_colPanel_genProp;
+	public static String GenerateEntitiesWizard_colPanel_colMapping;
+	public static String GenerateEntitiesWizard_colPanel_propName;
+	public static String GenerateEntitiesWizard_colPanel_propType;
+	public static String GenerateEntitiesWizard_colPanel_mapKind;
+	public static String GenerateEntitiesWizard_colPanel_colUpdateable;
+	public static String GenerateEntitiesWizard_colPanel_colInsertable;
+	public static String GenerateEntitiesWizard_colPanel_beanProp;
+	public static String GenerateEntitiesWizard_colPanel_getterScope;
+	public static String GenerateEntitiesWizard_colPanel_setterScope;
+	static {
+		NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS);
+	}
+
+	private JptUiEntityGenMessages() {
+		throw new UnsupportedOperationException();
+	}
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizard.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizard.java
new file mode 100644
index 0000000..ef6e3b5
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizard.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.TreeMap;
+
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.gen.internal2.Association;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+
+
+public class NewAssociationWizard extends Wizard {	
+
+	public static String ASSOCIATION_SCHEMA = "ASSOCIATION_SCHEMA";
+	public static String ASSOCIATION_REFERRER_TABLE = "ASSOCIATION_REFERRER_TABLE";
+	public static String ASSOCIATION_REFERENCED_TABLE = "ASSOCIATION_REFERENCED_TABLE";
+	public static String ASSOCIATION_JOIN_COLUMNS1 = "ASSOCIATION_REFERRER_COLUMNS1";
+	public static String ASSOCIATION_JOIN_COLUMNS2 = "ASSOCIATION_REFERRER_COLUMNS2"; //used in MTM associations only
+	public static String ASSOCIATION_JOIN_TABLE = "ASSOCIATION_JOIN_TABLE"; // TreeMap<String, String>
+	public static String ASSOCIATION_CADINALITY = "ASSOCIATION_CADINALITY";
+	
+	private JpaProject jpaProject;
+	private HashMap<String, Object> associationDataModel = new HashMap<String, Object>();
+
+	private ORMGenCustomizer customizer = null;	
+	
+	private AssociationTablesPage associationTablesPage;
+	private JoinColumnsPage joinColumnsPage;
+	private CardinalityPage cardinalityPage;
+	
+	public NewAssociationWizard( JpaProject jpaProject, ORMGenCustomizer customizer ) {
+		super();
+		this.jpaProject = jpaProject;
+		this.customizer = customizer;
+		this.setWindowTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_title);
+		
+		this.associationDataModel.put( NewAssociationWizard.ASSOCIATION_SCHEMA, this.customizer.getSchema());
+		this.associationDataModel.put( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1, new TreeMap<String, String>());
+		this.associationDataModel.put( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2, new TreeMap<String, String>());
+	}
+
+	public void addPages() {
+		super.addPages();
+		this.associationTablesPage = new AssociationTablesPage( customizer );
+		addPage(this.associationTablesPage);
+		
+		this.joinColumnsPage = new JoinColumnsPage(customizer);
+		addPage(this.joinColumnsPage);
+		
+		this.cardinalityPage = new CardinalityPage(customizer);
+		addPage(this.cardinalityPage);
+	}
+
+	public boolean performFinish() {
+		return true;
+	}
+	
+	public ORMGenCustomizer getCustomizer (){
+		return customizer;
+	} 
+	
+	public JpaProject getJpaProject(){
+		return this.jpaProject;
+	}
+
+//	public Schema getDefaultSchema() {
+//		return getJpaProject().getDefaultDbSchema();
+//	}
+//
+//	private boolean projectDefaultSchemaExists() {
+//		return ( this.getDefaultSchema() != null);
+//	}
+
+	public HashMap<String, Object> getDataModel(){
+		return this.associationDataModel;
+	}
+	
+	public void updateTableNames(){
+		IWizardPage[] pages = this.getPages();
+		for( IWizardPage page : pages){
+			((NewAssociationWizardPage)page).updateWithNewTables();
+		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	public Association getNewAssociation(){
+		String referrerTableName =getReferrerTableName(); 
+		String referencedTableName = getReferencedTableName();
+		List<String> referrerColNames = new ArrayList<String>();
+		List<String> referencedColNames = new ArrayList<String>();
+		
+		String cardinality = (String)associationDataModel.get( NewAssociationWizard.ASSOCIATION_CADINALITY );
+		if( cardinality.equals(Association.MANY_TO_MANY) ){
+			return createManyToManyAssociation();
+		}
+		
+		Object value = associationDataModel.get( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1);
+		if(value!=null){
+			TreeMap<String, String> joinColumns = (TreeMap<String, String>)value;		
+			for( String pk : joinColumns.keySet()){
+				referrerColNames.add(pk);
+				referencedColNames.add( joinColumns.get(pk));
+			}
+		}
+
+		/*if one-to-many then convert it to many-to-one to be consistent 
+		 * with the associations computed from the db foreign keys.
+		 * Don't see at this point how one-to-many would 
+		 * affect the generation.*/
+		if( cardinality.equals(Association.ONE_TO_MANY) ){
+			cardinality = Association.MANY_TO_ONE;
+			
+			String temp1 = referrerTableName;
+			referrerTableName = referencedTableName;
+			referencedTableName = temp1;
+			
+			List<String> temp2 = referrerColNames;
+			referrerColNames = referencedColNames;
+			referencedColNames = temp2;
+		}
+		
+		Association association = null;
+		association = new Association(this.customizer, referrerTableName, referrerColNames	, referencedTableName, referencedColNames);
+		association.setCardinality( cardinality );
+		association.setCustom(true);
+		return association;
+	}
+	
+	@SuppressWarnings("unchecked")
+	private Association createManyToManyAssociation() {
+		String referrerTableName =getReferrerTableName(); 
+		String joinTable = getJoinTableName();
+		String referencedTableName = getReferencedTableName();
+
+		List<String> referrerColNames = new ArrayList<String>();
+		List<String> referrerJoinColNames = new ArrayList<String>();
+		Object value = associationDataModel.get( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1);
+		if(value!=null){
+			TreeMap<String, String> joinColumns = (TreeMap<String, String>)value;		
+			for( String pk : joinColumns.keySet()){
+				referrerColNames.add(pk);
+				referrerJoinColNames.add( joinColumns.get(pk));
+			}
+		}
+		
+		value = associationDataModel.get( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2);
+		List<String> referencedColNames = new ArrayList<String>();
+		List<String> referencedJoinColNames = new ArrayList<String>();
+		if(value!=null){
+			TreeMap<String, String> joinColumns = (TreeMap<String, String>)value;		
+			for( String pk : joinColumns.keySet()){
+				referencedJoinColNames.add(pk);
+				referencedColNames.add( joinColumns.get(pk));
+			}
+		}
+
+		
+		Association association = null;
+		association = new Association(this.customizer, referrerTableName, referrerColNames, 
+				referencedTableName, referencedColNames, joinTable, referrerJoinColNames, referencedJoinColNames);
+		return association;
+	}
+
+	String getReferrerTableName(){
+		return (String)associationDataModel.get(NewAssociationWizard.ASSOCIATION_REFERRER_TABLE);
+	}
+
+	String getReferencedTableName(){
+		return (String)associationDataModel.get(NewAssociationWizard.ASSOCIATION_REFERENCED_TABLE);
+	}
+	
+	String getJoinTableName(){
+		return (String)associationDataModel.get(NewAssociationWizard.ASSOCIATION_JOIN_TABLE );
+	}
+	
+	String getCardinality(){
+		return (String)associationDataModel.get(NewAssociationWizard.ASSOCIATION_CADINALITY );
+	}
+	
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizardPage.java
new file mode 100644
index 0000000..6eaf73e
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizardPage.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+
+
+public abstract class NewAssociationWizardPage extends WizardPage {
+
+	protected ORMGenCustomizer customizer;
+	
+	public NewAssociationWizardPage(ORMGenCustomizer customizer, String name) {
+		super(name);
+		this.customizer = customizer ;
+	}
+	
+	protected HashMap<String, Object> getWizardDataModel(){
+		return ((NewAssociationWizard)this.getWizard()).getDataModel();
+	}
+	
+	protected String getReferrerTableName(){
+		return ((NewAssociationWizard)getWizard()).getReferrerTableName();
+	}
+
+	protected String getReferencedTableName(){
+		return ((NewAssociationWizard)getWizard()).getReferencedTableName();
+	}
+
+	protected String getJoinTableName(){
+		return ((NewAssociationWizard)getWizard()).getJoinTableName();
+	}
+
+	protected String getCardinality(){
+		return ((NewAssociationWizard)getWizard()).getCardinality() ;
+	}
+	
+	public void updateWithNewTables() {
+	}
+	
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/PromptJPAProjectWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/PromptJPAProjectWizardPage.java
new file mode 100644
index 0000000..5189394
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/PromptJPAProjectWizardPage.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.core.JptCorePlugin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.PlatformUI;
+
+public class PromptJPAProjectWizardPage extends WizardPage {
+
+	private static String SELECT_PROJECT_PAGE_NAME = "SelectJPAProject"; //$NON-NLS-1$
+	private Table projTable;
+	private TableViewer projTableViewer;
+	private static int PROJECT_NAME_COLUMN_INDEX = 0;
+	private final String helpContextId;
+	
+	protected PromptJPAProjectWizardPage( final String helpContextId ) {
+		super(SELECT_PROJECT_PAGE_NAME);
+		setTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_selectJPAProject );
+		setMessage( JptUiEntityGenMessages.GenerateEntitiesWizard_selectJPAProject_msg );
+		this.helpContextId = helpContextId;
+	}
+
+	public void createControl(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NULL);
+		int nColumns= 1;
+		GridLayout layout = new GridLayout();
+		layout.numColumns = nColumns;
+		composite.setLayout(layout);			
+		Label label = new Label( composite, SWT.NONE );
+		label.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_selectJPAProject );
+		
+		projTableViewer = new TableViewer(composite, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL | SWT.VIRTUAL);		
+		projTable = projTableViewer.getTable();
+		GridData gd = new GridData( SWT.FILL, SWT.FILL, true, true );
+		projTable.setLayoutData(gd);
+				
+		projTable.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				handleJpaProjectSelection();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+			
+		});
+		
+		projTableViewer = new TableViewer(projTable);
+		projTableViewer.setLabelProvider(new ProjectTableLabelProvider());
+		projTableViewer.setContentProvider(new ProjectTableContentProvider());
+		fillJpaProjectList();
+		setControl( composite );
+		validate();
+	}
+	
+	private void handleJpaProjectSelection() {
+		if (projTable.getSelectionIndex() != -1) {
+			TableItem item =  projTable.getItem(projTable.getSelectionIndex());
+			String projName = item.getText(0);
+			IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projName);
+			JpaProject jpaProj = JptCorePlugin.getJpaProject( project );
+			((GenerateEntitiesFromSchemaWizard)getWizard()).setJpaProject(jpaProj);
+			validate();
+		}
+	}
+	
+	private void fillJpaProjectList() {
+		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+		List<String> projNames = new ArrayList<String>();
+		for ( IProject project : projects )
+		{
+			JpaProject jpaProj = JptCorePlugin.getJpaProject( project );
+			if ( jpaProj != null ) {
+				projNames.add(project.getName());
+			}
+		}
+		projTableViewer.setInput(projNames);
+	}
+	
+	private void validate() {
+		if (projTable.getSelectionIndex() != -1)
+			setPageComplete(true);
+		else
+			setPageComplete(false);
+	}
+	
+	@Override
+	public final void performHelp() 
+	{
+	    PlatformUI.getWorkbench().getHelpSystem().displayHelp( this.helpContextId );
+	}
+
+	// inner classes
+	private final class ProjectTableLabelProvider extends LabelProvider implements ITableLabelProvider {
+		public Image getColumnImage(Object element, int columnIndex)
+		{
+			if (columnIndex == PROJECT_NAME_COLUMN_INDEX)
+				return PlatformUI.getWorkbench().getSharedImages().getImage(org.eclipse.ui.ide.IDE.SharedImages.IMG_OBJ_PROJECT);
+			return null;
+		}
+
+		public String getColumnText(Object element, int columnIndex)
+		{
+			assert element instanceof String;
+			String projectName = (String)element;
+			if (columnIndex == PROJECT_NAME_COLUMN_INDEX)
+				return projectName;
+			return null;
+		}		
+	}
+	
+	private final class ProjectTableContentProvider implements IStructuredContentProvider
+	{
+		public Object[] getElements(Object inputElement){
+			return ((Collection<?>) inputElement).toArray();
+		}
+
+		public void dispose(){}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput){}
+		
+	}
+}	
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SWTUtil.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SWTUtil.java
new file mode 100644
index 0000000..98b6b61
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SWTUtil.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Collection of utility methods to create SWT UI
+ *
+ */
+public class SWTUtil {
+	/**
+	 * Set the layoutData of the input control to occupy specified number of columns
+	 * @param c
+	 * @param columns
+	 */
+	public static void fillColumns(Control c, int columns){
+		GridData layoutData = new GridData();
+		layoutData.horizontalSpan = columns;
+		layoutData.verticalAlignment = SWT.FILL;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = true;
+		layoutData.grabExcessVerticalSpace = false;
+		c.setLayoutData(layoutData);
+		return ;
+	}
+
+	public static void fillColumnsWithIndent(Control c, int columns, int indent){
+		GridData layoutData = new GridData();
+		layoutData.horizontalSpan = columns;
+		layoutData.verticalAlignment = SWT.FILL;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = true;
+		layoutData.grabExcessVerticalSpace = false;
+		layoutData.horizontalIndent = indent ;
+		c.setLayoutData(layoutData);
+		return ;
+	}
+	
+	public static Label createLabel(Composite container, int span, String text) {
+		Label label = new Label(container, SWT.NONE);
+		label.setText(text);
+		GridData gd = new GridData();
+		gd.horizontalSpan = span;
+		label.setLayoutData(gd);
+		return label;
+	}
+
+	/**
+	 * Create a new label which occupies one grid column
+	 * @param parent
+	 * @param text
+	 */
+	public static Label newLabel(Composite parent, String text) {
+		Label label = new Label( parent, SWT.NONE);
+		label.setText( text );
+		label.setLayoutData(new GridData());
+		return label;
+	}
+
+	/**
+	 * Create a new label which occupies one grid column
+	 * @param parent
+	 * @param text
+	 */
+	public static Label newLabelWithIndent(Composite parent, String text, int indent) {
+		Label label = new Label( parent, SWT.NONE);
+		label.setText( text );
+		GridData layoutData = new GridData();
+		layoutData.horizontalAlignment = SWT.BEGINNING;
+		layoutData.verticalAlignment = SWT.TOP ;
+		layoutData.horizontalIndent = indent ;
+		label.setLayoutData(layoutData);
+		return label;
+	}
+	
+	/**
+	 * Creates a separator line. Expects a <code>GridLayout</code> with at least 1 column.
+	 * 
+	 * @param composite the parent composite
+	 * @param nColumns number of columns to span
+	 */
+	@SuppressWarnings("restriction")
+	public static void createSeparator(Composite composite, int nColumns) {
+		(new org.eclipse.jdt.internal.ui.wizards.dialogfields.Separator(
+				SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, 5);		
+	}
+
+	
+	public static Button createButton(Composite container, int span, String text, int style) {
+		Button btn = new Button(container, style);
+		btn.setText(text);
+		GridData gd = new GridData();
+		gd.horizontalSpan = span;
+		btn.setLayoutData(gd);
+		return btn;
+	}
+	
+	public static Combo createCombo(Composite container, int span ) {
+		Combo combo = new Combo(container, SWT.SINGLE | SWT.READ_ONLY);
+		GridData gd = new GridData();
+		gd.horizontalSpan = span;
+		gd.grabExcessHorizontalSpace=true;
+		gd.horizontalAlignment = SWT.FILL;
+		combo.setLayoutData(gd);
+		return combo;
+	}
+
+	public static Text createText(Composite container, int span ) {
+		Text text = new Text(container, SWT.BORDER);
+		GridData gd = new GridData();
+		gd.horizontalSpan = span;
+		gd.grabExcessHorizontalSpace=true;
+		gd.horizontalAlignment = SWT.FILL;
+		text.setLayoutData(gd);
+		return text;
+	}
+	
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SelectTableDialog.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SelectTableDialog.java
new file mode 100644
index 0000000..66311e5
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SelectTableDialog.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jpt.db.Schema;
+import org.eclipse.jpt.db.Table;
+import org.eclipse.jpt.ui.CommonImages;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+
+/**
+ * A database table selection dialog which allows user to filter tables by name
+ */
+public class SelectTableDialog extends ElementListSelectionDialog {
+	
+	public SelectTableDialog(Shell shell){
+		super(shell, new ILabelProvider(){
+			public Image getImage(Object element) {
+				return CommonImages.createImage(CommonImages.TABLE_IMAGE) ;
+			}
+
+			public String getText(Object element) {
+				return element.toString();
+			}
+			public void addListener(ILabelProviderListener listener) {}
+			public void dispose() {}
+
+			public boolean isLabelProperty(Object element, String property) {
+				return false;
+			}
+
+			public void removeListener(ILabelProviderListener listener) {}
+
+		});
+		this.setTitle( JptUiEntityGenMessages.AnnotateJavaClassWizard_classMappingPage_selectTableDlgTitle );//
+		this.setMessage( JptUiEntityGenMessages.AnnotateJavaClassWizard_classMappingPage_selectTableDlgDesc);//
+	}
+	
+	public SelectTableDialog(Shell shell, Schema schema){
+		this(shell);
+		
+		ArrayList<String> list = new ArrayList<String>();
+		Iterator<Table> tablesIt = schema.tables();
+		while (tablesIt.hasNext())
+		{
+			Table table = tablesIt.next();
+			list.add(table.getName());
+		}
+		this.setElements( list.toArray() );
+		
+	}	
+	
+	public SelectTableDialog(Shell shell, List<String> tableNames){
+		this(shell);
+		this.setElements( tableNames.toArray() );
+	}	
+	public String getSelectedTable()
+	{
+		String tableName = (String)this.getFirstResult();
+		return tableName ;
+	}
+	
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableAssociationsWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableAssociationsWizardPage.java
new file mode 100644
index 0000000..b36e5f6
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableAssociationsWizardPage.java
@@ -0,0 +1,751 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+
+import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.fillColumns;
+import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.newLabel;
+import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.newLabelWithIndent;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.ui.dialogs.StatusUtil;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.gen.internal2.Association;
+import org.eclipse.jpt.gen.internal2.AssociationRole;
+import org.eclipse.jpt.gen.internal2.ORMGenColumn;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+import org.eclipse.jpt.gen.internal2.util.DTPUtil;
+import org.eclipse.jpt.ui.CommonImages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+public class TableAssociationsWizardPage extends WizardPage {
+
+	private JpaProject jpaProject;
+	private ORMGenCustomizer customizer ;
+	
+	private AssociationsListComposite associationList; 
+	private Association selectedAssociation;
+	private Button deleteAssociationLink ;
+	private Button createAssociationLink ;
+	
+	//Controls in Association Edit Panel
+	private Composite associationsEditPanel ;
+	private Button generateAssociationCheckBox; 
+	private Label cardinalityLabel ;
+	private Combo cardinalityCombo ;
+	/*whether to generate the referrer-->referenced role.*/
+	private Button referrerRoleCheckBox; 
+	/*the name of the property in the referrer-->referenced role.*/
+	private Label referrerRolePropertyLabel;
+	private Text referrerRolePropertyField ;
+	/*the cascade in the referrer-->referenced role.*/
+	@SuppressWarnings("restriction")
+	private StringButtonDialogField referrerRoleCascadeField;
+	/*whether to generate the referenced->referrer role.*/
+	private Button referencedRoleCheckBox;
+	/*the name of the property in the referenced->referrer role.*/
+	private Label referencedRolePropertyLabel;
+	private Text referencedRolePropertyField ;
+	/*the cascade in the referenced->referrer role.*/
+	@SuppressWarnings("restriction")
+	private StringButtonDialogField referencedRoleCascadeField;
+	private Label joinConditionLabel;
+	private Text joinConditionText; 
+	
+	private Composite detailPanel ;
+	private StackLayout detailPanelStatckLayout ;
+	private Composite emptyPanel ;
+	
+	protected TableAssociationsWizardPage(JpaProject jpaProject ) {
+		super("Table Associations"); //$NON-NLS-1$
+		this.jpaProject = jpaProject;
+		setTitle(JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_title);
+		setMessage(JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_desc);
+		
+	}
+
+	public void createControl(Composite parent) {
+		initializeDialogUnits(parent);
+		
+		Composite composite = new Composite(parent, SWT.NULL);
+		int nColumns= 2 ;
+		GridLayout layout = new GridLayout();
+		layout.numColumns = nColumns;
+		composite.setLayout(layout);
+		//PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES);
+
+		Label label = new Label(composite, SWT.NONE);
+		label.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_label );
+		GridData gd = new GridData();
+		gd.horizontalSpan = 2;
+		label.setLayoutData( gd );
+		
+		createAssociationsListPanel(composite);
+		createAddDeleteButtons(composite, nColumns);
+		SWTUtil.createSeparator(composite, nColumns);
+		
+		createDetailPanel(composite);
+		setControl(composite);
+		
+		composite.layout(true);
+		this.setPageComplete( true);
+		
+	}
+
+	private void createAddDeleteButtons(Composite composite, int columns) {
+		
+		Composite c = new Composite( composite, SWT.NONE);
+		fillColumns(c, 1);
+		c.setLayout( new GridLayout(1,true) );
+		
+		createAssociationLink = new Button(c, SWT.NONE);
+		createAssociationLink.setToolTipText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_newAssoc );
+		createAssociationLink.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_ADD) );
+		createAssociationLink.addSelectionListener(new SelectionListener(){
+			public void widgetDefaultSelected(SelectionEvent e) {}	
+			public void widgetSelected(SelectionEvent e) {
+				launchNewAssociationsWizard();
+			}	
+			
+		});
+		
+		deleteAssociationLink = new Button(c, SWT.NONE);
+		deleteAssociationLink.setForeground( new Color(Display.getDefault(), 0,0,255));
+		deleteAssociationLink.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_DELETE)  );
+		deleteAssociationLink.setToolTipText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_delAssoc );
+		deleteAssociationLink.addSelectionListener(new SelectionListener(){
+			public void widgetDefaultSelected(SelectionEvent e) {}	
+			public void widgetSelected(SelectionEvent e) {
+				Association association = associationList.getSelectedAssociation();
+				if( association != null ){
+					ORMGenCustomizer customizer = getCustomizer();
+					customizer.deleteAssociation(association);
+					List<Association> associations = customizer.getAssociations();
+					associationList.updateAssociations(associations);
+					if( associations.size()==0 ){
+						hideAssociationDetail();
+					}
+				}
+			}	
+		});
+		deleteAssociationLink.setEnabled(false);
+		
+	}
+
+	private void createGenerateAssociationCheckbox(Composite composite,  int columns) {
+		generateAssociationCheckBox = new Button(composite, SWT.CHECK);
+		generateAssociationCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_genAssoc);
+		generateAssociationCheckBox.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+		
+			public void widgetSelected(SelectionEvent e) {
+				Association association = associationList.getSelectedAssociation();
+				if( association == null )
+					return;
+				association.setGenerated(generateAssociationCheckBox.getSelection());
+				
+				updateAssociationEditPanel(association);
+				associationList.updateSelectedAssociation();
+			}
+
+		});
+
+		fillColumns(generateAssociationCheckBox, columns-1);
+		newLabel(composite, "");
+	}
+
+	@SuppressWarnings("restriction")
+	private void createGenerateReferrerRoleControls(Composite parent,  int columns) {
+		referrerRoleCheckBox = new Button(parent, SWT.CHECK);
+		referrerRoleCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_entityRef );
+		referrerRoleCheckBox.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+		
+			public void widgetSelected(SelectionEvent e) {
+				boolean generate = referrerRoleCheckBox.getSelection();
+				//referrerRolePropertyField.setEditable( generate );
+				referrerRolePropertyLabel.setEnabled( generate );
+				referrerRolePropertyField.setEnabled( generate );
+				referrerRoleCascadeField.setEnabled(generate);
+				
+				//If both referencedRoleCheckBox and referencedRoleCheckBox unchecked, 
+				//the association itself shouldn't be generated 
+				if( !generate && !referencedRoleCheckBox.getSelection()){
+					generateAssociationCheckBox.setSelection(false);
+					cardinalityLabel.setEnabled( false );
+					cardinalityCombo.setEnabled(false);
+					referrerRoleCheckBox.setEnabled(false);
+					referencedRoleCheckBox.setEnabled(false);
+				}
+				
+				directionalityCheckBoxChanged( );			
+				
+				if( generate ){
+					AssociationRole role = selectedAssociation.getReferrerRole();
+					referrerRolePropertyField.setText( role.getPropertyName() );
+				}
+			}
+
+		});
+
+		SWTUtil.fillColumnsWithIndent(referrerRoleCheckBox , columns-1, 20 );
+		newLabel(parent, "");//$NON-NLS-1$
+		
+		referrerRolePropertyLabel = newLabelWithIndent( parent,  JptUiEntityGenMessages.property, 40 ); //$NON-NLS-1$
+		referrerRolePropertyField = new Text( parent, SWT.BORDER);
+		fillColumns(referrerRolePropertyField, 2);
+		referrerRolePropertyField.addModifyListener(new ModifyListener(){
+			@SuppressWarnings("deprecation")
+			public void modifyText(ModifyEvent e) {
+				if( selectedAssociation.getReferrerRole() == null )
+					return;
+				String fieldName = referrerRolePropertyField.getText();
+				IStatus status = JavaConventions.validateFieldName( fieldName );
+				if( !status.matches(IStatus.ERROR) ){
+					selectedAssociation.getReferrerRole().setPropertyName(fieldName);
+				}
+				updateStatus(status);
+			}			
+		});
+
+		Label label = new Label( parent, SWT.NONE);
+		label.setText( "" );//$NON-NLS-1$
+		label.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL));
+		
+		referrerRoleCascadeField = new StringButtonDialogField( new IStringButtonAdapter(){
+			public void changeControlPressed(DialogField field) {
+				if( editCascade( selectedAssociation.getReferrerRole() )){
+					referrerRoleCascadeField.setText(selectedAssociation.getReferrerRole().getCascade());
+				}
+			}	
+		}) ;
+		referrerRoleCascadeField.setLabelText( JptUiEntityGenMessages.cascade ); //$NON-NLS-1$
+		referrerRoleCascadeField.setButtonLabel(""); //$NON-NLS-1$
+		referrerRoleCascadeField.doFillIntoGrid(parent, 3);
+		referrerRoleCascadeField.getTextControl(parent).setEditable(false);
+		int maxFieldWidth = convertWidthInCharsToPixels(40);
+		LayoutUtil.setWidthHint(referrerRoleCascadeField.getTextControl(null), maxFieldWidth );
+		Button btn = referrerRoleCascadeField.getChangeControl(null);
+		GridData data = (GridData)btn.getLayoutData();
+		btn.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE) );
+		data.horizontalAlignment = SWT.BEGINNING;
+		data.widthHint = 30;
+		btn.setLayoutData(data);
+		
+		Label labelCtrl  = referrerRoleCascadeField.getLabelControl(parent);
+		data = (GridData)labelCtrl.getLayoutData();
+		data.horizontalIndent = 40 ;
+		labelCtrl.setLayoutData(data);
+		
+		
+		label = new Label( parent, SWT.NONE);
+		label.setText( "" );//$NON-NLS-1$
+		label.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL));
+		
+	}	
+	
+	
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if( visible ){
+			hideAssociationDetail();
+			updateAssociationsListPanel();
+		}
+	}
+
+	private void hideAssociationDetail( ){
+		this.detailPanelStatckLayout.topControl = emptyPanel;
+		this.detailPanel.layout();
+		this.detailPanel.getParent().layout();
+	}
+	
+	/**
+	 * Updates the status line and the OK button according to the given status
+	 * 
+	 * @param status status to apply
+	 */
+	@SuppressWarnings("restriction")
+	protected void updateStatus(IStatus status) {
+		setPageComplete(!status.matches(IStatus.ERROR));
+		
+		StatusUtil.applyToStatusLine(this, status);
+		if( status.getCode() == Status.OK ){
+			setMessage(JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_desc);
+		}
+	}
+	
+	@SuppressWarnings("restriction")
+	private void createGenerateReferencedRoleControls(Composite parent,  int columns) {
+		referencedRoleCheckBox = new Button(parent, SWT.CHECK);
+		referencedRoleCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_setRef );
+		referencedRoleCheckBox.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+		
+			public void widgetSelected(SelectionEvent e) {
+				boolean generate = referencedRoleCheckBox.getSelection();
+				referencedRolePropertyLabel.setEnabled( generate);
+				referencedRolePropertyField.setEnabled( generate);
+				referencedRoleCascadeField.setEnabled(generate);
+				
+				if( !generate && !referrerRoleCheckBox.getSelection()){
+					generateAssociationCheckBox.setSelection(false);
+					cardinalityCombo.setEnabled(false);
+					referrerRoleCheckBox.setEnabled(false);
+					referencedRoleCheckBox.setEnabled(false);
+				}
+				directionalityCheckBoxChanged();
+				if( generate ){
+					AssociationRole role = selectedAssociation.getReferencedRole();
+					referencedRolePropertyField.setText( role.getPropertyName() );
+				}
+			}
+
+		});
+
+		SWTUtil.fillColumnsWithIndent( referencedRoleCheckBox , columns-1, 20 );
+		newLabel(parent, "");//$NON-NLS-1$
+		
+		referencedRolePropertyLabel = SWTUtil.newLabelWithIndent(parent,  JptUiEntityGenMessages.property, 40 ); //$NON-NLS-1$
+		
+		referencedRolePropertyField = new Text( parent, SWT.BORDER);
+		fillColumns(referencedRolePropertyField, 2);
+		referencedRolePropertyField.addModifyListener(new ModifyListener(){
+			public void modifyText(ModifyEvent e) {
+				if( selectedAssociation.getReferencedRole() == null )
+					return ;
+				
+				String fieldName = referencedRolePropertyField.getText();
+				IStatus status = JavaConventions.validateIdentifier(fieldName,
+						CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+				if( !status.matches(IStatus.ERROR) ){
+					if( !fieldName.equals(selectedAssociation.getReferencedRole().getPropertyName()) )
+						selectedAssociation.getReferencedRole().setPropertyName(fieldName);
+				}
+				updateStatus(status);
+			}			
+		});
+		
+
+		Label label = new Label( parent, SWT.NONE);
+		label.setText( "" );//$NON-NLS-1$
+		label.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL));
+		
+		
+		referencedRoleCascadeField = new StringButtonDialogField( new IStringButtonAdapter(){
+			public void changeControlPressed(DialogField field) {
+				if( editCascade( selectedAssociation.getReferencedRole() ) ){
+					referencedRoleCascadeField.setText( selectedAssociation.getReferencedRole().getCascade() );
+				}
+			}	
+		}) ;
+		referencedRoleCascadeField.setLabelText( JptUiEntityGenMessages.cascade ); //$NON-NLS-1$
+		referencedRoleCascadeField.setButtonLabel(""); //$NON-NLS-1$
+		referencedRoleCascadeField.doFillIntoGrid(parent, 3);
+		referencedRoleCascadeField.getTextControl(parent).setEditable( false);
+		int maxFieldWidth = convertWidthInCharsToPixels(40);
+		LayoutUtil.setWidthHint(referencedRoleCascadeField.getTextControl(null), maxFieldWidth );
+		Button btn = referencedRoleCascadeField.getChangeControl(null);
+		btn.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE) );
+		GridData data = (GridData)btn.getLayoutData();
+		data.horizontalAlignment = SWT.BEGINNING;
+		data.widthHint = 30;
+		btn.setLayoutData(data);
+		
+		Label labelCtrl  = referencedRoleCascadeField.getLabelControl(parent);
+		data = (GridData)labelCtrl.getLayoutData();
+		data.horizontalIndent = 40 ;
+		labelCtrl.setLayoutData(data);
+		
+		label = new Label( parent, SWT.NONE);
+		label.setText( "" );//$NON-NLS-1$
+		label.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL));
+		
+	}	
+	
+	private void createDetailPanel(Composite composite ) {
+		
+		this.detailPanel = new Composite( composite, SWT.NONE);
+		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.grabExcessVerticalSpace = false;
+		this.detailPanel.setLayoutData(gd);
+		this.detailPanelStatckLayout = new StackLayout();
+		this.detailPanel.setLayout( this.detailPanelStatckLayout );
+		
+		emptyPanel = new Composite( detailPanel, SWT.NONE);
+		emptyPanel.setLayoutData(new GridData()); 
+		detailPanelStatckLayout.topControl = emptyPanel;
+		detailPanel.layout();
+		
+		composite.layout();
+	}
+	
+	
+	private Composite createAssociationsEditPanel(Composite composite, int columns) {
+		Composite parent = new Composite( composite, SWT.NONE);
+		fillColumns(parent, 4);
+
+		createGenerateAssociationCheckbox(parent,columns);
+		int nColumns= 4 ;
+		GridLayout layout = new GridLayout();
+		layout.numColumns = nColumns;
+		parent.setLayout(layout);
+
+		//Cardinality
+		cardinalityLabel = new Label(parent, SWT.NONE);
+		cardinalityLabel.setText( JptUiEntityGenMessages.cardinality);
+		GridData gd = new GridData();
+		gd.horizontalIndent = 20;
+		cardinalityLabel.setLayoutData( gd );
+		
+		cardinalityCombo = new Combo(parent, SWT.SINGLE | SWT.READ_ONLY );
+		
+		fillColumns(cardinalityCombo, 1);
+		
+		cardinalityCombo.addSelectionListener(new SelectionListener(){
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				selectedAssociation.setCardinality( cardinalityCombo.getText());
+				associationList.updateSelectedAssociation();
+			}
+		});
+		
+		//Adding a filler column
+		Label label = new Label( parent, SWT.NONE);
+		label.setText( "");//$NON-NLS-1$
+		GridData layoutData = new GridData();
+		layoutData.horizontalSpan = 2;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = true;
+		label.setLayoutData(layoutData);
+		
+		//Table join condition
+		joinConditionLabel = newLabelWithIndent(parent, JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_tableJoin, 20 );
+		
+		joinConditionText = new Text( parent, SWT.MULTI | SWT.BORDER );
+		joinConditionText.setEditable(false);
+		joinConditionText.setText(JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_joinedWhen);
+		layoutData = new GridData();
+		layoutData.horizontalSpan = 2;
+		layoutData.verticalAlignment = SWT.TOP;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = true;
+		layoutData.grabExcessVerticalSpace = false;
+		layoutData.heightHint = 50;
+		joinConditionText.setLayoutData(layoutData);
+		newLabel(parent, "");//$NON-NLS-1$
+
+		//Generate UI controls for ReferrerRole
+		createGenerateReferrerRoleControls(parent, columns);
+
+		//Generate UI controls for ReferencedRole
+		createGenerateReferencedRoleControls(parent, columns);
+		
+		
+		return parent;
+	}
+
+	public boolean editCascade(AssociationRole role) {
+		CascadeDialog dlg = CascadeDialog.create(role);
+		if (dlg.open() == Window.CANCEL ) {
+			return false;
+		}
+		
+		return true;
+	}	
+
+	private void createAssociationsListPanel(Composite parent) {
+		Composite composite = new Composite( parent, SWT.NULL );
+		composite.setLayout( new FillLayout());
+		composite.setBackground(new Color(Display.getDefault(),255, 0,0) );
+		GridData layoutData = new GridData();
+		layoutData.horizontalSpan = 1;
+		layoutData.verticalAlignment = SWT.FILL;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = false;
+		layoutData.grabExcessVerticalSpace = true;
+		layoutData.widthHint = 400;
+		layoutData.heightHint = 400;
+		composite.setLayoutData(layoutData);
+		
+		associationList = new AssociationsListComposite(composite, this);
+	}
+	
+	private void launchNewAssociationsWizard() {
+		ORMGenCustomizer customizer = getCustomizer();
+		NewAssociationWizard wizard = new NewAssociationWizard(this.jpaProject, customizer );
+		
+		WizardDialog dialog = new WizardDialog( this.getShell(), wizard);
+		dialog.create();
+		int returnCode = dialog.open();
+		if (returnCode == Window.OK) {
+			Association association = wizard.getNewAssociation();
+			if( association !=null ){
+				customizer.addAssociation(association);
+				updateForeignKeyColumnGenProperty(association);
+				updateAssociationsListPanel();
+			}
+		}		
+	}
+	/**
+	 * For user created association:
+	 * If association is to be generated, no need to generate the getter/setter for the column itself
+	 */
+	private void updateForeignKeyColumnGenProperty(Association association) {
+		//Need to process MANY_TO_ONE only since the the associations list are optimized to have MANY_TO_ONE
+		if( association.isCustom() && association.getCardinality().equals( Association.MANY_TO_ONE ) ){
+			boolean generateColumn =  !association.isGenerated();
+			//The "MANY" side DB table
+			//ORMGenTable table1 = association.getReferrerTable();
+			//The "ONE" side DB table
+			//ORMGenTable table2 = association.getReferencedTable();
+			//The list of foreign key columns in the MANY side, should not be generated
+			//The list of primary keys in the ONE side, will be generated
+			//List<ORMGenColumn> list2 = association.getReferencedColumns();	
+			List<ORMGenColumn> list1 = association.getReferrerColumns();	
+			for(ORMGenColumn c : list1 ){
+				if( c.isGenerated() != generateColumn){
+					if( !generateColumn && DTPUtil.isPrimaryKey( c.getDbColumn() ) ){
+						continue;
+					}
+					c.setGenerated(generateColumn);
+					c.setInsertable(generateColumn);
+					c.setUpdateable(generateColumn);
+				}
+			}
+		}
+	}
+
+	private void updateAssociationsListPanel() {
+			ORMGenCustomizer customizer = getCustomizer();
+			//If user changed the connection or schema
+			if( this.customizer != customizer ){
+				this.customizer = customizer; 
+			}
+			List<Association> associations = customizer.getAssociations();
+			this.associationList.updateAssociations( associations );
+	}
+
+	@SuppressWarnings("restriction")
+	public void updateAssociationEditPanel(Association association) {
+		this.selectedAssociation = association;
+
+		boolean enabled = association.isCustom();
+		this.deleteAssociationLink.setEnabled(enabled);
+		
+		//Create and display the associationsEditPanel if it was hidden before
+		if( associationsEditPanel == null ){
+			associationsEditPanel = this.createAssociationsEditPanel(this.detailPanel, 4);
+		}
+		this.detailPanelStatckLayout.topControl = associationsEditPanel;
+		this.detailPanel.layout();
+		this.detailPanel.getParent().layout();
+
+		//Update the UI controls from the model
+		String table1Name = association.getReferrerTableName();
+		String table2Name = association.getReferencedTableName();
+		String joinTableName = association.getJoinTableName();
+		
+		boolean isGenerated = association.isGenerated();
+		this.generateAssociationCheckBox.setSelection(isGenerated);
+		this.referrerRolePropertyLabel.setEnabled( isGenerated );
+		this.referrerRolePropertyField.setEnabled( isGenerated );
+		this.referrerRoleCheckBox.setEnabled( isGenerated );
+		this.referencedRolePropertyLabel.setEnabled( isGenerated );
+		this.referencedRolePropertyField.setEnabled( isGenerated );
+		this.referencedRoleCheckBox.setEnabled( isGenerated );
+		this.cardinalityLabel.setEnabled(isGenerated);
+		this.cardinalityCombo.setEnabled(isGenerated);
+		this.joinConditionLabel.setEnabled( isGenerated );
+		this.joinConditionText.setEnabled( isGenerated );
+		
+		String cardinality = association.getCardinality();
+		if( Association.MANY_TO_MANY.equals( cardinality ) ){
+			cardinalityCombo.removeAll();
+			cardinalityCombo.add( Association.MANY_TO_MANY);
+		}else{
+			cardinalityCombo.removeAll();
+			cardinalityCombo.add( Association.MANY_TO_ONE);
+			cardinalityCombo.add( Association.ONE_TO_ONE);
+		}
+		
+		cardinalityCombo.setText(cardinality);
+		cardinalityCombo.setEnabled(enabled);
+		
+		String text = null;
+		//if MTM
+		if( Association.MANY_TO_MANY.equals( cardinality ) ){
+			text = String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_setRef, table2Name, table1Name);
+		}else{
+			text = String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_entityRef, table2Name, table1Name);
+		}
+		this.referrerRoleCheckBox.setText(text);
+
+		//if OTO
+		if( Association.ONE_TO_ONE.equals( cardinality ) ){
+			text = String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_entityRef, table1Name, table2Name);
+		}else{
+			text = String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_setRef, table1Name, table2Name);
+		}
+		this.referencedRoleCheckBox.setText(text);
+
+		//AssociationRole properties
+		AssociationRole referrerRole = association.getReferrerRole();
+		if( referrerRole != null){
+			this.referrerRoleCheckBox.setSelection( true );
+			this.referrerRolePropertyField.setEditable(true);
+			this.referrerRolePropertyField.setText(referrerRole.getPropertyName());
+			this.referrerRoleCascadeField.setEnabled(true);
+			String cascade = referrerRole.getCascade();
+			if( cascade!=null ) 
+				this.referrerRoleCascadeField.setText( cascade );
+			
+			//if MTO: 
+			if( Association.MANY_TO_ONE.equals( cardinality ) ){
+				this.referrerRoleCheckBox.setEnabled( false );
+			}
+		}else{
+			this.referrerRoleCheckBox.setSelection( false );
+			this.referrerRolePropertyLabel.setEnabled(false);
+			this.referrerRolePropertyField.setEditable(false);
+			this.referrerRolePropertyField.setText("");
+			this.referrerRoleCascadeField.setEnabled(false);
+		}
+		
+		AssociationRole referencedRole = association.getReferencedRole();
+		if( referencedRole != null){
+			this.referencedRoleCheckBox.setSelection( true );
+			this.referencedRolePropertyLabel.setEnabled(true);
+			this.referencedRolePropertyField.setEditable(true);
+			this.referencedRolePropertyField.setText(referencedRole.getPropertyName());
+			this.referencedRoleCascadeField.setEnabled(true);
+			String cascade = referencedRole.getCascade();
+			if( cascade!=null ) 
+				this.referencedRoleCascadeField.setText(cascade);
+		}else{
+			this.referencedRoleCheckBox.setSelection( false );
+			this.referencedRolePropertyLabel.setEnabled(false);
+			this.referencedRolePropertyField.setEditable(false);
+			this.referencedRolePropertyField.setText("");
+			this.referencedRoleCascadeField.setEnabled(false);
+		}
+		
+		//Join conditions
+		updateJoinConditions(association, table1Name, table2Name, joinTableName);
+	}
+
+	private void updateJoinConditions(Association association,
+			String table1Name, String table2Name, String joinTableName) {
+		String text = "%s";
+		if( joinTableName == null ){
+			StringBuilder strText = new StringBuilder();
+			//text = JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_joinedWhen;
+			List<String> columnList1 = association.getReferrerColumnNames() ;
+			List<String> columnList2 = association.getReferencedColumnNames();
+			for( int i=0; i < columnList1.size(); i++){
+				strText.append( table1Name + "." + columnList1.get(i) );//$NON-NLS-1$
+				strText.append( "=" );//$NON-NLS-1$
+				strText.append( table2Name + "." + columnList2.get(i) );//$NON-NLS-1$
+				if( i < columnList1.size()-1 )
+					strText.append( "\n AND " );//$NON-NLS-1$
+			}
+			joinConditionText.setText( String.format( text , strText.toString()) ); 
+		}else{
+			StringBuilder strText = new StringBuilder();
+			//text = JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_joinedWhen;
+			List<String> columnList1 = association.getReferrerColumnNames() ;
+			List<String> joinColumnList1 = association.getReferrerJoinColumnNames()  ;
+			for( int i=0; i < columnList1.size(); i++){
+				strText.append( table1Name + "." + columnList1.get(i) );//$NON-NLS-1$
+				strText.append( "=" );//$NON-NLS-1$
+				strText.append( joinTableName + "." + joinColumnList1.get(i) );
+				strText.append( "\n AND " );//$NON-NLS-1$
+			}
+			
+			List<String> joinTableColumnList2 = association.getReferencedJoinColumnNames();
+			List<String> columnList2 = association.getReferencedColumnNames();
+			for( int i=0; i < joinTableColumnList2.size(); i++){
+				strText.append( joinTableName + "." + joinTableColumnList2.get(i) );
+				strText.append( "=" );//$NON-NLS-1$
+				strText.append( table2Name + "." + columnList2.get(i) );//$NON-NLS-1$
+				if( i < joinTableColumnList2.size()-1 )
+					strText.append( "\n AND " );//$NON-NLS-1$
+			}
+			
+			joinConditionText.setText( String.format( text , strText.toString()) ); 
+			
+		}
+	}
+
+	/**
+	 * Called when one of referrerRoleCheckBox or referencedRoleCheckBox 
+	 * changes value. 
+	 *
+	 */
+	private void directionalityCheckBoxChanged() {
+		String dir;
+		if (referrerRoleCheckBox.getSelection()) {
+			dir = referencedRoleCheckBox.getSelection() ? Association.BI_DI : Association.NORMAL_DI;
+		} else {
+			if (referencedRoleCheckBox.getSelection()) {
+				dir = Association.OPPOSITE_DI;
+			} else {
+				dir = null;
+			}
+		}
+		if (dir != null) {
+			selectedAssociation.setDirectionality(dir);
+		} else {
+			selectedAssociation.setGenerated(false);
+		}
+		
+		this.associationList.updateSelectedAssociation();
+	}	
+	
+	private ORMGenCustomizer getCustomizer(){
+		GenerateEntitiesFromSchemaWizard wizard = (GenerateEntitiesFromSchemaWizard) this.getWizard();
+		return wizard.getCustomizer();
+	}
+	
+	
+    @Override
+    public final void performHelp() 
+    {
+        PlatformUI.getWorkbench().getHelpSystem().displayHelp( GenerateEntitiesFromSchemaWizard.HELP_CONTEXT_ID );
+    }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableFigure.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableFigure.java
new file mode 100644
index 0000000..7fd0e75
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableFigure.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.GridLayout;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.jpt.ui.CommonImages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+
+/**
+ * A draw2D figure representing a database table
+ *
+ */
+public class TableFigure extends Figure {
+	  public static Color tableColor = new Color(null,220,232,241);
+	  public static Font tableFont = new Font(null, "Arial", 8, SWT.NONE);
+	  public static Color disabledColor = ColorConstants.white; 
+	  public static Color borderColor = new Color( null, 14,66,115);
+	  
+	  public static final int OUTLINE_CORNER_RADIUS = 6; 
+	  
+	  public TableFigure(String name) {
+		GridLayout gl = new GridLayout();
+		gl.marginHeight = 2;
+		gl.marginWidth = 10;
+		setLayoutManager(gl);
+
+		setBorder(new LineBorder(tableColor,0));
+	    setBackgroundColor(tableColor);
+	    setOpaque(true);
+	    setSize(150, 20);
+		
+		Label nameLabel = new Label("", CommonImages.createImage( CommonImages.TABLE_OBJ_IMAGE));
+		nameLabel.setFont(tableFont);
+		nameLabel.setText(name);
+		nameLabel.setForegroundColor(borderColor);
+		nameLabel.setLabelAlignment(PositionConstants.CENTER);
+	    add(nameLabel);	
+	  }
+	  
+	protected void paintClientArea(Graphics graphics)
+	{
+		super.paintClientArea(graphics);
+		graphics.pushState();
+		Rectangle r = getBounds().getCopy();
+		graphics.drawRoundRectangle(r.expand(new Insets(-1, -1, -2, -2)),
+				OUTLINE_CORNER_RADIUS, OUTLINE_CORNER_RADIUS );					
+		graphics.popState();
+	}	  
+	
+	public void setEnabled(boolean enabled ) {
+		super.setEnabled(enabled);
+		if( enabled ){
+			setBackgroundColor(tableColor);
+		}else{
+			setBackgroundColor(disabledColor);
+		}
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableGenPanel.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableGenPanel.java
new file mode 100644
index 0000000..c0c4293
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableGenPanel.java
@@ -0,0 +1,393 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.jpt.gen.internal2.ORMGenTable;
+import org.eclipse.jpt.ui.JptUiPlugin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * The UI panel for setting the default and specific 
+ * table entity generation properties.
+ * 
+ */
+class TableGenPanel
+{
+	WizardPage wizardPage ; 
+	
+	private Text classNameField; // used in setting individual table/entity generation only
+	
+	private Combo idGeneratorCombo;
+	private Text sequenceNameField;
+	
+	private Button entityAccessField;
+	private Button entityAccessProperty;
+	private Button associationFetchEager;
+	private Button associationFetchLazy;
+	
+	private Button collectionTypeSet;
+	private Button collectionTypeList;
+	
+	private Button generateOptionalAnnotations;
+	
+	private Label sequenceNameNoteLabel; 
+	
+	private boolean isUpdatingControls;
+	
+	private ORMGenTable mTable;
+	
+	private boolean isDefaultTable = false;
+	
+	private static Color NOTE_LABEL_COLOR = new Color( Display.getDefault(), 102,102,102);
+	
+	public TableGenPanel(Composite parent, int columns , boolean isDefaultTable, WizardPage wizardPage   ){
+		super();
+		this.wizardPage = wizardPage;
+		this.isDefaultTable = isDefaultTable;
+		createTableMappingPropertiesGroup(parent, columns);
+		SWTUtil.createLabel(parent, 4, "");
+	}
+	
+	protected void createTableMappingPropertiesGroup(Composite composite, int columns) {
+		Group parent = new Group(composite, SWT.NONE );
+		parent.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_tableMapping);
+		parent.setLayout(new GridLayout(columns, false));
+		GridData layoutData = new GridData();
+		layoutData.horizontalSpan = columns;
+		layoutData.verticalAlignment = SWT.FILL;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = true;
+		layoutData.grabExcessVerticalSpace = false;
+		parent.setLayoutData(layoutData);
+		
+		createClassNameControl(parent, columns);
+		
+		createIdGeneratorControls(parent, columns);
+		createEntityAccessControls(parent, columns);
+		
+		//AssociationFetch and CollectionType only available for default table generation
+		if( isDefaultTable ){
+			createAssociationFetchControls(parent, columns);
+			createCollectionTypeControls(parent, columns);
+			createGenerateOptionalAnnotationControls(parent, columns);
+		}
+	}
+	
+	private void createGenerateOptionalAnnotationControls(Group parent, int columns) {
+		SWTUtil.createLabel(parent, 1, "");
+		generateOptionalAnnotations = new Button(parent, SWT.CHECK );
+		generateOptionalAnnotations.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations);
+		generateOptionalAnnotations.setToolTipText(JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations_desc);
+
+		GridData gd = new GridData();
+		gd.horizontalSpan = columns-1;
+		gd.horizontalIndent = 3 ;
+		generateOptionalAnnotations.setLayoutData(gd);
+		generateOptionalAnnotations.addSelectionListener(new SelectionListener(){
+			public void widgetDefaultSelected(SelectionEvent e) {}
+			public void widgetSelected(SelectionEvent e) {
+				boolean selected = generateOptionalAnnotations.getSelection();
+				mTable.setGenerateDDLAnnotations(selected);
+			}
+		});
+	}
+
+	private void createClassNameControl(Composite parent, int columns) {
+		//Customize class name for specific table only
+		if( !isDefaultTable ){
+			SWTUtil.createLabel( parent, 1 , JptUiEntityGenMessages.GenerateEntitiesWizard_tablePanel_className );
+			
+			classNameField = new Text(parent, SWT.SINGLE | SWT.BORDER );
+			//mPackageNameField.setEditable(false);
+			SWTUtil.fillColumns(classNameField,3);
+			classNameField.addModifyListener(new ModifyListener(){
+				@SuppressWarnings({  "deprecation" })
+				public void modifyText(ModifyEvent e) {
+					if (e.getSource() == null || !isUpdatingControls) {
+						String className = classNameField.getText();
+						IStatus status = JavaConventions.validateJavaTypeName( className );
+						if( !status.matches(IStatus.ERROR) ){
+							mTable.setClassName(  className );
+							wizardPage.setErrorMessage(null);
+						}else{
+							wizardPage.setErrorMessage(status.getMessage());
+						}
+					}
+				}			
+			});
+		}
+	}
+	
+	class AssociationFetchListener implements SelectionListener{
+		public void widgetDefaultSelected(SelectionEvent e) {}
+		public void widgetSelected(SelectionEvent e) {
+			if (!isUpdatingControls) {
+				Button radioBtn = (Button)e.getSource();
+				mTable.setDefaultFetch( radioBtn.getData().toString());
+			}
+		}
+	}
+
+	private void createAssociationFetchControls(Composite composite, int columns) {
+		SWTUtil.createLabel(composite, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_fetch );
+		
+		Composite parent = new Composite( composite, SWT.NONE);
+		parent.setLayout(new RowLayout());
+		SWTUtil.fillColumns( parent , 3);
+				
+		associationFetchEager = new Button( parent, SWT.RADIO );
+		associationFetchEager.setText( "&Eager");
+		associationFetchEager.setData( ORMGenTable.EAGER_FETCH );
+
+		associationFetchLazy = new Button( parent, SWT.RADIO );
+		associationFetchLazy.setText( "La&zy");
+		associationFetchLazy.setData( ORMGenTable.LAZY_FETCH );
+		
+		AssociationFetchListener associationFetchListener = new AssociationFetchListener();
+		associationFetchLazy.addSelectionListener( associationFetchListener );
+		associationFetchEager.addSelectionListener( associationFetchListener );
+		
+	}
+
+	class CollectionTypeListener implements SelectionListener{
+		public void widgetDefaultSelected(SelectionEvent e) {}
+		public void widgetSelected(SelectionEvent e) {
+			if (!isUpdatingControls) {
+				Button radioBtn = (Button)e.getSource();
+				mTable.setDefaultCollectionType( radioBtn.getData().toString());
+			}
+		}
+	}	
+	
+	private void createCollectionTypeControls(Composite composite, int columns){
+		SWTUtil.createLabel(composite, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_collType );
+		
+		Composite parent = new Composite( composite, SWT.NONE);
+		parent.setLayout(new RowLayout());
+		SWTUtil.fillColumns( parent , 3);
+		
+		this.collectionTypeSet = new Button( parent, SWT.RADIO);
+		this.collectionTypeSet.setText( "java.util.Se&t");
+		this.collectionTypeSet.setData( ORMGenTable.SET_COLLECTION_TYPE );
+		this.collectionTypeList = new Button( parent, SWT.RADIO);
+		this.collectionTypeList.setText("java.util.&List");
+		this.collectionTypeList.setData(ORMGenTable.LIST_COLLECTION_TYPE); 
+		
+		CollectionTypeListener collectionTypeListener = new CollectionTypeListener();
+		collectionTypeList.addSelectionListener( collectionTypeListener );
+		collectionTypeSet.addSelectionListener( collectionTypeListener );
+		
+	}
+
+
+	public void setORMGenTable(ORMGenTable table) {
+		mTable = table;
+		
+		isUpdatingControls = true;
+				
+		try {
+			//ClassNameField is not available for default table
+			if(classNameField!= null )
+				classNameField.setText( mTable.getClassName() );
+			
+			final List<String> schemes = this.mTable.getCustomizer().getAllIdGenerators();
+			String[] values = new String[schemes.size()];
+			schemes.toArray(values);
+			idGeneratorCombo.setItems( values );
+			idGeneratorCombo.setText( mTable.getIdGenerator());
+			
+			String sequenceName = mTable.isDefaultsTable() ? mTable.getSequence() : mTable.getFormattedSequence();
+			sequenceName  = ( sequenceName==null?"":sequenceName ); 
+			sequenceNameField.setText( sequenceName );
+			if( sequenceName.length()> 0 ){
+				sequenceNameField.setEnabled(true);
+				sequenceNameNoteLabel.setEnabled(true);
+			}else{
+				sequenceNameField.setEnabled(false);
+				sequenceNameNoteLabel.setEnabled(false);
+			}
+			
+			String access = mTable.getAccess() ;
+			if(  ORMGenTable.FIELD_ACCESS.equals( access ) ){
+				this.entityAccessField.setSelection( true );
+			}else{
+				this.entityAccessProperty.setSelection( true );
+			}
+	
+			if(associationFetchLazy!=null && associationFetchEager != null ){
+				String defaultFetch = mTable.getDefaultFetch();
+				if( ORMGenTable.EAGER_FETCH.equals( defaultFetch ) )
+					associationFetchEager.setSelection(true);
+				else
+					associationFetchLazy.setSelection(true);
+			}
+			
+			//DefautlTable only
+			if(collectionTypeList!=null){
+				String cType = mTable.getDefaultCollectionType();
+				if( ORMGenTable.LIST_COLLECTION_TYPE.equals( cType ) ){
+					this.collectionTypeList.setSelection( true );
+				}else{
+					this.collectionTypeSet.setSelection( true );
+				}
+				
+				this.generateOptionalAnnotations.setSelection( mTable.isGenerateDDLAnnotations());
+			}
+			
+		} catch (Exception e) {
+			JptUiPlugin.log(e);
+		}
+		
+		isUpdatingControls = false;
+	}
+
+	private void createIdGeneratorControls(Composite parent, int columns) {
+		SWTUtil.createLabel(parent, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_keyGen );
+
+		idGeneratorCombo = new Combo(parent,SWT.SINGLE | SWT.READ_ONLY);
+		SWTUtil.fillColumns(idGeneratorCombo,3);
+		
+		idGeneratorCombo.addSelectionListener( new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+
+			public void widgetSelected(SelectionEvent e) {
+				if (isUpdatingControls) {
+					return;
+				}
+				
+				idGenChanged();
+			}});
+
+		SWTUtil.createLabel(parent, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_sequence );
+		sequenceNameField = new Text( parent, SWT.SINGLE | SWT.BORDER );
+		
+		SWTUtil.fillColumns(sequenceNameField, 3);
+		sequenceNameField.addModifyListener(new ModifyListener(){
+			public void modifyText(ModifyEvent e) {
+				if (e.getSource() == null || !isUpdatingControls) {
+
+					if( idGeneratorCombo.getText().equals("sequence")){
+						String sequenceName = sequenceNameField.getText();
+						if( sequenceName.toLowerCase().indexOf("$table")>=0 || 
+								sequenceName.toLowerCase().indexOf("$pk")>=0 ){
+							sequenceName = convertVarToLowerCase("$table", sequenceName);
+							sequenceName = convertVarToLowerCase("$pk", sequenceName);
+						}
+						if( sequenceName.trim().length() != 0 ){
+							mTable.setSeqence( sequenceName );
+							wizardPage.setErrorMessage(null);
+							wizardPage.setPageComplete(true);
+						}else{
+							wizardPage.setErrorMessage("Please specify a sequence name.");
+							wizardPage.setPageComplete(false);
+						}
+					}else{
+						wizardPage.setErrorMessage(null);
+						wizardPage.setPageComplete(true);
+					}
+				}
+			}
+
+			private String convertVarToLowerCase(String var, String sequenceName) {
+				int n = sequenceName.toLowerCase().indexOf( var );
+				if( n==0 ){
+					return var + sequenceName.substring( var.length());
+				}else if( n >0 ){
+					return sequenceName.substring(0,n) + var + sequenceName.substring( n + var.length());
+				}
+				return sequenceName;
+			}			
+		});
+		
+		SWTUtil.newLabel(parent, "");//$NON-NLS-1$
+		sequenceNameNoteLabel = new Label(parent, SWT.NONE);
+		String text =String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_sequenceNote, 
+				ORMGenTable.TABLE_SEQ_PATTERN, ORMGenTable.PK_SEQ_PATTERN);
+		sequenceNameNoteLabel.setText( text ) ;
+		sequenceNameNoteLabel.setEnabled(false);
+		SWTUtil.fillColumns( sequenceNameNoteLabel, 3);
+	}
+
+	private void idGenChanged() {
+		String scheme = (String)idGeneratorCombo.getText();
+		mTable.setIdGenerator(scheme);
+		
+		boolean isSequence = this.mTable.getCustomizer().getSequenceIdGenerators().contains(scheme);		
+		if (!isSequence) {
+			sequenceNameField.setText("");
+			sequenceNameField.setEnabled(false);
+			mTable.setSeqence(null);
+			sequenceNameNoteLabel.setEnabled(false);
+		}else{
+			sequenceNameField.setEnabled(true);
+			sequenceNameNoteLabel.setForeground( NOTE_LABEL_COLOR );
+			sequenceNameNoteLabel.setEnabled(true);
+			if( sequenceNameField.getText().length()==0 ) {
+				String newMessage = "Please specify a sequence name";
+				this.wizardPage.setErrorMessage(newMessage);
+				this.wizardPage.setPageComplete(false);
+			}else{
+				this.wizardPage.setErrorMessage(null);
+				this.wizardPage.setPageComplete(true);
+			}
+		}
+	}
+	
+	class EntityAccessFetchListener implements SelectionListener{
+		public void widgetDefaultSelected(SelectionEvent e) {}
+		public void widgetSelected(SelectionEvent e) {
+			if (!isUpdatingControls) {
+				Button radioBtn = (Button)e.getSource();
+				mTable.setAccess( radioBtn.getData().toString() );
+			}
+		}
+	}
+	
+	private void createEntityAccessControls(Composite composite, int columns) {
+		SWTUtil.createLabel(composite, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_access );
+		
+		Composite parent = new Composite( composite, SWT.NONE);
+		SWTUtil.fillColumns( parent , 3);
+		parent.setLayout(new RowLayout());
+
+		entityAccessField = new Button( parent, SWT.RADIO );
+		entityAccessField.setText( "&Field" ); //$NON-NLS1$
+		entityAccessField.setData( ORMGenTable.FIELD_ACCESS);
+
+		entityAccessProperty = new Button( parent, SWT.RADIO );
+		entityAccessProperty.setText(  "&Property" );//$NON-NLS1$
+		entityAccessProperty.setData( ORMGenTable.PROPERTY_ACCESS );
+		
+		EntityAccessFetchListener entityAccessFetchListener = new EntityAccessFetchListener();
+		entityAccessField.addSelectionListener( entityAccessFetchListener );
+		entityAccessProperty.addSelectionListener( entityAccessFetchListener );
+	}
+		
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesAndColumnsCustomizationWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesAndColumnsCustomizationWizardPage.java
new file mode 100644
index 0000000..c51ef8a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesAndColumnsCustomizationWizardPage.java
@@ -0,0 +1,351 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.ui.wizards.NewTypeWizardPage;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.gen.internal2.ORMGenColumn;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+import org.eclipse.jpt.gen.internal2.ORMGenTable;
+import org.eclipse.jpt.gen.internal2.util.DTPUtil;
+import org.eclipse.jpt.ui.CommonImages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.PlatformUI;
+
+public class TablesAndColumnsCustomizationWizardPage extends NewTypeWizardPage {
+
+	@SuppressWarnings("unused")
+	private JpaProject jpaProject;
+
+	private TreeViewer tableColumnTreeViewer ;
+	
+	private Composite detailPanel ;
+	private StackLayout detailPanelStatckLayout ;
+	private Composite tableGenDetatilGroup;
+	private ColumnGenPanel columnGenPanel;
+	private Composite columnGenDetatilGroup;
+	private TableGenPanel tableGenPanel;
+	private ORMGenTable selectedTable;
+	
+	private ORMGenCustomizer customizer;
+	
+	protected TablesAndColumnsCustomizationWizardPage(JpaProject jpaProject ) {
+		super(true, "TablesAndColumnsCustomizationWizardPage"); //$NON-NLS-1$
+		this.jpaProject = jpaProject;
+		setTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_tablesAndColumnsPage_title );
+		setMessage( JptUiEntityGenMessages.GenerateEntitiesWizard_tablesAndColumnsPage_desc);
+	}
+
+	// -------- Initialization ---------
+	/**
+	 * The wizard owning this page is responsible for calling this method with the
+	 * current selection. The selection is used to initialize the fields of the wizard 
+	 * page.
+	 * 
+	 * @param selection used to initialize the fields
+	 */
+	void init(IStructuredSelection selection) {
+		if( jpaProject != null ){
+			IJavaElement jelem = this.jpaProject.getJavaProject();
+			initContainerPage(jelem);
+			initTypePage(jelem);
+		}
+	}
+	
+	public void createControl(Composite parent) {
+		initializeDialogUnits(parent);
+		Composite composite = new Composite(parent, SWT.NULL);
+		int nColumns= 1	;
+		GridLayout layout = new GridLayout();
+		layout.numColumns = nColumns;
+		composite.setLayout(layout);
+		//PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES);
+
+		createTableAndColumnsListPanel(composite, 1);
+		
+		SWTUtil.createLabel( composite, 1, ""); //$NON-NLS-1$
+
+		SWTUtil.createSeparator(composite, 1);
+		
+		createGenerateDetailGroup(composite, 1);
+
+		setControl(composite);
+		this.setPageComplete( true );
+	}
+	
+	/**
+	 * A panel with JFace TreeViewer showing tables and columns to be generated into JPA entities
+	 * 
+	 * @param parent
+	 * @param columns
+	 */
+	private void createTableAndColumnsListPanel(Composite parent, int columns) {
+		Label label = new Label(parent, columns );
+		label.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_tablesAndColumnsPage_labelTableAndColumns );
+		SWTUtil.fillColumns( label , columns);
+		
+		GridData data = new GridData();
+		data.horizontalSpan = columns;
+		data.verticalAlignment = SWT.FILL;
+		data.horizontalAlignment = SWT.FILL;
+		data.grabExcessHorizontalSpace = true;
+		data.heightHint = 200;
+		data.grabExcessVerticalSpace = true;
+		
+		tableColumnTreeViewer = new TreeViewer(parent);
+		tableColumnTreeViewer.getTree().setLayoutData( data);		
+		tableColumnTreeViewer.setContentProvider(new TableColumnTreeContentProvider());
+		tableColumnTreeViewer.setLabelProvider(new TableColumnTreeLabelProvider());
+		
+		tableColumnTreeViewer.addSelectionChangedListener( new ISelectionChangedListener(){
+			public void selectionChanged(SelectionChangedEvent event) {
+				updateDetailPanel(event.getSelection());
+			}
+
+		});
+	}
+
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if(visible){
+			ORMGenCustomizer customizer = getCustomizer();
+			//If user changed the connection or schema
+			if( this.customizer != customizer ){
+				this.customizer = customizer; 
+				tableColumnTreeViewer.setInput( customizer );
+			}else{
+				tableColumnTreeViewer.refresh();
+			}
+			List<String> tableNames = this.customizer.getTableNames();
+			
+			//Select the first table
+			ORMGenTable ormGenTable = this.customizer.getTable(tableNames.get(0));
+			updateTabelGenDetail( ormGenTable );
+		}
+	}
+
+
+	private void updateDetailPanel(ISelection selection) {
+		TreeSelection ts = (TreeSelection)selection;
+		Object selectedObject = ts.getFirstElement();
+		if( selectedObject instanceof ORMGenTable ){
+			updateTabelGenDetail( (ORMGenTable)selectedObject );
+		}else if( selectedObject instanceof ORMGenColumn ){
+			updateColumnGenDetail( (ORMGenColumn)selectedObject );
+		}
+	}			
+	
+	private void updateColumnGenDetail(ORMGenColumn column) {
+		if(columnGenDetatilGroup==null){
+			columnGenDetatilGroup = new Composite(detailPanel, SWT.NONE);
+			GridLayout gridLayout = new GridLayout();
+			gridLayout.numColumns = 4;
+			columnGenDetatilGroup.setLayout(gridLayout);
+			this.columnGenPanel = new ColumnGenPanel(columnGenDetatilGroup, 4, getCustomizer() , this );
+		}
+		columnGenPanel.setColumn(column);
+		this.detailPanelStatckLayout.topControl = columnGenDetatilGroup;
+		this.detailPanel.layout();		
+		detailPanel.getParent().layout();
+	}
+
+	private void updateTabelGenDetail(ORMGenTable table) {
+		this.selectedTable = table;
+		if(tableGenDetatilGroup==null){
+			tableGenDetatilGroup = new Composite(detailPanel, SWT.NONE);
+			GridLayout gridLayout = new GridLayout();
+			gridLayout.numColumns = 4;
+			tableGenDetatilGroup.setLayout(gridLayout);
+			
+			this.tableGenPanel = new TableGenPanel(tableGenDetatilGroup, 4 , false, this );
+			createDomainJavaClassesPropertiesGroup(tableGenDetatilGroup, 4 );
+		}
+		tableGenPanel.setORMGenTable(table);
+		
+		this.detailPanelStatckLayout.topControl = tableGenDetatilGroup;
+		this.detailPanel.layout();		
+
+		String baseClass = table.getExtends();
+		if( baseClass!= null )
+			setSuperClass(baseClass, true);
+		
+		setSuperInterfaces( table.getImplements(), true);
+		
+		detailPanel.getParent().layout();
+	}
+	
+	protected void createDomainJavaClassesPropertiesGroup(Composite composite, int columns) {
+		Group parent = new Group( composite, SWT.NONE);
+		parent.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_domainJavaClass );
+		parent.setLayout(new GridLayout(columns, false));
+		SWTUtil.fillColumns( parent, columns);
+
+		createSuperClassControls(parent, columns);
+		createSuperInterfacesControls(parent, columns);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#superClassChanged()
+	 */
+	protected IStatus superClassChanged() {
+		IStatus status = super.superClassChanged();
+		String baseClass = getSuperClass();
+		if(baseClass!=null && this.selectedTable!=null ){
+			String oldBaseClass = this.selectedTable.getExtends();
+			if( !oldBaseClass.equals(baseClass ))
+				this.selectedTable.setExtends(baseClass);
+		}
+		return status; 
+	}	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#addSuperInterface(java.lang.String)
+	 */
+	@SuppressWarnings("unchecked")
+	public boolean addSuperInterface(String superInterface) {
+		super.addSuperInterface(superInterface);
+		List interfaces = getSuperInterfaces();
+		if(this.selectedTable!=null)
+			this.selectedTable.setImplements(interfaces);
+		return true;
+	}
+	
+	protected void handleFieldChanged(String fieldName) {
+		super.handleFieldChanged(fieldName);
+		if( this.fSuperClassStatus.matches(IStatus.ERROR)){
+			updateStatus(fSuperClassStatus);
+		}else{
+			setMessage("", IMessageProvider.NONE);
+			setErrorMessage(null);
+		}
+		
+	}	
+	
+	private ORMGenCustomizer getCustomizer(){
+		GenerateEntitiesFromSchemaWizard wizard = (GenerateEntitiesFromSchemaWizard) this.getWizard();
+		return wizard.getCustomizer();
+	}
+	/**
+	 * Content provider, and label provider for the DB Table/Column TreeViewer
+	 *
+	 */
+	class TableColumnTreeContentProvider implements ITreeContentProvider {
+		public Object[] getElements(Object inputElement) {
+			if( inputElement instanceof ORMGenCustomizer ){
+				ORMGenCustomizer input = (ORMGenCustomizer )inputElement;
+				List<String> tableNameList = input.getGenTableNames();
+				List<ORMGenTable> ret = new ArrayList<ORMGenTable>();
+				for(String t : tableNameList){
+					ORMGenTable ormGenTable = getCustomizer().getTable( t );
+					ret.add( ormGenTable );
+				}
+				return ret.toArray();
+			}
+			return new Object[]{};
+		}
+		public Object[] getChildren(Object parentElement) {
+			if( parentElement instanceof ORMGenTable ){
+				ORMGenTable table = (ORMGenTable) parentElement;
+				List<ORMGenColumn> columns = table.getColumns();
+				List<ORMGenColumn> ret = new ArrayList<ORMGenColumn>();
+				boolean isCompositePk = DTPUtil.getPrimaryKeyColumnNames(table.getDbTable()).size()>1;
+				for( ORMGenColumn col : columns){
+					if( col.isForeignKey() )
+						continue;
+					if( col.isPrimaryKey() && isCompositePk ){
+						continue;
+					}
+					ret.add(col);
+				}
+				return ret.toArray();
+			}
+			return new Object[]{};
+		}
+		public Object getParent(Object element) { 
+			if( element instanceof ORMGenColumn){
+				return null;
+			}
+			return null;
+		}
+		public boolean hasChildren(Object element) {
+			return( element instanceof ORMGenTable );
+		}
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
+		public void dispose() {}
+	}
+
+	class TableColumnTreeLabelProvider extends LabelProvider{
+
+		public Image getImage(Object element) {
+			if( element instanceof ORMGenTable ){
+				return CommonImages.createImage( CommonImages.TABLE_IMAGE );
+			}else 	if( element instanceof ORMGenColumn ){
+				ORMGenColumn col = ( ORMGenColumn)element;
+				if( col.isPrimaryKey() )
+					return CommonImages.createImage( CommonImages.COLUMN_KEY_IMAGE);
+				return CommonImages.createImage( CommonImages.COLUMN_IMAGE);
+			}
+			return null;
+		}
+		
+
+		public String getText(Object element) {
+			if( element instanceof ORMGenTable ){
+				return ((ORMGenTable)element).getName();
+			}else 			if( element instanceof ORMGenColumn ){
+				return ((ORMGenColumn)element).getName();
+			}
+			return super.getText(element);
+		}		
+	}
+	
+	private void createGenerateDetailGroup(Composite parent, int columns) {
+		detailPanel = new Composite(parent, SWT.NONE);
+		SWTUtil.fillColumns( detailPanel, columns);
+		  
+		detailPanelStatckLayout = new StackLayout();
+		detailPanel.setLayout(detailPanelStatckLayout);
+		  
+		Composite emptyPanel = new Composite(detailPanel, SWT.NONE);
+		emptyPanel.setLayoutData(new GridData());
+
+		detailPanelStatckLayout.topControl = emptyPanel;
+		detailPanel.layout();
+	}
+
+    @Override
+    public final void performHelp() 
+    {
+        PlatformUI.getWorkbench().getHelpSystem().displayHelp( GenerateEntitiesFromSchemaWizard.HELP_CONTEXT_ID );
+    }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesSelectorWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesSelectorWizardPage.java
new file mode 100644
index 0000000..30e05e8
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesSelectorWizardPage.java
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.ui.internal.wizards.gen;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.core.JptCorePlugin;
+import org.eclipse.jpt.db.ConnectionProfile;
+import org.eclipse.jpt.db.JptDbPlugin;
+import org.eclipse.jpt.db.Schema;
+import org.eclipse.jpt.db.Table;
+import org.eclipse.jpt.gen.internal2.Association;
+import org.eclipse.jpt.gen.internal2.ORMGenColumn;
+import org.eclipse.jpt.gen.internal2.ORMGenCustomizer;
+import org.eclipse.jpt.gen.internal2.util.DTPUtil;
+import org.eclipse.jpt.ui.CommonImages;
+import org.eclipse.jpt.ui.JptUiPlugin;
+import org.eclipse.jpt.ui.internal.JpaHelpContextIds;
+import org.eclipse.jpt.ui.internal.JptUiMessages;
+import org.eclipse.jpt.ui.internal.util.SWTUtil;
+import org.eclipse.jpt.ui.internal.util.TableLayoutComposite;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.PlatformUI;
+
+class TablesSelectorWizardPage extends WizardPage{
+
+	private static final int TABLE_COLUMN_INDEX = 0;
+	private JpaProject jpaProject;
+	private Schema schema = null;
+	private ORMGenCustomizer customizer = null;
+	private boolean synchronizePersistenceXml = true;
+
+	private DatabaseGroup databaseGroup;
+	private CheckboxTableViewer tableTable;
+
+	TablesSelectorWizardPage(JpaProject jpaProject ) {
+		super("TablesSelectorWizardPage"); //$NON-NLS-1$
+		this.jpaProject = jpaProject;
+		this.schema = jpaProject.getDefaultDbSchema();
+		setTitle(JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_selectTable );
+		setMessage(JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_chooseEntityTable );
+	}
+
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+	}
+
+	// -------- Provide access to wrapped DTP connection related classes ---------
+	ConnectionProfile getProjectConnectionProfile() {
+		String profileName = this.jpaProject.getDataSource().getConnectionProfileName();
+		return this.connectionProfileNamed(profileName);
+	}
+
+	ConnectionProfile connectionProfileNamed(String profileName) {
+		return JptDbPlugin.instance().getConnectionProfileFactory().buildConnectionProfile(profileName);
+	}
+
+	Schema getSchema(){
+		return this.schema;
+	}
+
+	void setSchema(Schema s){
+		this.schema = s;
+	}
+
+	public Collection<Table> getTables() {
+		Schema schema = this.getSchema();
+		if (schema != null && schema.getName() != null) {
+			return CollectionTools.collection(schema.tables());
+		}
+		return Collections.<Table> emptyList();
+	}
+
+
+	// -------- Initialization ---------
+	/**
+	 * The wizard owning this page is responsible for calling this method with the
+	 * current selection. The selection is used to initialize the fields of the wizard
+	 * page.
+	 *
+	 * @param selection used to initialize the fields
+	 */
+	void init(IStructuredSelection selection) {
+		doStatusUpdate();
+	}
+
+	public void createControl(Composite parent) {
+		initializeDialogUnits(parent);
+
+		Composite composite = new Composite(parent, SWT.NULL);
+		int nColumns= 3;
+		GridLayout layout = new GridLayout();
+		layout.numColumns = nColumns;
+		composite.setLayout(layout);
+
+		this.databaseGroup = createDatabaseGroup(composite, 400);
+
+		createTablesSelectionControl(composite, nColumns);
+
+		//Filler column
+		new Label( composite, SWT.NONE);
+		
+		final Button synchronizeClassesCheckBox = new Button(composite, SWT.CHECK);
+		synchronizeClassesCheckBox.setText(JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_synchronizeClasses );
+		synchronizeClassesCheckBox.setSelection(true);
+		synchronizeClassesCheckBox.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+
+			public void widgetSelected(SelectionEvent e) {
+				setSynchronizePersistenceXml(synchronizeClassesCheckBox.getSelection());
+			}
+
+		});
+		fillColumns( synchronizeClassesCheckBox, 2);
+
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(this.tableTable.getControl(), JpaHelpContextIds.DIALOG_GENERATE_ENTITIES_TABLES);
+
+		setControl(composite);
+
+		setPageComplete(true);
+	}
+
+	@Override
+	public void dispose() {
+		if (this.databaseGroup != null)
+			this.databaseGroup.dispose();
+		super.dispose();
+	}
+
+	@Override
+	public IWizardPage getPreviousPage() {
+		IWizardPage prevPage = super.getPreviousPage();
+		if (prevPage instanceof PromptJPAProjectWizardPage)
+			//Prevent going back to the PromptJPAProjectWizardPage
+			//if JPA project already selected
+			return prevPage.getPreviousPage();
+		else
+			return prevPage;
+	}
+
+	private DatabaseGroup createDatabaseGroup(Composite parent, int widthHint) {
+		DatabaseGroup dbGroup = new DatabaseGroup(this.getContainer(), jpaProject, parent, widthHint);
+		/**
+		 * listen for when the Database Connection changes its selected schema
+		 * so we can keep the page in synch
+		 */
+		class DatabasePageListener implements DatabaseGroup.Listener {
+			public void selectedConnectionProfileChanged(ConnectionProfile connectionProfile) {
+				// ignore
+				jpaProject.getDataSource().setConnectionProfileName(connectionProfile.getName());
+				JptCorePlugin.setConnectionProfileName(jpaProject.getProject(), connectionProfile.getName());
+				
+			}
+			@SuppressWarnings("unchecked")
+			public void selectedSchemaChanged(Schema schema) {
+				if( schema==null ){
+					updateTablesListViewer(Collections.EMPTY_LIST );
+					doStatusUpdate();
+					return;
+				}
+				jpaProject.setUserOverrideDefaultSchema(schema.getName());
+				setSchema( schema );
+				updateTablesSelector(schema);
+			}
+		}
+		dbGroup.addListener(new DatabasePageListener());
+		dbGroup.init();
+		return dbGroup;
+	}
+
+	boolean synchronizePersistenceXml() {
+		return this.synchronizePersistenceXml;
+	}
+
+	private void setSynchronizePersistenceXml(boolean synchronizePersistenceXml){
+		this.synchronizePersistenceXml = synchronizePersistenceXml;
+	}
+
+	private void selectAllTables(){
+		this.tableTable.setAllChecked(true);
+		doStatusUpdate();
+	}
+
+	private void deselectAllTables(){
+		this.tableTable.setAllChecked(false);
+		doStatusUpdate();
+	}
+
+	private void initTablesSelectionControl(Collection<Table> possibleTables) {
+		this.tableTable.setInput(possibleTables);
+	}
+
+	private void createTablesSelectionControl(Composite parent, int columns) {
+		Label tableLabel = new Label(parent, SWT.NONE);
+		GridData gd= new GridData();
+		gd.horizontalAlignment = GridData.FILL;
+		gd.verticalAlignment = GridData.BEGINNING;
+		tableLabel.setLayoutData( gd );
+		tableLabel.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_tables );
+		
+		TableLayoutComposite layout= new TableLayoutComposite(parent, SWT.NONE);
+		addColumnLayoutData(layout);
+
+		final org.eclipse.swt.widgets.Table table = new org.eclipse.swt.widgets.Table(layout, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER | SWT.CHECK);
+
+		TableColumn tableNameColumn = new TableColumn(table, SWT.NONE, TABLE_COLUMN_INDEX);
+		tableNameColumn.setText(JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_tableColumn );
+		tableNameColumn.setResizable(true);
+
+		gd= new GridData(GridData.FILL_BOTH);
+		gd.heightHint= SWTUtil.getTableHeightHint(table, 20);
+		gd.widthHint = 250;
+		gd.grabExcessHorizontalSpace = true;
+		gd.grabExcessVerticalSpace = true ;
+		layout.setLayoutData(gd);
+		layout.setBackground(new Color( Display.getDefault(), 255, 0,0));
+
+		this.tableTable = new CheckboxTableViewer(table);
+		this.tableTable.setUseHashlookup(true);
+		this.tableTable.setLabelProvider(this.buildTableTableLabelProvider());
+		this.tableTable.setContentProvider(this.buildTableTableContentProvider());
+		this.tableTable.setSorter(new ViewerSorter() {
+			@Override
+			public int compare(Viewer viewer, Object e1, Object e2) {
+				return ((Table) e1).getName().compareTo(((Table) e2).getName());
+			}
+		});
+
+		this.tableTable.addPostSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				handleTablesListSelectionChanged(event);
+			}
+		});
+
+		table.addKeyListener(new KeyAdapter() {
+			public void keyPressed(KeyEvent e) {
+				if (e.keyCode == SWT.F2 && e.stateMask == SWT.NONE) {
+					editEntityNameIfPossible();
+					e.doit= false;
+				}
+			}
+		});
+
+
+		updateTablesSelector( databaseGroup.getSelectedSchema() );
+
+		createButtonComposite(parent);
+		
+		GenerateEntitiesFromSchemaWizard generateEntitiesWizard = ((GenerateEntitiesFromSchemaWizard)this.getWizard());
+		Collection<Table> possibleTables = generateEntitiesWizard.getPossibleTables();
+
+		initTablesSelectionControl(possibleTables);		
+	}
+
+	private void createButtonComposite(Composite parent){
+
+		Composite buttonComposite = new Composite(parent, SWT.NULL);
+		GridLayout buttonLayout = new GridLayout(1, false);
+		buttonComposite.setLayout(buttonLayout);
+		GridData data =  new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		data.verticalAlignment = GridData.BEGINNING;
+		buttonComposite.setLayoutData(data);
+
+		Button selectAllButton = new Button(buttonComposite, SWT.PUSH);
+		selectAllButton.setToolTipText(JptUiMessages.General_selectAll);
+		selectAllButton.setImage( CommonImages.createImage(CommonImages.DESC_BUTTON_SELECT_ALL)  );
+		GridData gridData =  new GridData();
+		gridData.horizontalAlignment = GridData.FILL;
+		selectAllButton.setLayoutData(gridData);
+		selectAllButton.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+
+			public void widgetSelected(SelectionEvent e) {
+				selectAllTables();
+			}
+		});
+
+		Button deselectAllButton = new Button(buttonComposite, SWT.PUSH);
+		deselectAllButton.setToolTipText(JptUiMessages.General_deselectAll);
+		deselectAllButton.setImage( CommonImages.createImage(CommonImages.DESC_BUTTON_DESELECT_ALL) );
+		gridData =  new GridData();
+		gridData.horizontalAlignment = GridData.FILL;
+		deselectAllButton.setLayoutData(gridData);
+		deselectAllButton.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {}
+
+			public void widgetSelected(SelectionEvent e) {
+				deselectAllTables();
+			}
+		});
+	}
+
+
+	private void addColumnLayoutData(TableLayoutComposite layout) {
+		layout.addColumnData(new ColumnWeightData(50, true));
+	}
+
+	void editEntityNameIfPossible(){
+		Object[] selected = ((IStructuredSelection) this.tableTable.getSelection()).toArray();
+		if (selected.length != 1) {
+			return;
+		}
+	}
+
+	void handleTablesListSelectionChanged(SelectionChangedEvent event) {
+		doStatusUpdate();
+	}
+
+	private IBaseLabelProvider buildTableTableLabelProvider() {
+		return new TableTableLabelProvider();
+	}
+
+	private IContentProvider buildTableTableContentProvider() {
+		return new TableTableContentProvider();
+	}
+
+
+	Collection<Table> getSelectedTables() {
+		ArrayList<Table> selectedTables = new ArrayList<Table>();
+		for (Object selectedTable : this.tableTable.getCheckedElements())
+			selectedTables.add((Table) selectedTable);
+		return selectedTables;
+	}
+
+	private boolean hasTablesSelected() {
+		return (this.tableTable != null) ? (this.getSelectedTables().size() > 0) : false;
+	}
+
+	void updateTablesListViewer(Collection<Table> possibleTables) {
+		if (this.tableTable != null) {
+			this.initTablesSelectionControl(possibleTables);
+		}
+	}
+
+	/**
+	 * Update the status line and the OK button according to the given status
+	 */
+	protected void doStatusUpdate() {
+		if ( ! this.hasTablesSelected()) {
+			this.setPageComplete(false);
+		}else{
+			try{
+				getContainer().run(false, false, new IRunnableWithProgress(){
+					public void run( final IProgressMonitor monitor ) 
+				    	throws InvocationTargetException, InterruptedException
+				    {
+						monitor.beginTask("Updating", 10);
+				
+						Collection<Table> ret = getSelectedTables();
+						ArrayList<String> tableNames = new ArrayList<String>();
+						for( Table t : ret ){
+							tableNames.add(t.getName());
+						}
+						Schema schema = getSchema();
+						if( schema == null ){
+							return ;
+						}
+						customizer.setSchema(schema);
+						customizer.setTableNames(tableNames);
+						monitor.done();
+				    }
+				});
+			} catch (Exception e) {
+				JptUiPlugin.log(e);
+			}
+				
+			setPageComplete(true);
+		}
+	}
+
+	// ********** inner classes **********
+	private class TableTableLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+		TableTableLabelProvider() {
+			super();
+		}
+
+		@Override
+		public String getText(Object element) {
+			return ((Table) element).getName();
+		}
+
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+
+		public String getColumnText(Object element, int columnIndex) {
+			if (element == null) {
+				return null;
+			}
+			switch (columnIndex) {
+				case TABLE_COLUMN_INDEX:
+					return ((Table) element).getName();
+
+			}
+			throw new IllegalArgumentException("invalid column index: " + columnIndex);// $NON-NLS-1$
+		}
+
+	}
+
+
+	private class TableTableContentProvider implements IStructuredContentProvider {
+
+		TableTableContentProvider() {
+			super();
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {	}
+
+		public void dispose() {}
+
+		public Object[] getElements(Object inputElement) {
+			return ((Collection<?>) inputElement).toArray();
+		}
+
+	}
+
+	private void updateTablesSelector(final Schema schema) {
+		if(schema ==null)
+			return;
+		this.jpaProject.setUserOverrideDefaultSchema( schema.getName());
+		JptCorePlugin.setUserOverrideDefaultSchemaName(jpaProject.getProject(), schema.getName());
+		
+		updateTablesListViewer( CollectionTools.collection(schema.tables()));
+
+		//Create the ORMGenCustomizer
+		GenerateEntitiesFromSchemaWizard wizard = (GenerateEntitiesFromSchemaWizard) getWizard();
+		customizer = wizard.createORMGenCustomizer( schema );
+
+		if( tableTable!=null && customizer != null  ){
+			restoreWizardState();
+		}
+        doStatusUpdate();
+
+	}
+
+	private boolean restoreWizardState(){
+		boolean pageComplete = false;
+		List<String> preSelectedTableNames = this.customizer.getTableNames();
+		if(preSelectedTableNames!=null && preSelectedTableNames.size()>0) {
+			Set<String> set = new HashSet<String>();
+			for(String s : preSelectedTableNames ){
+				set.add(s);
+			}
+	        TableItem[] items = this.tableTable.getTable().getItems();
+	        for (int i = 0; i < items.length; ++i) {
+	            TableItem item = items[i];
+	            org.eclipse.jpt.db.Table element = (org.eclipse.jpt.db.Table)item.getData();
+	            if (element != null) {
+	                boolean check = set.contains(element.getName());
+	                // only set if different, to avoid flicker
+	                if (item.getChecked() != check) {
+	                    item.setChecked(check);
+	                    pageComplete = true;
+	                }
+	            }
+	        }
+		}
+		return pageComplete;
+	}
+
+
+	/**
+	 * Set the layoutData of the input control to occupy specified number of columns
+	 * @param c
+	 * @param columns
+	 */
+	private void fillColumns(Control c, int columns){
+		GridData layoutData = new GridData();
+		layoutData.horizontalSpan = columns;
+		layoutData.verticalAlignment = SWT.FILL;
+		layoutData.horizontalAlignment = SWT.FILL;
+		layoutData.grabExcessHorizontalSpace = true;
+		layoutData.grabExcessVerticalSpace = false;
+		c.setLayoutData(layoutData);
+		return ;
+	}
+
+    @Override
+    public final void performHelp() 
+    {
+        PlatformUI.getWorkbench().getHelpSystem().displayHelp( GenerateEntitiesFromSchemaWizard.HELP_CONTEXT_ID );
+    }
+}