You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by pp...@apache.org on 2009/12/03 08:43:05 UTC

svn commit: r886691 [1/3] - in /labs/fluid: example/ example/domain/ src/main/java/org/apache/openjpa/sdo/ src/main/java/org/apache/openjpa/sdo/mapping/ src/main/java/serp/ src/main/java/serp/bytecode/ src/main/resources/org/apache/openjpa/sdo/ src/tes...

Author: ppoddar
Date: Thu Dec  3 07:41:56 2009
New Revision: 886691

URL: http://svn.apache.org/viewvc?rev=886691&view=rev
Log:
Major update from Sergio's contribution. 

Added:
    labs/fluid/example/
    labs/fluid/example/domain/
    labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMapID.java   (with props)
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODynamicClassResolver.java   (with props)
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEndTransactionListener.java   (with props)
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/ContainedIdenticalTypeMapping.java   (with props)
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/ContainerRelationMapping.java   (with props)
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/EmbeddableIdenticalTypeMapping.java   (with props)
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/EmbeddedRelationListMapping.java   (with props)
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/EmbeddedRelationMapping.java   (with props)
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/SDOMappingStrategyInstaller.java
      - copied, changed from r778535, labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/SDOMappingStrategy.java
    labs/fluid/src/main/java/serp/
    labs/fluid/src/main/java/serp/bytecode/
    labs/fluid/src/main/java/serp/bytecode/Annotation.java   (with props)
    labs/fluid/src/test/java/example/basic/TestConfiguration.java   (with props)
Removed:
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOMappingRepository.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOTypeRepository.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/TypeNotFoundException.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/SDOMappingStrategy.java
Modified:
    labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMap.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/ImplHelper.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDO2POJOGenerator.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODelegatingResultList.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManager.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManagerFactory.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOInstanceMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOMetaDataFactory.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOProductDerivation.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOQuery.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOTypeParser.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/SourceCode.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/AbstractPropertyMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/IdenticalTypeMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/IdentityMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/PrimitiveListMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/PrimitiveMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/PropertyMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/RelationListMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/RelationMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/TypeMapping.java
    labs/fluid/src/main/java/org/apache/openjpa/sdo/mapping/VersionMapping.java
    labs/fluid/src/main/resources/org/apache/openjpa/sdo/localizer.properties
    labs/fluid/src/test/java/example/basic/TestCRUD.java
    labs/fluid/src/test/java/example/basic/TestRelation.java
    labs/fluid/src/test/java/org/apache/openjpa/sdo/TestSDO.java
    labs/fluid/src/test/java/org/apache/openjpa/sdo/TestSourceCode.java
    labs/fluid/src/test/java/test/common/AbstractSDOTest.java
    labs/fluid/src/test/resources/META-INF/persistence.xml

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMap.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMap.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMap.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMap.java Thu Dec  3 07:41:56 2009
@@ -25,6 +25,9 @@
 
 /**
  * Map for reverse lookup.
+ * Implemented as a pair of forward and reverse map.
+ * Both key and value in the map must be unique.
+ * 
  * 
  * @author Pinaki Poddar
  *
@@ -80,6 +83,12 @@
 		return forward.remove(key);
 	}
 
+	public K removeReverse(Object v) {
+		K key = reverse.get(v);
+		forward.remove(key);
+		return reverse.remove(v);
+	}
+	
 	public int size() {
 		return forward.size();
 	}

Added: labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMapID.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMapID.java?rev=886691&view=auto
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMapID.java (added)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMapID.java Thu Dec  3 07:41:56 2009
@@ -0,0 +1,195 @@
+/*
+ * 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.sdo;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.keyvalue.DefaultMapEntry;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+
+class BiDiMapID {
+
+	private HashMap<String, HashMap<String,Map.Entry<DataObject, Object>>> mapid = new HashMap<String, HashMap<String,Map.Entry<DataObject, Object>>>();
+	private SDOEntityManager em = null;
+	private BiDiMap<DataObject, Object> mapobj = new BiDiMap<DataObject, Object>();
+	private BiDiMapID() {
+	    super();
+	}
+	
+	public BiDiMapID(SDOEntityManager em) {
+	    this();
+	    this.em = em;
+	}
+	
+	public void clear() {
+		mapid.clear();
+		mapobj.clear();
+	}
+//TODO:  this is an hack, we use toString but we should manage Openjpa ID
+	public boolean containsKey(DataObject key) {
+		return mapobj.containsKey(key) || mapid.containsKey(key.getType().getName()) && mapid.get(key.getType().getName()).containsKey(ImplHelper.getIdValue(key).toString());
+	}
+
+	public boolean containsValue(Object value) {
+	    	if (mapobj.containsValue(value)) {
+	    	    return true;
+	    	}
+	    	String t = em.getRepos().getSDOType(value.getClass()).getName();
+	    	Object oid = em.getBroker().getStateManager(value) != null ? em.getBroker().getStateManager(value).getId() : null;
+	    	if (oid == null) {
+	    	    return false;
+	    	}
+	    	String id = oid.toString();
+		return mapid.containsKey(t) && mapid.get(t).containsKey(id);
+	}
+
+	public Set<Map.Entry<DataObject, Object>> entrySet() {
+	    Set<Map.Entry<DataObject, Object>> ret = new HashSet<Map.Entry<DataObject, Object>>();
+	    for (HashMap<String,Map.Entry<DataObject, Object>> he:mapid.values()) {
+		ret.addAll(he.values());
+	    }
+	    ret.addAll(mapobj.entrySet());
+	    return ret;
+	}
+
+	public Object get(DataObject key) {
+	    if (mapobj.containsKey(key)) {
+		return mapobj.get(key);
+	    } else if (this.containsKey(key)) {
+		return mapid.get(key.getType().getName()).get(ImplHelper.getIdValue(key).toString()).getValue();
+	    } else {
+		return null;
+	    }
+	}
+
+	public boolean isEmpty() {
+		return mapobj.isEmpty();
+	}
+
+	public Set<DataObject> keySet() {
+	    Set<DataObject> ret = new HashSet<DataObject>();
+	    for (HashMap<String,Map.Entry<DataObject, Object>> he:mapid.values()) {
+		for (Map.Entry<DataObject, Object> e:he.values()) {
+		    ret.add(e.getKey());
+		}
+	    }
+	    ret.addAll(mapobj.keySet());
+	    return ret;
+	}
+
+	public Object put(DataObject key, Object value) {
+	    String t = key.getType().getName();
+	    Object oid = ImplHelper.getIdValue(key);
+	    if (oid == null && em.getBroker().getStateManager(value) != null) {
+		oid = em.getBroker().getStateManager(value).getId();
+	    } 
+	    if (oid == null) {
+		return mapobj.put(key, value);
+	    }
+	    String id = oid.toString();
+	    Map.Entry<DataObject, Object> e = new DefaultMapEntry(key,value);
+	    if (!mapid.containsKey(t)) {
+		HashMap<String,Map.Entry<DataObject, Object>> he = new HashMap<String,Map.Entry<DataObject, Object>>();
+		mapid.put(t, he);		
+	    }
+	    return mapid.get(t).put(id, e);
+	}
+
+	@SuppressWarnings("unchecked")
+	public void putAll(Map<DataObject, Object> t) {
+		for (DataObject k:t.keySet())
+			put(k, t.get(k));
+	}
+
+	public Object remove(DataObject key) {
+	    String t = key.getType().getName();
+	    Object oid = ImplHelper.getIdValue(key);
+	    Object ret = null;
+	    if (oid == null) {
+		return mapobj.remove(key);		
+	    }
+	    String id = oid.toString();
+	    if (this.containsKey(key)) {
+		ret = mapid.get(t).remove(id).getValue();
+		if (mapid.get(t).isEmpty()) {
+		    mapid.remove(t);
+		}
+	    }
+	    return ret;
+	}
+
+	public DataObject removeReverse(Object v) {
+	    String t = em.getRepos().getSDOType(v.getClass()).getName();
+	    Object oid = em.getBroker().getStateManager(v) != null ? em.getBroker().getStateManager(v).getId() : null;
+	    DataObject ret = null;
+	    if (oid == null) {
+		return mapobj.removeReverse(v);
+	    }
+	    String id = oid.toString();
+	    if (this.containsValue(v)) {
+		ret = mapid.get(t).remove(id).getKey();
+		if (mapid.get(t).isEmpty()) {
+		    mapid.remove(t);
+		}
+	    }
+	    return ret;
+	}
+	
+	public int size() {
+	    int ret = 0;
+	    for (HashMap<String,Map.Entry<DataObject, Object>> he:mapid.values()) {
+		ret += he.size();
+	    }
+	    return ret + mapobj.size();
+	}
+
+	public Collection<Object> values() {
+	    ArrayList<Object> ret = new ArrayList<Object>();
+	    for (HashMap<String,Map.Entry<DataObject, Object>> he:mapid.values()) {
+		for (Map.Entry<DataObject, Object> e:he.values()) {
+		    ret.add(e.getValue());
+		}
+	    }
+	    ret.addAll(mapobj.values());
+	    return ret;
+	}
+	
+	public DataObject getReverse(Object v) {
+	    if (mapobj.containsValue(v)) {
+		return mapobj.getReverse(v);
+	    } else if (this.containsValue(v)) {
+		String t = em.getRepos().getSDOType(v.getClass()).getName();
+		Object oid = em.getBroker().getStateManager(v) != null ? em.getBroker().getStateManager(v).getId() : null;
+		if (oid == null) {
+		    return null;
+		}
+		String id = oid.toString();
+		return mapid.get(t).get(id).getKey();
+	    } else {
+		return null;
+	    }
+	}
+}

Propchange: labs/fluid/src/main/java/org/apache/openjpa/sdo/BiDiMapID.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/ImplHelper.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/ImplHelper.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/ImplHelper.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/ImplHelper.java Thu Dec  3 07:41:56 2009
@@ -19,13 +19,23 @@
 package org.apache.openjpa.sdo;
 
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
 
 import org.apache.commons.lang.StringUtils;
+import org.apache.openjpa.enhance.PersistenceCapable;
+import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.util.UserException;
 
+import serp.bytecode.lowlevel.ConstantPoolTable;
+
 import commonj.sdo.DataObject;
 import commonj.sdo.Property;
 import commonj.sdo.Type;
@@ -39,6 +49,8 @@
  */
 public final class ImplHelper {
 	private static Localizer _loc = Localizer.forPackage(ImplHelper.class);
+	private static HashMap<Type,List<Property>> containments = null;
+	private static HashMap<Type,List<Property>> references = null;
 
 	/**
 	 * Get the name of a method for a given property name.
@@ -157,7 +169,7 @@
 	public static boolean isIdentity(Property property) {
 		if (property == null)
 			return false;
-		if ("id".equals(property.getName()) && property.getType().isDataType())
+		if (("id".equals(property.getName()) || property.getAliasNames().contains("id")) && property.getType().isDataType())
 				return true;
 		if (isEMFImplementaionAvailable() && property.getType().isDataType()) {
 			try {
@@ -171,6 +183,94 @@
 		}
 		return false;
 	}
+
+	/**
+	 * Affirms if the type has any referencing property.
+	 */
+	public static List<Property> getReferenceProperties(Type t) {
+		ArrayList<Property> ret = null;
+		Collection<Type> parsedtypes = SDOTypeParser.getParsedTypes();
+		for (Type type:parsedtypes) {
+			List<Property> properties = type.getProperties();
+			for (Property p : properties) {
+				if (p.getType().equals(t) && !p.getType().isDataType() && !p.isContainment()) {
+					if (ret == null)
+						ret = new ArrayList<Property>();
+					ret.add(p);
+				}
+			}
+		}
+		return ret;
+	}
+
+	public static Map<Type,List<Property>> getContainments(boolean refresh) {
+		if (containments == null) { 
+			containments = new HashMap<Type,List<Property>>();		
+			references = new HashMap<Type,List<Property>>();
+			refreshPropertyRelations();
+		} else if (refresh)
+			refreshPropertyRelations();
+		return containments;
+	}	
+	
+	public static Map<Type,List<Property>> getReferences(boolean refresh) {
+		if (containments == null) { 
+			containments = new HashMap<Type,List<Property>>();		
+			references = new HashMap<Type,List<Property>>();
+			refreshPropertyRelations();
+		} else if (refresh)
+			refreshPropertyRelations();
+		return references;
+	}	
+
+	public static void refreshPropertyRelations () {
+		containments.clear();
+		references.clear();
+		Collection<Type> parsedtypes = SDOTypeParser.getParsedTypes();
+		for (Type t : parsedtypes) {
+			List<Property> c = getContainerProperties(t);
+			if (c != null) {
+				containments.put(t, c);
+			}				
+			List<Property> r = getReferenceProperties(t);
+			if (r != null) {
+				references.put(t, r);
+			}				
+		}		
+		
+	}
+	
+	public static Map<Type,List<Property>> getContainments() {
+		return getContainments(false);
+	}
+
+	public static Map<Type,List<Property>> getReferences() {
+		return getReferences(false);
+	}
+	
+	
+	/**
+	 * Return the property that contains the given type.
+	 */
+	public static List<Property> getContainerProperties(Type type) {
+		ArrayList<Property> ret = null;
+		Collection<Type> parsedtypes = SDOTypeParser.getParsedTypes();
+		for (Type t : parsedtypes) {
+			List<Property> properties = t.getProperties();
+			for (Property p : properties) {
+				if (!p.isContainment())
+					continue;
+				Property cp = getComponentProperty(p.getType());
+				if ((p.getType().equals(type)) 
+						|| (cp != null && cp.isContainment() && cp.getType().equals(type))) {
+					if (ret == null)
+						ret = new ArrayList<Property>();
+					ret.add(p);
+				}
+			}	
+		}
+		return ret;
+	}
 	
 	/**
 	 * Gets the property that represents version information.
@@ -197,6 +297,15 @@
 	}
 	
 	/**
+	 * Affirms if the property represents a LOB type.
+	 * LOB types are property or types that have alias named "LOB"
+	 */
+	public static boolean isLOB(Property property) {
+		return (property != null && property.getType().isDataType() && 
+				(property.getAliasNames().contains("LOB") || property.getType().getAliasNames().contains("LOB"))); 
+	}
+	
+	/**
 	 * Gets the value of the {@link #getIdentityProperty(Type) identity property}
 	 * of the given DataObject.
 	 */
@@ -296,6 +405,65 @@
 		}
 		return isEMFImplementation.booleanValue();
 	}
+	
+	public static Class getEnhancedClass(Object o) {
+		Class cls = o.getClass();
+		String name;
+		if (cls.getPackage() == null) {
+			name = cls.getName();
+			int index = name.lastIndexOf('.');
+			name = name.substring(0, index);
+        } else {
+        	name = cls.getPackage().getName();
+        }
+		if (name.equals("org.apache.openjpa.enhance"))
+			cls = cls.getSuperclass();
+		return cls;
+	}
+	
+  public static boolean idMatch(DataObject data, Object pc) {
+    Class cls = pc.getClass();
+    Property idprop = ImplHelper.getIdentityProperty(data.getType());
+    Method getter = Reflection.findGetter(cls, idprop.getName(), true);
+    try {
+      String pcid = getter.invoke(pc, NULL_ARGS).toString();
+      String id = data.get(idprop).toString();
+      return (id.equalsIgnoreCase(pcid) || id.trim().equalsIgnoreCase(pcid)); // this is an hack for ldap stores that trims DN 
+    } catch (Exception e) {
+      return false;
+    }    
+  }
+
+  public static boolean idMatch(SDOEntityManager em, DataObject data, Object pc) {
+    String pcid = (String) em.getObjectId(pc);
+    Property idprop = ImplHelper.getIdentityProperty(data.getType());
+    String id = data.get(idprop).toString();
+    return (id.equalsIgnoreCase(pcid) || id.trim().equalsIgnoreCase(pcid)); // this is an hack for ldap stores that trims DN 
+  }
+  
+  public static boolean isPersistenceCapable(Class cls) {
+  	return PersistenceCapable.class.isAssignableFrom(cls);
+  }
+  
+  public static boolean isEnhanced(byte[] b) {
+      ConstantPoolTable table = new ConstantPoolTable(b);
+      int idx = table.getEndIndex();
+
+      idx += 6; // skip access, cls, super
+      int ifaces = table.readUnsignedShort(idx);
+      int clsEntry, utfEntry;
+      String name;
+      for (int i = 0; i < ifaces; i++) {
+          idx += 2;
+          clsEntry = table.readUnsignedShort(idx);
+          utfEntry = table.readUnsignedShort(table.get(clsEntry));
+          name = table.readString(table.get(utfEntry));
+          if ("org/apache/openjpa/enhance/PersistenceCapable".equals(name))
+              return true;
+      }
+      return false;
+  }
+  
 	private static Boolean isEMFImplementation = null;
 	private static final String EMF_CLASS = 
 		"org.apache.tuscany.sdo.impl.ClassImpl";

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDO2POJOGenerator.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDO2POJOGenerator.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDO2POJOGenerator.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDO2POJOGenerator.java Thu Dec  3 07:41:56 2009
@@ -23,6 +23,7 @@
 import java.io.InputStream;
 import java.io.PrintStream;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -33,14 +34,19 @@
 import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.log.LogFactoryImpl;
+import org.apache.openjpa.lib.log.Log4JLogFactory;
 import org.apache.openjpa.lib.util.Files;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.lib.util.Options;
 import org.apache.openjpa.sdo.mapping.PropertyMapping;
-import org.apache.openjpa.sdo.mapping.SDOMappingStrategy;
+import org.apache.openjpa.sdo.mapping.SDOMappingStrategyInstaller;
 import org.apache.openjpa.sdo.mapping.TypeMapping;
 import org.apache.openjpa.util.UserException;
 
+import serp.bytecode.BCClass;
+import serp.bytecode.BCMethod;
+import serp.bytecode.Code;
+
 import commonj.sdo.Property;
 import commonj.sdo.Type;
 import commonj.sdo.helper.XSDHelper;
@@ -60,7 +66,7 @@
 	private Map<Type, SourceCode> _cache = new HashMap<Type, SourceCode>();
 	private Log 		 _log;
 	private Flags 		 flags;
-
+	private List<Type> _types = new ArrayList<Type>();
 	/**
 	 * Construct with default options.
 	 *
@@ -77,6 +83,7 @@
 		this.flags = flags;
 		LogFactoryImpl logFactory = new LogFactoryImpl();
 		logFactory.setDefaultLevel(LogFactoryImpl.getLevel(flags.logLevel));
+		//Log4JLogFactory logFactory = new Log4JLogFactory();
 		_log = logFactory.getLog(OpenJPAConfiguration.LOG_METADATA);
 	}
 	
@@ -116,10 +123,12 @@
 	 * 
 	 */
 	SourceCode generatePOJO(Type type) {
-		TypeMapping mapping = SDOMappingStrategy.decideStrategy(type, null);
+		TypeMapping mapping = SDOMappingStrategyInstaller.decideStrategy(type, null);
 		String pkgName       = mapping.getJavaPackageName();
-		String javaClassName = mapping.getJavaClassName();
+		String javaClassName = mapping.getSimpleJavaClassName();
 		SourceCode code = new SourceCode(pkgName, javaClassName);
+		SourceCode.Method defaultConstructor = null;
+
 		if (_log.isInfoEnabled())
 			_log.info(_loc.get("mapping-type", type.getName(), 
 				code.getFullClassName() ));
@@ -127,37 +136,63 @@
 		_cache.put(type, code);
 		
 		SourceCode.Class cls = code.getTopLevelClass();
+		if ((type.getBaseTypes().size() > 0))
+				cls.setSuper(ImplHelper.getFullClassName((Type)type.getBaseTypes().get(0)));
+		else
+			cls.addInterface("java.io.Serializable");
 		if (type.isAbstract()) 
 			cls.makeAbstract();
 		cls.makePublic();
 		
 		// annotate the class as @Entity
 		code.addImport("javax.persistence.*");
-		cls.addAnnotation("@Entity");
-		
-		
+		code.addImport("org.apache.openjpa.persistence.*");
+		String[] cannotations = mapping.getAnnotationStrings();
+		for (String anno:cannotations)
+			cls.addAnnotation(anno);		
+
 		// add private field with bean-style get/set methods for each property
-		List properties = type.getProperties();
-		for (Object p : properties) {
-			Property property    = (Property) p;
-			PropertyMapping pm   = mapping.getMapping(property);
+		Collection<PropertyMapping> properties = mapping.getMappings();
+		for (PropertyMapping pm:properties) {
 			String fieldName     = pm.getFieldName();
 			String fieldTypeName = pm.getFieldTypeName();
+
+			if (pm.getProperty() != null && pm.getProperty().getContainingType() != type) {
+				if (pm.getProperty().getType().isDataType() && !pm.getProperty().isMany()) {
+					if (_log.isTraceEnabled()) {
+						_log.trace(pm.getProperty().getContainingType().getName() + " --> " + fieldName + ": " + fieldTypeName);
+					}
+				}
+				
+				continue;
+			}
+
 			if (_log.isTraceEnabled())
-				_log.trace(_loc.get("mapping-property", property.getName(), 
+				_log.trace(_loc.get("mapping-property", fieldName, 
 						fieldTypeName, pm.getName()));
 			SourceCode.Field field = code.addField(fieldName, fieldTypeName)
-			    .makePrivate();
+					.makePrivate();
 			String[] annotations = pm.getAnnotationStrings();
 			for (String anno:annotations)
 				field.addAnnotation(anno);
 			field.addGetter();
-			if (!property.isReadOnly())
+			if (pm.getProperty() == null || !pm.getProperty().isReadOnly())
 				field.addSetter();
 		}
+
+		// add default constructor if class not abstract
+		if (!type.isAbstract()) {
+			defaultConstructor = code.addMethod(javaClassName, "");
+	    // add non default constructor
+      List<PropertyMapping[]> csfields = SDOMetaDataFactory.getConstructors(mapping);
+      if (csfields != null && !csfields.isEmpty()) {
+        addConstructors(javaClassName, code, csfields);
+      }			
+		}
+
 		return code;
 	}
-	
+		
 	void decorate(SourceCode code) {
 		code.addComment(false, 
 			"Generated from SDO Type definition.",
@@ -206,12 +241,14 @@
 	 */
 	void run(String[] args) {
 		_cache.clear();
+		_types.clear();
 		SDOTypeParser parser = new SDOTypeParser(new OpenJPAConfigurationImpl());
 		for (int i=0; args!=null && i<args.length; i++) {
 			List<Type> types = parser.parseXSDResource(args[i]);
-			for (Type type:types) {
-				getJavaSourceCode(type);
-			}
+			_types.addAll(types);
+		}
+		for (Type type:_types) {
+			getJavaSourceCode((Type)type);
 		}
 		record();
 	}
@@ -261,4 +298,20 @@
 		public String logLevel = "INFO";
 	}
 
+  private void addConstructors(String javaClassName, SourceCode code, List<PropertyMapping[]> csfields) {
+    for (PropertyMapping[] cfields:csfields) {
+      SourceCode.Method constructor = new SourceCode.Method(javaClassName, "");
+      fillConstructor(constructor, cfields);
+      code.addMethod(constructor);
+    }
+  }
+  
+  private void fillConstructor(SourceCode.Method constructor, PropertyMapping[] cfields) {
+    for (PropertyMapping pm:cfields) {
+      constructor.addArgument(pm.getFieldTypeName(), pm.getFieldName());
+      constructor.addCodeLine("set" + SourceCode.capitalize(pm.getFieldName()) + "(" + pm.getFieldName() + ")");
+    }
+    return;
+  }
+	
 }

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODelegatingResultList.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODelegatingResultList.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODelegatingResultList.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODelegatingResultList.java Thu Dec  3 07:41:56 2009
@@ -18,12 +18,19 @@
  */
 package org.apache.openjpa.sdo;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
 import java.util.ListIterator;
 
 import org.apache.openjpa.kernel.DelegatingResultList;
 import org.apache.openjpa.lib.rop.ResultList;
 import org.apache.openjpa.util.RuntimeExceptionTranslator;
 
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.EqualityHelper;
+
 /**
  * A ResultList that converts the persistent Java Objects to SDO DataObjects
  * before returning to the caller.
@@ -31,24 +38,87 @@
  * @author Pinaki Poddar
  * @since 0.1.0
  */
-@SuppressWarnings("serial")
 class SDODelegatingResultList extends DelegatingResultList {
 	private final SDOEntityManager em;
-	public SDODelegatingResultList(SDOEntityManager em, ResultList list, 
-			RuntimeExceptionTranslator trans) {
+	
+	public SDODelegatingResultList(SDOEntityManager em, ResultList<?> list, RuntimeExceptionTranslator trans) {
 		super(list, trans);
 		this.em = em;
 	}
+
+    public boolean contains(Object o) {
+        for (Iterator itr = this.iterator(); itr.hasNext();)
+            if (EqualityHelper.INSTANCE.equal((DataObject) o, (DataObject) itr.next()))
+                return true;
+        return false;
+    }
+
+    public boolean containsAll(Collection c) {
+        for (Iterator itr = c.iterator(); itr.hasNext();)
+            if (!contains(itr.next()))
+                return false;
+        return true;
+    }
+
+    public Object get(int index) {
+        return this.listIterator(index).next();
+    }
+
+	public int indexOf(Object o) {
+        int index = 0;
+        for (Iterator itr = this.iterator(); itr.hasNext(); index++)
+            if (EqualityHelper.INSTANCE.equal((DataObject) o, (DataObject) itr.next()))
+                return index;
+        return -1;
+    }
+	
+    public int lastIndexOf(Object o) {
+        int index = -1;
+        int i = 0;
+        for (Iterator itr = this.iterator(); itr.hasNext(); i++)
+            if (EqualityHelper.INSTANCE.equal((DataObject) o, (DataObject) itr.next()))
+                index = i;
+        return index;
+    }
 	
+    public boolean isEmpty() {
+        return !this.iterator().hasNext();
+    }
+
+	public Iterator iterator() {
+        return listIterator();
+    }
+
     public ListIterator listIterator() {
+        return listIterator(0);
+    }
+
+    public ListIterator listIterator(int index) {
         try {
-            return new SDOListIterator(getDelegate().listIterator());
+            return new SDOListIterator(getDelegate().listIterator(index));
         } catch (RuntimeException re) {
             throw translate(re);
         }
     }
     
+    public Object[] toArray() {
+        List<DataObject> list = new ArrayList<DataObject>();
+        Iterator<DataObject> itr = (Iterator<DataObject>) this.iterator();
+        while (itr.hasNext()) {
+            list.add(itr.next());
+        }
+        return list.toArray();
+    }
     
+    public Object[] toArray(Object[] a) {
+        List<DataObject> list = new ArrayList<DataObject>();
+        Iterator<DataObject> itr = (Iterator<DataObject>) this.iterator();
+        while (itr.hasNext()) {
+            list.add(itr.next());
+        }
+        return list.toArray(a);
+    }
+   
     public class SDOListIterator extends DelegatingListIterator {
     	
     	public SDOListIterator(ListIterator it) {
@@ -58,7 +128,11 @@
     	public Object next() {
     		Object o = super.next();
     		SDOEntityManager em = SDODelegatingResultList.this.em;
-    		return em.createDataObject(o);
+    		if (em.getSDOType(ImplHelper.getEnhancedClass(o)) != null) {
+    			return em.createDataObject(o, true);
+    		} else {
+    			return o;
+    		}
     	}
     }
 

Added: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODynamicClassResolver.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODynamicClassResolver.java?rev=886691&view=auto
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODynamicClassResolver.java (added)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODynamicClassResolver.java Thu Dec  3 07:41:56 2009
@@ -0,0 +1,59 @@
+package org.apache.openjpa.sdo;
+
+import org.apache.openjpa.lib.util.MultiClassLoader;
+import org.apache.openjpa.util.ClassResolverImpl;
+
+import serp.bytecode.BCClassLoader;
+import serp.bytecode.Project;
+
+/**
+ * A class resolver that returns a class loader that had loaded dynamically generated, enhanced Java classes
+ * for SDO types.
+ * This dynamic class loader 
+ * @author Pinaki Poddar
+ *
+ */
+public class SDODynamicClassResolver extends ClassResolverImpl {
+    private static Project project = new Project();
+    private BCClassLoader dynamicLoader;
+    
+    /**
+     * Gets the dynamic class loader that is a direct child of the given parent.
+     * If a previous call has initialized a dynamic class loader (may be with a different parent)
+     * then the existing loader is returned.
+     * If the given parent is null, then current thread's context class loader is used as parent.
+     * 
+     * @param parent a parent class loader.
+     * 
+     * @return
+     */
+    public BCClassLoader getDynamicClassLoader(ClassLoader parent) {
+        if (dynamicLoader == null) {
+            if (parent == null)
+                parent = Thread.currentThread().getContextClassLoader();
+            dynamicLoader = new BCClassLoader(project, parent);
+        }
+        return dynamicLoader;
+    }
+    
+    @Override
+    public ClassLoader getClassLoader(Class<?> contextClass, ClassLoader envLoader) {
+        ClassLoader original = super.getClassLoader(contextClass, envLoader);
+    	if (original instanceof MultiClassLoader) {
+			ClassLoader[] children = ((MultiClassLoader) original).getClassLoaders();
+			for (ClassLoader child : children) {
+			    if (child instanceof BCClassLoader) {
+			        return original;
+			    }
+			}
+			((MultiClassLoader) original).addClassLoader(getDynamicClassLoader(envLoader));
+			return original;
+		} else {
+			MultiClassLoader newLoader = new MultiClassLoader();
+			newLoader.addClassLoader(original);
+			newLoader.addClassLoader(getDynamicClassLoader(envLoader));
+			return newLoader;
+		}
+    }	
+
+}

Propchange: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDODynamicClassResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEndTransactionListener.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEndTransactionListener.java?rev=886691&view=auto
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEndTransactionListener.java (added)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEndTransactionListener.java Thu Dec  3 07:41:56 2009
@@ -0,0 +1,135 @@
+/*
+ * 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.sdo;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.event.EndTransactionListener;
+import org.apache.openjpa.event.TransactionEvent;
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Closeable;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager;
+import org.apache.openjpa.util.UserException;
+
+import commonj.sdo.DataObject;
+
+/**
+ * Manager that can be used to track and notify
+ * {@link RemoteCommitListener}s on remote commit events. If remote events
+ * are enabled, this manager should be installed as a transaction listener on
+ * all brokers so that it knows when commits are made.
+ *
+ * @author Sergio Tabanelli
+ */
+public class SDOEndTransactionListener
+    implements EndTransactionListener {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (SDOEndTransactionListener.class);
+	SDOEntityManager em;
+	private Set<Object> cacheremove = new HashSet<Object>();
+	private Set<Object> cachesync = new HashSet<Object>();
+
+
+    /**
+     * Constructor. Supply configuration.
+     */
+    public SDOEndTransactionListener(SDOEntityManager em) {
+		this.em = em;
+    }
+
+    //////////////////////////////////////
+    // TransactionListener implementation
+    //////////////////////////////////////
+
+    public void afterCommit(TransactionEvent event) {
+        Broker broker = (Broker) event.getSource();
+        Collection trans = event.getTransactionalObjects();
+        cacheremove.clear();
+        cachesync.clear();
+        if (trans.isEmpty())
+            return;
+         Object obj;
+        OpenJPAStateManager sm;
+        for (Iterator itr = trans.iterator(); itr.hasNext();) {
+            obj = itr.next();
+            sm = broker.getStateManager(obj);
+
+            if (sm == null || !sm.isPersistent() || !sm.isDirty())
+                continue;
+            if (sm.isDeleted())
+            	cacheremove.add(obj);
+            else 
+            	cachesync.add(obj);
+        }
+    }
+
+    public void beforeCommit(TransactionEvent event) {
+    }
+
+    public void afterRollback(TransactionEvent event) {
+        Broker broker = (Broker) event.getSource();
+        Collection trans = event.getTransactionalObjects();
+        cacheremove.clear();
+        cachesync.clear();
+        if (trans.isEmpty())
+            return;
+        Object obj;
+        OpenJPAStateManager sm;
+        for (Iterator itr = trans.iterator(); itr.hasNext();) {
+            obj = itr.next();
+            sm = broker.getStateManager(obj);
+            if (sm == null || !sm.isDirty())
+                continue;
+            if (!sm.isNew())
+            	cachesync.add(obj);
+            else 
+            	cacheremove.add(obj);
+        }
+    }
+
+    public void afterCommitComplete(TransactionEvent event) {
+    	sync();
+    }
+
+    public void afterRollbackComplete(TransactionEvent event) {
+    	sync();
+    }
+
+    public void afterStateTransitions(TransactionEvent event)
+	{
+	}
+    
+    private void sync() {
+        if (cacheremove .size() > 0)
+        	em.removeCachedPC(cacheremove);
+        if (cachesync .size() > 0)
+        	em.sync(cachesync);        	
+
+    }
+}

Propchange: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEndTransactionListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManager.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManager.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManager.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManager.java Thu Dec  3 07:41:56 2009
@@ -19,17 +19,26 @@
 package org.apache.openjpa.sdo;
 
 
+import java.lang.reflect.Method;
 import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.kernel.Broker;
 import org.apache.openjpa.kernel.Query;
 import org.apache.openjpa.kernel.jpql.JPQLParser;
+import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.persistence.EntityManagerImpl;
 import org.apache.openjpa.persistence.OpenJPAQuery;
+import org.apache.openjpa.sdo.mapping.TypeMapping;
+import org.apache.openjpa.util.OptimisticException;
 
+import commonj.sdo.ChangeSummary;
 import commonj.sdo.DataObject;
+import commonj.sdo.Property;
 import commonj.sdo.Type;
 
 /**
@@ -50,16 +59,24 @@
  */
 public class SDOEntityManager extends EntityManagerImpl {
 	// TODO: Change to a smarter cache
-	private BiDiMap<DataObject, Object> cache = new BiDiMap<DataObject, Object>();
+	private BiDiMap<DataObject,Object> cache = new BiDiMap<DataObject,Object>();
+    private static final Localizer _loc = Localizer.forPackage(SDOEntityManager.class);
+	
+	private SDOMetaDataFactory repos;
+
+  public SDOMetaDataFactory getRepos() {
+	    return repos;
+	}
+
+private String applyChangesMode;
 	
-	private SDOMappingRepository repos;
-		
 	public SDOEntityManager(SDOEntityManagerFactory emf, Broker broker) {
 		super(emf, broker);
-		repos = ((SDOMetaDataFactory)emf.getConfiguration().
+		applyChangesMode = emf.getApplyChanges();
+		this.addTransactionListener(new SDOEndTransactionListener(this));
+		repos = (SDOMetaDataFactory)emf.getConfiguration().
 				getMetaDataRepositoryInstance().
-				getMetaDataFactory()).
-				getSDOMappingRepository();
+				getMetaDataFactory();
 	}
 	
 	/**
@@ -78,11 +95,16 @@
 	 */
 	@Override
 	public <T> T find(Class<T> cls, Object oid) {
-		if (cls==DataObject.class) {
-			Type type = extractType(oid.toString());
+		if (cls == DataObject.class) {
+			Type sdoType = extractType(oid.toString());
 			String id = extractId(oid.toString());
-			DataObject data = scanLocalCache(type, id);
-			return (T)data;
+			DataObject sdo = null;
+			Class<?> javaType = repos.getJavaClass(sdoType);
+			Object pojo = super.find(javaType, id);
+			if (pojo != null) {
+				sdo = createDataObject(pojo, true);
+			}
+			return (T)sdo;
 		} 
 		return super.find(cls, oid);
 	}
@@ -94,13 +116,11 @@
 	@Override
 	public void persist(Object entity) {
 		if (entity instanceof DataObject) {
-			SDOInstanceMapping ctx = new SDOInstanceMapping(this, repos);
-			DataObject data = (DataObject)entity;
-			ctx.populatePC(data);
-			Collection closure = ctx.getClosure().values();
-			super.persistAll(closure);
+			DataObject sdo = (DataObject)entity;
+			Object pc = createPC(sdo, true);
+			super.persist(pc);
 			return;
-		}  
+		}
 		super.persist(entity);
 	}
 	
@@ -111,19 +131,11 @@
 	@Override
     public <T> T merge(T entity) {
     	if (entity instanceof DataObject) {
-    		DataObject data = (DataObject)entity;
-			SDOInstanceMapping ctx = new SDOInstanceMapping(this, repos);
-			ctx.populatePC(data);
-    		Map<DataObject, Object> workSet = ctx.getClosure();
-    		super.mergeAll(workSet.values());
-    		// TODO: This is not done, but how can we get the new version
-    		for (DataObject d:workSet.keySet()) {
-    			Object original = workSet.get(d);
-				//TODO: Version is always integer
-    			int newVersion = ((Integer)getVersion(original)).intValue() + 1;
-    			ImplHelper.setVersion(d, newVersion);
-    		}
-    		return (T)data;
+    		DataObject sdo = (DataObject)entity;
+            Object pc = createPC(sdo, false);
+            pc = super.merge(pc);
+    		sdo = createDataObject(pc, false);
+    		return (T)sdo;
     	}
         return super.merge(entity);
     }
@@ -134,11 +146,11 @@
     @Override
     public void remove(Object entity) {
     	if (entity instanceof DataObject) {
-			DataObject data = (DataObject)entity;
-			SDOInstanceMapping ctx = new SDOInstanceMapping(this, repos);
-			ctx.populatePC(data);
-			Collection closure = ctx.getClosure().values();
-			super.removeAll(super.mergeAll(closure));
+			DataObject sdo = (DataObject)entity;
+			Object pc = createPC(sdo, true);
+			super.remove(pc);
+			if (sdo.getContainer() != null)
+				sdo.detach();
 			return;
     	} 
     	super.remove(entity);
@@ -152,14 +164,45 @@
 		Query kernelQuery = getBroker().newQuery(JPQLParser.LANG_JPQL, jpql);
         return new SDOQuery(this, kernelQuery); 
 	}
+	
+	@Override
+	public void close() {
+		super.close();
+		cache.clear();
+	}
 
-	Object find(DataObject data) {
-		return cache.get(data);
+	public DataObject find(Type type, Object oid) {
+		DataObject data = null;
+		Class<?> cls = repos.getJavaClass(type);
+		Object o = super.find(cls, oid);
+		if (o != null) 
+			data = createDataObject(o, true);
+		return data;
 	}
 	
-	DataObject createDataObject(Object pc) {
+	/**
+	 * Creates a SDO DataObject from the given strongly-typed Java instance.
+	 * 
+	 * @param pojo strongly-typed Java instance.
+	 * @return
+	 */
+	DataObject createDataObject(Object pojo, boolean findCached) {
+	    if (pojo == null)
+	        return null;
 		SDOInstanceMapping ctx = new SDOInstanceMapping(this, repos);
-		return ctx.populateDataObject(pc);
+		return ctx.populateDataObject(pojo, findCached);
+	}
+
+	/**
+	 * Creates a strongly-typed Java instance from the given SDO DataObject.
+	 * @param data
+	 * @return
+	 */
+	Object createPC(DataObject sdo, boolean findCached) {
+	    if (sdo == null)
+	        return null;
+		SDOInstanceMapping ctx = new SDOInstanceMapping(this, repos);
+		return ctx.populatePC(sdo);
 	}
 	
 	/**
@@ -181,7 +224,7 @@
 	
 	protected Type extractType(String s) {
 		int colon = s.indexOf(':');
-		return (colon == -1) ? null : repos.getType(s.substring(0,colon)); 
+		return (colon == -1) ? null : repos.getSDOType(s.substring(0,colon)); 
 	}
 	
 	protected String extractId(String s) {
@@ -200,4 +243,80 @@
 	public void cache(DataObject data, Object pc) {
 		cache.put(data, pc);
 	}
+	
+	public void removeCachedPC(Set<Object> pc) {
+		for (Object p:pc) {
+			removeCached(p);
+		}
+	}
+
+  public void removeCached(Set<DataObject> data) {
+    for (DataObject p:data) {
+      cache.remove(p);
+    }
+  }
+
+  public void sync(Set<Object> pcl) {
+		SDOInstanceMapping ctx = new SDOInstanceMapping(this, repos);
+		for (Object pc : pcl) {
+			if (findCached(pc) == null) {
+				continue;
+			}
+			ctx.populateDataObject(pc, true);
+		}
+	}
+
+	public void removeCached(Object pc) {
+		cache.removeReverse(pc);
+	}
+
+    public void clearCached() {
+       cache.clear();
+     }
+  
+	
+	public Type getSDOType(Class cls) {
+		return repos.getSDOType(cls);
+	}
+	
+    public Type getSDOType(Class cls, boolean mustExist) {
+        return repos.getSDOType(cls);
+    }
+  
+	public Object findPC(DataObject o) {
+		Class<?> cls = repos.getJavaClass(o.getType());
+		TypeMapping tm = repos.getMapping(o.getType(), true);
+        ChangeSummary changeSummary = o.getDataGraph().getChangeSummary();
+        Object id;
+        ChangeSummary.Setting st = changeSummary.getOldValue(o,tm.getIdentityMapping().getProperty());
+        if (st == null)
+          id = o.get(tm.getIdentityMapping().getProperty());
+        else
+          id = st.getValue();         
+		Object pc = super.find(cls, id);		
+		return pc;
+	}
+
+	public void applyChanges(DataObject root) {
+		if (!root.equals(root.getDataGraph().getRootObject())) {
+			throw new RuntimeException(_loc.get("no-root-object").toString());
+		}	    
+		ChangeSummary changeSummary = root.getDataGraph().getChangeSummary();
+
+    SDOInstanceMapping ctx = new SDOInstanceMapping(this, repos);
+		List changedObjects = changeSummary.getChangedDataObjects();
+		Iterator i = changedObjects.iterator();
+		while (i.hasNext()) {
+			DataObject o = (DataObject) i.next();
+
+			if (!(o.equals(root))) {
+			  ctx.applyChanges(o);
+			}
+		}
+	}
+
+  public String getApplyChangesMode() {
+    return applyChangesMode;
+  }
+	
 }

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManagerFactory.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManagerFactory.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManagerFactory.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOEntityManagerFactory.java Thu Dec  3 07:41:56 2009
@@ -33,6 +33,7 @@
  */
 @SuppressWarnings("serial")
 public class SDOEntityManagerFactory extends EntityManagerFactoryImpl {
+  private String applyChanges;
 	public SDOEntityManagerFactory() {
 		super();
 	}
@@ -48,4 +49,12 @@
     protected EntityManagerImpl newEntityManagerImpl(Broker broker) {
         return new SDOEntityManager(this, broker);
     }
+
+    public String getApplyChanges() {
+      return applyChanges;
+    }
+
+    public void setApplyChanges(String applyChanges) {
+      this.applyChanges = applyChanges;
+    }
 }

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOInstanceMapping.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOInstanceMapping.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOInstanceMapping.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOInstanceMapping.java Thu Dec  3 07:41:56 2009
@@ -18,24 +18,26 @@
  */
 package org.apache.openjpa.sdo;
 
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 
 import javax.persistence.PersistenceException;
 
+import org.apache.openjpa.persistence.EntityNotFoundException;
 import org.apache.openjpa.sdo.mapping.PropertyMapping;
 import org.apache.openjpa.sdo.mapping.TypeMapping;
 import org.apache.openjpa.util.OptimisticException;
 
+import commonj.sdo.ChangeSummary;
 import commonj.sdo.DataObject;
-import commonj.sdo.Property;
 import commonj.sdo.Type;
 import commonj.sdo.helper.DataFactory;
 
 /**
  * Converts SDO DataObject to PersistenceCapable instance and vice versa.
- * Conversion is essentially copying data from one represnetaion to another.
- * Two aspects are a) maintaining indentity/version correspondence between
+ * Conversion is essentially copying data from one representation to another.
+ * Two aspects are a) maintaining identity/version correspondence between
  * DataObject and PersistenceCapable representation b) closure of the instance
  * being converted. 
  * 
@@ -44,36 +46,51 @@
  *
  */
 public class SDOInstanceMapping {
-	SDOMappingRepository repos;
-	SDOEntityManager em;
-	BiDiMap<DataObject, Object> closure = new BiDiMap<DataObject, Object>();
+	private final SDOMetaDataFactory repos;
+	private final SDOEntityManager em;
+	private final BiDiMap<DataObject,Object> closure;
+    protected static final Object[] NULL_ARGS = new Object[]{};
 
-	public SDOInstanceMapping(SDOEntityManager em, SDOMappingRepository repos) {
+	public SDOInstanceMapping(SDOEntityManager em, SDOMetaDataFactory repos) {
 		this.repos = repos;
 		this.em = em;
+		this.closure = new BiDiMap<DataObject,Object>();
 	}
 	
 	/**
 	 * Populates a DataObject from the field values of the given object.  
 	 */
-	public DataObject populateDataObject(Object pc) {
-		Class cls = pc.getClass();
-		Type type = repos.getSDOType(cls, true);
+	public DataObject populateDataObject(Object pc, boolean findCached) {
+		Class<?> cls = ImplHelper.getEnhancedClass(pc);
+		Type type = repos.getSDOType(cls);
 		DataObject data = (DataObject) closure.getReverse(pc);
 		if (data != null) {
-			sync(pc, data);
 			return data;
 		}
-		data = newDataObject(type, pc);
 		TypeMapping tm = repos.getMapping(type, true);
-		List properties = data.getInstanceProperties();
-		for (Object p:properties) {
-			Property property = (Property)p;
-			PropertyMapping pm = tm.getMapping(property);
+		if (findCached) {
+    		if ((data = em.findCached(pc)) == null)	{
+    			data = tm.newDataObject();
+    			cache(data, pc);
+    		} else {
+    			closure.put(data, pc);
+    		}
+		} else {
+            data = tm.newDataObject();
+            cache(data, pc);
+		}
+		Collection<PropertyMapping> properties = tm.getMappings();
+		for (PropertyMapping pm : properties) {
 			try {
 				pm.populateDataObject(data, pc, this);
+			} catch (InvocationTargetException e) {
+				if (e.getTargetException() instanceof EntityNotFoundException) {
+					EntityNotFoundException en = (EntityNotFoundException) e.getTargetException();
+					throw en;
+				} else
+					throw new PersistenceException(e);					
 			} catch (Exception e) {
-				e.printStackTrace();
+				throw new PersistenceException(e);
 			}
 		}
 		return data;
@@ -85,25 +102,26 @@
 	 */
 	public Object populatePC(DataObject data) {
 		Type type = data.getType();
-		Class cls = repos.getJavaClass(data.getType(), true);
+		Class<?> cls = repos.getJavaClass(type);
 		
-		Object pc = findCached(data);
+		Object pc = closure.get(data);
 		if (pc != null) {
-			sync(pc, data);
+//			sync(pc, data);
 			return pc;
 		}
-		
-		pc = newPC(cls, data);
-		cache(data, pc);
-		TypeMapping mapping = repos.getMapping(type, true);
+		TypeMapping tm = repos.getMapping(type, true);
+		if ((pc = em.findCached(data)) == null)
+		{
+			pc = tm.newPC();
+			cache(data, pc);
+		} else 
+			closure.put(data, pc);
+		Collection<PropertyMapping> properties = tm.getMappings();
 		try {
-			List properties = data.getInstanceProperties();
-			for (Object p: properties) {
-				Property property = (Property)p;
-				if (!data.isSet(property)) {
+			for (PropertyMapping pm : properties) {
+/*				if (pm.getProperty() != null && !data.isSet(pm.getProperty())) {
 					continue;
-				} 
-				PropertyMapping pm = mapping.getMapping(property);
+				} */
 				pm.populatePC(pc, data, this);
 			} 
 		} catch (Exception ex) {
@@ -111,7 +129,92 @@
 		}
 		return pc;
 	}
+
+   /**
+   * Populate the given object with DataObjet changes taken from  a DataGraph change summary
+   */
+  public Object applyChanges(DataObject data) {
+    Object pc = closure.get(data);
+    if (pc != null) {
+      return pc;
+    }
+    ChangeSummary changeSummary = data.getDataGraph().getChangeSummary();
+    boolean changed = changeSummary.isCreated(data) || changeSummary.isDeleted(data) || changeSummary.isModified(data);
+    pc = em.findCached(data);
+    if (pc == null) {
+      pc = em.findPC(data);
+    }
+    if (!changed) {
+      if (pc == null && "merge".equals(em.getApplyChangesMode())) {
+        pc = applyChangesCreate(data, pc);
+      }
+    } else if (changeSummary.isCreated(data) && !changeSummary.isDeleted(data)) {
+      if (pc == null || "merge".equals(em.getApplyChangesMode())) {
+        pc = applyChangesCreate(data, pc);      
+      }
+    } else if (!changeSummary.isCreated(data) && !changeSummary.isDeleted(data)) {
+      if (pc != null) {
+        applyChangesModify(data, pc, changeSummary.getOldValues(data));                    
+      } else if ("merge".equals(em.getApplyChangesMode())) {
+        pc = applyChangesCreate(data, pc);
+      }
+    } else if (changeSummary.isDeleted(data)) {
+      if (pc != null) {
+        em.remove(pc);            
+        em.removeCached(pc);
+        pc = null;
+      }
+    }    
+    if (pc != null && !pc.equals(closure.get(data))) {
+      closure.put(data, pc);
+    }
+    return pc;
+  }	
+	
+  /**
+	 * Populate the given object with DataObjet changes taken from  a DataGraph change summary
+	 */
+	public Object applyChangesCreate(DataObject data, Object pc) {
+    Type type = data.getType();
+    Class cls = repos.getJavaClass(type);
+    TypeMapping tm = repos.getMapping(type, true);
+    if (pc == null)
+    {
+      pc = tm.newPC();
+      closure.put(data, pc);
+    }
+    Collection<PropertyMapping> properties = tm.getMappings();
+    try {
+      for (PropertyMapping pm:properties) {
+/*        if (pm.getProperty() != null && !data.isSet(pm.getProperty())) {
+          continue;
+        } */
+        pm.applyChangesCreate(data, pc, this);
+      } 
+    } catch (Exception ex) {
+      throw new PersistenceException(ex);
+    }
+    em.persist(pc);
+    return pc;
+	}
 	
+  /**
+   * Populate the given object with DataObjet changes taken from  a DataGraph change summary
+   */
+  public Object applyChangesModify(DataObject data, Object pc, List<ChangeSummary.Setting> changes) {
+    Type type = data.getType();
+    TypeMapping tm = repos.getMapping(type, true);
+    for (ChangeSummary.Setting change:changes) {
+      PropertyMapping pm = tm.getMapping(change.getProperty());     
+      try {
+        pm.applyChangesModify(data, pc, change, this);
+      } catch (Exception e) {
+        throw new PersistenceException(e);
+      }
+    }
+    return pc;
+  }
+  
 	/**
 	 * Create a new instance of the given Class and synchronize identity/version
 	 * information with the given DataObject.
@@ -119,7 +222,7 @@
 	Object newPC(Class cls, DataObject data) {
 		try {
 			Object pc = cls.newInstance();
-			sync(pc, data);
+//			sync(pc, data);
 			return pc;
 		} catch (Exception e) {
 			throw new PersistenceException(e);
@@ -133,7 +236,7 @@
 	DataObject newDataObject(Type type, Object pc) {
 		try {
 			DataObject data = DataFactory.INSTANCE.create(type); 
-			sync(pc, data);
+//			sync(pc, data);
 			return data;
 		} catch (Exception e) {
 			throw new PersistenceException(e);
@@ -143,7 +246,7 @@
 	/**
 	 * Get the closure of DataObjects and PersistenceCapable instances.
 	 */
-	public Map getClosure() {
+	public BiDiMap<DataObject,Object> getClosure() {
 		return closure;
 	}
 	
@@ -162,7 +265,7 @@
 	 */
 	Object findCached(DataObject data) {
 		Object pc = closure.get(data);
-		if (pc == null)
+		if (pc == null) 
 			return em.findCached(data);
 		return pc;
 	}
@@ -195,12 +298,12 @@
 	 */
 	void sync(Object pc, DataObject data) {
 		Object idValue = ImplHelper.getIdValue(data);
-		Object version = ImplHelper.getVersion(data);
-		if (idValue != null) { // existing Data
-			int pcversion = (Integer)em.getVersion(pc); 
+		int version = ImplHelper.getVersion(data);
+		int pcversion = (Integer)em.getVersion(pc); 
+		if (version != 0) { // existing Data
 			if (pcversion!=0 && !em.getVersion(pc).equals(version))
 				throw new OptimisticException(pc);
-		} else {
+		} else if (pcversion!=0) {
 			try {
 				repos.getMapping(data.getType(), true).getIdentityMapping()
 					.populateDataObject(data, pc, this);
@@ -211,6 +314,8 @@
 			}
 		}
 	}
-
-
+  
+	public SDOEntityManager getEm() {
+		return em;
+	}
 }

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOMetaDataFactory.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOMetaDataFactory.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOMetaDataFactory.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOMetaDataFactory.java Thu Dec  3 07:41:56 2009
@@ -18,71 +18,167 @@
  */
 package org.apache.openjpa.sdo;
 
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.enhance.PCEnhancer;
+import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
+import org.apache.openjpa.jdbc.kernel.exps.GetColumn;
 import org.apache.openjpa.lib.conf.Configuration;
-import org.apache.openjpa.lib.meta.ClassArgParser;
-import org.apache.openjpa.persistence.PersistenceMetaDataFactory;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.Files;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.MultiClassLoader;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.persistence.AnnotationPersistenceMetaDataParser;
+import org.apache.openjpa.persistence.jdbc.PersistenceMappingFactory;
+import org.apache.openjpa.sdo.mapping.PropertyMapping;
+import org.apache.openjpa.sdo.mapping.SDOMappingStrategyInstaller;
+import org.apache.openjpa.sdo.mapping.TypeMapping;
+import org.apache.openjpa.util.UserException;
 
+import serp.bytecode.BCClass;
+import serp.bytecode.BCClassLoader;
+import serp.bytecode.BCField;
+import serp.bytecode.BCMethod;
+import serp.bytecode.Code;
+import serp.bytecode.Constants;
+import serp.bytecode.Project;
+
+import commonj.sdo.Property;
 import commonj.sdo.Type;
 
 /**
- * A specialized MetaDataFactory to process XML Schema based SDO MetaModel.
- * <br>
- * Caches bi-directional maps of SDO Type and Java Class.
+ * A specialized MetaDataFactory to generate dynamic Java classes for SDO Types found in XML Schema.
  * <br>
-  * Uses a {@link SDOTypeParser parser} to find SDO Types defined in *.xsd XML
- * Schema Definition resources. These resources are specified via configuration
- * as<br>
+  * Uses a {@link SDOTypeParser parser} to find SDO Types defined in XML Schema Definition resources as *.xsd files. 
+  * These resources are specified via configuration as<br>
  * <pre>
- * &lt;property name="openjpa.MetaDataFactory" value="sdo(Resources=my.xsd"/&gt;
+ * &lt;property name="openjpa.MetaDataFactory" value="sdo(Resources=person.xsd;po.xsd"/&gt;
  * </pre>
- * and resolved against the thread context's classloader.
+ * <br>
+ * The dynamically generated Java classes are annotated with JPA mapping information, enhanced and added to
+ * metadata repository as normal Java classes for OpenJPA kernel to process. The dynamic, enhanced Java classes
+ * are loaded by a {@linkplain SDODynamicClassResolver specialized classloader}.
  *
  * @author Pinaki Poddar
+ * 
  * @since 0.1.0
  */
-public class SDOMetaDataFactory extends PersistenceMetaDataFactory {
+public class SDOMetaDataFactory extends PersistenceMappingFactory {
+    private static Localizer _loc = Localizer.forPackage(SDOMetaDataFactory.class);
 	private OpenJPAConfiguration conf;
-	private String resources;
-	private List<String> resourceList;
 	private SDOTypeParser sdoTypeParser;
-	private Set<String> _typeNames = new HashSet<String>();
-	private SDOMappingRepository repos;
-	
+	private boolean _initailizing = false;
+    // Associates SDO Type and Java Class
+    private BiDiMap<Type, Class<?>> _cache = new BiDiMap<Type, Class<?>>();
+    private static final String ALIASPREFIX = "";
+    private static final String FIELDINDEXPREFIX = ".";
+    private static final String ALIASCONSTRUCTOR = "CONSTRUCTOR";
+    private Log _log;
+    // Mapping for each SDO Type
+    private Map<Type, TypeMapping> mappings = new HashMap<Type, TypeMapping>();
+    private File  _root;
+
 	@Override
 	public void setConfiguration(Configuration conf) {
 		super.setConfiguration(conf);
 		this.conf = (OpenJPAConfiguration)conf;
-		repos = new SDOMappingRepository(this.conf);
+	    _log = conf.getLog(OpenJPAConfiguration.LOG_METADATA);
 	}
 	
-	public SDOMappingRepository getSDOMappingRepository() {
-		return repos;
-	}
+	   /**
+     * Gets the strategy used for mapping of the given SDO Type.
+     * Constructs if necessary. 
+     * Resolving a mapping if asked.
+     */
+    public TypeMapping getMapping(Type type, boolean resolve) {
+        TypeMapping mapping = mappings.get(type);
+        Class<?> cls = getJavaClass(type);
+        if (mapping == null) {
+            if (_log.isInfoEnabled())
+                _log.info(_loc.get("type-mapping-new", type.getName(), toString(cls)).toString());
+            mapping = SDOMappingStrategyInstaller.decideStrategy(type, cls);
+            mappings.put(type, mapping);
+        }
+        if (resolve && !mapping.isResolved()) {
+            if (_log.isInfoEnabled())
+                _log.info(_loc.get("type-mapping-resolve", type.getName(), toString(cls)).toString());
+            MetaDataRepository mdr = conf.getMetaDataRepositoryInstance();
+            ClassMetaData cm = mdr.getCachedMetaData(cls);
+            if (cm == null) {
+                cm = mdr.getMetaData(cls, null, true);              
+            }
+            if (cm == null) {
+                throw new RuntimeException(_loc.get("resolve-mapping-failed", toString(cls), mdr).toString());
+            }
+            mapping.resolve(cm);
+        }
+        return mapping;
+    }
 	
 	@Override
-	public ClassArgParser newClassArgParser() {
-		return getSDOTypeParser();
+	public SDOTypeParser newClassArgParser() {
+        if (sdoTypeParser == null) {
+            sdoTypeParser = new SDOTypeParser(conf);
+        }
+        return sdoTypeParser;
 	}
 	
-	public SDOTypeParser getSDOTypeParser() {
-		if (sdoTypeParser == null) {
-			sdoTypeParser = new SDOTypeParser(conf);
-		}
-		return sdoTypeParser;
-	}
-		
-	public void setResources(String resources) {
-		this.resources = resources;
-	}
+	@Override
+    protected AnnotationPersistenceMetaDataParser newAnnotationParser() {
+        if ((repos.getConfiguration() instanceof JDBCConfigurationImpl))
+            return super.newAnnotationParser();
+        else
+        	return new AnnotationPersistenceMetaDataParser(repos.getConfiguration());
+    }
 	
-	public String getResources() {
-		return resources;
+	/**
+	 * Sets the XML Schema definition as *.xsd files that contain SDO Types. 
+	 * Parse the *.xsd resources to extract the SDO Type names.
+	 */
+	@Override
+	public void setResources(String xsdList) {
+	    super.setResources(xsdList);
+        if (rsrcs == null || rsrcs.isEmpty())
+            return;
+        for (String token : rsrcs) {
+            if (token.endsWith(".xsd")) {
+                newClassArgParser().parseXSDResource(token);
+            }
+        }
+	}
+
+    /**
+     * Get the fully-qualified, persistent Java class names.
+     * Invokes the parser for parsing XML Schema Definitions. 
+     * The parsed SDO types are then resolved to Java classes by the Mapping
+     * Repository, before returning from this method. 
+     */
+    @Override
+    public Set<String> getPersistentTypeNames(boolean devpath, ClassLoader envLoader) {
+        Set<String> names = parsePersistentTypeNames(envLoader);
+        initializeDynamicClasses(envLoader);
+        return names;
+    }
+    
+	@Override
+	protected Set<String> parsePersistentTypeNames(ClassLoader loader) {
+	    Set<String> javaTypeNames = new HashSet<String>();
+	    javaTypeNames.addAll(Arrays.asList(SDOTypeParser.toJavaClassNames(SDOTypeParser.getParsedTypes())));
+	    return javaTypeNames;
 	}
 	
 	public String getGeneratedClassDirectory() {
@@ -90,41 +186,340 @@
 	}
 	
 	public void setGeneratedClassDirectory(String dir) {
-		repos.setRootDirectory(dir);
 	}
-
 	
-	@Override
-	public void endConfiguration() {
-		if (resources == null || resources.trim().length()==0)
-			return;
-		resourceList = new ArrayList<String>();
-		String[] tokens = resources.split(";");
-		for (String token:tokens) {
-			resourceList.add(token);
-		}
+	private BCClassLoader getDynamicClassLoader(ClassLoader envLoader) {
+        if (envLoader instanceof MultiClassLoader) {
+            ClassLoader[] children = ((MultiClassLoader)envLoader).getClassLoaders();
+            for (ClassLoader child : children) {
+                if (child instanceof BCClassLoader)
+                    return (BCClassLoader)child;
+            }
+        }
+        return ((SDODynamicClassResolver)conf.getClassResolverInstance()).getDynamicClassLoader(envLoader);
 	}
 	
 	/**
-	 * Get the fully-qualified, persistent Java class names.
-	 * Invokes the parser for parsing XML Schema Definitions. 
-	 * The parsed SDO types are then resolved to Java classes by the Mapping
-	 * Repository, before returning from this method. 
+	 * Creates dynamic, enhanced Java classes for all the SDO Types known to this receiver.
+	 *  
+	 * @param loader the parent loader of the loader that will load the dynamic Java Classes.
 	 */
-	@Override
-    public Set getPersistentTypeNames(boolean devpath, ClassLoader envLoader) {
-    	if (resourceList == null || resourceList.isEmpty()) 
-    		return _typeNames;
-    	SDOTypeParser parser = getSDOTypeParser();
-    	List<String> tmpList = new ArrayList<String>(resourceList);
-    	resourceList.clear();
-    	for (String resource:tmpList) {
-    		List<Type> types = parser.parseXSDResource(resource);
-    		for (Type type:types) {
-    			Class c = repos.getJavaClass(type, true);//(type, envLoader);
-    			_typeNames.add(c.getName());
-    		}
-    	}
-    	return _typeNames;
+	private void initializeDynamicClasses(ClassLoader envLoader) {
+	    // this is a reentrant method
+	    if (_initailizing)
+	        return;
+	    _initailizing = true;
+	    
+        Collection<Type> sdoTypes = SDOTypeParser.getParsedTypes();
+        BCClassLoader tempLoader = new BCClassLoader(new Project());
+        Map<Type,BCClass> generatedClasses = new HashMap<Type, BCClass>();
+	    for (Type sdoType : sdoTypes) {
+              BCClass bccls = generateClass(sdoType, tempLoader);
+              log(_loc.get("generate-unenhanced", bccls.getName(), tempLoader, tempLoader.getParent()));
+              generatedClasses.put(sdoType, bccls);
+        }
+	    
+        for (Map.Entry<Type, BCClass> e : generatedClasses.entrySet()) {
+          log(_loc.get("generate-enhanced", e.getValue().getName(), tempLoader, tempLoader.getParent()));
+          BCClass bccls = enhanceByteCode(e.getValue(), repos, tempLoader);
+          generatedClasses.put(e.getKey(), bccls);
+        }
+      
+        // Now reload all enhanced class with a new loader whose parent loader is the envLoader
+        BCClassLoader dynamicLoader = getDynamicClassLoader(envLoader);
+        for (Map.Entry<Type, BCClass> e : generatedClasses.entrySet()) {
+            ByteArrayInputStream bytes = new ByteArrayInputStream(e.getValue().toByteArray());
+            dynamicLoader.getProject().loadClass(bytes, dynamicLoader);
+        }
+        for (Map.Entry<Type, BCClass> e : generatedClasses.entrySet()) {
+            String className = e.getValue().getName();
+            try {
+                Class<?> cls = Class.forName(className, true, dynamicLoader);
+                _cache.put(e.getKey(), cls);
+                log(_loc.get("load-enhanced", cls.getName(), dynamicLoader, dynamicLoader.getParent()));
+            } catch (Exception ex) {
+                throw new RuntimeException(_loc.get("load-enhanced-error", className, dynamicLoader, 
+                        dynamicLoader.getParent()).getMessage(), ex);
+            }
+      }
+	}
+	
+	void log(Localizer.Message m) {
+	    System.err.println(m.toString());
+	}
+	
+    public Class<?> getJavaClass(Type type) {
+        return _cache.get(type);
+    }
+    
+    public Type getSDOType(Class<?> cls) {
+        return _cache.getReverse(cls);
+    }
+    
+    public Type getSDOType(String name) {
+        return SDOTypeParser.findType(name);
+    }
+    
+    /**
+     * Generates unenhanced bytecode for dynamic Java class the given SDO Type.
+     * 
+     * @param type a SDO Type 
+     * @param loader a classloader for the dynamic Java class.
+     * @return bytecode for an unenhanced class
+     */
+    public BCClass generateClass(Type type, BCClassLoader loader) {
+        String javaClassName = ImplHelper.getFullClassName(type);
+        _log.info(_loc.get("generate-dynamic-class", javaClassName));
+        BCClass bccls = loader.getProject().loadClass(javaClassName);
+        
+        TypeMapping tm = SDOMappingStrategyInstaller.decideStrategy(type, null);
+        
+        // clear the class
+        bccls.clearAttributes();
+        bccls.clearDeclaredFields();
+        bccls.clearDeclaredInterfaces();
+        bccls.clearDeclaredMethods();
+        
+        // set it for Java 5
+        bccls.setMajorVersion(49); // 49 bytecode spec = 1.5 source spec
+        bccls.setMinorVersion(0);
+        bccls.setName(javaClassName);
+        bccls.makePublic();
+        if ((type.getBaseTypes().size() > 0)) {
+            bccls.setSuperclass(ImplHelper.getFullClassName((Type)type.getBaseTypes().get(0)));
+        } else {
+            bccls.setDeclaredInterfaces(new String[]{"java.io.Serializable"});
+        }
+        if (type.isAbstract()) {
+            bccls.setAbstract(true);
+        } else {
+            bccls.addDefaultConstructor().makePublic();         
+        }
+        // annotate the class with JPA Annotation
+        tm.annotate(bccls);     
+        
+        // add private field with bean-style get/set methods for each property
+        Collection<PropertyMapping> properties = tm.getMappings();
+        for (PropertyMapping pm:properties) {
+            if (pm.getProperty() != null && pm.getProperty().getContainingType() != type) {
+                System.err.println(pm.getProperty() + " ignored ");
+                continue;
+            }
+            // this is for container property
+            String tname = pm.getFieldTypeName();
+            if (tname.indexOf("<") != -1) {
+                tname = tname.substring(0, tname.indexOf("<"));
+            }
+            addField(bccls, pm.getFieldName(), tname, pm);          
+        }
+        if (!type.isAbstract()) {
+          List<PropertyMapping[]> csfields = getConstructors(tm);
+          if (csfields != null && !csfields.isEmpty()) {
+            addConstructors(bccls, csfields);
+          }
+        }
+        bccls = reloadDynamicClass(bccls, loader);
+//      write(bccls);
+        return bccls;
+    }
+    
+    /**
+     * Enhance the given bytecode.
+     * 
+     * @param bccls bytecode to be enhanced
+     * @param repos repository for metadata access
+     * @param loader loading classes and resources
+     *  
+     * @return enhanced Java class
+     */
+    public BCClass enhanceByteCode(BCClass bccls, MetaDataRepository repos, BCClassLoader loader) {
+        _log.info(_loc.get("enhance-dynamic-class", bccls.getName()));
+        repos.setValidate(MetaDataRepository.VALIDATE_NONE);
+        repos.setSourceMode(MetaDataRepository.MODE_META);
+        if (!ImplHelper.isEnhanced(bccls.toByteArray())) {
+            PCEnhancer enhancer = new PCEnhancer(conf, bccls, repos, loader);
+            int status = enhancer.run();
+            if (status != PCEnhancer.ENHANCE_PC)
+                throw new RuntimeException(bccls.getName() + " not enhanced. Enhancer status = " + status);
+            bccls = enhancer.getPCBytecode();
+        }
+        bccls = reloadDynamicClass(bccls, loader);
+        return bccls;
+    }       
+
+    public BCClass reloadDynamicClass(BCClass bccls, BCClassLoader newloader) {
+//      SDODynamicClassLoader loader = new SDODynamicClassLoader(Thread.currentThread().getContextClassLoader());
+        byte[] b = bccls.toByteArray();
+        bccls.getProject().removeClass(bccls);
+        bccls = newloader.getProject().loadClass(new ByteArrayInputStream(b), newloader);               
+        return bccls;
+    }
+    
+    Class reloadClass(BCClass bcls) {
+        write(bcls);
+        try {
+            return Class.forName(bcls.getName());
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    
+    void write(BCClass bcls) {
+        File classFile = getClassFile(bcls);
+        classFile.deleteOnExit();
+        if (_log.isInfoEnabled()) {
+            _log.info(_loc.get("write-class", classFile.getAbsolutePath()).toString());
+        }
+        try {
+            bcls.write(classFile);
+        } catch (IOException e) {
+            throw new UserException(e);
+        }
+    }
+
+    File getClassFile(BCClass bcls) {
+        File pkgdir = Files.getPackageFile(_root, bcls.getPackageName(), true);
+        return new File(pkgdir, bcls.getClassName() + ".class");
     }
+    
+    void setRootDirectory(String rootPath) {
+        File file = new File(rootPath);
+        File rootDir = (file.isAbsolute()) ? file : new File(_root, rootPath);
+        if (rootDir.exists() && rootDir.isDirectory()) {
+                _root = rootDir;
+        } else {
+            _log.warn(_loc.get("wrong-root-dir", rootPath, _root.getAbsolutePath()));
+        }
+    }
+    
+    /**
+     * Add bean getters and setters.
+     */    
+    private BCField addField (BCClass bc, String fieldName, String fieldType, PropertyMapping pm) {
+        if (_log.isTraceEnabled())
+            _log.trace(_loc.get("dynamic-method", fieldName,fieldType).toString());
+        
+        BCField field = bc.declareField(fieldName, fieldType);
+        field.setAccessFlags(Constants.ACCESS_PRIVATE);
+        pm.annotate(field);
+
+        // getter
+        String getterName = "get" + StringUtils.capitalize(fieldName);
+        BCMethod meth = bc.declareMethod(getterName, fieldType, null);
+        meth.makePublic();
+//      pm.annotate(meth);
+        Code code = meth.getCode(true);
+        code.aload().setThis();
+        code.getfield().setField(field);
+        code.xreturn().setType(fieldType);
+        code.calculateMaxStack();
+        code.calculateMaxLocals();
+
+        // setter
+        String setterName = "set" + StringUtils.capitalize(fieldName);
+        meth = bc.declareMethod(setterName, "void", new String[]{fieldType});
+        meth.makePublic();
+        code = meth.getCode(true);
+        code.aload().setThis();
+        code.xload().setParam(0).setType(fieldType);
+        code.putfield().setField(field);
+        code.vreturn();
+        code.calculateMaxStack();
+        code.calculateMaxLocals();
+        
+        return field;
+    }
+    
+    private void addConstructors(BCClass bccls, List<PropertyMapping[]> csfields) {
+      for (PropertyMapping[] cfields:csfields) {
+        addConstructor(bccls, cfields);
+      }
+    }
+    
+    private void addConstructor(BCClass bccls, PropertyMapping[] cfields) {
+      String[] params = new String[cfields.length];
+      int i = 0;
+      for (PropertyMapping pm:cfields) {
+        String tname = pm.getFieldTypeName();
+        if (tname.indexOf("<") != -1) {
+          tname = tname.substring(0, tname.indexOf("<"));
+        }
+        params[i++] = tname;
+      }
+      BCMethod method = bccls.getDeclaredMethod("<init>", params);
+      if (method != null)
+          return;
+
+      BCMethod defc = bccls.getDeclaredMethod("<init>", (String[]) null);
+      method = bccls.declareMethod("<init>", "void", params);
+      method.makePublic();
+      Code code = method.getCode(true);
+      if (defc != null) {
+        code.xload().setThis();
+        code.invokespecial()
+            .setMethod(defc);        
+      } else {
+        code.xload().setThis();
+        code.invokespecial()
+            .setMethod(bccls.getSuperclassName(), "<init>", "void", null);        
+      }
+      i = 0;
+      for (PropertyMapping pm:cfields) {
+        String tname = pm.getFieldTypeName();
+        if (tname.indexOf("<") != -1) {
+          tname = tname.substring(0, tname.indexOf("<"));
+        }
+        code.aload().setThis();
+        code.xload().setParam(i++).setType(tname);
+        code.putfield().setField(pm.getFieldName(), tname);
+      }
+      code.vreturn();
+      code.calculateMaxStack();
+      code.calculateMaxLocals();
+      return;
+  }
+    
+    String toString(Class cls) {
+        return (cls == null) ? "null" : cls + " loaded by " + cls.getClassLoader(); 
+    }
+
+  public static List<PropertyMapping[]> getConstructors(TypeMapping tm) {
+    Type type = tm.getType();
+    Map<String, Map<Integer, Property>> bimap = new HashMap<String, Map<Integer, Property>>();
+    for (Property p:(List<Property>)type.getProperties()) {
+      if (!p.getAliasNames().isEmpty()) {
+        for (String alias:(List<String>)p.getAliasNames()) {
+          if (alias.startsWith(ALIASPREFIX + ALIASCONSTRUCTOR)) {
+            int fi = alias.lastIndexOf(FIELDINDEXPREFIX);
+            if (fi != -1) {
+              Integer pos = new Integer(alias.substring(fi + 1));
+              String key = alias.substring(0, fi);
+              Map<Integer, Property> params;
+              if (bimap.containsKey(key)) {
+                params = bimap.get(key);
+              } else {
+                params = new HashMap<Integer, Property>();
+                bimap.put(key, params);
+              }
+              params.put(pos, p);
+            }
+          }
+        }
+      }
+    }
+    if (!bimap.isEmpty()) {
+      List<PropertyMapping[]> ret = new ArrayList<PropertyMapping[]>();
+      for (Map<Integer, Property> params:bimap.values()) {
+        PropertyMapping[] pms = new PropertyMapping[params.size()];
+        for (Map.Entry<Integer, Property> param:params.entrySet()) {
+          pms[param.getKey()] = tm.getMapping(param.getValue());
+        }
+        ret.add(pms);
+      }
+      return ret;
+    }
+    return null;
+  }
+
 }

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOProductDerivation.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOProductDerivation.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOProductDerivation.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOProductDerivation.java Thu Dec  3 07:41:56 2009
@@ -60,6 +60,7 @@
         Value value = conf.getValue("EntityManagerFactory");
         value.setAlias(SDO, SDOEntityManagerFactory.class.getName());
         conf.metaFactoryPlugin.setAlias(SDO, SDOMetaDataFactory.class.getName());
+        conf.setClassResolver(new SDODynamicClassResolver());
         return true;
     }	
     

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOQuery.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOQuery.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOQuery.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOQuery.java Thu Dec  3 07:41:56 2009
@@ -37,7 +37,7 @@
 @SuppressWarnings("serial")
 class SDOQuery extends QueryImpl implements OpenJPAQuery {
     public SDOQuery(EntityManagerImpl em, org.apache.openjpa.kernel.Query query) {
-    	super(em, query);
+    	super(em, PersistenceExceptions.getRollbackTranslator(em), query);
     }
 	
     public List getResultList() {
@@ -53,8 +53,16 @@
             else
                 return ret;
         }
-
         return Collections.singletonList(ob);
     }
 
+    public Object getSingleResult() {
+    	SDOEntityManager em = (SDOEntityManager)getEntityManager();
+    	Object o = super.getSingleResult();
+		if (em.getSDOType(ImplHelper.getEnhancedClass(o)) != null) {
+			return em.createDataObject(o, true);
+		} else {
+			return o;
+		}
+    }
 }

Modified: labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOTypeParser.java
URL: http://svn.apache.org/viewvc/labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOTypeParser.java?rev=886691&r1=886690&r2=886691&view=diff
==============================================================================
--- labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOTypeParser.java (original)
+++ labs/fluid/src/main/java/org/apache/openjpa/sdo/SDOTypeParser.java Thu Dec  3 07:41:56 2009
@@ -3,40 +3,38 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.apache.openjpa.conf.OpenJPAConfiguration;
-import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.meta.ClassArgParser;
 import org.apache.openjpa.lib.util.Localizer;
 
-import commonj.sdo.Property;
 import commonj.sdo.Type;
 import commonj.sdo.helper.XSDHelper;
 
 /**
  * Parses XML Schema definition for SDO Types.
+ * Statically caches the parsed types indexed by their SDO Type name as well as fully-qualified Java class names.
+ * Avoids repeated parse of the same resource.
  * 
  * @author Pinaki Poddar
  * @since 0.1.0
  */
 public class SDOTypeParser extends ClassArgParser {
-	private static final Localizer _loc = Localizer.forPackage
-		(SDOTypeParser.class);
-	private static Map<String, List<Type>> parsedResource = 
-		new HashMap<String, List<Type>>();
+	private static final Localizer _loc = Localizer.forPackage(SDOTypeParser.class);
+	private static Map<String, List<Type>> parsedResource = new HashMap<String, List<Type>>();
+	private static Map<String, Type> parsedTypes = new HashMap<String, Type>();
 	private Log _log;	
 	
 	/**
 	 * Supply configuration.
 	 */
-	SDOTypeParser(OpenJPAConfiguration conf) {
+	public SDOTypeParser(OpenJPAConfiguration conf) {
 		_log = conf.getLog(OpenJPAConfiguration.LOG_METADATA);
 	}
 	
@@ -48,17 +46,17 @@
 		}
 		
 		_log.info(_loc.get("parse-xml-schema", resource));
-		InputStream xsdInputStream = Thread.currentThread()
-				.getContextClassLoader().getResourceAsStream(resource);
+		ClassLoader loader = Thread.currentThread().getContextClassLoader();
+		InputStream xsdInputStream = loader.getResourceAsStream(resource);
 		if (xsdInputStream == null) {
 			if (_log.isWarnEnabled()) {
-				_log.warn(_loc.get("xsd-not-found", resource).toString());
+				_log.warn(_loc.get("xsd-not-found", resource, getClassLoader()).toString());
 			}
-			return Collections.EMPTY_LIST;
+			return Collections.emptyList();
 		}
 		List<Type> userTypes = new ArrayList<Type>();
 		try {
-			if (XSDHelper.INSTANCE==null)
+			if (XSDHelper.INSTANCE == null)
 				throw new RuntimeException("no-sdo-provider");
 			List types = XSDHelper.INSTANCE.define(xsdInputStream, null);
 			for (Object t : types) {
@@ -68,6 +66,7 @@
 				if (!(type.isDataType() || "DocumentRoot".equals(type.getName())
 						|| ImplHelper.isContainer(type))) {
 					userTypes.add(type);
+					parsedTypes.put(type.getName(), type);
 				}
 			}
 		} finally {
@@ -90,30 +89,44 @@
 	 */
 	@Override
 	public String[] parseTypeNames(String resource) {
-		if (resource==null || !resource.endsWith(".xsd"))
+		if (resource == null || !resource.endsWith(".xsd"))
 			return super.parseTypeNames(resource);
-		return toNames(parseXSDResource(resource));
+		return toJavaClassNames(parseXSDResource(resource));
 	}
 	
-	String[] toNames(List<Type> types) {
-		List<String> names = new ArrayList<String>();
-		for (Type type:types) {
-			String className = ImplHelper.getFullClassName(type); 
-			names.add(className);
+	/**
+	 * Gets fully-qualified Java class names for the given list of SDO Types. 
+	 */
+	public static String[] toJavaClassNames(Collection<Type> types) {
+	    if (types == null)
+	        return new String[0];
+		String[] names = new String[types.size()];
+		int i = 0;
+		for (Type type : types) {
+			names[i++] = ImplHelper.getFullClassName(type);
 		}
-		return names.toArray(new String[names.size()]);
+		return names;
 	}
 	
 	/**
-	 * Find a type of given name from all the types parsed from resources.
+	 * Find a SDO type of given name from all the currently parsed types.
 	 */
-	public Type findType(String name) {
-		for (List<Type> types:parsedResource.values()) {
-			for (Type type:types) {
-				if (type.getName().equals(name))
-					return type;
-			}
-		}
-		return null;
+	public static Type findType(String name) {
+	    return parsedTypes.get(name);
+	}
+	
+	/**
+	 * Gets all SDO types parsed so far.
+	 * @return
+	 */
+	public static Collection<Type> getParsedTypes() {
+	    return parsedTypes.values();
+	}
+	
+	/**
+	 * Get SDO Types parsed from the given resource.
+	 */
+	public static List<Type> getParsedTypes(String resource) {
+		return parsedResource.get(resource); 
 	}
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org