### Question:
StringFunctions { public static String urlDecode(final String encoded, final Charset charset) throws MyRuleException { final byte[] buff = new byte[encoded.length()]; int buffIndex = 0; for (int i = 0; i < encoded.length(); i++) { if (encoded.charAt(i) == '%') { if (i + 2 >= encoded.length()) { throw new MyRuleException("More characters are required after " + encoded.substring(i) + "."); } try { buff[buffIndex++] = (byte) Integer.parseInt(encoded.substring(i + 1, i + 3), 16); } catch (final NumberFormatException e) { throw new MyRuleException(e); } i += 2; } else if (allowed(encoded.charAt(i))) { buff[buffIndex++] = (byte) encoded.charAt(i); } else if (encoded.charAt(i) == '+') { buff[buffIndex++] = ' '; } else { throw new MyRuleException("Invalid character ( " + encoded.charAt(i) + " ) at " + i + "."); } } return new String(Arrays.copyOf(buff, buffIndex), charset); } private  StringFunctions(); static int getWidth(final String str, final Charset charset); static int getWidth(final String str); static String urlDecode(final String encoded, final Charset charset); static String urlEncode(final String string, final Charset charset);  }### Answer:
@Test public void testUrlDecode() throws MyRuleException { Assert.assertEquals("てすとスレ", StringFunctions.urlDecode("%82%C4%82%B7%82%C6%83X%83%8C", Charset.forName("Shift_JIS"))); Assert.assertEquals("名無し", StringFunctions.urlDecode("%96%BC%96%B3%82%B5", Charset.forName("Shift_JIS"))); Assert.assertEquals("新規スレッド作成", StringFunctions.urlDecode("%90V%8BK%83X%83%8C%83b%83h%8D%EC%90%AC", Charset.forName("Shift_JIS"))); Assert.assertEquals("てすと", StringFunctions.urlDecode("%82%C4%82%B7%82%C6", Charset.forName("Shift_JIS"))); Assert.assertEquals("書き込む", StringFunctions.urlDecode("%8F%91%82%AB%8D%9E%82%DE", Charset.forName("Shift_JIS"))); }