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:
Rsl1122 2018-12-17 23:05:20 +02:00
parent 9879d9a499
commit 81218c968f
15 changed files with 365 additions and 114 deletions

View File

@ -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 {

View File

@ -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.
*

View File

@ -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();
}

View File

@ -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());
}
}
}

View File

@ -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());
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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();
}
};
}
/**

View File

@ -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(() -> {

View File

@ -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 {

View File

@ -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));
}
};

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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());
}
}