From 35a9bdd705f62f8a220cfdd3c3409d4edea9a3b8 Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Sun, 2 Oct 2016 13:51:15 +0200 Subject: [PATCH 1/3] Fixed arabic stuff --- src/main/java/com/mapcode/Alphabet.java | 3 +- src/main/java/com/mapcode/DataModel.java | 0 src/main/java/com/mapcode/Decoder.java | 243 ++++++++++++++++++-- src/main/java/com/mapcode/Encoder.java | 0 src/main/java/com/mapcode/Territory.java | 0 src/test/java/com/mapcode/AlphabetTest.java | 87 +++++-- src/test/java/com/mapcode/MapcodeTest.java | 6 +- 7 files changed, 300 insertions(+), 39 deletions(-) mode change 100755 => 100644 src/main/java/com/mapcode/DataModel.java mode change 100755 => 100644 src/main/java/com/mapcode/Decoder.java mode change 100755 => 100644 src/main/java/com/mapcode/Encoder.java mode change 100755 => 100644 src/main/java/com/mapcode/Territory.java diff --git a/src/main/java/com/mapcode/Alphabet.java b/src/main/java/com/mapcode/Alphabet.java index b6a61a8..29cad68 100644 --- a/src/main/java/com/mapcode/Alphabet.java +++ b/src/main/java/com/mapcode/Alphabet.java @@ -45,7 +45,8 @@ public enum Alphabet { ARMENIAN(10), BENGALI(11), GURMUKHI(12), - TIBETAN(13); + TIBETAN(13), + ARABIC(14); /** * The numeric code is synonym for the alphanumeric code. Used in the decoder. diff --git a/src/main/java/com/mapcode/DataModel.java b/src/main/java/com/mapcode/DataModel.java old mode 100755 new mode 100644 diff --git a/src/main/java/com/mapcode/Decoder.java b/src/main/java/com/mapcode/Decoder.java old mode 100755 new mode 100644 index 7f577ef..d8176f4 --- a/src/main/java/com/mapcode/Decoder.java +++ b/src/main/java/com/mapcode/Decoder.java @@ -230,7 +230,7 @@ public Unicode2Ascii(final char min, final char max, @Nonnull final String conve private final static char[][] ASCII2LANGUAGE = { // Character: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 /* Roman */ {'\u0041', '\u0042', '\u0043', '\u0044', '\u0045', '\u0046', '\u0047', '\u0048', '\u0049', '\u004a', '\u004b', '\u004c', '\u004d', '\u004e', '\u004f', '\u0050', '\u0051', '\u0052', '\u0053', '\u0054', '\u0055', '\u0056', '\u0057', '\u0058', '\u0059', '\u005a', '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039'}, // Roman - /* Greek */ {'\u0391', '\u0392', '\u039e', '\u0394', MISSCODE, '\u0395', '\u0393', '\u0397', '\u0399', '\u03a0', '\u039a', '\u039b', '\u039c', '\u039d', '\u039f', '\u03a1', '\u0398', '\u03a8', '\u03a3', '\u03a4', MISSCODE, '\u03a6', '\u03a9', '\u03a7', '\u03a5', '\u0396', '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039'}, // Greek + /* Greek */ {'\u0391', '\u0392', '\u039e', '\u0394', '\u0388', '\u0395', '\u0393', '\u0397', '\u0399', '\u03a0', '\u039a', '\u039b', '\u039c', '\u039d', '\u039f', '\u03a1', '\u0398', '\u03a8', '\u03a3', '\u03a4', '\u0389', '\u03a6', '\u03a9', '\u03a7', '\u03a5', '\u0396', '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039'}, // Greek /* Cyrillic */ {'\u0410', '\u0412', '\u0421', '\u0414', '\u0415', '\u0416', '\u0413', '\u041d', '\u0418', '\u041f', '\u041a', '\u041b', '\u041c', '\u0417', '\u041e', '\u0420', '\u0424', '\u042f', '\u0426', '\u0422', '\u042d', '\u0427', '\u0428', '\u0425', '\u0423', '\u0411', '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039'}, // Cyrillic /* Hebrew */ {'\u05d0', '\u05d1', '\u05d2', '\u05d3', '\u05e3', '\u05d4', '\u05d6', '\u05d7', '\u05d5', '\u05d8', '\u05d9', '\u05da', '\u05db', '\u05dc', '\u05e1', '\u05dd', '\u05de', '\u05e0', '\u05e2', '\u05e4', '\u05e5', '\u05e6', '\u05e7', '\u05e8', '\u05e9', '\u05ea', '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039'}, // Hebrew /* Hindi */ {'\u0905', '\u0915', '\u0917', '\u0918', '\u090f', '\u091a', '\u091c', '\u091f', MISSCODE, '\u0920', '\u0923', '\u0924', '\u0926', '\u0927', MISSCODE, '\u0928', '\u092a', '\u092d', '\u092e', '\u0930', '\u092b', '\u0932', '\u0935', '\u0938', '\u0939', '\u0921', '\u0966', '\u0967', '\u0968', '\u0969', '\u096a', '\u096b', '\u096c', '\u096d', '\u096e', '\u096f'}, // Hindi @@ -242,12 +242,13 @@ public Unicode2Ascii(final char min, final char max, @Nonnull final String conve /* Armenian */ {'\u0556', '\u0532', '\u0533', '\u0534', '\u0535', '\u0538', '\u0539', '\u053a', '\u053b', '\u053d', '\u053f', '\u0540', '\u0541', '\u0543', '\u0555', '\u0547', '\u0548', '\u054a', '\u054d', '\u054e', '\u0545', '\u054f', '\u0550', '\u0551', '\u0552', '\u0553', '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039'}, // Armenian /* Bengali */ {'\u0985', '\u098c', '\u0995', '\u0996', '\u098f', '\u0997', '\u0999', '\u099a', MISSCODE, '\u099d', '\u09a0', '\u09a1', '\u09a2', '\u09a3', MISSCODE, '\u09a4', '\u09a5', '\u09a6', '\u09a8', '\u09aa', '\u0993', '\u09ac', '\u09ad', '\u09af', '\u09b2', '\u09b9', '\u09e6', '\u09e7', '\u09e8', '\u09e9', '\u09ea', '\u09eb', '\u09ec', '\u09ed', '\u09ee', '\u09ef'}, // Bengali /* Gurmukhi */ {'\u0a05', '\u0a15', '\u0a17', '\u0a18', '\u0a0f', '\u0a1a', '\u0a1c', '\u0a1f', MISSCODE, '\u0a20', '\u0a23', '\u0a24', '\u0a26', '\u0a27', MISSCODE, '\u0a28', '\u0a2a', '\u0a2d', '\u0a2e', '\u0a30', '\u0a2b', '\u0a32', '\u0a35', '\u0a38', '\u0a39', '\u0a21', '\u0a66', '\u0a67', '\u0a68', '\u0a69', '\u0a6a', '\u0a6b', '\u0a6c', '\u0a6d', '\u0a6e', '\u0a6f'}, // Gurmukhi - /* Tibetan */ {'\u0f58', '\u0f40', '\u0f41', '\u0f42', '\u0f64', '\u0f44', '\u0f45', '\u0f46', MISSCODE, '\u0f47', '\u0f4a', '\u0f4c', '\u0f4e', '\u0f4f', MISSCODE, '\u0f51', '\u0f53', '\u0f54', '\u0f56', '\u0f5e', '\u0f65', '\u0f5f', '\u0f61', '\u0f62', '\u0f63', '\u0f66', '\u0f20', '\u0f21', '\u0f22', '\u0f23', '\u0f24', '\u0f25', '\u0f26', '\u0f27', '\u0f28', '\u0f29'}, // Tibetan + /* Tibetan */ {'\u0f58', '\u0f40', '\u0f41', '\u0f42', '\u0f64', '\u0f44', '\u0f45', '\u0f46', MISSCODE, '\u0f47', '\u0f49', '\u0f55', '\u0f50', '\u0f4f', MISSCODE, '\u0f51', '\u0f53', '\u0f54', '\u0f56', '\u0f5e', '\u0f60', '\u0f5f', '\u0f61', '\u0f62', '\u0f63', '\u0f66', '\u0f20', '\u0f21', '\u0f22', '\u0f23', '\u0f24', '\u0f25', '\u0f26', '\u0f27', '\u0f28', '\u0f29'}, // Tibetan + /* Arabic */ {'\u0628', '\u062a', '\u062d', '\u062e', '\u0649', '\u062f', '\u0630', '\u0631', '\u0049', '\u0632', '\u0633', '\u0634', '\u0635', '\u0636', '\u004f', '\u0637', '\u0638', '\u0639', '\u063a', '\u0641', '\u0642', '\u0643', '\u0644', '\u0645', '\u0646', '\u0648', '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039'}, // Arabic }; private final static Unicode2Ascii[] UNICODE2ASCII = { /* Roman */ new Unicode2Ascii('\u0041', '\u005a', "ABCDEFGHIJKLMNOPQRSTUVWXYZ"), // Roman - /* Greek */ new Unicode2Ascii('\u0391', '\u03a9', "ABGDFZHQIKLMNCOJP?STYVXRW"), // Greek + /* Greek */ new Unicode2Ascii('\u0388', '\u03a9', "EU???????ABGDFZHQIKLMNCOJP?STYVXRW"), // Greek /* Cyrillic */ new Unicode2Ascii('\u0410', '\u042f', "AZBGDEFNI?KLMHOJPCTYQXSVW????U?R"), // Cyrillic /* Hebrew */ new Unicode2Ascii('\u05d0', '\u05ea', "ABCDFIGHJKLMNPQ?ROSETUVWXYZ"), // Hebrew /* Hindi */ new Unicode2Ascii('\u0905', '\u0939', "A?????????E?????B?CD?F?G??HJZ?KL?MNP?QU?RS?T?V??W??XY"), // Hindi @@ -259,7 +260,8 @@ public Unicode2Ascii(final char min, final char max, @Nonnull final String conve /* Armenian */ new Unicode2Ascii('\u0532', '\u0556', "BCDE??FGHI?J?KLM?N?U?PQ?R??STVWXYZ?OA"), // Armenian /* Bengali */ new Unicode2Ascii('\u0985', '\u09b9', "A??????B??E???U?CDF?GH??J??KLMNPQR?S?T?VW?X??Y??????Z"), // Bengali /* Gurmukhi */ new Unicode2Ascii('\u0a05', '\u0a39', "A?????????E?????B?CD?F?G??HJZ?KL?MNP?QU?RS?T?V??W??XY"), // Gurmukhi - /* Tibetan */ new Unicode2Ascii('\u0f40', '\u0f66', "BCD?FGHJ??K?L?MN?P?QR?S?A?????TV?WXYEUZ"), // Tibetan + /* Tibetan */ new Unicode2Ascii('\u0f40', '\u0f66', "BCD?FGHJ?K?????NMP?QRLS?A?????TVUWXYE?Z"), // Tibetan + /* Arabic */ new Unicode2Ascii('\u0628', '\u0649', "A?B??CDFGHJKLMNPQRS??????TUVWXY?ZE"), // Arabic /* Hindi */ new Unicode2Ascii('\u0966', '\u096f', ""), /* Malai */ new Unicode2Ascii('\u0d66', '\u0d6f', ""), @@ -269,7 +271,7 @@ public Unicode2Ascii(final char min, final char max, @Nonnull final String conve /* Tibetan */ new Unicode2Ascii('\u0f20', '\u0f29', ""), // Lowercase variants: - /* Greek */ new Unicode2Ascii('\u03B1', '\u03c9', "ABGDFZHQIKLMNCOJP?STYVXRW"), + /* Greek */ new Unicode2Ascii('\u03ad', '\u03c9', "EU??ABGDFZHQIKLMNCOJP?STYVXRW"), /* Georgian */ new Unicode2Ascii('\u10d0', '\u10ef', "AB?CE?D?UF?GHOJ?KLMINPQRSTVW?XYZ"), /* Armenian */ new Unicode2Ascii('\u0562', '\u0586', "BCDE??FGHI?J?KLM?N?U?PQ?R??STVWXYZ?OA") }; @@ -665,27 +667,37 @@ static String decodeUTF16(final String mapcode) { } result = Encoder.aeuPack(unpacked, false); } - return result; + + if (isAbjadScript(mapcode)) { + return convertFromAbjad(result); + } else { + return result; + } } - static String encodeUTF16(final String mapcode, final int alphabetCode) throws IllegalArgumentException { + static String encodeUTF16(final String mapcodeInput, final int alphabetCode) throws IllegalArgumentException { + + final String mapcode; + if ((alphabetCode == Alphabet.GREEK.getNumber()) || + (alphabetCode == Alphabet.HEBREW.getNumber()) || + (alphabetCode == Alphabet.ARABIC.getNumber())) { + mapcode = convertToAbjad(mapcodeInput); + } else { + mapcode = mapcodeInput; + } + final String mapcodeToEncode; - if (ASCII2LANGUAGE[alphabetCode][4] == MISSCODE) { - - // Alphabet does not contain 'E' (Greek). - if (mapcode.matches("^.*[EU].*")) { - final String unpacked = aeuUnpack(mapcode); - if (unpacked.isEmpty()) { - throw new IllegalArgumentException("encodeToAlphabetCode: cannot encode '" + mapcode + - "' to alphabet " + alphabetCode); - } - mapcodeToEncode = Encoder.aeuPack(unpacked, true); - } else { - mapcodeToEncode = mapcode; + if ((alphabetCode == Alphabet.GREEK.getNumber()) && ((mapcode.indexOf('E') != -1) || (mapcode.indexOf('U') != -1))) { + final String unpacked = aeuUnpack(mapcode); + if (unpacked.isEmpty()) { + throw new IllegalArgumentException("encodeToAlphabetCode: cannot encode '" + mapcode + + "' to alphabet " + alphabetCode); } + mapcodeToEncode = Encoder.aeuPack(unpacked, true); } else { mapcodeToEncode = mapcode; } + final StringBuilder sb = new StringBuilder(); for (char ch : mapcodeToEncode.toCharArray()) { ch = Character.toUpperCase(ch); @@ -821,4 +833,197 @@ private static MapcodeZone decodeExtension(final int y, final int x, final int d } return mapcodeZone; } + + private static boolean isAbjadScript(final String argStr) { + for (final char ch : argStr.toCharArray()) { + int c = (int) ch; + if ((c >= 1576) && (c <= 1609)) { + return true; // Arabic + } + if ((c >= 1488) && (c <= 1514)) { + return true; // Hebrew + } + if ((c >= 904) && (c <= 969)) { + return true; // Greek 0x388-0x3C9 + } + } + return false; + } + + private static String convertFromAbjad(final String mapcode) { + // split into prefix, s, postfix + int p = mapcode.lastIndexOf(' '); + if (p < 0) { + p = 0; + } else { + p++; + } + final String prefix = mapcode.substring(0, p); + String remainder = mapcode.substring(p); + final String postfix; + final int h = remainder.indexOf('-'); + final String s; + if (h > 0) { + postfix = remainder.substring(h); + s = aeuUnpack(remainder.substring(0, h)); + } else { + postfix = ""; + s = aeuUnpack(remainder); + } + + final int len = s.length(); + final int dot = s.indexOf('.'); + if ((dot < 2) || (dot > 5)) { + return mapcode; + } + final int form = (10 * dot) + (len - dot - 1); + + String newstr = ""; + if (form == 23) { + final int c = (DECODE_CHARS[(int) s.charAt(3)] * 8) + (DECODE_CHARS[(int) s.charAt(4)] - 18); + if ((c >= 0) && (c < 31)) { + newstr = s.substring(0, 2) + '.' + Data.ENCODE_CHARS[c] + s.charAt(5); + } + } else if (form == 24) { + final int c = (DECODE_CHARS[(int) s.charAt(3)] * 8) + (DECODE_CHARS[(int) s.charAt(4)] - 18); + if ((c >= 32) && (c < 63)) { + newstr = s.substring(0, 2) + Data.ENCODE_CHARS[c - 32] + '.' + s.charAt(5) + s.charAt(6); + } else if ((c >= 0) && (c < 31)) { + newstr = s.substring(0, 2) + '.' + Data.ENCODE_CHARS[c % 31] + s.charAt(5) + s.charAt(6); + } + } else if (form == 34) { + final int c = (DECODE_CHARS[(int) s.charAt(2)] * 10) + (DECODE_CHARS[(int) s.charAt(5)] - 7); + if ((c >= 0) && (c < 31)) { + newstr = s.substring(0, 2) + '.' + Data.ENCODE_CHARS[c] + s.charAt(4) + s.charAt(6) + s.charAt(7); + } else if ((c >= 31) && (c < 62)) { + newstr = s.substring(0, 2) + Data.ENCODE_CHARS[c - 31] + '.' + s.charAt(4) + s.charAt(6) + s.charAt(7); + } else if ((c >= 62) && (c < 93)) { + newstr = s.substring(0, 2) + Data.ENCODE_CHARS[c - 62] + s.charAt(4) + '.' + s.charAt(6) + s.charAt(7); + } + } else if (form == 35) { + final int c = ((DECODE_CHARS[(int) s.charAt(2)] * 8) + (DECODE_CHARS[(int) s.charAt(6)] - 18)); + if ((c >= 32) && (c < 63)) { + newstr = s.substring(0, 2) + Data.ENCODE_CHARS[c - 32] + s.charAt(4) + '.' + s.charAt(5) + s.charAt(7) + s.charAt(8); + } else if ((c >= 0) && (c < 31)) { + newstr = s.substring(0, 2) + Data.ENCODE_CHARS[c] + '.' + s.charAt(4) + s.charAt(5) + s.charAt(7) + s.charAt(8); + } + } else if (form == 45) { + final int c = (DECODE_CHARS[(int) s.charAt(2)] * 100) + (DECODE_CHARS[(int) s.charAt(5)] * 10) + (DECODE_CHARS[(int) s.charAt(8)] - 39); + if ((c >= 0) && (c < 961)) { + newstr = s.substring(0, 2) + Data.ENCODE_CHARS[c / 31] + s.charAt(3) + '.' + s.charAt(6) + s.charAt(7) + s.charAt(9) + Data.ENCODE_CHARS[c % 31]; + } + } else if (form == 55) { + final int c = (DECODE_CHARS[(int) s.charAt(2)] * 100) + (DECODE_CHARS[(int) s.charAt(6)] * 10) + (DECODE_CHARS[(int) s.charAt(9)] - 39); + if ((c >= 0) && (c < 961)) { + newstr = s.substring(0, 2) + Data.ENCODE_CHARS[c / 31] + s.charAt(3) + s.charAt(4) + '.' + s.charAt(7) + s.charAt(8) + s.charAt(10) + Data.ENCODE_CHARS[c % 31]; + } + } + + if (newstr.isEmpty()) { + return mapcode; + } + return prefix + Encoder.aeuPack(newstr, false) + postfix; + } + + private static String convertToAbjad(final String mapcode) { + String str; + final String rest; + final int h = mapcode.indexOf('-'); + if (h > 0) { + rest = mapcode.substring(h); + str = aeuUnpack(mapcode.substring(0, h)); + } else { + rest = ""; + str = aeuUnpack(mapcode); + } + + final int len = str.length(); + final int dot = str.indexOf('.'); + if ((dot < 2) || (dot > 5)) { + return mapcode; + } + final int form = (10 * dot) + (len - dot - 1); + + // see if >2 non-digits in a row + int inarow = 0; + for (final char ch : str.toCharArray()) { + if (ch != '.') { + inarow++; + if ((ch >= '0') && (ch <= '9')) { + inarow = 0; + } else if (inarow > 2) { + break; + } + } + } + + if ((inarow < 3) && ((form == 22) || (form == 32) || (form == 33) || (form == 42) || (form == 43) || (form == 44) || (form == 54))) { + // no need to do anything + return mapcode; + } + // determine the code of the second non-digit character (before or after the dot) + int c = DECODE_CHARS[(int) str.charAt(2)]; + if (c < 0) { + c = DECODE_CHARS[(int) str.charAt(3)]; + } + if (c < 0) { + return mapcode; // bad character + } + + // create 2 or 3 new digits + final char c1; + final char c2; + final char c3; + if (form >= 44) { + c = (c * 31) + DECODE_CHARS[(int) str.charAt(len - 1)] + 39; + if ((c < 39) || (c > 999)) { + return mapcode; // out of range (last character must be bad) + } + c1 = Data.ENCODE_CHARS[c / 100]; + c2 = Data.ENCODE_CHARS[((c % 100) / 10)]; + c3 = Data.ENCODE_CHARS[c % 10]; + } else if (len == 7) { + if (form == 24) { + c += 7; + } else if (form == 33) { + c += 38; + } else if (form == 42) { + c += 69; + } + c1 = Data.ENCODE_CHARS[c / 10]; + c2 = Data.ENCODE_CHARS[c % 10]; + c3 = '?'; + } else { + c1 = Data.ENCODE_CHARS[2 + (c / 8)]; + c2 = Data.ENCODE_CHARS[2 + (c % 8)]; + c3 = '?'; + } + + // re-order the characters + if (form == 22) { + str = str.substring(0, 2) + '.' + c1 + c2 + str.charAt(4); + } else if (form == 23) { + str = str.substring(0, 2) + '.' + c1 + c2 + str.charAt(4) + str.charAt(5); + } else if (form == 32) { + str = str.substring(0, 2) + '.' + (char) ((int) c1 + 4) + c2 + str.charAt(4) + str.charAt(5); + } else if (form == 24) { + str = str.substring(0, 2) + c1 + '.' + str.charAt(4) + c2 + str.charAt(5) + str.charAt(6); + } else if (form == 33) { + str = str.substring(0, 2) + c1 + '.' + str.charAt(4) + c2 + str.charAt(5) + str.charAt(6); + } else if (form == 42) { + str = str.substring(0, 2) + c1 + '.' + str.charAt(3) + c2 + str.charAt(5) + str.charAt(6); + } else if (form == 43) { + str = str.substring(0, 2) + (char) ((int) c1 + 4) + '.' + str.charAt(3) + str.charAt(5) + c2 + str.charAt(6) + str.charAt(7); + } else if (form == 34) { + str = str.substring(0, 2) + c1 + '.' + str.charAt(4) + str.charAt(5) + c2 + str.charAt(6) + str.charAt(7); + } else if (form == 44) { + str = str.substring(0, 2) + c1 + str.charAt(3) + '.' + c2 + str.charAt(5) + str.charAt(6) + c3 + str.charAt(7); + } else if (form == 54) { + str = str.substring(0, 2) + c1 + str.charAt(3) + str.charAt(4) + '.' + c2 + str.charAt(6) + str.charAt(7) + c3 + str.charAt(8); + } else { + // not a valid mapcode form + return mapcode; + } + return Encoder.aeuPack(str + rest, false); + } } diff --git a/src/main/java/com/mapcode/Encoder.java b/src/main/java/com/mapcode/Encoder.java old mode 100755 new mode 100644 diff --git a/src/main/java/com/mapcode/Territory.java b/src/main/java/com/mapcode/Territory.java old mode 100755 new mode 100644 diff --git a/src/test/java/com/mapcode/AlphabetTest.java b/src/test/java/com/mapcode/AlphabetTest.java index 26de862..58b56c4 100644 --- a/src/test/java/com/mapcode/AlphabetTest.java +++ b/src/test/java/com/mapcode/AlphabetTest.java @@ -28,25 +28,80 @@ public class AlphabetTest { private static final Logger LOG = LoggerFactory.getLogger(AlphabetTest.class); + private static final String[] CODE_TEST_PAIRS = { + "26.53UK", "\u039161.328\u03A5", + "FR.B016", "\u0395\u03A81.0716", + "000.EU", "\u0391\u0030\u0030.23", + "PQ.YZ", "\u03a1\u0398.57\u0396", + "PQ.XYZ", "\u03a1\u0398.56\u03a5\u0396", + "PQR.YZ", "\u03a1\u0398.89\u03a5\u0396", + "PQ.RXYZ", "\u03a1\u03983.\u03a70\u03a5\u0396", + "PQR.XYZ", "\u03a1\u03986.\u03a71\u03a5\u0396", + "PQRX.YZ", "\u03a1\u03989.\u03a72\u03a5\u0396", + "PQR.SXYZ", "\u03a1\u03984.\u03a3\u03a79\u03a5\u0396", + "PQRS.XYZ", "\u03a1\u03988.\u03a3\u03a79\u03a5\u0396", + "PQRS.WXYZ", "\u03a1\u03987\u03a3.8\u03a9\u03a72\u03a5", + "PQRST.WXYZ", "\u03a1\u03987\u03a3\u03a4.8\u03a9\u03a72\u03a5", + "P4.YZ", "\u03a14.\u03a5\u0396", + "PQ.4Z", "\u03a1\u0398.4\u0396", + "PQ.4YZ", "\u03a1\u0398.26\u03a5\u0396", + "PQ4.YZ", "\u03a1\u03984.\u03a5\u0396", + "PQ.46YZ", "\u03a1\u03981.61\u03a5\u0396", + "PQ4.6YZ", "\u03a1\u03984.6\u03a5\u0396", + "PQ46.YZ", "\u03a1\u039846.\u03a5\u0396", + "PQ4.S6YZ", "\u03a1\u03982.\u03a366\u03a5\u0396", + "PQ4S.6YZ", "\u03a1\u03984\u03a3.6\u03a5\u0396", + "PQ4S.W6YZ", "\u03a1\u03984\u03a3.\u03a96\u03a5\u0396", + "PQ4PQ.6YZ9", "\u03a1\u03984\u03a1\u0398.6\u03a5\u03969", + "PQ.YZ-BCD", "\u03a1\u0398.57\u0396-\u0392\u039e\u0394", + "PQ.XYZ-BCD", "\u03a1\u0398.56\u03a5\u0396-\u0392\u039e\u0394", + "PQR.YZ-BCD", "\u03a1\u0398.89\u03a5\u0396-\u0392\u039e\u0394", + "PQ.RXYZ-BCD", "\u03a1\u03983.\u03a70\u03a5\u0396-\u0392\u039e\u0394", + "PQR.XYZ-BCD", "\u03a1\u03986.\u03a71\u03a5\u0396-\u0392\u039e\u0394", + "PQRX.YZ-BCD", "\u03a1\u03989.\u03a72\u03a5\u0396-\u0392\u039e\u0394", + "PQR.SXYZ-BCD", "\u03a1\u03984.\u03a3\u03a79\u03a5\u0396-\u0392\u039e\u0394", + "PQRS.XYZ-BCD", "\u03a1\u03988.\u03a3\u03a79\u03a5\u0396-\u0392\u039e\u0394", + "PQRS.WXYZ-BCD", "\u03a1\u03987\u03a3.8\u03a9\u03a72\u03a5-\u0392\u039e\u0394", + "PQRST.WXYZ-BCD", "\u03a1\u03987\u03a3\u03a4.8\u03a9\u03a72\u03a5-\u0392\u039e\u0394", + "P4.YZ-BCD", "\u03a14.\u03a5\u0396-\u0392\u039e\u0394", + "PQ.4Z-BCD", "\u03a1\u0398.4\u0396-\u0392\u039e\u0394", + "PQ.4YZ-BCD", "\u03a1\u0398.26\u03a5\u0396-\u0392\u039e\u0394", + "PQ4.YZ-BCD", "\u03a1\u03984.\u03a5\u0396-\u0392\u039e\u0394", + "PQ.46YZ-BCD", "\u03a1\u03981.61\u03a5\u0396-\u0392\u039e\u0394", + "PQ4.6YZ-BCD", "\u03a1\u03984.6\u03a5\u0396-\u0392\u039e\u0394", + "PQ46.YZ-BCD", "\u03a1\u039846.\u03a5\u0396-\u0392\u039e\u0394", + "PQ4.S6YZ-BCD", "\u03a1\u03982.\u03a366\u03a5\u0396-\u0392\u039e\u0394", + "PQ4S.6YZ-BCD", "\u03a1\u03984\u03a3.6\u03a5\u0396-\u0392\u039e\u0394", + "PQ4S.W6YZ-BCD", "\u03a1\u03984\u03a3.\u03a96\u03a5\u0396-\u0392\u039e\u0394", + "PQ4PQ.6YZ9-BCD", "\u03a1\u03984\u03a1\u0398.6\u03a5\u03969-\u0392\u039e\u0394", + "" + }; + @Test public void testConvertToAlphabet() throws Exception { + LOG.info("testConvertToAlphabet"); - convertCodeInAlphabet("\u0397\u03a0.\u03982", Territory.GRC, Alphabet.GREEK, 0); - convertCodeInAlphabet("\u0397\u03a0.\u03982-\u03a62", Territory.GRC, Alphabet.GREEK, 2); - convertCodeInAlphabet("GRC \u0397\u03a0.\u03982-\u03a62", Territory.GRC, Alphabet.GREEK, 2); - - String code = "26.53UK"; - String codeGreek = Mapcode.convertStringToAlphabet(code, Alphabet.GREEK); - String codeAscii = Mapcode.convertStringToPlainAscii(codeGreek); - LOG.info("code = {}, codeGreek = {}, codeAscii = {}", code, codeGreek, codeAscii); - assertEquals(code, codeAscii); - - code = "000.EU"; - codeGreek = Mapcode.convertStringToAlphabet(code, Alphabet.GREEK); - codeAscii = Mapcode.convertStringToPlainAscii(codeGreek); - LOG.info("code = {}, codeGreek = {}, codeAscii = {}", code, codeGreek, codeAscii); - assertEquals(codeGreek, "\u0391\u0030\u0030.23"); - assertEquals(code, codeAscii); + convertCodeInAlphabet("\u0397\u03a0.22", Territory.GRC, Alphabet.GREEK, 0); + convertCodeInAlphabet("\u0397\u03a0.22-\u03a62", Territory.GRC, Alphabet.GREEK, 2); + convertCodeInAlphabet("GRC \u0397\u03a0.22-\u03a62", Territory.GRC, Alphabet.GREEK, 2); + + int i = 0; + while (true) { + final String code = CODE_TEST_PAIRS[i]; + if (code.isEmpty()) { + break; + } + final String codeGreek = Mapcode.convertStringToAlphabet(code, Alphabet.GREEK); + LOG.debug("testConvertToAlphabet: code={}, codeGreek={}", code, codeGreek); + final String expect = CODE_TEST_PAIRS[i + 1]; + if (!expect.isEmpty()) { + assertEquals(codeGreek, expect); + } + final String codeAscii = Mapcode.convertStringToPlainAscii(codeGreek); + LOG.debug("testConvertToAlphabet: code={}, codeGreek={}, codeAscii={}", code, codeGreek, codeAscii); + assertEquals(code, codeAscii); + i += 2; + } } @Test diff --git a/src/test/java/com/mapcode/MapcodeTest.java b/src/test/java/com/mapcode/MapcodeTest.java index 171552d..3b29788 100644 --- a/src/test/java/com/mapcode/MapcodeTest.java +++ b/src/test/java/com/mapcode/MapcodeTest.java @@ -113,7 +113,7 @@ public void checkInvalidPrecisionFormats() { assertFalse(Mapcode.isValidMapcodeFormat("PP.PP-12345Z")); assertFalse(Mapcode.isValidMapcodeFormat("PP.PP-123456Z")); assertFalse(Mapcode.isValidMapcodeFormat("PP.PP-1234567Z")); - assertFalse(Mapcode.isValidMapcodeFormat("PP.PP-123456789")); // more than 8 ePtension characters! + assertFalse(Mapcode.isValidMapcodeFormat("PP.PP-123456789")); // more than 8 extension characters! assertFalse(Mapcode.isValidMapcodeFormat("P.PPP")); assertFalse(Mapcode.isValidMapcodeFormat("PPP.P")); assertFalse(Mapcode.isValidMapcodeFormat("P.PPP-1")); @@ -137,8 +137,8 @@ public void checkPrecisionFormat1() { assertEquals(8, Mapcode.getPrecisionFormat("PP.QQ-12345678")); assertEquals(0, Mapcode.getPrecisionFormat("\u0e9a\u0e97\u0e84 \u0eab\u0ea7\u0e84.\u0ea73\u0eaa")); - assertEquals(1, Mapcode.getPrecisionFormat("\u0f40\u0f64\u0f4c \u0f535\u0f41\u0f42.5\u0f629-\u0f40")); - assertEquals(2, Mapcode.getPrecisionFormat("\u039d\u039b\u0394 \u03a7\u03a6\u0394.\u03a63\u03a9-\u039e7")); + assertEquals(1, Mapcode.getPrecisionFormat("\u0f40\u0f64\u0f55 \u0f535\u0f415.\u0f42\u0f629-\u0f40")); + assertEquals(2, Mapcode.getPrecisionFormat("\u039d\u039b\u0394 \u03a7\u03a68.\u03a63\u03a9-\u039e7")); } @Test(expected = UnknownPrecisionFormatException.class) From 9d91a1402dad3ffaa8678903fec7dab0969b8fc8 Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Sun, 2 Oct 2016 14:08:27 +0200 Subject: [PATCH 2/3] Fixed arabic stuff --- pom.xml | 2 +- src/main/java/com/mapcode/DataModel.java | 2 -- src/main/java/com/mapcode/Decoder.java | 1 + src/main/java/com/mapcode/Encoder.java | 1 - src/main/java/com/mapcode/Mapcode.java | 8 ++++---- src/main/java/com/mapcode/Point.java | 8 ++++---- src/main/java/com/mapcode/Territory.java | 1 - .../com/mapcode/UnknownAlphabetException.java | 3 --- .../mapcode/UnknownPrecisionFormatException.java | 3 --- src/test/java/com/mapcode/DataModelTest.java | 15 +++++---------- src/test/java/com/mapcode/DecoderTest.java | 1 - src/test/java/com/mapcode/EncodeDecodeTest.java | 3 +-- src/test/java/com/mapcode/EncoderTest.java | 2 -- src/test/java/com/mapcode/PointTest.java | 6 +++--- src/test/java/com/mapcode/ReferenceFileTest.java | 6 +----- src/test/java/com/mapcode/TerritoryTest.java | 12 ++++++------ 16 files changed, 26 insertions(+), 48 deletions(-) diff --git a/pom.xml b/pom.xml index fbccedb..b4343f1 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ mapcode jar - 2.2.5-SNAPSHOT + 2.3.0 Mapcode Java Library diff --git a/src/main/java/com/mapcode/DataModel.java b/src/main/java/com/mapcode/DataModel.java index 39b5d84..45a1ba7 100644 --- a/src/main/java/com/mapcode/DataModel.java +++ b/src/main/java/com/mapcode/DataModel.java @@ -170,11 +170,9 @@ public static DataModel getInstance() { i += 4; } } finally { - //noinspection ThrowFromFinallyBlock outputStream.close(); } } finally { - //noinspection ThrowFromFinallyBlock inputStream.close(); } } catch (final IOException e) { diff --git a/src/main/java/com/mapcode/Decoder.java b/src/main/java/com/mapcode/Decoder.java index d8176f4..0479603 100644 --- a/src/main/java/com/mapcode/Decoder.java +++ b/src/main/java/com/mapcode/Decoder.java @@ -925,6 +925,7 @@ private static String convertFromAbjad(final String mapcode) { return prefix + Encoder.aeuPack(newstr, false) + postfix; } + @SuppressWarnings("NumericCastThatLosesPrecision") private static String convertToAbjad(final String mapcode) { String str; final String rest; diff --git a/src/main/java/com/mapcode/Encoder.java b/src/main/java/com/mapcode/Encoder.java index deda5e5..39f2160 100644 --- a/src/main/java/com/mapcode/Encoder.java +++ b/src/main/java/com/mapcode/Encoder.java @@ -57,7 +57,6 @@ static List encode( private final static char[] ENCODE_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z', 'A', 'E', 'U'}; - @SuppressWarnings("ConstantConditions") @Nonnull private static List encode(final double argLatDeg, final double argLonDeg, @Nullable final Territory territory, final boolean limitToOneResult, diff --git a/src/main/java/com/mapcode/Mapcode.java b/src/main/java/com/mapcode/Mapcode.java index 5148312..77ee58a 100644 --- a/src/main/java/com/mapcode/Mapcode.java +++ b/src/main/java/com/mapcode/Mapcode.java @@ -421,14 +421,14 @@ public int hashCode() { } @Override - public boolean equals(@Nullable final Object o) { - if (this == o) { + public boolean equals(@Nullable final Object obj) { + if (this == obj) { return true; } - if (!(o instanceof Mapcode)) { + if (!(obj instanceof Mapcode)) { return false; } - final Mapcode that = (Mapcode) o; + final Mapcode that = (Mapcode) obj; return this.territory.equals(that.territory) && this.codePrecision8.equals(that.codePrecision8); } diff --git a/src/main/java/com/mapcode/Point.java b/src/main/java/com/mapcode/Point.java index 2eb65bd..92cebdc 100644 --- a/src/main/java/com/mapcode/Point.java +++ b/src/main/java/com/mapcode/Point.java @@ -225,14 +225,14 @@ public int hashCode() { @SuppressWarnings("NonFinalFieldReferenceInEquals") @Override - public boolean equals(final Object o) { - if (this == o) { + public boolean equals(final Object obj) { + if (this == obj) { return true; } - if (!(o instanceof Point)) { + if (!(obj instanceof Point)) { return false; } - final Point that = (Point) o; + final Point that = (Point) obj; return (this.latMicroDeg == that.latMicroDeg) && (this.lonMicroDeg == that.lonMicroDeg) && (this.latFractionOnlyDeg == that.latFractionOnlyDeg) && diff --git a/src/main/java/com/mapcode/Territory.java b/src/main/java/com/mapcode/Territory.java index 500ae4d..67940d7 100644 --- a/src/main/java/com/mapcode/Territory.java +++ b/src/main/java/com/mapcode/Territory.java @@ -912,7 +912,6 @@ private Territory( * @return Territory. * @throws UnknownTerritoryException Thrown if the territory is not found. */ - @SuppressWarnings("TailRecursion") @Nonnull private static Territory createFromString( @Nonnull final String alphaCode, diff --git a/src/main/java/com/mapcode/UnknownAlphabetException.java b/src/main/java/com/mapcode/UnknownAlphabetException.java index a7b27f9..069656c 100644 --- a/src/main/java/com/mapcode/UnknownAlphabetException.java +++ b/src/main/java/com/mapcode/UnknownAlphabetException.java @@ -25,11 +25,8 @@ public final class UnknownAlphabetException extends IllegalArgumentException { private static final long serialVersionUID = 1L; - private final Integer code; - public UnknownAlphabetException(@Nonnull final String message) { super(message); assert message != null; - this.code = null; } } diff --git a/src/main/java/com/mapcode/UnknownPrecisionFormatException.java b/src/main/java/com/mapcode/UnknownPrecisionFormatException.java index bf0deab..bc6764c 100644 --- a/src/main/java/com/mapcode/UnknownPrecisionFormatException.java +++ b/src/main/java/com/mapcode/UnknownPrecisionFormatException.java @@ -25,11 +25,8 @@ public final class UnknownPrecisionFormatException extends IllegalArgumentException { private static final long serialVersionUID = 1L; - private final Integer precision; - public UnknownPrecisionFormatException(@Nonnull final String message) { super(message); assert message != null; - this.precision = null; } } diff --git a/src/test/java/com/mapcode/DataModelTest.java b/src/test/java/com/mapcode/DataModelTest.java index 9e814bc..6717330 100644 --- a/src/test/java/com/mapcode/DataModelTest.java +++ b/src/test/java/com/mapcode/DataModelTest.java @@ -21,45 +21,40 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nonnull; - -import static org.junit.Assert.assertEquals; - -@SuppressWarnings({"OverlyBroadThrowsClause", "ProhibitedExceptionDeclared"}) public class DataModelTest { private static final Logger LOG = LoggerFactory.getLogger(DataModelTest.class); public void testFileOK() { LOG.info("testFileOK"); final DataModel dataModel = new DataModel("/com/mapcode/mminfo_ok.dat"); - Assert.assertTrue(dataModel != null); + Assert.assertNotNull(dataModel); } @Test(expected = IncorrectDataModelException.class) public void testFileTooShort() { LOG.info("testFileTooShort"); final DataModel dataModel = new DataModel("/com/mapcode/mminfo_too_short.dat"); - Assert.assertTrue(false); + Assert.assertNull(dataModel); } @Test(expected = IncorrectDataModelException.class) public void testFileEndsEarly() { LOG.info("testFileEndsEarly"); final DataModel dataModel = new DataModel("/com/mapcode/mminfo_ends_early.dat"); - Assert.assertTrue(false); + Assert.assertNull(dataModel); } @Test(expected = IncorrectDataModelException.class) public void testFileNoHeader() { LOG.info("testFileNoHeader"); final DataModel dataModel = new DataModel("/com/mapcode/mminfo_no_header.dat"); - Assert.assertTrue(false); + Assert.assertNull(dataModel); } @Test(expected = IncorrectDataModelException.class) public void testFileWrongversion() { LOG.info("testFileWrongversion"); final DataModel dataModel = new DataModel("/com/mapcode/mminfo_wrong_version.dat"); - Assert.assertTrue(false); + Assert.assertNull(dataModel); } } diff --git a/src/test/java/com/mapcode/DecoderTest.java b/src/test/java/com/mapcode/DecoderTest.java index 8a6711e..a1f46de 100644 --- a/src/test/java/com/mapcode/DecoderTest.java +++ b/src/test/java/com/mapcode/DecoderTest.java @@ -279,7 +279,6 @@ public void illegalArgument1() throws Exception { MapcodeCodec.decode(null, Territory.NLD); } - @SuppressWarnings("ConstantConditions") @Test(expected = UnknownMapcodeException.class) public void illegalArgument2() throws Exception { LOG.info("illegalArgument2"); diff --git a/src/test/java/com/mapcode/EncodeDecodeTest.java b/src/test/java/com/mapcode/EncodeDecodeTest.java index 0684e62..fc8d932 100644 --- a/src/test/java/com/mapcode/EncodeDecodeTest.java +++ b/src/test/java/com/mapcode/EncodeDecodeTest.java @@ -30,7 +30,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -@SuppressWarnings({"JUnitTestMethodWithNoAssertions", "OverlyBroadThrowsClause", "ProhibitedExceptionDeclared"}) +@SuppressWarnings({"OverlyBroadThrowsClause", "ProhibitedExceptionDeclared"}) public class EncodeDecodeTest { private static final Logger LOG = LoggerFactory.getLogger(EncodeDecodeTest.class); @@ -51,7 +51,6 @@ public void encodeDecodeTestRandomSeed() throws Exception { doEncodeDecode(seed); } - @SuppressWarnings("BusyWait") private static void doEncodeDecode(final long seed) throws InterruptedException { // Keep error count and create thread pool. diff --git a/src/test/java/com/mapcode/EncoderTest.java b/src/test/java/com/mapcode/EncoderTest.java index 445d285..f3d8960 100644 --- a/src/test/java/com/mapcode/EncoderTest.java +++ b/src/test/java/com/mapcode/EncoderTest.java @@ -21,11 +21,9 @@ import org.slf4j.LoggerFactory; import java.util.List; -import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; @SuppressWarnings({"OverlyBroadThrowsClause", "ProhibitedExceptionDeclared", "ValueOfIncrementOrDecrementUsed"}) public class EncoderTest { diff --git a/src/test/java/com/mapcode/PointTest.java b/src/test/java/com/mapcode/PointTest.java index e51a78b..15bda51 100644 --- a/src/test/java/com/mapcode/PointTest.java +++ b/src/test/java/com/mapcode/PointTest.java @@ -251,9 +251,9 @@ public void testWrap() { assertEquals(Point.fromDeg(89.99, (i * 360) + 0.0), Point.fromDeg(89.99, 0.0).wrap()); assertEquals(Point.fromDeg(90.01, (i * 360) + 0.0), Point.fromDeg(90.0, 0.0).wrap()); - assertEquals(Point.fromDeg(0.0, (i * 360) + -180.0), Point.fromDeg(0.0, -180.0).wrap()); - assertEquals(Point.fromDeg(0.0, (i * 360) + -179.99), Point.fromDeg(0.0, -179.99).wrap()); - assertEquals(Point.fromDeg(0.0, (i * 360) + -180.01), Point.fromDeg(0.0, 179.99).wrap()); + assertEquals(Point.fromDeg(0.0, (i * 360) - 180.0), Point.fromDeg(0.0, -180.0).wrap()); + assertEquals(Point.fromDeg(0.0, (i * 360) - 179.99), Point.fromDeg(0.0, -179.99).wrap()); + assertEquals(Point.fromDeg(0.0, (i * 360) - 180.01), Point.fromDeg(0.0, 179.99).wrap()); assertEquals(Point.fromDeg(0.0, (i * 360) + 180.0), Point.fromDeg(0.0, -180.0).wrap()); assertEquals(Point.fromDeg(0.0, (i * 360) + 179.99), Point.fromDeg(0.0, 179.99).wrap()); diff --git a/src/test/java/com/mapcode/ReferenceFileTest.java b/src/test/java/com/mapcode/ReferenceFileTest.java index cf01ce3..4232fbe 100644 --- a/src/test/java/com/mapcode/ReferenceFileTest.java +++ b/src/test/java/com/mapcode/ReferenceFileTest.java @@ -52,7 +52,6 @@ public class ReferenceFileTest { private static final int LOG_LINE_EVERY = 10000; - @SuppressWarnings("JUnitTestMethodWithNoAssertions") @Test public void checkRandomReferenceRecords() throws Exception { LOG.info("checkRandomReferenceRecords"); @@ -65,7 +64,6 @@ public void checkRandomReferenceRecords() throws Exception { checkFile(8, RANDOM_REFERENCE_FILE_3, false); } - @SuppressWarnings("JUnitTestMethodWithNoAssertions") @Test public void checkGridReferenceRecords() throws Exception { LOG.info("checkGridReferenceRecords"); @@ -78,7 +76,6 @@ public void checkGridReferenceRecords() throws Exception { checkFile(8, GRID_REFERENCE_FILE_3, false); } - @SuppressWarnings("JUnitTestMethodWithNoAssertions") @Test public void checkBoundariesReferenceRecords() throws Exception { LOG.info("checkBoundariesReferenceRecords"); @@ -86,7 +83,6 @@ public void checkBoundariesReferenceRecords() throws Exception { checkFile(8, BOUNDARIES_REFERENCE_FILE, true); } - @SuppressWarnings("BusyWait") private static void checkFile( final int precision, @Nonnull final String baseFileName, @@ -254,6 +250,7 @@ public void run() { // Keep distance. This is a multi-threaded get/set; requires synchronized. synchronized (deltaNm) { + //noinspection NumericCastThatLosesPrecision deltaNm[precision].set(Math.max(deltaNm[precision].get(), (long) (distanceM * 1.0e6))); } @@ -399,7 +396,6 @@ private ChunkedFile(final String baseFileName) throws IOException { @SuppressWarnings("OverlyBroadThrowsClause") @Nonnull private String readNonEmptyLine() throws IOException { - //noinspection NonConstantStringShouldBeStringBuffer String line = null; do { boolean tryNextChunk; diff --git a/src/test/java/com/mapcode/TerritoryTest.java b/src/test/java/com/mapcode/TerritoryTest.java index 2a05166..b97a44e 100644 --- a/src/test/java/com/mapcode/TerritoryTest.java +++ b/src/test/java/com/mapcode/TerritoryTest.java @@ -29,13 +29,13 @@ public class TerritoryTest { private static final Logger LOG = LoggerFactory.getLogger(TerritoryTest.class); @Test(expected = UnknownTerritoryException.class) - public void emptyTerritoryCodeTest() throws Exception { + public void emptyTerritoryCodeTest() { LOG.info("emptyCodeTest"); Territory.fromString(""); } @Test - public void checkFullName() throws Exception { + public void checkFullName() { LOG.info("checkFullName"); assertEquals(Territory.AAA, Territory.fromString("International")); assertEquals(Territory.AAA, Territory.fromString("Worldwide")); @@ -46,7 +46,7 @@ public void checkFullName() throws Exception { } @Test - public void checkDash() throws Exception { + public void checkDash() { LOG.info("checkDash"); assertEquals(Territory.IN_MN, Territory.fromString("IND-MN")); assertEquals(Territory.IN_MN, Territory.fromString("IND_MN")); @@ -59,7 +59,7 @@ public void checkDash() throws Exception { } @Test - public void disambiguateMNTest1() throws Exception { + public void disambiguateMNTest1() { LOG.info("disambiguateMNTest2"); final Territory territory0 = Territory.fromString("IND-MN"); final Territory territory1 = Territory.fromString("IN-MN"); @@ -71,7 +71,7 @@ public void disambiguateMNTest1() throws Exception { } @Test(expected = UnknownTerritoryException.class) - public void disambiguateMNTest2() throws Exception { + public void disambiguateMNTest2() { LOG.info("disambiguateMNTest2"); Territory.fromString("MN", Territory.RUS); } @@ -127,7 +127,7 @@ public void testTerritoryFromStringNumeric() throws Exception { } @Test - public void checkAlphabet() throws Exception { + public void checkAlphabet() { LOG.info("checkAlphabet"); assertEquals(Territory.NLD, Territory.fromString("NLD")); assertEquals(Territory.NLD, Territory.fromString("\u039d\u039b\u0394")); From caa9ecadd33eeec05d9580b19ff727ab78c3b05a Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Sun, 2 Oct 2016 14:53:47 +0200 Subject: [PATCH 3/3] Fixed arabic stuff --- README.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/README.md b/README.md index 1f4510c..6c38b40 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,95 @@ limitations under the License. Original C library created by Pieter Geelen. Work on Java version of the mapcode library by Rijn Buve. Initial port by Matthew Lowden. +# Using the Mapcode Library + +For a description of what mapcodes are, please visit http://mapcode.com. + +This library exposes a `Mapcode` class, which represents a full mapcode, +consisting of a code and a territory. You can extract the code and territory +with methods like `getCode()` and `getTerritory()`. Codes may be retrieved +in a multitude of scripts (or 'alphabets', as they are called in this +library), such as Roman, Greek, Hindi and Arabic. + +`Mapcode` objects are returned by the `MapcodeCodec` with encodes coordinates +to mapcodes and decodes mapcodes to coordinates (codec means coder/decoder). + +# Examples + +Here's an example to `decode()` mapcode within a given territory context. +Note that the territory context (`NLD` is this case) is only used to +disambiguate the code if needed. If the provided code is an international +code, the context is simply ignored, because no disambiguation is needed. + + final Territory territory = Territory.fromString("NLD"); + final String mapcode = "49.4V"; + try { + final Point p = MapcodeCodec.decode(mapcode, territory); + // p now points at the (lat, lon) for the mapcode. + } catch (final UnknownMapcodeException ignored) { + // The mapcode was not valid. + } + +And to `encode()` a latitude and longitude into a mapcode you would write: + + final List results = MapcodeCodec.encode(lat, lon); + +As you see, the returned result is actually a list of mapcodes. That's +because many locations have multiple mapcodes. The last code in the list +is always the longest code, the international code. This means this method +always returns a result (as for every location on Earth, there is at least +one mapcode). + +So, the last code is the international code, but notice that the first code +is not always the shortest, nor does it need to have the "correct" +territory associated to it. + +If you want to get the shortest code for a coordinate, you should should +specify a territory and use `encodeToShortest` like this: + + final Territory territory = Territory.NLD; + final Mapcode mapcode = encodeToShortest(lat, lon, territory); + +This makes sure you get the shortest code for a coordinate which has +territory `NLD` (or whatever you choose the territory to be). + +This method may fail, as the specified coordinate may not lie in the +specified territory. In that case a `UnknownMapcodeException` is thrown. + +The `Mapcode` class offers some additional methods to, for example, get +high-resolution mapcode strings. + + // Retrieve an ultra-high precision mapcode. + final String highRez = mapcode.getCode(8); + +Or to get full mapcode strings (Unicode), in different scripts (or alphabets): + + // Get a Roman version of the mapcode. + final String roman = mapcode.getCodeWithTerritory(Alphabet.ROMAN); + + // Get an Arabic version of the mapcode. + final String arabic = mapcode.getCodeWithTerritory(Alphabet.ARABIC); + +Note that mapcodes from different scripts can be passed as strings back +to the decoder and they will 'just work'. + +There's also a `Territory` class, which allows you get territory codes, +given their ISO 3-character code, or their full names (or even some +supported aliases). + + final Territory territory = Territory.fromString("France"); + // territory is now Territory.FRA. + +Finally, there is a `Point` utility class, which represents coordinates +with a latitude and longitude. The class offers some simple utility methods +like `distanceInMeters` to calculate the distance between two points. Note +that this method is only accurate for pretty short distances, up to, say +a couple of hundred kilometers. + +The `Point` class is usually easier to use than individual latitude and +longitude paramters and class makes sure it always wraps latitudes to +a range of `[-90, 90]` and longitude to `[-180, 180>`. + # Coding Formatting Style The code formatting style used is the default code formatting style from IntelliJ IDEA (version 14).