Author: simoneg
Date: Tue Jun  7 16:40:31 2011
New Revision: 1133089

URL: http://svn.apache.org/viewvc?rev=1133089&view=rev
Log:
Preliminary, yet to be completely functional, support for embedded entities.
Sparse fixes on optimistic locking support

Added:
    
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/SubEntitiesTest.java
   (with props)
    
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphNode.java
   (with props)
    
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphRoot.java
   (with props)
Modified:
    
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanCollectionModifiedListener.java
    
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanMapModifiedListener.java
    
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityDoc.aj
    
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityFindMains.aj
    
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/MongoUtils.java
    
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/Transaction.java
    
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/TransactionPart.java
    
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/BSONPieces.java
    
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/TransactionPartWritingTest.java
    
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/F1Team.java
    
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/Settings.java

Modified: 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanCollectionModifiedListener.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanCollectionModifiedListener.java?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanCollectionModifiedListener.java
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanCollectionModifiedListener.java
 Tue Jun  7 16:40:31 2011
@@ -33,6 +33,8 @@ public class BeanCollectionModifiedListe
                for (Object ac : delegate) {
                        if (ac instanceof MongoEntity) {
                                
bsonList.add(MongoUtils.getMongoId((MongoEntity) ac));
+                               if (prop.isSubEntity())
+                                       ((MongoEntity)ac).joined(bean);
                        } else {
                                bsonList.add(MongoUtils.convertToMongo(ac));
                        }

Modified: 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanMapModifiedListener.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanMapModifiedListener.java?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanMapModifiedListener.java
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/BeanMapModifiedListener.java
 Tue Jun  7 16:40:31 2011
@@ -57,6 +57,8 @@ public class BeanMapModifiedListener imp
                        Object val = entry.getValue();
                        if (val instanceof MongoEntity) {
                                MongoEntity mpval = (MongoEntity) val;
+                               if (pi.isSubEntity() || 
mpval.beanData().isJpaSubEntity())
+                                       mpval.joined(bean);
                                bson.put(k, MongoUtils.getMongoId(mpval));
                        } else {
                                bson.put(k, MongoUtils.convertToMongo(val));

Modified: 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityDoc.aj
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityDoc.aj?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityDoc.aj
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityDoc.aj
 Tue Jun  7 16:40:31 2011
@@ -1,6 +1,9 @@
 package org.apache.magma.database.mongo;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Set;
+import java.util.List;
 
 import javax.persistence.Transient;
 
@@ -14,6 +17,7 @@ import org.aspectj.lang.reflect.MethodSi
 import org.bson.BSONObject;
 
 import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
 
 public aspect MongoEntityDoc {
 
@@ -126,6 +130,7 @@ public aspect MongoEntityDoc {
                                        bh.getValue(piname);
                                }
                        }
+                       this.entityDocNeedsInit = false;
                }
        }
        
@@ -133,4 +138,25 @@ public aspect MongoEntityDoc {
                return this.myTransaction;
        }
                
+       BSONObject MongoEntity.findSub(String id) {
+               BSONObject md = checkGetBson();
+               return MongoUtils.findSub(id, md);
+       }
+       
+       List<String> MongoEntity.getSubIds() {
+               BSONObject md = checkGetBson();
+               Object beansobj = md.get("_beans");
+               if (beansobj == null || !(beansobj instanceof List)) return 
Collections.emptyList();
+               List<String> ret = new ArrayList<String>();
+               List beanslist = (List) beansobj;
+               for (Object object : beanslist) {
+                       if (object == null || !(object instanceof BSONObject)) 
continue;
+                       BSONObject subdb = (BSONObject) object;
+                       String subid = (String) subdb.get("_id");
+                       ret.add(subid);
+               }               
+               return ret;
+       }
+       
+       
 }

Modified: 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityFindMains.aj
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityFindMains.aj?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityFindMains.aj
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoEntityFindMains.aj
 Tue Jun  7 16:40:31 2011
@@ -37,9 +37,7 @@ public aspect MongoEntityFindMains {
                dones.put(this,"a");
                boolean loadedOnly = !cascade.equals(CascadeType.REMOVE);
                BeanData bd = this.beanData();
-               if (!bd.isJpaSubEntity()) {
-                       set.put(this,state);
-               }
+               set.put(this,state);
                BeanHandler bh = this.handler();
                List<PropertyInfo> rels = bd.getJpaRelationFields();
                for (PropertyInfo pi : rels) {
@@ -90,7 +88,7 @@ public aspect MongoEntityFindMains {
                                        loadeds.remove(val);                    
                
                                }
                                for (Object object : loadeds) {
-                                       if (pi.isJpaDeleteOrphans()) {
+                                       if (pi.isJpaDeleteOrphans() || 
pi.isSubEntity()) {
                                                
((MongoEntity)object).findMainEntities(CascadeType.REMOVE, set, 
MainState.DELETEORPHAN, dones);
                                        } else {
                                                
((MongoEntity)object).findMainEntities(cascade, set, MainState.ORPHAN, dones);

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=1133089&r1=1133088&r2=1133089&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
 Tue Jun  7 16:40:31 2011
@@ -28,6 +28,7 @@ import org.aspectj.lang.reflect.MethodSi
 import org.bson.BSONObject;
 
 import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
 
 public aspect MongoEntityLazyRelations {
 

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=1133089&r1=1133088&r2=1133089&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
 Tue Jun  7 16:40:31 2011
@@ -23,10 +23,12 @@ public aspect MongoEntityTransactionMeth
 
        private boolean MongoEntity.dirty = true;
        private TransactionPart MongoEntity.part = null;
+       private MongoEntity MongoEntity.dirtyDelegate = null;
        
        TransactionPart MongoEntity.getPart() {
                if (part == null) {
                        part = new TransactionPart();
+                       part.init(this);
                }
                return part;
        }
@@ -41,6 +43,27 @@ public aspect MongoEntityTransactionMeth
 
        void MongoEntity.dirtied() {
                this.dirty = true;
+               if (dirtyDelegate != null) {
+                       dirtyDelegate.dirtied();
+               }
+       }
+       
+       void MongoEntity.joined(MongoEntity entity) {
+               if (dirtyDelegate != null) {
+                       if (dirtyDelegate == entity) return;
+                       dirtyDelegate.findRoot().getPart().disjoin(getPart());
+                       getPart().populateBasics(this);
+               }
+               dirtyDelegate = entity;
+               getPart().joined(dirtyDelegate.findRoot().getPart());
+               if (entity != null && this.isDirty()) {
+                       entity.dirtied();
+               }
+       }
+       
+       MongoEntity MongoEntity.findRoot() {
+               if (dirtyDelegate == null) return this;
+               return dirtyDelegate.findRoot();
        }
        
        void MongoEntity.dirtyRemoved(PropertyInfo pi) {
@@ -71,8 +94,6 @@ public aspect MongoEntityTransactionMeth
                                }
                                bean.checkGetBson().put("_id", okval);
                                bean.dirtied();
-                       } else if (pi.isSubEntity()) {
-                               // TODO persist of an embedded doc
                        } else if (pi.isBasicType() || (pi.getType() != null && 
Enum.class.isAssignableFrom(pi.getType()))) {
                                // Basic types goes straight
                                bean.checkGetBson().put(pi.getJpaColName(), 
MongoUtils.convertToMongo(val));
@@ -106,6 +127,9 @@ public aspect MongoEntityTransactionMeth
                        }
                }
                proceed(bean, val);
+               if (pi.isSubEntity() && val != null && val instanceof 
MongoEntity) {
+                       ((MongoEntity)val).joined(bean);
+               }
                bean.dirtyHandleProperty(pi, val);
        }
        

Modified: 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoUtils.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoUtils.java?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoUtils.java
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/MongoUtils.java
 Tue Jun  7 16:40:31 2011
@@ -14,6 +14,8 @@ import org.apache.magma.conversion.Conve
 import org.apache.magma.database.InstallIdByDefault.WithDefaultId;
 import org.bson.BSONObject;
 
+import com.mongodb.BasicDBList;
+
 public class MongoUtils {
 
        public static Object convertFromMongo(Object val, Class type) {
@@ -42,7 +44,6 @@ public class MongoUtils {
                        }
                }
                if (val instanceof Boolean) return val;
-               // TODO case of a subentity
                if (val instanceof String) {
                        Converter c = Converters.getConverterFor(type);
                        if (c != null) {
@@ -58,7 +59,6 @@ public class MongoUtils {
                if (val instanceof String) return val;
                if (val instanceof Boolean) return val;
                if (val instanceof MongoEntity) {
-                       // TODO case of a subentity
                        return getMongoId((MongoEntity) val);
                }
                Class type = val.getClass();
@@ -72,7 +72,6 @@ public class MongoUtils {
 
        public static String getMongoId(MongoEntity keyobj) {
                keyobj.checkGetBson();
-               // XXX (??) add the class, so that polymorphic strctures can be 
restored
                if (keyobj instanceof WithDefaultId) {
                        long id = ((WithDefaultId) keyobj).getId();
                        return Long.toHexString(id);
@@ -151,4 +150,42 @@ public class MongoUtils {
                };
        }
        
+       public static BSONObject findSub(String id, BSONObject mainobj) {
+               Object beansobj = mainobj.get("_beans");
+               if (beansobj == null || !(beansobj instanceof List)) return 
null;
+               List beanslist = (List) beansobj;
+               for (Object object : beanslist) {
+                       if (object == null || !(object instanceof BSONObject)) 
continue;
+                       BSONObject subdb = (BSONObject) object;
+                       String subid = (String) subdb.get("_id");
+                       if (subid!= null && subid.equals(id)) return subdb; 
+               }
+               return null;
+       }
+
+       public static void addSub(BSONObject mainobj, BSONObject beanpart) {
+               Object beansobj = mainobj.get("_beans");
+               if (beansobj == null || !(beansobj instanceof List)) {
+                       beansobj = new BasicDBList();
+                       mainobj.put("_beans", beansobj);
+               }
+               List beanslist = (List) beansobj;
+               beanslist.add(beanpart);
+       }
+
+       public static void removeSub(String id, BSONObject mainobj) {
+               Object beansobj = mainobj.get("_beans");
+               if (beansobj == null || !(beansobj instanceof List)) return;
+               List beanslist = (List) beansobj;
+               if (beanslist.size() == 0) return;
+               for (Iterator iterator = beanslist.iterator(); 
iterator.hasNext();) {
+                       Object object = (Object) iterator.next();
+                       if (object == null || !(object instanceof BSONObject)) 
continue;
+                       BSONObject subdb = (BSONObject) object;
+                       String subid = (String) subdb.get("_id");
+                       if (subid!= null && subid.equals(id)) {
+                               iterator.remove();
+                       }
+               }
+       }
 }

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=1133089&r1=1133088&r2=1133089&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
 Tue Jun  7 16:40:31 2011
@@ -44,6 +44,8 @@ public class Transaction {
        private MongoDatabase db;
        
        private Map<String, MongoEntity> mainCache = new HashMap<String, 
MongoEntity>();
+       private Map<String,String> subsCache = new HashMap<String, String>();
+       
        private WriteConcern writeConcern;
        private List<MongoCursor> cursors = new ArrayList<MongoCursor>();
        private Set<MongoEntity> confirmedSave = new HashSet<MongoEntity>();
@@ -83,11 +85,23 @@ public class Transaction {
        
        public <T extends MongoEntity> T checkCache(Class<T> clazz, String id) {
                T ret = (T) mainCache.get(id);
+               if (ret != null) return ret;
+               String mainid = subsCache.get(id);
+               if (mainid == null) return null;
+               MongoEntity main = mainCache.get(mainid);
+               if (main == null) return null;
+               BSONObject subobj = main.findSub(id);
+               if (subobj == null) return null;
+               ret = (T) instantiateSub(main, clazz, subobj);
                return ret;
        }
        
        public void cache(String id, MongoEntity obj) {         
                mainCache.put(id, obj);
+               List<String> subIds = obj.getSubIds();
+               for (String subid : subIds) {
+                       subsCache.put(subid, id);
+               }
        }               
        
        
@@ -196,11 +210,9 @@ public class Transaction {
        
 
        public void save(MongoEntity mpbean) {
-               mpbean.prepareForDb(this);
                confirmedSave.add(mpbean);
                Map<MongoEntity,MainState> mains = 
mpbean.findMainEntities(CascadeType.PERSIST);
                for (MongoEntity entity : mains.keySet()) {
-                       entity.prepareForDb(this);
                        entity.setOnDb(true);
                        addEntity(entity);
                        if (entity.isFromDb()) {
@@ -214,12 +226,10 @@ public class Transaction {
 
 
        public void delete(MongoEntity mpbean) {
-               mpbean.prepareForDb(this);
-               mpbean.dirtied();
                confirmedDelete.add(mpbean);
                Map<MongoEntity,MainState> mains = 
mpbean.findMainEntities(CascadeType.REMOVE);
                for (MongoEntity entity : mains.keySet()) {
-                       entity.prepareForDb(this);
+                       entity.dirtied();
                        entity.setOnDb(false);                  
                        TransactionPart entpart = addEntity(entity);
                        entpart.deleted();
@@ -329,7 +339,7 @@ public class Transaction {
                if (insert) return;
                if (wr.getN() == 0) {
                        if (entity != null) {
-                               throw new OptimisticLockException(entity);
+                               throw new OptimisticLockException("While saving 
" + entity.getClass() + " : " + entity.checkGetBson().get("_id")+ " ver " + 
entity.checkGetBson().get("version"), null, entity);
                        }
                        throw new MagmaException("Server returned 0 inserts 
while saving {0}", entity != null ? entity : "transaction");
                }               
@@ -363,6 +373,7 @@ public class Transaction {
                for (MongoEntity ent : this.confirmedSave) {
                        TransactionPart part = ent.getPart();
                        if (part == null) continue;
+                       // TODO Since this is not ordered, deletes could appear 
after cascades, deleting otherwise cascaded entities
                        Map<MongoEntity,MainState> mains = 
ent.findMainEntities(CascadeType.PERSIST);
                        for (Map.Entry<MongoEntity, MainState> entry : 
mains.entrySet()) {
                                MainState state = entry.getValue();
@@ -383,21 +394,45 @@ public class Transaction {
                }
                
                for (MongoEntity deleting : todelete) {
+                       if (tosave.contains(deleting)) continue;
                        deleting.getPart().deleted();
                        deleting.dirtied();
                        tosave.add(deleting);
                }
                
-               for (Iterator iterator = tosave.iterator(); 
iterator.hasNext();) {
-                       MongoEntity saving = (MongoEntity) iterator.next();
-                       if (saving.isFromDb() && !saving.isDirty())
-                               iterator.remove();
-               }
+               {
+                       Set<MongoEntity> mains = null;
+                       do {
+                               mains = new HashSet<MongoEntity>();
+                               for (Iterator iterator = tosave.iterator(); 
iterator.hasNext();) {
+                                       MongoEntity saving = (MongoEntity) 
iterator.next();
+                                       if (saving.isFromDb() && 
!saving.isDirty()) {
+                                               iterator.remove();
+                                               continue;
+                                       }
+                                       
+                                       
+                                       this.addEntity(saving);
+                                       if (!saving.isFromDb())
+                                               
saving.getPart().populateBasics(saving);
+
+                                       // FIXME remove this, is only for 
testing
+                                       saving.getPart().check();
+                                       
+                                       MongoEntity root = saving.findRoot();
+                                       // If this one is not a main entity, 
remove it from saving list and add the real entity to it
+                                       if (root != saving) {
+                                               iterator.remove();
+                                               mains.add(root);
+                                       }
+                               }
+                       } while (tosave.addAll(mains));
+               }               
                
                if (tosave.size() == 0) return;
                
                BasicDBObject entlist = new BasicDBObject();
-               
+
                for (MongoEntity ent : tosave) {
                        MongoCollection coll = getCollection(ent.getClass());
                        String id = MongoUtils.getMongoId(ent);
@@ -424,7 +459,6 @@ public class Transaction {
                                TransactionPart part = ent.getPart();
                                MongoCollection coll = 
getCollection(ent.getClass());
                                String id = MongoUtils.getMongoId(ent);
-                               WriteResult wr = null;
                                
                                BasicDBObject search = new BasicDBObject("_id", 
id);
                                if (ent.isFromDb()) {
@@ -456,7 +490,7 @@ public class Transaction {
                                                        
search.append(vf.getJpaColName(), version);
                                                        
bh.setValue(vf.getName(), version + 1);
                                                        nversion = version + 1;
-                                                       // We need this because 
setVersion is not weaved by MongoPersistedImpl casue of LTW bugs 
+                                                       // We need this because 
setVersion is not weaved by MongoEntity Impls cause of LTW bugs 
                                                        
ent.checkGetBson().put(vf.getJpaColName(), version + 1);
                                                        bh.commit();
                                                }
@@ -466,7 +500,6 @@ public class Transaction {
                                        this.checkResult(coll.update(search, 
update, false, false, writeConcern), false, ent);
                                } else {
                                        BasicDBObject insert = new 
BasicDBObject();
-                                       part.populateBasics(ent);
                                        insert.put("version", 1);
                                        BasicDBList trlist = new BasicDBList();
                                        trlist.add(part);
@@ -552,6 +585,7 @@ public class Transaction {
                }
                this.cursors.clear();
                this.mainCache.clear();
+               this.subsCache.clear();
        }
        
        public MongoMetadata getMeta() {
@@ -567,4 +601,18 @@ public class Transaction {
        }
 
 
+       public MongoEntity instantiateSub(MongoEntity main, Class clazz, 
BSONObject subobj) {
+               addEntity(main);
+               
+               MongoEntity subent = MongoUtils.convertToObject(clazz, subobj);
+               addEntity(subent);
+               subent.setFromDb(main.isFromDb());
+               subent.joined(main);
+               String oid = (String)subobj.get("_id");
+               cache(oid, subent);
+               
+               return subent;
+       }
+
+
 }

Modified: 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/TransactionPart.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/TransactionPart.java?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/TransactionPart.java
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/main/java/org/apache/magma/database/mongo/TransactionPart.java
 Tue Jun  7 16:40:31 2011
@@ -1,5 +1,8 @@
 package org.apache.magma.database.mongo;
 
+import java.nio.channels.IllegalSelectorException;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -9,6 +12,7 @@ import org.apache.magma.beans.PropertyIn
 import org.bson.BSONObject;
 import org.junit.runner.manipulation.Sortable;
 
+import com.mongodb.BasicDBList;
 import com.mongodb.BasicDBObject;
 import com.mongodb.DBObject;
 
@@ -45,12 +49,19 @@ public class TransactionPart extends Bas
        public String getTransactionId() {
                return this.getString("__transactionId");
        }
+       public String getObjectId() {
+               return this.getString("_id");
+       }
        public void deleted() {
                this.put("__deleted", true);
        }
        public boolean isDeleted() {
                return this.getBoolean("__deleted", false);
        }
+       public void init(MongoEntity ent) {
+               BSONObject bson = ent.checkGetBson();
+               this.put("_id", bson.get("_id"));
+       }
        public void populateBasics(MongoEntity ent) {
                BSONObject bson = ent.checkGetBson();
                this.put("_jcl", bson.get("_jcl"));
@@ -64,16 +75,37 @@ public class TransactionPart extends Bas
                        if (pi.isJpaId() || pi.isJpaVersion()) continue;
                        Object val = handler.getValue(propname);
                        ent.dirtyModified(pi, val);
-               }
+               }       
        }
        public void reapply(BSONObject doc) {
                for (String key : this.keySet()) {
                        if (key.startsWith("__")) continue;
-                       Object object = this.get(key);
-                       if (object == null) {
-                               doc.removeField(key);
+                       if (key.equals("_id") && doc.containsField("_id")) 
continue;
+                       if (key.equals("_beans")) {
+                               BasicDBList beans = (BasicDBList) this.get(key);
+                               for (Object subobj : beans) {
+                                       DBObject sub = (DBObject) subobj;
+                                       TransactionPart subtr = new 
TransactionPart(sub);
+                                       // FIXME ignore it, remove it, but 
don't throw this exception
+                                       if (subtr.getObjectId() == null) throw 
new IllegalStateException("Found null id in a sub bean transaction update");
+                                       if (subtr.isDeleted()) {
+                                               
MongoUtils.removeSub(subtr.getObjectId(), doc);
+                                       } else {
+                                               BSONObject beanpart = 
MongoUtils.findSub(subtr.getObjectId(), doc);
+                                               if (beanpart == null) {
+                                                       beanpart = new 
BasicDBObject();
+                                                       MongoUtils.addSub(doc, 
beanpart);
+                                               }
+                                               subtr.reapply(beanpart);
+                                       }
+                               }
                        } else {
-                               doc.put(key, object);
+                               Object object = this.get(key);
+                               if (object == null) {
+                                       doc.removeField(key);
+                               } else {
+                                       doc.put(key, object);
+                               }
                        }
                }
        }
@@ -81,4 +113,33 @@ public class TransactionPart extends Bas
                return this.getTransactionId().compareTo(o.getTransactionId());
        }
        
+       public void joined(TransactionPart tp) {
+               BasicDBList beans = (BasicDBList) tp.get("_beans");
+               if (beans == null) {
+                       beans = new BasicDBList();
+                       tp.put("_beans", beans);
+               }
+               beans.add(this);
+       }
+       
+       public void disjoin(TransactionPart other) {
+               List<DBObject> beans = (List<DBObject>) get("_beans");
+               if (beans == null) return;
+               for (Iterator iterator = beans.iterator(); iterator.hasNext();) 
{
+                       DBObject subobj = (DBObject) iterator.next();
+                       if (subobj == other) {
+                               iterator.remove();
+                               break;
+                       }
+               }
+               TransactionPart np = new TransactionPart();
+               np.put("_id", other.get("_id"));
+               np.deleted();
+               beans.add(np);
+       }
+
+       public void check() {
+               if (get("_id") == null) throw new IllegalStateException("Null 
id in " + this.toString());
+       }
+       
 }

Modified: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/BSONPieces.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/BSONPieces.java?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/BSONPieces.java
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/BSONPieces.java
 Tue Jun  7 16:40:31 2011
@@ -1,14 +1,18 @@
 package org.apache.magma.database.mongo;
 
+import java.util.List;
+
 import org.apache.magma.database.mongo.test.domain.Address;
 import org.apache.magma.database.mongo.test.domain.Car;
 import org.apache.magma.database.mongo.test.domain.City;
 import org.apache.magma.database.mongo.test.domain.Person;
+import org.apache.magma.database.mongo.test.domain.Settings;
 import org.apache.magma.database.mongo.test.utils.MongoTestCursor;
 
 import static org.junit.Assert.*;
 import static org.hamcrest.CoreMatchers.*;
 
+import com.mongodb.BasicDBList;
 import com.mongodb.DBObject;
 import com.mongodb.util.JSON;
 
@@ -19,6 +23,7 @@ public class BSONPieces {
        public static String cityId = "2296e47076130001";
        public static String carId = "2296e47076130003";
        public static String addressId = "2296e47076130005";
+       public static String emptyF1Id = "2296e47076130006";
        
        public static DBObject simplePerson = (DBObject) JSON.parse(
                        "{" + 
@@ -101,4 +106,60 @@ public class BSONPieces {
                assertThat(a.getAddress(), equalTo("Via Tiburtina"));
        }
        
+       public static String createSettingsString(Settings s) {
+               String ret = "{";
+               ret += "\"_id\":";
+               ret += "\"" + Long.toHexString(LongObjectId.generate()) + "\"";
+               ret += ",";
+               if (s.getGreeting() != null) {
+                       ret += "\"greeting\":";
+                       ret += "\"" + s.getGreeting() + "\"";
+                       ret += ",";
+               }
+               if (s.getOwner() != null) {
+                       ret += "\"owner\":";
+                       ret += "\"" + Long.toHexString(s.getOwner().getId()) + 
"\"";
+                       ret += ",";                     
+               }
+               if (s.getReferredTo() != null) {
+                       ret += "\"referredTo\":";
+                       ret += "\"" + 
Long.toHexString(s.getReferredTo().getId()) + "\"";
+                       ret += ",";                     
+               }
+               ret += "\"likesCoffee\":";
+               if (s.isLikesCoffee()) {
+                       ret += "true";
+               } else {
+                       ret += "false";
+               }
+               ret += "}";
+               return ret;
+       }
+       
+       public static DBObject createSettingsObject(Settings s) {
+               return (DBObject) JSON.parse(createSettingsString(s));
+       }
+       
+       
+       public static DBObject emptyF1 = (DBObject) JSON.parse(
+                       "{" + 
+                       "       \"_id\" : \"" + emptyF1Id + "\"," + 
+                       "   \"_jcl\" : \"F1Team\"," +
+                       "   \"version\": 1," +
+                       "}" 
+               );
+       
+       public static void addBean(DBObject main, DBObject sub) {
+               List beans = (List) main.get("_beans");
+               if (beans == null) {
+                       beans = new BasicDBList();
+                       main.put("_beans", beans);
+               }
+               beans.add(sub);
+       }
+       
+       public static String getId(DBObject dbo) {
+               return (String)dbo.get("_id");
+       }
+       
 }

Added: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/SubEntitiesTest.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/SubEntitiesTest.java?rev=1133089&view=auto
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/SubEntitiesTest.java
 (added)
+++ 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/SubEntitiesTest.java
 Tue Jun  7 16:40:31 2011
@@ -0,0 +1,527 @@
+package org.apache.magma.database.mongo;
+
+import static 
org.apache.magma.database.mongo.test.utils.DBObjectMatcher.dbObject;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.magma.database.mongo.BSONPieces.*;
+
+import org.apache.magma.database.mongo.test.domain.F1Team;
+import org.apache.magma.database.mongo.test.domain.GraphNode;
+import org.apache.magma.database.mongo.test.domain.GraphRoot;
+import org.apache.magma.database.mongo.test.domain.Person;
+import org.apache.magma.database.mongo.test.domain.Settings;
+import org.apache.magma.database.mongo.test.utils.DBObjectMatcher;
+import org.apache.magma.database.mongo.test.utils.MongoTestCollection.Expect;
+import org.bson.BSONObject;
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import com.mongodb.BasicDBList;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.DummyResultFactory;
+import com.mongodb.util.JSON;
+
+
+public class SubEntitiesTest extends MongoDbTestBase {
+
+       @Test
+       public void readASetting() throws Exception {
+               DBObject fdb = cloneDbo(simplePerson);
+               
+               DBObject sub = createSettingsObject(new Settings(true, "The 
great", null, null));
+               
+               fdb.put("settings", getId(sub));
+               addBean(fdb, sub);
+               
+               mdb.getCollection("test", "person")
+                       .expectFindOne(dbObject("{'_id':'" + 
BSONPieces.simplePersonId + "'}"), fdb);
+               
+               Person p = db.load(Person.class, BSONPieces.simplePersonId);
+               
+               mdb.checkAll();
+               
+               assertThat(p, notNullValue());
+               Settings f1tset = p.getSettings();
+               assertThat(f1tset, notNullValue());
+               assertThat(f1tset.getGreeting(), equalTo("The great"));
+               assertThat(f1tset.isLikesCoffee(), equalTo(true));
+               assertThat(f1tset.isFromDb(), equalTo(true));
+       }
+       
+       @Test
+       public void readAList() throws Exception {
+               DBObject sp = cloneDbo(emptyF1);
+               
+               DBObject sub1 = createSettingsObject(new Settings(true, "Mr.", 
null, null));
+               DBObject sub2 = createSettingsObject(new Settings(true, 
"Master", null, null));
+               DBObject sub3 = createSettingsObject(new Settings(true, 
"Monster", null, null));
+               
+               BasicDBList list = new BasicDBList();
+               list.add(getId(sub1));
+               list.add(getId(sub2));
+               list.add(getId(sub3));
+               sp.put("settings", list);
+
+               addBean(sp, sub1);
+               addBean(sp, sub2);
+               addBean(sp, sub3);
+               
+               mdb.getCollection("test", "f1team")
+                       .expectFindOne(dbObject("{'_id':'" + 
BSONPieces.emptyF1Id + "'}"), sp);
+               
+               F1Team f1t = db.load(F1Team.class, BSONPieces.emptyF1Id);
+               
+               mdb.checkAll();
+               
+               assertThat(f1t, notNullValue());
+               List<Settings> settings = f1t.getSettings();
+               
+               assertThat(settings, notNullValue());
+               assertThat(settings.size(), equalTo(3));
+               
+               assertThat(settings.get(0).getGreeting(), equalTo("Mr."));
+               assertThat(settings.get(0).isFromDb(), equalTo(true));
+               assertThat(settings.get(1).getGreeting(), equalTo("Master"));
+               assertThat(settings.get(2).getGreeting(), equalTo("Monster"));
+       }
+       
+       @Test
+       public void dirtySub() throws Exception {
+               Person p = new Person();
+               
+               p.clearDirty();
+               
+               Settings s = new Settings(false, "Mr.", null, null);
+               p.setSettings(s);
+               
+               assertThat(p.isDirty(), equalTo(true));
+
+               p.clearDirty();
+               s.clearDirty();
+               
+               s.setGreeting("Hello Mr.");
+
+               assertThat(s.isDirty(), equalTo(true));
+               assertThat(p.isDirty(), equalTo(true));         
+       }
+
+       @Test
+       public void dirtySubList() throws Exception {
+               F1Team f1t = new F1Team();
+               f1t.clearDirty();
+               
+               Settings s = new Settings(false, "Mr.", null, null);
+               f1t.getSettings().add(s);
+               
+               assertThat(f1t.isDirty(), equalTo(true));
+               
+               f1t.clearDirty();
+               s.clearDirty();
+               
+               s.setGreeting("Goodbye Mr.");
+               
+               assertThat(s.isDirty(), equalTo(true));
+               assertThat(f1t.isDirty(), equalTo(true));                       
        
+       }
+       
+       @Test
+       public void checkTransactionPart() throws Exception {
+               Person p = new Person();
+               Settings s = new Settings(false, "Mr.", null, null);
+               p.setSettings(s);
+               
+               TransactionPart part = p.getPart();
+               part.populateBasics(p);
+               TransactionPart subpart = s.getPart();
+               subpart.populateBasics(s);
+               
+               Object beans = part.get("_beans");
+               assertThat(beans, notNullValue());
+               assertThat(beans, instanceOf(List.class));
+               List lb = (List) beans;
+               assertThat(lb.size(), equalTo(1));
+               Object sub = lb.get(0);
+               assertThat(sub, notNullValue());
+               assertThat(sub, instanceOf(BSONObject.class));
+               BSONObject subdb = (BSONObject) sub;
+               assertThat((String)subdb.get("greeting"), equalTo("Mr."));
+               
+               s.setGreeting("Hello Mr.");
+
+               assertThat((String)subdb.get("greeting"), equalTo("Hello Mr."));
+       }
+       
+       @Test
+       public void transactionPartApply() throws Exception {
+               Person p = new Person();
+               p.setName("Test");
+               Settings s = new Settings(false, "Mr.", null, null);
+               p.setSettings(s);
+               
+               TransactionPart part = p.getPart();
+               part.populateBasics(p);
+               TransactionPart subpart = s.getPart();
+               subpart.populateBasics(s);
+               
+
+               DBObject dbo = new BasicDBObject();
+               
+               part.reapply(dbo);
+               
+               assertThat((String)dbo.get("name"), equalTo("Test"));
+               Object beansobj = dbo.get("_beans");
+               assertThat(beansobj, notNullValue());
+               List beans = (List)beansobj;
+               assertThat(beans.size(), equalTo(1));
+               Object subobj = beans.get(0);
+               assertThat(subobj, notNullValue());
+               assertThat(subobj, instanceOf(DBObject.class));
+               DBObject subdbo = (DBObject) subobj;
+               assertThat((String)subdbo.get("greeting"), equalTo("Mr."));
+       }
+       
+       @Test
+       public void writeBasicSub() throws Exception {
+               Person p = new Person();
+               p.setName("Simone");
+               Settings s = new Settings(false, "Mr.", null, null);
+               p.setSettings(s);
+               
+               db.save(p);
+
+               mdb.checkAll();
+               
+               mdb.getCollection("test", "person")
+                       .expectInsert(dbObject("{'version': 1, 
'__transactions': [{'__transactionId' : '" + tr.getId() + "', 'name' :'Simone', 
'_jcl':'Person', 'settings':'" + Long.toHexString(s.getId()) + "', '_beans' : 
[{'_jcl':'Settings','greeting':'Mr.'}]}]}"));
+       
+               mdb.getCollection("test", "transactions")
+                       .clearExpectations()
+                       .expectInsert(dbObject("{'_id' : '" + tr.getId() + "', 
'state':'R', 'entities' : {'person' : ['" + Long.toHexString(p.getId()) + 
"'],'settings':'__NOTPRESENT__'} }"))
+                       .expectUpdate(dbObject("{'_id' : '" + tr.getId() + 
"'}"),dbObject("{'$set': {'state':'D'}}"));
+                       
+               db.commit();
+               mdb.checkAll();
+       }
+       
+       @Test
+       public void updateSimple() throws Exception {
+               DBObject fdb = cloneDbo(simplePerson);
+               
+               DBObject sub = createSettingsObject(new Settings(true, "The 
great", null, null));
+               
+               fdb.put("settings", getId(sub));
+               addBean(fdb, sub);
+               
+               mdb.getCollection("test", "person")
+                       .expectFindOne(dbObject("{'_id':'" + 
BSONPieces.simplePersonId + "'}"), fdb);
+               
+               Person p = db.load(Person.class, BSONPieces.simplePersonId);
+               Settings s = p.getSettings();
+               s.setGreeting("Test");
+               db.save(p);
+
+               mdb.getCollection("test", "person")
+                       .expectUpdate(
+                                       dbObject("{'_id':'" + 
Long.toHexString(p.getId()) + "'}"),
+                                       dbObject("{'$push': {'__transactions': 
{'__transactionId' : '" + tr.getId() + "', '_beans' : 
[{'greeting':'Test','_id':'" + Long.toHexString(s.getId()) + "'}]}}}"));
+       
+               mdb.getCollection("test", "transactions")
+                       .clearExpectations()
+                       .expectInsert(dbObject("{'_id' : '" + tr.getId() + "', 
'state':'R', 'entities' : {'person' : ['" + Long.toHexString(p.getId()) + 
"'],'settings':'__NOTPRESENT__'} }"))
+                       .expectUpdate(dbObject("{'_id' : '" + tr.getId() + 
"'}"),dbObject("{'$set': {'state':'D'}}"));
+                       
+               db.commit();
+               mdb.checkAll();
+               
+               
+
+       }
+       
+       @Test
+       public void writeListSub() throws Exception {
+               F1Team f1t = new F1Team();
+               f1t.setCar(null);
+               Settings s = new Settings(false, "Mr.", null, null);
+               Settings s2 = new Settings(false, "Master", null, null);
+               List<Settings> settings = f1t.getSettings();
+               settings.add(s);
+               settings.add(s2);
+               
+               db.save(f1t);
+
+               mdb.checkAll();
+               
+               mdb.getCollection("test", "f1team")
+                       .expectInsert(dbObject("{'version': 1, 
'__transactions': [{'__transactionId' : '" + tr.getId() + "', '_jcl':'F1Team', 
'settings':['" + Long.toHexString(s.getId()) + "','" + 
Long.toHexString(s2.getId()) + "'], '_beans' : 
[{'_jcl':'Settings','greeting':'Mr.'},{'_jcl':'Settings','greeting':'Master'}]}]}"));
+       
+               mdb.getCollection("test", "transactions")
+                       .clearExpectations()
+                       .expectInsert(dbObject("{'_id' : '" + tr.getId() + "', 
'state':'R', 'entities' : {'f1team' : ['" + Long.toHexString(f1t.getId()) + 
"'],'settings':'__NOTPRESENT__'} }"))
+                       .expectUpdate(dbObject("{'_id' : '" + tr.getId() + 
"'}"),dbObject("{'$set': {'state':'D'}}"));
+                       
+               db.commit();
+               mdb.checkAll();
+
+       }
+       
+       @Test
+       public void listUpdate() throws Exception {
+               DBObject sp = cloneDbo(emptyF1);
+               
+               DBObject sub1 = createSettingsObject(new Settings(true, "Mr.", 
null, null));
+               DBObject sub2 = createSettingsObject(new Settings(true, 
"Master", null, null));
+               DBObject sub3 = createSettingsObject(new Settings(true, 
"Monster", null, null));
+               
+               BasicDBList list = new BasicDBList();
+               list.add(getId(sub1));
+               list.add(getId(sub2));
+               list.add(getId(sub3));
+               sp.put("settings", list);
+
+               addBean(sp, sub1);
+               addBean(sp, sub2);
+               addBean(sp, sub3);
+               
+               mdb.getCollection("test", "f1team")
+                       .expectFindOne(dbObject("{'_id':'" + 
BSONPieces.emptyF1Id + "'}"), sp);
+               
+               F1Team f1t = db.load(F1Team.class, BSONPieces.emptyF1Id);
+               
+               mdb.checkAll();
+               
+               Settings s = f1t.getSettings().get(0);
+               s.setGreeting("Test");
+               db.save(f1t);
+               
+               mdb.getCollection("test", "f1team")
+                       .expectUpdate(
+                                       dbObject("{'_id':'" + 
Long.toHexString(f1t.getId()) + "'}"),
+                                       dbObject("{'$push': {'__transactions': 
{'__transactionId' : '" + tr.getId() + "', '_beans' : 
[{'greeting':'Test','_id':'" + Long.toHexString(s.getId()) + "'}]}}}"));
+       
+               mdb.getCollection("test", "transactions")
+                       .clearExpectations()
+                       .expectInsert(dbObject("{'_id' : '" + tr.getId() + "', 
'state':'R', 'entities' : {'f1team' : ['" + Long.toHexString(f1t.getId()) + 
"'],'settings':'__NOTPRESENT__'} }"))
+                       .expectUpdate(dbObject("{'_id' : '" + tr.getId() + 
"'}"),dbObject("{'$set': {'state':'D'}}"));
+                       
+               db.commit();
+               mdb.checkAll();
+               
+
+       }
+       
+       @Test
+       public void subEntityRemove() throws Exception {
+               DBObject fdb = cloneDbo(simplePerson);
+               
+               DBObject sub = createSettingsObject(new Settings(true, "The 
great", null, null));
+               
+               fdb.put("settings", getId(sub));
+               addBean(fdb, sub);
+               
+               mdb.getCollection("test", "person")
+                       .expectFindOne(dbObject("{'_id':'" + 
BSONPieces.simplePersonId + "'}"), fdb);
+               
+               Person p = db.load(Person.class, BSONPieces.simplePersonId);
+               Settings s = p.getSettings();
+               Settings s2 = new Settings(false,"Mr.", null, null);
+               p.setSettings(s2);
+               db.save(p);
+
+               DBObjectMatcher partmatch = dbObject("{'$push': 
{'__transactions': {'__transactionId' : '" + tr.getId() + "', '_beans' : 
[{'_id':'" + Long.toHexString(s.getId()) + "','__deleted':true},{'_id':'" + 
Long.toHexString(s2.getId()) + "','greeting':'Mr.'}]}}}");
+               mdb.getCollection("test", "person")
+                       .expectUpdate(
+                                       dbObject("{'_id':'" + 
Long.toHexString(p.getId()) + "'}"),
+                                       partmatch);
+       
+               mdb.getCollection("test", "transactions")
+                       .clearExpectations()
+                       .expectInsert(dbObject("{'_id' : '" + tr.getId() + "', 
'state':'R', 'entities' : {'person' : ['" + Long.toHexString(p.getId()) + 
"'],'settings':'__NOTPRESENT__'} }"))
+                       .expectUpdate(dbObject("{'_id' : '" + tr.getId() + 
"'}"),dbObject("{'$set': {'state':'D'}}"));
+                       
+               db.commit();
+               mdb.checkAll();         
+               
+               // Check applying the part
+               DBObject part = partmatch.getObtained();
+               part = (DBObject) part.get("$push");
+               part = (DBObject) part.get("__transactions");
+               
+               TransactionPart tp = new TransactionPart(part);
+               
+               tp.reapply(fdb);
+               
+               BSONObject sdbo = 
MongoUtils.findSub(Long.toHexString(s.getId()), fdb);
+               BSONObject s2dbo = 
MongoUtils.findSub(Long.toHexString(s2.getId()), fdb);
+
+               assertThat(((List)fdb.get("_beans")).size(), equalTo(1));
+               assertThat(sdbo, nullValue());
+               assertThat(s2dbo, notNullValue());
+               
+       }
+       
+       @Test
+       public void treeWriteTest() throws Exception {
+               GraphRoot gr = new GraphRoot();
+               
+               int cnt = 0;
+               // Create a tree
+               for (int i = 0; i < 10; i++) {
+                       GraphNode branch = new GraphNode("Branch " + i);
+                       gr.getRoots().add(branch);
+                       cnt++;
+                       for (int j = 0; j < 10; j++) {
+                               GraphNode leaf = new GraphNode("Leaf " + i + 
"-" + j);
+                               branch.addSub(leaf);
+                               cnt++;
+                       }
+               }
+               
+               db.save(gr);
+
+               mdb.checkAll();
+
+               DBObjectMatcher match = dbObject("{'version': 1, 
'__transactions': [{'__transactionId' : '" + tr.getId() + "'}]}");
+               
+               mdb.getCollection("test", "graphroot")
+                       .expectInsert(match);
+
+               db.commit();
+               
+               DBObject part = match.getObtained();
+               
+               System.out.println(JSON.serialize(part));
+               List transactions = (List) part.get("__transactions");
+               part = (DBObject) transactions.get(0);
+               
+               Object beansobj = part.get("_beans");
+               assertThat(beansobj, notNullValue());
+               assertThat(beansobj, instanceOf(List.class));
+               List<DBObject> beans = (List<DBObject>) beansobj;
+               assertThat(beans.size(), equalTo(cnt));
+               
+               for (DBObject dbo : beans) {
+                       Object subbeans = dbo.get("_beans");
+                       if (subbeans != null) {
+                               assertThat(subbeans, instanceOf(List.class));
+                               assertThat(((List)subbeans).size(), equalTo(0));
+                       }
+               }
+       }
+
+       // TODO this does not work at all
+       /*
+       @Test
+       public void graphWriteTest() throws Exception {
+               GraphRoot gr = new GraphRoot();
+               
+               int cnt = 0;
+               // Create some nodes
+               
+               List<GraphNode> nodes = new ArrayList<GraphNode>();
+               for (int i = 0; i < 20; i++) {
+                       GraphNode branch = new GraphNode("Node " + i);
+                       nodes.add(branch);
+                       cnt++;
+               }
+               
+               gr.getRoots().addAll(nodes);            
+               
+               for (GraphNode node : nodes) {
+                       node.getSubs().addAll(nodes);
+               }
+               
+               
+               db.save(gr);
+               mdb.checkAll();
+               DBObjectMatcher match = dbObject("{'version': 1, 
'__transactions': [{'__transactionId' : '" + tr.getId() + "'}]}");
+               mdb.getCollection("test", "graphroot")
+                       .expectInsert(match);
+               db.commit();
+               
+               DBObject part = match.getObtained();
+               
+               System.out.println(JSON.serialize(part));
+               List transactions = (List) part.get("__transactions");
+               part = (DBObject) transactions.get(0);
+               
+               Object beansobj = part.get("_beans");
+               assertThat(beansobj, notNullValue());
+               assertThat(beansobj, instanceOf(List.class));
+               List<DBObject> beans = (List<DBObject>) beansobj;
+               assertThat(beans.size(), equalTo(cnt));
+               
+               for (DBObject dbo : beans) {
+                       Object subbeans = dbo.get("_beans");
+                       if (subbeans != null) {
+                               assertThat(subbeans, instanceOf(List.class));
+                               assertThat(((List)subbeans).size(), equalTo(0));
+                       }
+               }
+               
+
+       }
+       */
+       
+       @Test
+       public void subMove() throws Exception {
+               DBObject fdb = cloneDbo(simplePerson);
+               
+               DBObject sub = createSettingsObject(new Settings(true, "The 
great", null, null));
+               String subid = getId(sub);
+               fdb.put("settings", subid);
+               addBean(fdb, sub);
+               
+               mdb.getCollection("test", "person")
+                       .expectFindOne(dbObject("{'_id':'" + 
BSONPieces.simplePersonId + "'}"), fdb);
+               
+               Person p = db.load(Person.class, BSONPieces.simplePersonId);
+               Settings s = p.getSettings();
+               p.setSettings(null);
+               
+               Person p2 = new Person();
+               p2.setSettings(s);
+               
+               db.save(p);
+               db.save(p2);
+
+               mdb.getCollection("test", "person")
+                       .addExpectation(new Expect("update", new Matcher[] { 
+                                               dbObject("{'_id':'" + 
Long.toHexString(p.getId()) + "'}"),
+                                               dbObject("{'$push' : 
{'__transactions':{'settings':'__NULL__','_beans':[{'_id':'" + subid + 
"','__deleted':true}]}}}"),anything(), anything(), anything() 
+                                       }, DummyResultFactory.ok(1), true, 
false))
+                       .addExpectation(new Expect("insert", new Matcher[] { 
+                                       dbObject("{'_id':'" + 
Long.toHexString(p2.getId()) + "','__transactions':[{'settings':'" + subid + 
"','_beans':[{'_id':'" + subid + "','greeting':'The 
great','__deleted':'__NOTPRESENT__'}]}]}"),anything(), anything(), anything() 
+                                       }, DummyResultFactory.ok(1), true, 
false));
+       
+               mdb.getCollection("test", "transactions")
+                       .clearExpectations()
+                       .expectInsert(dbObject("{'_id' : '" + tr.getId() + "', 
'state':'R', 'entities' : {'person' : ['" + Long.toHexString(p.getId()) + "','" 
+ Long.toHexString(p2.getId()) + "'],'settings':'__NOTPRESENT__'} }"))
+                       .expectUpdate(dbObject("{'_id' : '" + tr.getId() + 
"'}"),dbObject("{'$set': {'state':'D'}}"));
+                       
+               db.commit();
+               mdb.checkAll();
+               
+
+       }
+       
+       // TODO more graph tests
+       
+       
+       // TODO test passing a subobj between two mains
+       
+       // TODO test writing a map
+       
+       // TODO test updating a map subentity   
+
+       // TODO test list elements removal
+       
+       // TODO test map elements removal
+       
+       // TODO test persisting a graph of subentities
+       
+}

Propchange: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/SubEntitiesTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/TransactionPartWritingTest.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/TransactionPartWritingTest.java?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/TransactionPartWritingTest.java
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/TransactionPartWritingTest.java
 Tue Jun  7 16:40:31 2011
@@ -11,7 +11,6 @@ import org.apache.magma.database.mongo.t
 import org.apache.magma.database.mongo.test.domain.F1Team;
 import org.apache.magma.database.mongo.test.domain.Person;
 import org.apache.magma.database.mongo.test.domain.Person.PersonType;
-import org.apache.magma.database.mongo.test.domain.Settings;
 import org.apache.magma.database.mongo.test.utils.MongoTestCollection.Expect;
 import org.hamcrest.Matcher;
 import org.junit.Test;

Modified: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/F1Team.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/F1Team.java?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/F1Team.java
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/F1Team.java
 Tue Jun  7 16:40:31 2011
@@ -16,6 +16,7 @@ public class F1Team {
 
        private Car car = new Car();
        private List<Person> fans = new ArrayList<Person>();
+       private List<Settings> settings = new ArrayList<Settings>();
        
        public F1Team() {}
        
@@ -44,5 +45,14 @@ public class F1Team {
        public void setFans(List<Person> fans) {
                this.fans = fans;
        }
+
+       @OneToMany
+       public List<Settings> getSettings() {
+               return settings;
+       }
+       public void setSettings(List<Settings> settings) {
+               this.settings = settings;
+       }
+
        
 }

Added: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphNode.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphNode.java?rev=1133089&view=auto
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphNode.java
 (added)
+++ 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphNode.java
 Tue Jun  7 16:40:31 2011
@@ -0,0 +1,43 @@
+package org.apache.magma.database.mongo.test.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Entity;
+
+import org.apache.magma.beans.MagmaBean;
+import org.apache.magma.database.mongo.SubEntity;
+
+@Entity
+@SubEntity
+@MagmaBean
+public class GraphNode {
+
+       private String name;
+       private List<GraphNode> subs = new ArrayList<GraphNode>();
+       
+       public GraphNode(String name) {
+               this.name = name;
+       }
+       
+       
+       public List<GraphNode> getSubs() {
+               return subs;
+       }
+       public void setSubs(List<GraphNode> subs) {
+               this.subs = subs;
+       }
+       
+       public GraphNode addSub(GraphNode sub) {
+               this.getSubs().add(sub);
+               return this;
+       }
+       
+       public String getName() {
+               return name;
+       }
+       public void setName(String name) {
+               this.name = name;
+       }
+       
+}

Propchange: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphNode.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphRoot.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphRoot.java?rev=1133089&view=auto
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphRoot.java
 (added)
+++ 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphRoot.java
 Tue Jun  7 16:40:31 2011
@@ -0,0 +1,23 @@
+package org.apache.magma.database.mongo.test.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Entity;
+
+import org.apache.magma.beans.MagmaBean;
+
+@Entity
+@MagmaBean
+public class GraphRoot {
+
+       private List<GraphNode> roots = new ArrayList<GraphNode>();
+
+       public List<GraphNode> getRoots() {
+               return roots;
+       }
+       public void setRoots(List<GraphNode> roots) {
+               this.roots = roots;
+       }
+       
+}

Propchange: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/GraphRoot.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/Settings.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/Settings.java?rev=1133089&r1=1133088&r2=1133089&view=diff
==============================================================================
--- 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/Settings.java
 (original)
+++ 
labs/magma/trunk/database-mongodb/src/test/java/org/apache/magma/database/mongo/test/domain/Settings.java
 Tue Jun  7 16:40:31 2011
@@ -1,12 +1,31 @@
 package org.apache.magma.database.mongo.test.domain;
 
 import javax.persistence.Entity;
+import javax.persistence.OneToOne;
+
+import org.apache.magma.database.mongo.SubEntity;
 
 @Entity
+@SubEntity
 public class Settings {
 
        private boolean likesCoffee;
        private String greeting;
+       private Person owner;
+       private Car referredTo;
+       
+       public Settings(boolean likesCoffee, String greeting, Person owner, Car 
referredTo) {
+               this.likesCoffee = likesCoffee;
+               this.greeting = greeting;
+               this.owner = owner;
+               this.referredTo = referredTo;
+       }
+
+
+
+       public Settings() {}
+       
+       
        
        public boolean isLikesCoffee() {
                return likesCoffee;
@@ -20,5 +39,20 @@ public class Settings {
        public void setGreeting(String greeting) {
                this.greeting = greeting;
        }
+       @OneToOne
+       public Person getOwner() {
+               return owner;
+       }
+       public void setOwner(Person owner) {
+               this.owner = owner;
+       }
+       
+       @OneToOne
+       public Car getReferredTo() {
+               return referredTo;
+       }
+       public void setReferredTo(Car referredTo) {
+               this.referredTo = referredTo;
+       }
        
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to