cz.autoclient.league_of_legends.maps.GameObjectMap.java Source code

Java tutorial

Introduction

Here is the source code for cz.autoclient.league_of_legends.maps.GameObjectMap.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package cz.autoclient.league_of_legends.maps;

import cz.autoclient.league_of_legends.DataLoader;
import cz.autoclient.league_of_legends.GameObject;
import cz.autoclient.league_of_legends.LoLVersion;
import java.beans.Expression;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.json.JSONException;
import org.json.JSONObject;

/**
 *
 * @author Jakub
 * @param <T> GameObject is any object loaded from 
 */
public abstract class GameObjectMap<T extends GameObject> extends DataLoader
        implements Map<String, T>, Iterable<T> {
    private HashMap<String, T> data;
    public final Class<T> type;

    public String version = null;

    private volatile HashMap<Integer, List> cachedValueLists;
    private final Object cachedValueLists_mutex = new Object();

    public GameObjectMap(Class<T> type, LoLVersion v, boolean download_if_missing) {
        super(v, v.getRoot(), download_if_missing);
        this.type = type;
    }

    public Map<String, T> getData() {
        if (data == null) {
            loadData();
        }
        return data;
    }

    public synchronized void loadData() {
        if (data != null)
            return;
        data = new HashMap();
        JSONObject jsonData = getJSONData();
        try {
            jsonData = jsonData.getJSONObject("data");
        } catch (JSONException e) {
            return;
        }

        if (jsonData != null) {
            try {
                Iterator<String> keys = jsonData.keys();
                String key;
                JSONObject json_entry;
                while (keys.hasNext() && (key = keys.next()) != null) {
                    if ((json_entry = jsonData.getJSONObject(key)) != null) {
                        try {
                            T result = (T) new Expression(type, "new", new Object[] { this, key, json_entry })
                                    .getValue();
                            data.put(key, result);
                        } catch (Exception e) {
                            //must not happen
                            e.printStackTrace();
                            throw new RuntimeException(
                                    "Failed to instantiate game object of type " + type.getName());

                            //throw new NoSuchMethodException("Constructor for "+handler.getName()+" failed with exception:"+e);
                        }
                    }
                }
            } catch (JSONException ex) {
                return;
            }
        }
    }

    @Override
    public String getVersion() {
        if (version == null) {
            try {
                version = getJSONData().getString("version");
            } catch (JSONException e) {
                System.out.println(e);
                return "error";
            }
        }
        return version;
    }

    /**
     * Getter for any values within the GameObject and it's subclasses. 
     * Used as callback.
     * 
     * Typical implementation would look like:
     *   new ValueGetter<SummonerSpell, String> {
     *     public String getValue(SummonerSpell source) {
     *       return source.toString();
     *     }
     *   }
     * @param <T> 
     * @param <V> Type of value retrieved
     */
    public static interface ValueGetter<T extends GameObject, V> {
        public V getValue(T source);

        public default boolean valEquals(V value, T source) {
            V val2 = getValue(source);
            if (value == null) {
                return val2 == null;
            }
            return value.equals(val2);
        }
    }

    /**
     * Will call the given value getter for all elements and return array of values.
     * @param <V>
     * @param reader
     * @return 
     */
    public <V> List<V> enumValues(ValueGetter<T, V> reader) {
        if (cachedValueLists != null) {
            synchronized (cachedValueLists_mutex) {
                int code = reader.getClass().hashCode();
                if (cachedValueLists.containsKey(code))
                    return cachedValueLists.get(code);
            }
        }
        //System.out.println("Enumerating values using "+reader.getClass().getName());
        List<V> vals = new ArrayList();

        for (T o : this) {
            vals.add(reader.getValue(o));
        }
        return vals;
    }

    /**
     * Will call the given value getter for all elements and return array of values.
     * @param <V>
     * @param reader
     * @param cached true if you want to cache the resulting array
     * @return 
     */
    public <V> List<V> enumValues(ValueGetter<T, V> reader, boolean cached) {
        List<V> vals = enumValues(reader);
        if (cached) {
            synchronized (cachedValueLists_mutex) {
                if (cachedValueLists == null)
                    cachedValueLists = new HashMap();
                int code = reader.getClass().hashCode();
                if (!cachedValueLists.containsKey(code))
                    cachedValueLists.put(reader.getClass().hashCode(), vals);
            }
        }
        return vals;
    }

    /**
     * Will try this getter for every value untill one equals the second parameter
     * @param <V>
     * @param reader
     * @param desired value we are trying to find
     * @return 
     */
    public <V> T find(ValueGetter<T, V> reader, V desired) {
        for (T o : this) {
            if (reader.valEquals(desired, o))
                return o;
        }
        return null;
    }

    @Override
    public void unloadData() {
        for (GameObject o : this) {
            o.unloadData();
        }
        super.unloadData();
    }

    public JSONObject getJSONObject(String key) throws JSONException {
        return getJSONData().getJSONObject(key);
    }

    @Override
    public Iterator<T> iterator() {
        return ((HashMap<String, T>) getData()).values().iterator();
    }

    public Iterator<String> keys() {
        return ((HashMap<String, T>) getData()).keySet().iterator();
    }

    @Override
    public int size() {
        return getData().size();
    }

    @Override
    public boolean isEmpty() {
        return getData().isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return getData().containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return getData().containsValue(value);
    }

    @Override
    public T get(Object key) {
        return getData().get(key);
    }

    @Override
    public T put(String key, T value) {
        return getData().put(key, value);
    }

    @Override
    public T remove(Object key) {
        return getData().remove(key);
    }

    @Override
    public void putAll(Map<? extends String, ? extends T> m) {
        getData().putAll(m);
    }

    @Override
    public void clear() {
        getData().clear();
    }

    @Override
    public Set<String> keySet() {
        return getData().keySet();
    }

    @Override
    public Collection<T> values() {
        return getData().values();
    }

    @Override
    public Set<Entry<String, T>> entrySet() {
        return getData().entrySet();
    }

    @Override
    public boolean equals(Object o) {
        return getData().equals(o);
    }

    @Override
    public int hashCode() {
        return getData().hashCode();
    }

    @Override
    public T getOrDefault(Object key, T defaultValue) {
        return getData().getOrDefault(key, defaultValue);
    }

    @Override
    public void forEach(BiConsumer<? super String, ? super T> action) {
        getData().forEach(action);
    }

    @Override
    public void replaceAll(BiFunction<? super String, ? super T, ? extends T> function) {
        getData().replaceAll(function);
    }

    @Override
    public T putIfAbsent(String key, T value) {
        return getData().putIfAbsent(key, value);
    }

    @Override
    public boolean remove(Object key, Object value) {
        return getData().remove(key, value);
    }

    @Override
    public boolean replace(String key, T oldValue, T newValue) {
        return getData().replace(key, oldValue, newValue);
    }

    @Override
    public T replace(String key, T value) {
        return getData().replace(key, value);
    }

    @Override
    public T computeIfAbsent(String key, Function<? super String, ? extends T> mappingFunction) {
        return getData().computeIfAbsent(key, mappingFunction);
    }

    @Override
    public T computeIfPresent(String key, BiFunction<? super String, ? super T, ? extends T> remappingFunction) {
        return getData().computeIfPresent(key, remappingFunction);
    }

    @Override
    public T compute(String key, BiFunction<? super String, ? super T, ? extends T> remappingFunction) {
        return getData().compute(key, remappingFunction);
    }

    @Override
    public T merge(String key, T value, BiFunction<? super T, ? super T, ? extends T> remappingFunction) {
        return getData().merge(key, value, remappingFunction);
    }
}