Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

String List placement inside yaml #78

Open
ItsRainingHP opened this issue Jul 13, 2023 · 10 comments
Open

String List placement inside yaml #78

ItsRainingHP opened this issue Jul 13, 2023 · 10 comments

Comments

@ItsRainingHP
Copy link

ItsRainingHP commented Jul 13, 2023

Using a List of characters results in a YAML does not make sense and is not working.

I will edit and place code if you need me to though its very basic.

Code:

image

Mixed Results:

Worked for some reason -
image
Did not work at all -
image

@Carleslc
Copy link
Owner

I cannot reproduce it. This is my working code:

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

yamlFile.createOrLoadWithComments();

// Comment format

String lineDecorator = StringUtils.padding(30, '-'); // "-".repeat(30) with Java 11+

YamlCommentFormatter commentFormatter = yamlFile.options().commentFormatter();

commentFormatter.blockFormatter()
        .prefix("#" + lineDecorator + "#\n# ", YamlCommentFormatterConfiguration.DEFAULT_COMMENT_PREFIX)
        .suffix("\n#" + lineDecorator + "#");

// WebLore

ArrayList<String> webLore = new ArrayList<>();

webLore.add("Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful " +
        "perks and commands to use. The path to the top has many different options and requirements.");
webLore.add("One could be a crafter, building vast kingdoms and controlling many different animals. " +
        "Alternatively, one could decide to pursue the path of darkness. " +
        "Murdering players and bosses alike as they continue the path of becoming the strongest.");
webLore.add("However, to be considered the pinnacle of strength in mind and body alike, " +
        "one must walk every path; obtaining glory in both crafting and combat and " +
        "claiming a seat among the Overlords.");

yamlFile.setComment("WebLore", "WebLore\nLore in the Web GUI");
yamlFile.set("WebLore", webLore);

// Save

yamlFile.save();

// Output

System.out.println("WebLore");
System.out.println(String.join("\n", yamlFile.getStringList("WebLore")));

I've included an example for your comment format configuration.
I've excluded imports and exception handling.

Output

WebLore
Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful perks and commands to use. The path to the top has many different options and requirements.
One could be a crafter, building vast kingdoms and controlling many different animals. Alternatively, one could decide to pursue the path of darkness. Murdering players and bosses alike as they continue the path of becoming the strongest.
However, to be considered the pinnacle of strength in mind and body alike, one must walk every path; obtaining glory in both crafting and combat and claiming a seat among the Overlords.

issue78.yml

#------------------------------#
# WebLore
# Lore in the Web GUI
#------------------------------#
WebLore:
  - Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful
    perks and commands to use. The path to the top has many different options and
    requirements.
  - One could be a crafter, building vast kingdoms and controlling many different
    animals. Alternatively, one could decide to pursue the path of darkness. Murdering
    players and bosses alike as they continue the path of becoming the strongest.
  - However, to be considered the pinnacle of strength in mind and body alike, one
    must walk every path; obtaining glory in both crafting and combat and claiming
    a seat among the Overlords.

In addition, you can also try to disable splitting lines, maybe that's causing problems with your code:

// ...
// yamlFile.createOrLoadWithComments();

// Disable split lines

DumperOptions yamlOptions = ((SimpleYamlImplementation) yamlFile.getImplementation()).getDumperOptions();

yamlOptions.setSplitLines(false);

// ...

issue78.yml setSplitLines(false)

#------------------------------#
# WebLore
# Lore in the Web GUI
#------------------------------#
WebLore:
  - Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful perks and commands to use. The path to the top has many different options and requirements.
  - One could be a crafter, building vast kingdoms and controlling many different animals. Alternatively, one could decide to pursue the path of darkness. Murdering players and bosses alike as they continue the path of becoming the strongest.
  - However, to be considered the pinnacle of strength in mind and body alike, one must walk every path; obtaining glory in both crafting and combat and claiming a seat among the Overlords.

@Carleslc
Copy link
Owner

Also, why do you want to use a list of strings for that? That seems a block of text description, for that you can use a string literal:

// WebLore Literal

String webLoreString = "Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful " +
        "perks and commands to use. The path to the top has many different options and requirements.\n" +
        "One could be a crafter, building vast kingdoms and controlling many different animals. " +
        "Alternatively, one could decide to pursue the path of darkness. " +
        "Murdering players and bosses alike as they continue the path of becoming the strongest.\n" +
        "However, to be considered the pinnacle of strength in mind and body alike, " +
        "one must walk every path; obtaining glory in both crafting and combat and " +
        "claiming a seat among the Overlords.";

yamlFile.path("WebLoreLiteral")
        .comment("WebLore\nLore in the Web GUI")
        .set(webLoreString, QuoteStyle.LITERAL);

// Save

yamlFile.save();

// Output

System.out.println("WebLoreLiteral");
System.out.println(yamlFile.getString("WebLoreLiteral"));

Instead of string concatenation, if you use Java 15+ you can also use text blocks to improve the code readability of large string blocks.

Note that using yamlFile.path is an alternative to yamlFile.set and yamlFile.setComment to avoid writing the same key multiple times.

Output

WebLoreLiteral
Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful perks and commands to use. The path to the top has many different options and requirements.
One could be a crafter, building vast kingdoms and controlling many different animals. Alternatively, one could decide to pursue the path of darkness. Murdering players and bosses alike as they continue the path of becoming the strongest.
However, to be considered the pinnacle of strength in mind and body alike, one must walk every path; obtaining glory in both crafting and combat and claiming a seat among the Overlords.

issue78.yml (Literal String)

#--------------------#
# WebLore
# Lore in the Web GUI
#--------------------#
WebLoreLiteral: |-
  Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful perks and commands to use. The path to the top has many different options and requirements.
  One could be a crafter, building vast kingdoms and controlling many different animals. Alternatively, one could decide to pursue the path of darkness. Murdering players and bosses alike as they continue the path of becoming the strongest.
  However, to be considered the pinnacle of strength in mind and body alike, one must walk every path; obtaining glory in both crafting and combat and claiming a seat among the Overlords.

@ItsRainingHP
Copy link
Author

ItsRainingHP commented Jul 13, 2023

I will try splitting the lines. the webLore list prints out just fine for me, its the placement when writing to default that is giving mixed results.

I need the values to be a List of Strings. I do not want to use a literal because I do not want to have to split the String after reading the value in. Additionally, users easily understand how to create a list of Strings.

@ItsRainingHP
Copy link
Author

This fixed the issue thank you!

DumperOptions yamlOptions = ((SimpleYamlImplementation) yamlFile.getImplementation()).getDumperOptions();

yamlOptions.setSplitLines(false);

@ItsRainingHP
Copy link
Author

ItsRainingHP commented Jul 19, 2023

I was wrong. I still have an issue where its using a |- for the String list. This results in failing to read the list in. Is it possible for force the the yaml file to only use the array or list formatting? So that it only uses the following:

Option:
  - item1
  - item2
  - item3

or

Option: [item1, item2, item3]

@ItsRainingHP ItsRainingHP reopened this Jul 19, 2023
@Carleslc
Copy link
Owner

Carleslc commented Jul 19, 2023

There is no configuration option for that. You may do it with a custom representer (see the comment below), but first, we would need to know where the problem is, if it's something with your code, with Simple-YAML or with the snakeyaml implementation.
For that, you need to provide a minimal code to reproduce your issue.

As I said, I can't reproduce the issue, this code similar to the one provided before is working for me:

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

yamlFile.createOrLoadWithComments();

// Disable split lines

DumperOptions yamlOptions = ((SimpleYamlImplementation) yamlFile.getImplementation()).getDumperOptions();

yamlOptions.setSplitLines(false);

// Comment format

String lineDecorator = StringUtils.padding(30, '-'); // "-".repeat(30) with Java 11+

YamlCommentFormatter commentFormatter = yamlFile.options().commentFormatter();

commentFormatter.blockFormatter()
        .prefix("#" + lineDecorator + "#\n# ", YamlCommentFormatterConfiguration.DEFAULT_COMMENT_PREFIX)
        .suffix("\n#" + lineDecorator + "#");

// WebLore

ArrayList<String> webLore = new ArrayList<>();

webLore.add("Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful " +
        "perks and commands to use. The path to the top has many different options and requirements.");
webLore.add("One could be a crafter, building vast kingdoms and controlling many different animals. " +
        "Alternatively, one could decide to pursue the path of darkness. " +
        "Murdering players and bosses alike as they continue the path of becoming the strongest.");
webLore.add("However, to be considered the pinnacle of strength in mind and body alike, " +
        "one must walk every path; obtaining glory in both crafting and combat and " +
        "claiming a seat among the Overlords.");

yamlFile.setComment("WebLore", "WebLore\nLore in the Web GUI");
yamlFile.set("WebLore", webLore);

// Save

yamlFile.save();
yamlFile.load(); // unnecessary, but to reset the memory values and load them again from file to check if it's reading it properly

// Output

System.out.println("WebLore");
System.out.println(String.join("\n", yamlFile.getStringList("WebLore")));

issue78.yml

#------------------------------#
# WebLore
# Lore in the Web GUI
#------------------------------#
WebLore:
  - Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful perks and commands to use. The path to the top has many different options and requirements.
  - One could be a crafter, building vast kingdoms and controlling many different animals. Alternatively, one could decide to pursue the path of darkness. Murdering players and bosses alike as they continue the path of becoming the strongest.
  - However, to be considered the pinnacle of strength in mind and body alike, one must walk every path; obtaining glory in both crafting and combat and claiming a seat among the Overlords.

Try that code to see if it is working for you.

Also, if you change yamlFile.set("WebLore", webLore); to yamlFile.set("WebLore", webLore, QuoteStyle.LITERAL); then you would get a literal list, with each list element as a string literal:

#------------------------------#
# WebLore
# Lore in the Web GUI
#------------------------------#
WebLore:
  - |-
    Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful perks and commands to use. The path to the top has many different options and requirements.
  - |-
    One could be a crafter, building vast kingdoms and controlling many different animals. Alternatively, one could decide to pursue the path of darkness. Murdering players and bosses alike as they continue the path of becoming the strongest.
  - |-
    However, to be considered the pinnacle of strength in mind and body alike, one must walk every path; obtaining glory in both crafting and combat and claiming a seat among the Overlords.

This still works, it's a list.
But if you're getting |- in the whole value then it's treating it as a string, not a list.

@Carleslc
Copy link
Owner

As a reference, if you would like to use the array flow style for lists, this is how you can do it with a custom representer:

First, create a CustomYamlConfiguration class that inherits SimpleYamlImplementation. Here you can add your custom configurations so that doesn't bloat your main code.

import org.simpleyaml.configuration.comments.format.YamlCommentFormatter;
import org.simpleyaml.configuration.comments.format.YamlCommentFormatterConfiguration;
import org.simpleyaml.configuration.file.YamlConfigurationOptions;
import org.simpleyaml.configuration.implementation.SimpleYamlImplementation;
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
import org.simpleyaml.utils.StringUtils;

public class CustomYamlConfiguration extends SimpleYamlImplementation {

    public CustomYamlConfiguration() {
        // Set custom representer
        super(new CustomListRepresenter(new DumperOptions()));
    }

    @Override
    public void configure(YamlConfigurationOptions options) {
        // Apply default configurations first
        super.configure(options);

        // Comment format
        String lineDecorator = StringUtils.padding(30, '-'); // "-".repeat(30) with Java 11+

        YamlCommentFormatter commentFormatter = options.commentFormatter();

        commentFormatter.blockFormatter()
                .prefix("#" + lineDecorator + "#\n# ", YamlCommentFormatterConfiguration.DEFAULT_COMMENT_PREFIX)
                .suffix("\n#" + lineDecorator + "#");

        // Disable split lines
        DumperOptions yamlOptions = getDumperOptions();

        yamlOptions.setSplitLines(false);
    }
}

I've moved the comment formatting and disabling split lines to the configure method.

In the constructor of this configuration, you would pass a custom representer that inherits SnakeYamlRepresenter. In this case, I named that class CustomListRepresenter. This custom representer will force the flow style for lists:

import org.simpleyaml.configuration.implementation.snakeyaml.SnakeYamlRepresenter;
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
import org.simpleyaml.configuration.implementation.snakeyaml.lib.nodes.Node;
import org.simpleyaml.configuration.implementation.snakeyaml.lib.nodes.Tag;

import java.util.ArrayList;
import java.util.List;

public class CustomListRepresenter extends SnakeYamlRepresenter {

    public CustomListRepresenter(DumperOptions dumperOptions) {
        super(dumperOptions);
        this.addClassTag(ArrayList.class, Tag.SEQ);
        this.multiRepresenters.put(List.class, new RepresentCustomList());
    }

    protected class RepresentCustomList extends RepresentList {

        @Override
        public Node representData(Object data) {
            Tag classTag = CustomListRepresenter.this.getTag(data.getClass(), Tag.SEQ);
            DumperOptions.FlowStyle flowStyle = DumperOptions.FlowStyle.FLOW;

            return representSequence(classTag, (List<?>) data, flowStyle);
        }

    }
}

The default FlowStyle is BLOCK, you can see it in CustomListRepresenter.this.defaultFlowStyle variable.
Here we're forcing the list objects flow style to FLOW instead of the default flow style. You can explicitly set it to BLOCK if you want, but I don't think that would make a difference in comparison to the default style without a custom representer.

Then, in the main code, you set your custom configuration using the setImplementation method after creating the YamlFile:

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

// Set custom configuration
yamlFile.setImplementation(new CustomYamlConfiguration());

// Load file
yamlFile.createOrLoadWithComments();

// WebLore
ArrayList<String> webLore = new ArrayList<>();

webLore.add("Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful " +
        "perks and commands to use. The path to the top has many different options and requirements.");
webLore.add("One could be a crafter, building vast kingdoms and controlling many different animals. " +
        "Alternatively, one could decide to pursue the path of darkness. " +
        "Murdering players and bosses alike as they continue the path of becoming the strongest.");
webLore.add("However, to be considered the pinnacle of strength in mind and body alike, " +
        "one must walk every path; obtaining glory in both crafting and combat and " +
        "claiming a seat among the Overlords.");

yamlFile.setComment("WebLore", "WebLore\nLore in the Web GUI");
yamlFile.set("WebLore", webLore);

// Save
yamlFile.save();

// Output
System.out.println("WebLore");
System.out.println(String.join("\n", yamlFile.getStringList("WebLore")));

This is the result:

issue78.yml (Flow style for lists)

#------------------------------#
# WebLore
# Lore in the Web GUI
#------------------------------#
WebLore: ['Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful perks and commands to use. The path to the top has many different options and requirements.', 'One could be a crafter, building vast kingdoms and controlling many different animals. Alternatively, one could decide to pursue the path of darkness. Murdering players and bosses alike as they continue the path of becoming the strongest.', 'However, to be considered the pinnacle of strength in mind and body alike, one must walk every path; obtaining glory in both crafting and combat and claiming a seat among the Overlords.']

Or, removing the disable split lines (default setSplitLines(true)):

#------------------------------#
# WebLore
# Lore in the Web GUI
#------------------------------#
WebLore: ['Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many
    useful perks and commands to use. The path to the top has many different options
    and requirements.', 'One could be a crafter, building vast kingdoms and controlling
    many different animals. Alternatively, one could decide to pursue the path of
    darkness. Murdering players and bosses alike as they continue the path of becoming
    the strongest.', 'However, to be considered the pinnacle of strength in mind and
    body alike, one must walk every path; obtaining glory in both crafting and combat
    and claiming a seat among the Overlords.']

And withDumperOptions.FlowStyle.BLOCK style:

#------------------------------#
# WebLore
# Lore in the Web GUI
#------------------------------#
WebLore:
  - Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful
    perks and commands to use. The path to the top has many different options and
    requirements.
  - One could be a crafter, building vast kingdoms and controlling many different
    animals. Alternatively, one could decide to pursue the path of darkness. Murdering
    players and bosses alike as they continue the path of becoming the strongest.
  - However, to be considered the pinnacle of strength in mind and body alike, one
    must walk every path; obtaining glory in both crafting and combat and claiming
    a seat among the Overlords.

@ItsRainingHP
Copy link
Author

ItsRainingHP commented Jul 19, 2023

The only difference between your code and mine is that I am using ConfigurationSection#addDefault instead of YamlFile#addDefault. Could that be the issue? I will try using YamlFile#addDefault and post results once I am able.

@Carleslc
Copy link
Owner

Carleslc commented Jul 19, 2023

The only difference between your code and mine is that I am using ConfigurationSection#addDefault instead of YamlFile#addDefault. Could that be the issue? I will try using YamlFile#addDefault and post results once I am able.

My code uses the set method, but it's also working when using either addDefault or ConfigurationSection's addDefault.

Also remember you can use the path method to set values and comments without managing sections, as I wrote in this comment in another issue.

@ItsRainingHP
Copy link
Author

ItsRainingHP commented Jul 20, 2023

Well then I really do not know why its behaving the way it is. Seriously frustrating a common String List is failing.

Here is my code. Happy to improve or change with your suggestions:

 public YamlFile getConfig() {
        YamlFile yamlFile = new YamlFile("/config.yml");
        try {
            if (!yamlFile.exists()) {
                yamlFile.createNewFile();
                yamlFile.loadWithComments();
                yamlFile.setCommentFormat(YamlCommentFormat.PRETTY);
                DumperOptions yamlOptions = ((SimpleYamlImplementation) yamlFile.getImplementation()).getDumperOptions();
                yamlOptions.setSplitLines(false);
                ArrayList<String> webLore = new ArrayList<>();
                webLore.add("Recruits are just the beginning. Wide-eyed and hopeful, recruits gain many useful " +
                        "perks and commands to use. The path to the top has many different options and requirements.");
                webLore.add("One could be a crafter, building vast kingdoms and controlling many different animals. " +
                        "Alternatively, one could decide to pursue the path of darkness. " +
                        "Murdering players and bosses alike as they continue the path of becoming the strongest.");
                webLore.add("However, to be considered the pinnacle of strength in mind and body alike, " +
                        "one must walk every path; obtaining glory in both crafting and combat and " +
                        "claiming a seat among the Overlords");
                //Let me know if you need to see the declared variables here
                createDefaultSection(yamlFile, "rank1", "<#55FF55>Recruit", "Dirt", lore,
                        webLore, false, requiredRanks, path, "rank1",
                        "<#55FF55>Recruit", "<#55FF55>the Recruit", 1, 1, commands);
            } else {
                yamlFile.loadWithComments();
            }
            try {
                yamlFile.save();
            } catch (IOException e) {
                RDQ.getInstance().sendLoggerWarning(e.getMessage());
            }
        } catch (final Exception e) {
            RDQ.getInstance().sendLoggerWarning(e.getMessage());
        }
        return yamlFile;
    }

    private void createDefaultSection(YamlFile yamlFile, String rank, String title, String material,
                                          List<String> lore, List<String> webLore, boolean showRequirements,
                                          List<String> requiredRanks, List<String> path, String luckPermsGroup,
                                          String prefix, String suffix, int weight, int tier, List<String> commands) {
        ConfigurationSection rank1 = YamlHandler.createOrGetSection(yamlFile, rank);
        rank1.addDefault("Title", title);
        rank1.addDefault("Material", material);
        rank1.addDefault("Lore", lore);
        rank1.addDefault("WebLore", webLore);
        rank1.addDefault("ShowRequirementsInGame", showRequirements);
        rank1.addDefault("RequiredRanks", requiredRanks);
        rank1.addDefault("Path", path);
        rank1.addDefault("LuckPermsGroup", luckPermsGroup);
        rank1.addDefault("Prefix", prefix);
        rank1.addDefault("Suffix", suffix);
        rank1.addDefault("Weight", weight);
        rank1.addDefault("Tier", tier);
        rank1.addDefault("Commands", commands);
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants