@@ -655,10 +655,10 @@ public Alphabet[] getAlphabets() {
655655 */
656656 @ Nonnull
657657 static Territory fromNumber (final int number ) throws UnknownTerritoryException {
658- if ((number < 0 ) || (number >= codeList .size ())) {
658+ if ((number < 0 ) || (number >= CODE_LIST .size ())) {
659659 throw new UnknownTerritoryException (number );
660660 }
661- return codeList .get (number );
661+ return CODE_LIST .get (number );
662662 }
663663
664664 /**
@@ -704,47 +704,66 @@ public static Territory fromString(@Nonnull final String alphaCode,
704704 return createFromString (alphaCode , parentTerritory );
705705 }
706706
707- // Keep a mapping from ISO3 to ISO2 codes. This map is used to make sure valid ISO3 codes are being used.
708- private static final Map <String , String > MAP_ISO3_TO_ISO2 ;
707+ /**
708+ * Create a Territory object from a valid ISO2 country code.
709+ *
710+ * @param countryISO2 ISO 3166 country code, 2 characters.
711+ * @return Territory object for the country.
712+ * @throws IllegalArgumentException Thrown if the country code is not a valid ISO 3166 code, 2 characters.
713+ */
714+ @ Nonnull
715+ public static Territory fromCountryISO2 (@ Nonnull final String countryISO2 ) {
716+ return fromString (getCountryISO3FromISO2 (countryISO2 ));
717+ }
709718
710- static {
711- final String [] countries = Locale .getISOCountries ();
712- MAP_ISO3_TO_ISO2 = new HashMap <String , String >(countries .length );
713- for (final String countryISO2 : countries ) {
714- final String countryISO3 = new Locale ("" , countryISO2 ).getISO3Country ();
715- MAP_ISO3_TO_ISO2 .put (countryISO3 .toUpperCase (), countryISO2 .toUpperCase ());
719+ /**
720+ * Return the ISO 3166 2 character country code for a ISO 3166 3 character code.
721+ *
722+ * @param countryISO3 ISO 3166 country code, 3 characters.
723+ * @return ISO 3166 country code, 2 characters.
724+ */
725+ @ Nonnull
726+ public static String getCountryISO2FromISO3 (@ Nonnull final String countryISO3 ) {
727+ final String countryISO2 = MAP_ISO3_TO_ISO2 .get (countryISO3 .toUpperCase ());
728+ if (countryISO2 == null ) {
729+ throw new IllegalArgumentException ("Parameter " + countryISO3 + " must be a valid ISO 3166 country code, 3 characters" );
716730 }
731+ return countryISO2 ;
717732 }
718733
719734 /**
720- * Create a Territory object from a valid ISO2 country code.
735+ * Return the ISO 3166 3 character country code for a ISO 3166 2 character code.
721736 *
722- * @param countryISO2 ISO 3166-2 country code.
723- * @return Territory object for the country.
724- * @throws IllegalArgumentException Thrown if the country code is not a valid ISO 3166-2 code.
737+ * @param countryISO2 ISO 3166 country code, 2 characters.
738+ * @return ISO 3166 country code, characters.
725739 */
726740 @ Nonnull
727- public static Territory fromCountryISO2 (@ Nonnull final String countryISO2 ) {
741+ public static String getCountryISO3FromISO2 (@ Nonnull final String countryISO2 ) {
742+ // Clipperton Island not recognized by Java - treat separately.
743+ if ("CP" .equalsIgnoreCase (countryISO2 )) {
744+ return "CPT" ;
745+ }
746+
747+ // Otherwise, use Java locales.
728748 final Locale locale = new Locale ("" , countryISO2 );
729749 try {
730- final String countryISO3 = locale .getISO3Country ().toUpperCase ();
731- return fromString (countryISO3 );
750+ return locale .getISO3Country ().toUpperCase ();
732751 } catch (final MissingResourceException ignored ) {
733- throw new IllegalArgumentException ("Parameter " + countryISO2 + " must be a valid ISO 3166-2 country code" );
752+ throw new IllegalArgumentException ("Parameter " + countryISO2 + " must be a valid ISO 3166 country code, 2 characters " );
734753 }
735754 }
736755
737756 /**
738- * Create a Territory object from a valid ISO 3166-3 country code.
757+ * Create a Territory object from a valid ISO 3166 country code, 3 characters .
739758 *
740- * @param countryISO3 ISO 3166-3 country code.
759+ * @param countryISO3 ISO 3166 country code, 3 characters .
741760 * @return Territory object for the country.
742- * @throws IllegalArgumentException Thrown if the country code is not a valid ISO 3166-3 code.
761+ * @throws IllegalArgumentException Thrown if the country code is not a valid ISO 3166 code, 3 characters .
743762 */
744763 @ Nonnull
745764 public static Territory fromCountryISO3 (@ Nonnull final String countryISO3 ) {
746765 if (!MAP_ISO3_TO_ISO2 .containsKey (countryISO3 .toUpperCase ())) {
747- throw new IllegalArgumentException ("Parameter " + countryISO3 + " must be a valid ISO 3166-3 country code" );
766+ throw new IllegalArgumentException ("Parameter " + countryISO3 + " must be a valid ISO 3166 country code, 3 characters " );
748767 }
749768 return fromString (countryISO3 );
750769 }
@@ -798,7 +817,7 @@ public String toAlphaCode(@Nonnull final AlphaCodeFormat format, @Nullable final
798817 if (index != -1 ) {
799818 assert name ().length () > (index + 1 );
800819 final String shortName = name ().substring (index + 1 );
801- if ((format == AlphaCodeFormat .MINIMAL ) || (nameMap .get (shortName ).size () == 1 )) {
820+ if ((format == AlphaCodeFormat .MINIMAL ) || (NAME_MAP .get (shortName ).size () == 1 )) {
802821 result = shortName ;
803822 }
804823 }
@@ -833,7 +852,7 @@ public boolean isSubdivision() {
833852 * @return True if this territory contains other territory subdivisions.
834853 */
835854 public boolean hasSubdivisions () {
836- return parentList .contains (this );
855+ return PARENT_LIST .contains (this );
837856 }
838857
839858 /**
@@ -880,21 +899,36 @@ public boolean hasSubdivisions() {
880899 this .fullNameAliases = (fullNameAliases == null ) ? new String []{} : fullNameAliases ;
881900 }
882901
902+ // Keep a mapping from ISO3 to ISO2 codes. This map is used to make sure valid ISO3 codes are being used.
883903 @ Nonnull
884- private static final List < Territory > codeList ;
904+ private static final Map < String , String > MAP_ISO3_TO_ISO2 ;
885905 @ Nonnull
886- private static final Map < String , List <Territory >> nameMap ;
906+ private static final List <Territory > CODE_LIST ;
887907 @ Nonnull
888- private static final List <Territory > parentList ;
908+ private static final Map <String , List <Territory >> NAME_MAP ;
909+ @ Nonnull
910+ private static final List <Territory > PARENT_LIST ;
911+
912+ static {
913+ final String [] countries = Locale .getISOCountries ();
914+ MAP_ISO3_TO_ISO2 = new HashMap <String , String >(countries .length );
915+ for (final String countryISO2 : countries ) {
916+ final String countryISO3 = new Locale ("" , countryISO2 ).getISO3Country ();
917+ MAP_ISO3_TO_ISO2 .put (countryISO3 .toUpperCase (), countryISO2 .toUpperCase ());
918+ }
919+
920+ // Add Clipperton Island (not recognized by Java).
921+ MAP_ISO3_TO_ISO2 .put ("CPT" , "CP" );
922+ }
889923
890924 /**
891925 * Static checking of the static data structures.
892926 */
893927 static {
894928 final String errorPrefix = "Initializing error: " ;
895- codeList = new ArrayList <Territory >();
896- nameMap = new HashMap <String , List <Territory >>();
897- parentList = new ArrayList <Territory >();
929+ CODE_LIST = new ArrayList <Territory >();
930+ NAME_MAP = new HashMap <String , List <Territory >>();
931+ PARENT_LIST = new ArrayList <Territory >();
898932 int min = Integer .MAX_VALUE ;
899933 int max = Integer .MIN_VALUE ;
900934 final Set <Integer > territoryNumbers = new HashSet <Integer >();
@@ -915,13 +949,13 @@ public boolean hasSubdivisions() {
915949 }
916950 territoryNumbers .add (territory .getNumber ());
917951
918- final int initialCodeListSize = codeList .size ();
952+ final int initialCodeListSize = CODE_LIST .size ();
919953 for (int i = initialCodeListSize ; i <= territory .number ; i ++) {
920- codeList .add (null );
954+ CODE_LIST .add (null );
921955 }
922- codeList .set (territory .number , territory );
923- if ((territory .parentTerritory != null ) && !parentList .contains (territory .parentTerritory )) {
924- parentList .add (territory .parentTerritory );
956+ CODE_LIST .set (territory .number , territory );
957+ if ((territory .parentTerritory != null ) && !PARENT_LIST .contains (territory .parentTerritory )) {
958+ PARENT_LIST .add (territory .parentTerritory );
925959 }
926960
927961 // Check if territory name is unique.
@@ -985,7 +1019,7 @@ private static Territory createFromString(@Nonnull final String alphaCode,
9851019 alphaCode .trim ().replace ('_' , '-' )).toUpperCase ();
9861020
9871021 // Try as alpha code.
988- final List <Territory > territories = nameMap .get (trimmed );
1022+ final List <Territory > territories = NAME_MAP .get (trimmed );
9891023 if (territories != null ) {
9901024 if (parentTerritory == null ) {
9911025 return territories .get (0 );
@@ -1065,8 +1099,8 @@ private static void addNameWithSeperatorVariants(@Nonnull final String name, @No
10651099 }
10661100
10671101 private static void addName (@ Nonnull final String name , @ Nonnull final Territory territory ) {
1068- if (nameMap .containsKey (name )) {
1069- final List <Territory > territories = nameMap .get (name );
1102+ if (NAME_MAP .containsKey (name )) {
1103+ final List <Territory > territories = NAME_MAP .get (name );
10701104
10711105 // Add child territories in the order the parents are declared.
10721106 // This results in consistent decoding of ambiguous territory names.
@@ -1098,7 +1132,7 @@ private static void addName(@Nonnull final String name, @Nonnull final Territory
10981132 } else {
10991133 final ArrayList <Territory > arrayList = new ArrayList <Territory >();
11001134 arrayList .add (territory );
1101- nameMap .put (name , arrayList );
1135+ NAME_MAP .put (name , arrayList );
11021136 }
11031137 }
11041138}
0 commit comments