Bug 520387: EclipseLink metadata processing sets incorrect owning
descriptors

Signed-off-by: Will Dazey <dazeydev.3@gmail.com>
Reviewed-by: Lukas Jungmann <lukas.jungmann@oracle.com>
diff --git a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/framework/junit/JUnitTestCase.java b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/framework/junit/JUnitTestCase.java
index 4f704b0..e6f1817 100644
--- a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/framework/junit/JUnitTestCase.java
+++ b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/framework/junit/JUnitTestCase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -13,6 +13,8 @@
  *       - 329008: Support dynamic context creation without persistence.xml
  *     01/23/2013-2.5 Guy Pelletier
  *       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
+ *     09/11/2017-2.1 Will Dazey 
+ *       - 520387: multiple owning descriptors for an embeddable are not set
  ******************************************************************************/
 package org.eclipse.persistence.testing.framework.junit;
 
@@ -1001,6 +1003,16 @@ public static boolean isSelectForUpateNoWaitSupported(Platform platform) {
         return false;
     }
 
+    public static boolean supportsSequenceObjects(String puName) {
+        DatabasePlatform platform = getDatabaseSession(puName).getPlatform();
+        return platform.supportsSequenceObjects();
+    }
+
+    public boolean supportsSequenceObjects() {
+        DatabasePlatform platform = getDatabaseSession(getPersistenceUnitName()).getPlatform();
+        return platform.supportsSequenceObjects();
+    }
+
     /**
      * Return if stored procedures are supported for the database platform for the test database.
      */
diff --git a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/Author.java b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/Author.java
new file mode 100644
index 0000000..37a2e9b
--- /dev/null
+++ b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/Author.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     09/11/2017-2.1 Will Dazey 
+ *       - 520387: multiple owning descriptors for an embeddable are not set
+ ******************************************************************************/ 
+package org.eclipse.persistence.testing.models.jpa.advanced.compositepk;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="CMP3_AUTHOR")
+public class Author {
+
+    @EmbeddedId
+    private AuthorId id;
+    @Column(name="NAME")
+    private String name;
+
+    public Author() {
+        this.id = new AuthorId();
+    }
+
+    public Author(String name) {
+        this.id = new AuthorId();
+        this.name = name;
+    }
+
+    public AuthorId getId() {
+        return id;
+    }
+
+    public String toString() {
+        return "Author [id=" + this.id + ", name=" + this.name + "]";
+    }
+}
\ No newline at end of file
diff --git a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/AuthorId.java b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/AuthorId.java
new file mode 100644
index 0000000..0011e86
--- /dev/null
+++ b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/AuthorId.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     09/11/2017-2.1 Will Dazey 
+ *       - 520387: multiple owning descriptors for an embeddable are not set
+ ******************************************************************************/ 
+package org.eclipse.persistence.testing.models.jpa.advanced.compositepk;
+
+import java.io.Serializable;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Embedded;
+
+@Embeddable
+public class AuthorId implements Serializable {
+
+    private static final long serialVersionUID = -8247509662551594669L;
+
+    @Embedded
+    private NumberId numberId;
+
+    public AuthorId() {
+        this.numberId = new NumberId();
+    }
+
+    @Override
+    public int hashCode() {
+        return numberId.hashCode();
+    }
+
+    public NumberId getNumberId() {
+        return numberId;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        AuthorId other = (AuthorId) obj;
+        if (numberId == null) {
+            if (other.numberId != null)
+                return false;
+        } else if (!numberId.equals(other.numberId))
+            return false;
+        return true;
+    }
+
+    public String toString() {
+        return "AuthorId [numberId=" + this.numberId + "]";
+    }
+}
diff --git a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/Book.java b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/Book.java
new file mode 100644
index 0000000..4c9f6da
--- /dev/null
+++ b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/Book.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     09/11/2017-2.1 Will Dazey 
+ *       - 520387: multiple owning descriptors for an embeddable are not set
+ ******************************************************************************/ 
+package org.eclipse.persistence.testing.models.jpa.advanced.compositepk;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="CMP3_BOOK")
+public class Book {
+
+    @EmbeddedId
+    private BookId id;
+    @Column(name="TITLE")
+    private String title;
+
+    public Book() {
+        this.id = new BookId();
+        this.title = "Default Title";
+    }
+
+    public Book(String title) {
+        this.id = new BookId();
+        this.title = title;
+    }
+
+    public BookId getId() {
+        return id;
+    }
+
+    public String toString() {
+        return "Book [id=" + this.id + ", title=" + this.title + "]";
+    }
+}
diff --git a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/BookId.java b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/BookId.java
new file mode 100644
index 0000000..a52b995
--- /dev/null
+++ b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/BookId.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     09/11/2017-2.1 Will Dazey 
+ *       - 520387: multiple owning descriptors for an embeddable are not set
+ ******************************************************************************/ 
+package org.eclipse.persistence.testing.models.jpa.advanced.compositepk;
+
+import java.io.Serializable;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Embedded;
+
+@Embeddable
+public class BookId implements Serializable {
+
+    private static final long serialVersionUID = -2930906625230816968L;
+
+    @Embedded
+    private NumberId numberId;
+
+    public BookId() {
+        this.numberId = new NumberId();
+    }
+
+    @Override
+    public int hashCode() {
+        return numberId.hashCode();
+    }
+
+    public NumberId getNumberId() {
+        return numberId;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        BookId other = (BookId) obj;
+        if (numberId == null) {
+            if (other.numberId != null)
+                return false;
+        } else if (!numberId.equals(other.numberId))
+            return false;
+        return true;
+    }
+
+    public String toString() {
+        return "BookId [numberId=" + this.numberId + "]";
+    }
+
+}
diff --git a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/CompositePKTableCreator.java b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/CompositePKTableCreator.java
index 437f181..49d0ed4 100644
--- a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/CompositePKTableCreator.java
+++ b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/CompositePKTableCreator.java
@@ -23,6 +23,8 @@
  *       - 336122: ValidationException thrown for JoinColumns on OneToMany with composite primary key
  *     01/06/2015-2.6 Dalia Abo Sheasha
  *       - 454917: Informix tables need to use INT fields when referencing SERIAL types.
+ *     09/11/2017-2.1 Will Dazey 
+ *       - 520387: multiple owning descriptors for an embeddable are not set
  ******************************************************************************/
 
 package org.eclipse.persistence.testing.models.jpa.advanced.compositepk;
@@ -1135,6 +1137,60 @@ public static TableDefinition buildADMINPOOLTable() {
         return table;
     }
 
+    public static TableDefinition buildAUTHORTable() {
+        TableDefinition table = new TableDefinition();
+        table.setName("CMP3_AUTHOR");
+
+        FieldDefinition ID_NUMBER_field = new FieldDefinition();
+        ID_NUMBER_field.setName("ID_NUMBER");
+        ID_NUMBER_field.setTypeName("NUMERIC");
+        ID_NUMBER_field.setSize(15);
+        ID_NUMBER_field.setShouldAllowNull(false);
+        ID_NUMBER_field.setIsPrimaryKey(true);
+        ID_NUMBER_field.setUnique(false);
+        ID_NUMBER_field.setIsIdentity(true);
+        table.addField(ID_NUMBER_field);
+
+        FieldDefinition F_NAME_field = new FieldDefinition();
+        F_NAME_field.setName("NAME");
+        F_NAME_field.setTypeName("VARCHAR");
+        F_NAME_field.setSize(40);
+        F_NAME_field.setShouldAllowNull(false);
+        F_NAME_field.setIsPrimaryKey(false);
+        F_NAME_field.setUnique(false);
+        F_NAME_field.setIsIdentity(true);
+        table.addField(F_NAME_field);
+
+        return table;
+    }
+
+    public static TableDefinition buildBOOKTable() {
+        TableDefinition table = new TableDefinition();
+        table.setName("CMP3_BOOK");
+
+        FieldDefinition ID_NUMBER_field = new FieldDefinition();
+        ID_NUMBER_field.setName("ID_NUMBER");
+        ID_NUMBER_field.setTypeName("NUMERIC");
+        ID_NUMBER_field.setSize(15);
+        ID_NUMBER_field.setShouldAllowNull(false);
+        ID_NUMBER_field.setIsPrimaryKey(true);
+        ID_NUMBER_field.setUnique(false);
+        ID_NUMBER_field.setIsIdentity(true);
+        table.addField(ID_NUMBER_field);
+
+        FieldDefinition F_NAME_field = new FieldDefinition();
+        F_NAME_field.setName("TITLE");
+        F_NAME_field.setTypeName("VARCHAR");
+        F_NAME_field.setSize(40);
+        F_NAME_field.setShouldAllowNull(false);
+        F_NAME_field.setIsPrimaryKey(false);
+        F_NAME_field.setUnique(false);
+        F_NAME_field.setIsIdentity(true);
+        table.addField(F_NAME_field);
+
+        return table;
+    }
+
     /**
      * Dropping old foreign keys from schema change.
      */
diff --git a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/NumberId.java b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/NumberId.java
new file mode 100644
index 0000000..88ecfb6
--- /dev/null
+++ b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/compositepk/NumberId.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     09/11/2017-2.1 Will Dazey 
+ *       - 520387: multiple owning descriptors for an embeddable are not set
+ ******************************************************************************/ 
+package org.eclipse.persistence.testing.models.jpa.advanced.compositepk;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.GeneratedValue;
+import javax.persistence.SequenceGenerator;
+
+@Embeddable
+public class NumberId implements Serializable {
+
+    private static final long serialVersionUID = 4263409730381544959L;
+
+    @Column(name = "ID_NUMBER")
+    @SequenceGenerator(name = "ID_SEQ", sequenceName = "ID_SEQUENCE", allocationSize = 50, initialValue = 1000)
+    @GeneratedValue(generator = "ID_SEQ")
+    private Long value;
+
+    public NumberId() {
+        this(Long.valueOf(0L));
+    }
+
+    public NumberId(Long value) {
+        this.value = value;
+    }
+
+    public Long getValue() {
+        return value;
+    }
+
+    public final boolean equals(Object other) {
+        if (other == null) {
+            return false;
+        }
+        if (this == other) {
+            return true;
+        }
+        if (getClass() != other.getClass()) {
+            return false;
+        }
+        return Objects.equals(this.value, ((NumberId) other).value);
+    }
+
+    public final int hashCode() {
+        return Objects.hash(new Object[] { this.value });
+    }
+
+    public final String toString() {
+        return getClass().getSimpleName() + "[value=" + this.value + "]";
+    }
+}
diff --git a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/compositepk/AdvancedCompositePKJunitTest.java b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/compositepk/AdvancedCompositePKJunitTest.java
index ef03553..a1e9fc4 100644
--- a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/compositepk/AdvancedCompositePKJunitTest.java
+++ b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/compositepk/AdvancedCompositePKJunitTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2016 Oracle and/or its affiliates, IBM Corporation. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates, IBM Corporation. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -19,6 +19,8 @@
  *       - 314941: multiple joinColumns without referenced column names defined, no error
  *     01/25/2011-2.3 Guy Pelletier
  *       - 333913: @OrderBy and <order-by/> without arguments should order by primary
+ *     09/11/2017-2.1 Will Dazey 
+ *       - 520387: multiple owning descriptors for an embeddable are not set
  ******************************************************************************/
 package org.eclipse.persistence.testing.tests.jpa.advanced.compositepk;
 
@@ -35,12 +37,15 @@
 import junit.framework.*;
 
 import org.eclipse.persistence.descriptors.ClassDescriptor;
+import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
 import org.eclipse.persistence.jpa.JpaHelper;
 import org.eclipse.persistence.mappings.DatabaseMapping;
 import org.eclipse.persistence.mappings.OneToManyMapping;
 import org.eclipse.persistence.sessions.CopyGroup;
 import org.eclipse.persistence.sessions.server.ServerSession;
 import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
+import org.eclipse.persistence.testing.models.jpa.advanced.compositepk.Author;
+import org.eclipse.persistence.testing.models.jpa.advanced.compositepk.Book;
 import org.eclipse.persistence.testing.models.jpa.advanced.compositepk.Competency;
 import org.eclipse.persistence.testing.models.jpa.advanced.compositepk.Cubicle;
 import org.eclipse.persistence.testing.models.jpa.advanced.compositepk.JuniorScientist;
@@ -142,6 +147,7 @@ public static Test suite() {
             suite.addTest(new AdvancedCompositePKJunitTest("testGetIdentifier"));
             suite.addTest(new AdvancedCompositePKJunitTest("testFailedGetIdenitifier"));
             suite.addTest(new AdvancedCompositePKJunitTest("testGetIdenitifierOnNonEntity"));
+            suite.addTest(new AdvancedCompositePKJunitTest("testNestedEmbeddableSequenceGeneration"));
         }
         return suite;
     }
@@ -1024,4 +1030,24 @@ public void testGetIdenitifierOnNonEntity(){
         }
         fail("IllegalArgumentException not thrown for call to getIdentifier with a non-entity class.");
     }
+
+    // bug 520387
+    public void testNestedEmbeddableSequenceGeneration(){
+        if(!supportsSequenceObjects()) {
+            return;
+        }
+
+        Book b = new Book("Book1");
+        Author a = new Author("Author1");
+
+        EntityManager em = createEntityManager();
+        beginTransaction(em);
+        b = (Book) em.merge(b);
+        a = (Author) em.merge(a);
+
+        assertTrue("The PK value for "+ b.getClass() +" (" + b.getId().getNumberId().getValue() + ") is not sequence generated", (b.getId().getNumberId().getValue() >= new Long(1000)));
+        assertTrue("The PK value for "+ a.getClass() +" (" + a.getId().getNumberId().getValue() + ") is not sequence generated", (a.getId().getNumberId().getValue() >= new Long(1000)));
+
+        rollbackTransaction(em);
+    }
 }
diff --git a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/accessors/classes/EmbeddableAccessor.java b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/accessors/classes/EmbeddableAccessor.java
index e078694..2121c85 100644
--- a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/accessors/classes/EmbeddableAccessor.java
+++ b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/accessors/classes/EmbeddableAccessor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -54,6 +54,8 @@
  *       - 251554: ExcludeDefaultMapping annotation needed
  *     03/24/2011-2.3 Guy Pelletier
  *       - 337323: Multi-tenant with shared schema support (part 1)
+ *     09/11/2017-2.1 Will Dazey 
+ *       - 520387: multiple owning descriptors for an embeddable are not set
  ******************************************************************************/
 package org.eclipse.persistence.internal.jpa.metadata.accessors.classes;
 
@@ -154,10 +156,12 @@ protected void addPotentialEmbeddableAccessor(MetadataClass potentialEmbeddableC
             // another entity within the persistence unit.
             EmbeddableAccessor embeddableAccessor = getProject().getEmbeddableAccessor(potentialEmbeddableClass, true);
 
-            if (embeddableAccessor != null && ! embeddableAccessor.isPreProcessed()) {
+            if (embeddableAccessor != null) {
                 embeddableAccessor.addEmbeddingAccessor(embeddingAccessor);
                 embeddableAccessor.addOwningDescriptors(getOwningDescriptors());
-                embeddableAccessor.preProcess();
+                if(!embeddableAccessor.isPreProcessed()) {
+                    embeddableAccessor.preProcess();
+                }
             }
         }
     }