I am trying to load a Yaml file into a MultiMap using SnakeYAML, but I keep encountering the following exception: java.base/java.util.LinkedHashMap cannot be cast to com.google.common.collect.Multimap
. Is there any way to efficiently and effectively load a SnakeYAML object into a Guava MultiMap? I am aware that you can do this with regular HashMaps, but my target Yaml has duplicate keys, so it requires the use of MultiMaps. Thanks for the help in advance. My code for populating the MultiMap using SnakeYAML is as follows:
//Read the config file
InputStream configIn;
try {
configIn = FileUtil.loadFileAsStream(configPath);
//Load the config file into the YAML object
pluginConf = LinkedHashMultimap.create((Multimap<String, Object>) configData.load(configIn));
}
catch(FileNotFoundException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
EDIT: Sample YAML that has duplicate keys
join:
message: "JMessage1"
quit:
message: "QMessage1"
join:
message: "JMessage2"
quit:
message: "QMessage2"
join:
message: "JMessage3"
quit:
message: "QMessage3"
I did manage to solve this problem, but I used regex with regular HashMaps instead of the Guava Multimaps like I originally intended. For example, here's a YAML file that has duplicated keys:
join:
message: "JMessage1"
quit:
message: "QMessage1"
join:
message: "JMessage2"
quit:
message: "QMessage2"
To parse out all of the messages, all I did was simply add numbers to each of the parent keys that were being repeated (join
becomes join1
, quit
becomes quit1
, and so on). Since each key has a number in it, they can easily be reverted back to just saying join
or quit
with the following regex: str.replaceAll("[^a-zA-Z.]", "").toLowerCase()
in a for loop that iterates through the HashMap. Since the HashMap entries now just read as join
, quit
, join
, quit
when put through the loop, their values can be easily grabbed using something like the following snippet:
if(entry.equals("join")){
//Do stuff
}
After that, the values can be added to something like an ArrayList or other collection. In my case, I used an ArrayList and assigned the properties of the YAML file to instance variables of an object. The following snippet from one of my classes in the project accomplishes this:
//Iterate through the HashMap
for(Entry<?, ?> configEntry : pluginConf.entrySet()){
//Get a string from the selected key that contains only lower-case letters and periods
String entryKey = configEntry.getKey().toString().replaceAll("[^a-zA-Z.]", "").toLowerCase();
//Search for join messages
if(entryKey.equals("messages.join")){
//Get the key name of the current entry
String joinKeyName = configEntry.getKey().toString();
//Create a join message object
JoinMessage newJoinMessage = new JoinMessage(,
configData.getString(joinKeyName + ".message")
);
//Add the join message object to the join message ArrayList
joinMessages.add(newJoinMessage);
//Add to the join message quantity
joinMsgQuantity ++;
}
}
Not really using HashMaps that allow duplicates like I originally asked for, but this "hack" worked flawlessly for me. Hope this helps anyone else looking to do something like this.