com.anathema_roguelike.main.utilities.Utils.java Source code

Java tutorial

Introduction

Here is the source code for com.anathema_roguelike.main.utilities.Utils.java

Source

/*******************************************************************************
 * This file is part of AnathemaRL.
 *
 *     AnathemaRL is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     AnathemaRL is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with AnathemaRL.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package com.anathema_roguelike.main.utilities;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.math3.distribution.EnumeratedDistribution;
import org.apache.commons.math3.util.Pair;
import org.reflections.Reflections;

import com.anathema_roguelike.main.display.Color;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;

import gigadot.rebound.Rebound;
import squidpony.squidgrid.gui.gdx.SColor;

public class Utils {

    private static HashMap<Class<?>, ArrayList<?>> subtypeCache = new HashMap<>();
    private static HashMap<Class<? extends Annotation>, Set<Class<?>>> annotationCache = new HashMap<>();

    public static Properties names;
    public static Properties descriptions;
    public static Properties colors;

    static {
        try {
            names = new Properties();
            descriptions = new Properties();
            colors = new Properties();

            names.load(new FileInputStream("res/names.properties"));
            descriptions.load(new FileInputStream("res/descriptions.properties"));
            colors.load(new FileInputStream("res/colors.properties"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static <T extends HasWeightedProbability> T getWeightedRandomSample(Collection<T> col) {
        ArrayList<Pair<T, Double>> list = new ArrayList<>();

        col.forEach(i -> {
            list.add(new Pair<>(i, i.getWeightedProbability()));
        });

        return new EnumeratedDistribution<>(list).sample();
    }

    public static <T extends Number> T clamp(T n, T l, T h) {
        return (n.doubleValue() > h.doubleValue() ? h : (n.doubleValue() < l.doubleValue() ? l : n));
    }

    public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
        return map.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(), value))
                .map(Map.Entry::getKey).collect(Collectors.toSet());
    }

    public static Class<?> getSuperclass(Object subclass) {

        if (!(subclass instanceof Class<?>)) {
            return subclass.getClass().getSuperclass();
        } else {
            return ((Class<?>) subclass).getSuperclass();
        }

    }

    public static <T> Collection<Class<? extends T>> getSubclasses(Class<T> superclass) {
        return getSubclasses(superclass, false, false, Predicates.alwaysTrue());
    }

    public static <T> Collection<Class<? extends T>> getSubclasses(Class<T> superclass, boolean includeAbstract) {
        return getSubclasses(superclass, includeAbstract, false, Predicates.alwaysTrue());
    }

    public static <T> Collection<Class<? extends T>> getSubclasses(Class<T> superclass, boolean includeAbstract,
            boolean includeSuperclass) {
        return getSubclasses(superclass, includeAbstract, includeSuperclass, Predicates.alwaysTrue());
    }

    @SuppressWarnings("unchecked")
    public static <T> Collection<Class<? extends T>> getSubclasses(Class<T> superclass, boolean includeAbstract,
            boolean includeSuperclass, Predicate<Class<? extends T>> predicate) {
        ArrayList<Class<? extends T>> ret = new ArrayList<>();

        if (subtypeCache.containsKey(superclass)) {
            ret = new ArrayList<>((ArrayList<Class<? extends T>>) subtypeCache.get(superclass));
        } else {

            Rebound rebound = new Rebound("com.anathema_roguelike", includeAbstract);

            Set<Class<? extends T>> subTypes = rebound.getSubClassesOf(superclass);

            if (!includeSuperclass) {
                subTypes.remove(superclass);
            }

            ArrayList<Class<? extends T>> sorted = new ArrayList<>(subTypes);
            Collections.sort(sorted, new Comparator<Class<? extends T>>() {
                @Override
                public int compare(Class<? extends T> o1, Class<? extends T> o2) {
                    return o1.getName().compareTo(o2.getName());
                }
            });

            subtypeCache.put((Class<?>) superclass, (ArrayList<Class<? extends T>>) sorted);

            ret = new ArrayList<>(sorted);
        }

        return Collections2.filter(ret, predicate);
    }

    @SuppressWarnings("unchecked")
    public static <T> Collection<T> filterBySubclass(Collection<? super T> unfiltered, Class<T> type) {
        return (Collection<T>) Collections2.filter(unfiltered, item -> {
            if (item != null) {
                return (type.isAssignableFrom(item.getClass()));
            } else {
                return false;
            }
        });
    }

    public static Set<Class<?>> getAnnotatedClasses(Class<? extends Annotation> annotation) {
        Set<Class<?>> annotated = null;

        if (annotationCache.containsKey(annotation)) {
            annotated = annotationCache.get(annotation);
        } else {
            annotated = new Reflections("com.anathema_roguelike").getTypesAnnotatedWith(annotation);

            annotationCache.put(annotation, annotated);
        }

        return annotated;
    }

    static String getProperty(Properties properties, Object obj, String defaultValue) {

        if (!(obj instanceof Class)) {

            if (obj instanceof String) {
                return (String) obj;
            }

            obj = obj.getClass();
        }

        Class<?> cls = (Class<?>) obj;

        while (cls.isAnonymousClass()) {
            cls = cls.getEnclosingClass();
        }

        String property = properties.getProperty(cls.getSimpleName());

        if (property != null) {
            return property;
        } else {
            return defaultValue;
        }
    }

    public static String getDescription(Object obj) {

        if (obj instanceof String || obj.equals(String.class)) {
            return "";
        }

        return getProperty(descriptions, obj, getName(obj) + " MISSING DESCRIPTION");
    }

    public static String getName(Object obj) {

        Class<?> cls = classify(obj);

        String defaultValue = cls.getSimpleName();

        return getProperty(names, obj, splitCamelCase(defaultValue));
    }

    public static SColor getColor(Object obj) {
        Class<?> cls = classify(obj);

        String color = getProperty(colors, obj, "WHITE");

        try {
            return (SColor) Color.class.getField(color).get(null);
        } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
            throw (new RuntimeException(color + " is not defined on " + Color.class));
        }
    }

    static Class<?> classify(Object obj) {
        Class<?> cls;

        if (obj instanceof Class) {
            cls = (Class<?>) obj;
        } else {
            cls = obj.getClass();
        }

        while (cls.isAnonymousClass()) {
            cls = cls.getEnclosingClass();
        }

        return cls;
    }

    //from http://stackoverflow.com/questions/2559759/how-do-i-convert-camelcase-into-human-readable-names-in-java
    static String splitCamelCase(String s) {
        return s.replaceAll(String.format("%s|%s|%s", "(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])",
                "(?<=[A-Za-z])(?=[^A-Za-z])"), " ");
    }
}