Skip to content

Commit

Permalink
Support custom map creators in GenericBuilder, resolve #62
Browse files Browse the repository at this point in the history
The core_android patches still need to be fixed in order for the project to build correctly.
  • Loading branch information
TheElectronWill committed Apr 16, 2019
1 parent ba64580 commit 89c1d09
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,7 @@ public AbstractConfig(UnmodifiableConfig toCopy, Supplier<Map<String, Object>> m
}

protected static <T> Supplier<Map<String, T>> getDefaultMapCreator(boolean concurrent) {
if (Config.isInsertionOrderPreserved()) {
return concurrent ? ()->Collections.synchronizedMap(new LinkedHashMap<>()) : LinkedHashMap::new;
// TODO find or make a ConcurrentMap that preserves the insertion order
}
return concurrent ? ConcurrentHashMap::new : HashMap::new;
return Config.getDefaultMapCreator(concurrent);
}

protected static <T> Supplier<Map<String, T>> getWildcardMapCreator(Supplier<Map<String, Object>> mapCreator) {
Expand Down
37 changes: 33 additions & 4 deletions core/src/main/java/com/electronwill/nightconfig/core/Config.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
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;
Expand Down Expand Up @@ -241,7 +243,7 @@ default void update(List<String> path, Object value) {
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.
*
Expand Down Expand Up @@ -327,7 +329,7 @@ static Config wrap(Map<String, Object> map, ConfigFormat<?> format) {
static Config copy(UnmodifiableConfig config) {
return new SimpleConfig(config, config.configFormat(), false);
}

/**
* Creates a new Config with the content of the given config. The returned config will have
* the same format as the copied config, and be backed by the given supplier.
Expand Down Expand Up @@ -355,14 +357,14 @@ static Config copy(UnmodifiableConfig config, Supplier<Map<String, Object>> mapC
static Config copy(UnmodifiableConfig config, ConfigFormat<?> format) {
return new SimpleConfig(config, format, false);
}

/**
* Creates a new Config with the content of the given config.
* The returned config will be backed by the given map supplier.
*
* If you wish all your configs to preserve insertion order, please have a look at the more
* practical setting {@link #setInsertionOrderPreserved(boolean)}.
*
*
* @see #of(Supplier, ConfigFormat)
*
* @param config the config to copy
Expand Down Expand Up @@ -426,4 +428,31 @@ static boolean isInsertionOrderPreserved() {
static void setInsertionOrderPreserved(boolean orderPreserved) {
System.setProperty("nightconfig.preserveInsertionOrder", orderPreserved ? "true" : "false");
}

/**
* Returns a map supplier that fulfills the given requirements.
*
* @param concurrent true to make the maps thread-safe
* @param insertionOrderPreserved true to make the maps preserve the insertion order of values
* @return a map supplier corresponding to the given settings
*/
static <T> Supplier<Map<String, T>> getDefaultMapCreator(boolean concurrent, boolean insertionOrderPreserved) {
if (insertionOrderPreserved) {
return concurrent ? ()->Collections.synchronizedMap(new LinkedHashMap<>()) : LinkedHashMap::new;
// TODO find or make a ConcurrentMap that preserves the insertion order
}
return concurrent ? ConcurrentHashMap::new : HashMap::new;
}

/**
* Returns a map supplier that fullfills the given requirements. It preserves
* (or not) the insertion order of its values according to
* {@link Config#isInsertionOrderPreserved()}.
*
* @param concurrent true to make the maps thread-safe
* @return a map supplier corresponding to the given settings
*/
static <T> Supplier<Map<String, T>> getDefaultMapCreator(boolean concurrent) {
return getDefaultMapCreator(concurrent, Config.isInsertionOrderPreserved());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.function.Supplier;

/**
* A configuration format, that can parse, create and write some types of configurations.
*
* @param <C>the type of configurations createdby this format
* @param <C>the type of configurations created by this format
* @author TheElectronWill
*/
public interface ConfigFormat<C extends Config> {
Expand All @@ -29,14 +31,27 @@ public interface ConfigFormat<C extends Config> {
/**
* @return a config of this format
*/
C createConfig();
default C createConfig() {
return createConfig(Config.getDefaultMapCreator(false));
}

/**
* Creates a config of this format. The returned config is guaranteed to be thread-safe.
*
* @return a concurrent config of this format
*/
C createConcurrentConfig();
default C createConcurrentConfig() {
return createConfig(Config.getDefaultMapCreator(true));
}

/**
* Creates a config that uses the given map supplier for all its levels (top
* level and subconfigs).
*
* @param mapCreator the map supplier for the config
* @return a config of this format with the given map creator
*/
C createConfig(Supplier<Map<String, Object>> mapCreator);

/**
* Checks if this format supports CommentedConfigs. Note that supporting CommentedConfigs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import com.electronwill.nightconfig.core.io.ConfigParser;
import com.electronwill.nightconfig.core.io.ConfigWriter;

import java.util.Map;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
* The commented version of {@link InMemoryFormat}
Expand Down Expand Up @@ -45,13 +47,8 @@ public ConfigParser<CommentedConfig> createParser() {
}

@Override
public CommentedConfig createConfig() {
return CommentedConfig.of(this);
}

@Override
public CommentedConfig createConcurrentConfig() {
return CommentedConfig.ofConcurrent(this);
public CommentedConfig createConfig(Supplier<Map<String, Object>> mapCreator) {
return CommentedConfig.of(mapCreator, this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import com.electronwill.nightconfig.core.io.ConfigWriter;

import java.util.Collection;
import java.util.Map;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
* A ConfigFormat that is only in memory. Its method {@link #isInMemory()} returns always true.
Expand Down Expand Up @@ -60,13 +62,8 @@ public ConfigParser<Config> createParser() {
}

@Override
public Config createConfig() {
return Config.of(this);
}

@Override
public Config createConcurrentConfig() {
return Config.ofConcurrent(this);
public Config createConfig(Supplier<Map<String, Object>> mapCreator) {
return Config.of(mapCreator, this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import com.electronwill.nightconfig.core.io.ConfigParser;
import com.electronwill.nightconfig.core.io.ConfigWriter;

import java.util.Map;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
* @author TheElectronWill
Expand Down Expand Up @@ -39,6 +41,11 @@ public C createConcurrentConfig() {
return initialFormat.createConcurrentConfig();
}

@Override
public C createConfig(Supplier<Map<String, Object>> mapCreator) {
return initialFormat.createConfig(mapCreator);
}

@Override
public boolean supportsComments() {
return initialFormat.supportsComments();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.function.Supplier;

/**
* A generic FileConfig/CommentedFileConfig/someOtherFileConfig builder. The default settings are:
Expand All @@ -24,6 +26,8 @@
* <li>Not autosaved - change it with {@link #autosave()}</li>
* <li>Not autoreloaded - change it with {@link #autoreload()}</li>
* <li>Not thread-safe - change it with {@link #concurrent()}</li>
* <li>Values' insertion order preserved if {@link Config#isInsertionOrderPreserved()}
* returns true when the builder is constructed.</li>
* </ul>
*
* @author TheElectronWill
Expand All @@ -38,7 +42,9 @@ public abstract class GenericBuilder<Base extends Config, Result extends FileCon
protected WritingMode writingMode = WritingMode.REPLACE;
protected ParsingMode parsingMode = ParsingMode.REPLACE;
protected FileNotFoundAction nefAction = FileNotFoundAction.CREATE_EMPTY;
protected boolean sync = false, autosave = false, autoreload = false;
protected boolean sync = false, autosave = false, autoreload = false, concurrent = false;
protected boolean insertionOrder = Config.isInsertionOrderPreserved();
protected Supplier<Map<String, Object>> mapCreator = null;

GenericBuilder(Path file, ConfigFormat<? extends Base> format) {
this.file = file;
Expand Down Expand Up @@ -173,6 +179,33 @@ public GenericBuilder<Base, Result> concurrent() {
if (config == null) {
config = format.createConcurrentConfig();
}
concurrent = true;
return this;
}

/**
* Makes the configuration preserve the insertion order of its values.
*
* @return this builder
*/
public GenericBuilder<Base, Result> preserveInsertionOrder() {
insertionOrder = true;
return this;
}

/**
* Uses a specific Supplier to create the backing maps (one for the top level
* and one for each sub-configuration) of the configuration.
* <p><br>
* <b>Warning :</b> if {@link #autoreload()} is called, the map creator
* must return thread-safe maps, because the autoreloading system will modify
* the configuration from another thread.
*
* @param s the map supplier to use
* @return this builder
*/
public GenericBuilder<Base, Result> backingMapCreator(Supplier<Map<String,Object>> s) {
mapCreator = s;
return this;
}

Expand Down Expand Up @@ -219,8 +252,11 @@ public Result build() {
protected abstract Result buildNormal(FileConfig chain);

protected final Base getConfig() {
if (config == null) {// concurrent() has not been called
config = format.createConfig();
if (config == null) {
if (mapCreator == null) {
mapCreator = Config.getDefaultMapCreator(concurrent, insertionOrder);
}
config = format.createConfig(mapCreator);
}
return config;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import com.electronwill.nightconfig.core.io.ConfigParser;
import com.electronwill.nightconfig.core.io.ConfigWriter;

import java.util.Map;
import java.util.function.Supplier;

/**
* Represents the Hocon config format.
*
Expand All @@ -28,6 +31,13 @@ public static CommentedConfig newConfig() {
return INSTANCE.createConfig();
}

/**
* @return a new config with the given map creator
*/
public static CommentedConfig newConfig(Supplier<Map<String, Object>> s) {
return INSTANCE.createConfig(s);
}

/**
* @return a new thread-safe config with the hocon format
*/
Expand All @@ -53,13 +63,8 @@ public ConfigParser<CommentedConfig> createParser() {
}

@Override
public CommentedConfig createConfig() {
return CommentedConfig.of(this);
}

@Override
public CommentedConfig createConcurrentConfig() {
return CommentedConfig.ofConcurrent(this);
public CommentedConfig createConfig(Supplier<Map<String, Object>> mapCreator) {
return CommentedConfig.of(mapCreator, this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import java.util.function.Supplier;

/**
* @author TheElectronWill
Expand Down Expand Up @@ -93,6 +95,13 @@ public static Config newConfig() {
return FANCY.createConfig();
}

/**
* @return a new config with the given map creator
*/
public static Config newConfig(Supplier<Map<String, Object>> s) {
return FANCY.createConfig(s);
}

/**
* @return a new thread-safe config with the format {@link JsonFormat#fancyInstance()}.
*/
Expand All @@ -113,13 +122,8 @@ private JsonFormat() {}
public abstract ConfigParser<Config> createParser();

@Override
public Config createConfig() {
return Config.of(this);
}

@Override
public Config createConcurrentConfig() {
return Config.ofConcurrent(this);
public Config createConfig(Supplier<Map<String, Object>> mapCreator) {
return Config.of(mapCreator, this);
}

@Override
Expand Down

0 comments on commit 89c1d09

Please sign in to comment.