Search in sources :

Example 1 with Copyable

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;
}
Also used : java.lang.reflect(java.lang.reflect) Logger(org.apache.log4j.Logger) Game(mage.game.Game) java.util(java.util) GameEvent(mage.game.events.GameEvent) WatcherScope(mage.constants.WatcherScope) Cards(mage.cards.Cards) PlayerList(mage.players.PlayerList) Copyable(mage.util.Copyable) Serializable(java.io.Serializable) PlayerList(mage.players.PlayerList) Copyable(mage.util.Copyable) PlayerList(mage.players.PlayerList) Cards(mage.cards.Cards)

Aggregations

Serializable (java.io.Serializable)1 java.lang.reflect (java.lang.reflect)1 java.util (java.util)1 Cards (mage.cards.Cards)1 WatcherScope (mage.constants.WatcherScope)1 Game (mage.game.Game)1 GameEvent (mage.game.events.GameEvent)1 PlayerList (mage.players.PlayerList)1 Copyable (mage.util.Copyable)1 Logger (org.apache.log4j.Logger)1