Carleslc / Simple-YAML

This Java API provides an easy-to-use way to store data and provide configurations using the YAML format.
https://carleslc.me/Simple-YAML
GNU General Public License v3.0
130 stars 38 forks source link

ConfigurationSection#addDefault changes values if present #75

Closed ItsRainingHP closed 1 year ago

ItsRainingHP commented 1 year ago

As title states. Add default changes the values that are present. After changing them and initializing again the values are changed back to default.

image image

ItsRainingHP commented 1 year ago

I figured out my issue! I was creating ConfigurationSections which I guess overwrites all currently set Configuration Subkeys. I ended up using the following fix. You are free to add it to your API should you choose:

    public static ConfigurationSection createOrGetSection(@NotNull YamlFile yamlFile, String path) {
        if (yamlFile.isConfigurationSection(path)) {
            return yamlFile.getConfigurationSection(path);
        } else {
            return yamlFile.createSection(path);
        }
    }
Carleslc commented 1 year ago

Yes, creating a new section will set a new empty section for that key, so if the key (in this case "Database") already existed then after creating a new section it is like it has no values anymore because previous values are removed, therefore defaults are filled, overwriting anything previously existed. Creating sections is only for new sections, or to replace older sections.

That being said, you don't need to create sections manually in this case.

Apart from your solution, you have two alternatives for having your code working without creating sections manually:

Use full paths, like this:

yamlFile.setComment("Database.Type", "Database type [MySQL, Postgres, H2]");
yamlFile.addDefault("Database.Type", "H2");

yamlFile.setComment("Database.Address", "IP for database");
yamlFile.addDefault("Database.Address", "127.0.0.1");

yamlFile.setComment("Database.Port", "Port to database");
yamlFile.addDefault("Database.Port", "3366");

yamlFile.setComment("Database.Name", "Database Name");
yamlFile.addDefault("Database.Name", "database");

yamlFile.setComment("Database.Username", "DB User Login");
yamlFile.addDefault("Database.Username", "username");

yamlFile.setComment("Database.Password", "DB Password Login");
yamlFile.addDefault("Database.Password", "password");

yamlFile.setComment("Database.UseSSL", "Use SSL");
yamlFile.addDefault("Database.UseSSL", false);

yamlFile.setComment("Database.AllowPublicKeyRetrieval", "Allow public keys");
yamlFile.addDefault("Database.AllowPublicKeyRetrieval", false);

This works because sections are created and managed automatically as needed.

However, I guess you were creating the section because you don't want to write "Database." prefix for all subkeys, which is understandable, and there's already a pattern for this, using the yamlFile.path builder pattern, like this:

yamlFile.path("Database")
            .path("Type")
            .comment("Database type [MySQL, Postgres, H2]")
            .addDefault("H2")
        .parent()
            .path("Address")
            .comment("IP for database")
            .addDefault("127.0.0.1")
        .parent()
            .path("Port")
            .comment("Port to database")
            .addDefault("3366")
        .parent()
            .path("Name")
            .comment("Database Name")
            .addDefault("database")
        .parent()
            .path("Username")
            .comment("DB User Login")
            .addDefault("username")
        .parent()
            .path("Password")
            .comment("DB Password Login")
            .addDefault("password")
        .parent()
            .path("UseSSL")
            .comment("Use SSL")
            .addDefault(false)
        .parent()
            .path("AllowPublicKeyRetrieval")
            .comment("Allow public keys")
            .addDefault(false);

With this, you can add defaults and their comments without repeating keys, and you also don't need to manually manage sections.

If you don't like the builder pattern all in one sentence you can also split it like this:

YamlFile yamlFile = new YamlFile("issue75.yml");

yamlFile.createOrLoadWithComments();

YamlFileWrapper database = yamlFile.path("Database");

database.path("Type")
        .comment("Database type [MySQL, Postgres, H2]")
        .addDefault("H2");

database.path("Address")
        .comment("IP for database")
        .addDefault("127.0.0.1");

database.path("Port")
        .comment("Port to database")
        .addDefault("3366");

database.path("Name")
        .comment("Database Name")
        .addDefault("database");

database.path("Username")
        .comment("DB User Login")
        .addDefault("username");

database.path("Password")
        .comment("DB Password Login")
        .addDefault("password");

database.path("UseSSL")
        .comment("Use SSL")
        .addDefault(false);

database.path("AllowPublicKeyRetrieval")
        .comment("Allow public keys")
        .addDefault(false);

yamlFile.save();

The approach to use is up to your preferences.