Adding this would allow transferring from one object to another:
public <T> void assign(T target, T o) {
if (o == null) {
return;
}
if (dumpClonedClasses) {
System.out.println("start assign>" + o.getClass());
}
final Map<Object, Object> clones = new IdentityHashMap<Object, Object>(16);
try {
cloneInternal(o, target, clones);
} catch (final IllegalAccessException e) {
throw new CloningException("error during cloning of " + o, e);
}
}
and cloneInternal modified little bit, I just dump it here:
public <T> T cloneInternal(final T o, final T startWith, final Map<Object,
Object> clones) throws IllegalAccessException {
if (o == null) {
return null;
}
if (o == this) {
return null;
}
if (ignoredInstances.containsKey(o)) {
return o;
}
final Class<T> clz;
if (startWith != null) {
clz = (Class<T>) startWith.getClass();
} else {
clz = (Class<T>) o.getClass();
}
if (clz.isEnum()) {
return o;
}
// skip cloning ignored classes
if (nullInstead.contains(clz)) {
return null;
}
if (ignored.contains(clz)) {
return o;
}
for (final Class<?> iClz : ignoredInstanceOf) {
if (iClz.isAssignableFrom(clz)) {
return o;
}
}
if (isImmutable(clz)) {
return o;
}
if (o instanceof IFreezable) {
final IFreezable f = (IFreezable) o;
if (f.isFrozen()) {
return o;
}
}
final Object clonedPreviously = clones != null ? clones.get(o) : null;
if (clonedPreviously != null) {
return (T) clonedPreviously;
}
final Object fastClone = fastClone(o, clones);
if (fastClone != null) {
if (clones != null) {
clones.put(o, fastClone);
}
return (T) fastClone;
}
if (dumpClonedClasses) {
System.out.println("clone>" + clz);
}
if (clz.isArray()) {
final int length = Array.getLength(o);
final T newInstance = (T) Array.newInstance(clz.getComponentType(), length);
if (clones != null) {
clones.put(o, newInstance);
}
for (int i = 0; i < length; i++) {
final Object v = Array.get(o, i);
final Object clone = clones != null ? cloneInternal(v, null, clones) : v;
Array.set(newInstance, i, clone);
}
return newInstance;
}
final T newInstance;
if (startWith != null) {
newInstance = startWith;
} else {
newInstance = newInstance(clz);
}
if (clones != null) {
clones.put(o, newInstance);
}
final List<Field> fields = allFields(clz);
for (final Field field : fields) {
final int modifiers = field.getModifiers();
if (!Modifier.isStatic(modifiers)) {
if (nullTransient && Modifier.isTransient(modifiers)) {
// request by Jonathan : transient fields can be null-ed
final Class<?> type = field.getType();
if (!type.isPrimitive()) {
field.set(newInstance, null);
}
} else {
final Object fieldObject = field.get(o);
final boolean shouldClone = (cloneSynthetics || !cloneSynthetics && !field.isSynthetic()) && (cloneAnonymousParent || !cloneAnonymousParent && !isAnonymousParent(field));
final Object fieldObjectClone = clones != null ? shouldClone ? cloneInternal(fieldObject, null, clones) : fieldObject : fieldObject;
field.set(newInstance, fieldObjectClone);
if (dumpClonedClasses && fieldObjectClone != fieldObject) {
System.out.println("cloned field>" + field + " -- of class " + o.getClass());
}
}
}
}
return newInstance;
}
It needs to be called with null as startWith
Maybe there is a nicer way, but copying from one object to another seems to be
a nice feature, I think.