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 }