com.electronwill.nightconfig.core.Config Maven / Gradle / Ivy
package com.electronwill.nightconfig.core;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;
import static com.electronwill.nightconfig.core.utils.StringUtils.split;
/**
* A (modifiable) configuration that contains key/value mappings. Configurations are generally
* not thread-safe.
*
* @author TheElectronWill
*/
public interface Config extends UnmodifiableConfig {
/**
* Sets a config value.
*
* @param path the value's path, each part separated by a dot. Example "a.b.c"
* @param value the value to set
* @param the type of the old value
* @return the old value if any, or {@code null}
*/
default T set(String path, Object value) {
return set(split(path, '.'), value);
}
/**
* Sets a config value.
*
* @param path the value's path, each element of the list is a different part of the path.
* @param value the value to set
* @param the type of the old value
* @return the old value if any, or {@code null}
*/
T set(List path, Object value);
/**
* Adds a config value. The value is set iff there is no value associated with the given path.
*
* @param path the value's path, each element of the list is a different part of the path.
* @param value the value to set
* @return true if the value has been added, false if a value is already associated with the
* given path
*/
boolean add(List path, Object value);
/**
* Adds a config value. The value is set iff there is no value associated with the given path.
*
* @param path the value's path, each part separated by a dot. Example "a.b.c"
* @param value the value to set
* @return true if the value has been added, false if a value is already associated with the
* given path
*/
default boolean add(String path, Object value) {
return add(split(path, '.'), value);
}
/**
* Adds all the values of a config to this config, without replacing existing entries.
*
* @param config the source config
*/
default void addAll(UnmodifiableConfig config) {
for (UnmodifiableConfig.Entry ue : config.entrySet()) {
List key = Collections.singletonList(ue.getKey());
Object value = ue.getRawValue();
boolean existed = !add(key, value);
if (existed && value instanceof UnmodifiableConfig) {
}
}
}
/**
* Copies all the values of a config into this config. Existing entries are replaced, missing
* entries are created.
*
* @param config the source config
*/
default void putAll(UnmodifiableConfig config) {
valueMap().putAll(config.valueMap());
}
/**
* Removes a value from the config.
*
* @param path the value's path, each part separated by a dot. Example "a.b.c"
* @param the type of the old value
* @return the old value if any, or {@code null}
*/
default T remove(String path) {
return remove(split(path, '.'));
}
/**
* Removes a value from the config.
*
* @param path the value's path, each element of the list is a different part of the path.
* @param the type of the old value
* @return the old value if any, or {@code null}
*/
T remove(List path);
/**
* Removes all the values of the given config from this config.
*
* @param config the values to remove
*/
default void removeAll(UnmodifiableConfig config) {
valueMap().keySet().removeAll(config.valueMap().keySet());
}
/**
* Removes all values from the config.
*/
void clear();
/**
* Returns an Unmodifiable view of the config. Any change to the original (modifiable) config
* is still reflected to the returned UnmodifiableConfig, so it's unmodifiable but not
* immutable.
*
* @return an Unmodifiable view of the config.
*/
default UnmodifiableConfig unmodifiable() {
return new UnmodifiableConfig() {
@Override
public T getRaw(List path) {
return Config.this.getRaw(path);
}
@Override
public boolean contains(List path) {
return Config.this.contains(path);
}
@Override
public int size() {
return Config.this.size();
}
@Override
public Map valueMap() {
return Collections.unmodifiableMap(Config.this.valueMap());
}
@Override
public Set extends Entry> entrySet() {
return Config.this.entrySet();
}
@Override
public ConfigFormat> configFormat() {
return Config.this.configFormat();
}
};
}
/**
* Returns a checked view of the config. It checks that all the values put into the config are
* supported by the config's format (as per the {@link ConfigFormat#supportsType(Class)}
* method. Trying to insert an unsupported value throws an IllegalArgumentException.
*
* The values that are in the config when this method is called are also checked.
*
* @return a checked view of the config.
*/
default Config checked() {
return new CheckedConfig(this);
}
/**
* Returns a Map view of the config's values. Any change to the map is reflected in the config
* and vice-versa.
*/
Map valueMap();
/**
* Returns a Set view of the config's entries. Any change to the set or to the entries is
* reflected in the config, and vice-versa.
*/
@Override
Set extends Entry> entrySet();
/**
* A modifiable config entry.
*/
interface Entry extends UnmodifiableConfig.Entry {
/**
* Sets the entry's value.
*
* @param value the value to set
* @param the type of the old value
* @return the previous value
*/
T setValue(Object value);
}
/**
* Creates a new sub config of this config, as created when a subconfig's creation is
* implied by {@link #set(List, Object)} or {@link #add(List, Object)}.
*
* @return a new sub config
*/
Config createSubConfig();
//--- Scala convenience methods ---
/**
* For scala: sets a config value.
*
* @param path the value's path, each part separated by a dot. Example "a.b.c"
* @param value the value to set
* @see #set(String, Object)
*/
default void update(String path, Object value) {
set(path, value);
}
/**
* For scala: sets a config value.
*
* @param path the value's path, each element of the list is a different part of the path.
* @param value the value to set
* @see #set(List, Object)
*/
default void update(List path, Object value) {
set(path, value);
}
//--- Static methods ---
/**
* Creates a Config of the given format.
*
* @param format the config's format
* @return a new empty config
*/
static Config of(ConfigFormat extends Config> format) {
return new SimpleConfig(format, false);
}
/**
* Creates a Config backed by a certain kind of map, given by a supplier.
*
* If you wish all your configs to preserve insertion order, please have a look at the more
* practical setting {@link #setInsertionOrderPreserved(boolean)}.
*
* @param mapCreator a supplier which will be called to create all backing maps for this config (including sub-configs)
* @param format the config's format
* @return a new config backed by the map
*/
static Config of(Supplier