Fixed storage so that it copies fields from the entire object hierarchy

This commit is contained in:
nathan 2014-08-22 01:49:31 +02:00
parent d1fb857cc0
commit 9dfe590a80

View File

@ -25,8 +25,6 @@ import com.esotericsoftware.kryo.io.Output;
* Nothing spectacular about this storage -- it allows for persistent storage of objects to disk. * Nothing spectacular about this storage -- it allows for persistent storage of objects to disk.
*/ */
public class Storage { public class Storage {
// TODO: add snappy compression to storage objects??
private static final Logger logger = LoggerFactory.getLogger(Storage.class); private static final Logger logger = LoggerFactory.getLogger(Storage.class);
private static Map<File, Storage> storages = new HashMap<File, Storage>(1); private static Map<File, Storage> storages = new HashMap<File, Storage>(1);
@ -49,7 +47,6 @@ public class Storage {
throw new IllegalArgumentException("loadIntoObject cannot be null!"); throw new IllegalArgumentException("loadIntoObject cannot be null!");
} }
// if we load from a NEW storage at the same location as an ALREADY EXISTING storage, // if we load from a NEW storage at the same location as an ALREADY EXISTING storage,
// without saving the existing storage first --- whoops! // without saving the existing storage first --- whoops!
synchronized (storages) { synchronized (storages) {
@ -76,7 +73,7 @@ public class Storage {
storage.objectReference = new WeakReference(loadIntoObject); storage.objectReference = new WeakReference(loadIntoObject);
} }
if (source != null) { if (source != null && source != orig) {
copyFields(source, loadIntoObject); copyFields(source, loadIntoObject);
} }
} }
@ -294,45 +291,57 @@ public class Storage {
private static void copyFields(Object source, Object dest) { private static void copyFields(Object source, Object dest) {
Class<? extends Object> sourceClass = source.getClass(); Class<? extends Object> sourceClass = source.getClass();
Field[] destFields = dest.getClass().getDeclaredFields(); Class<? extends Object> destClass = dest.getClass();
for (Field destField : destFields) { if (sourceClass != destClass) {
String name = destField.getName(); throw new IllegalArgumentException("Source and Dest objects are not of the same class!");
try { }
Field sourceField = sourceClass.getDeclaredField(name);
destField.setAccessible(true);
sourceField.setAccessible(true);
Object sourceObj = sourceField.get(source); // have to walk up the object hierarchy.
while (destClass != Object.class) {
Field[] destFields = destClass.getDeclaredFields();
if (sourceObj instanceof Map) { for (Field destField : destFields) {
Object destObj = destField.get(dest); String name = destField.getName();
if (destObj == null) { try {
destField.set(dest, sourceObj); Field sourceField = sourceClass.getDeclaredField(name);
} else if (destObj instanceof Map) { destField.setAccessible(true);
@SuppressWarnings("unchecked") sourceField.setAccessible(true);
Map<Object, Object> sourceMap = (Map<Object, Object>) sourceObj;
@SuppressWarnings("unchecked")
Map<Object, Object> destMap = (Map<Object, Object>) destObj;
destMap.clear(); Object sourceObj = sourceField.get(source);
Iterator<?> entries = sourceMap.entrySet().iterator();
while (entries.hasNext()) { if (sourceObj instanceof Map) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)entries.next(); Object destObj = destField.get(dest);
Object key = entry.getKey(); if (destObj == null) {
Object value = entry.getValue(); destField.set(dest, sourceObj);
destMap.put(key, value); } else if (destObj instanceof Map) {
@SuppressWarnings("unchecked")
Map<Object, Object> sourceMap = (Map<Object, Object>) sourceObj;
@SuppressWarnings("unchecked")
Map<Object, Object> destMap = (Map<Object, Object>) destObj;
destMap.clear();
Iterator<?> entries = sourceMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)entries.next();
Object key = entry.getKey();
Object value = entry.getValue();
destMap.put(key, value);
}
} else {
logger.error("Incompatible field type! '{}'", name);
} }
} else { } else {
logger.error("Incompatible field type! '{}'", name); destField.set(dest, sourceObj);
} }
} else { } catch (Exception e) {
destField.set(dest, sourceObj); logger.error("Unable to copy field: {}", name, e);
} }
} catch (Exception e) {
logger.error("Unable to copy field: {}", name, e);
} }
destClass = destClass.getSuperclass();
sourceClass = sourceClass.getSuperclass();
} }
} }