All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cat.nyaa.nyaacore.configuration.PropertyHelper Maven / Gradle / Ivy

There is a newer version: 3.12.2
Show newest version
package cat.nyaa.nyaacore.configuration;

import cat.nyaa.nyaacore.cmdreceiver.Arguments;
import cat.nyaa.nyaacore.cmdreceiver.BadCommandException;
import cat.nyaa.nyaacore.utils.ReflectionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class PropertyHelper {
    private static final Pattern VALID_KEY = Pattern.compile("[a-z0-9/._-]+");

    public static void setProperty(CommandSender sender, ISerializable power, Field field, String value) {
        try {
            if (value.equals("null")) {
                field.set(power, null);
                return;
            }
            field.setAccessible(true);
            if (field.getType().equals(int.class) || field.getType().equals(Integer.class)) {
                try {
                    field.set(power, Integer.parseInt(value));
                } catch (NumberFormatException e) {
                    throw new BadCommandException("internal.error.bad_int", value);
                }
            } else if (field.getType().equals(long.class) || field.getType().equals(Long.class)) {
                try {
                    field.set(power, Long.parseLong(value));
                } catch (NumberFormatException e) {
                    throw new BadCommandException("internal.error.bad_int", value);
                }
            } else if (field.getType().equals(float.class) || field.getType().equals(Float.class)) {
                try {
                    field.set(power, Float.parseFloat(value));
                } catch (NumberFormatException e) {
                    throw new BadCommandException("internal.error.bad_double", value);
                }
            } else if (field.getType().equals(double.class) || field.getType().equals(Double.class)) {
                try {
                    field.set(power, Double.parseDouble(value));
                } catch (NumberFormatException e) {
                    throw new BadCommandException("internal.error.bad_double", value);
                }
            } else if (field.getType().equals(String.class)) {
                field.set(power, value);
            } else if (field.getType().equals(boolean.class) || field.getType().equals(Boolean.class)) {
                if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
                    field.set(power, Boolean.valueOf(value));
                } else {
                    throw new BadCommandException("message.error.invalid_option", value, field.getName(), "true, false");
                }
            } else if (field.getType().isEnum()) {
                try {
                    field.set(power, Enum.valueOf((Class) field.getType(), value));
                } catch (IllegalArgumentException e) {
                    throw new BadCommandException("internal.error.bad_enum", field.getName(), Stream.of(field.getType().getEnumConstants()).map(Object::toString).collect(Collectors.joining(", ")));
                }
            } else if (Collection.class.isAssignableFrom(field.getType())) {
                ParameterizedType listType = (ParameterizedType) field.getGenericType();
                Class listArg = (Class) listType.getActualTypeArguments()[0];
                String[] valueStrs = value.split(",");
                Stream values = Arrays.stream(valueStrs).filter(s -> !s.isEmpty()).map(String::trim);
                if (field.getType().equals(List.class)) {
                    if (listArg.isEnum()) {
                        Class enumClass = (Class) listArg;
                        Stream enumStream = values.map(v -> Enum.valueOf(enumClass, v));
                        List list = enumStream.collect(Collectors.toList());
                        field.set(power, list);
                    } else if (listArg.equals(String.class)) {
                        List list = values.collect(Collectors.toList());
                        field.set(power, list);
                    } else if (listArg.equals(Integer.class)) {
                        List list = values.map(Integer::parseInt).collect(Collectors.toList());
                        field.set(power, list);
                    } else if (listArg.equals(Double.class)) {
                        List list = values.map(Double::parseDouble).collect(Collectors.toList());
                        field.set(power, list);
                    } else {
                        throw new BadCommandException("internal.error.command_exception");
                    }
                } else {
                    if (listArg.isEnum()) {
                        Class enumClass = (Class) listArg;
                        Stream enumStream = values.map(v -> Enum.valueOf(enumClass, v));
                        Set set = enumStream.collect(Collectors.toSet());
                        field.set(power, set);
                    } else if (listArg.equals(String.class)) {
                        Set set = values.collect(Collectors.toSet());
                        field.set(power, set);
                    } else if (listArg.equals(Integer.class)) {
                        Set list = values.map(Integer::parseInt).collect(Collectors.toSet());
                        field.set(power, list);
                    } else if (listArg.equals(Double.class)) {
                        Set list = values.map(Double::parseDouble).collect(Collectors.toSet());
                        field.set(power, list);
                    } else {
                        throw new BadCommandException("internal.error.command_exception");
                    }
                }
            } else if (field.getType() == ItemStack.class) {
                Material m = getMaterial(value);
                ItemStack item;
                if (sender instanceof Player && value.equalsIgnoreCase("HAND")) {
                    ItemStack hand = ((Player) sender).getInventory().getItemInMainHand();
                    if (hand == null || hand.getType() == Material.AIR) {
                        throw new BadCommandException("message.error.iteminhand");
                    }
                    item = hand.clone();
                } else if (m == null || m == Material.AIR || !m.isItem()) {
                    throw new BadCommandException("message.error.material", value);
                } else {
                    item = new ItemStack(m);
                }
                field.set(power, item.clone());
            } else if (field.getType() == Enchantment.class) {
                Enchantment enchantment;
                if (VALID_KEY.matcher(value).matches()) {
                    enchantment = Enchantment.getByKey(NamespacedKey.minecraft(value));
                } else if (value.contains(":")) {
                    if (value.startsWith("minecraft:")) {
                        enchantment = Enchantment.getByKey(NamespacedKey.minecraft(value.split(":", 2)[1]));
                    } else {
                        enchantment = Enchantment.getByKey(new NamespacedKey(Objects.requireNonNull(Bukkit.getPluginManager().getPlugin(value.split(":", 2)[0])), value.split(":", 2)[1]));
                    }
                } else {
                    enchantment = Enchantment.getByName(value);
                }
                if (enchantment == null) {
                    enchantment = Arrays.stream(Enchantment.class.getDeclaredFields()).parallel().filter(f -> Modifier.isStatic(f.getModifiers())).filter(f -> f.getName().equals(value)).findAny().map(f -> {
                        try {
                            return (Enchantment) f.get(null);
                        } catch (IllegalAccessException e) {
                            throw new BadCommandException("message.error.invalid_enchant", e);
                        }
                    }).orElse(null);
                }
                field.set(power, enchantment);
            } else {
                throw new BadCommandException("message.error.invalid_command_arg");
            }
        } catch (IllegalAccessException e) {
            throw new BadCommandException("internal.error.command_exception", e);
        }
    }

    /**
     * return a list of properties in a iSerializable class
     * formatted in {@Code :}
     * safe to use by {@Link setUnchecked()}
     *
     * @param iSerializableClass class to resolve
     * @return a List of String that can be used in tab completion.
     */
    public static Collection resolveProperties(Class iSerializableClass) {
        List list = new ArrayList<>();
        Field[] f = iSerializableClass.getDeclaredFields();
        for (Field field : f) {
            ISerializable.Serializable ann = field.getAnnotation(ISerializable.Serializable.class);
            if (ann != null) {
                list.add(field.getName() + ":");
            }
        }
        Class superclass = iSerializableClass.getSuperclass();
        if (superclass != null && superclass.isAssignableFrom(ISerializable.class)) {
            list.addAll(resolveProperties((Class) superclass));
        }
        return list;
    }

    private static Material getMaterial(String name) {
        Material m = Material.matchMaterial(name, false);
        if (m == null) {
            m = Material.matchMaterial(name, true);
            if (m != null) {
                m = Bukkit.getUnsafe().fromLegacy(m);
                throw new BadCommandException("message.error.invalid_command_arg");
            }
        }
        return m;
    }

    public void setProperty(CommandSender sender, Arguments arguments, ISerializable resourceConfig) {
        String inst = arguments.nextString();
        String[] split = inst.split(":", 2);

        Class aClass = resourceConfig.getClass();
        List allFields = ReflectionUtils.getAllFields(aClass);
        Field declaredField = allFields.stream()
                .filter(field -> field.getName().equals(split[0]))
                .findFirst().orElseThrow(BadCommandException::new);
        String obj = split[1];
        setProperty(sender, resourceConfig, declaredField, obj);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy