/*
* This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT).
*
* Copyright (c) JCThePants (www.jcwhatever.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.jcwhatever.nucleus.utils.text;
import com.jcwhatever.nucleus.utils.text.components.IChatMessage;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* A simple Minecraft based JSON builder.
*/
public class SimpleJSONBuilder {
private int _estimatedSize = 2;
private Map<String, String> _textMap = new HashMap<>(3);
private Map<String, List<String>> _multiTextMap = new HashMap<>(3);
private Map<String, Boolean> _boolMap = new HashMap<>(3);
/**
* Insert a boolean property.
*
* @param propertyName The property name.
* @param value The property value.
*
* @return Self for chaining.
*/
public SimpleJSONBuilder bool(String propertyName, boolean value) {
_boolMap.put(propertyName, value);
_estimatedSize += propertyName.length() + 20;
return this;
}
/**
* Insert a text based property.
*
* @param propertyName The property name.
* @param value The text value.
* @param args Optional format arguments.
*
* @return Self for chaining.
*/
public SimpleJSONBuilder text(String propertyName, CharSequence value, Object... args) {
IChatMessage text = TextUtils.format(value, args);
_textMap.put(propertyName, text.toString());
_estimatedSize += propertyName.length() + text.length() + 20;
return this;
}
/**
* Insert a list of text.
*
* <p>List is converted to a JSON array of text.</p>
*
* @param propertyName The property name.
* @param values The text list.
*
* @return Self for chaining.
*/
public SimpleJSONBuilder text(String propertyName, List<String> values) {
_multiTextMap.put(propertyName, values);
_estimatedSize += propertyName.length() + (values.size() * 15) + 20;
return this;
}
/**
* Build the JSON text.
*
* @return The JSON text.
*/
public String build() {
StringBuilder buffer = new StringBuilder(_estimatedSize);
boolean hasProperties = false;
buffer.append('{');
// boolean entries
for (Entry<String, Boolean> boolEntry : _boolMap.entrySet()) {
if (hasProperties)
buffer.append(',');
hasProperties = true;
String propertyName = boolEntry.getKey();
Boolean value = boolEntry.getValue();
buffer.append('"');
buffer.append(propertyName);
buffer.append("\":");
buffer.append(value ? "true" : "false");
}
// text entries
for (Entry<String, String> textEntry : _textMap.entrySet()) {
if (hasProperties)
buffer.append(',');
hasProperties = true;
String propertyName = textEntry.getKey();
String text = textEntry.getValue();
TextComponents components = new TextComponents(text);
buffer.append('"');
buffer.append(propertyName);
buffer.append("\":\"");
try {
getJsonText(buffer, components, true);
} catch (IOException e) {
e.printStackTrace();
}
buffer.append('\"');
}
// multi text entries
for (Entry<String, List<String>> textEntry : _multiTextMap.entrySet()) {
if (hasProperties)
buffer.append(',');
hasProperties = true;
String propertyName = textEntry.getKey();
List<String> textList = textEntry.getValue();
buffer.append('"');
buffer.append(propertyName);
buffer.append("\":[");
for (int i=0; i < textList.size(); i++) {
String rawText = textList.get(i);
String text = TextUtils.format(rawText).toString();
TextComponents components = new TextComponents(text);
if (i != 0)
buffer.append(',');
buffer.append('"');
try {
getJsonText(buffer, components, true);
} catch (IOException e) {
e.printStackTrace();
}
buffer.append('"');
}
buffer.append(']');
}
buffer.append('}');
return buffer.toString();
}
/**
* Create a standalone text JSON string.
*
* @param textTemplate The text or text template.
* @param args Optional format arguments.
*
* @return The text JSON string.
*/
public static String text(Object textTemplate, Object... args) {
StringBuilder buffer = new StringBuilder(textTemplate.toString().length() + 30);
text(buffer, textTemplate, args);
return buffer.toString();
}
/**
* Create a standalone text JSON string and append to the
* supplied {@link StringBuilder}.
*
* @param buffer The {@link StringBuilder} to append the output to.
* @param textTemplate The text or text template.
* @param args Optional format arguments.
*/
public static void text(StringBuilder buffer, Object textTemplate, Object... args) {
try {
text((Appendable)buffer, textTemplate, args);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Create a standalone text JSON string and append to the
* supplied {@link java.lang.StringBuilder}.
*
* @param buffer The {@link java.lang.StringBuilder} to append the output to.
* @param textTemplate The text or text template.
* @param args Optional format arguments.
*/
public static void text(Appendable buffer, Object textTemplate, Object... args) throws IOException {
String rawText = TextUtils.format(textTemplate, args).toString();
TextComponents components = new TextComponents(rawText);
getJsonText(buffer, components, false);
}
/**
* Create a standalone text JSON string and append to the
* supplied {@link java.lang.StringBuilder}.
*
* @param buffer The {@link java.lang.Appendable} to append the output to.
* @param components The text components.
*/
public static void text(Appendable buffer, TextComponents components) {
try {
getJsonText(buffer, components, false);
} catch (IOException e) {
e.printStackTrace();
}
}
// generate standalone JSON text.
private static void getJsonText(Appendable buffer, TextComponents segments, boolean escape) throws IOException {
buffer.append('{');
getJsonTextSegment(buffer, segments.get(0), escape);
if (segments.size() > 1) {
buffer.append(",\"extra\":[");
for (int i=1; i < segments.size(); i++) {
buffer.append('{');
getJsonTextSegment(buffer, segments.get(i), escape);
buffer.append('}');
if (i < segments.size() - 1) {
buffer.append(',');
}
}
buffer.append(']');
}
buffer.append('}');
}
// generate a text property segment.
private static void getJsonTextSegment(Appendable buffer, TextComponent segment, boolean escape)
throws IOException {
buffer.append("\"text\":");
if (escape)
buffer.append("\\\"");
else
buffer.append('"');
buffer.append(segment.getText());
if (escape)
buffer.append("\\\"");
else
buffer.append('"');
if (!segment.isReset()) {
if (segment.getColor() != null) {
buffer.append(",\"color\":");
buffer.append(segment.getColor().getMinecraftName());
}
if (segment.isBold())
buffer.append(",\"bold\":true");
if (segment.isItalic())
buffer.append(",\"italic\":true");
if (segment.isMagic())
buffer.append(",\"obfuscated\":true");
if (segment.isStrikethrough())
buffer.append(",\"strikethrough\":true");
if (segment.isUnderline())
buffer.append(",\"underlined\":true");
}
}
}