mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-11-05 02:09:50 +01:00
Fixed to ConfigNode
- Removed some deprecated code usages - Removed deprecated code from ConfigNode - Fixed ConfigNode#addNode - ConfigNode#addNode and #addChild now returns the added node - If ConfigNode is root #remove now throws exception - Fixed ConfigNode#moveChild not copying values - Added ConfigNode#copyAll - Fixed ConfigNode#getKey(true) returning null.actual.key - ConfigNode#set(ConfigNode) now overrides values of the node being set. - Added ConfigNode#isLeafNode for when the node is a leaf node - Lots and lots of tests for ConfigNode Still broken because ConfigReader has a bug in it.
This commit is contained in:
parent
9879d9a499
commit
81218c968f
@ -40,12 +40,12 @@ public class PluginsConfigSection {
|
||||
public boolean hasSection(PluginData dataSource) {
|
||||
ConfigNode section = getPluginsSection();
|
||||
String pluginName = dataSource.getSourcePlugin();
|
||||
return section.getChildren().containsKey(pluginName)
|
||||
&& section.getConfigNode(pluginName).getChildren().containsKey("Enabled");
|
||||
return section.getNode(pluginName + ".Enabled").isPresent();
|
||||
}
|
||||
|
||||
private ConfigNode getPluginsSection() {
|
||||
return config.getConfigNode("Plugins");
|
||||
return config.getNode("Plugins")
|
||||
.orElse(config.addNode("Plugins"));
|
||||
}
|
||||
|
||||
public void createSection(PluginData dataSource) throws IOException {
|
||||
|
@ -99,6 +99,10 @@ public class PlanFiles implements SubSystem {
|
||||
return FileUtil.lines(plugin, fileName);
|
||||
}
|
||||
|
||||
public InputStream readStreamFromResource(String fileName) throws IOException {
|
||||
return plugin.getResource(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a file from jar as a flat String.
|
||||
*
|
||||
|
@ -18,6 +18,7 @@ package com.djrapitops.plan.system.info.server;
|
||||
|
||||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
import com.djrapitops.plan.system.settings.config.Config;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigReader;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -44,7 +45,9 @@ public class ServerInfoFile extends Config {
|
||||
}
|
||||
|
||||
public void prepare() throws IOException {
|
||||
copyDefaults(files.readFromResource("DefaultServerInfoFile.yml"));
|
||||
try (ConfigReader reader = new ConfigReader(files.readStreamFromResource("DefaultServerInfoFile.yml"))) {
|
||||
copyMissing(reader.read());
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ package com.djrapitops.plan.system.settings;
|
||||
|
||||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
import com.djrapitops.plan.system.settings.changes.ConfigUpdater;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigReader;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.system.settings.theme.Theme;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
@ -55,6 +56,8 @@ public class BukkitConfigSystem extends ConfigSystem {
|
||||
@Override
|
||||
protected void copyDefaults() throws IOException {
|
||||
configUpdater.applyConfigUpdate(config);
|
||||
config.copyDefaults(files.readFromResource("config.yml"));
|
||||
try (ConfigReader reader = new ConfigReader(files.readStreamFromResource("config.yml"))) {
|
||||
config.copyMissing(reader.read());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package com.djrapitops.plan.system.settings;
|
||||
|
||||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
import com.djrapitops.plan.system.settings.changes.ConfigUpdater;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigReader;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.system.settings.theme.Theme;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
@ -55,6 +56,8 @@ public class ProxyConfigSystem extends ConfigSystem {
|
||||
@Override
|
||||
protected void copyDefaults() throws IOException {
|
||||
configUpdater.applyConfigUpdate(config);
|
||||
config.copyDefaults(files.readFromResource("bungeeconfig.yml"));
|
||||
try (ConfigReader reader = new ConfigReader(files.readStreamFromResource("bungeeconfig.yml"))) {
|
||||
config.copyMissing(reader.read());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
package com.djrapitops.plan.system.settings.changes;
|
||||
|
||||
import com.djrapitops.plan.system.settings.config.Config;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigNode;
|
||||
|
||||
/**
|
||||
* Represents a change made to the config structure.
|
||||
@ -43,7 +42,9 @@ public interface ConfigChange {
|
||||
|
||||
@Override
|
||||
public void apply(Config config) {
|
||||
config.moveChild(oldPath, newPath);
|
||||
if (!config.moveChild(oldPath, newPath)) {
|
||||
throw new IllegalStateException("Failed to move config node from '" + oldPath + "' to '" + newPath + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -63,10 +64,7 @@ public interface ConfigChange {
|
||||
|
||||
@Override
|
||||
public void apply(Config config) {
|
||||
ConfigNode newNode = config.getConfigNode(newPath);
|
||||
ConfigNode oldNode = config.getConfigNode(oldPath);
|
||||
newNode.copyMissing(oldNode);
|
||||
newNode.set(oldNode.getString());
|
||||
config.getNode(oldPath).ifPresent(oldNode -> config.addNode(newPath).copyAll(oldNode));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -84,12 +82,14 @@ public interface ConfigChange {
|
||||
|
||||
@Override
|
||||
public boolean hasBeenApplied(Config config) {
|
||||
return !config.contains(oldPath);
|
||||
return !config.getNode(oldPath).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void apply(Config config) {
|
||||
config.removeNode(oldPath);
|
||||
if (!config.removeNode(oldPath)) {
|
||||
throw new IllegalStateException("Failed to remove config node from '" + oldPath + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -97,5 +97,4 @@ public interface ConfigChange {
|
||||
return "Removed " + oldPath;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,14 +24,12 @@
|
||||
package com.djrapitops.plan.system.settings.config;
|
||||
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
import org.apache.commons.text.TextStringBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Configuration utility for storing settings in a .yml file.
|
||||
@ -62,11 +60,6 @@ public class Config extends ConfigNode {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Config(File configFile, Iterable<String> defaults) {
|
||||
this(configFile, new ConfigReader(new Scanner(new TextStringBuilder().appendWithSeparators(defaults, "\n").toString())).readAndClose());
|
||||
}
|
||||
|
||||
public Config(File configFile, ConfigNode defaults) {
|
||||
this(configFile);
|
||||
copyMissing(defaults);
|
||||
|
@ -23,8 +23,6 @@
|
||||
*/
|
||||
package com.djrapitops.plan.system.settings.config;
|
||||
|
||||
import org.apache.commons.text.TextStringBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
@ -81,29 +79,26 @@ public class ConfigNode {
|
||||
return split;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ConfigNode getConfigNode(String path) {
|
||||
return getNode(path).orElse(null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean contains(String path) {
|
||||
return getNode(path).isPresent();
|
||||
}
|
||||
|
||||
protected void addNode(String path) {
|
||||
public ConfigNode addNode(String path) {
|
||||
ConfigNode newParent = this;
|
||||
if (!path.isEmpty()) {
|
||||
String[] parts = splitPathInTwo(path);
|
||||
String key = parts[0];
|
||||
String leftover = parts[1];
|
||||
|
||||
ConfigNode child;
|
||||
if (!childNodes.containsKey(key)) {
|
||||
addChild(new ConfigNode(key, newParent, null));
|
||||
child = addChild(new ConfigNode(key, newParent, null));
|
||||
} else {
|
||||
child = childNodes.get(key);
|
||||
}
|
||||
ConfigNode child = childNodes.get(key);
|
||||
child.addNode(leftover);
|
||||
return leftover.isEmpty() ? child : child.addNode(leftover);
|
||||
}
|
||||
throw new IllegalArgumentException("Can not add a node with empty path");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,16 +114,20 @@ public class ConfigNode {
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if (parent == null) {
|
||||
throw new IllegalStateException("Can not remove root node from a tree.");
|
||||
}
|
||||
parent.childNodes.remove(key);
|
||||
parent.nodeOrder.remove(key);
|
||||
updateParent(null);
|
||||
}
|
||||
|
||||
protected void addChild(ConfigNode child) {
|
||||
protected ConfigNode addChild(ConfigNode child) {
|
||||
getNode(child.key).ifPresent(ConfigNode::remove);
|
||||
childNodes.put(child.key, child);
|
||||
nodeOrder.add(child.key);
|
||||
child.updateParent(this);
|
||||
return child;
|
||||
}
|
||||
|
||||
protected void removeChild(ConfigNode child) {
|
||||
@ -148,21 +147,22 @@ public class ConfigNode {
|
||||
return false;
|
||||
}
|
||||
|
||||
addNode(newPath);
|
||||
|
||||
ConfigNode moveFrom = found.get();
|
||||
ConfigNode moveTo = getNode(newPath).orElseThrow(() -> new IllegalStateException("Config node was not added properly: " + newPath));
|
||||
|
||||
ConfigNode moveTo = addNode(newPath);
|
||||
ConfigNode oldParent = moveFrom.parent;
|
||||
ConfigNode newParent = moveTo.parent;
|
||||
|
||||
oldParent.removeChild(moveFrom);
|
||||
moveTo.copyAll(moveFrom);
|
||||
newParent.addChild(moveTo);
|
||||
|
||||
return getNode(newPath).isPresent();
|
||||
}
|
||||
|
||||
public String getKey(boolean deep) {
|
||||
if (deep && parent != null) {
|
||||
String deepKey = parent.getKey(true) + "." + key;
|
||||
if (deep) {
|
||||
String deepKey = parent != null ? parent.getKey(true) + "." + key : "";
|
||||
if (deepKey.startsWith(".")) {
|
||||
return deepKey.substring(1);
|
||||
}
|
||||
@ -197,14 +197,12 @@ public class ConfigNode {
|
||||
}
|
||||
|
||||
public <T> void set(String path, T value) {
|
||||
addNode(path);
|
||||
ConfigNode node = getNode(path).orElseThrow(() -> new IllegalStateException("Config node was not added properly: " + path));
|
||||
node.set(value);
|
||||
addNode(path).set(value);
|
||||
}
|
||||
|
||||
public <T> void set(T value) {
|
||||
if (value instanceof ConfigNode) {
|
||||
addChild(((ConfigNode) value));
|
||||
copyAll((ConfigNode) value);
|
||||
} else {
|
||||
ConfigValueParser<T> parser = ConfigValueParser.getParserFor(value.getClass());
|
||||
this.value = parser.decompose(value);
|
||||
@ -220,24 +218,23 @@ public class ConfigNode {
|
||||
}
|
||||
|
||||
public List<String> getStringList() {
|
||||
return new ConfigValueParser.StringListParser().compose(value);
|
||||
return value == null ? Collections.emptyList()
|
||||
: new ConfigValueParser.StringListParser().compose(value);
|
||||
}
|
||||
|
||||
public Integer getInteger() {
|
||||
return new ConfigValueParser.IntegerParser().compose(value);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Integer getInt() {
|
||||
return getInteger();
|
||||
return value == null ? null
|
||||
: new ConfigValueParser.IntegerParser().compose(value);
|
||||
}
|
||||
|
||||
public Long getLong() {
|
||||
return new ConfigValueParser.LongParser().compose(value);
|
||||
return value == null ? null
|
||||
: new ConfigValueParser.LongParser().compose(value);
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return new ConfigValueParser.StringParser().compose(value);
|
||||
return value == null ? null
|
||||
: new ConfigValueParser.StringParser().compose(value);
|
||||
}
|
||||
|
||||
public boolean getBoolean() {
|
||||
@ -252,11 +249,6 @@ public class ConfigNode {
|
||||
return getNode(path).map(ConfigNode::getInteger).orElse(null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Integer getInt(String path) {
|
||||
return getInteger(path);
|
||||
}
|
||||
|
||||
public Long getLong(String path) {
|
||||
return getNode(path).map(ConfigNode::getLong).orElse(null);
|
||||
}
|
||||
@ -290,6 +282,20 @@ public class ConfigNode {
|
||||
}
|
||||
}
|
||||
|
||||
public void copyAll(ConfigNode from) {
|
||||
comment = from.comment;
|
||||
value = from.value;
|
||||
for (String key : from.nodeOrder) {
|
||||
ConfigNode newChild = from.childNodes.get(key);
|
||||
if (childNodes.containsKey(key)) {
|
||||
ConfigNode oldChild = childNodes.get(key);
|
||||
oldChild.copyAll(newChild);
|
||||
} else {
|
||||
addChild(newChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected int getNodeDepth() {
|
||||
return parent != null ? parent.getNodeDepth() + 1 : 0;
|
||||
}
|
||||
@ -303,21 +309,7 @@ public class ConfigNode {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void copyDefaults(ConfigNode from) {
|
||||
copyMissing(from);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void copyDefaults(List<String> from) throws IOException {
|
||||
Scanner linesScanner = new Scanner(new TextStringBuilder().appendWithSeparators(from, "\n").toString());
|
||||
try (ConfigReader reader = new ConfigReader(linesScanner)) {
|
||||
copyMissing(reader.read());
|
||||
}
|
||||
public boolean isLeafNode() {
|
||||
return nodeOrder.isEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,21 @@ public interface ConfigValueParser<T> {
|
||||
} else if (Integer.class.isAssignableFrom(type)) {
|
||||
return new IntegerParser();
|
||||
}
|
||||
return new StringParser();
|
||||
return toStringParser();
|
||||
}
|
||||
|
||||
static ConfigValueParser toStringParser() {
|
||||
return new ConfigValueParser() {
|
||||
@Override
|
||||
public Object compose(String fromValue) {
|
||||
return fromValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decompose(Object ofValue) {
|
||||
return ofValue.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,7 +93,7 @@ public class WorldAliasSettings {
|
||||
public void addWorld(String world) {
|
||||
ConfigNode aliasSect = getAliasSection();
|
||||
|
||||
String previousValue = aliasSect.getConfigNode(world).getValue();
|
||||
String previousValue = aliasSect.getString(world);
|
||||
if (Verify.isEmpty(previousValue)) {
|
||||
aliasSect.set(world, world);
|
||||
processing.submitNonCritical(() -> {
|
||||
|
@ -133,7 +133,7 @@ public class ServerSpecificSettings {
|
||||
|
||||
public Integer getInt(UUID serverUUID, Setting setting) {
|
||||
String path = getPath(serverUUID, setting);
|
||||
return config.get().getInt(path);
|
||||
return config.get().getInteger(path);
|
||||
}
|
||||
|
||||
public void set(UUID serverUUID, Setting setting, Object value) throws IOException {
|
||||
|
@ -32,7 +32,7 @@ public class DisplaySettings {
|
||||
public static final Setting<ConfigNode> WORLD_ALIASES = new Setting<ConfigNode>("World_aliases", ConfigNode.class) {
|
||||
@Override
|
||||
public ConfigNode getValueFrom(ConfigNode node) {
|
||||
return node.getConfigNode(path);
|
||||
return node.getNode(path).orElse(node.addNode(path));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -19,14 +19,13 @@ package com.djrapitops.plan.system.settings.theme;
|
||||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
import com.djrapitops.plan.system.settings.config.Config;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigNode;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigReader;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.system.settings.paths.DisplaySettings;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Config that keeps track of theme.yml.
|
||||
@ -39,27 +38,27 @@ public class ThemeConfig extends Config {
|
||||
this(getConfigFile(files), getDefaults(files, config, logger));
|
||||
}
|
||||
|
||||
private ThemeConfig(File configFile, List<String> defaults) {
|
||||
private ThemeConfig(File configFile, ConfigNode defaults) {
|
||||
super(configFile, defaults);
|
||||
|
||||
if (defaults.isEmpty()) {
|
||||
if (defaults.isLeafNode()) {
|
||||
ConfigNode util = new ConfigNode("", null, "");
|
||||
for (ThemeVal themeVal : ThemeVal.values()) {
|
||||
util.set(themeVal.getThemePath(), themeVal.getDefaultValue());
|
||||
}
|
||||
copyDefaults(util);
|
||||
copyMissing(util);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> getDefaults(PlanFiles files, PlanConfig config, PluginLogger logger) {
|
||||
private static ConfigNode getDefaults(PlanFiles files, PlanConfig config, PluginLogger logger) {
|
||||
String fileName = config.get(DisplaySettings.THEME);
|
||||
String fileLocation = getFileLocation(fileName);
|
||||
|
||||
try {
|
||||
return files.readFromResource(fileLocation);
|
||||
try (ConfigReader reader = new ConfigReader(files.readStreamFromResource(fileLocation))) {
|
||||
return reader.read();
|
||||
} catch (IOException e) {
|
||||
logger.error("Could not find theme " + fileLocation + ". Attempting to use default.");
|
||||
return new ArrayList<>();
|
||||
return new ConfigNode(null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
package com.djrapitops.plan.system.settings.changes;
|
||||
|
||||
import com.djrapitops.plan.system.settings.config.Config;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigNode;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigReader;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -63,23 +62,6 @@ class ConfigChangeTest {
|
||||
assertFalse(new ConfigChange.Moved("Test", "MovedTo").hasBeenApplied(config));
|
||||
}
|
||||
|
||||
@Test
|
||||
void configParentIsSameObject() {
|
||||
config = prepareConfig("Test: 'value'");
|
||||
ConfigNode node = config.getConfigNode("Test");
|
||||
ConfigNode parent = node.getParent();
|
||||
assertTrue(parent instanceof Config);
|
||||
assertSame(config, parent);
|
||||
}
|
||||
|
||||
@Test
|
||||
void configParentChildrenIsSameObject() {
|
||||
config = prepareConfig("Test: 'value'");
|
||||
ConfigNode node = config.getConfigNode("Test");
|
||||
ConfigNode parent = node.getParent();
|
||||
assertSame(config.getChildren(), parent.getChildren());
|
||||
}
|
||||
|
||||
@Test
|
||||
void moveChangeRecognizesItHasBeenApplied() {
|
||||
config = prepareConfig("Test: 'value'");
|
||||
@ -87,7 +69,6 @@ class ConfigChangeTest {
|
||||
ConfigChange change = new ConfigChange.Moved("Test", "MovedTo");
|
||||
change.apply(config);
|
||||
|
||||
assertFalse(config.getChildren().containsKey("Test"));
|
||||
assertFalse(config.contains("Test"), "Old node was not removed");
|
||||
assertTrue(config.contains("MovedTo"), "New node was not created");
|
||||
assertTrue(change.hasBeenApplied(config), "Did not recognize it has been applied");
|
||||
@ -101,7 +82,7 @@ class ConfigChangeTest {
|
||||
|
||||
assertFalse(config.contains("Test"), "Old node was not removed");
|
||||
assertTrue(config.contains("MovedTo"), "New node was not created");
|
||||
String result = config.getConfigNode("MovedTo").getValue();
|
||||
String result = config.getString("MovedTo");
|
||||
assertEquals("value", result);
|
||||
}
|
||||
|
||||
@ -113,7 +94,7 @@ class ConfigChangeTest {
|
||||
|
||||
assertFalse(config.contains("Test"), "Old node was not removed");
|
||||
assertTrue(config.contains("MovedTo"), "New node was not created");
|
||||
String result = config.getConfigNode("MovedTo").getValue();
|
||||
String result = config.getString("MovedTo");
|
||||
assertEquals("value", result);
|
||||
}
|
||||
|
||||
@ -125,7 +106,7 @@ class ConfigChangeTest {
|
||||
|
||||
assertFalse(config.contains("Test"), "Old node was not removed");
|
||||
assertTrue(config.contains("MovedTo"), "New node was not created");
|
||||
String result = config.getConfigNode("MovedTo").getValue();
|
||||
String result = config.getString("MovedTo");
|
||||
assertEquals("\"value\"", result);
|
||||
}
|
||||
|
||||
@ -137,7 +118,7 @@ class ConfigChangeTest {
|
||||
|
||||
assertFalse(config.contains("Test"), "Old node was not removed");
|
||||
assertTrue(config.contains("MovedTo"), "New node was not created");
|
||||
String result = config.getConfigNode("MovedTo").getValue();
|
||||
String result = config.getString("MovedTo");
|
||||
assertEquals("'value'", result);
|
||||
}
|
||||
|
||||
|
@ -16,18 +16,278 @@
|
||||
*/
|
||||
package com.djrapitops.plan.system.settings.config;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.platform.runner.JUnitPlatform;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@RunWith(JUnitPlatform.class)
|
||||
class ConfigNodeTest {
|
||||
|
||||
@Test
|
||||
void rootNodeReturnsDepthZero() {
|
||||
assertEquals(0, new ConfigNode(null, null, null).getNodeDepth());
|
||||
private static final ConfigValueParser<String> STRING_PARSER = new ConfigValueParser.StringParser();
|
||||
|
||||
private static final String SIMPLE_STRING_NODE = "Simple_string_node";
|
||||
private static final String STRING_NODE_WITH_QUOTES = "String_node_with_quotes";
|
||||
private static final String STRING_NODE_WITH_DOUBLE_QUOTES = "String_node_with_double_quotes";
|
||||
private static final String FIRST_LEVEL = "1st_level";
|
||||
private static final String SECOND_LEVEL = "2nd_level";
|
||||
|
||||
private ConfigNode testTree;
|
||||
|
||||
@BeforeEach
|
||||
void prepareTree() {
|
||||
testTree = new ConfigNode(null, null, null);
|
||||
testTree.addChild(new ConfigNode(SIMPLE_STRING_NODE, testTree, "String"));
|
||||
testTree.addChild(new ConfigNode(STRING_NODE_WITH_QUOTES, testTree, "'String'"));
|
||||
testTree.addChild(new ConfigNode(STRING_NODE_WITH_DOUBLE_QUOTES, testTree, "\"String\""));
|
||||
ConfigNode emptyNode = new ConfigNode(FIRST_LEVEL, testTree, null);
|
||||
testTree.addChild(emptyNode);
|
||||
emptyNode.addChild(new ConfigNode(SECOND_LEVEL, emptyNode, "String"));
|
||||
|
||||
assertTrue(testTree.childNodes.containsKey(SIMPLE_STRING_NODE), "Tree construction failed, addChild does not work.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rootNodeReturnsDepthZero() {
|
||||
assertEquals(0, testTree.getNodeDepth());
|
||||
}
|
||||
|
||||
@Test
|
||||
void depthOneIsReturnedCorrectly() {
|
||||
assertEquals(1, testTree.childNodes.get(SIMPLE_STRING_NODE).getNodeDepth());
|
||||
}
|
||||
|
||||
@Test
|
||||
void depthTwoIsReturnedCorrectly() {
|
||||
assertEquals(2, testTree.childNodes.get(FIRST_LEVEL).childNodes.get(SECOND_LEVEL).getNodeDepth());
|
||||
}
|
||||
|
||||
@Test
|
||||
void firstLevelNodeIsFound() {
|
||||
assertTrue(testTree.getNode(SIMPLE_STRING_NODE).isPresent(), "Node was not found");
|
||||
}
|
||||
|
||||
@Test
|
||||
void secondLevelNodeIsFound() {
|
||||
assertTrue(testTree.getNode(FIRST_LEVEL + "." + SECOND_LEVEL).isPresent(), "Node was not found");
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalStringValueIsParsedCorrectly() {
|
||||
String expected = "String";
|
||||
String result = testTree.childNodes.get(SIMPLE_STRING_NODE).getString();
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalStringValueIsParsedCorrectlyViaPath() {
|
||||
String expected = "String";
|
||||
String result = testTree.getString(SIMPLE_STRING_NODE);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quotedStringValueIsParsedCorrectly() {
|
||||
String expected = "String";
|
||||
String result = testTree.childNodes.get(STRING_NODE_WITH_QUOTES).getString();
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quotedStringValueIsParsedCorrectlyViaPath() {
|
||||
String expected = "String";
|
||||
String result = testTree.getString(STRING_NODE_WITH_QUOTES);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void doubleQuotedStringValueIsParsedCorrectly() {
|
||||
String expected = "String";
|
||||
String result = testTree.childNodes.get(STRING_NODE_WITH_DOUBLE_QUOTES).getString();
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void doubleQuotedStringValueIsParsedCorrectlyViaPath() {
|
||||
String expected = "String";
|
||||
String result = testTree.getString(STRING_NODE_WITH_DOUBLE_QUOTES);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeFirstLevelChildRemovesFirstAndSecondLevelChildren() {
|
||||
assertTrue(testTree.childNodes.containsKey(FIRST_LEVEL));
|
||||
|
||||
ConfigNode removedNode = testTree.childNodes.get(FIRST_LEVEL);
|
||||
|
||||
testTree.removeNode(FIRST_LEVEL);
|
||||
|
||||
assertFalse(testTree.getNode(FIRST_LEVEL).isPresent());
|
||||
assertFalse(testTree.getNode(FIRST_LEVEL + "." + SECOND_LEVEL).isPresent());
|
||||
assertNull(removedNode.parent);
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeSecondLevelChildRemovesOnlySecondLevelChild() {
|
||||
assertTrue(testTree.childNodes.get(FIRST_LEVEL).childNodes.containsKey(SECOND_LEVEL));
|
||||
|
||||
testTree.removeNode(FIRST_LEVEL + "." + SECOND_LEVEL);
|
||||
|
||||
assertTrue(testTree.getNode(FIRST_LEVEL).isPresent());
|
||||
assertFalse(testTree.getNode(FIRST_LEVEL + "." + SECOND_LEVEL).isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getNodeDoesNotAddNodes() {
|
||||
assertFalse(testTree.getNode("NonexistentNode").isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void childNodesAreSorted() {
|
||||
List<String> nodeOrder = new ArrayList<>(testTree.nodeOrder);
|
||||
|
||||
testTree.sort();
|
||||
|
||||
assertNotEquals(nodeOrder, testTree.nodeOrder);
|
||||
Collections.sort(nodeOrder);
|
||||
assertEquals(nodeOrder, testTree.nodeOrder);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addChildUpdatesParent() {
|
||||
ConfigNode adding = new ConfigNode("Path", /*null parent*/null, null);
|
||||
testTree.addChild(adding);
|
||||
assertSame(testTree, adding.parent);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addFirstLevelNodeAddsSingleChild() {
|
||||
testTree.addNode("Path");
|
||||
assertTrue(testTree.getNode("Path").isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSecondLevelNodeAddsAllNodesInPath() {
|
||||
testTree.addNode("Path.Path");
|
||||
assertTrue(testTree.getNode("Path").isPresent());
|
||||
assertTrue(testTree.getNode("Path.Path").isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void moveMovesNodeToNewPath() {
|
||||
String oldPath = SIMPLE_STRING_NODE;
|
||||
String newPath = "New_path";
|
||||
|
||||
ConfigNode movedNode = testTree.childNodes.get(oldPath);
|
||||
ConfigNode oldParent = movedNode.parent;
|
||||
assertSame(testTree, oldParent);
|
||||
|
||||
System.out.println("Root: " + testTree);
|
||||
testTree.moveChild(oldPath, newPath);
|
||||
|
||||
// New has proper values
|
||||
Optional<ConfigNode> newNode = testTree.getNode(newPath);
|
||||
assertTrue(newNode.isPresent());
|
||||
assertEquals(movedNode.value, newNode.get().value);
|
||||
assertEquals(movedNode.comment, newNode.get().comment);
|
||||
assertEquals(movedNode.nodeOrder, newNode.get().nodeOrder);
|
||||
assertSame(oldParent, newNode.get().parent);
|
||||
|
||||
// Old has been removed
|
||||
assertFalse(testTree.getNode(oldPath).isPresent());
|
||||
assertNull(movedNode.parent);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonExistingNodeIsNotMoved() {
|
||||
assertFalse(testTree.moveChild("non-existing", "to"));
|
||||
assertFalse(testTree.getNode("to").isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deepKeyIsFullPath() {
|
||||
String expected = FIRST_LEVEL + "." + SECOND_LEVEL;
|
||||
String result = testTree.getNode(expected).map(node -> node.getKey(true)).orElse("FAIL");
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shallowKeyIsOnlyLastPart() {
|
||||
assertEquals(
|
||||
SECOND_LEVEL,
|
||||
testTree.getNode(FIRST_LEVEL + "." + SECOND_LEVEL)
|
||||
.map(node -> node.getKey(false))
|
||||
.orElse("FAIL")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void settingValueAddsMissingNodes() {
|
||||
String expectedValue = "Value";
|
||||
testTree.set("Path.Path", expectedValue);
|
||||
|
||||
Optional<ConfigNode> addedNode = testTree.getNode("Path.Path");
|
||||
assertTrue(addedNode.isPresent());
|
||||
assertEquals(expectedValue, addedNode.get().getString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void settingValueIsSet() {
|
||||
String expectedValue = "NewValue";
|
||||
testTree.set(SIMPLE_STRING_NODE, expectedValue);
|
||||
|
||||
assertEquals(expectedValue, testTree.getString(SIMPLE_STRING_NODE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getStringReturnsValue() {
|
||||
String expected = "Value";
|
||||
ConfigNode adding = new ConfigNode("Path", null, expected);
|
||||
String result = adding.getString();
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonExistentStringValueIsNotParsed() {
|
||||
assertNull(testTree.getString("Non-existent"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nullValueIsReturnedAsNull() {
|
||||
assertNull(testTree.getString(FIRST_LEVEL));
|
||||
}
|
||||
|
||||
@Test
|
||||
void settingConfigNodeOverridesValues() {
|
||||
ConfigNode adding = new ConfigNode(null, null, "NewValue");
|
||||
testTree.set(SIMPLE_STRING_NODE, adding);
|
||||
assertEquals(
|
||||
adding.getString(),
|
||||
testTree.getString(SIMPLE_STRING_NODE)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void settingConfigNodeAddsNewNodes() {
|
||||
ConfigNode adding = new ConfigNode(null, null, "NewValue");
|
||||
testTree.set("Path", adding);
|
||||
assertEquals(
|
||||
adding.getString(),
|
||||
testTree.getString("Path")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void settingConfigNodeCopiesChildren() {
|
||||
ConfigNode adding = testTree.getNode(FIRST_LEVEL).orElseThrow(() -> new AssertionError("Fail"));
|
||||
testTree.set(SIMPLE_STRING_NODE, adding);
|
||||
assertTrue(testTree.getNode(SIMPLE_STRING_NODE + "." + SECOND_LEVEL).isPresent());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user