diff --git a/Mage/src/main/java/mage/watchers/Watcher.java b/Mage/src/main/java/mage/watchers/Watcher.java index d9e007666a7..48c0d7d9ab2 100644 --- a/Mage/src/main/java/mage/watchers/Watcher.java +++ b/Mage/src/main/java/mage/watchers/Watcher.java @@ -91,6 +91,7 @@ public abstract class Watcher implements Serializable { Constructor constructor = (Constructor) constructors.get(0); + // collect all fields constructor.setAccessible(true); Object[] args = new Object[constructor.getParameterCount()]; for (int index = 0; index < constructor.getParameterTypes().length; index++) { @@ -108,17 +109,32 @@ public abstract class Watcher implements Serializable { List allFields = new ArrayList<>(); allFields.addAll(Arrays.asList(getClass().getDeclaredFields())); allFields.addAll(Arrays.asList(getClass().getSuperclass().getDeclaredFields())); + + // copy field's values for (Field field : allFields) { if (!Modifier.isStatic(field.getModifiers())) { - field.setAccessible(true); + if (field.getType() == Set.class) { + // Set ((Set) field.get(watcher)).clear(); ((Set) field.get(watcher)).addAll((Set) field.get(this)); } else if (field.getType() == Map.class || field.getType() == HashMap.class) { + // Map ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType(); Type valueType = parameterizedType.getActualTypeArguments()[1]; - if (valueType.getTypeName().contains("Set")) { + if (valueType.getTypeName().contains("SortedSet")) { + // Map> + Map> source = (Map>) field.get(this); + Map> target = (Map>) field.get(watcher); + target.clear(); + for (Map.Entry> e : source.entrySet()) { + Set set = new TreeSet<>(); + set.addAll(e.getValue()); + target.put(e.getKey(), set); + } + } else if (valueType.getTypeName().contains("Set")) { + // Map> Map> source = (Map>) field.get(this); Map> target = (Map>) field.get(watcher); target.clear(); @@ -128,6 +144,7 @@ public abstract class Watcher implements Serializable { target.put(e.getKey(), set); } } else if (valueType.getTypeName().contains("PlayerList")) { + // Map Map source = (Map) field.get(this); Map target = (Map) field.get(watcher); target.clear(); @@ -136,6 +153,7 @@ public abstract class Watcher implements Serializable { target.put(e.getKey(), list); } } else if (valueType.getTypeName().endsWith("Cards")) { + // Map Map source = (Map) field.get(this); Map target = (Map) field.get(watcher); target.clear(); @@ -144,6 +162,7 @@ public abstract class Watcher implements Serializable { target.put(e.getKey(), list); } } else if (valueType instanceof Class && Arrays.stream(((Class) valueType).getInterfaces()).anyMatch(c -> c.equals(Copyable.class))) { + // Map Map source = (Map) field.get(this); Map target = (Map) field.get(watcher); target.clear(); @@ -152,6 +171,7 @@ public abstract class Watcher implements Serializable { target.put(e.getKey(), object); } } else if (valueType.getTypeName().contains("List")) { + // Map> Map> source = (Map>) field.get(this); Map> target = (Map>) field.get(watcher); target.clear(); @@ -161,6 +181,7 @@ public abstract class Watcher implements Serializable { target.put(e.getKey(), list); } } else if (valueType.getTypeName().contains("Map")) { + // Map> Map> source = (Map>) field.get(this); Map> target = (Map>) field.get(watcher); target.clear(); @@ -170,14 +191,17 @@ public abstract class Watcher implements Serializable { target.put(e.getKey(), map); } } else { + // Map // TODO: add additional tests to find unsupported watcher data ((Map) field.get(watcher)).putAll((Map) field.get(this)); } } else if (field.getType() == List.class) { + // List ((List) field.get(watcher)).clear(); ((List) field.get(watcher)).addAll((List) field.get(this)); } else { + // Object field.set(watcher, field.get(this)); } } diff --git a/Mage/src/test/java/mage/WatcherTest.java b/Mage/src/test/java/mage/WatcherTest.java index 5a2eb037b6e..177678d8fda 100644 --- a/Mage/src/test/java/mage/WatcherTest.java +++ b/Mage/src/test/java/mage/WatcherTest.java @@ -72,6 +72,7 @@ public class WatcherTest { Map> copyListInMap = copy.getListInMapField(); assertEquals(2, copyListInMap.size()); assertTrue(copyListInMap.containsKey("k1")); + assertEquals(copyListInMap.get("k1").getClass(), listInMapField.get("k1").getClass()); assertEquals(ImmutableList.of("v1", "v1.1"), copyListInMap.get("k1")); assertTrue(copyListInMap.containsKey("k2")); assertEquals(ImmutableList.of("v2"), copyListInMap.get("k2")); @@ -103,6 +104,7 @@ public class WatcherTest { Map> copySetInMap = copy.getSetInMapField(); assertEquals(3, copySetInMap.size()); assertTrue(copySetInMap.containsKey("k3")); + assertEquals(copySetInMap.get("k3").getClass(), copySetInMap.get("k3").getClass()); assertEquals(ImmutableSet.of("v3"), copySetInMap.get("k3")); assertTrue(copySetInMap.containsKey("k4")); assertEquals(ImmutableSet.of("v4", "v4.1"), copySetInMap.get("k4")); @@ -136,6 +138,7 @@ public class WatcherTest { Map> copyMapInMap = copy.getMapInMapField(); assertEquals(2, copyMapInMap.size()); assertTrue(copyMapInMap.containsKey("k1")); + assertEquals(copyMapInMap.get("k1").getClass(), mapInMapField.get("k1").getClass()); assertEquals(ImmutableMap.of("k1.1", "v1.1", "k1.2", "v1.2"), copyMapInMap.get("k1")); assertTrue(copyMapInMap.containsKey("k2")); assertEquals(ImmutableMap.of("k2.1", "v2.1"), copyMapInMap.get("k2")); @@ -163,6 +166,7 @@ public class WatcherTest { Map> copySortedSetInMapField = copy.getSortedSetInMapField(); assertEquals(2, copySortedSetInMapField.size()); assertTrue(copySortedSetInMapField.containsKey("k1")); + assertEquals(copySortedSetInMapField.get("k1").getClass(), sortedSetInMapField.get("k1").getClass()); assertEquals(ImmutableSortedSet.of("v1_1", "v1_2"), copySortedSetInMapField.get("k1")); assertTrue(copySortedSetInMapField.containsKey("k2")); assertEquals(ImmutableSortedSet.of("v2_1", "v2_2"), copySortedSetInMapField.get("k2"));