From acfed5a266aded820a175efff3334cea78a82ffd Mon Sep 17 00:00:00 2001 From: jascotty2 Date: Thu, 29 Aug 2019 11:23:41 -0500 Subject: [PATCH] sync config work --- .../com/songoda/core/settingsv2/Comment.java | 40 +++++++ .../com/songoda/core/settingsv2/Config.java | 113 +++++++++++++++++- .../settingsv2/ConfigFormattingRules.java | 40 ++++++- .../settingsv2/adapters/ConfigAdapter.java | 66 ++++++++++ 4 files changed, 251 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/songoda/core/settingsv2/adapters/ConfigAdapter.java diff --git a/src/main/java/com/songoda/core/settingsv2/Comment.java b/src/main/java/com/songoda/core/settingsv2/Comment.java index a0809851..11a9c58b 100644 --- a/src/main/java/com/songoda/core/settingsv2/Comment.java +++ b/src/main/java/com/songoda/core/settingsv2/Comment.java @@ -1,6 +1,8 @@ package com.songoda.core.settingsv2; import com.songoda.core.settingsv2.ConfigFormattingRules.CommentStyle; +import java.io.IOException; +import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -39,4 +41,42 @@ public class Comment { return lines; } + public void writeComment(Writer output, int offset, CommentStyle defaultStyle) throws IOException { + CommentStyle style = commentStyle != null ? commentStyle : defaultStyle; + int minSpacing = 0, borderSpacing = 0; + // first draw the top of the comment + if (style.drawBorder) { + // grab the longest line in the list of lines + minSpacing = lines.stream().max((s1, s2) -> s1.length() - s2.length()).get().length(); + borderSpacing = minSpacing + style.commentPrefix.length() + style.commentSuffix.length(); + // draw the first line + output.write((new String(new char[offset])).replace('\0', ' ') + (new String(new char[borderSpacing + 2])).replace('\0', '#') + "\n"); + if (style.drawSpace) { + output.write((new String(new char[offset])).replace('\0', ' ') + + "#" + style.spacePrefixTop + + (new String(new char[borderSpacing - style.spacePrefixTop.length() - style.spaceSuffixTop.length()])).replace('\0', style.spaceCharTop) + + style.spaceSuffixTop + "#\n"); + } + } else if (style.drawSpace) { + output.write((new String(new char[offset])).replace('\0', ' ') + "#\n"); + } + // then the actual comment lines + for (String line : lines) { + // todo? should we auto-wrap comment lines that are longer than 80 characters? + output.write((new String(new char[offset])).replace('\0', ' ') + "#" + style.commentPrefix + + (minSpacing == 0 ? line : line + (new String(new char[minSpacing - line.length()])).replace('\0', ' ')) + style.commentSuffix + (style.drawBorder ? "#\n" : "\n")); + } + // now draw the bottom of the comment border + if (style.drawBorder) { + if (style.drawSpace) { + output.write((new String(new char[offset])).replace('\0', ' ') + + "#" + style.spacePrefixBottom + + (new String(new char[borderSpacing - style.spacePrefixBottom.length() - style.spaceSuffixBottom.length()])).replace('\0', style.spaceCharBottom) + + style.spaceSuffixBottom + "#\n"); + } + output.write((new String(new char[offset])).replace('\0', ' ') + (new String(new char[borderSpacing + 2])).replace('\0', '#') + "\n"); + } else if (style.drawSpace) { + output.write((new String(new char[offset])).replace('\0', ' ') + "#\n"); + } + } } diff --git a/src/main/java/com/songoda/core/settingsv2/Config.java b/src/main/java/com/songoda/core/settingsv2/Config.java index 9d2b376f..e3b0c224 100644 --- a/src/main/java/com/songoda/core/settingsv2/Config.java +++ b/src/main/java/com/songoda/core/settingsv2/Config.java @@ -1,23 +1,70 @@ package com.songoda.core.settingsv2; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import org.bukkit.Color; import org.bukkit.OfflinePlayer; import org.bukkit.configuration.Configuration; -import org.bukkit.configuration.ConfigurationOptions; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.configuration.file.YamlConfigurationOptions; +import org.bukkit.configuration.file.YamlConstructor; +import org.bukkit.configuration.file.YamlRepresenter; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.representer.Representer; -public class Config implements Configuration { +public class Config extends YamlConfiguration { + /* + Serialization notes: + // implements ConfigurationSerializable: + //public Map serialize(); + + // Class must contain one of: + // public static Object deserialize(@NotNull Map args); + // public static valueOf(Map args); + // public new (Map args) + */ + + final File file; + final DumperOptions yamlOptions = new DumperOptions(); + final Representer yamlRepresenter = new YamlRepresenter(); + final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions); + protected int indentation = 2; // between 2 and 9 (inclusive) + protected char pathChar = '.'; final HashMap configComments = new HashMap(); + final HashMap strictKeys = new HashMap(); + final HashMap values = new HashMap(); - public Config setConfigDescription(String... description) { + public Config(@NotNull File file) { + this.file = file; + } + + public Config(@NotNull Plugin plugin, @NotNull String file) { + this.file = new File(plugin.getDataFolder(), file); + } + + public Config(@NotNull Plugin plugin, @NotNull String directory, @NotNull String file) { + this.file = new File(plugin.getDataFolder() + directory, file); + } + + @NotNull + public Config setHeader(@NotNull String... description) { if (description.length == 0) { configComments.remove(null); } else { @@ -26,6 +73,64 @@ public class Config implements Configuration { return this; } + @NotNull + public Config setHeader(@Nullable List description) { + if (description == null || description.isEmpty()) { + configComments.remove(null); + } else { + configComments.put(null, new Comment(description)); + } + return this; + } + + @NotNull + public List getHeader() { + if (configComments.containsKey(null)) { + return configComments.get(null).getLines(); + } else { + return Collections.EMPTY_LIST; + } + } + + @NotNull + @Override + public String saveToString() { + try { + yamlOptions.setIndent(indentation); + yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + StringWriter str = new StringWriter(); + Comment header = configComments.get(null); + if (header != null) { + header.writeComment(str, 0, ConfigFormattingRules.CommentStyle.SPACED); + } + String dump = yaml.dump(this.getValues(false)); + if (dump.equals(BLANK_CONFIG)) { + dump = ""; + } + return str.toString() + dump; + } catch (IOException ex) { + Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, ex); + } + return ""; + } + + public int getIndent() { + return indentation; + } + + public void setIndent(int indentation) { + this.indentation = indentation; + } + + public char getPathSeparator() { + return pathChar; + } + + public void setPathSeparator(char pathChar) { + this.pathChar = pathChar; + } + @Override public void addDefault(String string, Object o) { throw new UnsupportedOperationException("Not supported yet."); @@ -52,7 +157,7 @@ public class Config implements Configuration { } @Override - public ConfigurationOptions options() { + public YamlConfigurationOptions options() { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/src/main/java/com/songoda/core/settingsv2/ConfigFormattingRules.java b/src/main/java/com/songoda/core/settingsv2/ConfigFormattingRules.java index e980d8ef..c4e448f4 100644 --- a/src/main/java/com/songoda/core/settingsv2/ConfigFormattingRules.java +++ b/src/main/java/com/songoda/core/settingsv2/ConfigFormattingRules.java @@ -12,19 +12,19 @@ public class ConfigFormattingRules { /** * # Comment */ - SIMPLE, + SIMPLE(false, false, " ", ""), /** * #
* # Comment
* #
*/ - SPACED, + SPACED(false, true, " ", ""), /** * ###########
* # Comment #
* ###########
*/ - BLOCKED, + BLOCKED(true, false, " ", " "), /** * #############
* #|¯¯¯¯¯¯¯¯¯|#
@@ -32,6 +32,38 @@ public class ConfigFormattingRules { * #|_________|#
* #############
*/ - BLOCKSPACED + BLOCKSPACED(true, true, "|¯", '¯', "¯|", "| ", " |", "|_", '_', "_|"); + + final boolean drawBorder, drawSpace; + final String commentPrefix, spacePrefixTop, spacePrefixBottom; + final String commentSuffix, spaceSuffixTop, spaceSuffixBottom; + final char spaceCharTop, spaceCharBottom; + + private CommentStyle(boolean drawBorder, boolean drawSpace, + String spacePrefixTop, char spaceCharTop, String spaceSuffixTop, + String commentPrefix, String commentSuffix, + String spacePrefixBottom, char spaceCharBottom, String spaceSuffixBottom) { + this.drawBorder = drawBorder; + this.drawSpace = drawSpace; + this.commentPrefix = commentPrefix; + this.spacePrefixTop = spacePrefixTop; + this.spacePrefixBottom = spacePrefixBottom; + this.commentSuffix = commentSuffix; + this.spaceSuffixTop = spaceSuffixTop; + this.spaceSuffixBottom = spaceSuffixBottom; + this.spaceCharTop = spaceCharTop; + this.spaceCharBottom = spaceCharBottom; + } + + private CommentStyle(boolean drawBorder, boolean drawSpace, String commentPrefix, String commentSuffix) { + this.drawBorder = drawBorder; + this.drawSpace = drawSpace; + this.commentPrefix = commentPrefix; + this.commentSuffix = commentSuffix; + this.spacePrefixTop = this.spacePrefixBottom = ""; + this.spaceCharTop = this.spaceCharBottom = ' '; + this.spaceSuffixTop = this.spaceSuffixBottom = ""; + } + } } diff --git a/src/main/java/com/songoda/core/settingsv2/adapters/ConfigAdapter.java b/src/main/java/com/songoda/core/settingsv2/adapters/ConfigAdapter.java new file mode 100644 index 00000000..2d557f42 --- /dev/null +++ b/src/main/java/com/songoda/core/settingsv2/adapters/ConfigAdapter.java @@ -0,0 +1,66 @@ +package com.songoda.core.settingsv2.adapters; + +import com.songoda.core.settingsv2.Config; +import java.util.List; +import org.bukkit.configuration.file.YamlConfigurationOptions; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ConfigAdapter extends YamlConfigurationOptions { + + public ConfigAdapter(Config configuration) { + super(configuration); + } + + @NotNull + @Override + public Config configuration() { + return (Config) super.configuration(); + } + + @NotNull + @Override + public YamlConfigurationOptions copyDefaults(boolean value) { + // we always copy new values + return this; + } + + @NotNull + @Override + public YamlConfigurationOptions pathSeparator(char value) { + ((Config) super.configuration()).setPathSeparator(value); + return this; + } + + @NotNull + @Override + public YamlConfigurationOptions header(@Nullable String value) { + if (value == null) { + ((Config) super.configuration()).setHeader((List) null); + } else { + ((Config) super.configuration()).setHeader(value.split("\n")); + } + return this; + } + + @NotNull + @Override + public YamlConfigurationOptions copyHeader(boolean value) { + if (!value) { + ((Config) super.configuration()).setHeader((List) null); + } + return this; + } + + @Override + public int indent() { + return ((Config) super.configuration()).getIndent(); + } + + @NotNull + @Override + public YamlConfigurationOptions indent(int value) { + ((Config) super.configuration()).setIndent(value); + return this; + } +}