190319 - completed validation on association override joinColumns and joinTable
diff --git a/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_validation.properties b/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_validation.properties
index 2979ac5..b98ce79 100644
--- a/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_validation.properties
+++ b/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_validation.properties
@@ -133,6 +133,9 @@
 VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME=In implied attribute \"{0}\", association override \"{1}\", inverse join column referenced column name \"{2}\" cannot be resolved on table \"{3}\"
 VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS=In implied attribute \"{0}\", association override \"{1}\", name must be specified when there are multiple inverse join columns
 VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS=In implied attribute \"{0}\", association override \"{1}\", referenced column name must be specified when there are multiple inverse join columns
+VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME=In implied association override \"{0}\", join table \"{1}\" cannot be resolved 
+VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG=In implied association override \"{0}\", join table catalog \"{1}\" cannot be resolved 
+VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA=In implied association override \"{0}\", join table schema \"{1}\" cannot be resolved 
 GENERATED_VALUE_UNRESOLVED_GENERATOR=No generator named \"{0}\" is defined in the persistence unit
 PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME=Primary key join column \"{0}\" cannot be resolved on table \"{1}\"
 PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS=Name must be specified when there are multiple primary key join columns
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaFactory.java
index 8f67a12..a6ddc36 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaFactory.java
@@ -16,6 +16,7 @@
 import org.eclipse.jpt.core.context.MappingFile;
 import org.eclipse.jpt.core.context.Orderable;
 import org.eclipse.jpt.core.context.PersistentType;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.UniqueConstraint;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverride;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer;
@@ -181,9 +182,9 @@
 	
 	JavaAttributeMapping buildJavaNullAttributeMapping(JavaPersistentAttribute parent);
 	
-	JavaTable buildJavaTable(JavaEntity parent);
+	JavaTable buildJavaTable(JavaEntity parent, Table.Owner owner);
 	
-	JavaJoinTable buildJavaJoinTable(JavaJoinTableJoiningStrategy parent);
+	JavaJoinTable buildJavaJoinTable(JavaJoinTableJoiningStrategy parent, Table.Owner owner);
 	
 	JavaColumn buildJavaColumn(JavaJpaContextNode parent, JavaBaseColumn.Owner owner);
 	
@@ -191,7 +192,7 @@
 	
 	JavaJoinColumn buildJavaJoinColumn(JavaJpaContextNode parent, JavaJoinColumn.Owner owner);
 	
-	JavaSecondaryTable buildJavaSecondaryTable(JavaEntity parent);
+	JavaSecondaryTable buildJavaSecondaryTable(JavaEntity parent, Table.Owner owner);
 	
 	JavaSequenceGenerator buildJavaSequenceGenerator(JavaJpaContextNode parent);
 	
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/AssociationOverride.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/AssociationOverride.java
index 3a32af0..b3f14ec 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/AssociationOverride.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/AssociationOverride.java
@@ -11,6 +11,7 @@
 
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 
 /**
  * 
@@ -47,5 +48,7 @@
 		JptValidator buildJoinTableJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver);
 
 		JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver);
+
+		JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver);
 	}
 }
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/AssociationOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/AssociationOverrideContainer.java
index 0ccec17..1655d86 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/AssociationOverrideContainer.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/AssociationOverrideContainer.java
@@ -12,6 +12,7 @@
 import java.util.ListIterator;
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 
 /**
  * Provisional API: This interface is part of an interim API that is still
@@ -79,12 +80,13 @@
 	
 	interface Owner extends OverrideContainer.Owner
 	{
-		
 		RelationshipReference resolveRelationshipReference(String associationOverrideName);
 
 		JptValidator buildJoinTableJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver);
 
 		JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver);
+
+		JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver);
 	}
 
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/Table.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/Table.java
index 477f188..8cbec92 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/Table.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/Table.java
@@ -10,6 +10,8 @@
 package org.eclipse.jpt.core.context;
 
 import java.util.ListIterator;
+import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.db.Catalog;
 import org.eclipse.jpt.db.Schema;
 import org.eclipse.jpt.db.SchemaContainer;
@@ -112,4 +114,17 @@
 	 */
 	boolean isResourceSpecified();
 
+	/**
+	 * Return when this table should be validated in its given context
+	 */
+	boolean shouldValidateAgainstDatabase();
+
+	/**
+	 * interface allowing columns to be used in multiple places
+	 * (e.g. basic mappings and attribute overrides)
+	 */
+	interface Owner
+	{
+		JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver);
+	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaBaseTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaBaseTable.java
new file mode 100644
index 0000000..d24884c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaBaseTable.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.core.context.java;
+
+import java.util.ListIterator;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.core.context.Table;
+import org.eclipse.jpt.core.utility.TextRange;
+
+/**
+ * 
+ * 
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ * 
+ * @version 3.0
+ * @since 3.0
+ */
+public interface JavaBaseTable
+	extends Table, JavaJpaContextNode
+{
+
+	TextRange getNameTextRange(CompilationUnit astRoot);
+
+	TextRange getSchemaTextRange(CompilationUnit astRoot);
+
+	TextRange getCatalogTextRange(CompilationUnit astRoot);
+
+	//****************** covariant overrides *******************
+
+	@SuppressWarnings("unchecked")
+	ListIterator<JavaUniqueConstraint> uniqueConstraints();
+
+	JavaUniqueConstraint addUniqueConstraint(int index);
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaReferenceTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaReferenceTable.java
index ba7c1b0..6250e0e 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaReferenceTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaReferenceTable.java
@@ -21,11 +21,11 @@
  * pioneering adopters on the understanding that any code that uses this API
  * will almost certainly be broken (repeatedly) as the API evolves.
  * 
- * @version 2.3
+ * @version 3.0
  * @since 2.3
  */
 public interface JavaReferenceTable
-	extends ReferenceTable, JavaJpaContextNode
+	extends ReferenceTable, JavaBaseTable
 {
 
 	// ********** covariant overrides **********
@@ -40,9 +40,4 @@
 
 	JavaJoinColumn addSpecifiedJoinColumn(int index);
 
-	@SuppressWarnings("unchecked")
-	ListIterator<JavaUniqueConstraint> uniqueConstraints();
-
-	JavaUniqueConstraint addUniqueConstraint(int index);
-
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaSecondaryTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaSecondaryTable.java
index 79113c3..96efe00 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaSecondaryTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaSecondaryTable.java
@@ -22,11 +22,11 @@
  * pioneering adopters on the understanding that any code that uses this API
  * will almost certainly be broken (repeatedly) as the API evolves.
  * 
- * @version 2.1
+ * @version 3.0
  * @since 2.0
  */
 public interface JavaSecondaryTable
-	extends SecondaryTable, JavaJpaContextNode
+	extends SecondaryTable, JavaBaseTable
 {
 
 	void initialize(SecondaryTableAnnotation secondaryTableResource);
@@ -49,10 +49,5 @@
 	ListIterator<JavaPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns();
 	
 	JavaPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn(int index);
-	
-	@SuppressWarnings("unchecked")
-	ListIterator<JavaUniqueConstraint> uniqueConstraints();
-	
-	JavaUniqueConstraint addUniqueConstraint(int index);
 
 }
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaTable.java
index 213ec05..21be84c 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JavaTable.java
@@ -9,8 +9,6 @@
  ******************************************************************************/
 package org.eclipse.jpt.core.context.java;
 
-import java.util.ListIterator;
-import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember;
 
 /**
@@ -22,11 +20,11 @@
  * pioneering adopters on the understanding that any code that uses this API
  * will almost certainly be broken (repeatedly) as the API evolves.
  * 
- * @version 2.1
+ * @version 3.0
  * @since 2.0
  */
 public interface JavaTable
-	extends Table, JavaJpaContextNode
+	extends JavaBaseTable
 {
 	void initialize(JavaResourcePersistentMember jrpm);
 	
@@ -36,11 +34,4 @@
 	 */
 	void update(JavaResourcePersistentMember jrpm);
 
-	
-	//****************** covariant overrides *******************
-
-	@SuppressWarnings("unchecked")
-	ListIterator<JavaUniqueConstraint> uniqueConstraints();
-	
-	JavaUniqueConstraint addUniqueConstraint(int index);
 }
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/orm/OrmBaseTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/orm/OrmBaseTable.java
new file mode 100644
index 0000000..ca4b721
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/orm/OrmBaseTable.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.core.context.orm;
+
+import java.util.ListIterator;
+import org.eclipse.jpt.core.context.Table;
+import org.eclipse.jpt.core.context.XmlContextNode;
+import org.eclipse.jpt.core.utility.TextRange;
+
+/**
+ * 
+ * 
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ * 
+ * @version 3.0
+ * @since 3.0
+ */
+public interface OrmBaseTable
+	extends Table, XmlContextNode
+{
+
+	TextRange getNameTextRange();
+
+	TextRange getSchemaTextRange();
+
+	TextRange getCatalogTextRange();
+
+	//****************** covariant overrides *******************
+
+	@SuppressWarnings("unchecked")
+	ListIterator<OrmUniqueConstraint> uniqueConstraints();
+
+	OrmUniqueConstraint addUniqueConstraint(int index);
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/orm/OrmXmlContextNodeFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/orm/OrmXmlContextNodeFactory.java
index 9a6c76f..123974a 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/orm/OrmXmlContextNodeFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/orm/OrmXmlContextNodeFactory.java
@@ -13,6 +13,7 @@
 import org.eclipse.jpt.core.context.AttributeOverride;
 import org.eclipse.jpt.core.context.JoiningStrategy;
 import org.eclipse.jpt.core.context.Orderable;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.UniqueConstraint;
 import org.eclipse.jpt.core.context.XmlContextNode;
 import org.eclipse.jpt.core.context.java.JavaAttributeMapping;
@@ -90,13 +91,13 @@
 	
 	OrmPersistentAttribute buildOrmPersistentAttribute(OrmPersistentType parent, OrmPersistentAttribute.Owner owner, XmlAttributeMapping resourceMapping);
 	
-	OrmTable buildOrmTable(OrmEntity parent);
+	OrmTable buildOrmTable(OrmEntity parent, Table.Owner owner);
 	
-	OrmSecondaryTable buildOrmSecondaryTable(OrmEntity parent, XmlSecondaryTable xmlSecondaryTable);
+	OrmSecondaryTable buildOrmSecondaryTable(OrmEntity parent, Table.Owner owner, XmlSecondaryTable xmlSecondaryTable);
 	
 	OrmPrimaryKeyJoinColumn buildOrmPrimaryKeyJoinColumn(XmlContextNode parent, OrmBaseJoinColumn.Owner owner, XmlPrimaryKeyJoinColumn resourcePkJoinColumn);
 	
-	OrmJoinTable buildOrmJoinTable(OrmJoinTableJoiningStrategy parent, XmlJoinTable resourceJoinTable);
+	OrmJoinTable buildOrmJoinTable(OrmJoinTableJoiningStrategy parent, Table.Owner owner, XmlJoinTable resourceJoinTable);
 	
 	OrmJoinColumn buildOrmJoinColumn(XmlContextNode parent, OrmJoinColumn.Owner owner, XmlJoinColumn resourceJoinColumn);
 	
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java
index 95fba5f..de2ec85 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java
@@ -19,6 +19,7 @@
 import org.eclipse.jpt.core.context.JpaRootContextNode;
 import org.eclipse.jpt.core.context.Orderable;
 import org.eclipse.jpt.core.context.PersistentType;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.UniqueConstraint;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverride;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer;
@@ -222,8 +223,8 @@
 		return new GenericJavaEmbeddable(parent);
 	}
 	
-	public JavaTable buildJavaTable(JavaEntity parent) {
-		return new GenericJavaTable(parent);
+	public JavaTable buildJavaTable(JavaEntity parent, Table.Owner owner) {
+		return new GenericJavaTable(parent, owner);
 	}
 	
 	public JavaColumn buildJavaColumn(JavaJpaContextNode parent, JavaBaseColumn.Owner owner) {
@@ -238,12 +239,12 @@
 		return new GenericJavaJoinColumn(parent, owner);
 	}
 	
-	public JavaJoinTable buildJavaJoinTable(JavaJoinTableJoiningStrategy parent) {
-		return new GenericJavaJoinTable(parent);
+	public JavaJoinTable buildJavaJoinTable(JavaJoinTableJoiningStrategy parent, Table.Owner owner) {
+		return new GenericJavaJoinTable(parent, owner);
 	}
 	
-	public JavaSecondaryTable buildJavaSecondaryTable(JavaEntity parent) {
-		return new GenericJavaSecondaryTable(parent);
+	public JavaSecondaryTable buildJavaSecondaryTable(JavaEntity parent, Table.Owner owner) {
+		return new GenericJavaSecondaryTable(parent, owner);
 	}
 	
 	public JavaBasicMapping buildJavaBasicMapping(JavaPersistentAttribute parent) {
@@ -398,7 +399,7 @@
 		throw new UnsupportedOperationException();
 	}
 	
-	public JavaCollectionTable2_0 buildJavaCollectionTable(JavaElementCollectionMapping2_0 parent) {
+	public JavaCollectionTable2_0 buildJavaCollectionTable(JavaElementCollectionMapping2_0 parent, Table.Owner owner) {
 		throw new UnsupportedOperationException();
 	}
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/JptValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/JptValidator.java
index 92e96e5..41b38db 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/JptValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/JptValidator.java
@@ -16,5 +16,8 @@
 
 public interface JptValidator
 {
-	void validate(List<IMessage> messages, IReporter reporter);
+	/**
+	 * Return a boolean used to determine whether to continue validating
+	 */
+	boolean validate(List<IMessage> messages, IReporter reporter);
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/TableTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/TableTextRangeResolver.java
new file mode 100644
index 0000000..947a1b0
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/TableTextRangeResolver.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ *  Copyright (c) 2010  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.core.internal.context;
+
+import org.eclipse.jpt.core.utility.TextRange;
+
+/**
+ * Interface to resolve text ranges on named columns
+ */
+public interface TableTextRangeResolver
+{
+	TextRange getNameTextRange();
+
+	TextRange getSchemaTextRange();
+
+	TextRange getCatalogTextRange();
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaEntity.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaEntity.java
index 3371d2f..ab6a533 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaEntity.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaEntity.java
@@ -29,6 +29,7 @@
 import org.eclipse.jpt.core.context.Entity;
 import org.eclipse.jpt.core.context.InheritanceType;
 import org.eclipse.jpt.core.context.JoinColumn;
+import org.eclipse.jpt.core.context.JoinTable;
 import org.eclipse.jpt.core.context.NamedColumn;
 import org.eclipse.jpt.core.context.PersistentAttribute;
 import org.eclipse.jpt.core.context.PersistentType;
@@ -57,14 +58,18 @@
 import org.eclipse.jpt.core.internal.context.JptValidator;
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideInverseJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinColumnValidator;
+import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinTableValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.AttributeOverrideColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.DiscriminatorColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.EntityPrimaryKeyJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.EntityTableDescriptionProvider;
 import org.eclipse.jpt.core.internal.jpa1.context.GenericEntityPrimaryKeyValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinTableTableDescriptionProvider;
+import org.eclipse.jpt.core.internal.jpa1.context.SecondaryTableValidator;
+import org.eclipse.jpt.core.internal.jpa1.context.TableValidator;
 import org.eclipse.jpt.core.internal.resource.java.NullPrimaryKeyJoinColumnAnnotation;
 import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
 import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
@@ -155,7 +160,7 @@
 	protected AbstractJavaEntity(JavaPersistentType parent) {
 		super(parent);
 		this.idClassReference = buildIdClassReference();
-		this.table = this.getJpaFactory().buildJavaTable(this);
+		this.table = this.getJpaFactory().buildJavaTable(this, new TableOwner());
 		this.discriminatorColumn = buildJavaDiscriminatorColumn();
 		this.specifiedSecondaryTables = new ArrayList<JavaSecondaryTable>();
 		this.specifiedPrimaryKeyJoinColumns = new ArrayList<JavaPrimaryKeyJoinColumn>();
@@ -487,7 +492,7 @@
 	}
 	
 	public JavaSecondaryTable addSpecifiedSecondaryTable(int index) {
-		JavaSecondaryTable secondaryTable = getJpaFactory().buildJavaSecondaryTable(this);
+		JavaSecondaryTable secondaryTable = getJpaFactory().buildJavaSecondaryTable(this, new SecondaryTableOwner());
 		this.specifiedSecondaryTables.add(index, secondaryTable);
 		SecondaryTableAnnotation secondaryTableResource = 
 				(SecondaryTableAnnotation) this.javaResourcePersistentType.
@@ -1259,7 +1264,7 @@
 	}
 
 	protected JavaSecondaryTable buildSecondaryTable(SecondaryTableAnnotation secondaryTableResource) {
-		JavaSecondaryTable secondaryTable = getJpaFactory().buildJavaSecondaryTable(this);
+		JavaSecondaryTable secondaryTable = getJpaFactory().buildJavaSecondaryTable(this, new SecondaryTableOwner());
 		secondaryTable.initialize(secondaryTableResource);
 		return secondaryTable;
 	}
@@ -1522,6 +1527,18 @@
 		return getResourceInheritance().getStrategyTextRange(astRoot);
 	}
 	
+
+	protected class TableOwner implements Table.Owner {
+		public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+			return new TableValidator(table, textRangeResolver);
+		}
+	}
+
+	protected class SecondaryTableOwner implements Table.Owner {
+		public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+			return new SecondaryTableValidator((SecondaryTable) table, textRangeResolver);
+		}
+	}
 	
 	// ********** association override container owner **********
 
@@ -1591,6 +1608,10 @@
 		public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 			return new AssociationOverrideInverseJoinColumnValidator(override, column, owner, textRangeResolver, new JoinTableTableDescriptionProvider());
 		}
+
+		public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) {
+			return new AssociationOverrideJoinTableValidator(override, (JoinTable) table, textRangeResolver);
+		}
 	}
 	
 	//********** AttributeOverrideContainer.Owner implementation *********	
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaJoinTableJoiningStrategy.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaJoinTableJoiningStrategy.java
index b0a729d..5789366 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaJoinTableJoiningStrategy.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaJoinTableJoiningStrategy.java
@@ -16,12 +16,12 @@
 import org.eclipse.jpt.core.context.JoinTableEnabledRelationshipReference;
 import org.eclipse.jpt.core.context.JoinTableJoiningStrategy;
 import org.eclipse.jpt.core.context.RelationshipMapping;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.java.JavaJoinTable;
 import org.eclipse.jpt.core.context.java.JavaJoinTableJoiningStrategy;
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.validation.JpaValidationDescriptionMessages;
 import org.eclipse.jpt.core.resource.java.JoinTableAnnotation;
-import org.eclipse.jpt.db.Table;
 import org.eclipse.jpt.utility.Filter;
 import org.eclipse.jpt.utility.internal.StringTools;
 import org.eclipse.wst.validation.internal.provisional.core.IMessage;
@@ -29,7 +29,7 @@
 
 public abstract class AbstractJavaJoinTableJoiningStrategy 
 	extends AbstractJavaJpaContextNode
-	implements JavaJoinTableJoiningStrategy
+	implements JavaJoinTableJoiningStrategy, Table.Owner
 {
 	protected JavaJoinTable joinTable;
 	
@@ -56,7 +56,7 @@
 		return getJoinTable().getName();
 	}
 
-	public Table getDbTable(String tableName) {
+	public org.eclipse.jpt.db.Table getDbTable(String tableName) {
 		return getJoinTable().getDbTable();
 	}
 
@@ -74,7 +74,7 @@
 
 	public void addStrategy() {
 		if (this.joinTable == null) {
-			this.joinTable = getJpaFactory().buildJavaJoinTable(this);
+			this.joinTable = this.buildJavaJoinTable();
 			addAnnotation();
 			this.firePropertyChanged(JOIN_TABLE_PROPERTY, null, this.joinTable);
 		}
@@ -127,7 +127,7 @@
 	public void initialize() {
 		JoinTableAnnotation annotation = getAnnotation();
 		if (mayHaveJoinTable()) {
-			this.joinTable = getJpaFactory().buildJavaJoinTable(this);
+			this.joinTable = this.buildJavaJoinTable();
 			this.joinTable.initialize(annotation);
 		}
 	}
@@ -136,7 +136,7 @@
 		JoinTableAnnotation annotation = getAnnotation();
 		if (mayHaveJoinTable()) {
 			if (this.joinTable == null) {
-				setJoinTable_(getJpaFactory().buildJavaJoinTable(this));
+				setJoinTable_(this.buildJavaJoinTable());
 			}
 			this.joinTable.update(annotation);
 		}
@@ -147,7 +147,12 @@
 			}
 		}
 	}
-	
+
+	protected JavaJoinTable buildJavaJoinTable() {
+		return getJpaFactory().buildJavaJoinTable(this, this);
+	}
+
+
 	// **************** Java completion proposals ******************************
 	
 	@Override
@@ -169,5 +174,4 @@
 			this.joinTable.validate(messages, reporter, astRoot);
 		}
 	}
-
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaTable.java
index db128ba..b99e9f5 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaTable.java
@@ -10,14 +10,16 @@
 package org.eclipse.jpt.core.internal.context.java;
 
 import java.util.Iterator;
+import java.util.List;
 import java.util.ListIterator;
 import java.util.Vector;
-
 import org.eclipse.jdt.core.dom.CompilationUnit;
-import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.UniqueConstraint;
+import org.eclipse.jpt.core.context.java.JavaBaseTable;
 import org.eclipse.jpt.core.context.java.JavaJpaContextNode;
 import org.eclipse.jpt.core.context.java.JavaUniqueConstraint;
+import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.resource.java.BaseTableAnnotation;
 import org.eclipse.jpt.core.resource.java.UniqueConstraintAnnotation;
 import org.eclipse.jpt.core.utility.TextRange;
@@ -33,13 +35,15 @@
 import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
 import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
 import org.eclipse.jpt.utility.internal.iterators.EmptyIterator;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 
 /**
  * Java table
  */
 public abstract class AbstractJavaTable
 	extends AbstractJavaJpaContextNode
-	implements Table, UniqueConstraint.Owner
+	implements JavaBaseTable, UniqueConstraint.Owner
 {
 	protected String specifiedName;
 	protected String defaultName;
@@ -52,13 +56,18 @@
 
 	protected final Vector<JavaUniqueConstraint> uniqueConstraints = new Vector<JavaUniqueConstraint>();
 
+	protected final Owner owner;
 
 	// ********** constructor **********
 
-	protected AbstractJavaTable(JavaJpaContextNode parent) {
+	protected AbstractJavaTable(JavaJpaContextNode parent, Owner owner) {
 		super(parent);
+		this.owner = owner;
 	}
 
+	protected Owner getOwner() {
+		return this.owner;
+	}
 
 	// ********** abstract methods **********
 
@@ -283,7 +292,7 @@
 		return (textRange != null) ? textRange : this.getParent().getValidationTextRange(astRoot);
 	}
 
-	protected TextRange getNameTextRange(CompilationUnit astRoot) {
+	public TextRange getNameTextRange(CompilationUnit astRoot) {
 		return this.getTextRange(this.getAnnotation().getNameTextRange(astRoot), astRoot);
 	}
 
@@ -291,7 +300,7 @@
 		return this.getAnnotation().nameTouches(pos, astRoot);
 	}
 
-	protected TextRange getSchemaTextRange(CompilationUnit astRoot) {
+	public TextRange getSchemaTextRange(CompilationUnit astRoot) {
 		return this.getTextRange(this.getAnnotation().getSchemaTextRange(astRoot), astRoot);
 	}
 
@@ -299,7 +308,7 @@
 		return this.getAnnotation().schemaTouches(pos, astRoot);
 	}
 
-	protected TextRange getCatalogTextRange(CompilationUnit astRoot) {
+	public TextRange getCatalogTextRange(CompilationUnit astRoot) {
 		return this.getTextRange(this.getAnnotation().getCatalogTextRange(astRoot), astRoot);
 	}
 
@@ -400,6 +409,19 @@
 		return this.getTextRange(this.getAnnotation().getTextRange(astRoot), astRoot);
 	}
 
+	@Override
+	public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+		super.validate(messages, reporter, astRoot);
+		this.buildTableValidator(astRoot).validate(messages, reporter);
+	}
+
+	protected JptValidator buildTableValidator(CompilationUnit astRoot) {
+		return this.getOwner().buildTableValidator(this, buildTextRangeResolver(astRoot));
+	}
+
+	protected TableTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
+		return new JavaTableTextRangeResolver(this, astRoot);
+	}
 
 	// ********** Java completion proposals **********
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinTableJoiningStrategy.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinTableJoiningStrategy.java
index 3db5f02..f2e1aae 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinTableJoiningStrategy.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinTableJoiningStrategy.java
@@ -11,13 +11,17 @@
 
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jpt.core.context.JoinColumn;
+import org.eclipse.jpt.core.context.JoinTable;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.java.JavaJoinTableEnabledRelationshipReference;
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.jpa1.context.InverseJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinTableTableDescriptionProvider;
+import org.eclipse.jpt.core.internal.jpa1.context.JoinTableValidator;
 import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute;
 import org.eclipse.jpt.core.resource.java.JoinTableAnnotation;
 import org.eclipse.jpt.core.utility.TextRange;
@@ -31,6 +35,10 @@
 	public GenericJavaJoinTableJoiningStrategy(JavaJoinTableEnabledRelationshipReference parent) {
 		super(parent);
 	}
+
+	public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+		return new JoinTableValidator((JoinTable) table, textRangeResolver);
+	}
 	
 	public boolean isOverridableAssociation() {
 		return getJpaPlatformVariation().isJoinTableOverridable();
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/JavaTableTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/JavaTableTextRangeResolver.java
new file mode 100644
index 0000000..3c8479c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/JavaTableTextRangeResolver.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ *  Copyright (c) 2010  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.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.core.context.java.JavaBaseTable;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.core.utility.TextRange;
+
+public class JavaTableTextRangeResolver
+	implements TableTextRangeResolver
+{
+	protected final JavaBaseTable javaTable;
+
+	protected final CompilationUnit astRoot;
+
+	public JavaTableTextRangeResolver(JavaBaseTable javaTable, CompilationUnit astRoot) {
+		this.javaTable = javaTable;
+		this.astRoot = astRoot;
+	}
+
+	protected JavaBaseTable getTable() {
+		return this.javaTable;
+	}
+
+	public TextRange getNameTextRange() {
+		return this.javaTable.getNameTextRange(this.astRoot);
+	}
+
+	public TextRange getCatalogTextRange() {
+		return this.javaTable.getCatalogTextRange(this.astRoot);
+	}
+
+	public TextRange getSchemaTextRange() {
+		return this.javaTable.getSchemaTextRange(this.astRoot);
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmEntity.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmEntity.java
index 5eb5118..48b90bd 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmEntity.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmEntity.java
@@ -31,6 +31,8 @@
 import org.eclipse.jpt.core.context.Entity;
 import org.eclipse.jpt.core.context.InheritanceType;
 import org.eclipse.jpt.core.context.JoinColumn;
+import org.eclipse.jpt.core.context.JoinTable;
+import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.NamedColumn;
 import org.eclipse.jpt.core.context.PersistentAttribute;
 import org.eclipse.jpt.core.context.PersistentType;
@@ -39,7 +41,6 @@
 import org.eclipse.jpt.core.context.SecondaryTable;
 import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.TypeMapping;
-import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverride;
 import org.eclipse.jpt.core.context.java.JavaAttributeOverride;
 import org.eclipse.jpt.core.context.java.JavaColumn;
@@ -69,15 +70,19 @@
 import org.eclipse.jpt.core.internal.context.JptValidator;
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.java.AbstractJavaEntity;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideInverseJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinColumnValidator;
+import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinTableValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.AttributeOverrideColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.DiscriminatorColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.EntityPrimaryKeyJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.EntityTableDescriptionProvider;
 import org.eclipse.jpt.core.internal.jpa1.context.GenericEntityPrimaryKeyValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinTableTableDescriptionProvider;
+import org.eclipse.jpt.core.internal.jpa1.context.SecondaryTableValidator;
+import org.eclipse.jpt.core.internal.jpa1.context.TableValidator;
 import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
 import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.jpa2.context.SingleRelationshipMapping2_0;
@@ -167,7 +172,7 @@
 	protected AbstractOrmEntity(OrmPersistentType parent, XmlEntity resourceMapping) {
 		super(parent, resourceMapping);
 		this.idClassReference = buildIdClassReference();
-		this.table = getXmlContextNodeFactory().buildOrmTable(this);
+		this.table = getXmlContextNodeFactory().buildOrmTable(this, new TableOwner());
 		this.specifiedSecondaryTables = new ArrayList<OrmSecondaryTable>();
 		this.virtualSecondaryTables = new ArrayList<OrmSecondaryTable>();
 		this.discriminatorColumn = buildDiscriminatorColumn();
@@ -1483,7 +1488,7 @@
 	}
 
 	protected OrmSecondaryTable buildSecondaryTable(XmlSecondaryTable xmlSecondaryTable) {
-		return getXmlContextNodeFactory().buildOrmSecondaryTable(this, xmlSecondaryTable);
+		return getXmlContextNodeFactory().buildOrmSecondaryTable(this, new SecondaryTableOwner(), xmlSecondaryTable);
 	}
 	
 	protected OrmSecondaryTable buildVirtualSecondaryTable(JavaSecondaryTable javaSecondaryTable) {
@@ -1805,7 +1810,19 @@
 	protected TextRange getInheritanceStrategyTextRange() {
 		return this.resourceTypeMapping.getInheritanceStrategyTextRange();
 	}
-		
+
+	protected class TableOwner implements Table.Owner {
+		public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+			return new TableValidator(table, textRangeResolver);
+		}
+	}
+
+	protected class SecondaryTableOwner implements Table.Owner {
+		public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+			return new SecondaryTableValidator((SecondaryTable) table, textRangeResolver);
+		}
+	}
+
 	protected class AssociationOverrideContainerOwner
 		implements OrmAssociationOverrideContainer.Owner
 	{
@@ -1868,7 +1885,11 @@
 		public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 			return new AssociationOverrideInverseJoinColumnValidator(override, column, owner, textRangeResolver, new JoinTableTableDescriptionProvider());
 		}
-		
+
+		public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) {
+			return new AssociationOverrideJoinTableValidator(override, (JoinTable) table, textRangeResolver);
+		}
+
 		public TextRange getValidationTextRange() {
 			return AbstractOrmEntity.this.getValidationTextRange();
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmJoinTableJoiningStrategy.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmJoinTableJoiningStrategy.java
index 7cc5d7a..6dbfa49 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmJoinTableJoiningStrategy.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmJoinTableJoiningStrategy.java
@@ -15,20 +15,20 @@
 import org.eclipse.jpt.core.context.JoinTableEnabledRelationshipReference;
 import org.eclipse.jpt.core.context.JoinTableJoiningStrategy;
 import org.eclipse.jpt.core.context.RelationshipMapping;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.orm.OrmJoinTable;
 import org.eclipse.jpt.core.context.orm.OrmJoinTableJoiningStrategy;
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.validation.JpaValidationDescriptionMessages;
 import org.eclipse.jpt.core.resource.orm.OrmFactory;
 import org.eclipse.jpt.core.resource.orm.XmlJoinTable;
-import org.eclipse.jpt.db.Table;
 import org.eclipse.jpt.utility.internal.StringTools;
 import org.eclipse.wst.validation.internal.provisional.core.IMessage;
 import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 
 public abstract class AbstractOrmJoinTableJoiningStrategy 
 	extends AbstractOrmXmlContextNode
-	implements OrmJoinTableJoiningStrategy
+	implements OrmJoinTableJoiningStrategy, Table.Owner
 {
 	protected OrmJoinTable joinTable;
 	
@@ -65,7 +65,7 @@
 		return getJoinTable().getName();
 	}
 
-	public Table getDbTable(String tableName) {
+	public org.eclipse.jpt.db.Table getDbTable(String tableName) {
 		return getJoinTable().getDbTable();
 	}
 
@@ -84,7 +84,7 @@
 	public void addStrategy() {
 		if (this.joinTable == null) {
 			XmlJoinTable resourceJoinTable = OrmFactory.eINSTANCE.createXmlJoinTable();
-			this.joinTable = getXmlContextNodeFactory().buildOrmJoinTable(this, resourceJoinTable);
+			this.joinTable = this.buildOrmJoinTable(resourceJoinTable);
 			setResourceJoinTable(resourceJoinTable);
 			this.firePropertyChanged(JOIN_TABLE_PROPERTY, null, this.joinTable);
 		}
@@ -135,14 +135,14 @@
 	
 	protected void initialize() {
 		if (mayHaveJoinTable()) {
-			this.joinTable = getXmlContextNodeFactory().buildOrmJoinTable(this, getResourceJoinTable());
+			this.joinTable = this.buildOrmJoinTable(getResourceJoinTable());
 		}
 	}
 	
 	public void update() {
 		if (mayHaveJoinTable()) {
 			if (this.joinTable == null) {
-				setJoinTable_(getXmlContextNodeFactory().buildOrmJoinTable(this, getResourceJoinTable()));
+				setJoinTable_(this.buildOrmJoinTable(getResourceJoinTable()));
 			}
 			this.joinTable.update();
 		}
@@ -153,8 +153,12 @@
 			}
 		}
 	}
-	
-	
+
+	protected OrmJoinTable buildOrmJoinTable(XmlJoinTable resourceJoinTable) {
+		return getXmlContextNodeFactory().buildOrmJoinTable(this, this, resourceJoinTable);
+	}
+
+
 	// **************** validation *********************************************
 	
 	@Override
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmTable.java
index 41d1ff0..c567ac4 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmTable.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2009 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2010 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.
@@ -13,13 +13,15 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
-
 import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.UniqueConstraint;
 import org.eclipse.jpt.core.context.XmlContextNode;
+import org.eclipse.jpt.core.context.orm.OrmBaseTable;
 import org.eclipse.jpt.core.context.orm.OrmUniqueConstraint;
-import org.eclipse.jpt.core.resource.orm.OrmFactory;
+import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.resource.orm.AbstractXmlTable;
+import org.eclipse.jpt.core.resource.orm.OrmFactory;
 import org.eclipse.jpt.core.resource.orm.XmlUniqueConstraint;
 import org.eclipse.jpt.core.utility.TextRange;
 import org.eclipse.jpt.db.Catalog;
@@ -30,13 +32,15 @@
 import org.eclipse.jpt.utility.internal.iterators.CloneIterator;
 import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
 import org.eclipse.jpt.utility.internal.iterators.EmptyIterator;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 
 /**
  * 
  */
 public abstract class AbstractOrmTable
 	extends AbstractOrmXmlContextNode
-	implements Table, UniqueConstraint.Owner
+	implements OrmBaseTable, UniqueConstraint.Owner
 {
 	protected String specifiedName;
 	protected String defaultName;
@@ -49,12 +53,19 @@
 
 	protected final List<OrmUniqueConstraint> uniqueConstraints;
 
+	protected final Owner owner;
+
 
 	// ********** constructor **********
 
-	protected AbstractOrmTable(XmlContextNode parent) {
+	protected AbstractOrmTable(XmlContextNode parent, Owner owner) {
 		super(parent);
 		this.uniqueConstraints = new ArrayList<OrmUniqueConstraint>();
+		this.owner = owner;
+	}
+
+	protected Owner getOwner() {
+		return this.owner;
 	}
 
 
@@ -272,7 +283,7 @@
 		return (textRange != null) ? textRange : this.getParent().getValidationTextRange();
 	}
 
-	protected TextRange getNameTextRange() {
+	public TextRange getNameTextRange() {
 		return this.getTextRange(this.getResourceTableNameTextRange());
 	}
 
@@ -281,7 +292,7 @@
 		return (resourceTable == null) ? null : resourceTable.getNameTextRange();
 	}
 
-	protected TextRange getSchemaTextRange() {
+	public TextRange getSchemaTextRange() {
 		return this.getTextRange(this.getResourceTableSchemaTextRange());
 	}
 
@@ -290,7 +301,7 @@
 		return (resourceTable == null) ? null : resourceTable.getSchemaTextRange();
 	}
 
-	protected TextRange getCatalogTextRange() {
+	public TextRange getCatalogTextRange() {
 		return this.getTextRange(this.getResourceTableCatalogTextRange());
 	}
 
@@ -446,6 +457,20 @@
 		return this.getTextRange(this.getResourceTableValidationTextRange());
 	}
 
+	@Override
+	public void validate(List<IMessage> messages, IReporter reporter) {
+		super.validate(messages, reporter);
+		this.buildTableValidator().validate(messages, reporter);
+	}
+
+	protected JptValidator buildTableValidator() {
+		return this.getOwner().buildTableValidator(this, buildTextRangeResolver());
+	}
+
+	protected TableTextRangeResolver buildTextRangeResolver() {
+		return new OrmTableTextRangeResolver(this);
+	}
+
 	protected TextRange getResourceTableValidationTextRange() {
 		AbstractXmlTable resourceTable = this.getResourceTable();
 		return (resourceTable == null) ? null : resourceTable.getValidationTextRange();
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmXmlContextNodeFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmXmlContextNodeFactory.java
index 5fdcfc1..8f60cb8 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmXmlContextNodeFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmXmlContextNodeFactory.java
@@ -13,6 +13,7 @@
 import org.eclipse.jpt.core.context.AttributeOverride;
 import org.eclipse.jpt.core.context.JoiningStrategy;
 import org.eclipse.jpt.core.context.Orderable;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.UniqueConstraint;
 import org.eclipse.jpt.core.context.XmlContextNode;
 import org.eclipse.jpt.core.context.java.JavaAttributeMapping;
@@ -210,20 +211,20 @@
 		return new GenericOrmPersistentAttribute(parent, owner, resourceMapping);
 	}
 	
-	public OrmTable buildOrmTable(OrmEntity parent) {
-		return new GenericOrmTable(parent);
+	public OrmTable buildOrmTable(OrmEntity parent, Table.Owner owner) {
+		return new GenericOrmTable(parent, owner);
 	}
 	
-	public OrmSecondaryTable buildOrmSecondaryTable(OrmEntity parent, XmlSecondaryTable xmlSecondaryTable) {
-		return new GenericOrmSecondaryTable(parent, xmlSecondaryTable);
+	public OrmSecondaryTable buildOrmSecondaryTable(OrmEntity parent, Table.Owner owner, XmlSecondaryTable xmlSecondaryTable) {
+		return new GenericOrmSecondaryTable(parent, owner, xmlSecondaryTable);
 	}
 	
 	public OrmPrimaryKeyJoinColumn buildOrmPrimaryKeyJoinColumn(XmlContextNode parent, OrmBaseJoinColumn.Owner owner, XmlPrimaryKeyJoinColumn resourcePkJoinColumn) {
 		return new GenericOrmPrimaryKeyJoinColumn(parent, owner, resourcePkJoinColumn);
 	}
 	
-	public OrmJoinTable buildOrmJoinTable(OrmJoinTableJoiningStrategy parent, XmlJoinTable resourceJoinTable) {
-		return new GenericOrmJoinTable(parent, resourceJoinTable);
+	public OrmJoinTable buildOrmJoinTable(OrmJoinTableJoiningStrategy parent, Table.Owner owner, XmlJoinTable resourceJoinTable) {
+		return new GenericOrmJoinTable(parent, owner, resourceJoinTable);
 	}
 	
 	public OrmJoinColumn buildOrmJoinColumn(XmlContextNode parent, OrmJoinColumn.Owner owner, XmlJoinColumn resourceJoinColumn) {
@@ -389,7 +390,7 @@
 		return new NullOrmOrphanRemoval2_0(parent);
 	}
 	
-	public OrmCollectionTable2_0 buildOrmCollectionTable(OrmElementCollectionMapping2_0 parent, XmlCollectionTable resource) {
+	public OrmCollectionTable2_0 buildOrmCollectionTable(OrmElementCollectionMapping2_0 parent, Table.Owner owner, XmlCollectionTable resource) {
 		throw new UnsupportedOperationException();
 	}
 	
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinTableJoiningStrategy.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinTableJoiningStrategy.java
index 2749795..22c0f41 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinTableJoiningStrategy.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinTableJoiningStrategy.java
@@ -11,14 +11,18 @@
 package org.eclipse.jpt.core.internal.context.orm;
 
 import org.eclipse.jpt.core.context.JoinColumn;
+import org.eclipse.jpt.core.context.JoinTable;
 import org.eclipse.jpt.core.context.PersistentAttribute;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.orm.OrmJoinTableEnabledRelationshipReference;
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.jpa1.context.InverseJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinTableTableDescriptionProvider;
+import org.eclipse.jpt.core.internal.jpa1.context.JoinTableValidator;
 import org.eclipse.jpt.core.resource.orm.XmlJoinTable;
 import org.eclipse.jpt.core.resource.orm.XmlJoinTableMapping;
 import org.eclipse.jpt.core.utility.TextRange;
@@ -89,4 +93,8 @@
 	public JptValidator buildJoinTableInverseJoinColumnValidator(JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 		return new InverseJoinColumnValidator(this.getPersistentAttribute(), column, owner, textRangeResolver, new JoinTableTableDescriptionProvider());
 	}
+
+	public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+		return new JoinTableValidator(getPersistentAttribute(), (JoinTable) table, textRangeResolver);
+	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/NullOrmJoinTableJoiningStrategy.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/NullOrmJoinTableJoiningStrategy.java
index 21221a1..0c7876b 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/NullOrmJoinTableJoiningStrategy.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/NullOrmJoinTableJoiningStrategy.java
@@ -11,11 +11,13 @@
 package org.eclipse.jpt.core.internal.context.orm;
 
 import org.eclipse.jpt.core.context.JoinColumn;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.orm.OrmJoinTableEnabledRelationshipReference;
 import org.eclipse.jpt.core.context.orm.OrmRelationshipMapping;
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.resource.orm.XmlJoinTable;
 import org.eclipse.jpt.core.utility.TextRange;
 
@@ -88,4 +90,8 @@
 	public JptValidator buildJoinTableInverseJoinColumnValidator(JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 		throw new UnsupportedOperationException();
 	}
+
+	public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+		throw new UnsupportedOperationException();
+	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/OrmTableTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/OrmTableTextRangeResolver.java
new file mode 100644
index 0000000..e54b477
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/OrmTableTextRangeResolver.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ *  Copyright (c) 2010  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.core.internal.context.orm;
+
+import org.eclipse.jpt.core.context.orm.OrmBaseTable;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.core.utility.TextRange;
+
+public class OrmTableTextRangeResolver
+	implements TableTextRangeResolver
+{
+	protected final OrmBaseTable ormTable;
+
+	public OrmTableTextRangeResolver(OrmBaseTable ormTable) {
+		this.ormTable = ormTable;
+	}
+
+	protected OrmBaseTable getTable() {
+		return this.ormTable;
+	}
+
+	public TextRange getNameTextRange() {
+		return this.ormTable.getNameTextRange();
+	}
+
+	public TextRange getCatalogTextRange() {
+		return this.ormTable.getCatalogTextRange();
+	}
+
+	public TextRange getSchemaTextRange() {
+		return this.ormTable.getSchemaTextRange();
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractJoinTableValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractJoinTableValidator.java
new file mode 100644
index 0000000..644be2d
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractJoinTableValidator.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.core.internal.jpa1.context;
+
+import org.eclipse.jpt.core.context.JoinTable;
+import org.eclipse.jpt.core.context.PersistentAttribute;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
+
+public abstract class AbstractJoinTableValidator extends AbstractTableValidator
+{
+	protected AbstractJoinTableValidator(JoinTable table, TableTextRangeResolver textRangeResolver) {
+		super(table, textRangeResolver);
+	}
+
+	protected AbstractJoinTableValidator(PersistentAttribute persistentAttribute, JoinTable table, TableTextRangeResolver textRangeResolver) {
+		super(persistentAttribute, table, textRangeResolver);
+	}
+
+	@Override
+	protected String getUnresolvedCatalogMessage() {
+		return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_CATALOG;
+	}
+
+	@Override
+	protected String getUnresolvedSchemaMessage() {
+		return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_SCHEMA;
+	}
+
+	@Override
+	protected String getUnresolvedNameMessage() {
+		return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_NAME;
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractNamedColumnValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractNamedColumnValidator.java
index 6fa112d..f6d9513 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractNamedColumnValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractNamedColumnValidator.java
@@ -88,13 +88,12 @@
 		return this.persistentAttribute.getName();
 	}
 
-	public void validate(List<IMessage> messages, IReporter reporter) {
+	public boolean validate(List<IMessage> messages, IReporter reporter) {
 		if (this.tableValidator.isTableNameInvalid()) {
-			this.tableValidator.validate(messages, reporter);
+			return this.tableValidator.validate(messages, reporter);
 		}
-		else {
-			this.validateName(messages);
-		}
+		this.validateName(messages);
+		return true;
 	}
 
 	protected void validateName(List<IMessage> messages) {
@@ -140,8 +139,8 @@
 	}
 	
 	public static class NullTableValidator implements TableValidator {
-		public void validate(List<IMessage> messages, IReporter reporter) {
-			// nothing to validate
+		public boolean validate(List<IMessage> messages, IReporter reporter) {
+			return true;
 		}
 		public boolean isTableNameInvalid() {
 			return false;
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractPersistentAttributeValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractPersistentAttributeValidator.java
index 32259ee..fd75e58 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractPersistentAttributeValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractPersistentAttributeValidator.java
@@ -36,8 +36,9 @@
 	}
 
 
-	public void validate(List<IMessage> messages, IReporter reporter) {
+	public boolean validate(List<IMessage> messages, IReporter reporter) {
 		this.validateAttribute(messages);
+		return true;
 	}
 
 	protected abstract void validateAttribute(List<IMessage> messages);
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractTableValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractTableValidator.java
new file mode 100644
index 0000000..c906c56
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractTableValidator.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ *  Copyright (c) 2010  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.core.internal.jpa1.context;
+
+import java.util.List;
+import org.eclipse.jpt.core.context.PersistentAttribute;
+import org.eclipse.jpt.core.context.Table;
+import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+public abstract class AbstractTableValidator
+	implements JptValidator
+{
+
+	protected final PersistentAttribute persistentAttribute;
+
+	protected final Table table;
+
+	protected final TableTextRangeResolver textRangeResolver;
+
+	protected AbstractTableValidator(
+				Table table,
+				TableTextRangeResolver textRangeResolver) {
+		this(null, table, textRangeResolver);
+	}
+
+	protected AbstractTableValidator(
+				PersistentAttribute persistentAttribute,
+				Table table,
+				TableTextRangeResolver textRangeResolver) {
+		super();
+		this.persistentAttribute = persistentAttribute;
+		this.table = table;
+		this.textRangeResolver = textRangeResolver;
+	}
+
+	protected Table getTable() {
+		return this.table;
+	}
+
+	protected TableTextRangeResolver getTextRangeResolver() {
+		return this.textRangeResolver;
+	}
+
+	protected boolean isPersistentAttributeVirtual() {
+		return this.persistentAttribute != null && this.persistentAttribute.isVirtual();
+	}
+
+	protected String getPersistentAttributeName() {
+		return this.persistentAttribute.getName();
+	}
+
+	public boolean validate(List<IMessage> messages, IReporter reporter) {
+		if (this.shouldValidateAgainstDatabase()) {
+			return this.validateAgainstDatabase(messages);
+		}
+		return false;
+	}
+
+	protected boolean shouldValidateAgainstDatabase() {
+		return this.table.shouldValidateAgainstDatabase();
+	}
+
+	protected boolean validateAgainstDatabase(List<IMessage> messages) {
+		if ( ! this.table.hasResolvedCatalog()) {
+			messages.add(buildUnresolvedCatalogMessage());
+			return false;
+		}
+
+		if ( ! this.table.hasResolvedSchema()) {
+			messages.add(buildUnresolvedSchemaMessage());
+			return false;
+		}
+
+		if ( ! this.table.isResolved()) {
+			if (this.table.getName() != null) { //if name is null, the validation will be handled elsewhere, such as the target entity is not defined
+				messages.add(buildUnresolvedNameMessage());
+			}
+			return false;
+		}
+		return true;
+	}
+
+	protected IMessage buildUnresolvedCatalogMessage() {
+		if (isPersistentAttributeVirtual()) {
+			return this.buildVirtualAttributeUnresolvedCatalogMessage();
+		}
+		return this.buildUnresolvedCatalogMessage(this.getUnresolvedCatalogMessage());
+	}
+
+	protected abstract String getUnresolvedCatalogMessage();
+
+	protected IMessage buildUnresolvedCatalogMessage(String message) {
+		return DefaultJpaValidationMessages.buildMessage(
+			IMessage.HIGH_SEVERITY,
+			message,
+			new String[] {this.table.getCatalog(), this.table.getName()}, 
+			this.table, 
+			this.textRangeResolver.getCatalogTextRange()
+		);
+	}
+
+	protected IMessage buildVirtualAttributeUnresolvedCatalogMessage() {
+		return DefaultJpaValidationMessages.buildMessage(
+			IMessage.HIGH_SEVERITY,
+			this.getVirtualAttributeUnresolvedCatalogMessage(),
+			new String[] {this.getPersistentAttributeName(), this.table.getCatalog(), this.table.getName()},
+			this.table, 
+			this.textRangeResolver.getCatalogTextRange()
+		);
+	}
+
+	protected abstract String getVirtualAttributeUnresolvedCatalogMessage();
+
+	protected IMessage buildUnresolvedSchemaMessage() {
+		if (isPersistentAttributeVirtual()) {
+			return this.buildVirtualAttributeUnresolvedSchemaMessage();
+		}
+		return this.buildUnresolvedSchemaMessage(this.getUnresolvedSchemaMessage());
+	}
+
+	protected abstract String getUnresolvedSchemaMessage();
+
+	protected IMessage buildUnresolvedSchemaMessage(String message) {
+		return DefaultJpaValidationMessages.buildMessage(
+			IMessage.HIGH_SEVERITY,
+			message,
+			new String[] {this.table.getSchema(), this.table.getName()}, 
+			this.table, 
+			this.textRangeResolver.getSchemaTextRange()
+		);
+	}
+
+	protected IMessage buildVirtualAttributeUnresolvedSchemaMessage() {
+		return DefaultJpaValidationMessages.buildMessage(
+			IMessage.HIGH_SEVERITY,
+			this.getVirtualAttributeUnresolvedSchemaMessage(),
+			new String[] {this.getPersistentAttributeName(), this.table.getSchema(), this.table.getName()},
+			this.table, 
+			this.textRangeResolver.getSchemaTextRange()
+		);
+	}
+
+	protected abstract String getVirtualAttributeUnresolvedSchemaMessage();
+
+	protected IMessage buildUnresolvedNameMessage() {
+		if (isPersistentAttributeVirtual()) {
+			return this.buildVirtualAttributeUnresolvedNameMessage();
+		}
+		return this.buildUnresolvedNameMessage(this.getUnresolvedNameMessage());
+	}
+
+	protected abstract String getUnresolvedNameMessage();
+
+	protected IMessage buildUnresolvedNameMessage(String message) {
+		return DefaultJpaValidationMessages.buildMessage(
+			IMessage.HIGH_SEVERITY,
+			message,
+			new String[] {this.table.getName()}, 
+			this.table, 
+			this.textRangeResolver.getNameTextRange()
+		);
+	}
+
+	protected IMessage buildVirtualAttributeUnresolvedNameMessage() {
+		return DefaultJpaValidationMessages.buildMessage(
+			IMessage.HIGH_SEVERITY,
+			this.getVirtualAttributeUnresolvedNameMessage(),
+			new String[] {this.getPersistentAttributeName(), this.table.getName()},
+			this.table, 
+			this.textRangeResolver.getNameTextRange()
+		);
+	}
+
+	protected abstract String getVirtualAttributeUnresolvedNameMessage();
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractTypeMappingValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractTypeMappingValidator.java
index e8bcdbb..fd5a5c7 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractTypeMappingValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractTypeMappingValidator.java
@@ -37,8 +37,9 @@
 	}
 
 
-	public void validate(List<IMessage> messages, IReporter reporter) {
+	public boolean validate(List<IMessage> messages, IReporter reporter) {
 		this.validateType(messages);
+		return true;
 	}
 
 	protected abstract void validateType(List<IMessage> messages);
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AssociationOverrideInverseJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AssociationOverrideInverseJoinColumnValidator.java
index 3924492..dbbfc12 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AssociationOverrideInverseJoinColumnValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AssociationOverrideInverseJoinColumnValidator.java
@@ -19,7 +19,7 @@
 import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.wst.validation.internal.provisional.core.IMessage;
 
-public class AssociationOverrideInverseJoinColumnValidator extends JoinColumnValidator
+public class AssociationOverrideInverseJoinColumnValidator extends InverseJoinColumnValidator
 {
 	private final AssociationOverride override;
 
@@ -46,7 +46,7 @@
 
 	@Override
 	protected TableValidator buildTableValidator() {
-		return new AssociationOverrideJoinColumnTableValidator(this.persistentAttribute, this.getColumn(), this.getTextRangeResolver(), this.tableDescriptionProvider);
+		return new AssociationOverrideInverseJoinColumnTableValidator(this.persistentAttribute, this.getColumn(), this.getTextRangeResolver(), this.tableDescriptionProvider);
 	}
 
 	@Override
@@ -194,9 +194,9 @@
 	}
 
 
-	public class AssociationOverrideJoinColumnTableValidator extends JoinColumnTableValidator {
+	public class AssociationOverrideInverseJoinColumnTableValidator extends InverseJoinColumnTableValidator {
 
-		protected AssociationOverrideJoinColumnTableValidator(
+		protected AssociationOverrideInverseJoinColumnTableValidator(
 			PersistentAttribute persistentAttribute, JoinColumn column, JoinColumnTextRangeResolver textRangeResolver, TableDescriptionProvider provider) {
 			super(persistentAttribute, column, textRangeResolver, provider);
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AssociationOverrideJoinTableValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AssociationOverrideJoinTableValidator.java
new file mode 100644
index 0000000..c47f12d
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AssociationOverrideJoinTableValidator.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ *  Copyright (c) 2010  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.core.internal.jpa1.context;
+
+import org.eclipse.jpt.core.context.AssociationOverride;
+import org.eclipse.jpt.core.context.JoinTable;
+import org.eclipse.jpt.core.context.PersistentAttribute;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+
+public class AssociationOverrideJoinTableValidator extends AbstractJoinTableValidator
+{
+	private final AssociationOverride override;
+
+	public AssociationOverrideJoinTableValidator(
+				AssociationOverride override,
+				JoinTable table,
+				TableTextRangeResolver textRangeResolver) {
+		super(table, textRangeResolver);
+		this.override = override;
+	}
+
+	public AssociationOverrideJoinTableValidator(
+				PersistentAttribute persistentAttribute,
+				AssociationOverride override, 
+				JoinTable table, 
+				TableTextRangeResolver textRangeResolver) {
+		super(persistentAttribute, table, textRangeResolver);
+		this.override = override;
+	}
+
+	@Override
+	protected IMessage buildUnresolvedNameMessage() {
+		if (this.override.isVirtual()) {
+			return this.buildVirtualOverrideUnresolvedNameMessage();
+		}
+		return super.buildUnresolvedNameMessage();
+	}
+
+	protected IMessage buildVirtualOverrideUnresolvedNameMessage() {
+		return DefaultJpaValidationMessages.buildMessage(
+			IMessage.HIGH_SEVERITY,
+			JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME,
+			new String[] {this.override.getName(), this.getTable().getName()},
+			this.getTable(), 
+			this.getTextRangeResolver().getNameTextRange()
+		);
+	}
+
+	@Override
+	protected IMessage buildUnresolvedCatalogMessage() {
+		if (this.override.isVirtual()) {
+			return this.buildVirtualOverrideUnresolvedCatalogMessage();
+		}
+		return super.buildUnresolvedCatalogMessage();
+	}
+
+	protected IMessage buildVirtualOverrideUnresolvedCatalogMessage() {
+		return DefaultJpaValidationMessages.buildMessage(
+			IMessage.HIGH_SEVERITY,
+			JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG,
+			new String[] {this.override.getName(), this.getTable().getCatalog()},
+			this.getTable(), 
+			this.getTextRangeResolver().getCatalogTextRange()
+		);
+	}
+
+	@Override
+	protected IMessage buildUnresolvedSchemaMessage() {
+		if (this.override.isVirtual()) {
+			return this.buildVirtualOverrideUnresolvedSchemaMessage();
+		}
+		return super.buildUnresolvedSchemaMessage();
+	}
+
+	protected IMessage buildVirtualOverrideUnresolvedSchemaMessage() {
+		return DefaultJpaValidationMessages.buildMessage(
+			IMessage.HIGH_SEVERITY,
+			JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA,
+			new String[] {this.override.getName(), this.getTable().getSchema()},
+			this.getTable(), 
+			this.getTextRangeResolver().getSchemaTextRange()
+		);
+	}
+
+	@Override
+	protected IMessage buildVirtualAttributeUnresolvedNameMessage() {
+		throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$
+	}
+
+	@Override
+	protected IMessage buildVirtualAttributeUnresolvedCatalogMessage() {
+		throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$
+	}
+
+	@Override
+	protected IMessage buildVirtualAttributeUnresolvedSchemaMessage() {
+		throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedCatalogMessage() {
+		throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedSchemaMessage() {
+		throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedNameMessage() {
+		throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AttributeOverrideColumnValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AttributeOverrideColumnValidator.java
index 63604d9..8bf0567 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AttributeOverrideColumnValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AttributeOverrideColumnValidator.java
@@ -127,6 +127,22 @@
 		}
 		
 		@Override
+		protected IMessage buildVirtualAttributeTableNotValidMessage() {
+			return DefaultJpaValidationMessages.buildMessage(
+				IMessage.HIGH_SEVERITY,
+				this.getVirtualAttributeColumnTableNotValidMessage(),
+				new String[] {
+					getPersistentAttributeName(),
+					AttributeOverrideColumnValidator.this.override.getName(),
+					getColumn().getTable(),
+					getColumn().getName(),
+					this.getColumnTableDescriptionMessage()},
+				getColumn(), 
+				getTextRangeResolver().getTableTextRange()
+			);
+		}
+
+		@Override
 		protected String getVirtualAttributeColumnTableNotValidMessage() {
 			return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID;
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/BaseColumnTableValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/BaseColumnTableValidator.java
index bf0386f..48069d2 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/BaseColumnTableValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/BaseColumnTableValidator.java
@@ -60,8 +60,9 @@
 		return this.getColumn().tableNameIsInvalid();
 	}
 	
-	public void validate(List<IMessage> messages, IReporter reporter) {
+	public boolean validate(List<IMessage> messages, IReporter reporter) {
 		messages.add(buildTableNotValidMessage());
+		return false;
 	}
 
 	public IMessage buildTableNotValidMessage() {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.java
index 82eb610..f5305f4 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.java
@@ -37,7 +37,7 @@
 		return entity().getIdClassReference();
 	}
 	
-	public void validate(List<IMessage> messages, IReporter reporter) {
+	public boolean validate(List<IMessage> messages, IReporter reporter) {
 		// if an entity is non-root, it is not allowed to define primary keys
 		if (! entity().isRoot()) {
 			validatePrimaryKeyForNonRoot(messages, reporter);
@@ -45,6 +45,7 @@
 		else {
 			validatePrimaryKeyForRoot(messages, reporter);
 		}
+		return true;
 	}
 	
 	protected void validatePrimaryKeyForNonRoot(List<IMessage> messages, IReporter reporter) {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java
index 55fe515..d61d1f0 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java
@@ -36,7 +36,7 @@
 		return mappedSuperclass().getIdClassReference();
 	}
 	
-	public void validate(List<IMessage> messages, IReporter reporter) {
+	public boolean validate(List<IMessage> messages, IReporter reporter) {
 		validatePrimaryKeyIsNotRedefined(messages, reporter);
 		validateIdClassIsUsedIfNecessary(messages, reporter);
 		
@@ -48,5 +48,6 @@
 		if (specifiesIdClass()) {
 			validateIdClass(idClassReference().getIdClass(), messages, reporter);
 		}
+		return true;
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/JoinTableValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/JoinTableValidator.java
new file mode 100644
index 0000000..b60662c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/JoinTableValidator.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.core.internal.jpa1.context;
+
+import org.eclipse.jpt.core.context.JoinTable;
+import org.eclipse.jpt.core.context.PersistentAttribute;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
+
+public class JoinTableValidator extends AbstractJoinTableValidator
+{
+	public JoinTableValidator(JoinTable table, TableTextRangeResolver textRangeResolver) {
+		super(table, textRangeResolver);
+	}
+
+	public JoinTableValidator(PersistentAttribute persistentAttribute, JoinTable table, TableTextRangeResolver textRangeResolver) {
+		super(persistentAttribute, table, textRangeResolver);
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedCatalogMessage() {
+		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_CATALOG;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedSchemaMessage() {
+		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_SCHEMA;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedNameMessage() {
+		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_NAME;
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/SecondaryTablePrimaryKeyJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/SecondaryTablePrimaryKeyJoinColumnValidator.java
index 37f6fda..da7f5e8 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/SecondaryTablePrimaryKeyJoinColumnValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/SecondaryTablePrimaryKeyJoinColumnValidator.java
@@ -73,7 +73,7 @@
 		return DefaultJpaValidationMessages.buildMessage(
 			IMessage.HIGH_SEVERITY,
 			JpaValidationMessages.VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME,
-			new String[] {this.getSecondaryTableName(), getColumn().getName(), getColumn().getDbTable().getName()},
+			new String[] {this.getSecondaryTableName(), getColumn().getReferencedColumnName(), getColumn().getReferencedColumnDbTable().getName()},
 			getColumn(), 
 			getTextRangeResolver().getReferencedColumnNameTextRange()
 		);
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/SecondaryTableValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/SecondaryTableValidator.java
new file mode 100644
index 0000000..170c4df
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/SecondaryTableValidator.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.core.internal.jpa1.context;
+
+import org.eclipse.jpt.core.context.SecondaryTable;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
+
+public class SecondaryTableValidator extends AbstractTableValidator
+{
+	public SecondaryTableValidator(SecondaryTable table, TableTextRangeResolver textRangeResolver) {
+		super(table, textRangeResolver);
+	}
+
+	@Override
+	public SecondaryTable getTable() {
+		return (SecondaryTable) super.getTable();
+	}
+
+	@Override
+	protected String getUnresolvedCatalogMessage() {
+		return JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_CATALOG;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedCatalogMessage() {
+		throw new UnsupportedOperationException("No SecondaryTable annotations exist on attributes"); //$NON-NLS-1$
+	}
+
+	@Override
+	protected String getUnresolvedSchemaMessage() {
+		return JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_SCHEMA;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedSchemaMessage() {
+		throw new UnsupportedOperationException("No SecondaryTable annotations exist on attributes"); //$NON-NLS-1$
+	}
+
+	@Override
+	protected String getUnresolvedNameMessage() {
+		return JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_NAME;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedNameMessage() {
+		throw new UnsupportedOperationException("No SecondaryTable annotations exist on attributes"); //$NON-NLS-1$
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/TableValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/TableValidator.java
new file mode 100644
index 0000000..a9b040a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/TableValidator.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.core.internal.jpa1.context;
+
+import org.eclipse.jpt.core.context.Table;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
+
+public class TableValidator extends AbstractTableValidator
+{
+	public TableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+		super(table, textRangeResolver);
+	}
+
+	@Override
+	protected String getUnresolvedCatalogMessage() {
+		return JpaValidationMessages.TABLE_UNRESOLVED_CATALOG;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedCatalogMessage() {
+		throw new UnsupportedOperationException("No Table annotations exist on attributes"); //$NON-NLS-1$
+	}
+
+	@Override
+	protected String getUnresolvedSchemaMessage() {
+		return JpaValidationMessages.TABLE_UNRESOLVED_SCHEMA;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedSchemaMessage() {
+		throw new UnsupportedOperationException("No Table annotations exist on attributes"); //$NON-NLS-1$
+	}
+
+	@Override
+	protected String getUnresolvedNameMessage() {
+		return JpaValidationMessages.TABLE_UNRESOLVED_NAME;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedNameMessage() {
+		throw new UnsupportedOperationException("No Table annotations exist on attributes"); //$NON-NLS-1$
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java
index 8b61da8..c3054d7 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java
@@ -21,6 +21,7 @@
 import org.eclipse.jpt.core.context.JoinColumn;
 import org.eclipse.jpt.core.context.RelationshipMapping;
 import org.eclipse.jpt.core.context.RelationshipReference;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.TypeMapping;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverride;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer;
@@ -29,13 +30,13 @@
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
 import org.eclipse.jpt.core.internal.context.MappingTools;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode;
 import org.eclipse.jpt.core.resource.java.AssociationOverrideAnnotation;
 import org.eclipse.jpt.core.resource.java.AssociationOverridesAnnotation;
 import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember;
 import org.eclipse.jpt.core.resource.java.NestableAnnotation;
 import org.eclipse.jpt.core.utility.TextRange;
-import org.eclipse.jpt.db.Table;
 import org.eclipse.jpt.utility.Filter;
 import org.eclipse.jpt.utility.internal.CollectionTools;
 import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
@@ -420,7 +421,7 @@
 			return getOwner().getDefaultTableName();
 		}
 
-		public Table getDbTable(String tableName) {
+		public org.eclipse.jpt.db.Table getDbTable(String tableName) {
 			return getOwner().getDbTable(tableName);
 		}
 
@@ -435,5 +436,9 @@
 		public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, org.eclipse.jpt.core.context.JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 			return getOwner().buildJoinTableInverseJoinColumnValidator(override, column, owner, textRangeResolver);
 		}
+
+		public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) {
+			return getOwner().buildTableValidator(override, table, textRangeResolver);
+		}
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java
index 3664af3..4f40cff 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java
@@ -19,18 +19,22 @@
 import org.eclipse.jpt.core.context.BaseColumn;
 import org.eclipse.jpt.core.context.BaseOverride;
 import org.eclipse.jpt.core.context.JoinColumn;
-import org.eclipse.jpt.core.context.RelationshipReference;
-import org.eclipse.jpt.core.context.TypeMapping;
 import org.eclipse.jpt.core.context.JoinColumn.Owner;
+import org.eclipse.jpt.core.context.JoinTable;
+import org.eclipse.jpt.core.context.RelationshipReference;
+import org.eclipse.jpt.core.context.Table;
+import org.eclipse.jpt.core.context.TypeMapping;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer;
 import org.eclipse.jpt.core.context.java.JavaPersistentAttribute;
 import org.eclipse.jpt.core.internal.context.BaseColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
 import org.eclipse.jpt.core.internal.context.MappingTools;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.java.AbstractJavaBaseEmbeddedMapping;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideInverseJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinColumnValidator;
+import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinTableValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.EntityTableDescriptionProvider;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinTableTableDescriptionProvider;
 import org.eclipse.jpt.core.jpa2.JpaFactory2_0;
@@ -265,5 +269,9 @@
 		public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 			return new AssociationOverrideInverseJoinColumnValidator(override, column, owner, textRangeResolver, new JoinTableTableDescriptionProvider());
 		}
+
+		public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) {
+			return new AssociationOverrideJoinTableValidator(override, (JoinTable) table, textRangeResolver);
+		}
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinTable.java
index 639af17..ec1a5b1 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinTable.java
@@ -29,7 +29,6 @@
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.context.NamedColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.resource.java.NullJoinColumnAnnotation;
-import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.resource.java.JoinColumnAnnotation;
 import org.eclipse.jpt.core.resource.java.JoinTableAnnotation;
 import org.eclipse.jpt.core.utility.TextRange;
@@ -57,8 +56,8 @@
 	protected final JavaJoinColumn.Owner inverseJoinColumnOwner;
 
 
-	public GenericJavaJoinTable(JavaJoinTableJoiningStrategy parent) {
-		super(parent);
+	public GenericJavaJoinTable(JavaJoinTableJoiningStrategy parent, Owner owner) {
+		super(parent, owner);
 		this.inverseJoinColumnOwner = this.buildInverseJoinColumnOwner();
 	}
 
@@ -309,26 +308,10 @@
 		this.validateJoinColumns(this.inverseJoinColumns(), messages, reporter, astRoot);
 	}
 
-	@Override
-	protected boolean shouldValidateAgainstDatabase() {
+	public boolean shouldValidateAgainstDatabase() {
 		return getParent().shouldValidateAgainstDatabase();
 	}
 
-	@Override
-	protected String getUnresolvedCatalogMessageId() {
-		return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_CATALOG;
-	}
-	
-	@Override
-	protected String getUnresolvedSchemaMessageId() {
-		return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_SCHEMA;
-	}
-	
-	@Override
-	protected String getUnresolvedNameMessageId() {
-		return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_NAME;
-	}
-
 
 	// ********** join column owner adapters **********
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaReferenceTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaReferenceTable.java
index 51691fe..f19ed56 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaReferenceTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaReferenceTable.java
@@ -22,7 +22,6 @@
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.context.java.AbstractJavaTable;
 import org.eclipse.jpt.core.internal.resource.java.NullJoinColumnAnnotation;
-import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
 import org.eclipse.jpt.core.resource.java.JoinColumnAnnotation;
 import org.eclipse.jpt.core.resource.java.ReferenceTableAnnotation;
 import org.eclipse.jpt.utility.Filter;
@@ -47,8 +46,8 @@
 	protected final JavaJoinColumn.Owner joinColumnOwner;
 
 
-	protected GenericJavaReferenceTable(JavaJpaContextNode parent) {
-		super(parent);
+	protected GenericJavaReferenceTable(JavaJpaContextNode parent, Owner owner) {
+		super(parent, owner);
 		this.joinColumnOwner = this.buildJoinColumnOwner();
 	}
 
@@ -288,11 +287,8 @@
 
 	@Override
 	public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
-		super.validate(messages, reporter, astRoot);
-		boolean continueValidating = true;
-		if (this.shouldValidateAgainstDatabase()) {
-			continueValidating = this.validateAgainstDatabase(messages, reporter, astRoot);
-		}
+		boolean continueValidating = this.buildTableValidator(astRoot).validate(messages, reporter);
+
 		//join column validation will handle the check for whether to validate against the database
 		//some validation messages are not database specific. If the database validation for the
 		//table fails we will stop there and not validate the join columns at all
@@ -300,51 +296,6 @@
 			this.validateJoinColumns(messages, reporter, astRoot);
 		}
 	}
-	
-	protected abstract boolean shouldValidateAgainstDatabase();
-
-	protected boolean validateAgainstDatabase(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
-		if ( ! this.hasResolvedCatalog()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					this.getUnresolvedCatalogMessageId(),
-					new String[] {this.getCatalog(), this.getName()}, 
-					this, 
-					this.getCatalogTextRange(astRoot)
-				)
-			);
-			return false;
-		}
-
-		if ( ! this.hasResolvedSchema()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					this.getUnresolvedSchemaMessageId(),
-					new String[] {this.getSchema(), this.getName()}, 
-					this, 
-					this.getSchemaTextRange(astRoot)
-				)
-			);
-			return false;
-		}
-
-		if ( ! this.isResolved()) {
-			if (getName() != null) { //if name is null, the validation will be handled elsewhere, such as the target entity is not defined
-				messages.add(
-					DefaultJpaValidationMessages.buildMessage(
-							IMessage.HIGH_SEVERITY,
-							this.getUnresolvedNameMessageId(),
-							new String[] {this.getName()}, 
-							this, 
-							this.getNameTextRange(astRoot))
-					);
-			}
-			return false;
-		}
-		return true;
-	}
 
 	protected void validateJoinColumns(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
 		this.validateJoinColumns(this.joinColumns(), messages, reporter, astRoot);		
@@ -355,11 +306,5 @@
 			joinColumns.next().validate(messages, reporter, astRoot);
 		}
 	}
-
-	protected abstract String getUnresolvedCatalogMessageId();
-	
-	protected abstract String getUnresolvedSchemaMessageId();
-	
-	protected abstract String getUnresolvedNameMessageId();
 }
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java
index 972fa51..829af1c 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java
@@ -29,8 +29,6 @@
 import org.eclipse.jpt.core.internal.context.java.AbstractJavaTable;
 import org.eclipse.jpt.core.internal.jpa1.context.SecondaryTablePrimaryKeyJoinColumnValidator;
 import org.eclipse.jpt.core.internal.resource.java.NullPrimaryKeyJoinColumnAnnotation;
-import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
-import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.resource.java.PrimaryKeyJoinColumnAnnotation;
 import org.eclipse.jpt.core.resource.java.SecondaryTableAnnotation;
 import org.eclipse.jpt.core.utility.TextRange;
@@ -57,8 +55,8 @@
 
 	protected SecondaryTableAnnotation resourceSecondaryTable;
 	
-	public GenericJavaSecondaryTable(JavaEntity parent) {
-		super(parent);
+	public GenericJavaSecondaryTable(JavaEntity parent, Owner owner) {
+		super(parent, owner);
 		this.specifiedPrimaryKeyJoinColumns = new ArrayList<JavaPrimaryKeyJoinColumn>();
 		this.primaryKeyJoinColumnOwner = this.buildPrimaryKeyJoinColumnOwner();
 	}
@@ -287,11 +285,8 @@
 
 	@Override
 	public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
-		super.validate(messages, reporter, astRoot);
-		boolean continueValidating = true;
-		if (this.connectionProfileIsActive()) {
-			continueValidating = this.validateAgainstDatabase(messages, astRoot);
-		}
+		boolean continueValidating = this.buildTableValidator(astRoot).validate(messages, reporter);
+
 		//join column validation will handle the check for whether to validate against the database
 		//some validation messages are not database specific. If the database validation for the
 		//table fails we will stop there and not validate the join columns at all
@@ -302,46 +297,8 @@
 		}
 	}
 
-	protected boolean validateAgainstDatabase(List<IMessage> messages, CompilationUnit astRoot) {
-		if ( ! this.hasResolvedCatalog()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_CATALOG,
-					new String[] {this.getCatalog(), this.getName()}, 
-					this, 
-					this.getCatalogTextRange(astRoot)
-				)
-			);
-			return false;
-		}
-		
-		if ( ! this.hasResolvedSchema()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_SCHEMA,
-					new String[] {this.getSchema(), this.getName()}, 
-					this, 
-					this.getSchemaTextRange(astRoot)
-				)
-			);
-			return false;
-		}
-		
-		if ( ! this.isResolved()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_NAME,
-					new String[] {this.getName()}, 
-					this, 
-					this.getNameTextRange(astRoot)
-				)
-			);
-			return false;
-		}
-		return true;
+	public boolean shouldValidateAgainstDatabase() {
+		return this.connectionProfileIsActive();
 	}
 
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTable.java
index ec81d5f..e573b60 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTable.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2009 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2010 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.
@@ -9,17 +9,11 @@
  ******************************************************************************/
 package org.eclipse.jpt.core.internal.jpa1.context.java;
 
-import java.util.List;
-import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jpt.core.context.java.JavaEntity;
 import org.eclipse.jpt.core.context.java.JavaTable;
 import org.eclipse.jpt.core.internal.context.java.AbstractJavaTable;
-import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
-import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember;
 import org.eclipse.jpt.core.resource.java.TableAnnotation;
-import org.eclipse.wst.validation.internal.provisional.core.IMessage;
-import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 
 public class GenericJavaTable
 	extends AbstractJavaTable
@@ -27,8 +21,8 @@
 {
 	protected JavaResourcePersistentMember resourcePersistentMember;
 
-	public GenericJavaTable(JavaEntity parent) {
-		super(parent);
+	public GenericJavaTable(JavaEntity parent, Owner owner) {
+		super(parent, owner);
 	}
 	
 	public void initialize(JavaResourcePersistentMember pr) {
@@ -101,53 +95,8 @@
 
 
 	//******************* validation **********************
-	
-	@Override
-	public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
-		super.validate(messages, reporter, astRoot);
-		if (this.connectionProfileIsActive()) {
-			this.validateAgainstDatabase(messages, astRoot);
-		}
-	}
 
-	protected void validateAgainstDatabase(List<IMessage> messages, CompilationUnit astRoot) {
-		if ( ! this.hasResolvedCatalog()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.TABLE_UNRESOLVED_CATALOG,
-					new String[] {this.getCatalog(), this.getName()}, 
-					this, 
-					this.getCatalogTextRange(astRoot)
-				)
-			);
-			return;
-		}
-		
-		if ( ! this.hasResolvedSchema()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.TABLE_UNRESOLVED_SCHEMA,
-					new String[] {this.getSchema(), this.getName()}, 
-					this, 
-					this.getSchemaTextRange(astRoot)
-				)
-			);
-			return;
-		}
-		
-		if ( ! this.isResolved()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.TABLE_UNRESOLVED_NAME,
-					new String[] {this.getName()}, 
-					this, 
-					this.getNameTextRange(astRoot)
-				)
-			);
-		}
+	public boolean shouldValidateAgainstDatabase() {
+		return this.connectionProfileIsActive();
 	}
-
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java
index ad3ed8f..2f6de99 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java
@@ -21,6 +21,7 @@
 import org.eclipse.jpt.core.context.JoiningStrategy;
 import org.eclipse.jpt.core.context.RelationshipMapping;
 import org.eclipse.jpt.core.context.RelationshipReference;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.TypeMapping;
 import org.eclipse.jpt.core.context.XmlContextNode;
 import org.eclipse.jpt.core.context.orm.OrmAssociationOverride;
@@ -29,11 +30,11 @@
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
 import org.eclipse.jpt.core.internal.context.MappingTools;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode;
 import org.eclipse.jpt.core.resource.orm.OrmFactory;
 import org.eclipse.jpt.core.resource.orm.XmlAssociationOverride;
 import org.eclipse.jpt.core.utility.TextRange;
-import org.eclipse.jpt.db.Table;
 import org.eclipse.jpt.utility.internal.CollectionTools;
 import org.eclipse.jpt.utility.internal.iterators.CloneIterator;
 import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
@@ -355,7 +356,7 @@
 			return getOwner().getDefaultTableName();
 		}
 
-		public Table getDbTable(String tableName) {
+		public org.eclipse.jpt.db.Table getDbTable(String tableName) {
 			return getOwner().getDbTable(tableName);
 		}
 
@@ -370,5 +371,9 @@
 		public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 			return getOwner().buildJoinTableInverseJoinColumnValidator(override, column, owner, textRangeResolver);
 		}
+
+		public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) {
+			return getOwner().buildTableValidator(override, table, textRangeResolver);
+		}
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java
index dd043fe..05072fe 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java
@@ -18,10 +18,12 @@
 import org.eclipse.jpt.core.context.BaseColumn;
 import org.eclipse.jpt.core.context.BaseOverride;
 import org.eclipse.jpt.core.context.JoinColumn;
+import org.eclipse.jpt.core.context.JoinColumn.Owner;
+import org.eclipse.jpt.core.context.JoinTable;
 import org.eclipse.jpt.core.context.RelationshipMapping;
 import org.eclipse.jpt.core.context.RelationshipReference;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.TypeMapping;
-import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverride;
 import org.eclipse.jpt.core.context.orm.OrmAssociationOverrideContainer;
 import org.eclipse.jpt.core.context.orm.OrmAttributeMapping;
@@ -31,9 +33,11 @@
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
 import org.eclipse.jpt.core.internal.context.MappingTools;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.orm.AbstractOrmBaseEmbeddedMapping;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideInverseJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinColumnValidator;
+import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinTableValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.EntityTableDescriptionProvider;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinTableTableDescriptionProvider;
 import org.eclipse.jpt.core.jpa2.context.java.JavaEmbeddedMapping2_0;
@@ -286,5 +290,9 @@
 		public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 			return new AssociationOverrideInverseJoinColumnValidator(getPersistentAttribute(), override, column, owner, textRangeResolver, new JoinTableTableDescriptionProvider());
 		}
+
+		public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) {
+			return new AssociationOverrideJoinTableValidator(getPersistentAttribute(), override, (JoinTable) table, textRangeResolver);
+		}
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinTable.java
index ce4faf9..85fafb8 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinTable.java
@@ -29,7 +29,6 @@
 import org.eclipse.jpt.core.internal.context.JptValidator;
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.context.NamedColumnTextRangeResolver;
-import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.resource.orm.AbstractXmlReferenceTable;
 import org.eclipse.jpt.core.resource.orm.OrmFactory;
 import org.eclipse.jpt.core.resource.orm.XmlJoinColumn;
@@ -59,8 +58,8 @@
 	protected final OrmJoinColumn.Owner inverseJoinColumnOwner;
 
 
-	public GenericOrmJoinTable(OrmJoinTableJoiningStrategy parent, XmlJoinTable resourceJoinTable) {
-		super(parent);
+	public GenericOrmJoinTable(OrmJoinTableJoiningStrategy parent, Owner owner, XmlJoinTable resourceJoinTable) {
+		super(parent, owner);
 		this.inverseJoinColumnOwner = this.buildInverseJoinColumnOwner();
 		this.initialize(resourceJoinTable);
 	}
@@ -313,40 +312,10 @@
 		this.validateJoinColumns(this.inverseJoinColumns(), messages, reporter);
 	}
 
-	@Override
-	protected boolean shouldValidateAgainstDatabase() {
+	public boolean shouldValidateAgainstDatabase() {
 		return getParent().shouldValidateAgainstDatabase();
 	}
 
-	@Override
-	protected String getUnresolvedCatalogMessageId() {
-		return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_CATALOG;
-	}
-
-	@Override
-	protected String getUnresolvedNameMessageId() {
-		return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_NAME;
-	}
-
-	@Override
-	protected String getUnresolvedSchemaMessageId() {
-		return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_SCHEMA;
-	}
-
-	@Override
-	protected String getVirtualAttributeUnresolvedCatalogMessageId() {
-		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_CATALOG;
-	}
-
-	@Override
-	protected String getVirtualAttributeUnresolvedNameMessageId() {
-		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_NAME;
-	}
-
-	@Override
-	protected String getVirtualAttributeUnresolvedSchemaMessageId() {
-		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_SCHEMA;
-	}
 
 	// ********** join column owner adapters **********
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmReferenceTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmReferenceTable.java
index 03a9825..df5aefc 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmReferenceTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmReferenceTable.java
@@ -15,14 +15,12 @@
 import java.util.Vector;
 
 import org.eclipse.jpt.core.context.JoinColumn;
-import org.eclipse.jpt.core.context.PersistentAttribute;
 import org.eclipse.jpt.core.context.ReferenceTable;
 import org.eclipse.jpt.core.context.XmlContextNode;
 import org.eclipse.jpt.core.context.orm.OrmJoinColumn;
 import org.eclipse.jpt.core.context.orm.OrmReferenceTable;
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.context.orm.AbstractOrmTable;
-import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
 import org.eclipse.jpt.core.resource.orm.AbstractXmlReferenceTable;
 import org.eclipse.jpt.core.resource.orm.OrmFactory;
 import org.eclipse.jpt.core.resource.orm.XmlJoinColumn;
@@ -45,8 +43,8 @@
 	protected final OrmJoinColumn.Owner joinColumnOwner;
 
 
-	protected GenericOrmReferenceTable(XmlContextNode parent) {
-		super(parent);
+	protected GenericOrmReferenceTable(XmlContextNode parent, Owner owner) {
+		super(parent, owner);
 		this.joinColumnOwner = this.buildJoinColumnOwner();
 	}
 
@@ -281,11 +279,8 @@
 
 	@Override
 	public void validate(List<IMessage> messages, IReporter reporter) {
-		super.validate(messages, reporter);
-		boolean continueValidating = true;
-		if (this.shouldValidateAgainstDatabase()) {
-			continueValidating = this.validateAgainstDatabase(messages, reporter);
-		}
+		boolean continueValidating = this.buildTableValidator().validate(messages, reporter);
+
 		//join column validation will handle the check for whether to validate against the database
 		//some validation messages are not database specific. If the database validation for the
 		//table fails we will stop there and not validate the join columns at all
@@ -293,87 +288,6 @@
 			this.validateJoinColumns(messages, reporter);
 		}
 	}
-	protected abstract boolean shouldValidateAgainstDatabase();
-	
-	protected boolean validateAgainstDatabase(List<IMessage> messages, IReporter reporter) {
-		PersistentAttribute persistentAttribute = this.getPersistentAttribute();
-		if ( ! this.hasResolvedCatalog()) {
-			if (persistentAttribute.isVirtual()) {
-				messages.add(
-					DefaultJpaValidationMessages.buildMessage(
-						IMessage.HIGH_SEVERITY,
-						getVirtualAttributeUnresolvedCatalogMessageId(),
-						new String[] {persistentAttribute.getName(), this.getCatalog(), this.getName()}, 
-						this,
-						this.getCatalogTextRange()
-					)
-				);
-			} else {
-				messages.add(
-					DefaultJpaValidationMessages.buildMessage(
-						IMessage.HIGH_SEVERITY,
-						getUnresolvedCatalogMessageId(),
-						new String[] {this.getCatalog(), this.getName()}, 
-						this,
-						this.getCatalogTextRange()
-					)
-				);
-			}
-			return false;
-		}
-
-		if ( ! this.hasResolvedSchema()) {
-			if (persistentAttribute.isVirtual()) {
-				messages.add(
-					DefaultJpaValidationMessages.buildMessage(
-						IMessage.HIGH_SEVERITY,
-						getVirtualAttributeUnresolvedSchemaMessageId(),
-						new String[] {persistentAttribute.getName(), this.getSchema(), this.getName()}, 
-						this,
-						this.getSchemaTextRange()
-					)
-				);
-			} else {
-				messages.add(
-					DefaultJpaValidationMessages.buildMessage(
-						IMessage.HIGH_SEVERITY,
-						getUnresolvedSchemaMessageId(),
-						new String[] {this.getSchema(), this.getName()}, 
-						this,
-						this.getSchemaTextRange()
-					)
-				);
-			}
-			return false;
-		}
-		if ( ! this.isResolved()) {
-			if (getName() != null) { //if name is null, the validation will be handled elsewhere, such as the target entity is not defined
-				if (persistentAttribute.isVirtual()) {
-					messages.add(
-						DefaultJpaValidationMessages.buildMessage(
-							IMessage.HIGH_SEVERITY,
-							getVirtualAttributeUnresolvedNameMessageId(),
-							new String[] {persistentAttribute.getName(), this.getName()}, 
-							this,
-							this.getNameTextRange()
-						)
-					);
-				} 
-				else {
-					messages.add(
-						DefaultJpaValidationMessages.buildMessage(
-								IMessage.HIGH_SEVERITY,
-								getUnresolvedNameMessageId(),
-								new String[] {this.getName()}, 
-								this, 
-								this.getNameTextRange())
-						);
-				}
-			}
-			return false;
-		}
-		return true;
-	}
 
 	protected void validateJoinColumns(List<IMessage> messages, IReporter reporter) {
 		this.validateJoinColumns(this.joinColumns(), messages, reporter);		
@@ -384,17 +298,4 @@
 			joinColumns.next().validate(messages, reporter);
 		}
 	}
-	
-	protected abstract String getUnresolvedCatalogMessageId();
-	
-	protected abstract String getUnresolvedSchemaMessageId();
-	
-	protected abstract String getUnresolvedNameMessageId();
-	
-	protected abstract String getVirtualAttributeUnresolvedCatalogMessageId();
-	
-	protected abstract String getVirtualAttributeUnresolvedSchemaMessageId();
-	
-	protected abstract String getVirtualAttributeUnresolvedNameMessageId();
-
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java
index 01c4ee6..a51ccef 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java
@@ -28,8 +28,6 @@
 import org.eclipse.jpt.core.internal.context.NamedColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.orm.AbstractOrmTable;
 import org.eclipse.jpt.core.internal.jpa1.context.SecondaryTablePrimaryKeyJoinColumnValidator;
-import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
-import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.resource.orm.OrmFactory;
 import org.eclipse.jpt.core.resource.orm.XmlPrimaryKeyJoinColumn;
 import org.eclipse.jpt.core.resource.orm.XmlSecondaryTable;
@@ -59,8 +57,8 @@
 	protected final OrmBaseJoinColumn.Owner joinColumnOwner;
 
 
-	public GenericOrmSecondaryTable(OrmEntity parent, XmlSecondaryTable xmlSecondaryTable) {
-		super(parent);
+	public GenericOrmSecondaryTable(OrmEntity parent, Owner owner, XmlSecondaryTable xmlSecondaryTable) {
+		super(parent, owner);
 		this.joinColumnOwner = this.buildJoinColumnOwner();
 		this.initialize(xmlSecondaryTable);
 	}
@@ -297,55 +295,21 @@
 
 	// ********** validation **********
 
-	@Override
-	public void validate(List<IMessage> messages, IReporter reporter) {
-		super.validate(messages, reporter);
-		if (this.connectionProfileIsActive()) {
-			this.validateAgainstDatabase(messages);
-		}
-		for (Iterator<OrmPrimaryKeyJoinColumn> stream = this.primaryKeyJoinColumns(); stream.hasNext(); ) {
-			stream.next().validate(messages, reporter);
-		}
+	public boolean shouldValidateAgainstDatabase() {
+		return this.connectionProfileIsActive();
 	}
 
-	protected void validateAgainstDatabase(List<IMessage> messages) {
-		if ( ! this.hasResolvedCatalog()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_CATALOG,
-					new String[] {this.getCatalog(), this.getName()}, 
-					this,
-					this.getCatalogTextRange()
-				)
-			);
-			return;
-		}
-		
-		if ( ! this.hasResolvedSchema()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_SCHEMA,
-					new String[] {this.getSchema(), this.getName()}, 
-					this,
-					this.getSchemaTextRange()
-				)
-			);
-			return;
-		}
-		
-		if ( ! this.isResolved()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_NAME,
-					new String[] {this.getName()}, 
-					this, 
-					this.getNameTextRange()
-				)
-			);
-			return;
+	@Override
+	public void validate(List<IMessage> messages, IReporter reporter) {
+		boolean continueValidating = this.buildTableValidator().validate(messages, reporter);
+
+		//join column validation will handle the check for whether to validate against the database
+		//some validation messages are not database specific. If the database validation for the
+		//table fails we will stop there and not validate the join columns at all
+		if (continueValidating) {
+			for (Iterator<OrmPrimaryKeyJoinColumn> stream = this.primaryKeyJoinColumns(); stream.hasNext(); ) {
+				stream.next().validate(messages, reporter);
+			}
 		}
 	}
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTable.java
index 63fcf35..95ce49a 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTable.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTable.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2009 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2010 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.
@@ -9,17 +9,12 @@
  ******************************************************************************/
 package org.eclipse.jpt.core.internal.jpa1.context.orm;
 
-import java.util.List;
 import org.eclipse.jpt.core.context.orm.OrmEntity;
 import org.eclipse.jpt.core.context.orm.OrmTable;
 import org.eclipse.jpt.core.internal.context.orm.AbstractOrmTable;
-import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
-import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.resource.orm.OrmFactory;
 import org.eclipse.jpt.core.resource.orm.XmlEntity;
 import org.eclipse.jpt.core.resource.orm.XmlTable;
-import org.eclipse.wst.validation.internal.provisional.core.IMessage;
-import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 
 /**
  * 
@@ -30,8 +25,8 @@
 {
 	protected XmlEntity resourceEntity;
 	
-	public GenericOrmTable(OrmEntity parent) {
-		super(parent);
+	public GenericOrmTable(OrmEntity parent, Owner owner) {
+		super(parent, owner);
 	}
 
 	public OrmEntity getOrmEntity() {
@@ -79,56 +74,11 @@
 	protected String buildDefaultCatalog() {
 		return this.getOrmEntity().getDefaultCatalog();
 	}
-	
+
+
 	//*********** Validation *******************************
 	
-	@Override
-	public void validate(List<IMessage> messages, IReporter reporter) {
-		super.validate(messages, reporter);
-		if (this.connectionProfileIsActive()) {
-			this.validateAgainstDatabase(messages);
-		}
+	public boolean shouldValidateAgainstDatabase() {
+		return this.connectionProfileIsActive();
 	}
-
-	protected void validateAgainstDatabase(List<IMessage> messages) {
-		if ( ! this.hasResolvedCatalog()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.TABLE_UNRESOLVED_CATALOG,
-					new String[] {this.getCatalog(), this.getName()}, 
-					this,
-					this.getCatalogTextRange()
-				)
-			);
-			return;
-		}
-		
-		if ( ! this.hasResolvedSchema()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.TABLE_UNRESOLVED_SCHEMA,
-					new String[] {this.getSchema(), this.getName()}, 
-					this,
-					this.getSchemaTextRange()
-				)
-			);
-			return;
-		}
-		
-		if ( ! this.isResolved()) {
-			messages.add(
-				DefaultJpaValidationMessages.buildMessage(
-					IMessage.HIGH_SEVERITY,
-					JpaValidationMessages.TABLE_UNRESOLVED_NAME,
-					new String[] {this.getName()}, 
-					this, 
-					this.getNameTextRange()
-				)
-			);
-			return;
-		}
-	}
-
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericJpaFactory2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericJpaFactory2_0.java
index 32c814c..b9ce8bf 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericJpaFactory2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericJpaFactory2_0.java
@@ -13,6 +13,7 @@
 import org.eclipse.jpt.core.JpaProject.Config;
 import org.eclipse.jpt.core.context.JoiningStrategy;
 import org.eclipse.jpt.core.context.PersistentType;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverride;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideRelationshipReference;
@@ -158,8 +159,8 @@
 	}
 	
 	@Override
-	public JavaCollectionTable2_0 buildJavaCollectionTable(JavaElementCollectionMapping2_0 parent) {
-		return new GenericJavaCollectionTable2_0(parent);
+	public JavaCollectionTable2_0 buildJavaCollectionTable(JavaElementCollectionMapping2_0 parent, Table.Owner owner) {
+		return new GenericJavaCollectionTable2_0(parent, owner);
 	}
 
 	@Override
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/CollectionTableValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/CollectionTableValidator.java
new file mode 100644
index 0000000..cdbe70b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/CollectionTableValidator.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.core.internal.jpa2.context;
+
+import org.eclipse.jpt.core.context.PersistentAttribute;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.core.internal.jpa1.context.AbstractTableValidator;
+import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.core.jpa2.context.CollectionTable2_0;
+
+public class CollectionTableValidator extends AbstractTableValidator
+{
+	public CollectionTableValidator(CollectionTable2_0 table, TableTextRangeResolver textRangeResolver) {
+		super(table, textRangeResolver);
+	}
+
+	public CollectionTableValidator(PersistentAttribute persistentAttribute, CollectionTable2_0 table, TableTextRangeResolver textRangeResolver) {
+		super(persistentAttribute, table, textRangeResolver);
+	}
+
+	@Override
+	protected String getUnresolvedCatalogMessage() {
+		return JpaValidationMessages.COLLECTION_TABLE_UNRESOLVED_CATALOG;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedCatalogMessage() {
+		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_CATALOG;
+	}
+
+	@Override
+	protected String getUnresolvedSchemaMessage() {
+		return JpaValidationMessages.COLLECTION_TABLE_UNRESOLVED_SCHEMA;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedSchemaMessage() {
+		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_SCHEMA;
+	}
+
+	@Override
+	protected String getUnresolvedNameMessage() {
+		return JpaValidationMessages.COLLECTION_TABLE_UNRESOLVED_NAME;
+	}
+
+	@Override
+	protected String getVirtualAttributeUnresolvedNameMessage() {
+		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_NAME;
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/AbstractJavaElementCollectionMapping2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/AbstractJavaElementCollectionMapping2_0.java
index 86fcf31..7728045 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/AbstractJavaElementCollectionMapping2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/AbstractJavaElementCollectionMapping2_0.java
@@ -27,11 +27,12 @@
 import org.eclipse.jpt.core.context.FetchType;
 import org.eclipse.jpt.core.context.Fetchable;
 import org.eclipse.jpt.core.context.JoinColumn;
+import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.NamedColumn;
 import org.eclipse.jpt.core.context.PersistentType;
 import org.eclipse.jpt.core.context.RelationshipReference;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.TypeMapping;
-import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer;
 import org.eclipse.jpt.core.context.java.JavaAttributeOverrideContainer;
 import org.eclipse.jpt.core.context.java.JavaBaseColumn;
@@ -44,6 +45,7 @@
 import org.eclipse.jpt.core.internal.context.JptValidator;
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.java.AbstractJavaAttributeMapping;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.AttributeOverrideColumnValidator;
@@ -51,10 +53,12 @@
 import org.eclipse.jpt.core.internal.jpa1.context.MapKeyAttributeOverrideColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.MapKeyColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.NamedColumnValidator;
+import org.eclipse.jpt.core.internal.jpa2.context.CollectionTableValidator;
 import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
 import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.jpa2.JpaFactory2_0;
 import org.eclipse.jpt.core.jpa2.MappingKeys2_0;
+import org.eclipse.jpt.core.jpa2.context.CollectionTable2_0;
 import org.eclipse.jpt.core.jpa2.context.MetamodelField;
 import org.eclipse.jpt.core.jpa2.context.Orderable2_0;
 import org.eclipse.jpt.core.jpa2.context.java.JavaCollectionTable2_0;
@@ -72,7 +76,6 @@
 import org.eclipse.jpt.core.resource.java.MapKeyAnnotation;
 import org.eclipse.jpt.core.resource.java.TemporalAnnotation;
 import org.eclipse.jpt.core.utility.TextRange;
-import org.eclipse.jpt.db.Table;
 import org.eclipse.jpt.utility.Filter;
 import org.eclipse.jpt.utility.internal.CollectionTools;
 import org.eclipse.jpt.utility.internal.StringTools;
@@ -137,7 +140,7 @@
 	protected AbstractJavaElementCollectionMapping2_0(JavaPersistentAttribute parent) {
 		super(parent);
 		this.orderable = getJpaFactory().buildJavaOrderable(this, buildOrderableOwner());
-		this.collectionTable = getJpaFactory().buildJavaCollectionTable(this);
+		this.collectionTable = getJpaFactory().buildJavaCollectionTable(this, new CollectionTableOwner());
 		this.valueColumn = getJpaFactory().buildJavaColumn(parent, new ValueColumnOwner());
 		this.nullConverter = getJpaFactory().buildJavaNullConverter(this);
 		this.valueConverter = this.nullConverter;
@@ -539,7 +542,7 @@
 			public String getTableName() {
 				return getCollectionTable().getName();
 			}
-			public Table getDbTable(String tableName) {
+			public org.eclipse.jpt.db.Table getDbTable(String tableName) {
 				return getCollectionTable().getDbTable();
 			}
 		};
@@ -1221,6 +1224,12 @@
 	}
 
 
+	protected class CollectionTableOwner implements Table.Owner {
+		public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+			return new CollectionTableValidator((CollectionTable2_0) table, textRangeResolver);
+		}
+	}
+
 	protected abstract class ColumnOwner implements JavaBaseColumn.Owner {
 		public String getDefaultTableName() {
 			return getCollectionTable().getName();
@@ -1230,7 +1239,7 @@
 			return AbstractJavaElementCollectionMapping2_0.this.getTypeMapping();
 		}
 		
-		public Table getDbTable(String tableName) {
+		public org.eclipse.jpt.db.Table getDbTable(String tableName) {
 			if (getCollectionTable().getName() != null && getCollectionTable().getName().equals(tableName)) {
 				return AbstractJavaElementCollectionMapping2_0.this.getCollectionTable().getDbTable();
 			}
@@ -1350,11 +1359,15 @@
 		}
 
 		public JptValidator buildJoinTableJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
-			throw new UnsupportedOperationException("An element collection with containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
+			throw new UnsupportedOperationException("An element collection containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
 		}
 
 		public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
-			throw new UnsupportedOperationException("An element collection with containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
+			throw new UnsupportedOperationException("An element collection containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
+		}
+
+		public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) {
+			throw new UnsupportedOperationException("An element collection containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
 		}
 	}
 	
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaCollectionTable2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaCollectionTable2_0.java
index 5c3a173..99e5b28 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaCollectionTable2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaCollectionTable2_0.java
@@ -25,7 +25,6 @@
 import org.eclipse.jpt.core.internal.jpa1.context.CollectionTableTableDescriptionProvider;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.java.GenericJavaReferenceTable;
-import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.jpa2.context.java.JavaCollectionTable2_0;
 import org.eclipse.jpt.core.jpa2.context.java.JavaElementCollectionMapping2_0;
 import org.eclipse.jpt.core.jpa2.resource.java.CollectionTable2_0Annotation;
@@ -41,8 +40,8 @@
 	implements JavaCollectionTable2_0
 {
 
-	public GenericJavaCollectionTable2_0(JavaElementCollectionMapping2_0 parent) {
-		super(parent);
+	public GenericJavaCollectionTable2_0(JavaElementCollectionMapping2_0 parent, Owner owner) {
+		super(parent, owner);
 	}
 
 	@Override
@@ -88,26 +87,10 @@
 
 	// ********** validation **********
 
-	@Override
-	protected boolean shouldValidateAgainstDatabase() {
+	public boolean shouldValidateAgainstDatabase() {
 		return getParent().shouldValidateAgainstDatabase();
 	}
 
-	@Override
-	protected String getUnresolvedCatalogMessageId() {
-		return JpaValidationMessages.COLLECTION_TABLE_UNRESOLVED_CATALOG;
-	}
-	
-	@Override
-	protected String getUnresolvedSchemaMessageId() {
-		return JpaValidationMessages.COLLECTION_TABLE_UNRESOLVED_SCHEMA;
-	}
-	
-	@Override
-	protected String getUnresolvedNameMessageId() {
-		return JpaValidationMessages.COLLECTION_TABLE_UNRESOLVED_NAME;
-	}
-
 
 	// ********** join column owner adapter **********
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaJoinTableInAssociationOverrideJoiningStrategy2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaJoinTableInAssociationOverrideJoiningStrategy2_0.java
index d0206ce..2485182 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaJoinTableInAssociationOverrideJoiningStrategy2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaJoinTableInAssociationOverrideJoiningStrategy2_0.java
@@ -12,11 +12,15 @@
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jpt.core.context.JoinColumn;
 import org.eclipse.jpt.core.context.JoinColumn.Owner;
+import org.eclipse.jpt.core.context.JoinTable;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.java.AbstractJavaJoinTableJoiningStrategy;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideInverseJoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinColumnValidator;
+import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinTableValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinTableTableDescriptionProvider;
 import org.eclipse.jpt.core.jpa2.context.java.JavaAssociationOverrideRelationshipReference2_0;
 import org.eclipse.jpt.core.jpa2.context.java.JavaJoinTableInAssociationOverrideJoiningStrategy2_0;
@@ -33,7 +37,11 @@
 	public GenericJavaJoinTableInAssociationOverrideJoiningStrategy2_0(JavaAssociationOverrideRelationshipReference2_0 parent) {
 		super(parent);
 	}
-	
+
+	public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+		return new AssociationOverrideJoinTableValidator(getRelationshipReference().getAssociationOverride(), (JoinTable) table, textRangeResolver);
+	}
+
 	public boolean isOverridableAssociation() {
 		return false;
 	}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/AbstractOrmElementCollectionMapping2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/AbstractOrmElementCollectionMapping2_0.java
index c848fed..eea9553 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/AbstractOrmElementCollectionMapping2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/AbstractOrmElementCollectionMapping2_0.java
@@ -32,6 +32,7 @@
 import org.eclipse.jpt.core.context.NamedColumn;
 import org.eclipse.jpt.core.context.PersistentType;
 import org.eclipse.jpt.core.context.RelationshipReference;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.TypeMapping;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverride;
 import org.eclipse.jpt.core.context.java.JavaAttributeOverride;
@@ -48,6 +49,7 @@
 import org.eclipse.jpt.core.internal.context.JptValidator;
 import org.eclipse.jpt.core.internal.context.MappingTools;
 import org.eclipse.jpt.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.orm.AbstractOrmAttributeMapping;
 import org.eclipse.jpt.core.internal.context.orm.VirtualXmlAttributeOverrideColumn;
 import org.eclipse.jpt.core.internal.jpa1.context.AssociationOverrideJoinColumnValidator;
@@ -56,9 +58,11 @@
 import org.eclipse.jpt.core.internal.jpa1.context.MapKeyAttributeOverrideColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.MapKeyColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.NamedColumnValidator;
+import org.eclipse.jpt.core.internal.jpa2.context.CollectionTableValidator;
 import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
 import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.jpa2.MappingKeys2_0;
+import org.eclipse.jpt.core.jpa2.context.CollectionTable2_0;
 import org.eclipse.jpt.core.jpa2.context.MetamodelField;
 import org.eclipse.jpt.core.jpa2.context.Orderable2_0;
 import org.eclipse.jpt.core.jpa2.context.PersistentAttribute2_0;
@@ -77,7 +81,6 @@
 import org.eclipse.jpt.core.resource.orm.XmlColumn;
 import org.eclipse.jpt.core.resource.orm.XmlElementCollection;
 import org.eclipse.jpt.core.utility.TextRange;
-import org.eclipse.jpt.db.Table;
 import org.eclipse.jpt.utility.internal.CollectionTools;
 import org.eclipse.jpt.utility.internal.StringTools;
 import org.eclipse.jpt.utility.internal.Transformer;
@@ -145,7 +148,7 @@
 		this.defaultTargetClass = buildDefaultTargetClass();
 		this.resolvedTargetType = this.resolveTargetType();
 		this.resolvedTargetEmbeddable = resolveTargetEmbeddable();
-		this.collectionTable = getXmlContextNodeFactory().buildOrmCollectionTable(this, getResourceCollectionTable());
+		this.collectionTable = getXmlContextNodeFactory().buildOrmCollectionTable(this, new CollectionTableOwner(), getResourceCollectionTable());
 		this.valueType = this.buildValueType();
 		this.valueColumn = getXmlContextNodeFactory().buildOrmColumn(this, new ValueColumnOwner());
 		this.nullValueConverter = this.getXmlContextNodeFactory().buildOrmNullConverter(this);
@@ -492,7 +495,7 @@
 			public String getTableName() {
 				return getCollectionTable().getName();
 			}
-			public Table getDbTable(String tableName) {
+			public org.eclipse.jpt.db.Table getDbTable(String tableName) {
 				return getCollectionTable().getDbTable();
 			}
 		};
@@ -1295,6 +1298,12 @@
 		return this.resourceAttributeMapping.getTargetClassTextRange();
 	}
 
+	protected class CollectionTableOwner implements Table.Owner {
+		public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+			return new CollectionTableValidator(getPersistentAttribute(), (CollectionTable2_0) table, textRangeResolver);
+		}
+	}
+
 	protected abstract class ColumnOwner implements OrmColumn.Owner {		
 		public String getDefaultTableName() {
 			return getCollectionTable().getName();
@@ -1304,7 +1313,7 @@
 			return AbstractOrmElementCollectionMapping2_0.this.getTypeMapping();
 		}
 		
-		public Table getDbTable(String tableName) {
+		public org.eclipse.jpt.db.Table getDbTable(String tableName) {
 			if (getCollectionTable().getName().equals(tableName)) {
 				return AbstractOrmElementCollectionMapping2_0.this.getCollectionTable().getDbTable();
 			}
@@ -1434,11 +1443,15 @@
 		}
 
 		public JptValidator buildJoinTableJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
-			throw new UnsupportedOperationException("An element collection with containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
+			throw new UnsupportedOperationException("An element collection containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
 		}
 
 		public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
-			throw new UnsupportedOperationException("An element collection with containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
+			throw new UnsupportedOperationException("An element collection containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
+		}
+
+		public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) {
+			throw new UnsupportedOperationException("An element collection containing a nested relationship mapping using a JoinTable is not supported"); //$NON-NLS-1$
 		}
 
 		public TextRange getValidationTextRange() {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmAssociationOverrideRelationshipReference2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmAssociationOverrideRelationshipReference2_0.java
index e0d2bd4..5bec62c 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmAssociationOverrideRelationshipReference2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmAssociationOverrideRelationshipReference2_0.java
@@ -13,10 +13,12 @@
 import org.eclipse.jpt.core.context.AssociationOverrideRelationshipReference;
 import org.eclipse.jpt.core.context.JoinColumn;
 import org.eclipse.jpt.core.context.JoiningStrategy;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.orm.OrmAssociationOverride;
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.orm.AbstractOrmAssociationOverrideRelationshipReference;
 import org.eclipse.jpt.core.jpa2.context.AssociationOverrideRelationshipReference2_0;
 import org.eclipse.jpt.core.jpa2.context.orm.OrmAssociationOverrideRelationshipReference2_0;
@@ -119,4 +121,8 @@
 	public JptValidator buildJoinTableInverseJoinColumnValidator(JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 		return getAssociationOverride().getOwner().buildJoinTableInverseJoinColumnValidator(getAssociationOverride(), column, owner, textRangeResolver);
 	}
+
+	public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+		return getAssociationOverride().getOwner().buildTableValidator(getAssociationOverride(), table, textRangeResolver);
+	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmCollectionTable2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmCollectionTable2_0.java
index 2fbd152..a95750a 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmCollectionTable2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmCollectionTable2_0.java
@@ -24,7 +24,6 @@
 import org.eclipse.jpt.core.internal.jpa1.context.CollectionTableTableDescriptionProvider;
 import org.eclipse.jpt.core.internal.jpa1.context.JoinColumnValidator;
 import org.eclipse.jpt.core.internal.jpa1.context.orm.GenericOrmReferenceTable;
-import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
 import org.eclipse.jpt.core.jpa2.context.CollectionTable2_0;
 import org.eclipse.jpt.core.jpa2.context.orm.OrmCollectionTable2_0;
 import org.eclipse.jpt.core.jpa2.context.orm.OrmElementCollectionMapping2_0;
@@ -41,8 +40,8 @@
 	implements OrmCollectionTable2_0
 {
 
-	public GenericOrmCollectionTable2_0(OrmElementCollectionMapping2_0 parent, XmlCollectionTable xmlCollectionTable) {
-		super(parent);
+	public GenericOrmCollectionTable2_0(OrmElementCollectionMapping2_0 parent, Owner owner, XmlCollectionTable xmlCollectionTable) {
+		super(parent, owner);
 		this.initialize(xmlCollectionTable);
 	}
 
@@ -91,41 +90,10 @@
 
 	// ********** validation **********
 
-	@Override
-	protected boolean shouldValidateAgainstDatabase() {
+	public boolean shouldValidateAgainstDatabase() {
 		return getParent().shouldValidateAgainstDatabase();
 	}
 
-	@Override
-	protected String getUnresolvedCatalogMessageId() {
-		return JpaValidationMessages.COLLECTION_TABLE_UNRESOLVED_CATALOG;
-	}
-
-	@Override
-	protected String getUnresolvedNameMessageId() {
-		return JpaValidationMessages.COLLECTION_TABLE_UNRESOLVED_NAME;
-	}
-
-	@Override
-	protected String getUnresolvedSchemaMessageId() {
-		return JpaValidationMessages.COLLECTION_TABLE_UNRESOLVED_SCHEMA;
-	}
-
-	@Override
-	protected String getVirtualAttributeUnresolvedCatalogMessageId() {
-		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_CATALOG;
-	}
-
-	@Override
-	protected String getVirtualAttributeUnresolvedNameMessageId() {
-		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_NAME;
-	}
-
-	@Override
-	protected String getVirtualAttributeUnresolvedSchemaMessageId() {
-		return JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_SCHEMA;
-	}
-
 
 	// ********** join column owner adapters **********
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmJoinTableInAssociationOverrideJoiningStrategy2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmJoinTableInAssociationOverrideJoiningStrategy2_0.java
index d41e98c..efb52a0 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmJoinTableInAssociationOverrideJoiningStrategy2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmJoinTableInAssociationOverrideJoiningStrategy2_0.java
@@ -10,8 +10,10 @@
 package org.eclipse.jpt.core.internal.jpa2.context.orm;
 
 import org.eclipse.jpt.core.context.JoinColumn;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.orm.AbstractOrmJoinTableJoiningStrategy;
 import org.eclipse.jpt.core.jpa2.context.orm.OrmAssociationOverrideRelationshipReference2_0;
 import org.eclipse.jpt.core.jpa2.context.orm.OrmJoinTableInAssociationOverrideJoiningStrategy2_0;
@@ -81,4 +83,8 @@
 	public JptValidator buildJoinTableInverseJoinColumnValidator(JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
 		return getRelationshipReference().buildJoinTableInverseJoinColumnValidator(column, owner, textRangeResolver);
 	}
+
+	public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) {
+		return getRelationshipReference().buildTableValidator(table, textRangeResolver);
+	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmXml2_0ContextNodeFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmXml2_0ContextNodeFactory.java
index b8abde8..176a0cc 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmXml2_0ContextNodeFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/orm/GenericOrmXml2_0ContextNodeFactory.java
@@ -10,6 +10,7 @@
 package org.eclipse.jpt.core.internal.jpa2.context.orm;
 
 import org.eclipse.jpt.core.context.JoiningStrategy;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.XmlContextNode;
 import org.eclipse.jpt.core.context.java.JavaAttributeMapping;
 import org.eclipse.jpt.core.context.java.JavaBasicMapping;
@@ -131,8 +132,8 @@
 	}
 
 	@Override
-	public OrmCollectionTable2_0 buildOrmCollectionTable(OrmElementCollectionMapping2_0 parent, XmlCollectionTable resource) {
-		return new GenericOrmCollectionTable2_0(parent, resource);
+	public OrmCollectionTable2_0 buildOrmCollectionTable(OrmElementCollectionMapping2_0 parent, Table.Owner owner, XmlCollectionTable resource) {
+		return new GenericOrmCollectionTable2_0(parent, owner, resource);
 	}
 	
 	@Override
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidationMessages.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidationMessages.java
index 1afdb5c..4853501 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidationMessages.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidationMessages.java
@@ -138,6 +138,9 @@
 	public static final String VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME = "VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME";
 	public static final String VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS = "VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS";
 	public static final String VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS = "VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS";
+	public static final String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME = "VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME";
+	public static final String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG = "VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG";
+	public static final String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA = "VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA";
 	
 	public static final String GENERATED_VALUE_UNRESOLVED_GENERATOR = "GENERATED_VALUE_UNRESOLVED_GENERATOR";
 	public static final String PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME = "PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME";
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaFactory2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaFactory2_0.java
index 57bdc33..a331d9e 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaFactory2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaFactory2_0.java
@@ -12,6 +12,7 @@
 import org.eclipse.jpt.core.JpaDataSource;
 import org.eclipse.jpt.core.JpaFactory;
 import org.eclipse.jpt.core.context.Orderable;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer;
 import org.eclipse.jpt.core.context.java.JavaAttributeMapping;
 import org.eclipse.jpt.core.context.java.JavaBaseColumn;
@@ -78,7 +79,7 @@
 	
 	JavaOrderColumn2_0 buildJavaOrderColumn(JavaOrderable2_0 parent, JavaNamedColumn.Owner owner);
 	
-	JavaCollectionTable2_0 buildJavaCollectionTable(JavaElementCollectionMapping2_0 parent);
+	JavaCollectionTable2_0 buildJavaCollectionTable(JavaElementCollectionMapping2_0 parent, Table.Owner owner);
 
 	JavaColumn buildJavaMapKeyColumn(JavaJpaContextNode parent, JavaBaseColumn.Owner owner);
 	
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/orm/OrmAssociationOverrideRelationshipReference2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/orm/OrmAssociationOverrideRelationshipReference2_0.java
index 86d10ac..dbdb130 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/orm/OrmAssociationOverrideRelationshipReference2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/orm/OrmAssociationOverrideRelationshipReference2_0.java
@@ -14,12 +14,14 @@
 import org.eclipse.jpt.core.context.JoinColumnJoiningStrategy;
 import org.eclipse.jpt.core.context.RelationshipMapping;
 import org.eclipse.jpt.core.context.RelationshipReference;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.XmlContextNode;
 import org.eclipse.jpt.core.context.JoinColumn.Owner;
 import org.eclipse.jpt.core.context.orm.OrmAssociationOverride;
 import org.eclipse.jpt.core.context.orm.OrmAssociationOverrideRelationshipReference;
 import org.eclipse.jpt.core.internal.context.JoinColumnTextRangeResolver;
 import org.eclipse.jpt.core.internal.context.JptValidator;
+import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
 import org.eclipse.jpt.core.jpa2.context.AssociationOverrideRelationshipReference2_0;
 import org.eclipse.jpt.core.resource.orm.XmlAssociationOverride;
 
@@ -54,5 +56,7 @@
 	JptValidator buildJoinTableJoinColumnValidator(JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver);
 
 	JptValidator buildJoinTableInverseJoinColumnValidator(JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver);
-	
+
+	JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver);
+
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/orm/OrmXml2_0ContextNodeFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/orm/OrmXml2_0ContextNodeFactory.java
index bfc292a..4413df2 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/orm/OrmXml2_0ContextNodeFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/orm/OrmXml2_0ContextNodeFactory.java
@@ -10,6 +10,7 @@
 package org.eclipse.jpt.core.jpa2.context.orm;
 
 import org.eclipse.jpt.core.context.Orderable;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.orm.OrmAssociationOverrideContainer;
 import org.eclipse.jpt.core.context.orm.OrmAttributeMapping;
 import org.eclipse.jpt.core.context.orm.OrmNamedColumn;
@@ -60,5 +61,5 @@
 	
 	OrmOrderColumn2_0 buildOrmOrderColumn(OrmOrderable2_0 parent, OrmNamedColumn.Owner owner);
 	
-	OrmCollectionTable2_0 buildOrmCollectionTable(OrmElementCollectionMapping2_0 parent, XmlCollectionTable resource);
+	OrmCollectionTable2_0 buildOrmCollectionTable(OrmElementCollectionMapping2_0 parent, Table.Owner owner, XmlCollectionTable resource);
 }
diff --git a/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/EclipseLink2_0JpaFactory.java b/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/EclipseLink2_0JpaFactory.java
index 3a04b81..8bb0b0f 100644
--- a/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/EclipseLink2_0JpaFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/EclipseLink2_0JpaFactory.java
@@ -12,6 +12,7 @@
 import org.eclipse.jpt.core.JpaProject.Config;
 import org.eclipse.jpt.core.context.JoiningStrategy;
 import org.eclipse.jpt.core.context.PersistentType;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverride;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer;
 import org.eclipse.jpt.core.context.java.JavaAssociationOverrideRelationshipReference;
@@ -138,8 +139,8 @@
 	}
 
 	@Override
-	public JavaCollectionTable2_0 buildJavaCollectionTable(JavaElementCollectionMapping2_0 parent) {
-		return new GenericJavaCollectionTable2_0(parent);
+	public JavaCollectionTable2_0 buildJavaCollectionTable(JavaElementCollectionMapping2_0 parent, Table.Owner owner) {
+		return new GenericJavaCollectionTable2_0(parent, owner);
 	}
 
 	@Override
diff --git a/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/context/orm/EclipseLinkOrmXml2_0ContextNodeFactory.java b/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/context/orm/EclipseLinkOrmXml2_0ContextNodeFactory.java
index 789ca77..4719fe0 100644
--- a/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/context/orm/EclipseLinkOrmXml2_0ContextNodeFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/context/orm/EclipseLinkOrmXml2_0ContextNodeFactory.java
@@ -10,6 +10,7 @@
 package org.eclipse.jpt.eclipselink.core.internal.v2_0.context.orm;
 
 import org.eclipse.jpt.core.context.JoiningStrategy;
+import org.eclipse.jpt.core.context.Table;
 import org.eclipse.jpt.core.context.XmlContextNode;
 import org.eclipse.jpt.core.context.java.JavaAttributeMapping;
 import org.eclipse.jpt.core.context.java.JavaBasicMapping;
@@ -148,8 +149,8 @@
 	}
 
 	@Override
-	public OrmCollectionTable2_0 buildOrmCollectionTable(OrmElementCollectionMapping2_0 parent, XmlCollectionTable resource) {
-		return new GenericOrmCollectionTable2_0(parent, resource);
+	public OrmCollectionTable2_0 buildOrmCollectionTable(OrmElementCollectionMapping2_0 parent, Table.Owner owner, XmlCollectionTable resource) {
+		return new GenericOrmCollectionTable2_0(parent, owner, resource);
 	}
 
 	@Override
diff --git a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_validation_preferences.properties b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_validation_preferences.properties
index 21d7448..d9aa846 100644
--- a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_validation_preferences.properties
+++ b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_validation_preferences.properties
@@ -133,6 +133,9 @@
 VIRTUAL_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID=Implied map key attribute override table for column is not valid:
 VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_NAME=Implied attribute override column cannot be resolved:
 VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID=Implied attribute override table for column not valid:
+VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG=Implied association catalog cannot be resolved for join table:
+VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA=Implied association schema cannot be resolved join table:
+VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME=Implied association cannot be resolved join table:
 VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_TABLE_NOT_VALID=Implied association override table for join column is not valid:
 VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME=Implied association override join column cannot be resolved:
 VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME=Implied association override referenced column in join column cannot be resolved:
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/JptUiValidationPreferenceMessages.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/JptUiValidationPreferenceMessages.java
index ae99beb..e8242e6 100644
--- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/JptUiValidationPreferenceMessages.java
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/JptUiValidationPreferenceMessages.java
@@ -163,6 +163,9 @@
 	public static String VIRTUAL_ATTRIBUTE_MAP_KEY_COLUMN_TABLE_NOT_VALID;
 	public static String VIRTUAL_ATTRIBUTE_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID;
 	
+	public static String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG;
+	public static String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA;
+	public static String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME;
 	public static String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME;
 	public static String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME;
 	public static String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_TABLE_NOT_VALID;
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/preferences/JpaProblemSeveritiesPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/preferences/JpaProblemSeveritiesPage.java
index c72d7ad..13c3dc8 100644
--- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/preferences/JpaProblemSeveritiesPage.java
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/preferences/JpaProblemSeveritiesPage.java
@@ -510,6 +510,9 @@
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID,                    				JpaValidationMessages.VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_NAME,                                    JpaValidationMessages.VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_NAME);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID, 							JpaValidationMessages.VIRTUAL_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID);
+		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG, 							JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG);
+		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA, 							JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA);
+		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME, 								JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME,                   							JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, 							JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_TABLE_NOT_VALID, 											JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_TABLE_NOT_VALID);