JAL-3210 Barebones gradle/buildship/eclipse. See README
[jalview.git] / utils / MessageBundleChecker.java
diff --git a/utils/MessageBundleChecker.java b/utils/MessageBundleChecker.java
deleted file mode 100644 (file)
index c870f6d..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- * 
- * This file is part of Jalview.
- * 
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *  
- * Jalview is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty 
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
- * PURPOSE.  See the GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.regex.Pattern;
-
-/**
- * This class scans Java source files for calls to MessageManager and reports
- * <ul>
- * <li>calls using keys not found in Messages.properties</li>
- * <li>any unused keys in Messages.properties</li>
- * </ul>
- * It does not handle dynamically constructed keys, these are reported as
- * possible errors for manual inspection. <br>
- * For comparing translated bundles with Messages.properties, see i18nAnt.xml
- * 
- * @author gmcarstairs
- *
- */
-public class MessageBundleChecker implements BufferedLineReader.LineCleaner
-{
-  /*
-   * regex ^"[^"]*"$
-   * opening quote, closing quote, no quotes in between
-   */
-  static Pattern STRING_PATTERN = Pattern.compile("^\"[^\"]*\"$");
-
-  /*
-   * number of text lines to read at a time in order to parse
-   * code that is split over several lines
-   */
-  static int bufferSize = 3;
-
-  /*
-   * resource bundle key is arg0 for these methods
-   */
-  static final String METHOD1 = "MessageManager.getString(";
-
-  static final String METHOD2 = "MessageManager.formatMessage(";
-
-  static final String METHOD3 = "MessageManager.getStringOrReturn(";
-
-  /*
-   * resource bundle key is arg1 for this method
-   */
-  static final String JVINIT = "JvSwingUtils.jvInitComponent(";
-
-  static final String[] METHODS = { METHOD1, METHOD2, METHOD3, JVINIT };
-
-  /*
-   * root of the Java source folders we want to scan
-   */
-  String sourcePath;
-
-  /*
-   * contents of Messages.properties
-   */
-  private Properties messages;
-
-  /*
-   * keys from Messages.properties
-   * we remove entries from here as they are found to be used
-   * any left over are unused entries
-   */
-  private TreeSet<String> messageKeys;
-
-  private int javaCount;
-
-  private Set<String> invalidKeys;
-
-  private Set<String> dynamicKeys;
-
-  /**
-   * Runs the scan given the path to the root of Java source directories
-   * 
-   * @param args
-   *          [0] path to the source folder to scan
-   * @param args
-   *          [1] (optional) read buffer size (default is 3); increasing this
-   *          may detect more results but will give higher error counts due to
-   *          double counting of the same code
-   * @throws IOException
-   */
-  public static void main(String[] args) throws IOException
-  {
-    if (args.length != 1 && args.length != 2)
-    {
-      System.out.println("Usage: <pathToSourceFolder> [readBufferSize]");
-      return;
-    }
-    if (args.length == 2)
-    {
-      bufferSize = Integer.valueOf(args[1]);
-    }
-    new MessageBundleChecker().doMain(args[0]);
-  }
-
-  /**
-   * Main method to perform the work
-   * 
-   * @param srcPath
-   * @throws IOException
-   */
-  private void doMain(String srcPath) throws IOException
-  {
-    System.out.println("Scanning " + srcPath
-            + " for calls to MessageManager\n");
-    sourcePath = srcPath;
-    loadMessages();
-    File dir = new File(srcPath);
-    if (!dir.exists())
-    {
-      System.out.println(srcPath + " not found");
-      return;
-    }
-
-    invalidKeys = new HashSet<>();
-    dynamicKeys = new HashSet<>();
-
-    if (dir.isDirectory())
-    {
-      scanDirectory(dir);
-    }
-    else
-    {
-      scanFile(dir);
-    }
-    reportResults();
-  }
-
-  /**
-   * Prints out counts to sysout
-   */
-  private void reportResults()
-  {
-    System.out.println("\nScanned " + javaCount + " source files");
-    System.out.println(
-            "Messages.properties has " + messages.size()
-            + " keys");
-    if (!invalidKeys.isEmpty())
-    {
-      System.out.println("Found " + invalidKeys.size()
-              + " possibly invalid parameter call"
-              + (invalidKeys.size() > 1 ? "s" : ""));
-    }
-
-    System.out.println("Keys not found, assumed constructed dynamically:");
-    int dynamicCount = 0;
-    for (String key : messageKeys)
-    {
-      if (isDynamic(key))
-      {
-        System.out.println("    " + key);
-        dynamicCount++;
-      }
-    }
-
-    if (dynamicCount < messageKeys.size())
-    {
-      System.out.println((messageKeys.size() - dynamicCount)
-              + " keys not found, possibly unused");
-      for (String key : messageKeys)
-      {
-        if (!isDynamic(key))
-        {
-          System.out.println("    " + key);
-        }
-      }
-    }
-    System.out
-            .println("(Run i18nAnt.xml to compare other message bundles)");
-  }
-
-  /**
-   * Answers true if the key starts with one of the recorded dynamic key stubs,
-   * else false
-   * 
-   * @param key
-   * @return
-   */
-  private boolean isDynamic(String key)
-  {
-    for (String dynamic : dynamicKeys)
-    {
-      if (key.startsWith(dynamic))
-      {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Scan all files within a directory
-   * 
-   * @param dir
-   * @throws IOException
-   */
-  private void scanDirectory(File dir) throws IOException
-  {
-    File[] files = dir.listFiles();
-    if (files != null)
-    {
-      for (File f : files)
-      {
-        if (f.isDirectory())
-        {
-          scanDirectory(f);
-        }
-        else
-        {
-          scanFile(f);
-        }
-      }
-    }
-  }
-
-  /**
-   * Scan a Java file
-   * 
-   * @param f
-   */
-  private void scanFile(File f) throws IOException
-  {
-    String path = f.getPath();
-    if (!path.endsWith(".java"))
-    {
-      return;
-    }
-    javaCount++;
-
-    /*
-     * skip class with designed dynamic lookup call
-     */
-    if (path.endsWith("gui/JvSwingUtils.java"))
-    {
-      return;
-    }
-
-    BufferedReader br = new BufferedReader(new FileReader(f));
-    BufferedLineReader blr = new BufferedLineReader(br, bufferSize, this);
-
-    int lineNo = 0;
-    String line = blr.read();
-    while (line != null)
-    {
-      lineNo++;
-      inspectSourceLines(path, lineNo, line);
-      line = blr.read();
-    }
-    br.close();
-
-  }
-
-  /**
-   * Look for calls to MessageManager methods, possibly split over two or more
-   * lines that have been concatenated while parsing the file
-   * 
-   * @param path
-   * @param lineNo
-   * @param line
-   */
-  private void inspectSourceLines(String path, int lineNo, String line)
-  {
-    String lineNos = String
-            .format("%d-%d", lineNo, lineNo + bufferSize
-            - 1);
-    for (String method : METHODS)
-    {
-      int pos = line.indexOf(method);
-      if (pos == -1)
-      {
-        continue;
-      }
-
-      /*
-       * extract what follows the opening bracket of the method call
-       */
-      String methodArgs = line.substring(pos + method.length()).trim();
-      if ("".equals(methodArgs))
-      {
-        /*
-         * arguments are on next line - catch in the next read loop iteration
-         */
-        continue;
-      }
-      if (methodArgs.indexOf(",") == -1 && methodArgs.indexOf(")") == -1)
-      {
-        /*
-         * arguments continue on next line - catch in the next read loop iteration
-         */
-        continue;
-      }
-
-      if (JVINIT == method && methodArgs.indexOf(",") == -1)
-      {
-        /*
-         * not interested in 1-arg calls to jvInitComponent
-         */
-        continue;
-      }
-
-      String messageKey = getMessageKey(method, methodArgs);
-
-      if (METHOD3 == method)
-      {
-        System.out.println(String.format("Dynamic key at %s line %s %s",
-                path.substring(sourcePath.length()), lineNos, line));
-        String key = messageKey.substring(1, messageKey.length() - 1);
-        dynamicKeys.add(key);
-        continue;
-      }
-
-      if (messageKey == null)
-      {
-        System.out.println(String.format("Trouble parsing %s line %s %s",
-                path.substring(sourcePath.length()), lineNos, line));
-        continue;
-      }
-
-      if (!(STRING_PATTERN.matcher(messageKey).matches()))
-      {
-        System.out.println(String.format("Dynamic key at %s line %s %s",
-                path.substring(sourcePath.length()), lineNos, line));
-        continue;
-      }
-
-      /*
-       * strip leading and trailing quote
-       */
-      messageKey = messageKey.substring(1, messageKey.length() - 1);
-
-      if (!this.messages.containsKey(messageKey))
-      {
-        System.out.println(String.format(
-                "Unmatched key '%s' at line %s of %s", messageKey, lineNos,
-                path.substring(sourcePath.length())));
-        if (!invalidKeys.contains(messageKey))
-        {
-          invalidKeys.add(messageKey);
-        }
-      }
-      messageKeys.remove(messageKey);
-    }
-  }
-
-  /**
-   * Helper method to parse out the resource bundle key parameter of a method
-   * call
-   * 
-   * @param method
-   * @param methodArgs
-   *          the rest of the source line starting with arguments to method
-   * @return
-   */
-  private String getMessageKey(String method, String methodArgs)
-  {
-    String key = methodArgs;
-
-    /*
-     * locate second argument if calling jvInitComponent()
-     */
-    if (method == JVINIT)
-    {
-      int commaLoc = methodArgs.indexOf(",");
-      if (commaLoc == -1)
-      {
-        return null;
-      }
-      key = key.substring(commaLoc + 1).trim();
-    }
-
-    /*
-     * take up to next comma or ) or end of line
-     */
-    int commaPos = key.indexOf(",");
-    int bracePos = key.indexOf(")");
-    int endPos = commaPos == -1 ? bracePos : (bracePos == -1 ? commaPos
-            : Math.min(commaPos, bracePos));
-    if (endPos == -1 && key.length() > 1 && key.endsWith("\""))
-    {
-      endPos = key.length();
-    }
-
-    return endPos == -1 ? null : key.substring(0, endPos);
-  }
-
-  /**
-   * Loads properties from Message.properties
-   * 
-   * @throws IOException
-   */
-  void loadMessages() throws IOException
-  {
-    messages = new Properties();
-    FileReader reader = new FileReader(new File(sourcePath,
-            "../resources/lang/Messages.properties"));
-    messages.load(reader);
-    reader.close();
-
-    messageKeys = new TreeSet<>();
-    for (Object key : messages.keySet())
-    {
-      messageKeys.add((String) key);
-    }
-
-  }
-
-  /**
-   * Remove any trailing comments, change tabs to space, and trim
-   */
-  @Override
-  public String cleanLine(String l)
-  {
-    if (l != null)
-    {
-      int pos = l.indexOf("//");
-      if (pos != -1)
-      {
-        l = l.substring(0, pos);
-      }
-      l = l.replace("\t", " ").trim();
-    }
-    return l;
-  }
-
-}