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 2008/05/13 16:47:55 UTC

svn commit: r655887 - in /cayenne/main/trunk: docs/doc/src/main/resources/ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/

Author: aadamchik
Date: Tue May 13 07:47:54 2008
New Revision: 655887

URL: http://svn.apache.org/viewvc?rev=655887&view=rev
Log:
CAY-1046 Make PK metadata available via Obj* API.

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/SyntheticPKObjAttribute.java
Modified:
    cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ClientObjEntity.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjAttribute.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java

Modified: cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=655887&r1=655886&r2=655887&view=diff
==============================================================================
--- cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt Tue May 13 07:47:54 2008
@@ -38,6 +38,7 @@
 CAY-1033 remove completed merge tokens from view in cayenne modeler
 CAY-1035 Replace QueryMetadata String cache policies with an enum
 CAY-1038 Upgrade to Ashwood 2.0
+CAY-1046 Make PK metadata available via Obj* API.
 CAY-1048 Deprecate but preserve functionality of QueryMetadata.isRefreshingObjects() 
 CAY-1049 Refactor QueryAssembler/SelectTranslator
 CAY-1050 MySQLSniffer should configure created adapter to use MySQL default engine for tables

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ClientObjEntity.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ClientObjEntity.java?rev=655887&r1=655886&r2=655887&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ClientObjEntity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ClientObjEntity.java Tue May 13 07:47:54 2008
@@ -19,34 +19,41 @@
 
 package org.apache.cayenne.map;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 
 /**
- * A client version of ObjEntity that delegates some of its method calls to
- * its corresponding server entity.
- *
+ * A client version of ObjEntity that overrides server entity algorithms for accessing
+ * some pieces of information
+ * 
  * @since 3.0
  * @author Kevin Menard
  */
-public class ClientObjEntity extends ObjEntity {
+class ClientObjEntity extends ObjEntity {
 
-    private Collection<String> primaryKeyNames;
+    private Collection<ObjAttribute> primaryKeys;
 
-    public ClientObjEntity() {
-        super();
-    }
-
-    public ClientObjEntity(final String name) {
+    ClientObjEntity(String name) {
         super(name);
+        this.primaryKeys = Collections.<ObjAttribute> emptyList();
     }
 
     @Override
     public Collection<String> getPrimaryKeyNames() {
-        return Collections.unmodifiableCollection(primaryKeyNames);
+        Collection<String> names = new ArrayList<String>(primaryKeys.size());
+        for (ObjAttribute attribute : primaryKeys) {
+            names.add(attribute.getName());
+        }
+        return Collections.unmodifiableCollection(names);
+    }
+
+    @Override
+    public Collection<ObjAttribute> getPrimaryKeys() {
+        return Collections.unmodifiableCollection(primaryKeys);
     }
 
-    public void setPrimaryKeyNames(final Collection<String> primaryKeyNames) {
-        this.primaryKeyNames = primaryKeyNames;
+    void setPrimaryKeys(Collection<ObjAttribute> primaryKeys) {
+        this.primaryKeys = primaryKeys;
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjAttribute.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjAttribute.java?rev=655887&r1=655886&r2=655887&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjAttribute.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjAttribute.java Tue May 13 07:47:54 2008
@@ -258,6 +258,12 @@
 
         DbAttribute dbAttribute = getDbAttribute();
         if (dbAttribute != null) {
+            
+            // expose PK attribute names - the client may need those to build ObjectIds
+            if (dbAttribute.isPrimaryKey()) {
+                attribute.setDbAttributePath(dbAttribute.getName());
+            }
+
             attribute.setMandatory(dbAttribute.isMandatory());
             attribute.setMaxLength(dbAttribute.getMaxLength());
         }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java?rev=655887&r1=655886&r2=655887&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java Tue May 13 07:47:54 2008
@@ -30,6 +30,7 @@
 import java.util.TreeMap;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionException;
 import org.apache.cayenne.exp.ExpressionFactory;
@@ -38,6 +39,7 @@
 import org.apache.cayenne.map.event.ObjEntityListener;
 import org.apache.cayenne.map.event.RelationshipEvent;
 import org.apache.cayenne.util.CayenneMapEntry;
+import org.apache.cayenne.util.NameConverter;
 import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.commons.collections.Transformer;
@@ -189,17 +191,32 @@
         entity.setClassName(getClientClassName());
         entity.setSuperClassName(getClientSuperClassName());
         entity.setSuperEntityName(getSuperEntityName());
-        entity.setPrimaryKeyNames(getPrimaryKeyNames());
 
         // TODO: should we also copy lock type?
 
-        // copy attributes
-        for (Attribute attribute : getDeclaredAttributes()) {
-            entity.addAttribute(((ObjAttribute) attribute).getClientAttribute());
+        Collection<ObjAttribute> primaryKeys = getMutablePrimaryKeys();
+        Collection<ObjAttribute> clientPK = new ArrayList<ObjAttribute>(primaryKeys
+                .size());
+
+        for (ObjAttribute attribute : getDeclaredAttributes()) {
+            ObjAttribute clientAttribute = attribute.getClientAttribute();
+            entity.addAttribute(clientAttribute);
+
+            if (primaryKeys.remove(attribute)) {
+                clientPK.add(clientAttribute);
+            }
+        }
+
+        // after all meaningful pks got removed, here we only have synthetic pks left...
+        for (ObjAttribute attribute : primaryKeys) {
+            ObjAttribute clientAttribute = attribute.getClientAttribute();
+            clientPK.add(clientAttribute);
         }
 
+        entity.setPrimaryKeys(clientPK);
+
         // copy relationships; skip runtime generated relationships
-        for (Relationship relationship : getDeclaredRelationships()) {
+        for (ObjRelationship relationship : getDeclaredRelationships()) {
             if (relationship.isRuntime()) {
                 continue;
             }
@@ -211,8 +228,7 @@
                 continue;
             }
 
-            entity.addRelationship(((ObjRelationship) relationship)
-                    .getClientRelationship());
+            entity.addRelationship(relationship.getClientRelationship());
         }
 
         // TODO: andrus 2/5/2007 - copy embeddables
@@ -571,6 +587,46 @@
     }
 
     /**
+     * Returns an unmodifiable collection of ObjAttributes representing the primary key of
+     * the table described by this DbEntity. Note that since PK is very often not an
+     * object property, the returned collection may contain "synthetic" ObjAttributes that
+     * are created on the fly and are not a part of ObjEntity and will not be a part of
+     * entity.getAttributes(). Real meaningful PK attributes
+     * 
+     * @since 3.0
+     */
+    public Collection<ObjAttribute> getPrimaryKeys() {
+        return Collections.unmodifiableCollection(getMutablePrimaryKeys());
+    }
+
+    private Collection<ObjAttribute> getMutablePrimaryKeys() {
+        if (getDbEntity() == null) {
+            throw new CayenneRuntimeException("No DbEntity for ObjEntity: " + getName());
+        }
+
+        Collection<DbAttribute> pkAttributes = getDbEntity().getPrimaryKeys();
+        Collection<ObjAttribute> attributes = new ArrayList<ObjAttribute>(pkAttributes
+                .size());
+
+        for (DbAttribute pk : pkAttributes) {
+            ObjAttribute attribute = getAttributeForDbAttribute(pk);
+
+            // create synthetic attribute
+            if (attribute == null) {
+                attribute = new SyntheticPKObjAttribute(NameConverter.underscoredToJava(
+                        pk.getName(),
+                        false));
+                attribute.setDbAttributePath(pk.getName());
+                attribute.setType(TypesMapping.getJavaBySqlType(pk.getType()));
+            }
+
+            attributes.add(attribute);
+        }
+
+        return attributes;
+    }
+
+    /**
      * Returns a named attribute that either belongs to this ObjEntity or is inherited.
      * Returns null if no matching attribute is found.
      */
@@ -736,19 +792,22 @@
         return null;
     }
 
+    /**
+     * @since 3.0
+     */
     public Collection<String> getPrimaryKeyNames() {
         if (getDbEntity() == null) {
             throw new CayenneRuntimeException("No DbEntity for ObjEntity: " + getName());
         }
 
         Collection<DbAttribute> pkAttributes = getDbEntity().getPrimaryKeys();
-        Collection<String> ret = new ArrayList<String>(pkAttributes.size());
+        Collection<String> names = new ArrayList<String>(pkAttributes.size());
 
         for (DbAttribute pk : pkAttributes) {
-            ret.add(pk.getName());
+            names.add(pk.getName());
         }
 
-        return Collections.unmodifiableCollection(ret);
+        return Collections.unmodifiableCollection(names);
     }
 
     /**
@@ -829,7 +888,7 @@
 
         return (superEntity != null) ? superEntity.isSubentityOf(entity) : false;
     }
-    
+
     /**
      * @since 3.0
      */

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/SyntheticPKObjAttribute.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/SyntheticPKObjAttribute.java?rev=655887&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/SyntheticPKObjAttribute.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/SyntheticPKObjAttribute.java Tue May 13 07:47:54 2008
@@ -0,0 +1,52 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.map;
+
+
+/**
+ * A "synthetic" server-side ObjAttribute used to describe unmapped PK>.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+class SyntheticPKObjAttribute extends ObjAttribute {
+
+    SyntheticPKObjAttribute(String name) {
+        super(name);
+    }
+
+    @Override
+    public ObjAttribute getClientAttribute() {
+        ClientObjAttribute attribute = new ClientObjAttribute(getName());
+        attribute.setType(getType());
+
+        // unconditionally expose DbAttribute path and configure as mandatory.
+        attribute.setDbAttributePath(dbAttributePath);
+        attribute.setMandatory(true);
+
+        DbAttribute dbAttribute = getDbAttribute();
+        if (dbAttribute != null) {
+            attribute.setMaxLength(dbAttribute.getMaxLength());
+        }
+
+        // TODO: will likely need "userForLocking" property as well.
+
+        return attribute;
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java?rev=655887&r1=655886&r2=655887&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java Tue May 13 07:47:54 2008
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.map;
 
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -32,6 +33,44 @@
 
 public class ObjEntityTest extends CayenneCase {
 
+    public void testGetPrimaryKeys() {
+        ObjEntity artistE = getObjEntity("Artist");
+        Collection<ObjAttribute> pks = artistE.getPrimaryKeys();
+        assertEquals(1, pks.size());
+
+        ObjAttribute pk = pks.iterator().next();
+        assertEquals("java.lang.Long", pk.getType());
+        assertEquals("ARTIST_ID", pk.getDbAttributePath());
+        assertEquals("artistId", pk.getName());
+        assertNull(pk.getEntity());
+        assertFalse(artistE.getAttributes().contains(pk));
+
+        ObjEntity clientArtistE = artistE.getClientEntity();
+        Collection<ObjAttribute> clientpks = clientArtistE.getPrimaryKeys();
+        assertEquals(1, clientpks.size());
+        ObjAttribute clientPk = clientpks.iterator().next();
+        assertEquals("java.lang.Long", clientPk.getType());
+        assertEquals("ARTIST_ID", clientPk.getDbAttributePath());
+        assertEquals("artistId", clientPk.getName());
+        assertNull(clientPk.getEntity());
+        assertFalse(clientArtistE.getAttributes().contains(pk));
+
+        ObjEntity meaningfulPKE = getObjEntity("MeaningfulPKTest1");
+        Collection<ObjAttribute> mpks = meaningfulPKE.getPrimaryKeys();
+        assertEquals(1, mpks.size());
+
+        ObjAttribute mpk = mpks.iterator().next();
+        assertTrue(meaningfulPKE.getAttributes().contains(mpk));
+        
+        ObjEntity clientMeaningfulPKE = meaningfulPKE.getClientEntity();
+        Collection<ObjAttribute> clientmpks = clientMeaningfulPKE.getPrimaryKeys();
+        assertEquals(1, clientmpks.size());
+
+        ObjAttribute clientmpk = clientmpks.iterator().next();
+        assertEquals("java.lang.Integer", clientmpk.getType());
+        assertTrue(clientMeaningfulPKE.getAttributes().contains(clientmpk));
+    }
+
     /**
      * @deprecated since 3.0 as the method being tested is deprecated.
      */