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 2007/12/16 23:19:41 UTC

svn commit: r604721 - in /cayenne/main/trunk/framework: cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/ cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/r...

Author: aadamchik
Date: Sun Dec 16 14:19:40 2007
New Revision: 604721

URL: http://svn.apache.org/viewvc?rev=604721&view=rev
Log:
CAY-734 Link JPA Embeddable and Embedded annotations with Cayenne runtime
(first cut of the Embeddable enhancer)

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EmbeddableVisitor.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/CayenneEnhancerVisitorFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EnhancementHelper.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/FieldAccessor.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/enhancer/JpaEnhancerVisitorFactory.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntityMap.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/CayenneEnhancerVisitorFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/CayenneEnhancerVisitorFactory.java?rev=604721&r1=604720&r2=604721&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/CayenneEnhancerVisitorFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/CayenneEnhancerVisitorFactory.java Sun Dec 16 14:19:40 2007
@@ -21,6 +21,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.map.ObjEntity;
 import org.objectweb.asm.ClassVisitor;
@@ -35,6 +36,7 @@
 public class CayenneEnhancerVisitorFactory implements EnhancerVisitorFactory {
 
     protected Map<String, ObjEntity> entitiesByClass;
+    protected Map<String, Embeddable> embeddablesByClass;
 
     public CayenneEnhancerVisitorFactory(EntityResolver entityResolver) {
         indexEntities(entityResolver);
@@ -46,25 +48,47 @@
         // manually
 
         this.entitiesByClass = new HashMap<String, ObjEntity>();
-        for (Object object : entityResolver.getObjEntities()) {
-            ObjEntity entity = (ObjEntity) object;
+        for (ObjEntity entity : entityResolver.getObjEntities()) {
             entitiesByClass.put(entity.getClassName(), entity);
         }
+
+        this.embeddablesByClass = new HashMap<String, Embeddable>();
+        for (Embeddable embeddable : entityResolver.getEmbeddables()) {
+            embeddablesByClass.put(embeddable.getClassName(), embeddable);
+        }
     }
 
     public ClassVisitor createVisitor(String className, ClassVisitor out) {
-        ObjEntity entity = entitiesByClass.get(className.replace('/', '.'));
-        if (entity == null) {
-            return null;
+        String key = className.replace('/', '.');
+
+        ObjEntity entity = entitiesByClass.get(key);
+        if (entity != null) {
+
+            // create enhancer chain
+            PersistentInterfaceVisitor e1 = new PersistentInterfaceVisitor(out);
+            PersistentAccessorVisitor e2 = new PersistentAccessorVisitor(e1, entity);
+
+            // this ensures that both enhanced and original classes have compatible
+            // serialized
+            // format even if no serialVersionUID is defined by the user
+            SerialVersionUIDAdder e3 = new SerialVersionUIDAdder(e2);
+            return e3;
+        }
+
+        Embeddable embeddable = embeddablesByClass.get(key);
+        if (embeddable != null) {
+            // create enhancer chain
+            EmbeddableVisitor e1 = new EmbeddableVisitor(out);
+
+            // TODO: andrus 12/16/2007 - setter visitor...
+
+            // this ensures that both enhanced and original classes have compatible
+            // serialized
+            // format even if no serialVersionUID is defined by the user
+            SerialVersionUIDAdder e2 = new SerialVersionUIDAdder(e1);
+            return e2;
         }
 
-        // create enhancer chain
-        PersistentInterfaceVisitor e1 = new PersistentInterfaceVisitor(out);
-        PersistentAccessorVisitor e2 = new PersistentAccessorVisitor(e1, entity);
-
-        // this ensures that both enhanced and original classes have compatible serialized
-        // format even if no serialVersionUID is defined by the user
-        SerialVersionUIDAdder e3 = new SerialVersionUIDAdder(e2);
-        return e3;
+        return null;
     }
 }

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EmbeddableVisitor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EmbeddableVisitor.java?rev=604721&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EmbeddableVisitor.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EmbeddableVisitor.java Sun Dec 16 14:19:40 2007
@@ -0,0 +1,46 @@
+/*****************************************************************
+ *   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.enhancer;
+
+import org.apache.cayenne.Persistent;
+import org.objectweb.asm.ClassAdapter;
+import org.objectweb.asm.ClassVisitor;
+
+/**
+ * Enhances classes passed through the visitor to add embeddable fields and methods needed
+ * by Cayenne.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class EmbeddableVisitor extends ClassAdapter {
+
+    protected EnhancementHelper helper;
+
+    public EmbeddableVisitor(ClassVisitor visitor) {
+        super(visitor);
+        this.helper = new EnhancementHelper(this);
+    }
+
+    @Override
+    public void visitEnd() {
+        helper.createProperty(Persistent.class, "owner");
+        helper.createProperty(String.class, "embeddedProperty");
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EnhancementHelper.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EnhancementHelper.java?rev=604721&r1=604720&r2=604721&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EnhancementHelper.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/enhancer/EnhancementHelper.java Sun Dec 16 14:19:40 2007
@@ -63,7 +63,7 @@
         this.currentClass = Type.getType("L" + className + ";");
     }
 
-    public String[] addInterface(String[] interfaces, Class newInterface) {
+    public String[] addInterface(String[] interfaces, Class<?> newInterface) {
 
         String name = Type.getInternalName(newInterface);
         if (interfaces == null || interfaces.length == 0) {
@@ -83,7 +83,7 @@
      * Creates a new protected field in the current class. Field name will be
      * automatically prefixed by "$cay_".
      */
-    public void createField(Class fieldType, String name) {
+    public void createField(Class<?> fieldType, String name) {
         createField(fieldType, name, false);
     }
 
@@ -91,7 +91,7 @@
      * Creates a new protected field in the current class. Field name will be
      * automatically prefixed by "$cay_".
      */
-    public void createField(Class fieldType, String name, boolean isTransient) {
+    public void createField(Class<?> fieldType, String name, boolean isTransient) {
         Type asmType = Type.getType(fieldType);
         int access = Opcodes.ACC_PROTECTED;
         if (isTransient) {
@@ -101,11 +101,11 @@
         createField(name, asmType, access);
     }
 
-    public void createProperty(Class propertyType, String name) {
+    public void createProperty(Class<?> propertyType, String name) {
         createProperty(propertyType, name, false);
     }
 
-    public void createProperty(Class propertyType, String name, boolean isTransient) {
+    public void createProperty(Class<?> propertyType, String name, boolean isTransient) {
         Type asmType = Type.getType(propertyType);
 
         int access = Opcodes.ACC_PROTECTED;

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java?rev=604721&r1=604720&r2=604721&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java Sun Dec 16 14:19:40 2007
@@ -273,6 +273,18 @@
 
         return c;
     }
+    
+    /**
+     * @since 3.0
+     */
+    public Collection<Embeddable> getEmbeddables() {
+        CompositeCollection c = new CompositeCollection();
+        for (DataMap map : getDataMaps()) {
+            c.addComposited(map.getEmbeddables());
+        }
+
+        return c;
+    }
 
     public Collection<Procedure> getProcedures() {
         CompositeCollection c = new CompositeCollection();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/FieldAccessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/FieldAccessor.java?rev=604721&r1=604720&r2=604721&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/FieldAccessor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/FieldAccessor.java Sun Dec 16 14:19:40 2007
@@ -36,7 +36,7 @@
     protected Field field;
     protected Object nullValue;
 
-    public FieldAccessor(Class objectClass, String propertyName, Class propertyType) {
+    public FieldAccessor(Class<?> objectClass, String propertyName, Class<?> propertyType) {
         // sanity check
         if (objectClass == null) {
             throw new IllegalArgumentException("Null objectClass");
@@ -93,7 +93,7 @@
      * Finds a field for the property, ensuring that direct access via reflection is
      * possible.
      */
-    protected Field prepareField(Class beanClass, String propertyName, Class propertyType) {
+    protected Field prepareField(Class<?> beanClass, String propertyName, Class<?> propertyType) {
         Field field;
 
         // locate field
@@ -144,7 +144,7 @@
     /**
      * Recursively looks for a named field in a class hierarchy.
      */
-    protected Field lookupFieldInHierarchy(Class beanClass, String fieldName)
+    protected Field lookupFieldInHierarchy(Class<?> beanClass, String fieldName)
             throws SecurityException, NoSuchFieldException {
 
         // TODO: support property names following other common naming patterns, such as
@@ -155,7 +155,7 @@
         }
         catch (NoSuchFieldException e) {
 
-            Class superClass = beanClass.getSuperclass();
+            Class<?> superClass = beanClass.getSuperclass();
             if (superClass == null || superClass.getName().equals(Object.class.getName())) {
                 throw e;
             }

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java?rev=604721&r1=604720&r2=604721&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java Sun Dec 16 14:19:40 2007
@@ -203,7 +203,7 @@
     public synchronized EntityManagerFactory createContainerEntityManagerFactory(
             PersistenceUnitInfo unit,
             Map map) {
-        
+
         if (logger.isInfoEnabled() && map != null) {
             logger.info("Extra container PersistenceUnitInfo properties: " + map);
         }
@@ -235,11 +235,11 @@
 
             // add transformer before DataMapConverter starts loading the classes via app
             // class loader
+            ClassFileTransformer enhancer = new Enhancer(new JpaEnhancerVisitorFactory(
+                    loader.getEntityMap()));
             Map<String, JpaClassDescriptor> managedClasses = loader
                     .getEntityMap()
                     .getMangedClasses();
-            ClassFileTransformer enhancer = new Enhancer(new JpaEnhancerVisitorFactory(
-                    managedClasses));
             unit.addTransformer(new UnitClassTransformer(managedClasses, loader
                     .getContext()
                     .getTempClassLoader(), enhancer));
@@ -327,16 +327,16 @@
      */
     protected void loadSchema(DataSource dataSource, DbAdapter adapter, DataMap map) {
 
-        Collection tables = map.getDbEntities();
+        Collection<DbEntity> tables = map.getDbEntities();
         if (tables.isEmpty()) {
             return;
         }
 
-        // sniff a first table precense
+        // sniff a first table presence
 
         // TODO: andrus 9/1/2006 - should we make this check a part of DbGenerator (and
         // query - a part of DbAdapter)?
-        DbEntity table = (DbEntity) tables.iterator().next();
+        DbEntity table = tables.iterator().next();
 
         try {
             Connection c = dataSource.getConnection();

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/enhancer/JpaEnhancerVisitorFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/enhancer/JpaEnhancerVisitorFactory.java?rev=604721&r1=604720&r2=604721&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/enhancer/JpaEnhancerVisitorFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/enhancer/JpaEnhancerVisitorFactory.java Sun Dec 16 14:19:40 2007
@@ -18,11 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.jpa.enhancer;
 
-import java.util.Map;
-
+import org.apache.cayenne.enhancer.EmbeddableVisitor;
 import org.apache.cayenne.enhancer.EnhancerVisitorFactory;
 import org.apache.cayenne.enhancer.PersistentInterfaceVisitor;
-import org.apache.cayenne.jpa.map.JpaClassDescriptor;
+import org.apache.cayenne.jpa.map.JpaEmbeddable;
+import org.apache.cayenne.jpa.map.JpaEntity;
+import org.apache.cayenne.jpa.map.JpaEntityMap;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.commons.SerialVersionUIDAdder;
 
@@ -33,29 +34,46 @@
  */
 public class JpaEnhancerVisitorFactory implements EnhancerVisitorFactory {
 
-    private Map<String, JpaClassDescriptor> managedClasses;
+    private JpaEntityMap entityMap;
 
-    public JpaEnhancerVisitorFactory(Map<String, JpaClassDescriptor> managedClasses) {
-        this.managedClasses = managedClasses;
+    public JpaEnhancerVisitorFactory(JpaEntityMap entityMap) {
+        this.entityMap = entityMap;
     }
 
     public ClassVisitor createVisitor(String className, ClassVisitor out) {
-        JpaClassDescriptor descriptor = managedClasses.get(className.replace('/', '.'));
-        if (descriptor == null) {
-            return null;
-        }
 
-        // from here the code is copied essentially verbatim
-        // from CayenneEnhancerVisitorFactory.
+        String key = className.replace('/', '.');
+
+        JpaEntity entity = entityMap.entityForClass(key);
+        if (entity != null) {
+
+            // create enhancer chain
+            PersistentInterfaceVisitor e1 = new PersistentInterfaceVisitor(out);
+            JpaAccessorVisitor e2 = new JpaAccessorVisitor(e1, entity
+                    .getClassDescriptor());
+
+            // this ensures that both enhanced and original classes have compatible
+            // serialized
+            // format even if no serialVersionUID is defined by the user
+            SerialVersionUIDAdder e3 = new SerialVersionUIDAdder(e2);
 
-        // create enhancer chain
-        PersistentInterfaceVisitor e1 = new PersistentInterfaceVisitor(out);
-        JpaAccessorVisitor e2 = new JpaAccessorVisitor(e1, descriptor);
-
-        // this ensures that both enhanced and original classes have compatible serialized
-        // format even if no serialVersionUID is defined by the user
-        SerialVersionUIDAdder e3 = new SerialVersionUIDAdder(e2);
+            return e3;
+        }
+
+        JpaEmbeddable embeddable = entityMap.embeddableForClass(key);
+        if (embeddable != null) {
+            // create enhancer chain
+            EmbeddableVisitor e1 = new EmbeddableVisitor(out);
+
+            // TODO: andrus 12/16/2007 - setter visitor...
+
+            // this ensures that both enhanced and original classes have compatible
+            // serialized
+            // format even if no serialVersionUID is defined by the user
+            SerialVersionUIDAdder e2 = new SerialVersionUIDAdder(e1);
+            return e2;
+        }
 
-        return e3;
+        return null;
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntityMap.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntityMap.java?rev=604721&r1=604720&r2=604721&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntityMap.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntityMap.java Sun Dec 16 14:19:40 2007
@@ -173,16 +173,12 @@
 
         if (entities != null) {
             for (JpaEntity object : entities) {
-                // TODO: andrus, 5/1/2006 - need not enhance entities extending mapped
-                // superclasses
                 managedClasses.put(object.getClassName(), object.getClassDescriptor());
             }
         }
 
         if (embeddables != null) {
             for (JpaEmbeddable object : embeddables) {
-                // TODO: andrus, 5/1/2006 - need not enhance entities extending mapped
-                // superclasses
                 managedClasses.put(object.getClassName(), object.getClassDescriptor());
             }
         }
@@ -193,7 +189,7 @@
     /**
      * Returns a JpaEntity describing a given persistent class.
      */
-    public JpaEntity entityForClass(Class entityClass) {
+    public JpaEntity entityForClass(Class<?> entityClass) {
 
         if (entityClass == null) {
             throw new IllegalArgumentException("Null entity class");
@@ -209,6 +205,10 @@
         if (entityClassName == null) {
             throw new IllegalArgumentException("Null entity class name");
         }
+        
+        if(entities == null) {
+            return null;
+        }
 
         for (JpaEntity entity : entities) {
             if (entityClassName.equals(entity.getClassName())) {
@@ -218,6 +218,40 @@
 
         return null;
     }
+    
+    /**
+     * Returns a JpaEmbeddable describing a given embeddable class.
+     */
+    public JpaEmbeddable embeddableForClass(Class<?> embeddableClass) {
+
+        if (embeddableClass == null) {
+            throw new IllegalArgumentException("Null embeddable class");
+        }
+
+        return embeddableForClass(embeddableClass.getName());
+    }
+    
+    /**
+     * Returns a JpaEmbeddable describing a given embeddable class.
+     */
+    public JpaEmbeddable embeddableForClass(String embeddableClassName) {
+        if (embeddableClassName == null) {
+            throw new IllegalArgumentException("Null embeddable class name");
+        }
+        
+        if(embeddables == null) {
+            return null;
+        }
+
+        for (JpaEmbeddable embeddable : embeddables) {
+            if (embeddableClassName.equals(embeddable.getClassName())) {
+                return embeddable;
+            }
+        }
+
+        return null;
+    }
+
 
     public AccessType getAccess() {
         return access;