You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2006/04/30 21:20:19 UTC

svn commit: r398407 - in /incubator/cayenne/jpa/trunk: cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/ cayenne-jpa/src/main/java/org/apache/cayenne/jpa/bridge/ cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/ ...

Author: aadamchik
Date: Sun Apr 30 12:20:16 2006
New Revision: 398407

URL: http://svn.apache.org/viewcvs?rev=398407&view=rev
Log:
generics introspection code to detect to-many relationship types

Modified:
    incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Department.java
    incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Person.java
    incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Project.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaClassDescriptor.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaPropertyDescriptor.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToMany.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToOne.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToMany.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToOne.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessorTest.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean1.java
    incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean3.java

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Department.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Department.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Department.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Department.java Sun Apr 30 12:20:16 2006
@@ -19,6 +19,7 @@
 
 import javax.persistence.Entity;
 import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
 import javax.persistence.QueryHint;
 
 import org.apache.cayenne.jpa.bridge.QueryHints;
@@ -32,7 +33,11 @@
 
     protected String name;
     protected String description;
+    
+    @OneToMany
     protected List<Person> employees;
+    
+    @OneToMany
     protected List<Project> projects;
 
     public String getDescription() {

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Person.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Person.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Person.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Person.java Sun Apr 30 12:20:16 2006
@@ -19,6 +19,9 @@
 import java.util.List;
 
 import javax.persistence.Entity;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
 
 @Entity
 public class Person {
@@ -26,8 +29,14 @@
     protected double baseSalary;
     protected Date dateHired;
     protected String fullName;
+
+    @ManyToOne
     protected Department department;
+
+    @OneToMany
     protected List<Project> managedProjects;
+
+    @ManyToMany
     protected List<Project> projects;
 
     public double getBaseSalary() {

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Project.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Project.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Project.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa-annotations-example/src/main/java/org/apache/cayenne/jpa/example/entity/Project.java Sun Apr 30 12:20:16 2006
@@ -17,11 +17,22 @@
 
 import java.util.List;
 
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+
+@Entity
 public class Project {
 
     protected String name;
+    
+    @ManyToOne
     protected Department department;
+    
+    @ManyToOne
     protected Person manager;
+    
+    @OneToMany
     protected List<Person> members;
 
     public Department getDepartment() {

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java Sun Apr 30 12:20:16 2006
@@ -263,6 +263,12 @@
             JpaEntity jpaTargetEntity = ((JpaEntityMap) path.getRoot())
                     .entityForClass(relationship.getTargetEntityName());
 
+            if (jpaTargetEntity == null) {
+                recordConflict(path, "Unknown target entity '"
+                        + relationship.getTargetEntityName());
+                return false;
+            }
+
             DbEntity cayenneSrcDbEntity = cayenneSrcEntity.getDbEntity();
 
             DbEntity cayenneTargetDbEntity = cayenneSrcEntity.getDataMap().getDbEntity(

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java Sun Apr 30 12:20:16 2006
@@ -17,7 +17,6 @@
 
 import org.apache.cayenne.jpa.JpaProviderException;
 import org.apache.cayenne.jpa.map.AccessType;
-import org.apache.cayenne.jpa.map.JpaRelationship;
 import org.apache.cayenne.jpa.map.JpaAttribute;
 import org.apache.cayenne.jpa.map.JpaBasic;
 import org.apache.cayenne.jpa.map.JpaColumn;
@@ -25,14 +24,18 @@
 import org.apache.cayenne.jpa.map.JpaEntityMap;
 import org.apache.cayenne.jpa.map.JpaId;
 import org.apache.cayenne.jpa.map.JpaJoinColumn;
+import org.apache.cayenne.jpa.map.JpaManyToMany;
 import org.apache.cayenne.jpa.map.JpaManyToOne;
 import org.apache.cayenne.jpa.map.JpaMappedSuperclass;
+import org.apache.cayenne.jpa.map.JpaOneToMany;
 import org.apache.cayenne.jpa.map.JpaOneToOne;
+import org.apache.cayenne.jpa.map.JpaRelationship;
 import org.apache.cayenne.jpa.map.JpaTable;
 import org.apache.cayenne.util.BaseTreeVisitor;
 import org.apache.cayenne.util.HierarchicalTreeVisitor;
 import org.apache.cayenne.util.TraversalUtil;
 import org.objectstyle.cayenne.project.ProjectPath;
+import org.objectstyle.cayenne.util.Util;
 import org.objectstyle.cayenne.validation.SimpleValidationFailure;
 
 /**
@@ -73,6 +76,12 @@
             attributeVisitor.addChildVisitor(JpaBasic.class, new BasicVisitor());
             attributeVisitor.addChildVisitor(JpaManyToOne.class, new FKVisitor());
             attributeVisitor.addChildVisitor(JpaOneToOne.class, new FKVisitor());
+            attributeVisitor.addChildVisitor(
+                    JpaManyToMany.class,
+                    new RelationshipVisitor());
+            attributeVisitor.addChildVisitor(
+                    JpaOneToMany.class,
+                    new RelationshipVisitor());
 
             addChildVisitor(JpaAttribute.class, attributeVisitor);
             addChildVisitor(JpaId.class, new IdVisitor());
@@ -243,15 +252,20 @@
 
     }
 
-    final class FKVisitor extends BaseTreeVisitor {
+    final class FKVisitor extends RelationshipVisitor {
 
         @Override
         public boolean onStartNode(ProjectPath path) {
 
+            if (!super.onStartNode(path)) {
+                return false;
+            }
+
             JpaAttribute attribute = (JpaAttribute) path.getObjectParent();
             if (attribute.getJoinColumns().isEmpty()) {
 
                 JpaRelationship relationship = (JpaRelationship) path.getObject();
+
                 if (relationship.isOwner()) {
 
                     // JPA Spec, 2.1.8.2 (same for all relationship owners):
@@ -297,6 +311,46 @@
                                 : id.getName();
                         joinColumn.setName(attribute.getName() + '_' + pkName);
                     }
+                }
+            }
+
+            return true;
+        }
+    }
+
+    class RelationshipVisitor extends BaseTreeVisitor {
+
+        @Override
+        public boolean onStartNode(ProjectPath path) {
+
+            JpaRelationship relationship = (JpaRelationship) path.getObject();
+            if (Util.isEmptyString(relationship.getTargetEntityName())) {
+
+                JpaEntity entity = (JpaEntity) path.firstInstanceOf(JpaEntity.class);
+
+                String name = relationship.getParent().getName();
+                JpaEntityMap entityMap = (JpaEntityMap) path.getRoot();
+
+                JpaClassDescriptor srcDescriptor = context.getLoadedDescriptor(entity
+                        .getClassName());
+                JpaPropertyDescriptor property;
+
+                if (entityMap.getAccess() == AccessType.FIELD) {
+                    property = srcDescriptor.getFieldDescriptor(name);
+                }
+                else {
+                    property = srcDescriptor.getPropertyDescriptor(name);
+                }
+
+                Class targetEntityType = property.getTargetEntityType();
+
+                if (targetEntityType == null) {
+                    context.recordConflict(new SimpleValidationFailure(property
+                            .getMember(), "Undefined target entity type: " + name));
+                    return false;
+                }
+                else {
+                    relationship.setTargetEntityName(targetEntityType.getName());
                 }
             }
 

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaClassDescriptor.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaClassDescriptor.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaClassDescriptor.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaClassDescriptor.java Sun Apr 30 12:20:16 2006
@@ -47,7 +47,27 @@
     public Class getManagedClass() {
         return managedClass;
     }
-    
+
+    public JpaPropertyDescriptor getFieldDescriptor(String name) {
+        for (JpaPropertyDescriptor d : getFieldDescriptors()) {
+            if (name.equals(d.getName())) {
+                return d;
+            }
+        }
+
+        return null;
+    }
+
+    public JpaPropertyDescriptor getPropertyDescriptor(String name) {
+        for (JpaPropertyDescriptor d : getPropertyDescriptors()) {
+            if (name.equals(d.getName())) {
+                return d;
+            }
+        }
+
+        return null;
+    }
+
     public JpaPropertyDescriptor getFieldDescriptor(Member field) {
         for (JpaPropertyDescriptor d : getFieldDescriptors()) {
             if (d.getMember().equals(field)) {

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaPropertyDescriptor.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaPropertyDescriptor.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaPropertyDescriptor.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/conf/JpaPropertyDescriptor.java Sun Apr 30 12:20:16 2006
@@ -19,6 +19,9 @@
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
 import java.util.regex.Matcher;
 
 import org.apache.cayenne.jpa.JpaProviderException;
@@ -33,11 +36,14 @@
     protected AnnotatedElement member;
     protected String name;
     protected Class type;
+    protected Type genericType;
+    protected Class targetEntityType;
 
     public JpaPropertyDescriptor(Field field) {
         this.member = field;
         this.name = field.getName();
         this.type = field.getType();
+        this.genericType = field.getGenericType();
     }
 
     public JpaPropertyDescriptor(Method getter, String name) {
@@ -52,6 +58,28 @@
         this.member = getter;
         this.name = name;
         this.type = getter.getReturnType();
+        this.genericType = getter.getGenericReturnType();
+    }
+
+    protected void processTargetEntityType() {
+
+        this.targetEntityType = Void.TYPE;
+
+        if (Collection.class.isAssignableFrom(type)) {
+            if (genericType instanceof ParameterizedType) {
+                ParameterizedType pType = (ParameterizedType) genericType;
+                Type[] bounds = pType.getActualTypeArguments();
+                for (int i = bounds.length - 1; i >= 0; i--) {
+                    if (bounds[i] instanceof Class) {
+                        this.targetEntityType = (Class) bounds[i];
+                        return;
+                    }
+                }
+            }
+        }
+        else {
+            targetEntityType = type;
+        }
     }
 
     public AnnotatedElement getMember() {
@@ -66,6 +94,14 @@
         return type;
     }
 
+    public Class getTargetEntityType() {
+        if (targetEntityType == null) {
+            processTargetEntityType();
+        }
+
+        return Void.TYPE.equals(targetEntityType) ? null : targetEntityType;
+    }
+
     /**
      * Returns true if the property is a default simple attribute.
      * <h3>JPA Spec, 2.1.6:</h3>
@@ -78,6 +114,8 @@
      * an error if no annotation is present and none of the above rules apply.
      */
     public boolean isDefaultNonRelationalType() {
+
+        Class type = getTargetEntityType();
 
         if (type.isPrimitive() || type.isEnum()) {
             return true;

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToMany.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToMany.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToMany.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToMany.java Sun Apr 30 12:20:16 2006
@@ -26,7 +26,9 @@
     }
 
     public JpaManyToMany(ManyToMany annotation) {
-        this.targetEntityName = annotation.targetEntity().getName();
+        if (!Void.TYPE.equals(annotation.targetEntity())) {
+            this.targetEntityName = annotation.targetEntity().getName();
+        }
 
         // resolve internal collection
         getCascades();

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToOne.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToOne.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToOne.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaManyToOne.java Sun Apr 30 12:20:16 2006
@@ -30,7 +30,9 @@
     }
 
     public JpaManyToOne(ManyToOne annotation) {
-        this.targetEntityName = annotation.targetEntity().getName();
+        if (!Void.TYPE.equals(annotation.targetEntity())) {
+            this.targetEntityName = annotation.targetEntity().getName();
+        }
 
         // resolve internal collection
         getCascades();

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToMany.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToMany.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToMany.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToMany.java Sun Apr 30 12:20:16 2006
@@ -28,7 +28,9 @@
     }
 
     public JpaOneToMany(OneToMany annotation) {
-        this.targetEntityName = annotation.targetEntity().getName();
+        if (!Void.TYPE.equals(annotation.targetEntity())) {
+            this.targetEntityName = annotation.targetEntity().getName();
+        }
 
         // resolve internal collection
         getCascades();

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToOne.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToOne.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToOne.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/main/java/org/apache/cayenne/jpa/map/JpaOneToOne.java Sun Apr 30 12:20:16 2006
@@ -30,7 +30,9 @@
     }
 
     public JpaOneToOne(OneToOne annotation) {
-        this.targetEntityName = annotation.targetEntity().getName();
+        if (!Void.TYPE.equals(annotation.targetEntity())) {
+            this.targetEntityName = annotation.targetEntity().getName();
+        }
 
         // resolve internal collection
         getCascades();

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessorTest.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessorTest.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessorTest.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessorTest.java Sun Apr 30 12:20:16 2006
@@ -19,19 +19,24 @@
 
 import junit.framework.TestCase;
 
+import org.apache.cayenne.jpa.map.JpaAttribute;
 import org.apache.cayenne.jpa.map.JpaEntity;
 import org.apache.cayenne.jpa.map.JpaEntityMap;
 
 public class EntityMapDefaultsProcessorTest extends TestCase {
 
-    public void testMissingAttributeAnnotation() {
+    protected JpaEntity entity;
+    protected JpaLoaderContext context;
 
+    @Override
+    protected void setUp() throws Exception {
         // sanity check - test object must not be serializable to be rejected...
         assertFalse(Serializable.class.isAssignableFrom(MockAnnotatedBean3.class));
 
         JpaEntityMap map = new JpaEntityMap();
-        JpaLoaderContext context = new JpaLoaderContext();
+        context = new JpaLoaderContext();
         EntityMapAnnotationLoader loader = new EntityMapAnnotationLoader(context);
+        loader.loadClassMapping(map, MockAnnotatedBean1.class);
         loader.loadClassMapping(map, MockAnnotatedBean3.class);
 
         // apply defaults
@@ -39,10 +44,51 @@
                 context);
         defaultsProcessor.applyDefaults(map);
 
-        assertEquals(1, map.getEntities().size());
-        JpaEntity entity = map.getEntities().iterator().next();
-        assertEquals(1, entity.getAttributes().size());
+        entity = map.entityForClass(MockAnnotatedBean3.class);
+        assertNotNull(entity);
+    }
+
+    public void testMissingAttributeAnnotation() throws Exception {
 
         assertTrue(context.getConflicts().hasFailures());
+
+        assertTrue(context.getConflicts().getFailures(
+                MockAnnotatedBean3.class.getDeclaredField("attribute1")).isEmpty());
+
+        assertFalse(context.getConflicts().getFailures(
+                MockAnnotatedBean3.class.getDeclaredField("attribute2")).isEmpty());
+
+        assertNotNull(entity.attributeForName("attribute1"));
+        assertNull(entity.attributeForName("attribute2"));
+    }
+
+    public void testTargetEntityNameToOne() {
+        JpaAttribute toBean2 = entity.attributeForName("toBean2");
+        assertNotNull(toBean2);
+        assertNotNull(toBean2.getManyToOne());
+        assertEquals(MockAnnotatedBean1.class.getName(), toBean2
+                .getManyToOne()
+                .getTargetEntityName());
+    }
+
+    public void testTargetEntityNameCollection() throws Exception {
+
+        assertTrue(context.getConflicts().getFailures(
+                MockAnnotatedBean3.class.getDeclaredField("toBean2s1")).isEmpty());
+        JpaAttribute toBean2s1 = entity.attributeForName("toBean2s1");
+        assertNotNull(toBean2s1);
+
+        assertNotNull(toBean2s1.getOneToMany());
+        assertEquals(MockAnnotatedBean1.class.getName(), toBean2s1
+                .getOneToMany()
+                .getTargetEntityName());
+
+        assertFalse("Expected failure", context.getConflicts().getFailures(
+                MockAnnotatedBean3.class.getDeclaredField("toBean2s2")).isEmpty());
+        JpaAttribute toBean2s2 = entity.attributeForName("toBean2s2");
+        assertNotNull(toBean2s2);
+
+        assertNotNull(toBean2s2.getOneToMany());
+        assertNull(toBean2s2.getOneToMany().getTargetEntityName());
     }
 }

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean1.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean1.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean1.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean1.java Sun Apr 30 12:20:16 2006
@@ -16,6 +16,7 @@
 package org.apache.cayenne.jpa.conf;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.IdClass;
 import javax.persistence.NamedQuery;
 
@@ -26,4 +27,6 @@
 @Entity
 public class MockAnnotatedBean1 {
 
+    @Id
+    int id;
 }

Modified: incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean3.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean3.java?rev=398407&r1=398406&r2=398407&view=diff
==============================================================================
--- incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean3.java (original)
+++ incubator/cayenne/jpa/trunk/cayenne-jpa/src/test/java/org/apache/cayenne/jpa/conf/MockAnnotatedBean3.java Sun Apr 30 12:20:16 2006
@@ -15,8 +15,12 @@
  */
 package org.apache.cayenne.jpa.conf;
 
+import java.util.Collection;
+
 import javax.persistence.Basic;
 import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
 
 @Entity
 public class MockAnnotatedBean3 {
@@ -26,4 +30,14 @@
 
     // no annotation here should result in a conflict.
     protected MockAnnotatedBean1 attribute2;
+
+    @ManyToOne
+    protected MockAnnotatedBean1 toBean2;
+
+    @OneToMany
+    protected Collection<MockAnnotatedBean1> toBean2s1;
+
+    @OneToMany
+    // no collection type - must result in a failure
+    protected Collection toBean2s2;
 }