com.megahardcore.service.config.MultiWorldConfig.java Source code

Java tutorial

Introduction

Here is the source code for com.megahardcore.service.config.MultiWorldConfig.java

Source

/*
 * This file is part of
 * MegaHardCore Server Plugin for Minecraft
 *
 * Copyright (C) 2012 Ryan Hamshire
 * Copyright (C) 2013 Diemex
 *
 * MegaHardCore is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MegaHardCore 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 Affero Public License
 * along with MegaHardCore.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.megahardcore.service.config;

import com.megahardcore.MegaHardCore;
import com.megahardcore.service.MHCModule;
import com.megahardcore.service.config.customtypes.BlockRelationsList;
import com.megahardcore.service.config.customtypes.BlockType;
import com.megahardcore.service.config.customtypes.BlockTypeList;
import com.megahardcore.service.config.customtypes.PotionEffectHolder;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Table;
import org.apache.commons.lang.Validate;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Modular configuration class that utilizes a ConfigNode enumeration as easy access and storage of configuration option values.
 *
 * @author Mitsugaru (original author)
 * @author Diemex (modifies to allow multiworld)
 */
public abstract class MultiWorldConfig extends MHCModule {

    /**
     * For mods like MystCraft which allow Players to create their own dimensions, so the admin doesn't have to add worlds manually
     */
    protected boolean enabledForAll = true;

    /**
     * String that will enable the plugin in all worlds
     */
    public static final String ALL_WORLDS = "@all";

    private Table<String/*world*/, ConfigNode, Object> OPTIONS;

    /**
     * Constructor.
     *
     * @param plugin - Plugin instance.
     */
    public MultiWorldConfig(MegaHardCore plugin) {
        super(plugin);
        init();
    }

    /**
     * Inits Objects and deletes old ones at the same time
     */
    protected void init() {
        OPTIONS = HashBasedTable.create();
    }

    /**
     * Set a value for the given node and world
     *
     * @param world - World for the value
     * @param node  - ConfigNode for the given value
     * @param value - the Object to save
     */
    public void set(final String world, final ConfigNode node, Object value) {
        Validate.notNull(node, "Supplied ConfigNode was null - world: " + world + " value: " + value);
        Validate.notNull(world, "Supplied World was null - node: " + node + " value: " + value);
        switch (node.getVarType()) {
        case LIST: {
            if (value instanceof List) {
                List list = (List) value;
                OPTIONS.put(world, node, list);
                break;
            }
        }
        case DOUBLE: {
            if (value instanceof Double) {
                OPTIONS.put(world, node, value);
                break;
            }
        }
        case STRING: {
            if (value instanceof String) {
                OPTIONS.put(world, node, value);
                break;
            }
        }
        case INTEGER: {
            if (value instanceof Integer || value instanceof Double) {
                //fix error when double is provided which can be casted
                if (value instanceof Double)
                    value = ((Double) value).intValue();
                OPTIONS.put(world, node, value);
                break;
            }
        }
        case BOOLEAN: {
            if (value instanceof Boolean) {
                OPTIONS.put(world, node, value);
                break;
            }
        }
        case POTION_EFFECT: {
            if (value instanceof PotionEffectHolder) {
                OPTIONS.put(world, node, value);
                break;
            }
        }
        case BLOCKTYPE: {
            if (value instanceof BlockType) {
                OPTIONS.put(world, node, value);
                break;
            }
        }
        case BLOCKTYPE_LIST: {
            if (value instanceof BlockTypeList) {
                OPTIONS.put(world, node, value);
                break;
            }
        }
        case BLOCK_RELATION_LIST: {
            if (value instanceof BlockRelationsList) {
                OPTIONS.put(world, node, value);
                break;
            }
        }
        default: {
            OPTIONS.put(world, node, node.getDefaultValue());
            String inputClassName = value != null ? value.getClass().getName() : "null";
            throw new IllegalArgumentException(
                    node.getPath() + " expects " + node.getVarType() + " but got " + inputClassName);
        }
        }
    }

    //     __            _     _          _   _               _ _   __    __           _     _
    //    /__\ __   __ _| |__ | | ___  __| | (_)_ __     __ _| | | / / /\ \ \___  _ __| | __| |___
    //   /_\| '_ \ / _` | '_ \| |/ _ \/ _` | | | '_ \   / _` | | | \ \/  \/ / _ \| '__| |/ _` / __|
    //  //__| | | | (_| | |_) | |  __/ (_| | | | | | | | (_| | | |  \  /\  / (_) | |  | | (_| \__ \
    //  \__/|_| |_|\__,_|_.__/|_|\___|\__,_| |_|_| |_|  \__,_|_|_|   \/  \/ \___/|_|  |_|\__,_|___/
    //

    /**
     * Return all world names were MHC is activated
     *
     * @return world names
     */
    public String[] getEnabledWorlds() {
        ArrayList<String> worlds = OPTIONS.rowMap().entrySet().stream().map(Map.Entry::getKey)
                .collect(Collectors.toCollection(ArrayList::new));
        return worlds.toArray(new String[worlds.size()]);
    }

    public boolean isEnabledIn(String world) {
        return OPTIONS.containsRow(world);
    }

    /**
     * Does this config apply to all loaded worlds
     *
     * @return if applies to all worlds
     */
    public boolean isEnabledForAll() {
        return enabledForAll;
    }

    //     ___     _   _
    //    / _ \___| |_| |_ ___ _ __ ___
    //   / /_\/ _ \ __| __/ _ \ '__/ __|
    //  / /_\\  __/ |_| ||  __/ |  \__ \
    //  \____/\___|\__|\__\___|_|  |___/
    //

    private static final BiMap<ConfigNode.VarType, Class> varTypeClassMap = HashBiMap.create();

    static {
        varTypeClassMap.put(ConfigNode.VarType.INTEGER, Integer.class);
        varTypeClassMap.put(ConfigNode.VarType.BOOLEAN, Boolean.class);
        varTypeClassMap.put(ConfigNode.VarType.BLOCKTYPE, BlockType.class);
        varTypeClassMap.put(ConfigNode.VarType.BLOCKTYPE_LIST, BlockTypeList.class);
        varTypeClassMap.put(ConfigNode.VarType.BLOCK_RELATION_LIST, BlockRelationsList.class);
        varTypeClassMap.put(ConfigNode.VarType.DOUBLE, Double.class);
        varTypeClassMap.put(ConfigNode.VarType.LIST, List.class);
        varTypeClassMap.put(ConfigNode.VarType.POTION_EFFECT, PotionEffectHolder.class);
        varTypeClassMap.put(ConfigNode.VarType.STRING, String.class);
    }

    /**
     * Generic get() (untested)
     *
     * @param node  node to use
     * @param world world name
     * @param clazz type of node
     * @param <T> Any type
     *
     * @return node value for the given world
     */
    public <T> T get(final ConfigNode node, final String world, Class<T> clazz) {
        if (!varTypeClassMap.containsKey(node.getVarType()))
            throw new IllegalArgumentException("Node " + node + " doesn't have a class set");
        Object val = OPTIONS.get(world, node);
        //VarType of node has to match VarType of the expected class
        if (varTypeClassMap.inverse().get(clazz) == node.getVarType()) {
            //Check cast
            if (varTypeClassMap.get(node.getVarType()).isInstance(val))
                return (T) OPTIONS.get(world, node);
            else
                return (T) node.getValueToDisable();
        } else
            throw new IllegalArgumentException("Attempted to get " + node.toString() + " of type "
                    + node.getVarType() + " as " + varTypeClassMap.get(node.getVarType()));
    }

    /**
     * Get the integer value of the node.
     *
     * @param node - Node to use.
     *
     * @return Value of the node. Returns -1 if unknown.
     */
    public int getInt(final ConfigNode node, final String world) {
        int i = -1;
        switch (node.getVarType()) {
        case INTEGER: {
            Object obj = null;
            if (OPTIONS.contains(world, node))
                obj = OPTIONS.get(world, node);
            else if (enabledForAll)
                obj = OPTIONS.get(ALL_WORLDS, node);
            i = obj instanceof Integer ? (Integer) obj : (Integer) node.getValueToDisable();
            break;
        }
        default: {
            throw new IllegalArgumentException(
                    "Attempted to get " + node.toString() + " of type " + node.getVarType() + " as an integer.");
        }
        }
        return i;
    }

    /**
     * Get the double value of the node.
     *
     * @param node - Node to use.
     *
     * @return Value of the node. Returns 0 if unknown.
     */
    public double getDouble(final ConfigNode node, final String world) {
        double d;
        switch (node.getVarType()) {
        case DOUBLE: {
            Object obj = null;
            if (OPTIONS.contains(world, node))
                obj = OPTIONS.get(world, node);
            else if (enabledForAll)
                obj = OPTIONS.get(ALL_WORLDS, node);
            d = obj instanceof Number ? ((Number) obj).doubleValue() : (Double) node.getValueToDisable();
            break;
        }
        default: {
            throw new IllegalArgumentException(
                    "Attempted to get " + node.toString() + " of type " + node.getVarType() + " as a double.");
        }
        }
        return d;
    }

    /**
     * Get the boolean value of the node.
     *
     * @param node - Node to use.
     *
     * @return Value of the node. Returns false if unknown.
     */
    public boolean getBoolean(final ConfigNode node, final String world) {
        boolean bool = false;
        switch (node.getVarType()) {
        case BOOLEAN: {
            Object obj = null;
            if (OPTIONS.contains(world, node))
                obj = OPTIONS.get(world, node);
            else if (enabledForAll)
                obj = OPTIONS.get(ALL_WORLDS, node);
            bool = obj instanceof Boolean ? (Boolean) obj : (Boolean) node.getValueToDisable();
            break;
        }
        default: {
            throw new IllegalArgumentException(
                    "Attempted to get " + node.toString() + " of type " + node.getVarType() + " as a boolean.");
        }
        }
        return bool;
    }

    /**
     * Get the string value of the node.
     *
     * @param node - Node to use.
     *
     * @return Value of the node. Returns and empty string if unknown.
     */
    public String getString(final ConfigNode node, final String world) {
        String out = "";
        switch (node.getVarType()) {
        case STRING: {
            Object obj = null;
            if (OPTIONS.contains(world, node))
                obj = OPTIONS.get(world, node);
            else if (enabledForAll)
                obj = OPTIONS.get(ALL_WORLDS, node);
            out = obj instanceof String ? (String) obj : (String) node.getValueToDisable();
            break;
        }
        default: {
            throw new IllegalArgumentException(
                    "Attempted to get " + node.toString() + " of type " + node.getVarType() + " as a string.");
        }
        }
        return out;
    }

    /**
     * Get the list value of the node.
     *
     * @param node - Node to use.
     *
     * @return Value of the node. Returns an empty list if unknown.
     */
    public List getStringList(final ConfigNode node, final String world) {
        List list = new ArrayList<String>();
        switch (node.getVarType()) {
        case LIST: {
            Object obj = null;
            if (OPTIONS.contains(world, node))
                obj = OPTIONS.get(world, node);
            else if (enabledForAll)
                obj = OPTIONS.get(ALL_WORLDS, node);
            list = obj instanceof List ? (List) obj : (List) node.getValueToDisable();
            break;
        }
        default: {
            throw new IllegalArgumentException("Attempted to get " + node.toString() + " of type "
                    + node.getVarType() + " as a List<String>.");
        }
        }
        return list;
    }

    public PotionEffectHolder getPotionEffect(final ConfigNode node, final String world) {
        PotionEffectHolder effect;

        switch (node.getVarType()) {
        case POTION_EFFECT: {
            Object obj = null;
            if (OPTIONS.contains(world, node))
                obj = OPTIONS.get(world, node);
            else if (enabledForAll)
                obj = OPTIONS.get(ALL_WORLDS, node);
            effect = obj instanceof PotionEffectHolder ? (PotionEffectHolder) obj
                    : (PotionEffectHolder) node.getValueToDisable();
            break;
        }
        default: {
            throw new IllegalArgumentException("Attempted to get " + node.toString() + " of type "
                    + node.getVarType() + " as a PotionEffectHolder.");
        }
        }
        return effect;
    }

    public BlockTypeList getBlocktypeList(final ConfigNode node, final String world) {
        BlockTypeList blockList;

        switch (node.getVarType()) {
        case BLOCKTYPE_LIST: {
            Object obj = null;
            if (OPTIONS.contains(world, node))
                obj = OPTIONS.get(world, node);
            else if (enabledForAll)
                obj = OPTIONS.get(ALL_WORLDS, node);
            blockList = obj instanceof BlockTypeList ? (BlockTypeList) obj
                    : (BlockTypeList) node.getValueToDisable();
            break;
        }
        default: {
            throw new IllegalArgumentException("Attempted to get " + node.toString() + " of type "
                    + node.getVarType() + " as a BlockTypeList.");
        }
        }
        return blockList;
    }

    public BlockRelationsList getBlockRelationList(final ConfigNode node, final String world) {
        BlockRelationsList blockList;

        switch (node.getVarType()) {
        case BLOCK_RELATION_LIST: {
            Object obj = null;
            if (OPTIONS.contains(world, node))
                obj = OPTIONS.get(world, node);
            else if (enabledForAll)
                obj = OPTIONS.get(ALL_WORLDS, node);
            blockList = obj instanceof BlockRelationsList ? (BlockRelationsList) obj
                    : (BlockRelationsList) node.getValueToDisable();
            break;
        }
        default: {
            throw new IllegalArgumentException("Attempted to get " + node.toString() + " of type "
                    + node.getVarType() + " as a BlockRelationsList.");
        }
        }
        return blockList;
    }

    public abstract void load();

    /**
     * Clear all the loaded config options. Primarily for unit testing purposes.
     */
    public void clearCache() {
        OPTIONS.clear();
    }
}