mirror of
https://github.com/songoda/SongodaCore.git
synced 2024-11-23 18:45:34 +01:00
add comment system to new config
This commit is contained in:
parent
7c3936cdf8
commit
167e8c0faf
@ -29,6 +29,16 @@ public class Comment {
|
||||
this.lines.addAll(lines);
|
||||
}
|
||||
|
||||
public Comment(CommentStyle commentStyle, String... lines) {
|
||||
this.commentStyle = commentStyle;
|
||||
this.lines.addAll(Arrays.asList(lines));
|
||||
}
|
||||
|
||||
public Comment(CommentStyle commentStyle, List<String> lines) {
|
||||
this.commentStyle = commentStyle;
|
||||
this.lines.addAll(lines);
|
||||
}
|
||||
|
||||
public CommentStyle getCommentStyle() {
|
||||
return commentStyle;
|
||||
}
|
||||
|
@ -12,15 +12,21 @@ import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConstructor;
|
||||
@ -61,6 +67,7 @@ public class Config extends SongodaConfigurationSection {
|
||||
final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions);
|
||||
SaveTask saveTask;
|
||||
Timer autosaveTimer;
|
||||
////////////// Config settings ////////////////
|
||||
/**
|
||||
* save file whenever a change is made
|
||||
*/
|
||||
@ -73,6 +80,28 @@ public class Config extends SongodaConfigurationSection {
|
||||
* remove nodes not defined in defaults
|
||||
*/
|
||||
boolean autoremove = false;
|
||||
/**
|
||||
* load comments when loading the file
|
||||
* TODO
|
||||
*/
|
||||
boolean loadComments = false;
|
||||
/**
|
||||
* Default comment applied to config nodes
|
||||
*/
|
||||
ConfigFormattingRules.CommentStyle defaultNodeCommentFormat = ConfigFormattingRules.CommentStyle.SIMPLE;
|
||||
/**
|
||||
* Default comment applied to section nodes
|
||||
*/
|
||||
ConfigFormattingRules.CommentStyle defaultSectionCommentFormat = ConfigFormattingRules.CommentStyle.SPACED;
|
||||
/**
|
||||
* Extra lines to put between root nodes
|
||||
*/
|
||||
int rootNodeSpacing = 1;
|
||||
/**
|
||||
* Extra lines to put in front of comments. <br>
|
||||
* This is separate from rootNodeSpacing, if applicable.
|
||||
*/
|
||||
int commentSpacing = 1;
|
||||
|
||||
public Config(@NotNull File file) {
|
||||
this.plugin = null;
|
||||
@ -109,6 +138,7 @@ public class Config extends SongodaConfigurationSection {
|
||||
* @param autosave set to true if autosaving is enabled.
|
||||
* @return this class
|
||||
*/
|
||||
@NotNull
|
||||
public Config setAutosave(boolean autosave) {
|
||||
this.autosave = autosave;
|
||||
return this;
|
||||
@ -135,17 +165,76 @@ public class Config extends SongodaConfigurationSection {
|
||||
/**
|
||||
* This setting is used to prevent users to from adding extraneous settings
|
||||
* to the config and to remove deprecated settings. <br>
|
||||
* If this is enabled, the config will delete any nodes that are not
|
||||
* defined as a default setting.
|
||||
* If this is enabled, the config will delete any nodes that are not defined
|
||||
* as a default setting.
|
||||
*
|
||||
* @param autoremove Remove settings that don't exist as defaults
|
||||
* @return this class
|
||||
*/
|
||||
@NotNull
|
||||
public Config setAutoremove(boolean autoremove) {
|
||||
this.autoremove = autoremove;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default comment applied to config nodes
|
||||
*/
|
||||
public ConfigFormattingRules.CommentStyle getDefaultNodeCommentFormat() {
|
||||
return defaultNodeCommentFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default comment applied to config nodes
|
||||
*/
|
||||
public void setDefaultNodeCommentFormat(ConfigFormattingRules.CommentStyle defaultNodeCommentFormat) {
|
||||
this.defaultNodeCommentFormat = defaultNodeCommentFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default comment applied to section nodes
|
||||
*/
|
||||
public ConfigFormattingRules.CommentStyle getDefaultSectionCommentFormat() {
|
||||
return defaultSectionCommentFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default comment applied to section nodes
|
||||
*/
|
||||
public void setDefaultSectionCommentFormat(ConfigFormattingRules.CommentStyle defaultSectionCommentFormat) {
|
||||
this.defaultSectionCommentFormat = defaultSectionCommentFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra lines to put between root nodes
|
||||
*/
|
||||
public int getRootNodeSpacing() {
|
||||
return rootNodeSpacing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra lines to put between root nodes
|
||||
*/
|
||||
public void setRootNodeSpacing(int rootNodeSpacing) {
|
||||
this.rootNodeSpacing = rootNodeSpacing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra lines to put in front of comments. <br>
|
||||
* This is separate from rootNodeSpacing, if applicable.
|
||||
*/
|
||||
public int getCommentSpacing() {
|
||||
return commentSpacing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra lines to put in front of comments. <br>
|
||||
* This is separate from rootNodeSpacing, if applicable.
|
||||
*/
|
||||
public void setCommentSpacing(int commentSpacing) {
|
||||
this.commentSpacing = commentSpacing;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Config setHeader(@NotNull String... description) {
|
||||
if (description.length == 0) {
|
||||
@ -156,6 +245,16 @@ public class Config extends SongodaConfigurationSection {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Config setHeader(@Nullable ConfigFormattingRules.CommentStyle commentStyle, @NotNull String... description) {
|
||||
if (description.length == 0) {
|
||||
configComments.remove(null);
|
||||
} else {
|
||||
configComments.put(null, new Comment(commentStyle, description));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Config setHeader(@Nullable List<String> description) {
|
||||
if (description == null || description.isEmpty()) {
|
||||
@ -166,6 +265,16 @@ public class Config extends SongodaConfigurationSection {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Config setHeader(@Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> description) {
|
||||
if (description == null || description.isEmpty()) {
|
||||
configComments.remove(null);
|
||||
} else {
|
||||
configComments.put(null, new Comment(commentStyle, description));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> getHeader() {
|
||||
if (configComments.containsKey(null)) {
|
||||
@ -208,7 +317,9 @@ public class Config extends SongodaConfigurationSection {
|
||||
throw new InvalidConfigurationException("Top level is not a Map.");
|
||||
}
|
||||
if (input != null) {
|
||||
this.parseComments(contents, input);
|
||||
if(loadComments) {
|
||||
this.parseComments(contents, input);
|
||||
}
|
||||
this.convertMapsToSections(input, this);
|
||||
}
|
||||
}
|
||||
@ -226,9 +337,10 @@ public class Config extends SongodaConfigurationSection {
|
||||
}
|
||||
|
||||
protected void parseComments(@NotNull String contents, @NotNull Map<?, ?> input) {
|
||||
// TODO
|
||||
// TODO?
|
||||
// if starts with a comment, load all nonbreaking comments as a header
|
||||
// then load all comments and assign to the next valid node loaded
|
||||
// (Only load comments that are on their own line)
|
||||
}
|
||||
|
||||
public void deleteNonDefaultSettings() {
|
||||
@ -272,6 +384,13 @@ public class Config extends SongodaConfigurationSection {
|
||||
}
|
||||
|
||||
public boolean save() {
|
||||
if(saveTask != null) {
|
||||
//Close Threads
|
||||
saveTask.cancel();
|
||||
autosaveTimer.cancel();
|
||||
saveTask = null;
|
||||
autosaveTimer = null;
|
||||
}
|
||||
return save(file);
|
||||
}
|
||||
|
||||
@ -307,14 +426,13 @@ public class Config extends SongodaConfigurationSection {
|
||||
Comment header = configComments.get(null);
|
||||
if (header != null) {
|
||||
header.writeComment(str, 0, ConfigFormattingRules.CommentStyle.SPACED);
|
||||
str.write("\n"); // add one space after the header
|
||||
}
|
||||
String dump = yaml.dump(this.getValues(false));
|
||||
if (dump.equals(BLANK_CONFIG)) {
|
||||
dump = "";
|
||||
} else {
|
||||
// line-by-line apply line spacing formatting and comments per-node
|
||||
if (!dump.equals(BLANK_CONFIG)) {
|
||||
writeComments(dump, str);
|
||||
}
|
||||
return str.toString() + dump;
|
||||
return str.toString();
|
||||
} catch (Throwable ex) {
|
||||
Logger.getLogger(Config.class.getName()).log(Level.SEVERE, "Error saving config", ex);
|
||||
delaySave();
|
||||
@ -322,6 +440,96 @@ public class Config extends SongodaConfigurationSection {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected final Pattern yamlNode = Pattern.compile("^( *)([^:\\{\\}\\[\\],&\\*#\\?\\|\\-<>=!%@`]+):(.*)$");
|
||||
|
||||
protected void writeComments(String data, Writer out) throws IOException {
|
||||
// line-by-line apply line spacing formatting and comments per-node
|
||||
BufferedReader in = new BufferedReader(new StringReader(data));
|
||||
String line;
|
||||
boolean insideScalar = false;
|
||||
boolean firstNode = true;
|
||||
int index = 0;
|
||||
LinkedList<String> currentPath = new LinkedList();
|
||||
while ((line = in.readLine()) != null) {
|
||||
// ignore comments and empty lines (there shouldn't be any, but just in case)
|
||||
if (line.trim().startsWith("#") || line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check to see if this is a line that we can process
|
||||
int lineOffset = getOffset(line);
|
||||
insideScalar &= lineOffset <= index;
|
||||
Matcher m;
|
||||
if (!insideScalar && (m = yamlNode.matcher(line)).find()) {
|
||||
// we found a config node! ^.^
|
||||
// check to see what the full path is
|
||||
int depth = (m.group(1).length() / indentation);
|
||||
while (depth < currentPath.size()) {
|
||||
currentPath.removeLast();
|
||||
}
|
||||
currentPath.add(m.group(2));
|
||||
String path = currentPath.stream().collect(Collectors.joining(String.valueOf(pathChar)));
|
||||
|
||||
// if this is a root-level node, apply extra spacing if we aren't the first node
|
||||
if (!firstNode && depth == 0 && rootNodeSpacing > 0) {
|
||||
out.write((new String(new char[rootNodeSpacing])).replace("\0", "\n")); // yes it's silly, but it works :>
|
||||
}
|
||||
firstNode = false; // we're no longer on the first node
|
||||
|
||||
// insert the relavant comment
|
||||
Comment comment = getComment(path);
|
||||
if (comment != null) {
|
||||
// add spacing between previous nodes and comments
|
||||
if (depth != 0) {
|
||||
out.write((new String(new char[commentSpacing])).replace("\0", "\n"));
|
||||
}
|
||||
|
||||
// formatting style for this node
|
||||
ConfigFormattingRules.CommentStyle style = comment.getCommentStyle();
|
||||
if (style == null) {
|
||||
// check to see what type of node this is
|
||||
if (!m.group(3).trim().isEmpty()) {
|
||||
// setting node
|
||||
style = defaultNodeCommentFormat;
|
||||
} else {
|
||||
// probably a section? (need to peek ahead to check if this is a list)
|
||||
in.mark(1000);
|
||||
String nextLine = in.readLine().trim();
|
||||
in.reset();
|
||||
if (nextLine.startsWith("-")) {
|
||||
// not a section :P
|
||||
style = defaultNodeCommentFormat;
|
||||
} else {
|
||||
style = defaultSectionCommentFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write it down!
|
||||
comment.writeComment(out, lineOffset, style);
|
||||
}
|
||||
// ignore scalars
|
||||
index = lineOffset;
|
||||
if (m.group(3).trim().equals("|") || m.group(3).trim().equals(">")) {
|
||||
insideScalar = true;
|
||||
}
|
||||
}
|
||||
|
||||
out.write(line);
|
||||
out.write("\n");
|
||||
}
|
||||
}
|
||||
|
||||
protected static int getOffset(String s) {
|
||||
char[] chars = s.toCharArray();
|
||||
for (int i = 0; i < chars.length; ++i) {
|
||||
if (chars[i] != ' ') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
class SaveTask extends TimerTask {
|
||||
|
||||
@Override
|
||||
|
@ -2,6 +2,7 @@ package com.songoda.core.settingsv2;
|
||||
|
||||
import com.songoda.core.settingsv2.adapters.ConfigDefaultsAdapter;
|
||||
import com.songoda.core.settingsv2.adapters.ConfigOptionsAdapter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
@ -29,31 +30,33 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
protected int indentation = 2; // between 2 and 9 (inclusive)
|
||||
protected char pathChar = '.';
|
||||
final HashMap<String, Comment> configComments;
|
||||
final HashMap<String, Class> strictKeys;
|
||||
final HashMap<String, Comment> defaultComments;
|
||||
final LinkedHashMap<String, Object> defaults;
|
||||
final LinkedHashMap<String, Object> values;
|
||||
/**
|
||||
* Internal root state: if any configuration value has changed from file state
|
||||
*/
|
||||
boolean changed = false;
|
||||
final boolean isDefault;
|
||||
final Object lock = new Object();
|
||||
|
||||
SongodaConfigurationSection() {
|
||||
this.root = this;
|
||||
this.parent = null;
|
||||
isDefault = false;
|
||||
fullPath = "";
|
||||
configComments = new HashMap();
|
||||
strictKeys = new HashMap();
|
||||
defaultComments = new HashMap();
|
||||
defaults = new LinkedHashMap();
|
||||
values = new LinkedHashMap();
|
||||
}
|
||||
|
||||
SongodaConfigurationSection(SongodaConfigurationSection root, SongodaConfigurationSection parent, String path) {
|
||||
SongodaConfigurationSection(SongodaConfigurationSection root, SongodaConfigurationSection parent, String path, boolean isDefault) {
|
||||
this.root = root;
|
||||
this.parent = parent;
|
||||
fullPath = parent.fullPath + path + root.pathChar;
|
||||
configComments = null;
|
||||
strictKeys = null;
|
||||
this.fullPath = parent.fullPath + path + root.pathChar;
|
||||
this.isDefault = isDefault;
|
||||
configComments = defaultComments = null;
|
||||
defaults = null;
|
||||
values = null;
|
||||
}
|
||||
@ -66,12 +69,8 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
root.indentation = indentation;
|
||||
}
|
||||
|
||||
public char getPathSeparator() {
|
||||
return root.pathChar;
|
||||
}
|
||||
|
||||
protected void onChange() {
|
||||
if(parent != null) {
|
||||
if (parent != null) {
|
||||
root.onChange();
|
||||
}
|
||||
}
|
||||
@ -83,18 +82,75 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
* @param pathChar character to use
|
||||
*/
|
||||
public void setPathSeparator(char pathChar) {
|
||||
if(!root.values.isEmpty() || !root.defaults.isEmpty())
|
||||
if (!root.values.isEmpty() || !root.defaults.isEmpty())
|
||||
throw new RuntimeException("Path change after config initialization");
|
||||
root.pathChar = pathChar;
|
||||
}
|
||||
|
||||
public char getPathSeparator() {
|
||||
return root.pathChar;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection createDefaultSection(@NotNull String path) {
|
||||
SongodaConfigurationSection section = new SongodaConfigurationSection(root, this, path, true);
|
||||
synchronized (root.lock) {
|
||||
root.defaults.put(fullPath + path, section);
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection createDefaultSection(@NotNull String path, String... comment) {
|
||||
SongodaConfigurationSection section = new SongodaConfigurationSection(root, this, path, true);
|
||||
synchronized (root.lock) {
|
||||
root.defaults.put(fullPath + path, section);
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... lines) {
|
||||
return setComment(path, commentStyle, lines.length == 0 ? (List) null : Arrays.asList(lines));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> lines) {
|
||||
synchronized (root.lock) {
|
||||
if (isDefault) {
|
||||
root.defaultComments.put(fullPath + path, lines != null ? new Comment(commentStyle, lines) : null);
|
||||
} else {
|
||||
root.configComments.put(fullPath + path, lines != null ? new Comment(commentStyle, lines) : null);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection setDefaultComment(@NotNull String path, String... lines) {
|
||||
return setDefaultComment(path, lines.length == 0 ? (List) null : Arrays.asList(lines));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection setDefaultComment(@NotNull String path, @Nullable List<String> lines) {
|
||||
synchronized (root.lock) {
|
||||
root.defaultComments.put(fullPath + path, new Comment(lines));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Comment getComment(@NotNull String path) {
|
||||
Comment result = root.configComments.get(fullPath + path);
|
||||
if (result == null) {
|
||||
result = root.defaultComments.get(fullPath + path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDefault(@NotNull String path, @Nullable Object value) {
|
||||
root.defaults.put(fullPath + path, value);
|
||||
if(!root.changed) {
|
||||
root.changed = root.values.get(fullPath + path) == null;
|
||||
}
|
||||
onChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,7 +160,7 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
|
||||
@Override
|
||||
public void setDefaults(Configuration c) {
|
||||
if(fullPath.isEmpty()) {
|
||||
if (fullPath.isEmpty()) {
|
||||
root.defaults.clear();
|
||||
} else {
|
||||
root.defaults.keySet().stream()
|
||||
@ -135,23 +191,23 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
LinkedHashSet<String> result = new LinkedHashSet();
|
||||
int pathIndex = fullPath.lastIndexOf(root.pathChar);
|
||||
if (deep) {
|
||||
result.addAll(root.values.keySet().stream()
|
||||
result.addAll(root.defaults.keySet().stream()
|
||||
.filter(k -> k.startsWith(fullPath))
|
||||
.map(k -> !k.endsWith(String.valueOf(root.pathChar)) ? k.substring(pathIndex + 1) : k.substring(pathIndex + 1, k.length() - 1))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new)));
|
||||
result.addAll(root.defaults.keySet().stream()
|
||||
result.addAll(root.values.keySet().stream()
|
||||
.filter(k -> k.startsWith(fullPath))
|
||||
.map(k -> !k.endsWith(String.valueOf(root.pathChar)) ? k.substring(pathIndex + 1) : k.substring(pathIndex + 1, k.length() - 1))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new)));
|
||||
} else {
|
||||
result.addAll(root.values.keySet().stream()
|
||||
.filter(k -> k.startsWith(fullPath) && k.lastIndexOf(root.pathChar) == pathIndex)
|
||||
.map(k -> !k.endsWith(String.valueOf(root.pathChar)) ? k.substring(pathIndex + 1) : k.substring(pathIndex + 1, k.length() - 1))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new)));
|
||||
result.addAll(root.defaults.keySet().stream()
|
||||
.filter(k -> k.startsWith(fullPath) && k.lastIndexOf(root.pathChar) == pathIndex + 1)
|
||||
.map(k -> !k.endsWith(String.valueOf(root.pathChar)) ? k.substring(pathIndex + 1) : k.substring(pathIndex + 1, k.length() - 1))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new)));
|
||||
result.addAll(root.values.keySet().stream()
|
||||
.filter(k -> k.startsWith(fullPath) && k.lastIndexOf(root.pathChar) == pathIndex)
|
||||
.map(k -> !k.endsWith(String.valueOf(root.pathChar)) ? k.substring(pathIndex + 1) : k.substring(pathIndex + 1, k.length() - 1))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -177,14 +233,14 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
(v1, v2) -> { throw new IllegalStateException(); }, // never going to be merging keys
|
||||
LinkedHashMap::new)));
|
||||
} else {
|
||||
result.putAll((Map<String, Object>) root.values.entrySet().stream()
|
||||
result.putAll((Map<String, Object>) root.defaults.entrySet().stream()
|
||||
.filter(k -> k.getKey().startsWith(fullPath) && k.getKey().lastIndexOf(root.pathChar) == pathIndex)
|
||||
.collect(Collectors.toMap(
|
||||
e -> !e.getKey().endsWith(String.valueOf(root.pathChar)) ? e.getKey().substring(pathIndex + 1) : e.getKey().substring(pathIndex + 1, e.getKey().length() - 1),
|
||||
e -> e.getValue(),
|
||||
(v1, v2) -> { throw new IllegalStateException(); }, // never going to be merging keys
|
||||
LinkedHashMap::new)));
|
||||
result.putAll((Map<String, Object>) root.defaults.entrySet().stream()
|
||||
result.putAll((Map<String, Object>) root.values.entrySet().stream()
|
||||
.filter(k -> k.getKey().startsWith(fullPath) && k.getKey().lastIndexOf(root.pathChar) == pathIndex)
|
||||
.collect(Collectors.toMap(
|
||||
e -> !e.getKey().endsWith(String.valueOf(root.pathChar)) ? e.getKey().substring(pathIndex + 1) : e.getKey().substring(pathIndex + 1, e.getKey().length() - 1),
|
||||
@ -217,7 +273,7 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
if(fullPath.isEmpty())
|
||||
if (fullPath.isEmpty())
|
||||
return "";
|
||||
String[] parts = fullPath.split(Pattern.quote(String.valueOf(root.pathChar)));
|
||||
return parts[parts.length - 1];
|
||||
@ -252,20 +308,66 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
|
||||
@Override
|
||||
public void set(@NotNull String path, @Nullable Object value) {
|
||||
synchronized(root.lock) {
|
||||
if (value != null) {
|
||||
root.changed |= root.values.put(fullPath + path, value) != value;
|
||||
} else {
|
||||
root.changed |= root.values.remove(fullPath + path) != null;
|
||||
if (isDefault) {
|
||||
root.defaults.put(fullPath + path, value);
|
||||
} else {
|
||||
synchronized (root.lock) {
|
||||
if (value != null) {
|
||||
root.changed |= root.values.put(fullPath + path, value) != value;
|
||||
} else {
|
||||
root.changed |= root.values.remove(fullPath + path) != null;
|
||||
}
|
||||
}
|
||||
onChange();
|
||||
}
|
||||
onChange();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection set(@NotNull String path, @Nullable Object value, String ... comment) {
|
||||
set(path, value);
|
||||
return setComment(path, null, comment);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection set(@NotNull String path, @Nullable Object value, List<String> comment) {
|
||||
set(path, value);
|
||||
return setComment(path, null, comment);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String ... comment) {
|
||||
set(path, value);
|
||||
return setComment(path, commentStyle, comment);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, List<String> comment) {
|
||||
set(path, value);
|
||||
return setComment(path, commentStyle, comment);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection setDefault(@NotNull String path, @Nullable Object value) {
|
||||
addDefault(path, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection setDefault(@NotNull String path, @Nullable Object value, String ... comment) {
|
||||
addDefault(path, value);
|
||||
return setDefaultComment(path, comment);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection setDefault(@NotNull String path, @Nullable Object value, List<String> comment) {
|
||||
addDefault(path, value);
|
||||
return setDefaultComment(path, comment);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SongodaConfigurationSection createSection(@NotNull String path) {
|
||||
SongodaConfigurationSection section = new SongodaConfigurationSection(root, this, path);
|
||||
SongodaConfigurationSection section = new SongodaConfigurationSection(root, this, path, false);
|
||||
synchronized(root.lock) {
|
||||
root.values.put(fullPath + path, section);
|
||||
}
|
||||
@ -274,11 +376,38 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
return section;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection createSection(@NotNull String path, String... comment) {
|
||||
return createSection(path, null, comment.length == 0 ? (List) null : Arrays.asList(comment));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection createSection(@NotNull String path, @Nullable List<String> comment) {
|
||||
return createSection(path, null, comment);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
|
||||
return createSection(path, commentStyle, comment.length == 0 ? (List) null : Arrays.asList(comment));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SongodaConfigurationSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> comment) {
|
||||
SongodaConfigurationSection section = new SongodaConfigurationSection(root, this, path, false);
|
||||
synchronized (root.lock) {
|
||||
root.values.put(fullPath + path, section);
|
||||
}
|
||||
setComment(path, commentStyle, comment);
|
||||
root.changed = true;
|
||||
onChange();
|
||||
return section;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SongodaConfigurationSection createSection(@NotNull String path, Map<?, ?> map) {
|
||||
SongodaConfigurationSection section = new SongodaConfigurationSection(root, this, path);
|
||||
synchronized(root.lock) {
|
||||
SongodaConfigurationSection section = new SongodaConfigurationSection(root, this, path, false);
|
||||
synchronized (root.lock) {
|
||||
root.values.put(fullPath + path, section);
|
||||
}
|
||||
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
||||
@ -388,4 +517,9 @@ public class SongodaConfigurationSection extends MemoryConfiguration {
|
||||
Object result = get(path);
|
||||
return result instanceof SongodaConfigurationSection ? (SongodaConfigurationSection) result : null;
|
||||
}
|
||||
|
||||
public SongodaConfigurationSection getOrCreateConfigurationSection(@NotNull String path) {
|
||||
Object result = get(path);
|
||||
return result instanceof SongodaConfigurationSection ? (SongodaConfigurationSection) result : createSection(path);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user