Giter Club home page Giter Club logo

configurate's People

Contributors

aaron1011 avatar astei avatar dags- avatar denwav avatar dualspiral avatar ferusgrim avatar forresthopkinsa avatar gabizou avatar jpenilla avatar karlatemp avatar kashike avatar kezz avatar lignium avatar lucko avatar machine-maker avatar parlough avatar portlek avatar renovate-bot avatar renovate[bot] avatar robertherhold avatar tehbrian avatar vaigarashi avatar zidane avatar zml2008 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

configurate's Issues

Implement fallback configs

The original HOCON Config class has a setFallback(Config config) method.
(This example is using the old Sponge ConfigFile class)

URL fallbackUrl = getClass().getClassLoader().getResource("FallbackInsideJar.conf");
ConfigFile config = ConfigFile.parseFile(configFile).withFallback(fallbackUrl);
config.save(true);

This is a really important feature. First of all, it simplifies the code that is needed to initialize the config.
It also simplifies config updates (new plugin version adds some new config nodes).

I found no way to replicate this behaviour with your HoconConfigurationLoader.

It is possible to initialize a config with a ressource from a jar (looks really ugly), but that doesn't fully replace the fallback method:

if (!configFile.exists()) 
{
    configFile.createNewFile();

    ConfigurationLoader initialConfigLoader = HoconConfigurationLoader.builder()
    .setSource(Resources.asCharSource(fallbackUrl, UTF8_CHARSET))
    .setSink(Files.asCharSink(configFile, UTF8_CHARSET)).build();

    initialConfigLoader.save(initialConfigLoader.load());
}

Merge and save an "empty" configuration

kashike | does configurate not save if all the values are empty? I'm merging a config that has "m{s = ["blah"]}", and saving, but it doesn't get saved
kashike | this an issue my side, or configurate/hocon?
    zml | that should work
    zml | works for PEX iirc
    zml | open an issue and I'll make a unit test for it

source config:

maps {
    source = [
    ]
}

on save, an empty file is generated

Annotation-based data object usage

Couple ways to do this:

  • Populate fields
public class MySuperCoolConfig {
    @Setting("config-key") public String key;
}
  • Construct interfaces
public interface MySuperCoolConfig { // Safer, but how would this affect creating setters and stuff?
    @Setting("config-key")
    public String key();
}

This might also require generating custom classes (or compile-time annotation processing?)

What of my existing work can be salvaged from libcomponents/flow-cerialization?

Exception when using using 3.0 hocon configuration loader

When trying to use the hocon configuration loader I get the following exception.

Caused by: java.lang.NoSuchMethodError: com.typesafe.config.impl.ConfigImpl.newSimpleOrigin(Ljava/lang/String;)Lcom/typesafe/config/ConfigOrigin;
    at com.typesafe.config.ConfigOriginFactory.newSimple(ConfigOriginFactory.java:42)
    at ninja.leaping.configurate.hocon.HoconConfigurationLoader.<clinit>(HoconConfigurationLoader.java:155)
    at net.catharos.commons.Configuration.<init>(Configuration.java:53)
    at net.catharos.commons.Configuration.<init>(Configuration.java:40)
    at net.catharos.commons.Settings.<init>(Settings.java:28)
    at net.catharos.client.ClientSettings.<init>(ClientSettings.java:22)
    ... 52 more

Thread-safety

Because plugin developers aren't smart enough to take care of this

Backslash in JSON Configuration File

Backslashes are only read by JSONConfigurationLoader if they are escaped in the file by using double backslashes. This is annoying for creating path configurations on any file system using \ as the file separator (most notably Windows)

@Setting annotation with no value or comment.

What is the expected behaviour when an @setting annotation has no value or comment?

I can't see a test case for this, and in addition SpongePowered/Sponge#115

https://github.com/SpongePowered/SpongeCommon/blob/ed5b96c03ad68bea48ecc604269fff549a63e1bf/src/main/java/org/spongepowered/common/configuration/SpongeConfig.java#L204

Sql settings arn't being generated, but the commands module is. The only difference between the two I can see is that the commands module has a comment.

Advanced config formatting options (HOCON)

There should be a way to control the output format of config files.

There are 2 types of "containers": Lists [1,2,3] and Maps {a=1,b=2}.
These containers should have an option to toggle between single-line output and multi-line output.

Right now this input

formattedMessage = [
    {text: "Please ", color: gold}, 
    {text: "/confirm", color: red, clickEvent: {action:run_command,value:"/confirm"}}, 
    {text: " or", color: gold}, 
    {text: "/deny", color: red, clickEvent: {action: run_command, value: "/deny"}}, 
    {text: " this action.", color: gold}
]

is formatted like this when saved to a file:

formattedMessage=[
    {
        color=gold
        text="Please "
    },
    {
        clickEvent {
            action="run_command"
            value="/confirm"
        }
        color=red
        text="/confirm"
    },
    {
        color=gold
        text=" or"
    },
    {
        clickEvent {
            action="run_command"
            value="/deny"
        }
        color=red
        text="/deny"
    },
    {
        color=gold
        text=" this action."
    }
]

Add a value processor for Settings

The loading right now doesn't necessarily let you control what to do when Configurate loads a value. As someone who strictly tries to idiot-proof anything the end-user can screw up, this makes having to verify values read from the configuration pretty tedious. Perhaps allowing to specify a Function to process the value beforehand can be added to the @Setting annotation? This will allow the developer to manipulate the value given by the mapper and perform actions warning the user should the returned value be invalid upon loading.

@Setting(value = "path.to.int", processor = new IntegerCheckProcessor(defaultValue))

bug in method caller: not valid to create ConfigObject from map with non-String key:

on attempting to set a nodes value as a HashMap<UUID, ArrayList<ClaimEntry>>
i have a serializer registered for ClaimEntry, and as UUID serializes to a string, shouldn't this work?

also when i change uuid to string and attempt i get the following [14:17:41] [Client thread/INFO]: [CHAT] Created claim at 27,129 to 143,143 [14:32:08] [Server thread/INFO]: [java.lang.Throwable$WrappedPrintStream:println:748]: com.typesafe.config.ConfigException$BugOrBroken: bug in method caller: not valid to create ConfigValue from: uk.co.haxyshideout.pixelmon.protection.ClaimEntry@624ae9a1 [14:32:08] [Server thread/INFO]: [java.lang.Throwable$WrappedPrintStream:println:748]: at com.typesafe.config.impl.ConfigImpl.fromAnyRef(ConfigImpl.java:275)

Heres the serializer, registered it with TypeSerializers.registerSerializer(new ClaimEntrySerializer());

http://pastebin.ubuntu.com/11788001/
http://pastebin.ubuntu.com/11787972/

Improve formatting (HOCON)

This input file:

# The Version of this config. This is a one-line comment.
version = 7

# The color of tomato
color = RED

# Time until server explodes
timeout = 30

# Name of the AI
ai-name = GLaDOS

generates this output:

# Name of the AI

ai-name=GLaDOS
# The color of tomato

color=RED
# Time until server explodes

timeout=30
# The Version of this config. This is a one-line comment.

version=7

First of all the order of the config nodes changes. I think that is not a good behaviour.
Also, the new lines separate the comments from the config nodes.

I would also prefer "x = y" instead of "x=y" for the separators

Make loaders more configurable

Currently the output generated by various loaders is not as configurable as would be desirable.

Probably the best way to implement this while maintaining the current immutability of the loader would be to start using a builder pattern for constructing loaders

Things that need to be configured

HOCON

  • expose Config(Parse|Render)Options directly

Yaml

  • indentation
  • flow/block style
  • quote everything?
  • DumperOptions? (snakeyaml kinda sucks though)

JSON

  • Indentation
  • prettyprint

Few issues with current setup

  1. Nodes are unable to retrieve parent. Adding a getParent() method would be useful.

  2. There is no way to create a SimpleCommentedConfigurationNode with a path, value, and comment in 1 line. Currently I have to create the node then call setComment on it.

  3. I do not see a way to retrieve the current path of a node. So if I do something like this

    ConfigurationNode node = this.config.getNode("general").getChild("config-enabled").setValue(true);
    

    I should be able to use node.getPath() which would return general.config-enabled

  4. Is it possible to pass a path and have nodes generated, if they do not exist, for the full path? so if I use the same example above but instead wrote it as

    ConfigurationNode node = this.config.getNode("general.config-enabled").setValue(true);
    

    The output would be

    general {
      config-enabled=true
    }
    
  5. Perhaps a getKey() method? which would return the name of the current node. Using the same example as above

    node.getKey() would return "config-enabled"
    node.getPath() would return "general.config-enabled"
    node.getValue() would return "true"

  6. Retrieving a child node that contains a value which is not a map or list always creates a new node object

    rootNode.getNode(key).getChild(childKey)
    

    Example above if called twice will return 2 different objects.

Adding a comment to a node key not working properly

I am unable to do the following

# some comment
entity-activation-range {
   enabled=true
}

If I attempt to generate that, I end up with

entity-activation-range=null

However, setting comments to entries within a node is fine. For example, this works fine

entity-activation-range {
   # some comment
   enabled=true
}

Call to disable alphabetical order.

If I want my config to look like this:
version="0.3"
node1 = "banana"
aForApple="yes"
I can't because nodes are locked in alphabetical order. If I could disable that, I could get that outcome.

ConfigurationNode#mergeValuesFrom(ConfigurationNode other) and comments

Unfortunately when using ConfigurationNode#mergeValuesFrom(ConfigurationNode other) the comments are not properly merged.

Is this a bug, or simply by design?

Example config file:

# Cortex Configuration
# -----------------------
# Author - Logan Speck (Wingz/varrix)
# Contact - Twitter: @itswingz | Sponge: wingz
# Libraries - PaginatedLists by mmonkey (https://forums.spongepowered.org/t/paginated-lists-a-library-for-plugin-developers/6964)
# Description - Cortex is simply the Sponge equivalent of Bukkit's /plugins.
#               It displays all mods and their metadata. A light-weight yet featureful plugin.


# Variable Legend
# -----------------------
# ${<COLOR/STYLE>} - this allows you to specify any color or style, example: "${RED}Red text!" You can also
#                    use number-codes if you would like using the same format as declaration (-> ${6}Gold text!)
# ${containerId} - displays the id the mod has specified
# ${containerName} - displays the name the mod has specified
# ${containerVersion} - displays the version the mod has specified.
# ${dynamicVersionFormat}
# ${blankChatBox} - displays a completely empty chat box.


# Logger Properties
# -----------------------
logger {
  # Level (Source: http://www.slf4j.org/api/org/apache/log4j/Level.html)
  # ALL - The ALL has the lowest possible rank and is intended to turn on all logging.
  # DEBUG - The DEBUG Level designates fine-grained informational events that are most useful to debug an application.
  # ERROR - The ERROR level designates error events that might still allow the application to continue running.
  # FATAL - The FATAL level designates very severe error events that will presumably lead the application to abort.
  # INFO - The INFO level designates informational messages that highlight the progress of the application at coarse-grained level.
  # OFF - The OFF has the highest possible rank and is intended to turn off logging.
  # TRACE - The TRACE Level designates finer-grained informational events than the DEBUG
  # WARN - The WARN level designates potentially harmful situations.
  level = "ALL"
}


# Command Settings
# -----------------------
commands {
  state {
    # /cortex <help,version,about,author>
    cortex = false
    # /cortex -m <check,set,add,remove,help>
    cortexManagement = false
    plugins = true
    mods = true
    components = true
  }

  # false - /mods, /plugins, and /components will display the same thing
  # true - all commands will display specifically what they're named for (components is mixed)
  separate = true
}


# Storage Settings
# -----------------------
storage {
  # Keeps all data in-memory and will not write any changes.
  temporary = false
  # The type of storage to use.
  # Supported Types: MySQL, HOCON
  type = "hocon"

  # HOCON
  hocon {
    # Storage strategy to use with user data.
    # Supported Strategies: simple, separate, scalable
    userDataStorageStrategy = "super"
  }
}


# Database
# -----------------------
database {
  ## MySQL Database ##
  # More settings to come...
  mySQL {
    url = ""
    user = "user"
    pass = "pass"
  }
}


# Viewing Rules
# -----------------------
# secret - the mod will be represented with question marks.
# disclosed - the mod will be fully disclosed.
# restricted - the mod will not be shown.


# Permissions Note
# -----------------------
# Alternatively you could simply use permissions.
# Permissions: all = "modtracker.super"
#              specific = "modtracker.<mod-id>.<viewing-rule>" (example: "modtracker.modtracker.restricted")

data {
  # Universal Data
  universal {
    # This mod is restricted from viewing for all players (unless that player has a specified view below that overrides this)
    cortex = "restricted"
  }


  # IP Data
  # This whole node is removable when not using HOCON and not using userDataStorageStrategy "super".
  ips {
    # Randomly generated IP (may be in use)
    "217.30.124.171" {
      cortex {
        rule = "secret"

        # Watchdog rules:
        # ALL/* - Any and all changes/queries will be reported.
        # MUTATION - Any changes will be reported.
        # QUERY - Any queries will be reported.

        # An array of Strings that can either be IPs or UUIDs.
        # These elements will each be a pair of "who" (ip/uuid) and "what" (watchdog rules) separated by colones which
        # is then concatenated into a single String separating the "who" and "what" by comma.
        # EXAMPLE: "c0fbf1c17b614fb28d679fa079f0c48e,MUTATION:QUERY"
        watchdog = []
      }
    }
  }


  # User Data
  # This whole node is removable when not using HOCON and not using userDataStorageStrategy "super".
  users {
    c0fbf1c17b614fb28d679fa079f0c48e {
      # Can see cortex as `???` because this overrides the `universal` settings.
      cortex = "secret"
    }

    c3fed4d91c024fb89bf1cb0166aa9104 {
      # Can see cortex properly as this overrides the `universal` settings.
      cortex = "disclosed"
    }
  }
}

Output from mergValuesFrom(...):

# Command Settings
# -----------------------
# 
commands {
    separate=true
    state {
        components=true
        cortex=false
        cortexManagement=false
        mods=true
        plugins=true
    }
}
data {
    ips {
        "217.30.124.171" {
            cortex {
                rule=secret
                watchdog=null
            }
        }
    }
    universal {
        cortex=restricted
    }
    users {
        c0fbf1c17b614fb28d679fa079f0c48e {
            cortex=secret
        }
        c3fed4d91c024fb89bf1cb0166aa9104 {
            cortex=disclosed
        }
    }
}
# Database
# -----------------------
# 
database {
    mySQL {
        pass=pass
        url=""
        user=user
    }
}
# Logger Properties
# -----------------------
# 
logger {
    level=ALL
}
# Storage Settings
# -----------------------
# 
storage {
    hocon {
        userDataStorageStrategy=super
    }
    temporary=false
    type=hocon
}

Automatically create file when saving

Right now it is necessary to manually create the output file when saving a HOCON config:

ConfigurationLoader configLoader = HoconConfigurationLoader.builder().setFile(outputFile).build();
if (!outputFile.exists()) outputFile.createNewFile();
configLoader.save(node);

The creation of the file should be a part of the save method.

Intended behaviour?

The following code produces this config file when ran without a existing config file,
as im defining a default value for the boolean in the getBoolean method,
shouldn't wildCanFlee be set to this default value when saved?

# General settings for the world
general {
    # Wild Pokemon can try and flee from battles
    wildCanFlee=null
}
        HoconConfigurationLoader configurationLoader = HoconConfigurationLoader.builder().setFile(new File("newpixelmonconfig.hocon")).build();
        CommentedConfigurationNode mainNode = configurationLoader.load();

        CommentedConfigurationNode generalNode = mainNode.getNode("general");
        generalNode.setComment("General settings for the world");
        allowWildPokemonFleeing = generalNode.getNode("wildCanFlee").setComment("Wild Pokemon can try and flee from battles").getBoolean(false);

        configurationLoader.save(mainNode);

Also is there a way to make configurate not sort the map before writing?, alphabetical order kinda ruins internal ordering

Calling same code fails first time.

calling this code will fail the first time with a error while getting the uuidNode,
the second time it is run, it saves fine

    public void saveClaims() {

        try {
            CommentedConfigurationNode mainNode = MainMod.goldenShovelConfig.load();
            CommentedConfigurationNode claimsNode = mainNode.getNode("Claims");

            for(HashMap.Entry<UUID, ArrayList<ClaimEntry>> uuidEntry : claimEntries.entrySet()) {
                CommentedConfigurationNode uuidNode = claimsNode.getNode(uuidEntry.getKey().toString());
                ArrayList<HashMap<String,Object>> regionDatas = new ArrayList<>();
                for(ClaimEntry claimEntry : uuidEntry.getValue()) {
                    HashMap<String, Object> claimHashMap = new HashMap<>();
                    claimHashMap.put("data",claimEntry.getData());
                    regionDatas.add(claimHashMap);
                }
                uuidNode.setValue(regionDatas);
            }


            MainMod.goldenShovelConfig.save(mainNode);
        } catch (Exception e) {
            claimEntries.clear();
            e.printStackTrace();
        }

    }
[19:29:45] [Server thread/INFO]: [java.lang.Throwable$WrappedPrintStream:println:748]: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.UUID
[19:29:45] [Server thread/INFO]: [java.lang.Throwable$WrappedPrintStream:println:748]:  at uk.co.haxyshideout.pixelmon.protection.GoldenShovelStore.saveClaims(GoldenShovelStore.java:62)
[19:29:45] [Server thread/INFO]: [java.lang.Throwable$WrappedPrintStream:println:748]:  at uk.co.haxyshideout.pixelmon.protection.GoldenShovelStore.createClaim(GoldenShovelStore.java:110)
[19:29:45] [Server thread/INFO]: [java.lang.Throwable$WrappedPrintStream:println:748]:  at uk.co.haxyshideout.pixelmon.protection.GoldenShovelStore.createClaim(GoldenShovelStore.java:103)
[19:29:45] [Server thread/INFO]: [java.lang.Throwable$WrappedPrintStream:println:748]:  at uk.co.haxyshideout.pixelmon.protection.GoldenShovelStore.createChestClaim(GoldenShovelStore.java:97)
[19:29:45] [Server thread/INFO]: [java.lang.Throwable$WrappedPrintStream:println:748]:  at uk.co.haxyshideout.pixelmon.eventhandlers.GoldenShovelHandler.onChestPlacement(GoldenShovelHandler.java:25)

Mapping not working for objects annotated with ConfigSerializeable

This is my config object:

public class DaemonConfig extends HoconConfig {
    @Getter
    @Setting(value = "mongo")
    private MongoCredentials mongoCredentials;
    @Getter
    @Setting(value = "redis")
    private RedisCredentials redisCredentials;
    @Getter @Setter
    @Setting(value = "node-name", comment = "The name of this node.")
    private String nodeName = "minecloud.node.one";
    @Getter @Setter
    @Setting(value = "first-run", comment = "Run daemon configuration if true.")
    private boolean firstRun = true;

    @ConfigSerializable
    public class MongoCredentials {
        @Getter @Setter
        @Setting(value = "host", comment = "The hostname/ip of the mongodb node.")
        private String mongoHost = "localhost";
        @Getter @Setter
        @Setting(value = "port", comment = "The port mongodb runs on.")
        private int mongoPort = 27017;
        @Getter @Setter
        @Setting(value = "database", comment = "The database minecloud should use.")
        private String mongoDatabase = "minecloud";
        @Getter @Setter
        @Setting(value = "username", comment = "Optional username to use when connecting to mongodb.")
        private String mongoUsername = "";
        @Getter @Setter
        @Setting(value = "password", comment = "Optional password to use when connecting to mongodb.")
        private String mongoPassword = "";
    }

    @ConfigSerializable
    public class RedisCredentials {
        @Getter @Setter
        @Setting(value = "host", comment = "The hostname/ip of the redis node.")
        private String redisHost = "localhost";
        @Getter @Setter
        @Setting(value = "port", comment = "The port redis runs on.")
        private int redisPort = 6379;
        @Getter @Setter
        @Setting(value = "username", comment = "Optional username to use when connecting to redis.")
        private String redisUsername = "";
        @Getter @Setter
        @Setting(value = "password", comment = "Optional password to use when connecting to redis.")
        private String redisPassword = "";
    }
}

Output:

# Run daemon configuration if true.
first-run=true
# The name of this node.
node-name="minecloud.node.one"

Utility class for handling mapping:

public class HoconConfig {
    private transient HoconConfigurationLoader loader;
    private transient ObjectMapper<? extends HoconConfig>.BoundInstance boundInstance;
    private transient ConfigurationNode node;

    /**
     * Loads a config from file and maps it to an object
     * of the specified class.
     *
     * @param clazz The class to map.
     * @param file The file to read/write from/to.
     * @param <T> The type to return as.
     * @return Object of type T
     */
    public static <T extends  HoconConfig> T load(Class<T> clazz, File file) {
        Objects.requireNonNull(clazz, "Config clazz cannot be null.");
        Objects.requireNonNull(file, "Config file cannot be null.");

        ObjectMapper<T> mapper = null;

        try {
            mapper = ObjectMapper.forClass(clazz);

            if (mapper != null) {
                HoconConfigurationLoader.Builder builder = HoconConfigurationLoader.builder().setFile(file);
                HoconConfigurationLoader loader = builder.build();
                ConfigurationNode node = loader.load();

                ObjectMapper<T>.BoundInstance boundInstance = mapper.bindToNew();
                T instance = boundInstance.populate(node);

                if (!file.exists()) {
                    if (!file.getParentFile().exists()) {
                        file.mkdirs();
                    }

                    file.createNewFile();
                    loader = builder.setFile(file).build();
                }

                instance.init(loader, node, boundInstance);
                instance.save();

                return instance;
            }
        } catch (ObjectMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public void load() {
        if (node != null && boundInstance != null) {
            try {
                boundInstance.populate(node);
            } catch (ObjectMappingException e) {
                e.printStackTrace();
            }
        }
    }

    public void save() {
        if (loader != null && node != null) {
            try {
                boundInstance.serialize(node);
                loader.save(node);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ObjectMappingException e) {
                e.printStackTrace();
            }
        }
    }

    protected void init(HoconConfigurationLoader loader, ConfigurationNode node, ObjectMapper.BoundInstance boundInstance) {
        this.loader = loader;
        this.node = node;
        this.boundInstance = boundInstance;

        load();
    }
}

ConfigurationOption acceptsType losing information somewhere

For context, I am adding an accepted type, which is BlockState.

To verify this has been added, I call..

        if(!configurationOptions.acceptsType(BlockTypes.AIR.getDefaultState().getClass()))
            throw new RuntimeException();

This runs fine with no error.

After calling this however,

config = configManager.load(CraftBookPlugin.<CraftBookPlugin>inst().configurationOptions);

if(!config.getNode("anything").getOptions().acceptsType(BlockTypes.AIR.getDefaultState().getClass()))
            throw new RuntimeException();

This will now throw the exception.

Lazy calculation of default values

Proposal: for the non-primitive getters (getValue(), getValue(Function<Object,T>) and getValue(TypeToken<T>) add another overload accepting a Supplier<T> that will be called if and only if a default value is required.

Use case is any case where calculation of the default value is costly and should only occur if necessary.

Comments with multiple lines

It should be possible to add multiline comments for detailed descriptions. To add this feature, the CommentedCOnfigurationNode should be modified:

public List<String> getComments();
public CommentedConfigurationNode setComments(String ... comment);

Example config:

# ConfigurateTest Config File
# ---------------------------
#
# This is a summary of this file.
# The summary has multiple lines. And empty lines:
#
# (c) boformer 2015 
{
    # The Version of this config. This is a one-line comment.
    version = 7

    # Some config values are complex and need a multiline description.
    # Possible Values: RED, GREEN, BLUE, YELLOW, BLACK
    color = RED

    # Time until server explodes
    timeout = 30

    # Name of the AI
    ai-name = GLaDOS
}

Missing TypeSerializer for char

I get NPEs if I want to use char types with the ObjectMapper.

Stacktrace:

java.lang.NullPointerException
        at ninja.leaping.configurate.objectmapping.ObjectMapper$FieldData.serializeTo(ObjectMapper.java:105) ~[ObjectMapper$FieldData.class:1.8-1577-3.1.0-BETA-1024]
        at ninja.leaping.configurate.objectmapping.ObjectMapper$FieldData.deserializeFrom(ObjectMapper.java:87) ~[ObjectMapper$FieldData.class:1.8-1577-3.1.0-BETA-1024]
        at ninja.leaping.configurate.objectmapping.ObjectMapper$BoundInstance.populate(ObjectMapper.java:140) ~[ObjectMapper$BoundInstance.class:1.8-1577-3.1.0-BETA-1024]
        at com.github.games647.healthname.config.Settings.load(Settings.java:55) ~[Settings.class:?]
        at com.github.games647.healthname.HealthName.onPreInit(HealthName.java:60) ~[HealthName.class:?]
        at org.spongepowered.common.event.listener.GamePreInitializationEventListener_HealthName_onPreInit4.handle(Unknown Source) ~[?:?]
        at org.spongepowered.common.event.RegisteredListener.handle(RegisteredListener.java:86) ~[RegisteredListener.class:1.8-1577-3.1.0-BETA-1024]

The code I used:
Config object
Loader
When I tried to change the char to a String, it works fine without any exceptions.

NoClassDefFoundError when using configurate

Hello, I am using your configurate library to make a Sponge plugin. I wanted to use YAML so I added the dependency to my pom.xml. I have no errors in Eclipse, but when I run my Sponge plugin I get a NoClassDefFoundError on the YAML classes. Any ideas how to fix tihs?

Add in all the basic types

  • String
  • Boolean
  • int
  • long
  • float
  • double
  • function-defined (be ready for java 8, yeah?)
  • list of the above

These are nice to have when working with configs

Add URI mapper

Most configurations will have a URI somewhere. It would be nice to have one built in to the library.

Unable to use the same key within a node

As title states, I am unable to have multiple keys with the same name within a node structure. So for example

entity-activation-range {
}
modules {
    entity-activation-range=true
}

I cannot get this to work. The modules entry overrides the first causing it to show up as

entity-activation-range=null

Option to set value to default if absent

Currently if a value is null and a default is provided, the default will just be returned be returned. Having an option to also set the value to the default would be nice. This would allow the first save to save all the defaults to disk.

Issue loading configuration file from within Jar

The current contents of the config.conf file:

config {
  testing=true
  testingAgain=true
  testingInt=2424
  testingString=lolhi
}

Now, using the code below:

BufferedReader br = new BufferedReader(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("config.conf")));
String line = null;
try {
    while ((line = br.readLine()) != null) {
        this.logger.warn(line);
    }
    this.logger.warn("END OF FILE");
} catch (IOException e) {
    e.printStackTrace();
}

I get the output of:

[02:42:18] [Server thread/WARN] [voxelwars]: config {
[02:42:18] [Server thread/WARN] [voxelwars]:   testing=true
[02:42:18] [Server thread/WARN] [voxelwars]:   testingAgain=true
[02:42:18] [Server thread/WARN] [voxelwars]:   testingInt=2424
[02:42:18] [Server thread/WARN] [voxelwars]:   testingString=lolhi
[02:42:18] [Server thread/WARN] [voxelwars]: }
[02:42:18] [Server thread/WARN] [voxelwars]: END OF FILE

However, while the above file-loading method seems to work, I run into issues attempting to do the same thing with Configurate.

The Gist of my Config.java class

Using the below code for testing (similar to the above):

        Config config = new Config("config.conf");

        this.logger.warn("Testing " + config.get(ConfigPath.TESTING).getBoolean());
        this.logger.warn("TestingAgain " + config.get(ConfigPath.TESTING_AGAIN).getBoolean());
        this.logger.warn("TestingInt " + config.get(ConfigPath.TESTING_INT).getInt());
        this.logger.warn("TestingString " + config.get(ConfigPath.TESTING_STRING).getString());

        config.set(ConfigPath.NEW_VALUE, "Yup.");
        this.logger.warn("NewValue " + config.get(ConfigPath.NEW_VALUE).getString());

        config.set(ConfigPath.TESTING_STRING, "Testing Overriding Existing String");
        this.logger.warn("TestingString " + config.get(ConfigPath.TESTING_STRING).getString());

I get the following output:

[02:42:18] [Server thread/WARN] [voxelwars]: Testing false
[02:42:18] [Server thread/WARN] [voxelwars]: TestingAgain false
[02:42:18] [Server thread/WARN] [voxelwars]: TestingInt 0
[02:42:18] [Server thread/WARN] [voxelwars]: TestingString null
[02:42:18] [Server thread/WARN] [voxelwars]: NewValue Yup.
[02:42:18] [Server thread/WARN] [voxelwars]: TestingString Testing Overriding Existing String

Now, considering that everyone else seems to have no issues in this regard, I'm fairly confident the issue lies within my own usage, but I can't for the life of me figure out WHAT I'm doing wrong.

I would assume that it lies between the difference of how, exactly, I'm casting the object. In the first method, I load is as a stream. Whereas, in the second method, I load it was a URL. However, this concession was necessary, as Configurate does not (currently) have an InputStream alternative.

Any assistance I could receive on how to make this work would be very much so appreciated. :)

Config transformation framework

For easy transformation of configuration schemas, a migration framework like used in CommandBook would be useful to implement. There are probably changes that need to be made to accommodate the fact that we exclusively use Object[] paths rather than the strings with path separator characters of previous config library iterations, but these things have been useful in the past

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.