use of mage.util.Copyable in project mage by magefree.
the class Watcher method copy.
public <T extends Watcher> T copy() {
try {
// use getDeclaredConstructors to allow for package-private constructors (i.e. omit public)
List<?> constructors = Arrays.asList(this.getClass().getDeclaredConstructors());
if (constructors.size() > 1) {
logger.error(getClass().getSimpleName() + " has multiple constructors");
return null;
}
Constructor<? extends Watcher> constructor = (Constructor<? extends Watcher>) constructors.get(0);
constructor.setAccessible(true);
Object[] args = new Object[constructor.getParameterCount()];
for (int index = 0; index < constructor.getParameterTypes().length; index++) {
Class<?> parameterType = constructor.getParameterTypes()[index];
if (parameterType.isPrimitive()) {
if (parameterType.getSimpleName().equalsIgnoreCase("boolean")) {
args[index] = false;
}
} else {
args[index] = null;
}
}
T watcher = (T) constructor.newInstance(args);
List<Field> allFields = new ArrayList<>();
allFields.addAll(Arrays.asList(getClass().getDeclaredFields()));
allFields.addAll(Arrays.asList(getClass().getSuperclass().getDeclaredFields()));
for (Field field : allFields) {
if (!Modifier.isStatic(field.getModifiers())) {
field.setAccessible(true);
if (field.getType() == Set.class) {
((Set) field.get(watcher)).clear();
((Set) field.get(watcher)).addAll((Set) field.get(this));
} else if (field.getType() == Map.class || field.getType() == HashMap.class) {
ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
Type valueType = parameterizedType.getActualTypeArguments()[1];
if (valueType.getTypeName().contains("Set")) {
Map<Object, Set<Object>> source = (Map<Object, Set<Object>>) field.get(this);
Map<Object, Set<Object>> target = (Map<Object, Set<Object>>) field.get(watcher);
target.clear();
for (Map.Entry<Object, Set<Object>> e : source.entrySet()) {
Set<Object> set = new HashSet<>();
set.addAll(e.getValue());
target.put(e.getKey(), set);
}
} else if (valueType.getTypeName().contains("PlayerList")) {
Map<Object, PlayerList> source = (Map<Object, PlayerList>) field.get(this);
Map<Object, PlayerList> target = (Map<Object, PlayerList>) field.get(watcher);
target.clear();
for (Map.Entry<Object, PlayerList> e : source.entrySet()) {
PlayerList list = e.getValue().copy();
target.put(e.getKey(), list);
}
} else if (valueType.getTypeName().endsWith("Cards")) {
Map<Object, Cards> source = (Map<Object, Cards>) field.get(this);
Map<Object, Cards> target = (Map<Object, Cards>) field.get(watcher);
target.clear();
for (Map.Entry<Object, Cards> e : source.entrySet()) {
Cards list = e.getValue().copy();
target.put(e.getKey(), list);
}
} else if (valueType instanceof Class && Arrays.stream(((Class) valueType).getInterfaces()).anyMatch(c -> c.equals(Copyable.class))) {
Map<Object, Copyable> source = (Map<Object, Copyable>) field.get(this);
Map<Object, Copyable> target = (Map<Object, Copyable>) field.get(watcher);
target.clear();
for (Map.Entry<Object, Copyable> e : source.entrySet()) {
Copyable object = (Copyable) e.getValue().copy();
target.put(e.getKey(), object);
}
} else if (valueType.getTypeName().contains("List")) {
Map<Object, List<Object>> source = (Map<Object, List<Object>>) field.get(this);
Map<Object, List<Object>> target = (Map<Object, List<Object>>) field.get(watcher);
target.clear();
for (Map.Entry<Object, List<Object>> e : source.entrySet()) {
List<Object> list = new ArrayList<>();
list.addAll(e.getValue());
target.put(e.getKey(), list);
}
} else if (valueType.getTypeName().contains("Map")) {
Map<Object, Map<Object, Object>> source = (Map<Object, Map<Object, Object>>) field.get(this);
Map<Object, Map<Object, Object>> target = (Map<Object, Map<Object, Object>>) field.get(watcher);
target.clear();
for (Map.Entry<Object, Map<Object, Object>> e : source.entrySet()) {
Map<Object, Object> map = new HashMap<>();
map.putAll(e.getValue());
target.put(e.getKey(), map);
}
} else {
// 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) field.get(watcher)).clear();
((List) field.get(watcher)).addAll((List) field.get(this));
} else {
field.set(watcher, field.get(this));
}
}
}
return watcher;
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
logger.error("Can't copy watcher: " + e.getMessage(), e);
}
return null;
}
Aggregations