Object obj, Key parentKey, ClassInfo parentInfo, Field parentField){
Class<?> clazz = obj.getClass();
ClassInfo info = ClassInfo.getClassInfo(clazz);
Field idField = info.getIdField();
Entity entity;
Object idVal = Util.readField(obj, idField);
// id with null value means insert
if(idVal == null){
if(parentKey==null){
entity = GaeMappingUtils.createEntityInstance(idField, info, obj);
}else {
entity = GaeMappingUtils.createEntityInstanceFromParent(idField, info, obj, parentKey, parentInfo, parentField);
}
GaeMappingUtils.fillEntity(obj, entity);
List<Entity> entities2Insert = entitiesMap.get(PersistenceType.INSERT);
if(entities2Insert == null){
entities2Insert = new ArrayList<Entity>();
entitiesMap.put(PersistenceType.INSERT, entities2Insert);
}
entities2Insert.add(entity);
List<Object> objects2Insert = objectsMap.get(PersistenceType.INSERT);
if(objects2Insert == null){
objects2Insert = new ArrayList<Object>();
objectsMap.put(PersistenceType.INSERT, objects2Insert);
}
objects2Insert.add(obj);
}else {
if(parentKey == null){
entity = GaeMappingUtils.createEntityInstanceForUpdate(info, obj);
}else {
entity = GaeMappingUtils.createEntityInstanceForUpdateFromParent(
info, obj, parentKey, parentInfo, parentField);
}
GaeMappingUtils.fillEntity(obj, entity);
List<Entity> entities2Update = entitiesMap.get(PersistenceType.UPDATE);
if(entities2Update == null){
entities2Update = new ArrayList<Entity>();
entitiesMap.put(PersistenceType.UPDATE, entities2Update);
}
entities2Update.add(entity);
}
for(Field f: info.ownedFields){
// doesn't do anything with One<T>
if(ClassInfo.isOne(f)){
// set the owner field in the child object using the content of the one
One4PM<?> relObj = (One4PM<?>)Util.readField(obj, f);
Map<FieldMapKeys, Object> m = info.oneFieldMap.get(f);
if(m != null){
Field asField = (Field)m.get(FieldMapKeys.FIELD);
if(relObj.isModified()){
// unassociates previous object
Object prevObj =relObj.getPrev();
if(prevObj != null){
Util.setField(prevObj, asField, null);
}
// resets modified flag
relObj.setModified(false);
List<Object> objects2Save = objectsMap.get(PersistenceType.SAVE);
if(objects2Save == null){
objects2Save = new ArrayList<Object>();
objectsMap.put(PersistenceType.SAVE, objects2Save);
}
objects2Save.add(prevObj);
Object oneObj = relObj.get();
if(oneObj != null){
Util.setField(oneObj, asField, obj);
objects2Save.add(oneObj);
}
}
}
}else if(ClassInfo.isMany(f)){
Many4PM<?> lq = (Many4PM<?>)Util.readField(obj, f);
// when you remove an element from a Many<T>, it just removes the link
if(!lq.asList2Remove().isEmpty()){
Field asField = (Field)info.manyFieldMap.get(f).get(FieldMapKeys.FIELD);
for(Object elt : lq.asList2Remove()){
Util.setField(elt, asField, null);
List<Object> objects2Save = objectsMap.get(PersistenceType.SAVE);
if(objects2Save == null){
objects2Save = new ArrayList<Object>();
objectsMap.put(PersistenceType.SAVE, objects2Save);
}
objects2Save.add(elt);
}
lq.asList2Remove().clear();
}
if(!lq.asList2Add().isEmpty()){
Field asField = (Field)info.manyFieldMap.get(f).get(FieldMapKeys.FIELD);
for(Object elt : lq.asList2Add()){
Util.setField(elt, asField, obj);
List<Object> objects2Save = objectsMap.get(PersistenceType.SAVE);
if(objects2Save == null){
objects2Save = new ArrayList<Object>();
objectsMap.put(PersistenceType.SAVE, objects2Save);
}
objects2Save.add(elt);
}
lq.asList2Add().clear();
}
}
}
for(Field f: info.aggregatedFields){
if(ClassInfo.isOne(f)){
One4PM<?> one = (One4PM<?>)Util.readField(obj, f);
if(one.isModified()){
// deletes previous object
Object prevObj =one.getPrev();
if(prevObj != null){
Class<?> delClazz = prevObj.getClass();
ClassInfo delInfo = ClassInfo.getClassInfo(delClazz);
Key delKey = GaeMappingUtils.makeKeyFromParent(
delInfo, prevObj, entity.getKey(), info, f);
List<Key> key2Remove = keysMap.get(PersistenceType.DELETE);
if(key2Remove == null){
key2Remove = new ArrayList<Key>();
keysMap.put(PersistenceType.DELETE, key2Remove);
}
key2Remove.add(delKey);
}
// resets modified flag
one.setModified(false);
Object oneObj = one.get();
if(oneObj != null){
_updateBuildMaps(entitiesMap, objectsMap, keysMap, oneObj, entity.getKey(), info, f);
}
}
}
else if(ClassInfo.isMany(f)){
Many4PM<?> lq = (Many4PM<?>)Util.readField(obj, f);
// do not update all objects, would be crazy :)
// UPDATE IS THE RESPONSABILITY OF THE CODER
/*if(!lq.asList().isEmpty()){
for(Object elt : lq.asList()){
_buildUpdateList(entities, entities2Remove, objects2Save, elt, entity.getKey(), info, f);
}
}*/
// add to entities2remove child entities that have been removed
if(!lq.asList2Remove().isEmpty()){
Key delKey;
for(Object elt : lq.asList2Remove()){
Class<?> delClazz = elt.getClass();
ClassInfo delInfo = ClassInfo.getClassInfo(delClazz);
delKey = GaeMappingUtils.makeKeyFromParent(
delInfo, elt, entity.getKey(), info, f);
List<Key> key2Remove = keysMap.get(PersistenceType.DELETE);
if(key2Remove == null){
key2Remove = new ArrayList<Key>();
keysMap.put(PersistenceType.DELETE, key2Remove);
}
key2Remove.add(delKey);
}
lq.asList2Remove().clear();
}
if(!lq.asList2Add().isEmpty()){
for(Object elt : lq.asList2Add()){
_updateBuildMaps(entitiesMap, objectsMap, keysMap, elt, entity.getKey(), info, f);
}
lq.asList2Add().clear();
}
}
}