/** @param reallyRemoveIt true: really remove it; false: dry run, only produce logging */
 public void removeXKeysTask(boolean reallyRemoveIt) {
   List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
   Set<String> allLangs = getAllLanguages();
   int counter = 0;
   for (String langKey : allLangs) {
     Locale locale = i18nMgr.getLocaleOrNull(langKey);
     for (String bundleName : allBundles) {
       Properties properties =
           i18nMgr.getPropertiesWithoutResolvingRecursively(locale, bundleName);
       Set<Object> keys = properties.keySet();
       for (Object keyObj : keys) {
         String key = (String) keyObj;
         if (key.endsWith("X")) {
           String value = properties.getProperty(key);
           if (StringHelper.containsNonWhitespace(value)) {
             log.warn(
                 "NONEMPTY XKEY detected in lang::"
                     + locale.getLanguage()
                     + " bundle::"
                     + bundleName
                     + " key::"
                     + key
                     + " value::"
                     + value);
             if (reallyRemoveIt) {
               addKey(locale, bundleName, key.substring(0, key.length() - 1), value);
             }
           }
           log.info(
               "XKEY detected in lang::"
                   + locale.getLanguage()
                   + " bundle::"
                   + bundleName
                   + " key::"
                   + key);
           logText.append(
               i18nMgr.getPropertiesFile(
                       locale, bundleName, I18nModule.getPropertyFilesBaseDir(locale, bundleName))
                   + " XKEY detected in lang::"
                   + locale.getLanguage()
                   + " bundle::"
                   + bundleName
                   + " key::"
                   + key
                   + " value::"
                   + value
                   + "\n");
           if (reallyRemoveIt) {
             deleteKey(locale, bundleName, key);
           }
           counter++;
         }
       }
     }
   }
   if (reallyRemoveIt) {
     log.info(counter + " X-Keys got removed!");
   }
 }
 /** @param reallyRemoveIt true: really remove it; false: dry run, only produce logging */
 public void removeTodoKeysTask(boolean reallyRemoveIt) {
   List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
   Set<String> allLangs = getAllLanguages();
   int counter = 0;
   String[] comparisonStrings = {"TODO"};
   for (String langKey : allLangs) {
     Locale locale = i18nMgr.getLocaleOrNull(langKey);
     for (String bundleName : allBundles) {
       Properties properties =
           i18nMgr.getPropertiesWithoutResolvingRecursively(locale, bundleName);
       Set<Object> keys = properties.keySet();
       for (Object keyObj : keys) {
         String key = (String) keyObj;
         String value = properties.getProperty(key);
         for (int i = 0; i < comparisonStrings.length; i++) {
           int pos = value.toLowerCase().indexOf(comparisonStrings[i].toLowerCase());
           if (pos != -1 && pos < 2 && !value.toLowerCase().equals("todos")) {
             log.info(
                 "TODO-Key detected in lang::"
                     + locale.getLanguage()
                     + " bundle::"
                     + bundleName
                     + " key::"
                     + key
                     + " value::"
                     + value);
             if (value.length() > comparisonStrings[i].length() + 1) {
               log.warn(
                   "this is a TODO-Key WITH TEXT::"
                       + value.substring(comparisonStrings[i].length())
                       + "::");
             } else {
               logText.append(
                   i18nMgr.getPropertiesFile(
                           locale,
                           bundleName,
                           I18nModule.getPropertyFilesBaseDir(locale, bundleName))
                       + " TODO-Key detected in lang::"
                       + locale.getLanguage()
                       + " bundle::"
                       + bundleName
                       + " key::"
                       + key
                       + " value::"
                       + value
                       + "\n");
               if (reallyRemoveIt) {
                 deleteKey(locale, bundleName, key);
               }
             }
             counter++;
           }
         }
       } // each key
     } // each bundle
   }
   log.info(counter + " TODO-Keys got removed!");
 }
 /** @param reallyRemoveIt true: really remove it; false: dry run, only produce logging */
 public void removeEmptyKeysTask(boolean reallyRemoveIt) {
   List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
   int counter = 0;
   Set<String> allLangs = getAllLanguages();
   for (String langKey : allLangs) {
     Locale locale = i18nMgr.getLocaleOrNull(langKey);
     for (String bundleName : allBundles) {
       Properties properties =
           i18nMgr.getPropertiesWithoutResolvingRecursively(locale, bundleName);
       Set<Object> keys = properties.keySet();
       for (Object keyObj : keys) {
         String key = (String) keyObj;
         String value = properties.getProperty(key);
         if (!StringHelper.containsNonWhitespace(value)) {
           log.info(
               "empty Key detected in lang::"
                   + locale.getLanguage()
                   + " bundle::"
                   + bundleName
                   + " key::"
                   + key
                   + " value::"
                   + value);
           logText.append(
               i18nMgr.getPropertiesFile(
                       locale, bundleName, I18nModule.getPropertyFilesBaseDir(locale, bundleName))
                   + " empty Key detected in lang"
                   + locale.getLanguage()
                   + " bundle::"
                   + bundleName
                   + " key::"
                   + key
                   + " value::"
                   + value
                   + "\n");
           if (reallyRemoveIt) {
             deleteKey(locale, bundleName, key);
           }
         }
         counter++;
       } // each key
     } // each bundle
   }
   log.info(counter + " empty Keys got removed!");
 }
  /** @param reallyRemoveIt true: really remove it; false: dry run, only produce logging */
  public void removeReferenceLanguageCopiesTask(boolean reallyRemoveIt) {
    List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
    // don't remove EN and DE here, this is a shared Map!!
    int counter = 0;
    int aliasCounter = 0;
    // prepare exclusion list
    String exKeys =
        FileUtils.load(
            new File(
                I18nModule.getTransToolApplicationLanguagesSrcDir()
                    + "/org/olat/lms/commons/i18n/devtools/exclusionKeys.txt"),
            "UTF-8");
    String[] exArray = exKeys.split("\n");
    List<String> exList = new ArrayList<String>(Arrays.asList(exArray));

    Set<String> allLangs = getAllLanguages();
    for (String langKey : allLangs) {
      Locale locale = i18nMgr.getLocaleOrNull(langKey);
      if (locale.toString().equals("de") || locale.toString().equals("en")) {
        // don't compare with DE and EN itself
        continue;
      }
      for (String bundleName : allBundles) {
        Properties properties =
            i18nMgr.getPropertiesWithoutResolvingRecursively(locale, bundleName);
        Properties refPropDe =
            i18nMgr.getPropertiesWithoutResolvingRecursively(new Locale("de"), bundleName);
        Properties refPropEn =
            i18nMgr.getPropertiesWithoutResolvingRecursively(new Locale("en"), bundleName);
        Set<Object> keys = properties.keySet();
        for (Object keyObj : keys) {
          String key = (String) keyObj;
          // dont handle if in exclusion list
          if (!exList.contains(key)) {
            String value = properties.getProperty(key);
            // get ref-lang. value and compare:
            boolean foundInReferenceDe = false;
            boolean foundInReferenceEn = false;
            if (value.equals(refPropDe.getProperty(key))) {
              log.info(
                  "Value of Key found in reference Language DE. lang::"
                      + locale.getLanguage()
                      + " bundle::"
                      + bundleName
                      + " key::"
                      + key
                      + " value::"
                      + value);
              foundInReferenceDe = true;
            }
            if (value.equals(refPropEn.getProperty(key))) {
              log.info(
                  "Value of Key found in reference Language EN. lang::"
                      + locale.getLanguage()
                      + " bundle::"
                      + bundleName
                      + " key::"
                      + key
                      + " value::"
                      + value);
              foundInReferenceEn = true;
            }
            // probably an alias if found in both ref. lang.
            boolean readyToDelete = (foundInReferenceDe || foundInReferenceEn);
            if (foundInReferenceDe && foundInReferenceEn) {
              log.info(
                  "Matching value in both reference languages. lang::"
                      + locale.getLanguage()
                      + " bundle::"
                      + bundleName
                      + " key::"
                      + key
                      + " value::"
                      + value);
              readyToDelete = false;
              aliasCounter++;
            }
            if (readyToDelete && reallyRemoveIt) {
              deleteKey(locale, bundleName, key);
            }
            if (readyToDelete) {
              counter++;
              logText.append(
                  i18nMgr.getPropertiesFile(
                          locale,
                          bundleName,
                          I18nModule.getPropertyFilesBaseDir(locale, bundleName))
                      + " value of key found in reference -> remove lang::"
                      + locale.getLanguage()
                      + " bundle::"
                      + bundleName
                      + " key::"
                      + key
                      + " value::"
                      + value
                      + "\n");
            }
          }
        }
      }
    }
    log.info(counter + " Keys found/deleted with values copied from only one reference languages!");
    log.info(aliasCounter + " Keys which seems to be alias found and NOT deleted!");
  }
  protected void changeReferencesInValues(
      String originBundleName, String targetBundleName, String origKey, String targetKey) {
    // operation:
    boolean movePackage = false;
    boolean renameKey = false;
    if (!originBundleName.equals(targetBundleName)) movePackage = true;
    if (!origKey.equals(targetKey)) renameKey = true;
    int counter = 0;
    Pattern resolvingKeyPattern =
        Pattern.compile("\\$\\{?(" + originBundleName + ")+:([\\w\\.\\-]*[\\w\\-])\\}?");

    List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
    Set<String> allLangs = getAllLanguages();
    for (String langKey : allLangs) {
      Locale locale = i18nMgr.getLocaleOrNull(langKey);

      for (String bundleName : allBundles) {
        Properties properties =
            i18nMgr.getPropertiesWithoutResolvingRecursively(locale, bundleName);
        Set<Object> keys = properties.keySet();

        for (Object keyObj : keys) {
          String key = (String) keyObj;
          String value = properties.getProperty(key);

          Matcher matcher = resolvingKeyPattern.matcher(value);
          int lastPos = 0;
          while (matcher.find()) {
            String matchedKey = matcher.group(2);
            String matchedBundle = matcher.group(1);
            if (matchedKey.equals(origKey)
                && ((matchedBundle == null && bundleName.equals(originBundleName))
                    || originBundleName.equals(matchedBundle))) {
              StringBuffer newValue = new StringBuffer();
              newValue.append(value.substring(0, matcher.start()));
              newValue.append("$");
              if (movePackage) {
                if (!targetBundleName.equals(matchedBundle)) {
                  newValue.append(targetBundleName);
                }
              }
              newValue.append(":");
              if (renameKey) {
                newValue.append(targetKey);
              } else {
                newValue.append(origKey);
              }

              lastPos = matcher.end();
              newValue.append(value.substring(lastPos));
              log.info("Key:: " + key + " should get changed to value:: " + newValue.toString());
              logText.append(
                  i18nMgr.getPropertiesFile(
                          locale,
                          bundleName,
                          I18nModule.getPropertyFilesBaseDir(locale, bundleName))
                      + " update reference in lang::"
                      + locale.getLanguage()
                      + " bundle::"
                      + bundleName
                      + " key::"
                      + key
                      + " value::"
                      + value
                      + " \n\t to new value:: "
                      + newValue.toString()
                      + "\n");
              counter++;
              // changeValueForSingleKey(locale, bundleName, key, newValue.toString());
            }
          }
        } // each key
      }
    }
    log.info(counter + " values have been updated.");
  }