Package net.aufdemrand.denizen.scripts.commands.core

Source Code of net.aufdemrand.denizen.scripts.commands.core.YamlCommand

package net.aufdemrand.denizen.scripts.commands.core;

import net.aufdemrand.denizen.Settings;
import net.aufdemrand.denizen.events.bukkit.ReplaceableTagEvent;
import net.aufdemrand.denizencore.exceptions.CommandExecutionException;
import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException;
import net.aufdemrand.denizen.scripts.ScriptEntry;
import net.aufdemrand.denizen.scripts.commands.AbstractCommand;
import net.aufdemrand.denizen.tags.Attribute;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.objects.*;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizencore.scripts.ScriptHelper;
import net.aufdemrand.denizencore.utilities.YamlConfiguration;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.json.JSONObject;

import java.io.*;
import java.net.URLDecoder;
import java.util.*;

public class YamlCommand extends AbstractCommand implements Listener {

    @Override
    public void onEnable() {
        Bukkit.getServer().getPluginManager().registerEvents(this, DenizenAPI.getCurrentInstance());
    }

    Map<String, YamlConfiguration> yamls = new HashMap<String, YamlConfiguration>();

    private YamlConfiguration getYaml(String id) {
        if (id == null) return null;
        return yamls.get(id.toUpperCase());
    }

    public static enum Action { LOAD, UNLOAD, CREATE, WRITE, SAVE, SET }

    public static enum YAML_Action { SET_VALUE, INCREASE, DECREASE, MULTIPLY,
        DIVIDE, INSERT, REMOVE, SPLIT, DELETE }

    @Override
    public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {

        boolean isSet = false;

        for (aH.Argument arg : aH.interpret(scriptEntry.getArguments())) {
            if (!scriptEntry.hasObject("action") &&
                    arg.matchesPrefix("LOAD")) {
                scriptEntry.addObject("action", new Element("LOAD"));
                scriptEntry.addObject("filename", arg.asElement());
            }

            else if (!scriptEntry.hasObject("action") &&
                    arg.matchesPrefix("SAVEFILE", "FILESAVE")) {
                scriptEntry.addObject("action", new Element("SAVE"));
                scriptEntry.addObject("filename", arg.asElement());
            }

            else if (!scriptEntry.hasObject("action") &&
                    arg.matches("CREATE")) {
                scriptEntry.addObject("action", new Element("CREATE"));
            }

            else if (!scriptEntry.hasObject("action") &&
                    arg.matches("SET")) {
                scriptEntry.addObject("action", new Element("SET"));
                isSet = true;
            }

            else if (!scriptEntry.hasObject("action") &&
                    arg.matches("UNLOAD")) {
                scriptEntry.addObject("action", new Element("UNLOAD"));
            }

            else if (!scriptEntry.hasObject("action") &&
                    arg.matchesPrefix("WRITE")) {
                scriptEntry.addObject("action", new Element("WRITE"));
                scriptEntry.addObject("key", arg.asElement());
            }

            else if (!scriptEntry.hasObject("value") &&
                    arg.matchesPrefix("VALUE")) {
                if (arg.matchesArgumentType(dList.class))
                    scriptEntry.addObject("value", arg.asType(dList.class));
                else
                    scriptEntry.addObject("value", arg.asElement());
            }

            else if (!scriptEntry.hasObject("id") &&
                    arg.matchesPrefix("ID")) {
                scriptEntry.addObject("id", arg.asElement());
            }

            else if (!scriptEntry.hasObject("split") &&
                    arg.matches("split_list")) {
                scriptEntry.addObject("split", Element.TRUE);
            }

            // Check for key:value/action
            else if (isSet &&
                    !scriptEntry.hasObject("value") &&
                    arg.raw_value.split(":", 3).length == 2) {

                String[] flagArgs = arg.raw_value.split(":", 2);
                scriptEntry.addObject("key", new Element(flagArgs[0]));

                if (flagArgs[1].equals("++") || flagArgs[1].equals("+")) {
                    scriptEntry.addObject("yaml_action", YAML_Action.INCREASE);
                    scriptEntry.addObject("value", new Element(1));
                }
                else if (flagArgs[1].equals("--") || flagArgs[1].equals("-")) {
                    scriptEntry.addObject("yaml_action", YAML_Action.DECREASE);
                    scriptEntry.addObject("value", new Element(1));
                }
                else if (flagArgs[1].equals("!")) {
                    scriptEntry.addObject("yaml_action", YAML_Action.DELETE);
                    scriptEntry.addObject("value", Element.FALSE);
                }
                else if (flagArgs[1].equals("<-")) {
                    scriptEntry.addObject("yaml_action", YAML_Action.REMOVE);
                    scriptEntry.addObject("value", Element.FALSE);
                }
                else {
                    // No ACTION, we're just setting a value...
                    scriptEntry.addObject("yaml_action", YAML_Action.SET_VALUE);
                    scriptEntry.addObject("value", new Element(flagArgs[1]));
                }
            }

            // Check for key:action:value
            else if (isSet &&
                    !scriptEntry.hasObject("value") &&
                    arg.raw_value.split(":", 3).length == 3) {
                String[] flagArgs = arg.raw_value.split(":", 3);
                scriptEntry.addObject("key", new Element(flagArgs[0]));

                if (flagArgs[1].equals("->"))
                    scriptEntry.addObject("yaml_action", YAML_Action.INSERT);

                else if (flagArgs[1].equals("<-"))
                    scriptEntry.addObject("yaml_action", YAML_Action.REMOVE);

                else if (flagArgs[1].equals("||") || flagArgs[1].equals("|"))
                    scriptEntry.addObject("yaml_action", YAML_Action.SPLIT);

                else if (flagArgs[1].equals("++") || flagArgs[1].equals("+"))
                    scriptEntry.addObject("yaml_action", YAML_Action.INCREASE);

                else if (flagArgs[1].equals("--") || flagArgs[1].equals("-"))
                    scriptEntry.addObject("yaml_action", YAML_Action.DECREASE);

                else if (flagArgs[1].equals("**") || flagArgs[1].equals("*"))
                    scriptEntry.addObject("yaml_action", YAML_Action.MULTIPLY);

                else if (flagArgs[1].equals("//") || flagArgs[1].equals("/"))
                    scriptEntry.addObject("yaml_action", YAML_Action.DIVIDE);

                else {
                    scriptEntry.addObject("yaml_action", YAML_Action.SET_VALUE);
                    scriptEntry.addObject("value", new Element(arg.raw_value.split(":", 2)[1]));
                    continue;
                }
                scriptEntry.addObject("value", new Element(flagArgs[2]));
            }

            else arg.reportUnhandled();
        }

        // Check for required arguments

        if (!scriptEntry.hasObject("id"))
            throw new InvalidArgumentsException("Must specify an id!");

        if (!scriptEntry.hasObject("action"))
            throw new InvalidArgumentsException("Must specify an action!");

        if (!scriptEntry.hasObject("key") &&
                scriptEntry.getElement("action").asString().equalsIgnoreCase("write"))
            throw new InvalidArgumentsException("Must specify a key!");

        scriptEntry.defaultObject("value", new Element(""));
    }


    @Override
    public void execute(final ScriptEntry scriptEntry) throws CommandExecutionException {

        Element filename = scriptEntry.getElement("filename");
        Element key = scriptEntry.getElement("key");
        dObject value = scriptEntry.getdObject("value");
        Element split = scriptEntry.getElement("split");
        YAML_Action yaml_action = (YAML_Action) scriptEntry.getObject("yaml_action");
        Element actionElement = scriptEntry.getElement("action");
        Element idElement = scriptEntry.getElement("id");

        YamlConfiguration yamlConfiguration;

        dB.report(scriptEntry, getName(),
                        idElement.debug()
                        + actionElement.debug()
                        + (filename != null ? filename.debug() : "")
                        + (yaml_action != null ? aH.debugObj("yaml_action", yaml_action.name()): "")
                        + (key != null ? key.debug() : "")
                        + (value != null ? value.debug() : "")
                        + (split != null ? split.debug() : ""));

        // Do action
        Action action = Action.valueOf(actionElement.asString().toUpperCase());
        String id = idElement.asString().toUpperCase();

        switch (action) {

            case LOAD:
                File file = new File(DenizenAPI.getCurrentInstance().getDataFolder(), filename.asString());
                if (!file.exists()) {
                    dB.echoError("File cannot be found!");
                    return;
                }
                try {
                    FileInputStream fis = new FileInputStream(file);
                    yamlConfiguration = YamlConfiguration.load(ScriptHelper.convertStreamToString(fis));
                    fis.close();
                }
                catch (Exception e) {
                    dB.echoError(e);
                    return;
                }
                if (yamls.containsKey(id))
                    yamls.remove(id);
                if (yamlConfiguration != null)
                    yamls.put(id, yamlConfiguration);
                break;

            case UNLOAD:
                if (yamls.containsKey(id))
                    yamls.remove(id);
                else
                    dB.echoError("Unknown YAML ID '" + id + "'");
                break;

            case SAVE:
                if (yamls.containsKey(id)) {
                    try {
                        if (!Settings.allowStrangeYAMLSaves()) {
                            File fileObj = new File(DenizenAPI.getCurrentInstance().
                                    getDataFolder().getAbsolutePath() + "/" + filename.asString());
                            String directory = URLDecoder.decode(System.getProperty("user.dir"));
                            if (!fileObj.getCanonicalPath().startsWith(directory)) {
                                dB.echoError("Outside-the-main-folder YAML saves disabled by administrator.");
                                return;
                            }
                        }
                        File fileObj = new File(DenizenAPI.getCurrentInstance().
                                getDataFolder().getAbsolutePath() + "/" + filename.asString());
                        fileObj.getParentFile().mkdirs();
                        FileWriter fw = new FileWriter(DenizenAPI.getCurrentInstance()
                                .getDataFolder().getAbsolutePath() + "/" + filename.asString());
                        BufferedWriter writer = new BufferedWriter(fw);
                        writer.write(yamls.get(id).saveToString());
                        writer.close();
                        fw.close();
                    } catch (IOException e) {
                        dB.echoError(e);
                    }
                }
                else
                    dB.echoError("Unknown YAML ID '" + id + "'");
                break;

            case WRITE:
                if (yamls.containsKey(id)) {
                    if (value instanceof Element)
                        yamls.get(id).set(key.asString(), ((Element) value).asString());
                    else if (split != null && split.asBoolean())
                        yamls.get(id).set(key.asString(), value);
                    else
                        yamls.get(id).set(key.asString(), value.identify());
                }
                else
                    dB.echoError("Unknown YAML ID '" + id + "'");
                break;

            case SET:
                if (yamls.containsKey(id)) {
                    if (yaml_action == null || key == null || value == null) {
                        dB.echoError("Must specify a YAML action and value!");
                        return;
                    }
                    YamlConfiguration yaml = yamls.get(id);

                    int index = -1;
                    if (key.asString().contains("[")) {
                        try {
                            index = Integer.valueOf(key.asString().split("\\[")[1].replace("]", "")) - 1;
                        } catch (Exception e) { index = -1; }
                        key = Element.valueOf(key.asString().split("\\[")[0]);
                    }

                    String keyStr = key.asString();
                    String valueStr = value.identify();

                    switch (yaml_action) {
                        case INCREASE:
                            Set(yaml, index, keyStr, String.valueOf(aH.getIntegerFrom(Get(yaml, index, keyStr, "0")) + aH.getIntegerFrom(valueStr)));
                            break;
                        case DECREASE:
                            Set(yaml, index, keyStr, String.valueOf(aH.getIntegerFrom(Get(yaml, index, keyStr, "0")) - aH.getIntegerFrom(valueStr)));
                            break;
                        case MULTIPLY:
                            Set(yaml, index, keyStr, String.valueOf(aH.getIntegerFrom(Get(yaml, index, keyStr, "1")) * aH.getIntegerFrom(valueStr)));
                            break;
                        case DIVIDE:
                            Set(yaml, index, keyStr, String.valueOf(aH.getIntegerFrom(Get(yaml, index, keyStr, "1")) / aH.getIntegerFrom(valueStr)));
                            break;
                        case DELETE:
                            yaml.set(keyStr, null);
                            break;
                        case SET_VALUE:
                            Set(yaml, index, keyStr, valueStr);
                            break;
                        case INSERT:
                        {
                            List<String> list = yaml.getStringList(keyStr);
                            if (list == null)
                                list = new ArrayList<String>();
                            list.add(valueStr);
                            yaml.set(keyStr, list);
                            break;
                        }
                        case REMOVE:
                        {
                            List<String> list = yaml.getStringList(keyStr);
                            if (list == null)
                                break;
                            if (index > -1 && index < list.size()) {
                                list.remove(index);
                            }
                            else {
                                for (int i = 0; i < list.size(); i++) {
                                    if (list.get(i).equalsIgnoreCase(valueStr)) {
                                        list.remove(i);
                                        break;
                                    }
                                }
                                yaml.set(keyStr, list);
                                break;
                            }
                        }
                        case SPLIT:
                        {
                            List<String> list = yaml.getStringList(keyStr);
                            if (list == null)
                                list = new ArrayList<String>();
                            list.addAll(dList.valueOf(valueStr));
                            yaml.set(keyStr, list);
                            break;
                        }
                    }
                }
                else
                    dB.echoError("Unknown YAML ID '" + id + "'");
                break;

            case CREATE:
                if (yamls.containsKey(id))
                    yamls.remove(id);
                yamlConfiguration = new YamlConfiguration();
                yamls.put(id.toUpperCase(), yamlConfiguration);
                break;
        }

    }

    public String Get(YamlConfiguration yaml, int index, String key, String def) {
        if (index == -1) {
            return yaml.getString(key, def);
        }
        else {
            List<String> list = yaml.getStringList(key);
            if (index < 0)
                index = 0;
            if (index > list.size())
                index = list.size() -1;
            if (list.size() == 0)
                return "";
            return list.get(index);
        }
    }

    public void Set(YamlConfiguration yaml, int index, String key, String value) {
        if (index == -1) {
            yaml.set(key, value);
        }
        else {
            List<String> list = yaml.getStringList(key);
            if (index < 0)
                index = 0;
            if (index > list.size())
                index = list.size() -1;
            if (list.size() == 0)
                list.add("");
            list.set(index, value);
            yaml.set(key, list);
        }
    }

    @EventHandler
    public void yaml(ReplaceableTagEvent event) {

        if (!event.matches("yaml")) return;

        Attribute attribute = event.getAttributes();

        // <--[tag]
        // @attribute <yaml.list>
        // @returns dList
        // @description
        // Returns a list of all currently loaded YAML ID's.
        // -->
        if (attribute.getAttribute(2).equalsIgnoreCase("list")) {
            dList list = new dList();
            list.addAll(yamls.keySet());
            event.setReplaced(list.getAttribute(attribute.fulfill(2)));
            return;
        }

        // YAML tag requires name context and type context.
        if (!event.hasNameContext() || !(event.hasTypeContext() || attribute.getAttribute(2).equalsIgnoreCase("to_json"))) {
            dB.echoError("YAML tag '" + event.raw_tag + "' is missing required context. Tag replacement aborted.");
            return;
        }

        // Set id (name context) and path (type context)
        String id = event.getNameContext();
        String path = event.getTypeContext();

        // Check if there is a yaml file loaded with the specified id
        if (!yamls.containsKey(id.toUpperCase())) {
            dB.echoError("YAML tag '" + event.raw_tag + "' has specified an invalid ID, or the specified id has already" +
                    " been closed. Tag replacement aborted. ID given: '" + id + "'.");
            return;
        }

        // Catch up with what has already been processed.
        attribute.fulfill(1);

        //
        // Check attributes
        //

        // <--[tag]
        // @attribute <yaml[<id>].contains[<path>]>
        // @returns Element(Boolean)
        // @description
        // Returns true if the file has the specified path.
        // Otherwise, returns false.
        // -->
        if (attribute.startsWith("contains")) {
            event.setReplaced(new Element(getYaml(id).contains(path))
                    .getAttribute(attribute.fulfill(1)));
            return;
        }

        // <--[tag]
        // @attribute <yaml[<id>].is_list[<path>]>
        // @returns Element(Boolean)
        // @description
        // Returns true if the specified path results in a list.
        // -->
        if (attribute.startsWith("is_list")) {
            event.setReplaced(new Element(getYaml(id).isList(path))
                    .getAttribute(attribute.fulfill(1)));
            return;
        }

        // <--[tag]
        // @attribute <yaml[<id>].read[<path>]>
        // @returns Element
        // @description
        // Returns the value of the key at the path.
        // If the key is a list, returns a dList instead.
        // -->
        if (attribute.startsWith("read")) {
            attribute.fulfill(1);

            if (getYaml(id).isList(path)) {
                List<String> value = getYaml(id).getStringList(path);
                if (value == null) {
                    // If value is null, the key at the specified path didn't exist.
                    return;
                }
                else {
                    event.setReplaced(new dList(value).getAttribute(attribute));
                    return;
                }
            }
            else {
                String value = getYaml(id).getString(path);
                if (value == null) {
                    // If value is null, the key at the specified path didn't exist.
                    return;
                }
                else {
                    event.setReplaced(new Element(value).getAttribute(attribute));
                    return;
                }
            }
        }

        // <--[tag]
        // @attribute <yaml[<id>].list_deep_keys[<path>]>
        // @returns dList
        // @description
        // Returns a dList of all the keys at the path and all subpaths.
        // -->
        if (attribute.startsWith("list_deep_keys")) {
            Set<String> keys;
            if (path != null && path.length() > 0) {
                YamlConfiguration section = getYaml(id).getConfigurationSection(path);
                if (section == null) {
                    return;
                }
                keys = section.getKeys(true);
            }
            else {
                keys = getYaml(id).getKeys(true);
            }
            if (keys == null) {
                return;

            } else {
                ArrayList<String> list = new ArrayList<String>();
                list.addAll(keys);
                event.setReplaced(new dList(list).getAttribute(attribute.fulfill(1)));
                return;
            }
        }

        // <--[tag]
        // @attribute <yaml[<id>].list_keys[<path>]>
        // @returns dList
        // @description
        // Returns a dList of all the keys at the path.
        // -->
        if (attribute.startsWith("list_keys")) {
            Set<String> keys;
            if (path != null && path.length() > 0) {
                YamlConfiguration section = getYaml(id).getConfigurationSection(path);
                if (section == null) {
                    return;
                }
                keys = section.getKeys(false);
            }
            else {
                keys = getYaml(id).getKeys(false);
            }
            if (keys == null) {
                return;

            } else {
                ArrayList<String> list = new ArrayList<String>();
                list.addAll(keys);
                event.setReplaced(new dList(list).getAttribute(attribute.fulfill(1)));
                return;
            }
        }

        // <--[tag]
        // @attribute <yaml[<id>].to_json>
        // @returns dList
        // @description
        // Converts the YAML container to a JSON array.
        // -->
        if (attribute.startsWith("to_json")) {
            JSONObject jsobj = new JSONObject(getYaml(id).getMap());
            event.setReplaced(new Element(jsobj.toString()).getAttribute(attribute.fulfill(1)));
            return;
        }
    }
}
TOP

Related Classes of net.aufdemrand.denizen.scripts.commands.core.YamlCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.