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.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -97,6 +99,8 @@ import java.util.concurrent.ConcurrentHashMap;
*/ */
public class Cloner { public class Cloner {
static Logger log = Logger.getLogger(Cloner.class.getName());
/** /**
* Keeps track of the objects that have been cloned so far. * Keeps track of the objects that have been cloned so far.
*/ */
@ -190,14 +194,24 @@ public class Cloner {
* method called. * method called.
*/ */
public <T> T clone( T object, boolean useFunctions ) { public <T> T clone( T object, boolean useFunctions ) {
if( object == null ) { if( object == null ) {
return null; return null;
} }
if( log.isLoggable(Level.FINER) ) {
log.finer("cloning:" + object.getClass() + "@" + System.identityHashCode(object));
}
Class<T> type = objectClass(object); Class<T> type = objectClass(object);
// Check the index to see if we already have it // Check the index to see if we already have it
Object clone = index.get(object); Object clone = index.get(object);
if( clone != null ) { 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); return type.cast(clone);
} }
@ -213,6 +227,15 @@ public class Cloner {
// Now call the function again to deep clone the fields // Now call the function again to deep clone the fields
f.cloneFields(this, result, object); 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; return result;
} }
@ -246,6 +269,10 @@ public class Cloner {
throw new IllegalArgumentException("Object is not cloneable, type:" + type); 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); return type.cast(clone);
} }
@ -272,6 +299,27 @@ public class Cloner {
return (CloneFunction<T>)functions.get(type); 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 * Clears the object index allowing the cloner to be reused for a brand new
* cloning operation. * cloning operation.

Loading…
Cancel
Save