You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by si...@apache.org on 2011/05/19 01:32:19 UTC

svn commit: r1124464 - in /labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo: MongoEntityLazyRelations.aj MongoEntityTransactionMethods.aj PropertyInfoAdditions.aj Transaction.java

Author: simoneg
Date: Wed May 18 23:32:18 2011
New Revision: 1124464

URL: http://svn.apache.org/viewvc?rev=1124464&view=rev
Log:
Keep track of removed entities, to implement orphan removal and to persist entities modified before being detached from the main graph

Modified:
    labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityLazyRelations.aj
    labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityTransactionMethods.aj
    labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/PropertyInfoAdditions.aj
    labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/Transaction.java

Modified: labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityLazyRelations.aj
URL: http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityLazyRelations.aj?rev=1124464&r1=1124463&r2=1124464&view=diff
==============================================================================
--- labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityLazyRelations.aj (original)
+++ labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityLazyRelations.aj Wed May 18 23:32:18 2011
@@ -3,6 +3,7 @@ package org.apache.magma.database.mongo;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -95,7 +96,11 @@ public aspect MongoEntityLazyRelations {
 		bh.setValue(pi.getName(), ret);
 		bh.commit();			
 
-		bean.loaded(pi.getName());
+		if (dynamic) {
+			bean.loaded(pi.getName(), collection);
+		} else {
+			bean.loaded(pi.getName(), (Collection)null);
+		}
 		return ret;
 	}
 
@@ -130,7 +135,13 @@ public aspect MongoEntityLazyRelations {
 		bh.setValue(pi.getName(), ret);
 		bh.commit();			
 		
-		bean.loaded(pi.getName());
+		Class valclazz = pi.getMapValueClass();
+		if (MongoEntity.class.isAssignableFrom(valclazz)) {
+			bean.loaded(pi.getName(), collection.values());			
+		} else {
+			bean.loaded(pi.getName(), (Collection)null);			
+		}
+		
 		return ret;
 	}
 	
@@ -167,24 +178,55 @@ public aspect MongoEntityLazyRelations {
 			BeanHandler bh = bean.handler();
 			bh.setValue(pi.getName(), ret);
 			bh.commit();			
+			bean.loaded(pi.getName(), ret);			
+		} else if (ret != null) {
+			bean.loaded(pi.getName(), ret);			
+			bean.dirtyHandleProperty(pi, ret);
 		}
 		
-		bean.loaded(pi.getName());			
 		return ret;
 	}	
 	
 	
 	// Loadeds properties
-	private Set<String> MongoEntity.loadeds;
+	private Map<String, Set<MongoEntity>> MongoEntity.loadeds;
 	
 	boolean MongoEntity.isLoaded(String name) {
 		if (loadeds == null) return false;
-		return loadeds.contains(name);
+		return loadeds.containsKey(name);
+	}
+	
+	Collection<MongoEntity> MongoEntity.getLoaded(String name) {
+		if (loadeds == null) return Collections.emptyList();
+		Collection<MongoEntity> ret =loadeds.get(name);
+		if (ret == null) return Collections.emptyList();
+		return ret;
 	}
 	
-	void MongoEntity.loaded(String name) {
-		if (loadeds == null) loadeds = new HashSet<String>();
-		loadeds.add(name);
+	Set<Map.Entry<String, Set<MongoEntity>>> MongoEntity.getLoadedsEntry() {
+		if (loadeds == null) return Collections.EMPTY_SET;
+		return loadeds.entrySet();
+	}
+	
+	void MongoEntity.loaded(String name, MongoEntity previous) {
+		if (previous != null) {
+			this.loaded(name, Arrays.asList(previous));
+		} else {
+			this.loaded(name, (Collection)null);
+		}
+	}
+	void MongoEntity.loaded(String name, Collection<MongoEntity> previous) {
+		if (loadeds == null) loadeds = new HashMap<String,Set<MongoEntity>>();
+		Set<MongoEntity> entities = loadeds.get(name);
+		if (previous != null) {
+			if (entities == null) {
+				entities = new HashSet<MongoEntity>();
+				loadeds.put(name, entities);
+			}
+			entities.addAll(previous);
+		} else {
+			loadeds.put(name, null);
+		}
 	}
 	
 	

Modified: labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityTransactionMethods.aj
URL: http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityTransactionMethods.aj?rev=1124464&r1=1124463&r2=1124464&view=diff
==============================================================================
--- labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityTransactionMethods.aj (original)
+++ labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityTransactionMethods.aj Wed May 18 23:32:18 2011
@@ -3,7 +3,10 @@ package org.apache.magma.database.mongo;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Collection;
 
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.magma.beans.BeanHandler;
 import org.apache.magma.beans.PropertyInfo;
 import org.aspectj.lang.reflect.MethodSignature;
 
@@ -70,11 +73,14 @@ public aspect MongoEntityTransactionMeth
 				bean.dirtied();
 			} else if (pi.isSubEntity()) {
 				// TODO persist of an embedded doc
-			} else if (pi.isBasicType() || pi.isMongoPersisted() || (pi.getType() != null && Enum.class.isAssignableFrom(pi.getType()))) {
+			} else if (pi.isBasicType() || (pi.getType() != null && Enum.class.isAssignableFrom(pi.getType()))) {
 				// Basic types goes straight
 				bean.checkGetBson().put(pi.getJpaColName(), MongoUtils.convertToMongo(val));
 				bean.dirtyModified(pi, MongoUtils.convertToMongo(val));
-				bean.loaded(pi.getName());
+			} else if (pi.isMongoPersisted()) {
+				if (!bean.isLoaded(pi.getName())) bean.loaded(pi.getName(), (Collection)null);
+				bean.checkGetBson().put(pi.getJpaColName(), MongoUtils.convertToMongo(val));
+				bean.dirtyModified(pi, MongoUtils.convertToMongo(val));				
 			} else if (pi.isCollection()) {
 				// TODO change in collection!
 				throw new UnsupportedOperationException();
@@ -82,14 +88,24 @@ public aspect MongoEntityTransactionMeth
 		}		
 	}
 	
-	after(MongoEntity bean, Object val) :
-		execution(* *.set*(..)) 
+	
+	void around(MongoEntity bean, Object val) :
+		execution(void *.set*(..)) 
 		&& !MongoEntityOps.mongoOps()
 		&& this(bean)
 		&& args(val)
 	{
 		Method method = ((MethodSignature)thisJoinPointStaticPart.getSignature()).getMethod();
 		PropertyInfo pi = bean.beanData().findProperty(method);
+		if (pi.isMongoPersisted() && !pi.isMap() && !pi.isCollection() && !bean.isLoaded(pi.getName()) && pi.isReadable()) {
+			// Force a load to store previous bean if any
+			try {
+				PropertyUtils.getProperty(bean, pi.getName());
+			} catch (Exception e) {
+				// Should never happen
+			}
+		}
+		proceed(bean, val);
 		bean.dirtyHandleProperty(pi, val);
 	}
 	

Modified: labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/PropertyInfoAdditions.aj
URL: http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/PropertyInfoAdditions.aj?rev=1124464&r1=1124463&r2=1124464&view=diff
==============================================================================
--- labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/PropertyInfoAdditions.aj (original)
+++ labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/PropertyInfoAdditions.aj Wed May 18 23:32:18 2011
@@ -1,6 +1,8 @@
 package org.apache.magma.database.mongo;
 
 import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
 import javax.persistence.CascadeType;
@@ -48,6 +50,7 @@ public aspect PropertyInfoAdditions {
 	
 	private JpaRelations PropertyInfo.jpaRelation = null;
 	private CascadeType[] PropertyInfo.jpaCascade = null;
+	private boolean PropertyInfo.jpaDeleteOrphans = false;
 	private String PropertyInfo.jpaMappedBy = null;
 	
 	
@@ -83,6 +86,10 @@ public aspect PropertyInfoAdditions {
 		return this.jpaRelation;
 	}
 	
+	public boolean PropertyInfo.isJpaDeleteOrphans() {
+		return this.jpaDeleteOrphans;
+	}
+	
 	
 	after(PropertyInfo info, PropertyDescriptor desc, Class beanClass) : 
 		execution(* PropertyInfo.init(PropertyDescriptor, Class)) 
@@ -120,6 +127,7 @@ public aspect PropertyInfoAdditions {
 				info.jpaCascade = assoc.cascade();
 				info.jpaRelation = JpaRelations.OneToOne;
 				info.jpaMappedBy = assoc.mappedBy();
+				info.jpaDeleteOrphans |= checkOrphanRemoval(assoc);
 			}
 		}
 
@@ -129,6 +137,7 @@ public aspect PropertyInfoAdditions {
 				info.jpaCascade = assoc.cascade();
 				info.jpaRelation = JpaRelations.OneToMany;
 				info.jpaMappedBy = assoc.mappedBy();
+				info.jpaDeleteOrphans |= checkOrphanRemoval(assoc);
 			}
 		}
 	
@@ -137,6 +146,7 @@ public aspect PropertyInfoAdditions {
 			if (assoc != null) {
 				info.jpaCascade = assoc.cascade();
 				info.jpaRelation = JpaRelations.ManyToMany;				
+				info.jpaDeleteOrphans |= checkOrphanRemoval(assoc);
 			}
 		}
 
@@ -146,9 +156,39 @@ public aspect PropertyInfoAdditions {
 				info.jpaCascade = assoc.cascade();
 				info.jpaRelation = JpaRelations.ManyToOne;				
 				info.jpaMappedBy = assoc.mappedBy();
+				info.jpaDeleteOrphans |= checkOrphanRemoval(assoc);
 			}
 		}
 		
-	}	
+		if (!info.jpaDeleteOrphans) {
+			Annotation[] anns = rm.getAnnotations();
+			for (Annotation ann : anns) {
+				info.jpaDeleteOrphans |= ann.annotationType().getName().equals("org.apache.openjpa.persistence.ElementDependent");
+				// TODO eventually parse also other old ORM specific options
+			}
+		}
+	}
+	
+	private boolean checkOrphanRemoval(Annotation a) {
+		Method meth = null;
+		try {
+			meth = a.getClass().getMethod("orphanRemoval");
+		} catch (SecurityException e) {
+			// TODO maybe we should warn for this one?
+			return false;
+		} catch (NoSuchMethodException e) {
+			return false;
+		}
+		if (meth == null) return false;
+		if (!meth.getReturnType().equals(Boolean.TYPE)) return false;
+		try {
+			return (Boolean)meth.invoke(a);
+		} catch (IllegalAccessException e) {
+			// TODO maybe we should warn for this one?
+			return false;
+		} catch (Exception e) {
+			return false;
+		}
+	}
 	
 }

Modified: labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/Transaction.java
URL: http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/Transaction.java?rev=1124464&r1=1124463&r2=1124464&view=diff
==============================================================================
--- labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/Transaction.java (original)
+++ labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/Transaction.java Wed May 18 23:32:18 2011
@@ -345,16 +345,46 @@ public class Transaction {
 	public void commit() {
 		MongoDB mdb = this.db.getDb();
 		Set<MongoEntity> reallySaving = new HashSet<MongoEntity>();
-		BasicDBObject entlist = new BasicDBObject();
+		Set<MongoEntity> orphans = new HashSet<MongoEntity>();
+		
 		for (MongoEntity ent : this.confirmedSave) {
 			if (!ent.isDirty()) continue;
 			TransactionPart part = ent.getPart();
 			if (part == null) continue;
+			reallySaving.add(ent);
+		}
+		
+		// TODO this should be acycle, what if a dirty loaded is inside another dirty loaded and so on?
+		// Add dirty loadeds of really saving entities and orphans to delete
+		Set<MongoEntity> discovereds = new HashSet<MongoEntity>();
+		for (MongoEntity ent : reallySaving) {
+			Set<Map.Entry<String, Set<MongoEntity>>> loadeds = ent.getLoadedsEntry();
+			for (Map.Entry<String, Set<MongoEntity>> loaded : loadeds) {
+				Set<MongoEntity> oldents = loaded.getValue();
+				if (oldents == null || oldents.size() == 0) continue;
+				PropertyInfo loadedpi = ent.beanData().getProperty(loaded.getKey());
+				if (loadedpi.isMongoPersisted()) {
+					if (loadedpi.isJpaDeleteOrphans()) {
+						// FIXME list all orphans
+					} else {
+						for (MongoEntity oldent : oldents) {
+							if (oldent.isFromDb())
+								discovereds.add(oldent);
+						}
+					}
+				}
+			}
+		}	
+		reallySaving.addAll(discovereds);
+		
+		if (reallySaving.size() == 0) return;
+		
+		
+		BasicDBObject entlist = new BasicDBObject();
+		for (MongoEntity ent : reallySaving) {
 			MongoCollection coll = getCollection(ent.getClass());
 			String id = MongoUtils.getMongoId(ent);
 			
-			reallySaving.add(ent);
-			
 			BasicDBList colllist = (BasicDBList) entlist.get(coll.getName());
 			if (colllist == null) {
 				colllist = new BasicDBList();
@@ -362,7 +392,7 @@ public class Transaction {
 			}
 			colllist.add(id);
 		}
-		if (reallySaving.size() == 0) return;
+		// FIXME also add orphans to entlist
 		
 		MongoCollection trcoll = getCollection("transactions");
 		BasicDBObject mydbo = new BasicDBObject();



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