From 3a3e1144dc951a99e487d81ccafbe6a5542a2428 Mon Sep 17 00:00:00 2001 From: Bukkit/Spigot Date: Sat, 5 Feb 2011 22:44:48 -0800 Subject: [PATCH] Added node and writing functions to Configuration. By: sk89q --- .../org/bukkit/util/config/Configuration.java | 42 ++++++- .../bukkit/util/config/ConfigurationNode.java | 112 ++++++++++++++++++ 2 files changed, 152 insertions(+), 2 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/util/config/Configuration.java b/paper-api/src/main/java/org/bukkit/util/config/Configuration.java index 228812bbd1..0cb63f15a1 100644 --- a/paper-api/src/main/java/org/bukkit/util/config/Configuration.java +++ b/paper-api/src/main/java/org/bukkit/util/config/Configuration.java @@ -2,12 +2,16 @@ package org.bukkit.util.config; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStreamWriter; import java.util.HashMap; import java.util.Map; +import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.SafeConstructor; import org.yaml.snakeyaml.reader.UnicodeReader; +import org.yaml.snakeyaml.representer.Representer; /** * YAML configuration loader. To use this class, construct it with path to @@ -43,18 +47,25 @@ import org.yaml.snakeyaml.reader.UnicodeReader; * @author sk89q */ public class Configuration extends ConfigurationNode { - private Yaml yaml = new Yaml(new SafeConstructor()); + private Yaml yaml; private File file; public Configuration(File file) { super(new HashMap()); + + DumperOptions options = new DumperOptions(); + options.setIndent(4); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + + yaml = new Yaml(new SafeConstructor(), new Representer(), options); + this.file = file; } /** * Loads the configuration file. All errors are thrown away. */ - public void load() { + public void load() { FileInputStream stream = null; try { @@ -74,6 +85,33 @@ public class Configuration extends ConfigurationNode { } } + /** + * Saves the configuration to disk. All errors are clobbered. + * + * @return true if it was successful + */ + public boolean save() { + FileOutputStream stream = null; + + file.getParentFile().mkdirs(); + + try { + stream = new FileOutputStream(file); + yaml.dump(root, new OutputStreamWriter(stream, "UTF-8")); + return true; + } catch (IOException e) { + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (IOException e) { + } + } + + return false; + } + @SuppressWarnings("unchecked") private void read(Object input) throws ConfigurationException { try { diff --git a/paper-api/src/main/java/org/bukkit/util/config/ConfigurationNode.java b/paper-api/src/main/java/org/bukkit/util/config/ConfigurationNode.java index b7c0bda3ce..32a1fc243b 100644 --- a/paper-api/src/main/java/org/bukkit/util/config/ConfigurationNode.java +++ b/paper-api/src/main/java/org/bukkit/util/config/ConfigurationNode.java @@ -1,6 +1,7 @@ package org.bukkit.util.config; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -59,6 +60,42 @@ public class ConfigurationNode { return null; } + + /** + * Set the property at a location. This will override existing + * configuration data to have it conform to key/value mappings. + * + * @param path + * @param value + */ + @SuppressWarnings("unchecked") + public void setProperty(String path, Object value) { + if (!path.contains(".")) { + root.put(path, value); + return; + } + + String[] parts = path.split("\\."); + Map node = root; + + for (int i = 0; i < parts.length; i++) { + Object o = node.get(parts[i]); + + // Found our target! + if (i == parts.length - 1) { + node.put(parts[i], value); + return; + } + + if (o == null || !(o instanceof Map)) { + // This will override existing configuration data! + o = new HashMap(); + node.put(parts[i], o); + } + + node = (Map)o; + } + } /** * Gets a string at a location. This will either return an String @@ -302,6 +339,81 @@ public class ConfigurationNode { return list; } + /** + * Gets a list of nodes. Non-valid entries will not be in the list. + * There will be no null slots. If the list is not defined, the + * default will be returned. 'null' can be passed for the default + * and an empty list will be returned instead. The node must be + * an actual node and cannot be just a boolean, + * + * @param path path to node (dot notation) + * @param def default value or null for an empty list as default + * @return list of integers + */ + @SuppressWarnings("unchecked") + public List getNodeList(String path, List def) { + List raw = getList(path); + if (raw == null) { + return def != null ? def : new ArrayList(); + } + + List list = new ArrayList(); + for (Object o : raw) { + if (o instanceof Map) { + list.add(new ConfigurationNode((Map)o)); + } + } + + return list; + } + + /** + * Get a configuration node at a path. If the node doesn't exist or the + * path does not lead to a node, null will be returned. A node has + * key/value mappings. + * + * @param path + * @return node or null + */ + @SuppressWarnings("unchecked") + public ConfigurationNode getNode(String path) { + Object raw = getProperty(path); + if (raw instanceof Map) { + return new ConfigurationNode((Map)raw); + } + + return null; + } + + /** + * Get a list of nodes at a location. If the map at the particular location + * does not exist or it is not a map, null will be returned. + * + * @param path path to node (dot notation) + * @return map of nodes + */ + @SuppressWarnings("unchecked") + public Map getNodes(String path) { + Object o = getProperty(path); + if (o == null) { + return null; + } else if (o instanceof Map) { + Map nodes = + new HashMap(); + + for (Map.Entry entry : ((Map)o).entrySet()) { + if (entry.getValue() instanceof Map) { + nodes.put(entry.getKey(), + new ConfigurationNode((Map) entry.getValue())); + } + } + + return nodes; + } else { + return null; + } + } + /** * Casts a value to an integer. May return null. *