Added 'finer' logging for the clone() method to provide visibility for

debugging.
Added a setClonedValue() method to force uncloned or precloned references
in some specific use-cases.
Added an isCloned() method to tell if an object has already been cloned
in this cloner's 'session'.
cleanup_build_scripts
Paul Speed 9 years ago
parent c6aac78f42
commit 2028f3b3f8
  1. 48
      jme3-core/src/main/java/com/jme3/util/clone/Cloner.java

@ -37,6 +37,8 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -97,6 +99,8 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class Cloner {
static Logger log = Logger.getLogger(Cloner.class.getName());
/**
* Keeps track of the objects that have been cloned so far.
*/
@ -190,14 +194,24 @@ public class Cloner {
* method called.
*/
public <T> T clone( T object, boolean useFunctions ) {
if( object == null ) {
return null;
}
if( log.isLoggable(Level.FINER) ) {
log.finer("cloning:" + object.getClass() + "@" + System.identityHashCode(object));
}
Class<T> type = objectClass(object);
// Check the index to see if we already have it
Object clone = index.get(object);
if( clone != null ) {
if( log.isLoggable(Level.FINER) ) {
log.finer("cloned:" + object.getClass() + "@" + System.identityHashCode(object)
+ " as cached:" + clone.getClass() + "@" + System.identityHashCode(clone));
}
return type.cast(clone);
}
@ -213,6 +227,15 @@ public class Cloner {
// Now call the function again to deep clone the fields
f.cloneFields(this, result, object);
if( log.isLoggable(Level.FINER) ) {
if( result == null ) {
log.finer("cloned:" + object.getClass() + "@" + System.identityHashCode(object)
+ " as transformed:null");
} else {
log.finer("clone:" + object.getClass() + "@" + System.identityHashCode(object)
+ " as transformed:" + result.getClass() + "@" + System.identityHashCode(result));
}
}
return result;
}
@ -246,6 +269,10 @@ public class Cloner {
throw new IllegalArgumentException("Object is not cloneable, type:" + type);
}
if( log.isLoggable(Level.FINER) ) {
log.finer("cloned:" + object.getClass() + "@" + System.identityHashCode(object)
+ " as " + clone.getClass() + "@" + System.identityHashCode(clone));
}
return type.cast(clone);
}
@ -272,6 +299,27 @@ public class Cloner {
return (CloneFunction<T>)functions.get(type);
}
/**
* Forces an object to be added to the indexing cache such that attempts
* to clone the 'original' will always result in the 'clone' being returned.
* This can be used to stub out specific values from being cloned or to
* force global shared instances to be used even if the object is cloneable
* normally.
*/
public <T> void setClonedValue( T original, T clone ) {
index.put(original, clone);
}
/**
* Returns true if the specified object has already been cloned
* by this cloner during this session. Cloned objects are cached
* for later use and it's sometimes convenient to know if some
* objects have already been cloned.
*/
public boolean isCloned( Object o ) {
return index.containsKey(o);
}
/**
* Clears the object index allowing the cloner to be reused for a brand new
* cloning operation.

Loading…
Cancel
Save