package mods.eln.i18n;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class SourceCodeParser {
private static final Pattern JAVA_TR_PATTERN = Pattern.compile("(?:tr|TR)\\s*\\(\\s*\"(.*?)\"\\s*[,)]");
private static final Pattern JAVA_FORGE_PATTERN =
Pattern.compile("TR_([A-Z]*)\\s*\\(\\s*(?:I18N.)?Type.(.*?)\\s*,\\s\"(.*?)\"\\s*\\)");
private static final String MULTIPLE_LOCATIONS = "Appearing in multiple source files";
private SourceCodeParser() {
}
static Map<String, Set<TranslationItem>> parseSourceFolder(final File file) throws IOException {
Map<String, Set<TranslationItem>> strings = new TreeMap<String, Set<TranslationItem>>();
strings.put(MULTIPLE_LOCATIONS, new TreeSet<TranslationItem>());
parseSourceFolderRecursive(file, strings);
return strings;
}
private static void parseSourceFolderRecursive(final File folder, final Map<String, Set<TranslationItem>> strings)
throws IOException {
// Check that arguments are valid.
if (folder != null && folder.exists()) {
// Do for each file.
for (final File file : folder.listFiles()) {
// If the file is a directory, call the method recursively.
if (file.isDirectory()) {
parseSourceFolderRecursive(file, strings);
// If it is a file and has the file extension .java, parse the Java file.
} else if (file.isFile() && file.getName().endsWith(".java")) {
System.out.println("Parsing Java source file: " + file.getName() + "...");
parseJavaFile(file, strings);
// If it is a file and has the file extension .kt, parse the Kotlin file.
} else if (file.isFile() && file.getName().endsWith(".kt")) {
System.out.println("Parsing Kotlin source file: " + file.getName() + "...");
parseKotlinFile(file, strings);
}
}
}
}
private static void parseJavaFile(final File file, final Map<String, Set<TranslationItem>> strings)
throws IOException {
// Load file into memory.
final String content = new Scanner(file).useDelimiter("\\Z").next();
final Set<TranslationItem> textsToTranslate = new TreeSet<TranslationItem>();
// Find all matches for Java style translations.
final Matcher trMatcher = JAVA_TR_PATTERN.matcher(content);
while (trMatcher.find()) {
final TranslationItem textToTranslate = new TranslationItem(trMatcher.group(1));
System.out.println(" " + textToTranslate.getKey());
if (!isStringAlreadyPresent(textToTranslate, strings)) {
textsToTranslate.add(textToTranslate);
}
}
final Matcher forgeMatcher = JAVA_FORGE_PATTERN.matcher(content);
while (forgeMatcher.find()) {
final String property = forgeMatcher.group(1).toLowerCase();
final I18N.Type type = I18N.Type.valueOf(forgeMatcher.group(2));
final String text = forgeMatcher.group(3);
final TranslationItem textToTranslate = new TranslationItem(type.getPrefix() +
I18N.encodeLangKey(text, type.isWhitespacesInFileReplaced()) + "." + property, text);
System.out.println(" " + textToTranslate.getKey());
if (!isStringAlreadyPresent(textToTranslate, strings)) {
textsToTranslate.add(textToTranslate);
}
}
// If there were translations for that file, add the list of translations to the map.
if (!textsToTranslate.isEmpty()) {
strings.put(file.getPath(), textsToTranslate);
}
}
private static void parseKotlinFile(final File file, final Map<String, Set<TranslationItem>> strings) throws IOException {
// TODO: This is unlikely to work perfectly. It'll do for now.
parseJavaFile(file, strings);
}
private static boolean isStringAlreadyPresent(final TranslationItem string,
final Map<String, Set<TranslationItem>> strings) {
for (final String fileName : strings.keySet()) {
if (MULTIPLE_LOCATIONS.equals(fileName)) {
if (strings.get(fileName).contains(string))
return true;
} else {
if (strings.get(fileName).remove(string)) {
strings.get(MULTIPLE_LOCATIONS).add(string);
return true;
}
}
}
return false;
}
}