fr.zcraft.zlib.components.rawtext.RawTextPart.java Source code

Java tutorial

Introduction

Here is the source code for fr.zcraft.zlib.components.rawtext.RawTextPart.java

Source

/*
 * Copyright or  or Copr. ZLib contributors (2015 - 2016)
 *
 * This software is governed by the CeCILL-B license under French law and
 * abiding by the rules of distribution of free software.  You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL-B
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 *
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 *
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-B license and that you accept its terms.
 */

package fr.zcraft.zlib.components.rawtext;

import com.google.common.base.CaseFormat;
import fr.zcraft.zlib.components.commands.Command;
import fr.zcraft.zlib.components.commands.Commands;
import fr.zcraft.zlib.tools.PluginLogger;
import fr.zcraft.zlib.tools.items.ItemUtils;
import fr.zcraft.zlib.tools.reflection.NMSException;
import org.bukkit.Achievement;
import org.bukkit.ChatColor;
import org.bukkit.Statistic;
import org.bukkit.entity.Entity;
import org.bukkit.inventory.ItemStack;
import org.json.simple.JSONArray;
import org.json.simple.JSONAware;
import org.json.simple.JSONObject;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;

public abstract class RawTextPart<T extends RawTextPart<T>> implements Iterable<RawTextPart>, JSONAware {
    static private enum ActionClick {
        OPEN_URL, RUN_COMMAND, SUGGEST_COMMAND
    }

    static private enum ActionHover {
        SHOW_TEXT, SHOW_ACHIEVEMENT, SHOW_ITEM, SHOW_ENTITY
    }

    private String text;
    private boolean translate = false;

    private final RawTextPart parent;
    private final ArrayList<RawTextPart> extra = new ArrayList<>();

    private ChatColor color;
    //Text styles
    private boolean bold = false;
    private boolean italic = false;
    private boolean underline = false;
    private boolean obfuscated = false;
    private boolean strikethrough = false;

    //Other
    private ActionClick actionClick = null;
    private String actionClickValue = null;

    private ActionHover actionHover = null;
    private Object actionHoverValue = null;

    RawTextPart() {
        this(null);
    }

    RawTextPart(String text) {
        this(text, null);
    }

    RawTextPart(String text, RawTextPart parent) {
        this.text = text;
        this.parent = parent;
    }

    public RawTextPart then() {
        return then(null);
    }

    public RawTextPart then(String text) {
        RawTextPart root = getRoot();
        RawTextPart newPart = new RawTextSubPart(text, root);

        root.extra.add(newPart);
        return newPart;
    }

    public T text(String text) {
        this.text = text;
        this.translate = false;

        return (T) this;
    }

    public T translate(String text) {
        this.text = text;
        this.translate = true;

        return (T) this;
    }

    public T translate(ItemStack item) {
        String trName;

        try {
            trName = ItemUtils.getI18nName(item);
        } catch (NMSException ex) {
            PluginLogger.warning("Exception while retreiving item i18n key", ex);
            trName = "item." + item.getType().toString().toLowerCase() + ".name";
        }

        return translate(trName);
    }

    public T color(ChatColor color) {
        if (this.color != null)
            throw new IllegalStateException("Color already set.");
        if (color == null)
            return (T) this;
        if (!color.isColor())
            throw new IllegalArgumentException("Invalid color.");
        this.color = color;

        return (T) this;
    }

    public T style(ChatColor style) {
        if (style == null)
            return (T) this;
        if (style.isColor())
            return this.color(style);

        switch (style) {
        case BOLD:
            bold = true;
            break;
        case ITALIC:
            italic = true;
            break;
        case STRIKETHROUGH:
            strikethrough = true;
            break;
        case UNDERLINE:
            underline = true;
            break;
        case MAGIC:
            obfuscated = true;
            break;
        default:
            throw new IllegalArgumentException("Invalid style : " + style.name());
        }

        return (T) this;
    }

    public T style(ChatColor... styles) {
        for (ChatColor style : styles) {
            style(style);
        }
        return (T) this;
    }

    public T style(Iterable<ChatColor> styles) {
        for (ChatColor style : styles) {
            style(style);
        }
        return (T) this;
    }

    private T hover(ActionHover action, Object object) {
        if (actionHover != null)
            throw new IllegalStateException("Hover action " + actionHover.name() + " has already been set.");
        actionHover = action;
        actionHoverValue = object;
        return (T) this;
    }

    public T hover(RawTextPart hoverText) {
        return hover(ActionHover.SHOW_TEXT, hoverText.build());
    }

    private String enumCamel(Enum enumValue) {
        return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, enumValue.toString());
    }

    public T hover(Achievement achievement) {
        return hover(ActionHover.SHOW_ACHIEVEMENT, "achievement." + RawText.getI18nKey(achievement));
    }

    public T hover(Statistic statistic) {
        return hover(ActionHover.SHOW_ACHIEVEMENT, "stat." + enumCamel(statistic));
    }

    public T hover(ItemStack item) {
        return hover(ActionHover.SHOW_ITEM, RawText.toJSONString(item));
    }

    public T hover(Entity entity) {
        return hover(ActionHover.SHOW_ENTITY, RawText.toJSON(entity).toJSONString());
    }

    private T click(ActionClick action, String value) {
        if (actionClick != null)
            throw new IllegalStateException("Hover action " + actionClick.name() + " has already been set.");
        actionClick = action;
        actionClickValue = value;
        return (T) this;
    }

    public T command(String command) {
        return click(ActionClick.RUN_COMMAND, command);
    }

    public T command(Class<? extends Command> command, String... args) {
        Command commandInfo = Commands.getCommandInfo(command);
        if (commandInfo == null)
            throw new IllegalArgumentException("Unknown command");
        return command(commandInfo.build(args));
    }

    public T uri(String uri) throws URISyntaxException {
        return uri(new URI(uri));
    }

    public T uri(URI uri) {
        return click(ActionClick.OPEN_URL, uri.toString());
    }

    public T suggest(String suggestion) {
        return click(ActionClick.SUGGEST_COMMAND, suggestion);
    }

    public RawText build() {
        if (parent != null)
            return parent.build();
        if (this instanceof RawText)
            return (RawText) this;
        throw new RuntimeException("Dangling non-root text part");
    }

    private RawTextPart getRoot() {
        if (parent != null)
            return parent.getRoot();
        return this;
    }

    static private JSONObject actionToJSON(Enum action, Object value) {
        JSONObject obj = new JSONObject();
        obj.put("action", action.name().toLowerCase());
        obj.put("value", value);
        return obj;
    }

    public JSONObject toJSON() {
        JSONObject obj = new JSONObject();
        if (translate) {
            obj.put("translate", text);
        } else {
            obj.put("text", text);
        }

        if (!extra.isEmpty()) {
            JSONArray extraArray = new JSONArray();
            for (RawTextPart childPart : this) {
                extraArray.add(childPart.toJSON());
            }
            obj.put("extra", extraArray);
        }

        if (color != null)
            obj.put("color", RawText.toStyleName(color));

        if (bold)
            obj.put("bold", true);
        if (italic)
            obj.put("italic", true);
        if (underline)
            obj.put("underlined", true);
        if (strikethrough)
            obj.put("strikethrough", true);
        if (obfuscated)
            obj.put("obfuscated", true);

        if (actionClick != null && actionClickValue != null)
            obj.put("clickEvent", actionToJSON(actionClick, actionClickValue));

        if (actionHover != null && actionHoverValue != null)
            obj.put("hoverEvent", actionToJSON(actionHover, actionHoverValue));

        return obj;
    }

    @Override
    public String toJSONString() {
        return toJSON().toJSONString();
    }

    public String toPlainText() {
        StringBuilder buf = new StringBuilder();
        writePlainText(buf);
        return buf.toString();
    }

    private void writePlainText(StringBuilder buf) {
        buf.append(text);

        for (RawTextPart subPart : this) {
            subPart.writePlainText(buf);
        }
    }

    public String toFormattedText() {
        StringBuilder buf = new StringBuilder();
        writeFormattedText(buf);
        return buf.toString();
    }

    private void writeFormattedText(StringBuilder buf) {
        if (color != null)
            buf.append(color);
        if (bold)
            buf.append(ChatColor.BOLD);
        if (italic)
            buf.append(ChatColor.ITALIC);
        if (underline)
            buf.append(ChatColor.UNDERLINE);
        if (strikethrough)
            buf.append(ChatColor.STRIKETHROUGH);
        if (obfuscated)
            buf.append(ChatColor.MAGIC);

        buf.append(text);
        buf.append(ChatColor.RESET);

        for (RawTextPart subPart : this) {
            subPart.writeFormattedText(buf);
        }

    }

    @Override
    public Iterator<RawTextPart> iterator() {
        return extra.iterator();
    }
}