private static String convertToneNumber2ToneMark(final String pinyinStr) {
    String lowerCasePinyinStr = pinyinStr.toLowerCase();

    if (lowerCasePinyinStr.matches("[a-z]*[1-5]?")) {
      final char defautlCharValue = '$';
      final int defautlIndexValue = -1;

      char unmarkedVowel = defautlCharValue;
      int indexOfUnmarkedVowel = defautlIndexValue;

      final char charA = 'a';
      final char charE = 'e';
      final String ouStr = "ou";
      final String allUnmarkedVowelStr = "aeiouv";
      final String allMarkedVowelStr = "āáăàaēéĕèeīíĭìiōóŏòoūúŭùuǖǘǚǜü";

      if (lowerCasePinyinStr.matches("[a-z]*[1-5]")) {

        int tuneNumber =
            Character.getNumericValue(lowerCasePinyinStr.charAt(lowerCasePinyinStr.length() - 1));

        int indexOfA = lowerCasePinyinStr.indexOf(charA);
        int indexOfE = lowerCasePinyinStr.indexOf(charE);
        int ouIndex = lowerCasePinyinStr.indexOf(ouStr);

        if (-1 != indexOfA) {
          indexOfUnmarkedVowel = indexOfA;
          unmarkedVowel = charA;
        } else if (-1 != indexOfE) {
          indexOfUnmarkedVowel = indexOfE;
          unmarkedVowel = charE;
        } else if (-1 != ouIndex) {
          indexOfUnmarkedVowel = ouIndex;
          unmarkedVowel = ouStr.charAt(0);
        } else {
          for (int i = lowerCasePinyinStr.length() - 1; i >= 0; i--) {
            if (String.valueOf(lowerCasePinyinStr.charAt(i)).matches(
                "[" + allUnmarkedVowelStr + "]")) {
              indexOfUnmarkedVowel = i;
              unmarkedVowel = lowerCasePinyinStr.charAt(i);
              break;
            }
          }
        }

        if ((defautlCharValue != unmarkedVowel) && (defautlIndexValue != indexOfUnmarkedVowel)) {
          int rowIndex = allUnmarkedVowelStr.indexOf(unmarkedVowel);
          int columnIndex = tuneNumber - 1;

          int vowelLocation = rowIndex * 5 + columnIndex;

          char markedVowel = allMarkedVowelStr.charAt(vowelLocation);

            return lowerCasePinyinStr.substring(0, indexOfUnmarkedVowel).replaceAll("v",
                    "ü") + markedVowel + lowerCasePinyinStr.substring(indexOfUnmarkedVowel + 1,
                    lowerCasePinyinStr.length() - 1).replaceAll("v", "ü");

        } else
        // error happens in the procedure of locating vowel
        {
          return lowerCasePinyinStr;
        }
      } else
      // input string has no any tune number
      {
        // only replace v with ü (umlat) character
        return lowerCasePinyinStr.replaceAll("v", "ü");
      }
    } else
    // bad format
    {
      return lowerCasePinyinStr;
    }
  }