You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by jr...@apache.org on 2009/06/12 04:40:14 UTC

svn commit: r783966 - in /openjpa/trunk: openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attr...

Author: jrbauer
Date: Fri Jun 12 02:40:14 2009
New Revision: 783966

URL: http://svn.apache.org/viewvc?rev=783966&view=rev
Log:
OPENJPA-1135 Apply overrides to deferred embeddable attributes

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEmbedXML.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEntityXML.java   (with props)
Modified:
    openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
    openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java
    openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/TestAttrOverridesXml.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/embed-orm.xml
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java

Modified: openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java?rev=783966&r1=783965&r2=783966&view=diff
==============================================================================
--- openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java (original)
+++ openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java Fri Jun 12 02:40:14 2009
@@ -525,6 +525,7 @@
         if (_log != null && _log.isTraceEnabled())
             _log.trace(_loc.get("end-parse", getSourceName()));
         _results = new ArrayList(_curResults);
+        clearDeferredMetaData();
     }
 
     /**
@@ -679,4 +680,7 @@
         e.initCause(cause);
         return e;
     }
+
+    protected void clearDeferredMetaData() {
+    }
 }

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java?rev=783966&r1=783965&r2=783966&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java Fri Jun 12 02:40:14 2009
@@ -1297,9 +1297,14 @@
                 parseColumns(efm, attr.column());
         }
     }
-    
+
     public static FieldMapping getEmbeddedFieldMapping(FieldMapping fm,
-            String attrName) {
+        String attrName) {
+        return getEmbeddedFieldMapping(fm, attrName, true);
+    }
+
+    public static FieldMapping getEmbeddedFieldMapping(FieldMapping fm,
+            String attrName, boolean mustExist) {
         ClassMapping embed = null;
         boolean isKey = false;
         boolean isValue = false;
@@ -1323,31 +1328,83 @@
                     throw new MetaDataException(_loc.get("embed-override-name",
                         fm, attrName));
                 if (isKey) 
-                    embed = getEmbeddedMapping(fm.getKeyMapping());
+                    embed = getEmbeddedMapping(fm.getKeyMapping(), mustExist);
                 else if (isValue)     
-                    embed = getEmbeddedMapping(fm.getElementMapping());
+                    embed = getEmbeddedMapping(fm.getElementMapping(), 
+                        mustExist);
                 break;
             default: // an embeddable
                 if (isKey || isValue)
                     throw new MetaDataException(_loc.get("embed-override-name",
                         fm, attrName));
-                embed = getEmbeddedMapping(fm.getValueMapping());
+                embed = getEmbeddedMapping(fm.getValueMapping(), mustExist);
                 break;
         }
         
-        if (embed == null) 
-            throw new MetaDataException(_loc.get("not-embedded", fm));
+        if (embed == null) {
+            if (mustExist)
+                throw new MetaDataException(_loc.get("not-embedded", fm));
+            return null;
+        }
         return getAttributeOverrideField(attrName, fm, embed);
     }
-    
-    public static ClassMapping getEmbeddedMapping(ValueMapping val) {
+
+    public static Class<?> getEmbeddedClassType(FieldMapping fm,
+        String attrName) {
+        ValueMapping embed = null;
+        boolean isKey = false;
+        boolean isValue = false;
+        if (attrName != null && attrName.startsWith("key."))
+            isKey = true;
+        else if (attrName != null && attrName.startsWith("value."))
+            isValue = true;
+        if (isKey || isValue)
+            attrName = attrName.substring(attrName.indexOf(".")+1);
+            
+        int typeCode = fm.getValue().getDeclaredTypeCode();
+        switch (typeCode) {
+            case JavaTypes.COLLECTION : // a collection of embeddables
+                if (isKey || isValue)
+                    throw new MetaDataException(_loc.get("embed-override-name",
+                        fm, attrName));
+                embed = fm.getElementMapping();
+                break;
+            case JavaTypes.MAP: // a map
+                if (!isKey && !isValue)
+                    throw new MetaDataException(_loc.get("embed-override-name",
+                        fm, attrName));
+                if (isKey) 
+                    embed = fm.getKeyMapping();
+                else if (isValue)     
+                    embed = fm.getElementMapping();
+                break;
+            default: // an embeddable
+                if (isKey || isValue)
+                    throw new MetaDataException(_loc.get("embed-override-name",
+                        fm, attrName));
+                embed = fm.getValueMapping();
+                break;
+        }
+        
+        if (embed == null) {
+            throw new MetaDataException(_loc.get("not-embedded", fm));
+        }
+        return embed.getDeclaredType();
+    }
+
+    public static ClassMapping getEmbeddedMapping(ValueMapping val, boolean 
+        createNew) {
         ClassMapping embed = val.getEmbeddedMapping();
-        if (embed != null) 
+        if (embed != null || !createNew) 
             return embed;
-        
+
         val.addEmbeddedMetaData();
         return val.getEmbeddedMapping();
+    }
 
+    
+    public static ClassMapping getEmbeddedMapping(ValueMapping val) {
+        return getEmbeddedMapping(val, true);
     }
     
     public static FieldMapping getAttributeOverrideField(String attrName,

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java?rev=783966&r1=783965&r2=783966&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java Fri Jun 12 02:40:14 2009
@@ -56,8 +56,11 @@
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.meta.MetaDataContext;
+import org.apache.openjpa.meta.ValueMetaData;
 import org.apache.openjpa.persistence.XMLPersistenceMetaDataParser;
 import org.apache.openjpa.util.InternalException;
+import org.apache.openjpa.util.MetaDataException;
 import org.xml.sax.Attributes;
 import org.xml.sax.Locator;
 import org.xml.sax.SAXException;
@@ -123,6 +126,10 @@
     private Column _discCol;
     private int _resultIdx = 0;
 
+    private final Map<Class<?>, ArrayList<DeferredEmbeddableOverrides>> 
+        _deferredMappings = new HashMap<Class<?>, 
+             ArrayList<DeferredEmbeddableOverrides>>();
+
     /**
      * Constructor; supply configuration.
      */
@@ -655,9 +662,13 @@
      * Set unique for field.
      */
     private void setUnique(FieldMapping fm) {
-        if (_unique.size() == 2) // i.e. TRUE & FALSE
+        setUnique(fm, _unique);
+    }
+
+    private void setUnique(FieldMapping fm, EnumSet<UniqueFlag> unique) {
+        if (unique.size() == 2) // i.e. TRUE & FALSE
             getLog().warn(_loc.get("inconsist-col-attrs", fm));
-        else if (_unique.contains(UniqueFlag.TRUE))
+        else if (unique.contains(UniqueFlag.TRUE))
             fm.getValueInfo().setUnique(new Unique());
     }
 
@@ -690,9 +701,23 @@
         FieldMapping fm = null;
         if (elem instanceof ClassMapping)
             fm = getAttributeOverride((ClassMapping) elem);
-        else
-            fm = getAttributeOverrideForEmbeddable((FieldMapping) elem);
-        if (_cols != null) {
+        else {
+            FieldMapping basefm = (FieldMapping) elem;
+            
+            fm = getAttributeOverrideForEmbeddable(basefm, _override, false);
+            if (fm == null) {
+                DeferredEmbeddableOverrides dfm = 
+                    getDeferredFieldMappingInfo(
+                        AnnotationPersistenceMappingParser.
+                        getEmbeddedClassType(basefm, _override),
+                        basefm, _override, true);
+                dfm._defCols = _cols;
+                dfm._defTable = _colTable;
+                dfm._attrName = _override;
+                dfm._unique = _unique;
+            }
+        }
+        if (fm != null && _cols != null) {
             fm.getValueInfo().setColumns(_cols);
             if (_colTable != null)
                 fm.getMappingInfo().setTableName(_colTable);
@@ -717,10 +742,11 @@
     /**
      * Return the proper override.
      */
-    private FieldMapping getAttributeOverrideForEmbeddable(FieldMapping fm) 
+    private FieldMapping getAttributeOverrideForEmbeddable(FieldMapping fm, 
+        String attrName, boolean mustExist) 
     throws SAXException {
         return AnnotationPersistenceMappingParser.getEmbeddedFieldMapping(fm, 
-            _override);
+            attrName, mustExist);
     }
 
     /**
@@ -747,14 +773,27 @@
             Object elem = currentElement();
             FieldMapping fm = null;
             if (elem instanceof FieldMapping) {
-                fm = (FieldMapping) elem;
-                if (_override != null) 
-                    fm = getAttributeOverrideForEmbeddable(fm);
+                fm = (FieldMapping) elem; 
+                if (_override != null) {
+                    FieldMapping basefm = (FieldMapping) elem;
+                    fm = getAttributeOverrideForEmbeddable(basefm, 
+                        _override, false);
+                    if (fm == null) {
+                        DeferredEmbeddableOverrides dfm = 
+                            getDeferredFieldMappingInfo(
+                                AnnotationPersistenceMappingParser.
+                                getEmbeddedClassType(basefm, _override),
+                                basefm, _override, true);
+                        dfm._defTable = table;
+                        dfm._attrName = _override;
+                    }
+                }
             } else if (elem instanceof ClassMapping) {
                 ClassMapping cm = (ClassMapping) elem;
                 fm = getAttributeOverride(cm);
             }
-            fm.getMappingInfo().setTableName(table);
+            if (fm != null)
+                fm.getMappingInfo().setTableName(table);
         }
         return true;
     }
@@ -767,17 +806,32 @@
         FieldMapping fm = null;
         if (elem instanceof FieldMapping) {
             fm = (FieldMapping) elem;
-            if (_override != null)
-                fm = getAttributeOverrideForEmbeddable(fm);
+            if (_override != null) {
+                FieldMapping basefm = (FieldMapping) elem;
+                fm = getAttributeOverrideForEmbeddable(basefm, _override, 
+                    false);
+                if (fm == null) {
+                    DeferredEmbeddableOverrides dfm = 
+                        getDeferredFieldMappingInfo(
+                            AnnotationPersistenceMappingParser.
+                            getEmbeddedClassType(basefm, _override),
+                            basefm, _override, true);
+                    dfm._defCols = _cols;
+                    dfm._defElemJoinCols = _joinCols;
+                    dfm._attrName = _override;
+                }
+            }
         } else if (elem instanceof ClassMapping){
             ClassMapping cm = (ClassMapping) elem;
             fm = getAttributeOverride(cm);
         }
 
-        if (_joinCols != null)
-            fm.getMappingInfo().setColumns(_joinCols);
-        if (_cols != null)
-            fm.getElementMapping().getValueInfo().setColumns(_cols);
+        if (fm != null) {
+            if (_joinCols != null)
+                fm.getMappingInfo().setColumns(_joinCols);
+            if (_cols != null)
+                fm.getElementMapping().getValueInfo().setColumns(_cols);
+        }
         clearColumnInfo();
     }
 
@@ -845,7 +899,7 @@
             // a collection of basic types
             // the column is in a separate table
             if (fm.isElementCollection() &&
-                fm.getElementMapping().getEmbeddedMapping() == null) {
+                !fm.getElementMapping().isEmbedded()) {
                 List list = fm.getElementMapping().getValueInfo().getColumns();
                 if (list.size() == 0) {
                     list = new ArrayList();
@@ -1208,4 +1262,125 @@
         }
         return col;
     }
+    
+    /**
+     * Process all deferred embeddable overrides for a given class.  
+     * This should only occur after the embeddable is mapped.
+     * 
+     * @param embedType  embeddable class 
+     * @param access class level access for embeddable
+     * @throws SAXException 
+     */
+    @Override
+    protected void applyDeferredEmbeddableOverrides(Class<?> cls) 
+        throws SAXException {
+        ArrayList<DeferredEmbeddableOverrides> defMappings = 
+            _deferredMappings.get(cls);
+        if (defMappings == null)
+            return;
+        
+        for (DeferredEmbeddableOverrides defMap : defMappings) {
+            FieldMapping fm = (FieldMapping)defMap._fm;
+            if (defMap == null)
+                return;
+            fm = getAttributeOverrideForEmbeddable(fm, defMap._attrName, true);
+            // Apply column, table, and unique overrides
+            if (defMap._defCols != null) {
+                fm.getValueInfo().setColumns(defMap._defCols);
+                if (defMap._defTable != null)
+                    fm.getMappingInfo().setTableName(defMap._defTable);
+                setUnique(fm, defMap._unique);
+            }
+            // Apply Join column and element join columns overrides overrides
+            if (defMap._defJoinCols != null)
+                fm.getMappingInfo().setColumns(defMap._defJoinCols);
+            if (defMap._defElemJoinCols != null)
+                fm.getElementMapping().getValueInfo().setColumns(
+                    defMap._defElemJoinCols);
+        }
+        // Clean up after applying mappings
+        defMappings.clear();
+        _deferredMappings.remove(cls);
+    }
+
+    /*
+     * Defer overrides for the specified field mapping
+     */
+    private void deferEmbeddableOverrides(
+        Class cls, DeferredEmbeddableOverrides defMap) {
+        ArrayList<DeferredEmbeddableOverrides> defMappings = 
+            _deferredMappings.get(cls);
+        if (defMappings == null) {
+            defMappings = new ArrayList<DeferredEmbeddableOverrides>();
+            _deferredMappings.put(cls, defMappings);
+        }
+        defMappings.add(defMap);
+    }
+    
+    /*
+     * Clean up any deferred mappings
+     */
+    @Override
+    protected void clearDeferredMetaData() {
+        super.clearDeferredMetaData();
+        _deferredMappings.clear();
+    }
+    
+    /*
+     * Get embeddable overrides for the specified field mapping.  If create
+     * is true, create a new override if one does not exist.
+     */
+    private DeferredEmbeddableOverrides 
+        getDeferredFieldMappingInfo(Class<?> cls, FieldMapping fm, 
+            String attrName, boolean create) {
+
+        ArrayList<DeferredEmbeddableOverrides> defMappings = 
+            _deferredMappings.get(cls);
+        
+        if (defMappings == null && create) {
+            defMappings = new ArrayList<DeferredEmbeddableOverrides>();
+            _deferredMappings.put(cls, defMappings);
+        }
+        DeferredEmbeddableOverrides dfm = 
+            findDeferredMapping(cls, fm, attrName);
+
+        if (dfm == null & create) {
+            dfm = new DeferredEmbeddableOverrides(fm, attrName);
+            deferEmbeddableOverrides(cls, dfm);
+        }
+        return dfm;            
+    }
+
+    /*
+     * Find deferred mappings for the given class, fm, and attr name
+     */
+    private DeferredEmbeddableOverrides findDeferredMapping(Class<?> cls, 
+        FieldMapping fm, String attrName) {
+        ArrayList<DeferredEmbeddableOverrides> defMappings = 
+            _deferredMappings.get(cls);
+        if (defMappings == null)
+            return null;
+        
+        for (DeferredEmbeddableOverrides dfm : defMappings) {
+            if (dfm != null && dfm._fm == fm && 
+                attrName.equals(dfm._attrName))
+                return dfm;
+        }
+        return null;
+    }
+    
+    // Inner class for storing override information
+    class DeferredEmbeddableOverrides {
+        DeferredEmbeddableOverrides(FieldMapping fm, String attrName) {
+            _fm = fm;
+            _attrName = attrName;
+        }
+        private FieldMapping _fm;
+        private List<Column> _defCols;
+        private List<Column> _defElemJoinCols;
+        private List<Column> _defJoinCols;
+        private String _defTable;
+        private String _attrName;
+        private EnumSet<UniqueFlag> _unique;
+    }    
 }

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEmbedXML.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEmbedXML.java?rev=783966&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEmbedXML.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEmbedXML.java Fri Jun 12 02:40:14 2009
@@ -0,0 +1,39 @@
+/*
+ * 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.openjpa.persistence.embed.attrOverrides;
+
+public class BasicEmbedXML {
+
+    private Integer intValue;
+
+    public BasicEmbedXML() {
+    }
+
+    public BasicEmbedXML(int integerValue) {
+        this.intValue = new Integer(integerValue);
+    }
+
+    public Integer getIntegerValue() {
+        return this.intValue;
+    }
+
+    public void setNotIntegerValue(Integer intValue) {
+        this.intValue = intValue;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEmbedXML.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEntityXML.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEntityXML.java?rev=783966&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEntityXML.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEntityXML.java Fri Jun 12 02:40:14 2009
@@ -0,0 +1,45 @@
+/*
+ * 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.openjpa.persistence.embed.attrOverrides;
+
+import java.util.List;
+
+public class BasicEntityXML {
+
+    private int id;
+
+    private List<BasicEmbedXML> listIntAttrOverEmbed;
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setListIntAttrOverEmbed(
+        List<BasicEmbedXML> listIntAttrOverEmbed) {
+        this.listIntAttrOverEmbed = listIntAttrOverEmbed;
+    }
+
+    public List<BasicEmbedXML> getListIntAttrOverEmbed() {
+        return listIntAttrOverEmbed;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/BasicEntityXML.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/TestAttrOverridesXml.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/TestAttrOverridesXml.java?rev=783966&r1=783965&r2=783966&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/TestAttrOverridesXml.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/attrOverrides/TestAttrOverridesXml.java Fri Jun 12 02:40:14 2009
@@ -18,8 +18,11 @@
  */
 package org.apache.openjpa.persistence.embed.attrOverrides;
 
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Random;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityTransaction;
@@ -27,15 +30,14 @@
 
 import junit.framework.Assert;
 
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
 import org.apache.openjpa.persistence.test.AllowFailure;
 import org.apache.openjpa.persistence.test.SQLListenerTestCase;
 
-@AllowFailure(message=
-	"Multi-level embedding" + 
-	"JPA 2.0 Access Style " + 
-    "XML Metadata "         + 
-    "Attribute Override "   +  
-    " is not yet supported")
 public class TestAttrOverridesXml extends SQLListenerTestCase {
    
     public int numPersons = 4;
@@ -51,6 +53,12 @@
         return "embed-pu";
     }
     
+    @AllowFailure(message=
+        "Multi-level embedding" + 
+        "JPA 2.0 Access Style " + 
+        "XML Metadata "         + 
+        "Attribute Override "   +  
+        " is not yet supported")
     public void testAttrOverride1() {
         sql.clear();
     	createObj1();
@@ -59,6 +67,31 @@
         assertAttrOverrides("CustomerXml1");
     }
     
+    /**
+     * This test verifies that an embeddable column attribute override defined 
+     * in XML overrides the base column definition.
+     */
+    public void testBasicEmbedAttrOverride() {       
+        OpenJPAEntityManagerSPI em = emf.createEntityManager();
+        
+        BasicEntityXML be = new BasicEntityXML();
+        be.setId(new Random().nextInt());
+        
+        BasicEmbedXML bem = new BasicEmbedXML();
+        bem.setNotIntegerValue(new Random().nextInt());
+        ArrayList<BasicEmbedXML> al = new ArrayList<BasicEmbedXML>();
+        al.add(bem);
+        be.setListIntAttrOverEmbed(al);
+        
+        em.getTransaction().begin();
+        em.persist(be);
+        em.getTransaction().commit();
+        
+        assertTrue(verifyColumnOverride(em, "listIntAttrOverEmbedColTable", 
+            "intValueAttributeOverride"));
+        em.close();
+    }
+    
     public void createObj1() {
         EntityManager em = emf.createEntityManager();
         EntityTransaction tran = em.getTransaction();
@@ -120,4 +153,33 @@
         if (!found)
             fail();
     }
+
+    private boolean verifyColumnOverride( 
+        OpenJPAEntityManagerSPI em, String tableName,
+        String columnName) {
+
+        JDBCConfiguration conf = (JDBCConfiguration) 
+            em.getEntityManagerFactory().getConfiguration();
+        DBDictionary dict = conf.getDBDictionaryInstance();
+
+        Connection conn = (Connection)em.getConnection();
+        try {
+            DatabaseMetaData dbmd = conn.getMetaData();
+            // (meta, catalog, schemaName, tableName, conn)
+            Column[] cols = dict.getColumns(dbmd, null, null, 
+                    tableName, columnName, conn);
+            if (cols != null && cols.length == 1) {
+                Column col = cols[0];
+                String colName = col.getName();
+                if (col.getTableName().equalsIgnoreCase(tableName) &&
+                    colName.equalsIgnoreCase(columnName))
+                    return true;
+            }
+        } catch (Throwable e) {
+            fail("Unable to get column information.");
+        }
+        return false;
+    }
+
+
 }

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/embed-orm.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/embed-orm.xml?rev=783966&r1=783965&r2=783966&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/embed-orm.xml (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/embed-orm.xml Fri Jun 12 02:40:14 2009
@@ -184,6 +184,22 @@
         </attributes>
     </entity>
 
+    <entity name="BasicEntityXML"
+        class="org.apache.openjpa.persistence.embed.attrOverrides.BasicEntityXML">
+        <attributes>
+            <id name="id" />
+            <element-collection name="listIntAttrOverEmbed" fetch="EAGER">
+                <order-column name="valueOrderColumn" />
+                <attribute-override name="intValue">
+                    <column name="intValueAttributeOverride" />
+                </attribute-override>
+                <collection-table name="listIntAttrOverEmbedColTable">
+                    <join-column name="parent_id" />
+                </collection-table>
+            </element-collection>
+        </attributes>
+    </entity>
+
     <embeddable 
         class="org.apache.openjpa.persistence.embed.attrOverrides.AddressXml" 
         access="FIELD">
@@ -235,4 +251,11 @@
 		</attributes>
 	</embeddable>
 
-</entity-mappings>
+    <embeddable class="org.apache.openjpa.persistence.embed.attrOverrides.BasicEmbedXML">
+        <attributes>
+            <basic name="intValue">
+                <column name="shouldNotExist" />
+            </basic>
+        </attributes>
+    </embeddable>
+</entity-mappings>
\ No newline at end of file

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java?rev=783966&r1=783965&r2=783966&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java Fri Jun 12 02:40:14 2009
@@ -1553,7 +1553,9 @@
         FieldMetaData fmd = (FieldMetaData) currentElement();
         String dec = currentText();
         if (fmd.isElementCollection() &&
-            fmd.getElement().getEmbeddedMetaData() != null) {
+            fmd.getElement().getEmbeddedMetaData() != null ||
+            isDeferredEmbeddable(fmd.getElement().getDeclaredType(), 
+                fmd.getElement())) {
             if (dec.length() == 0 || dec.equals("ASC") ||
                 dec.equals("DESC"))
                 throw new MetaDataException(_loc.get(
@@ -1895,34 +1897,58 @@
 	}
     
     /**
-     * Process all deferred embeddables for a given class.  This should only
-     * happen after the access type of the embeddable is known.
+     * Process all deferred embeddables and embeddable mapping overrides
+     * for a given class.  This should only happen after the access type 
+     * of the embeddable is known.
      * 
-     * @param embedType  embeddable class 
+     * @param embedType embeddable class 
      * @param access class level access for embeddable
+     * @throws SAXException 
      */
     protected void addDeferredEmbeddableMetaData(Class<?> embedType, 
-        int access) {
+        int access) throws SAXException {
         ArrayList<MetaDataContext> fmds = _embeddables.get(embedType);
         if (fmds != null && fmds.size() > 0) {
-            for (int i = fmds.size() -1 ; i >= 0; i--) {
-                MetaDataContext md = fmds.get(i);
+            for (MetaDataContext md : fmds) {
                 if (md instanceof FieldMetaData) {
-                    ((FieldMetaData)md).addEmbeddedMetaData(access);            
+                    FieldMetaData fmd = (FieldMetaData)md;
+                    fmd.addEmbeddedMetaData(access);
                 }
                 else if (md instanceof ValueMetaData) {
-                    ((ValueMetaData)md).addEmbeddedMetaData(access);
+                    ValueMetaData vmd = (ValueMetaData)md;
+                    vmd.addEmbeddedMetaData(access);
                 }
-                fmds.remove(i);
-            }
-            // If all mds in the list were processed, remove the item
-            // from the map.
-            if (fmds.size() == 0) {
-                _embeddables.remove(embedType);
             }
+            applyDeferredEmbeddableOverrides(embedType);
+            // Clean up deferrals after they have been processed
+            fmds.clear();
+            _embeddables.remove(embedType);
+        }
+    }
+
+    /*
+     * Clear any deferred metadata
+     */
+    @Override
+    protected void clearDeferredMetaData() {
+        _embeddables.clear();
+    }
+
+    /*
+     * Determines whether the embeddable type is deferred.
+     */
+    protected boolean isDeferredEmbeddable(Class<?> embedType, 
+        MetaDataContext fmd) {
+        ArrayList<MetaDataContext> fmds = _embeddables.get(embedType);
+        if (fmds != null) {
+            return fmds.contains(fmd);
         }
+        return false;
     }
     
+    /*
+     * Add the fmd to the defer list for for the given embeddable type
+     */
     protected void deferEmbeddable(Class<?> embedType, MetaDataContext fmd) {
         ArrayList<MetaDataContext> fmds = _embeddables.get(embedType);
         if (fmds == null) {
@@ -1931,4 +1957,11 @@
         }
         fmds.add(fmd);
     }
+    
+    /*
+     * Apply any deferred overrides.
+     */
+    protected void applyDeferredEmbeddableOverrides(Class<?> cls)
+        throws SAXException {
+    }
 }