Add the ability to clonse java.util.Arrays$ArrayList.
Dieser Commit ist enthalten in:
Ursprung
486ac2653d
Commit
3bd1361c9a
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package com.comphenix.protocol.reflect.cloning;
|
package com.comphenix.protocol.reflect.cloning;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -55,32 +56,37 @@ public class CollectionCloner implements Cloner {
|
|||||||
throw new IllegalArgumentException("source cannot be NULL.");
|
throw new IllegalArgumentException("source cannot be NULL.");
|
||||||
|
|
||||||
Class<?> clazz = source.getClass();
|
Class<?> clazz = source.getClass();
|
||||||
|
|
||||||
if (source instanceof Collection) {
|
if (source instanceof Collection) {
|
||||||
Collection<Object> copy = cloneConstructor(Collection.class, clazz, source);
|
Collection<Object> copy = cloneConstructor(Collection.class, clazz, source);
|
||||||
|
|
||||||
// Next, clone each element in the collection
|
// Next, clone each element in the collection
|
||||||
copy.clear();
|
try {
|
||||||
|
copy.clear();
|
||||||
for (Object element : (Collection<Object>) source) {
|
|
||||||
copy.add(getClone(element, source));
|
for (Object element : (Collection<Object>) source) {
|
||||||
|
copy.add(getClone(element, source));
|
||||||
|
}
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// Immutable - we can't do much about that
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
|
|
||||||
} else if (source instanceof Map) {
|
} else if (source instanceof Map) {
|
||||||
|
|
||||||
Map<Object, Object> copy = cloneConstructor(Map.class, clazz, source);
|
Map<Object, Object> copy = cloneConstructor(Map.class, clazz, source);
|
||||||
|
|
||||||
// Next, clone each element in the collection
|
// Next, clone each element in the collection
|
||||||
copy.clear();
|
try {
|
||||||
|
copy.clear();
|
||||||
for (Entry<Object, Object> element : ((Map<Object, Object>) source).entrySet()) {
|
|
||||||
Object key = getClone(element.getKey(), source);
|
for (Entry<Object, Object> element : ((Map<Object, Object>) source).entrySet()) {
|
||||||
Object value = getClone(element.getValue(), source);
|
Object key = getClone(element.getKey(), source);
|
||||||
copy.put(key, value);
|
Object value = getClone(element.getValue(), source);
|
||||||
|
copy.put(key, value);
|
||||||
|
}
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// Immutable - we can't do much about that
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
|
|
||||||
} else if (clazz.isArray()) {
|
} else if (clazz.isArray()) {
|
||||||
@ -163,12 +169,14 @@ public class CollectionCloner implements Cloner {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T> T cloneConstructor(Class<?> superclass, Class<?> clazz, Object source) {
|
private <T> T cloneConstructor(Class<?> superclass, Class<?> clazz, Object source) {
|
||||||
|
|
||||||
// Not all collections or maps implement "clone", but most *do* implement the "copy constructor" pattern
|
// Not all collections or maps implement "clone", but most *do* implement the "copy constructor" pattern
|
||||||
try {
|
try {
|
||||||
Constructor<?> constructCopy = clazz.getConstructor(Collection.class);
|
Constructor<?> constructCopy = clazz.getConstructor(Collection.class);
|
||||||
return (T) constructCopy.newInstance(source);
|
return (T) constructCopy.newInstance(source);
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
|
if (source instanceof Serializable)
|
||||||
|
return (T) new SerializableCloner().clone(source);
|
||||||
|
// Delegate to serializable if possible
|
||||||
return (T) cloneObject(clazz, source);
|
return (T) cloneObject(clazz, source);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Cannot construct collection.", e);
|
throw new RuntimeException("Cannot construct collection.", e);
|
||||||
|
@ -21,7 +21,7 @@ public class SerializableCloner implements Cloner {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object clone(Object source) {
|
public Object clone(Object source) {
|
||||||
return clone(source);
|
return SerializableCloner.clone((Serializable)source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.comphenix.protocol.reflect.cloning;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.BukkitInitialization;
|
||||||
|
|
||||||
|
public class AggregateClonerTest {
|
||||||
|
@BeforeClass
|
||||||
|
public static void initializeBukkit() throws IllegalAccessException {
|
||||||
|
BukkitInitialization.initializePackage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testArrays() {
|
||||||
|
List<Integer> input = Arrays.asList(1, 2, 3);
|
||||||
|
assertEquals(input, AggregateCloner.DEFAULT.clone(input));
|
||||||
|
}
|
||||||
|
}
|
In neuem Issue referenzieren
Einen Benutzer sperren