001 package com.khubla.pragmatach.plugin.mongodb.serializer; 002 003 import java.lang.reflect.Field; 004 import java.lang.reflect.ParameterizedType; 005 import java.lang.reflect.Type; 006 import java.util.HashSet; 007 import java.util.Iterator; 008 import java.util.Set; 009 010 import javax.persistence.Entity; 011 012 import org.apache.commons.beanutils.PropertyUtils; 013 014 import com.khubla.pragmatach.framework.api.PragmatachException; 015 import com.khubla.pragmatach.plugin.mongodb.MongoDBObjectPersister; 016 import com.khubla.pragmatach.plugin.mongodb.util.ClassTypeUtils; 017 import com.mongodb.BasicDBObject; 018 import com.mongodb.DBObject; 019 020 /** 021 * @author tom 022 */ 023 public class SetFieldSerializer implements FieldSerializer { 024 /** 025 * type utils 026 */ 027 private final ClassTypeUtils classTypeUtils; 028 /** 029 * the type 030 */ 031 private final Class<?> typeClazz; 032 033 /** 034 * ctor 035 */ 036 public SetFieldSerializer(Class<?> typeClazz) { 037 this.typeClazz = typeClazz; 038 classTypeUtils = new ClassTypeUtils(this.typeClazz); 039 } 040 041 @SuppressWarnings({ "rawtypes", "unchecked" }) 042 @Override 043 public void deserializeField(Object object, Field field, DBObject dbObject) throws PragmatachException { 044 try { 045 if (null != dbObject) { 046 /* 047 * eager load? 048 */ 049 if (ClassTypeUtils.isEagerLoad(field)) { 050 /* 051 * create the set 052 */ 053 final HashSet set = new HashSet(); 054 /* 055 * get the contained type of the set 056 */ 057 final Class<?> containedType = getContainedType(field); 058 if (null != containedType.getAnnotation(Entity.class)) { 059 /* 060 * persister for the contained type 061 */ 062 final MongoDBObjectPersister mongoDBObjectPersister = new MongoDBObjectPersister(containedType); 063 /* 064 * get the set 065 */ 066 final DBObject setObject = (DBObject) dbObject.get(field.getName()); 067 if (null != setObject) { 068 /* 069 * walk the ids 070 */ 071 int i = 0; 072 String id = (String) setObject.get(Integer.toString(i)); 073 while (null != id) { 074 /* 075 * get the object for the id 076 */ 077 final DBObject containedObjectJSON = mongoDBObjectPersister.find(id); 078 /* 079 * sanity check 080 */ 081 if (null != containedObjectJSON) { 082 final Object containedObject = mongoDBObjectPersister.load(containedObjectJSON); 083 set.add(containedObject); 084 } 085 /* 086 * next one 087 */ 088 id = (String) setObject.get(Integer.toString(++i)); 089 } 090 } 091 /* 092 * set the field 093 */ 094 PropertyUtils.setProperty(object, field.getName(), set); 095 } else { 096 throw new Exception("Type '" + containedType.getName() + "' is not an @Entity"); 097 } 098 } 099 } 100 } catch (final Exception e) { 101 throw new PragmatachException("Exception in deserializeField", e); 102 } 103 } 104 105 /** 106 * get the interior type of the set 107 */ 108 private Class<?> getContainedType(Field field) throws PragmatachException { 109 final Type type = field.getGenericType(); 110 final ParameterizedType parameterizedType = (ParameterizedType) type; 111 return (Class<?>) parameterizedType.getActualTypeArguments()[0]; 112 } 113 114 /** 115 * the strategy here is that we store the id's in the parent object, and then use DAOs to persist each contained object. 116 */ 117 @Override 118 public void serializeField(BasicDBObject parentDBObject, Object object, Field field) throws PragmatachException { 119 try { 120 /* 121 * check if cascade 122 */ 123 if (ClassTypeUtils.isCascadeSave(field)) { 124 /* 125 * get the set 126 */ 127 final Set<?> set = (Set<?>) PropertyUtils.getProperty(object, field.getName()); 128 if (null != set) { 129 /* 130 * get the contained type of the set 131 */ 132 final Class<?> containedType = getContainedType(field); 133 /* 134 * the object for the set id's 135 */ 136 final BasicDBObject dbObject = new BasicDBObject(); 137 /* 138 * walk the set 139 */ 140 int i = 0; 141 final Iterator<?> iter = set.iterator(); 142 while (iter.hasNext()) { 143 final Object o = iter.next(); 144 /* 145 * save the object 146 */ 147 final MongoDBObjectPersister mongoDBObjectPersister = new MongoDBObjectPersister(containedType); 148 mongoDBObjectPersister.save(o); 149 /* 150 * store the id 151 */ 152 final String id = classTypeUtils.getId(o); 153 dbObject.append(Integer.toString(i++), id); 154 } 155 /* 156 * add the id's to the parent 157 */ 158 parentDBObject.append(field.getName(), dbObject); 159 } 160 } 161 } catch (final Exception e) { 162 throw new PragmatachException("Exception in serializeField", e); 163 } 164 } 165 }