313766 - StackOverflowError with a self-referential ElementCollection or Embedded
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaBaseEmbeddedMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaBaseEmbeddedMapping.java
index e6277f9..e50c6e2 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaBaseEmbeddedMapping.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaBaseEmbeddedMapping.java
@@ -104,12 +104,13 @@
 		setTargetEmbeddable_(this.getPersistentAttribute().getEmbeddable());
 		this.attributeOverrideContainer.update(this.getResourcePersistentAttribute());
 	}
-	
+
 	protected Iterator<AttributeMapping> embeddableAttributeMappings() {
-		if (this.getTargetEmbeddable() == null) {
-			return EmptyIterator.instance();
+		Embeddable targetEmbeddable = getTargetEmbeddable();
+		if (targetEmbeddable != null && targetEmbeddable != getPersistentAttribute().getOwningTypeMapping()) {
+			return targetEmbeddable.attributeMappings();
 		}
-		return this.getTargetEmbeddable().attributeMappings();
+		return EmptyIterator.instance();
 	}
 	
 	@Override
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmBaseEmbeddedMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmBaseEmbeddedMapping.java
index 2b7ca2f..eb17fba 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmBaseEmbeddedMapping.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmBaseEmbeddedMapping.java
@@ -92,12 +92,13 @@
 		this.targetEmbeddable = newTargetEmbeddable;
 		firePropertyChanged(TARGET_EMBEDDABLE_PROPERTY, oldTargetEmbeddable, newTargetEmbeddable);
 	}
-	
+
 	protected Iterator<AttributeMapping> embeddableAttributeMappings() {
-		if (this.getTargetEmbeddable() == null) {
-			return EmptyIterator.instance();
+		Embeddable targetEmbeddable = getTargetEmbeddable();
+		if (targetEmbeddable != null && targetEmbeddable != getPersistentAttribute().getOwningTypeMapping()) {
+			return targetEmbeddable.attributeMappings();
 		}
-		return this.getTargetEmbeddable().attributeMappings();
+		return EmptyIterator.instance();
 	}
 	
 	@Override
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 927361d..8736b45 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
@@ -997,10 +997,11 @@
 	}
 
 	protected Iterator<AttributeMapping> embeddableAttributeMappings() {
-		if (this.getResolvedTargetEmbeddable() == null) {
-			return EmptyIterator.instance();
+		Embeddable targetEmbeddable = getResolvedTargetEmbeddable();
+		if (targetEmbeddable != null && targetEmbeddable != getPersistentAttribute().getOwningTypeMapping()) {
+			return targetEmbeddable.attributeMappings();
 		}
-		return this.getResolvedTargetEmbeddable().attributeMappings();
+		return EmptyIterator.instance();
 	}
 
 	@Override
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 bd9a4d5..13ef480 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
@@ -665,10 +665,11 @@
 	}
 
 	protected Iterator<AttributeMapping> embeddableAttributeMappings() {
-		if (this.getResolvedTargetEmbeddable() == null) {
-			return EmptyIterator.instance();
+		Embeddable targetEmbeddable = getResolvedTargetEmbeddable();
+		if (targetEmbeddable != null && targetEmbeddable != getPersistentAttribute().getOwningTypeMapping()) {
+			return targetEmbeddable.attributeMappings();
 		}
-		return this.getResolvedTargetEmbeddable().attributeMappings();
+		return EmptyIterator.instance();
 	}
 
 	@Override
diff --git a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/java/GenericJavaElementCollectionMapping2_0Tests.java b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/java/GenericJavaElementCollectionMapping2_0Tests.java
index 3e59dcf..264396c 100644
--- a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/java/GenericJavaElementCollectionMapping2_0Tests.java
+++ b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/java/GenericJavaElementCollectionMapping2_0Tests.java
@@ -308,6 +308,31 @@
 		this.javaProject.createCompilationUnit(PACKAGE_NAME, "PropertyInfo.java", sourceWriter);
 	}
 
+	private void createSelfReferentialElementCollection() throws Exception {
+		SourceWriter sourceWriter = new SourceWriter() {
+			public void appendSourceTo(StringBuilder sb) {
+					sb.append("import ");
+					sb.append(JPA.EMBEDDABLE);
+					sb.append(";");
+					sb.append(CR);
+					sb.append("import ");
+					sb.append(JPA2_0.ELEMENT_COLLECTION);
+					sb.append(";");
+					sb.append(CR).append(CR);
+				sb.append("@Embeddable");
+				sb.append(CR);
+				sb.append("public class ").append("Foo").append(" ");
+				sb.append("{").append(CR);
+				sb.append(CR);
+				sb.append("    @ElementCollection").append(CR);
+				sb.append("    private java.util.List<Foo> elementCollection;").append(CR);
+				sb.append(CR);
+				sb.append("}").append(CR);
+		}
+		};
+		this.javaProject.createCompilationUnit(PACKAGE_NAME, "Foo.java", sourceWriter);
+	}
+
 	public GenericJavaElementCollectionMapping2_0Tests(String name) {
 		super(name);
 	}
@@ -2025,4 +2050,13 @@
 		assertEquals("city", specifiedOverrides.next().getName());
 		assertFalse(specifiedOverrides.hasNext());
 	}
+
+	public void testSelfReferentialElementCollection() throws Exception {
+		createSelfReferentialElementCollection();
+		addXmlClassRef(PACKAGE_NAME + ".Foo");
+		
+		//If there is a StackOverflowError you will not be able to get the mapping
+		JavaElementCollectionMapping2_0 elementCollectionMapping = (JavaElementCollectionMapping2_0) getJavaPersistentType().getAttributeNamed("elementCollection").getMapping();
+		assertFalse(elementCollectionMapping.allOverrideableAttributeMappingNames().hasNext());
+	}
 }
diff --git a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/java/GenericJavaEmbeddedMapping2_0Tests.java b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/java/GenericJavaEmbeddedMapping2_0Tests.java
index 95d3b45..863196c 100644
--- a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/java/GenericJavaEmbeddedMapping2_0Tests.java
+++ b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/java/GenericJavaEmbeddedMapping2_0Tests.java
@@ -358,7 +358,32 @@
 		};
 		this.javaProject.createCompilationUnit(PACKAGE_NAME, "Embeddable1.java", sourceWriter);
 	}
-	
+
+	private void createSelfReferentialEmbedded() throws Exception {
+		SourceWriter sourceWriter = new SourceWriter() {
+			public void appendSourceTo(StringBuilder sb) {
+					sb.append("import ");
+					sb.append(JPA.EMBEDDABLE);
+					sb.append(";");
+					sb.append(CR);
+					sb.append("import ");
+					sb.append(JPA.EMBEDDED);
+					sb.append(";");
+					sb.append(CR).append(CR);
+				sb.append("@Embeddable");
+				sb.append(CR);
+				sb.append("public class ").append("Foo").append(" ");
+				sb.append("{").append(CR);
+				sb.append(CR);
+				sb.append("    @Embedded").append(CR);
+				sb.append("    private Foo embedded;").append(CR);
+				sb.append(CR);
+				sb.append("}").append(CR);
+		}
+		};
+		this.javaProject.createCompilationUnit(PACKAGE_NAME, "Foo.java", sourceWriter);
+	}
+
 	public void testMorphToVersionMapping() throws Exception {
 		createTestEntityWithEmbeddedMapping();
 		createEmbeddableType();
@@ -1508,4 +1533,12 @@
 		assertEquals(0, specifiedAttributeOverride.getColumn().getScale());
 	}
 
+	public void testSelfReferentialEmbeddedMapping() throws Exception {
+		createSelfReferentialEmbedded();
+		addXmlClassRef(PACKAGE_NAME + ".Foo");
+		
+		//If there is a StackOverflowError you will not be able to get the mapping
+		JavaEmbeddedMapping2_0 embeddedMapping = (JavaEmbeddedMapping2_0) getJavaPersistentType().getAttributeNamed("embedded").getMapping();
+		assertFalse(embeddedMapping.allOverrideableAttributeMappingNames().hasNext());
+	}
 }
diff --git a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/orm/GenericOrmElementCollectionMapping2_0Tests.java b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/orm/GenericOrmElementCollectionMapping2_0Tests.java
index 676d055..e7fe66b 100644
--- a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/orm/GenericOrmElementCollectionMapping2_0Tests.java
+++ b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/orm/GenericOrmElementCollectionMapping2_0Tests.java
@@ -257,6 +257,31 @@
 			}
 		});
 	}
+
+	private void createSelfReferentialElementCollection() throws Exception {
+		SourceWriter sourceWriter = new SourceWriter() {
+			public void appendSourceTo(StringBuilder sb) {
+					sb.append("import ");
+					sb.append(JPA.EMBEDDABLE);
+					sb.append(";");
+					sb.append(CR);
+					sb.append("import ");
+					sb.append(JPA2_0.ELEMENT_COLLECTION);
+					sb.append(";");
+					sb.append(CR).append(CR);
+				sb.append("@Embeddable");
+				sb.append(CR);
+				sb.append("public class ").append("Foo").append(" ");
+				sb.append("{").append(CR);
+				sb.append(CR);
+				sb.append("    @ElementCollection").append(CR);
+				sb.append("    private java.util.List<Foo> elementCollection;").append(CR);
+				sb.append(CR);
+				sb.append("}").append(CR);
+		}
+		};
+		this.javaProject.createCompilationUnit(PACKAGE_NAME, "Foo.java", sourceWriter);
+	}
 	
 	public void testUpdateName() throws Exception {
 		OrmPersistentType ormPersistentType = getEntityMappings().addPersistentType(MappingKeys.ENTITY_TYPE_MAPPING_KEY, "model.Foo");
@@ -1418,4 +1443,12 @@
 		assertNull(ormColumn.getSpecifiedTable());
 		assertEquals(TYPE_NAME + "_addresses", ormColumn.getDefaultTable());
 	}
+
+	public void testSelfReferentialElementCollectionMapping() throws Exception {
+		createSelfReferentialElementCollection();
+		OrmPersistentType persistentType = getEntityMappings().addPersistentType(MappingKeys.EMBEDDABLE_TYPE_MAPPING_KEY, PACKAGE_NAME + ".Foo");
+
+		OrmElementCollectionMapping2_0 mapping = (OrmElementCollectionMapping2_0) persistentType.getAttributeNamed("elementCollection").getMapping();
+		assertFalse(mapping.allOverrideableAttributeMappingNames().hasNext());
+	}
 }
\ No newline at end of file
diff --git a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/orm/GenericOrmEmbeddedMapping2_0Tests.java b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/orm/GenericOrmEmbeddedMapping2_0Tests.java
index 4c808c5..ad0fe31 100644
--- a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/orm/GenericOrmEmbeddedMapping2_0Tests.java
+++ b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jpa2/context/orm/GenericOrmEmbeddedMapping2_0Tests.java
@@ -310,6 +310,33 @@
 		this.javaProject.createCompilationUnit(PACKAGE_NAME, "ZipCode.java", sourceWriter);
 	}
 
+	private void createSelfReferentialEmbedded() throws Exception {
+		SourceWriter sourceWriter = new SourceWriter() {
+			public void appendSourceTo(StringBuilder sb) {
+					sb.append("import ");
+					sb.append(JPA.EMBEDDABLE);
+					sb.append(";");
+					sb.append(CR);
+					sb.append("import ");
+					sb.append(JPA.EMBEDDED);
+					sb.append(";");
+					sb.append(CR).append(CR);
+				sb.append("@Embeddable");
+				sb.append(CR);
+				sb.append("public class ").append("Foo").append(" ");
+				sb.append("{").append(CR);
+				sb.append(CR);
+				sb.append("    @Embedded").append(CR);
+				sb.append("    private Foo embedded;").append(CR);
+				sb.append(CR);
+				sb.append("    private String name;").append(CR);
+				sb.append(CR);
+				sb.append("}").append(CR);
+		}
+		};
+		this.javaProject.createCompilationUnit(PACKAGE_NAME, "Foo.java", sourceWriter);
+	}
+
 	public void testUpdateName() throws Exception {
 		OrmPersistentType ormPersistentType = getEntityMappings().addPersistentType(MappingKeys.ENTITY_TYPE_MAPPING_KEY, "model.Foo");
 		OrmPersistentAttribute ormPersistentAttribute = ormPersistentType.addSpecifiedAttribute(MappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY, "embeddedMapping");
@@ -1673,4 +1700,12 @@
 		assertEquals(0, specifiedAttributeOverride.getColumn().getPrecision());
 		assertEquals(0, specifiedAttributeOverride.getColumn().getScale());
 	}
+
+	public void testSelfReferentialEmbeddedMapping() throws Exception {
+		createSelfReferentialEmbedded();
+		OrmPersistentType persistentType = getEntityMappings().addPersistentType(MappingKeys.EMBEDDABLE_TYPE_MAPPING_KEY, PACKAGE_NAME + ".Foo");
+
+		OrmEmbeddedMapping2_0 embeddedMapping = (OrmEmbeddedMapping2_0) persistentType.getAttributeNamed("embedded").getMapping();
+		assertFalse(embeddedMapping.allOverrideableAttributeMappingNames().hasNext());
+	}
 }
\ No newline at end of file
diff --git a/jpa/tests/org.eclipse.jpt.eclipselink.core.tests/src/org/eclipse/jpt/eclipselink2_0/core/tests/internal/context/java/EclipseLink2_0JavaElementCollectionMappingTests.java b/jpa/tests/org.eclipse.jpt.eclipselink.core.tests/src/org/eclipse/jpt/eclipselink2_0/core/tests/internal/context/java/EclipseLink2_0JavaElementCollectionMappingTests.java
index 9b0df09..d5b35d2 100644
--- a/jpa/tests/org.eclipse.jpt.eclipselink.core.tests/src/org/eclipse/jpt/eclipselink2_0/core/tests/internal/context/java/EclipseLink2_0JavaElementCollectionMappingTests.java
+++ b/jpa/tests/org.eclipse.jpt.eclipselink.core.tests/src/org/eclipse/jpt/eclipselink2_0/core/tests/internal/context/java/EclipseLink2_0JavaElementCollectionMappingTests.java
@@ -309,6 +309,31 @@
 		this.javaProject.createCompilationUnit(PACKAGE_NAME, "PropertyInfo.java", sourceWriter);
 	}
 
+	private void createSelfReferentialElementCollection() throws Exception {
+		SourceWriter sourceWriter = new SourceWriter() {
+			public void appendSourceTo(StringBuilder sb) {
+					sb.append("import ");
+					sb.append(JPA.EMBEDDABLE);
+					sb.append(";");
+					sb.append(CR);
+					sb.append("import ");
+					sb.append(JPA2_0.ELEMENT_COLLECTION);
+					sb.append(";");
+					sb.append(CR).append(CR);
+				sb.append("@Embeddable");
+				sb.append(CR);
+				sb.append("public class ").append("Foo").append(" ");
+				sb.append("{").append(CR);
+				sb.append(CR);
+				sb.append("    @ElementCollection").append(CR);
+				sb.append("    private java.util.List<Foo> elementCollection;").append(CR);
+				sb.append(CR);
+				sb.append("}").append(CR);
+		}
+		};
+		this.javaProject.createCompilationUnit(PACKAGE_NAME, "Foo.java", sourceWriter);
+	}
+
 	public EclipseLink2_0JavaElementCollectionMappingTests(String name) {
 		super(name);
 	}
@@ -2027,4 +2052,13 @@
 		assertEquals("city", specifiedOverrides.next().getName());
 		assertFalse(specifiedOverrides.hasNext());
 	}
+	
+	public void testSelfReferentialElementCollection() throws Exception {
+		createSelfReferentialElementCollection();
+		addXmlClassRef(PACKAGE_NAME + ".Foo");
+		
+		//If there is a StackOverflowError you will not be able to get the mapping
+		JavaElementCollectionMapping2_0 elementCollectionMapping = (JavaElementCollectionMapping2_0) getJavaPersistentType().getAttributeNamed("elementCollection").getMapping();
+		assertFalse(elementCollectionMapping.allOverrideableAttributeMappingNames().hasNext());
+	}
 }
diff --git a/jpa/tests/org.eclipse.jpt.eclipselink.core.tests/src/org/eclipse/jpt/eclipselink2_0/core/tests/internal/context/orm/EclipseLink2_0OrmElementCollectionMappingTests.java b/jpa/tests/org.eclipse.jpt.eclipselink.core.tests/src/org/eclipse/jpt/eclipselink2_0/core/tests/internal/context/orm/EclipseLink2_0OrmElementCollectionMappingTests.java
index 02d9287..a757dec 100644
--- a/jpa/tests/org.eclipse.jpt.eclipselink.core.tests/src/org/eclipse/jpt/eclipselink2_0/core/tests/internal/context/orm/EclipseLink2_0OrmElementCollectionMappingTests.java
+++ b/jpa/tests/org.eclipse.jpt.eclipselink.core.tests/src/org/eclipse/jpt/eclipselink2_0/core/tests/internal/context/orm/EclipseLink2_0OrmElementCollectionMappingTests.java
@@ -244,7 +244,32 @@
 			}
 		});
 	}
-	
+
+	private void createSelfReferentialElementCollection() throws Exception {
+		SourceWriter sourceWriter = new SourceWriter() {
+			public void appendSourceTo(StringBuilder sb) {
+					sb.append("import ");
+					sb.append(JPA.EMBEDDABLE);
+					sb.append(";");
+					sb.append(CR);
+					sb.append("import ");
+					sb.append(JPA2_0.ELEMENT_COLLECTION);
+					sb.append(";");
+					sb.append(CR).append(CR);
+				sb.append("@Embeddable");
+				sb.append(CR);
+				sb.append("public class ").append("Foo").append(" ");
+				sb.append("{").append(CR);
+				sb.append(CR);
+				sb.append("    @ElementCollection").append(CR);
+				sb.append("    private java.util.List<Foo> elementCollection;").append(CR);
+				sb.append(CR);
+				sb.append("}").append(CR);
+		}
+		};
+		this.javaProject.createCompilationUnit(PACKAGE_NAME, "Foo.java", sourceWriter);
+	}
+
 	public void testUpdateName() throws Exception {
 		OrmPersistentType ormPersistentType = getEntityMappings().addPersistentType(MappingKeys.ENTITY_TYPE_MAPPING_KEY, "model.Foo");
 		OrmPersistentAttribute ormPersistentAttribute = ormPersistentType.addSpecifiedAttribute(MappingKeys2_0.ELEMENT_COLLECTION_ATTRIBUTE_MAPPING_KEY, "oneToOneMapping");
@@ -1402,4 +1427,12 @@
 		assertNull(ormColumn.getSpecifiedTable());
 		assertEquals(TYPE_NAME + "_addresses", ormColumn.getDefaultTable());
 	}
+
+	public void testSelfReferentialElementCollectionMapping() throws Exception {
+		createSelfReferentialElementCollection();
+		OrmPersistentType persistentType = getEntityMappings().addPersistentType(MappingKeys.EMBEDDABLE_TYPE_MAPPING_KEY, PACKAGE_NAME + ".Foo");
+
+		OrmElementCollectionMapping2_0 mapping = (OrmElementCollectionMapping2_0) persistentType.getAttributeNamed("elementCollection").getMapping();
+		assertFalse(mapping.allOverrideableAttributeMappingNames().hasNext());
+	}
 }
\ No newline at end of file