package org.mafagafogigante.dungeon.wiki;
import org.mafagafogigante.dungeon.io.JsonObjectFactory;
import org.mafagafogigante.dungeon.logging.DungeonLogger;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Uninstantiable Wiki class that loads the Wiki when it is required.
*/
final class Wiki {
private static List<Article> articleList;
private Wiki() {
throw new AssertionError();
}
/**
* Initializes the Wiki. Build a map with all the See Also references until all the articles have been loaded, so it
* is possible to check that these references are valid.
*/
private static void initialize() {
// The field cannot be initialized in the field declaration as a comparison to null is used to determine whether or
// not it has already been initialized.
articleList = new ArrayList<>();
Map<Article, Collection<String>> seeAlsoMap = new HashMap<>();
JsonObject wikiJsonObject = JsonObjectFactory.makeJsonObject("wiki.json");
for (JsonValue jsonValue : wikiJsonObject.get("articles").asArray()) {
JsonObject jsonObject = jsonValue.asObject();
Article article = new Article(jsonObject.get("title").asString(), jsonObject.get("content").asString());
if (jsonObject.get("seeAlso") != null) {
seeAlsoMap.put(article, new ArrayList<String>());
for (JsonValue referenceJsonValue : jsonObject.get("seeAlso").asArray()) {
seeAlsoMap.get(article).add(referenceJsonValue.asString());
}
}
articleList.add(article);
}
// Validate the references and add them.
addReferences(seeAlsoMap);
}
private static void addReferences(Map<Article, Collection<String>> seeAlsoMap) {
// To speed up, make a set with all the valid article names.
Set<String> validReferences = new HashSet<>();
for (Article article : articleList) {
validReferences.add(article.getName().getSingular());
}
for (Entry<Article, Collection<String>> entry : seeAlsoMap.entrySet()) {
for (String reference : entry.getValue()) {
if (validReferences.contains(reference)) {
String articleName = entry.getKey().getName().getSingular();
if (entry.getKey().hasReference(reference)) {
DungeonLogger.warning(String.format("Found repeated reference (%s) in %s.", reference, articleName));
} else if (articleName.equals(reference)) {
DungeonLogger.warning(String.format("Found reference to self in %s.", articleName));
} else {
entry.getKey().addReference(reference);
}
} else {
DungeonLogger.warning("Got invalid wiki reference: " + reference + ".");
}
}
}
}
/**
* Returns an unmodifiable view of the collection of articles.
*/
static Collection<Article> getArticles() {
if (articleList == null) {
initialize();
}
return Collections.unmodifiableCollection(articleList);
}
@Override
public String toString() {
return "Wiki{articleList=" + articleList + '}';
}
}