Skip to content

Commit dabbb91

Browse files
committed
Added alphabets
1 parent 64b2a5f commit dabbb91

File tree

9 files changed

+306
-30
lines changed

9 files changed

+306
-30
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (C) 2014-2015 Stichting Mapcode Foundation (http://www.mapcode.com)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mapcode;
18+
19+
import javax.annotation.Nonnull;
20+
21+
/**
22+
* This enum defines all alphabets supported for mapcodes. Mapcodes can be safely converted between
23+
* alphabets and fed to the mapcode decoder.
24+
*/
25+
public enum Alphabet {
26+
ROMAN(0),
27+
GREEK(1),
28+
CYRILLIC(2),
29+
HEBREW(3),
30+
HINDI(4),
31+
MALAI(5),
32+
GEORGIAN(6),
33+
KATAKANA(7),
34+
THAI(8),
35+
LAO(9),
36+
ARMENIAN(10),
37+
BENGALI(11),
38+
GURMUKHI(12),
39+
TIBETAN(13);
40+
41+
public final int code;
42+
43+
private Alphabet(final int code) {
44+
this.code = code;
45+
}
46+
47+
@Nonnull
48+
public static Alphabet fromCode(final int code) throws UnknownAlphabetException {
49+
for (final Alphabet alphabet : values()) {
50+
if (alphabet.code == code) {
51+
return alphabet;
52+
}
53+
}
54+
throw new UnknownAlphabetException(code);
55+
}
56+
57+
public static class UnknownAlphabetException extends RuntimeException {
58+
final int code;
59+
60+
public UnknownAlphabetException(final int code) {
61+
super();
62+
this.code = code;
63+
}
64+
}
65+
}

src/main/java/com/mapcode/CheckArgs.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import javax.annotation.Nonnull;
2020
import javax.annotation.Nullable;
2121

22+
import static com.mapcode.Mapcode.isValidMapcodeFormat;
23+
2224
/**
2325
* Package private helper methods.
2426
*/
@@ -42,4 +44,13 @@ static void checkNonnull(@Nonnull final String param, @Nullable final Object obj
4244
throw new IllegalArgumentException("Parameter " + param + " should not be null");
4345
}
4446
}
47+
48+
static void checkMapcode(@Nonnull final String param, @Nullable final String mapcode)
49+
throws IllegalArgumentException {
50+
checkNonnull(param, mapcode);
51+
if (!isValidMapcodeFormat(mapcode)) {
52+
throw new IllegalArgumentException(mapcode + " is not a correctly formatted mapcode; " +
53+
"the regular expression for the mapcode syntax is: " + Mapcode.REGEX_MAPCODE_FORMAT);
54+
}
55+
}
4556
}

src/main/java/com/mapcode/Decoder.java

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ static Point decode(@Nonnull final String argMapcode,
173173

174174
private static final int CCODE_EARTH = 540;
175175

176-
private final static int[] decode_chars = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
176+
private final static int[] DECODE_CHARS = {
177+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
177178
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
178179
-1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -2, 10, 11, 12, -3, 13, 14, 15,
179180
1, 16, 17, 18, 19, 20, 0, 21, 22, 23, 24, 25, -4, 26, 27, 28, 29, 30, -1, -1, -1, -1, -1, -1, -2, 10, 11,
@@ -197,6 +198,23 @@ public Unicode2Ascii(final int min, final int max, @Nullable final String conver
197198
}
198199
}
199200

201+
private final static int[][] ASCII2LANGUAGE = {
202+
{0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // roman
203+
{0x0391, 0x0392, 0x039e, 0x0394, 0x003f, 0x0395, 0x0393, 0x0397, 0x0399, 0x03a0, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f, 0x03a1, 0x0398, 0x03a8, 0x03a3, 0x03a4, 0x003f, 0x03a6, 0x03a9, 0x03a7, 0x03a5, 0x0396, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // greek
204+
{0x0410, 0x0412, 0x0421, 0x0414, 0x0415, 0x0416, 0x0413, 0x041d, 0x0418, 0x041f, 0x041a, 0x041b, 0x041c, 0x0417, 0x041e, 0x0420, 0x0424, 0x042f, 0x0426, 0x0422, 0x042d, 0x0427, 0x0428, 0x0425, 0x0423, 0x0411, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // cyrillic
205+
{0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05e3, 0x05d4, 0x05d6, 0x05d7, 0x05d5, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05e1, 0x05dd, 0x05de, 0x05e0, 0x05e2, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // hebrew
206+
{0x0905, 0x0915, 0x0917, 0x0918, 0x090f, 0x091a, 0x091c, 0x091f, 0x003f, 0x0920, 0x0923, 0x0924, 0x0926, 0x0927, 0x003f, 0x0928, 0x092a, 0x092d, 0x092e, 0x0930, 0x092b, 0x0932, 0x0935, 0x0938, 0x0939, 0x0921, 0x0966, 0x0967, 0x0968, 0x0969, 0x096a, 0x096b, 0x096c, 0x096d, 0x096e, 0x096f}, // hindi
207+
{0x0d12, 0x0d15, 0x0d16, 0x0d17, 0x0d0b, 0x0d1a, 0x0d1c, 0x0d1f, 0x0d07, 0x0d21, 0x0d24, 0x0d25, 0x0d26, 0x0d27, 0x0d20, 0x0d28, 0x0d2e, 0x0d30, 0x0d31, 0x0d32, 0x0d09, 0x0d34, 0x0d35, 0x0d36, 0x0d38, 0x0d39, 0x0d66, 0x0d67, 0x0d68, 0x0d69, 0x0d6a, 0x0d6b, 0x0d6c, 0x0d6d, 0x0d6e, 0x0d6f}, // malay
208+
{0x10a0, 0x10a1, 0x10a3, 0x10a6, 0x10a4, 0x10a9, 0x10ab, 0x10ac, 0x10b3, 0x10ae, 0x10b0, 0x10b1, 0x10b2, 0x10b4, 0x10ad, 0x10b5, 0x10b6, 0x10b7, 0x10b8, 0x10b9, 0x10a8, 0x10ba, 0x10bb, 0x10bd, 0x10be, 0x10bf, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // Georgian
209+
{0x30a2, 0x30ab, 0x30ad, 0x30af, 0x30aa, 0x30b1, 0x30b3, 0x30b5, 0x30a4, 0x30b9, 0x30c1, 0x30c8, 0x30ca, 0x30cc, 0x30a6, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30e1, 0x30a8, 0x30e2, 0x30e8, 0x30e9, 0x30ed, 0x30f2, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // Katakana
210+
{0x0e30, 0x0e01, 0x0e02, 0x0e04, 0x0e32, 0x0e07, 0x0e08, 0x0e09, 0x0e31, 0x0e0a, 0x0e11, 0x0e14, 0x0e16, 0x0e17, 0x0e0d, 0x0e18, 0x0e1a, 0x0e1c, 0x0e21, 0x0e23, 0x0e2c, 0x0e25, 0x0e27, 0x0e2d, 0x0e2e, 0x0e2f, 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59}, // Thai
211+
{0x0eb0, 0x0e81, 0x0e82, 0x0e84, 0x0ec3, 0x0e87, 0x0e88, 0x0e8a, 0x0ec4, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9a, 0x0ec6, 0x0e9c, 0x0e9e, 0x0ea1, 0x0ea2, 0x0ea3, 0x0ebd, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eaf, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // Laos
212+
{0x0556, 0x0532, 0x0533, 0x0534, 0x0535, 0x0538, 0x0539, 0x053a, 0x053b, 0x053d, 0x053f, 0x0540, 0x0541, 0x0543, 0x0555, 0x0547, 0x0548, 0x054a, 0x054d, 0x054e, 0x0545, 0x054f, 0x0550, 0x0551, 0x0552, 0x0553, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // armenian
213+
{0x0985, 0x098c, 0x0995, 0x0996, 0x098f, 0x0997, 0x0999, 0x099a, 0x003f, 0x099d, 0x09a0, 0x09a1, 0x09a2, 0x09a3, 0x003f, 0x09a4, 0x09a5, 0x09a6, 0x09a8, 0x09aa, 0x0993, 0x09ac, 0x09ad, 0x09af, 0x09b2, 0x09b9, 0x09e6, 0x09e7, 0x09e8, 0x09e9, 0x09ea, 0x09eb, 0x09ec, 0x09ed, 0x09ee, 0x09ef}, // Bengali
214+
{0x0a05, 0x0a15, 0x0a17, 0x0a18, 0x0a0f, 0x0a1a, 0x0a1c, 0x0a1f, 0x003f, 0x0a20, 0x0a23, 0x0a24, 0x0a26, 0x0a27, 0x003f, 0x0a28, 0x0a2a, 0x0a2d, 0x0a2e, 0x0a30, 0x0a2b, 0x0a32, 0x0a35, 0x0a38, 0x0a39, 0x0a21, 0x0a66, 0x0a67, 0x0a68, 0x0a69, 0x0a6a, 0x0a6b, 0x0a6c, 0x0a6d, 0x0a6e, 0x0a6f}, // Gurmukhi
215+
{0x0f58, 0x0f40, 0x0f41, 0x0f42, 0x0f64, 0x0f44, 0x0f45, 0x0f46, 0x003f, 0x0f47, 0x0f4a, 0x0f4c, 0x0f4e, 0x0f4f, 0x003f, 0x0f51, 0x0f53, 0x0f54, 0x0f56, 0x0f5e, 0x0f65, 0x0f5f, 0x0f61, 0x0f62, 0x0f63, 0x0f66, 0x0f20, 0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27, 0x0f28, 0x0f29}, // Tibetan
216+
};
217+
200218
private final static Unicode2Ascii[] UNICODE2ASCII = {
201219
new Unicode2Ascii(0x0041, 0x005a, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"), // Roman
202220
new Unicode2Ascii(0x0391, 0x03a9, "ABGDFZHQIKLMNCOJP?STYVXRW"), // Greek
@@ -331,7 +349,7 @@ private static Point decodeNameless(final String str, final int firstrec, final
331349
boolean swapletters = false;
332350

333351
if ((mapcoderData.getCodex() != 21) && (a <= 31)) {
334-
final int offset = decode_chars[(int) result.charAt(0)];
352+
final int offset = DECODE_CHARS[(int) result.charAt(0)];
335353

336354
if (offset < (r * (p + 1))) {
337355
nrX = offset / (p + 1);
@@ -340,7 +358,7 @@ private static Point decodeNameless(final String str, final int firstrec, final
340358
nrX = r + ((offset - (r * (p + 1))) / p);
341359
}
342360
} else if ((mapcoderData.getCodex() != 21) && (a < 62)) {
343-
nrX = decode_chars[(int) result.charAt(0)];
361+
nrX = DECODE_CHARS[(int) result.charAt(0)];
344362
if (nrX < (62 - a)) {
345363
swapletters = mapcoderData.getCodex() == 22;
346364
} else {
@@ -513,11 +531,11 @@ private static String aeuUnpack(final String argStr) {
513531
// less than 2 letters after dot
514532

515533
if (str.charAt(0) == 'A') { // v1.50
516-
int v1 = decode_chars[(int) str.charAt(lastpos)];
534+
int v1 = DECODE_CHARS[(int) str.charAt(lastpos)];
517535
if (v1 < 0) {
518536
v1 = 31;
519537
}
520-
int v2 = decode_chars[(int) str.charAt(lastpos - 1)];
538+
int v2 = DECODE_CHARS[(int) str.charAt(lastpos - 1)];
521539
if (v2 < 0) {
522540
v2 = 31;
523541
}
@@ -548,7 +566,7 @@ private static String aeuUnpack(final String argStr) {
548566
} else if (e == 'U') {
549567
v += 33;
550568
} else {
551-
final int ve = decode_chars[(int) str.charAt(lastpos)];
569+
final int ve = DECODE_CHARS[(int) str.charAt(lastpos)];
552570
if (ve < 0) {
553571
return "";
554572
}
@@ -569,9 +587,10 @@ private static String aeuUnpack(final String argStr) {
569587

570588
for (int v = 0; v <= lastpos; v++) {
571589
if (v != dotpos) {
572-
if (decode_chars[(int) str.charAt(v)] < 0) {
590+
final int i = (int) str.charAt(v);
591+
if (DECODE_CHARS[i] < 0) {
573592
return ""; // bad char!
574-
} else if (voweled && (decode_chars[(int) str.charAt(v)] > 9)) {
593+
} else if (voweled && (DECODE_CHARS[(int) str.charAt(v)] > 9)) {
575594
return ""; // nonodigit!
576595
}
577596
}
@@ -618,10 +637,43 @@ static String decodeUTF16(final String str) {
618637
return asciibuf.toString();
619638
}
620639

640+
static String encodeUTF16(final String string, final int alphabet) {
641+
final StringBuilder sb = new StringBuilder();
642+
for (char ch : string.toCharArray()) {
643+
ch = Character.toUpperCase(ch);
644+
if (ch > 'Z') {
645+
// Not in any valid range?
646+
sb.append('?');
647+
} else if (ch < 'A') {
648+
// Valid but not a letter (e.g. a dot, a space...).
649+
// Leave untranslated.
650+
sb.append(ch);
651+
} else {
652+
sb.append((char) ASCII2LANGUAGE[alphabet][(int) ch - (int) 'A']);
653+
}
654+
}
655+
return sb.toString();
656+
}
657+
658+
static String encodeToAlphabetCode(final String mapcode, int alphabetCode) {
659+
if (ASCII2LANGUAGE[alphabetCode][4] == 0x003f) {
660+
if (mapcode.matches("^.*[EUeu].*")) {
661+
final String unpacked = aeuUnpack(mapcode);
662+
if (unpacked.isEmpty()) {
663+
throw new AssertionError("encodeToAlphabetCode: cannot encode '" + mapcode +
664+
"' to alphabet " + alphabetCode + ' ' + Alphabet.fromCode(alphabetCode));
665+
}
666+
final String packed = Encoder.aeuPack(unpacked, true);
667+
return encodeUTF16(packed, alphabetCode);
668+
}
669+
}
670+
return encodeUTF16(mapcode, alphabetCode);
671+
}
672+
621673
@Nonnull
622674
private static Point decodeTriple(final String str) {
623675
//noinspection NumericCastThatLosesPrecision
624-
final byte c1 = (byte) decode_chars[(int) str.charAt(0)];
676+
final byte c1 = (byte) DECODE_CHARS[(int) str.charAt(0)];
625677
final int x = fastDecode(str.substring(1));
626678
if (c1 < 24) {
627679
return Point.fromMicroDeg(((c1 / 6) * 34) + (x % 34), ((c1 % 6) * 28) + (x / 34));
@@ -655,10 +707,10 @@ private static int fastDecode(final String code)
655707
{
656708
return value;
657709
}
658-
if (decode_chars[c] < 0) {
710+
if (DECODE_CHARS[c] < 0) {
659711
return -1;
660712
}
661-
value = (value * 31) + decode_chars[c];
713+
value = (value * 31) + DECODE_CHARS[c];
662714
}
663715
return value;
664716
}
@@ -667,7 +719,7 @@ private static int fastDecode(final String code)
667719
private static Point add2res(final int y, final int x, final int dividerx4, final int dividery, final int ydirection, final String extrapostfix) {
668720
if (!extrapostfix.isEmpty()) {
669721
int c1 = (int) extrapostfix.charAt(0);
670-
c1 = decode_chars[c1];
722+
c1 = DECODE_CHARS[c1];
671723
if (c1 < 0) {
672724
c1 = 0;
673725
} else if (c1 > 29) {
@@ -677,7 +729,7 @@ private static Point add2res(final int y, final int x, final int dividerx4, fina
677729
final int x1 = c1 % 5;
678730
int c2 = (extrapostfix.length() == 2) ? (int) extrapostfix.charAt(1) : 72; // 72='H'=code
679731
// 15=(3+2*6)
680-
c2 = decode_chars[c2];
732+
c2 = DECODE_CHARS[c2];
681733
if (c2 < 0) {
682734
c2 = 0;
683735
} else if (c2 > 29) {

src/main/java/com/mapcode/Encoder.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static List<Mapcode> encode(
5353
// Private methods.
5454
// ----------------------------------------------------------------------
5555

56-
private final static char[] encode_chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', 'D', 'F',
56+
private final static char[] ENCODE_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', 'D', 'F',
5757
'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z', 'A', 'E', 'U'};
5858

5959
@Nonnull
@@ -172,10 +172,10 @@ private static String addPostfix(final int extrax4, final int extray, final int
172172
final int gy = ((30 * extray) / dividery);
173173
final int x1 = (gx / 6);
174174
final int y1 = (gy / 5);
175-
String s = "-" + encode_chars[((y1 * 5) + x1)];
175+
String s = "-" + ENCODE_CHARS[((y1 * 5) + x1)];
176176
final int x2 = (gx % 6);
177177
final int y2 = (gy % 5);
178-
s += encode_chars[((y2 * 6) + x2)];
178+
s += ENCODE_CHARS[((y2 * 6) + x2)];
179179
return s;
180180
}
181181

@@ -446,7 +446,7 @@ private static String encodeNameless(final Point pointToEncode, final Data mapco
446446
return "";
447447
}
448448

449-
private static String aeuPack(final String argStr, final boolean argShort) {
449+
static String aeuPack(final String argStr, final boolean argShort) {
450450
String str = argStr;
451451
int dotpos = -9;
452452
int rlen = str.length();
@@ -473,10 +473,10 @@ private static String aeuPack(final String argStr, final boolean argShort) {
473473
// after the dot?
474474
if (argShort) {
475475
final int v = ((((int) str.charAt(0)) - 48) * 100) + ((((int) str.charAt(rlen - 2)) - 48) * 10) + (((int) str.charAt(rlen - 1)) - 48);
476-
return 'A' + str.substring(1, rlen - 2) + encode_chars[v / 32] + encode_chars[v % 32] + rest;
476+
return 'A' + str.substring(1, rlen - 2) + ENCODE_CHARS[v / 32] + ENCODE_CHARS[v % 32] + rest;
477477
} else {
478478
final int v = (((((int) str.charAt(rlen - 2)) - 48) * 10) + ((int) str.charAt(rlen - 1))) - 48;
479-
str = str.substring(0, rlen - 2) + encode_chars[31 + (v / 34)] + encode_chars[v % 34];
479+
str = str.substring(0, rlen - 2) + ENCODE_CHARS[31 + (v / 34)] + ENCODE_CHARS[v % 34];
480480
}
481481
}
482482
return str + rest;
@@ -488,7 +488,7 @@ private static String fastEncode(final int argValue, final int argNrChars) {
488488
final StringBuilder result = new StringBuilder();
489489
while (nrChars > 0) {
490490
nrChars--;
491-
result.insert(0, encode_chars[value % 31]);
491+
result.insert(0, ENCODE_CHARS[value % 31]);
492492
value = value / 31;
493493
}
494494
return result.toString();
@@ -507,9 +507,9 @@ private static int encode6(final int x, final int y, final int width, final int
507507

508508
private static String encodeTriple(final int difx, final int dify) {
509509
if (dify < (4 * 34)) {
510-
return encode_chars[((difx / 28) + (6 * (dify / 34)))] + fastEncode(((difx % 28) * 34) + (dify % 34), 2);
510+
return ENCODE_CHARS[((difx / 28) + (6 * (dify / 34)))] + fastEncode(((difx % 28) * 34) + (dify % 34), 2);
511511
} else {
512-
return encode_chars[((difx / 24) + 24)] + fastEncode((((difx % 24) * 40) + dify) - 136, 2);
512+
return ENCODE_CHARS[((difx / 24) + 24)] + fastEncode((((difx % 24) * 40) + dify) - 136, 2);
513513
}
514514
}
515515
}

src/main/java/com/mapcode/Mapcode.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
import java.util.regex.Matcher;
2222
import java.util.regex.Pattern;
2323

24+
import static com.mapcode.CheckArgs.checkMapcode;
25+
import static com.mapcode.CheckArgs.checkNonnull;
26+
2427
/**
2528
* This class defines a single mapcode encoding result, including the mapcode itself and the
2629
* territory definition.
@@ -58,12 +61,7 @@ public Mapcode(
5861
@Nonnull final String mapcode,
5962
@Nonnull final Territory territory) throws IllegalArgumentException {
6063

61-
// Check mapcode format.
62-
if (!isValidMapcodeFormat(mapcode)) {
63-
throw new IllegalArgumentException(mapcode + " is not a correctly formatted mapcode; " +
64-
"the regular expression for the mapcode syntax is: " + REGEX_MAPCODE_FORMAT);
65-
}
66-
64+
checkMapcode("mapcode", mapcode);
6765
final String mapcodeUppercase = mapcode.toUpperCase();
6866
this.mapcodePrecision2 = mapcodeUppercase;
6967
if (mapcodeUppercase.contains("-")) {
@@ -252,20 +250,35 @@ public static MapcodeFormatType getMapcodeFormatType(@Nonnull final String mapco
252250
* mapcode representing a location on Earth.
253251
*/
254252
public static boolean isValidMapcodeFormat(@Nonnull final String mapcode) {
253+
checkNonnull("mapcode", mapcode);
255254
return getMapcodeFormatType(mapcode.toUpperCase()) != MapcodeFormatType.MAPCODE_TYPE_INVALID;
256255
}
257256

258257
/**
259-
* Convert a mapcode which potentially contains Unicode characters, to an ASCII veriant.
258+
* Convert a mapcode which potentially contains Unicode characters, to an ASCII variant.
260259
*
261260
* @param mapcode Mapcode, with optional Unicode characters.
262261
* @return ASCII, non-Unicode string.
263262
*/
264263
@Nonnull
265264
public static String convertToAscii(@Nonnull final String mapcode) {
265+
// Cannot call: checkMapcode() - recursive.
266266
return Decoder.decodeUTF16(mapcode.toUpperCase());
267267
}
268268

269+
/**
270+
* Convert a mapcode into the same mapcode using a different (or the same) alphabet.
271+
*
272+
* @param mapcode Mapcode to be converted.
273+
* @param alphabet Alphabet to convert to, may contain Unicode characters.
274+
* @return Converted mapcode.
275+
*/
276+
@Nonnull
277+
public static String convertToAlphabet(@Nonnull final String mapcode, @Nonnull final Alphabet alphabet) {
278+
checkMapcode("mapcode", mapcode);
279+
return Decoder.encodeToAlphabetCode(mapcode.toUpperCase(), alphabet.code);
280+
}
281+
269282
/**
270283
* Return the local mapcode string, potentially ambiguous.
271284
*

0 commit comments

Comments
 (0)