From d198eca1b63a4575a2e5fe8265934060b0c40031 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sun, 14 Feb 2016 16:31:35 +0100 Subject: [PATCH] #514 Messages tool adds missing messages as comments - Add the English text as a TODO comment for all missing messages in the translations - Add a TODO comment for missing tags - Change the task and messages verifier to use YamlConfiguration --- src/tools/messages/MessageFileVerifier.java | 156 +++++++++++--------- src/tools/messages/VerifyMessagesTask.java | 46 ++---- src/tools/utils/FileUtils.java | 2 +- 3 files changed, 104 insertions(+), 100 deletions(-) diff --git a/src/tools/messages/MessageFileVerifier.java b/src/tools/messages/MessageFileVerifier.java index 3da84912..68e07ea4 100644 --- a/src/tools/messages/MessageFileVerifier.java +++ b/src/tools/messages/MessageFileVerifier.java @@ -1,16 +1,21 @@ package messages; +import com.google.common.base.Predicate; import com.google.common.collect.HashMultimap; +import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.util.StringUtils; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import utils.FileUtils; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -21,8 +26,6 @@ import java.util.Set; */ public class MessageFileVerifier { - private static final String NEW_LINE = "\n"; - private final String messagesFile; private final Set unknownKeys = new HashSet<>(); // Map with the missing key and a boolean indicating whether or not it was added to the file by this object @@ -69,47 +72,30 @@ public class MessageFileVerifier { } private void verifyKeys() { - List messageKeys = getAllMessageKeys(); - List fileLines = readFileLines(); - for (String line : fileLines) { - // Skip comments and empty lines - if (!line.startsWith("#") && !line.trim().isEmpty()) { - processKeyInFile(line, messageKeys); + FileConfiguration configuration = YamlConfiguration.loadConfiguration(new File(messagesFile)); + + // Check known keys (their existence + presence of all tags) + for (MessageKey messageKey : MessageKey.values()) { + final String key = messageKey.getKey(); + if (configuration.isString(key)) { + checkTagsInMessage(messageKey, configuration.getString(key)); + } else { + missingKeys.put(key, false); } } - // All keys that remain are keys that are absent in the file - for (MessageKey missingKey : messageKeys) { - missingKeys.put(missingKey.getKey(), false); - } - } - - private void processKeyInFile(String line, List messageKeys) { - if (line.indexOf(':') == -1) { - System.out.println("Skipping line in unknown format: '" + line + "'"); - return; - } - - final String readKey = line.substring(0, line.indexOf(':')); - boolean foundKey = false; - for (Iterator it = messageKeys.iterator(); it.hasNext(); ) { - MessageKey messageKey = it.next(); - if (messageKey.getKey().equals(readKey)) { - checkTagsInMessage(readKey, line.substring(line.indexOf(':')), messageKey.getTags()); - it.remove(); - foundKey = true; - break; + // Check FileConfiguration for all of its keys to find unknown keys + for (String key : configuration.getValues(true).keySet()) { + if (!messageKeyExists(key)) { + unknownKeys.add(key); } } - if (!foundKey) { - unknownKeys.add(readKey); - } } - private void checkTagsInMessage(String key, String message, String[] tags) { - for (String tag : tags) { + private void checkTagsInMessage(MessageKey messageKey, String message) { + for (String tag : messageKey.getTags()) { if (!message.contains(tag)) { - missingTags.put(key, tag); + missingTags.put(messageKey.getKey(), tag); } } } @@ -119,54 +105,90 @@ public class MessageFileVerifier { * * @param defaultMessages The collection of default messages */ - public void addMissingKeys(Map defaultMessages) { + public void addMissingKeys(FileConfiguration defaultMessages) { + final List fileLines = new ArrayList<>( + Arrays.asList(FileUtils.readFromFile(messagesFile).split("\\n"))); + List keysToAdd = new ArrayList<>(); for (Map.Entry entry : missingKeys.entrySet()) { - if (Boolean.FALSE.equals(entry.getValue()) && defaultMessages.get(entry.getKey()) != null) { - keysToAdd.add(entry.getKey()); + final String key = entry.getKey(); + + if (Boolean.FALSE.equals(entry.getValue()) && defaultMessages.get(key) != null) { + keysToAdd.add(key); } } - // We know that all keys in keysToAdd are safe to retrieve and write - StringBuilder sb = new StringBuilder(NEW_LINE); + // Add missing keys as comments to the bottom of the file for (String keyToAdd : keysToAdd) { - sb.append(keyToAdd).append(":").append(defaultMessages.get(keyToAdd)).append(NEW_LINE); - missingKeys.put(keyToAdd, true); + int indexOfComment = Iterables.indexOf(fileLines, isCommentFor(keyToAdd)); + if (indexOfComment != -1) { + // Comment for keyToAdd already exists, so remove it since we're going to add it + fileLines.remove(indexOfComment); + } + String comment = commentForKey(keyToAdd) + "'" + + defaultMessages.getString(keyToAdd).replace("'", "''") + "'"; + fileLines.add(comment); + missingKeys.put(keyToAdd, Boolean.TRUE); } - FileUtils.appendToFile(messagesFile, sb.toString()); - } - private static List getAllMessageKeys() { - return new ArrayList<>(Arrays.asList(MessageKey.values())); + // Add a comment above messages missing a tag + for (Map.Entry> entry : missingTags.asMap().entrySet()) { + final String key = entry.getKey(); + addCommentForMissingTags(fileLines, key, entry.getValue()); + } + + FileUtils.writeToFile(messagesFile, StringUtils.join("\n", fileLines)); } /** - * Read all lines from the messages file and skip empty lines and comment lines. - * This method appends lines starting with two spaces to the previously read line, - * akin to a YAML parser. + * Add a comment above a message to note the tags the message is missing. Removes + * any similar comment that may already be above the message. + * + * @param fileLines The lines of the file (to modify) + * @param key The key of the message + * @param tags The missing tags */ - private List readFileLines() { - String[] rawLines = FileUtils.readFromFile(messagesFile).split("\\n"); - List lines = new ArrayList<>(); - for (String line : rawLines) { - // Skip comments and empty lines - if (!line.startsWith("#") && !StringUtils.isEmpty(line)) { - // Line is indented, i.e. it needs to be appended to the previous line - if (line.startsWith(" ")) { - appendToLastElement(lines, line.substring(1)); - } else { - lines.add(line); + private void addCommentForMissingTags(List fileLines, final String key, Collection tags) { + int indexForComment = Iterables.indexOf(fileLines, isCommentFor(key)); + if (indexForComment == -1) { + indexForComment = Iterables.indexOf(fileLines, new Predicate() { + @Override + public boolean apply(String input) { + return input.startsWith(key + ": "); } + }); + if (indexForComment == -1) { + System.err.println("Error adding comment for key '" + key + "': couldn't find entry in file lines"); + return; } + } else { + fileLines.remove(indexForComment); } - return lines; + + String tagWord = tags.size() > 1 ? "tags" : "tag"; + fileLines.add(indexForComment, commentForKey(key) + + String.format("Missing %s %s", tagWord, StringUtils.join(", ", tags))); } - private static void appendToLastElement(List list, String text) { - if (list.isEmpty()) { - throw new IllegalStateException("List cannot be empty!"); + private static String commentForKey(String key) { + return String.format("# TODO %s: ", key); + } + + private static Predicate isCommentFor(final String key) { + return new Predicate() { + @Override + public boolean apply(String input) { + return input.startsWith(commentForKey(key)); + } + }; + } + + private static boolean messageKeyExists(String key) { + for (MessageKey messageKey : MessageKey.values()) { + if (messageKey.getKey().equals(key)) { + return true; + } } - int lastIndex = list.size() - 1; - list.set(lastIndex, list.get(lastIndex).concat(text)); + return false; } } diff --git a/src/tools/messages/VerifyMessagesTask.java b/src/tools/messages/VerifyMessagesTask.java index 19eacf24..e540554a 100644 --- a/src/tools/messages/VerifyMessagesTask.java +++ b/src/tools/messages/VerifyMessagesTask.java @@ -2,14 +2,14 @@ package messages; import com.google.common.collect.Multimap; import fr.xephi.authme.util.StringUtils; -import utils.FileUtils; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import utils.ToolTask; import utils.ToolsConstants; import java.io.File; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; @@ -29,6 +29,8 @@ public final class VerifyMessagesTask implements ToolTask { private static final Pattern MESSAGE_FILE_PATTERN = Pattern.compile("messages_[a-z]{2,7}\\.yml"); /** Tag that is replaced to the messages folder in user input. */ private static final String SOURCES_TAG = "{msgdir}"; + /** File to get default messages from (assumes that it is complete). */ + private static final String DEFAULT_MESSAGES_FILE = MESSAGES_FOLDER + "messages_en.yml"; @Override public String getTaskName() { @@ -43,13 +45,7 @@ public final class VerifyMessagesTask implements ToolTask { String inputFile = scanner.nextLine(); System.out.println("Add any missing keys to files? ['y' = yes]"); - boolean addMissingKeys = "y".equals(scanner.nextLine()); - - // Set up needed objects - Map defaultMessages = null; - if (addMissingKeys) { - defaultMessages = constructDefaultMessages(); - } + boolean addMissingKeys = "y".equalsIgnoreCase(scanner.nextLine()); List messageFiles; if (StringUtils.isEmpty(inputFile)) { @@ -59,6 +55,11 @@ public final class VerifyMessagesTask implements ToolTask { messageFiles = Collections.singletonList(customFile); } + FileConfiguration defaultMessages = null; + if (addMissingKeys) { + defaultMessages = YamlConfiguration.loadConfiguration(new File(DEFAULT_MESSAGES_FILE)); + } + // Verify the given files for (File file : messageFiles) { System.out.println("Verifying '" + file.getName() + "'"); @@ -92,19 +93,18 @@ public final class VerifyMessagesTask implements ToolTask { } } - private static void verifyFileAndAddKeys(MessageFileVerifier verifier, Map defaultMessages) { + private static void verifyFileAndAddKeys(MessageFileVerifier verifier, FileConfiguration defaultMessages) { Map missingKeys = verifier.getMissingKeys(); - if (!missingKeys.isEmpty()) { + if (!missingKeys.isEmpty() || !verifier.getMissingTags().isEmpty()) { verifier.addMissingKeys(defaultMessages); - missingKeys = verifier.getMissingKeys(); List addedKeys = getKeysWithValue(Boolean.TRUE, missingKeys); System.out.println(" Added missing keys " + addedKeys); List unsuccessfulKeys = getKeysWithValue(Boolean.FALSE, missingKeys); if (!unsuccessfulKeys.isEmpty()) { - System.out.println(" Warning! Could not add all missing keys (problem with loading " + + System.err.println(" Warning! Could not add all missing keys (problem with loading " + "default messages?)"); - System.out.println(" Could not add keys " + unsuccessfulKeys); + System.err.println(" Could not add keys " + unsuccessfulKeys); } } @@ -119,24 +119,6 @@ public final class VerifyMessagesTask implements ToolTask { } } - private static Map constructDefaultMessages() { - String defaultMessagesFile = MESSAGES_FOLDER + "messages_en.yml"; - List lines = FileUtils.readLinesFromFile(defaultMessagesFile); - Map messages = new HashMap<>(lines.size()); - for (String line : lines) { - if (line.startsWith("#") || line.trim().isEmpty()) { - continue; - } - if (line.indexOf(':') == -1 || line.indexOf(':') == line.length() - 1) { - System.out.println("Warning! Unknown format in default messages file for line '" + line + "'"); - } else { - String key = line.substring(0, line.indexOf(':')); - messages.put(key, line.substring(line.indexOf(':') + 1)); - } - } - return messages; - } - private static List getKeysWithValue(V value, Map map) { List result = new ArrayList<>(); for (Map.Entry entry : map.entrySet()) { diff --git a/src/tools/utils/FileUtils.java b/src/tools/utils/FileUtils.java index 49bcab9f..02b9eddd 100644 --- a/src/tools/utils/FileUtils.java +++ b/src/tools/utils/FileUtils.java @@ -24,7 +24,7 @@ public final class FileUtils { writeToFile(destinationFile, result); } - private static void writeToFile(String outputFile, String contents) { + public static void writeToFile(String outputFile, String contents) { try { Files.write(Paths.get(outputFile), contents.getBytes()); } catch (IOException e) {