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>
- * <property name="openjpa.MetaDataFactory" value="sdo(Resources=my.xsd"/>
+ * <property name="openjpa.MetaDataFactory" value="sdo(Resources=person.xsd;po.xsd"/>
* </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