package org.bukkit.configuration; import org.bukkit.configuration.serialization.ConfigurationSerializable; import java.io.File; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.inventory.ItemStack; import org.bukkit.material.MaterialData; import org.bukkit.util.Vector; /** * A type of {@link ConfigurationSection} that is stored in memory. */ public class MemorySection implements ConfigurationSection { protected final Map map = new LinkedHashMap(); private final Configuration root; private final ConfigurationSection parent; private final String path; private final String fullPath; /** * Creates an empty MemorySection for use as a root {@link Configuration} section. *

* Note that calling this without being yourself a {@link Configuration} will throw an * exception! * * @throws IllegalStateException Thrown if this is not a {@link Configuration} root. */ protected MemorySection() { if (!(this instanceof Configuration)) { throw new IllegalStateException("Cannot contruct a root MemorySection when not a Configuration"); } this.path = ""; this.fullPath = ""; this.parent = null; this.root = (Configuration)this; } /** * Creates an empty MemorySection with the specified parent and path. * * @param parent Parent section that contains this own section. * @param path Path that you may access this section from via the root {@link Configuration}. * @throws IllegalArgumentException Thrown is parent or path is null, or if parent contains no root Configuration. */ protected MemorySection(ConfigurationSection parent, String path) { if (parent == null) { throw new IllegalArgumentException("Parent cannot be null"); } if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } this.path = path; this.parent = parent; this.root = parent.getRoot(); if (root == null) { throw new IllegalArgumentException("Path cannot be orphaned"); } this.fullPath = createPath(parent, path); } public Set getKeys(boolean deep) { Set result = new LinkedHashSet(); if (getRoot().options().copyDefaults()) { ConfigurationSection defaults = getDefaultSection(); if (defaults != null) { result.addAll(defaults.getKeys(deep)); } } mapChildrenKeys(result, this, deep); return result; } public Map getValues(boolean deep) { Map result = new LinkedHashMap(); if (getRoot().options().copyDefaults()) { ConfigurationSection defaults = getDefaultSection(); if (defaults != null) { result.putAll(defaults.getValues(deep)); } } mapChildrenValues(result, this, deep); return result; } public boolean contains(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } return get(path) != null; } public boolean isSet(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } if (getRoot().options().copyDefaults()) { return contains(path); } else { return get(path, null) != null; } } public String getCurrentPath() { return fullPath; } public String getName() { return path; } public Configuration getRoot() { return root; } public ConfigurationSection getParent() { return parent; } public void addDefault(String path, Object value) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } if (root == null) { throw new IllegalStateException("Cannot set default on orphaned section"); } else { root.addDefault(createPath(this, path), value); } } public ConfigurationSection getDefaultSection() { if (getRoot() == null) { return null; } Configuration defaults = getRoot().getDefaults(); if (defaults != null) { if (defaults.isConfigurationSection(getCurrentPath())) { return defaults.getConfigurationSection(getCurrentPath()); } } return null; } public void set(String path, Object value) { String[] split = path.split(Pattern.quote(Character.toString(getRoot().options().pathSeparator()))); ConfigurationSection section = this; if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } else if (path.length() == 0) { throw new IllegalArgumentException("Cannot set to an empty path"); } for (int i = 0; i < split.length - 1; i++) { ConfigurationSection last = section; section = last.getConfigurationSection(split[i]); if (section == null) { section = last.createSection(split[i]); } } String key = split[split.length - 1]; if (section == this) { map.put(key, prepForStorage(value)); } else { section.set(key, value); } } public Object get(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } return get(path, getDefault(path)); } public Object get(String path, Object def) { Object result = null; String[] split = path.split(Pattern.quote(Character.toString(getRoot().options().pathSeparator()))); ConfigurationSection section = this; if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } else if (path.length() == 0) { return this; } for (int i = 0; (i < split.length - 1) && (section != null); i++) { section = getConfigurationSection(split[i]); } String key = split[split.length - 1]; if (section == this) { result = map.get(key); } else if (section != null) { result = section.get(key); } return (result == null) ? def : result; } public ConfigurationSection createSection(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } else if (path.length() == 0) { throw new IllegalArgumentException("Cannot create section at empty path"); } String[] split = path.split(Pattern.quote(Character.toString(getRoot().options().pathSeparator()))); ConfigurationSection section = this; for (int i = 0; i < split.length - 1; i++) { ConfigurationSection last = section; section = getConfigurationSection(split[i]); if (section == null) { section = last.createSection(split[i]); } } String key = split[split.length - 1]; if (section == this) { ConfigurationSection result = new MemorySection(this, key); map.put(key, result); return result; } else { return section.createSection(key); } } // Primitives public String getString(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object def = getDefault(path); return getString(path, (def instanceof String) ? (String)def : null); } public String getString(String path, String def) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, def); return (val instanceof String) ? (String)val : def; } public boolean isString(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof String; } public int getInt(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object def = getDefault(path); return getInt(path, (def instanceof Integer) ? (Integer)def : 0); } public int getInt(String path, int def) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, def); return (val instanceof Integer) ? (Integer)val : def; } public boolean isInt(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof Integer; } public boolean getBoolean(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object def = getDefault(path); return getBoolean(path, (def instanceof Boolean) ? (Boolean)def : false); } public boolean getBoolean(String path, boolean def) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, def); return (val instanceof Boolean) ? (Boolean)val : def; } public boolean isBoolean(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof Boolean; } public double getDouble(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object def = getDefault(path); return getDouble(path, (def instanceof Double) ? (Double)def : 0); } public double getDouble(String path, double def) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, def); return (val instanceof Double) ? (Double)val : def; } public boolean isDouble(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof Double; } public long getLong(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object def = getDefault(path); return getLong(path, (def instanceof Long) ? (Long)def : 0); } public long getLong(String path, long def) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, def); return (val instanceof Long) ? (Long)val : def; } public boolean isLong(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof Long; } // Java public List getList(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object def = getDefault(path); return getList(path, (def instanceof List) ? (List)def : null); } public List getList(String path, List def) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, def); return (val instanceof List) ? (List)val : def; } public boolean isList(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof List; } // Bukkit public Vector getVector(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object def = getDefault(path); return getVector(path, (def instanceof Vector) ? (Vector)def : null); } public Vector getVector(String path, Vector def) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, def); return (val instanceof Vector) ? (Vector)val : def; } public boolean isVector(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof Vector; } public OfflinePlayer getOfflinePlayer(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object def = getDefault(path); return getOfflinePlayer(path, (def instanceof OfflinePlayer) ? (OfflinePlayer)def : null); } public OfflinePlayer getOfflinePlayer(String path, OfflinePlayer def) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, def); return (val instanceof OfflinePlayer) ? (OfflinePlayer)val : def; } public boolean isOfflinePlayer(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof OfflinePlayer; } public ItemStack getItemStack(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object def = getDefault(path); return getItemStack(path, (def instanceof ItemStack) ? (ItemStack)def : null); } public ItemStack getItemStack(String path, ItemStack def) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, def); return (val instanceof ItemStack) ? (ItemStack)val : def; } public boolean isItemStack(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof ItemStack; } public ConfigurationSection getConfigurationSection(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path, getDefault(path)); return (val instanceof ConfigurationSection) ? (ConfigurationSection)val : null; } public boolean isConfigurationSection(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Object val = get(path); return val instanceof ConfigurationSection; } protected Object prepForStorage(Object input) { if (input == null) { throw new IllegalArgumentException("Cannot store null"); } if (isPrimitiveWrapper(input) || isNaturallyStorable(input)) { return input; } else if (input instanceof ConfigurationSerializable) { return input; } throw new IllegalArgumentException("Cannot store " + input + " into " + this + ", unsupported class"); } protected boolean isPrimitiveWrapper(Object input) { return input instanceof Integer || input instanceof Boolean || input instanceof Character || input instanceof Byte || input instanceof Short || input instanceof Double || input instanceof Long || input instanceof Float; } protected boolean isNaturallyStorable(Object input) { return input instanceof List || input instanceof Iterable || input instanceof String || input instanceof File || input instanceof Enum; } protected Object getDefault(String path) { if (path == null) { throw new IllegalArgumentException("Path cannot be null"); } Configuration defaults = root.getDefaults(); return (defaults == null) ? null : defaults.get(createPath(this, path)); } protected void mapChildrenKeys(Set output, ConfigurationSection section, boolean deep) { if (section instanceof MemorySection) { MemorySection sec = (MemorySection)section; for (Map.Entry entry : sec.map.entrySet()) { output.add(createPath(section, entry.getKey(), this)); if ((deep) && (entry.getValue() instanceof ConfigurationSection)) { ConfigurationSection subsection = (ConfigurationSection)entry.getValue(); mapChildrenKeys(output, subsection, deep); } } } else { Set keys = section.getKeys(deep); for (String key : keys) { output.add(createPath(section, key, this)); } } } protected void mapChildrenValues(Map output, ConfigurationSection section, boolean deep) { if (section instanceof MemorySection) { MemorySection sec = (MemorySection)section; for (Map.Entry entry : sec.map.entrySet()) { output.put(createPath(section, entry.getKey(), this), entry.getValue()); if (entry.getValue() instanceof ConfigurationSection) { if (deep) { mapChildrenValues(output, (ConfigurationSection)entry.getValue(), deep); } } } } else { Map values = section.getValues(deep); for (Map.Entry entry : values.entrySet()) { output.put(createPath(section, entry.getKey(), this), entry.getValue()); } } } /** * Creates a full path to the given {@link ConfigurationSection} from its root {@link Configuration}. *

* You may use this method for any given {@link ConfigurationSection}, not only {@link MemorySection}. * * @param section Section to create a path for. * @param key Name of the specified section. * @return Full path of the section from its root. */ public static String createPath(ConfigurationSection section, String key) { return createPath(section, key, (section == null) ? null : section.getRoot()); } /** * Creates a relative path to the given {@link ConfigurationSection} from the given relative section. *

* You may use this method for any given {@link ConfigurationSection}, not only {@link MemorySection}. * * @param section Section to create a path for. * @param key Name of the specified section. * @param relativeTo Section to create the path relative to. * @return Full path of the section from its root. */ public static String createPath(ConfigurationSection section, String key, ConfigurationSection relativeTo) { StringBuilder builder = new StringBuilder(); if (section != null) { for (ConfigurationSection parent = section; (parent != null) && (parent != relativeTo); parent = parent.getParent()) { if (builder.length() > 0) { builder.insert(0, section.getRoot().options().pathSeparator()); } builder.insert(0, parent.getName()); } } if ((key != null) && (key.length() > 0)) { if (builder.length() > 0) { builder.append(section.getRoot().options().pathSeparator()); } builder.append(key); } return builder.toString(); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append(getClass().getSimpleName()); builder.append("[path='"); builder.append(getCurrentPath()); builder.append("', root='"); builder.append(root.getClass().getSimpleName()); builder.append("']"); return builder.toString(); } }