/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.basics.location;
import java.io.Serializable;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.joda.convert.FromString;
import org.joda.convert.ToString;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableSet;
import com.opengamma.strata.collect.ArgChecker;
/**
* A country or territory.
* <p>
* This class represents a country or territory that it is useful to identify.
* Any two letter code may be used, however it is intended to use codes based on ISO-3166-1 alpha-2.
* <p>
* This class is immutable and thread-safe.
*/
public final class Country
implements Comparable<Country>, Serializable {
/** Serialization version. */
private static final long serialVersionUID = 1L;
/**
* A cache of instances.
*/
private static final ConcurrentMap<String, Country> CACHE = new ConcurrentHashMap<>();
/**
* The matcher for the code.
*/
private static final CharMatcher CODE_MATCHER = CharMatcher.inRange('A', 'Z');
// selected countries of Europe
/**
* The region of 'EU' - Europe (special status in ISO-3166).
*/
public static final Country EU = of("EU");
/**
* The country 'BE' - Belgium.
*/
public static final Country BE = of("BE");
/**
* The country 'CH' - Switzerland.
*/
public static final Country CH = of("CH");
/**
* The currency 'CZ' - Czech Republic.
*/
public static final Country CZ = of("CZ");
/**
* The country 'DE' - Germany.
*/
public static final Country DE = of("DE");
/**
* The country 'DK' - Denmark.
*/
public static final Country DK = of("DK");
/**
* The currency 'ES' - Spain.
*/
public static final Country ES = of("ES");
/**
* The currency 'FI' - Finland.
*/
public static final Country FI = of("FI");
/**
* The currency 'FR' - France.
*/
public static final Country FR = of("FR");
/**
* The country 'GB' - United Kingdom.
*/
public static final Country GB = of("GB");
/**
* The country 'GR' - Greece.
*/
public static final Country GR = of("GR");
/**
* The currency 'HU' = Hungary.
*/
public static final Country HU = of("HU");
/**
* The currency 'IS' - Iceland.
*/
public static final Country IS = of("IS");
/**
* The currency 'IT' - Italy.
*/
public static final Country IT = of("IT");
/**
* The currency 'LU' - Luxembourg.
*/
public static final Country LU = of("LU");
/**
* The currency 'NL' - Netherlands.
*/
public static final Country NL = of("NL");
/**
* The currency 'NO' - Norway.
*/
public static final Country NO = of("NO");
/**
* The currency 'PL' = Poland.
*/
public static final Country PL = of("PL");
/**
* The currency 'PT' - Portugal.
*/
public static final Country PT = of("PT");
/**
* The currency 'SE' - Sweden.
*/
public static final Country SE = of("SE");
/**
* The currency 'SK' - Slovakia.
*/
public static final Country SK = of("SK");
/**
* The country 'TR' - Turkey.
*/
public static final Country TR = of("TR");
// selected countries of the Americas
/**
* The country 'AR' - Argentina.
*/
public static final Country AR = of("AR");
/**
* The country 'BR' - Brazil.
*/
public static final Country BR = of("BR");
/**
* The country 'CA' - Canada.
*/
public static final Country CA = of("CA");
/**
* The country 'CL' - Chile.
*/
public static final Country CL = of("CL");
/**
* The country 'MX' - Mexico.
*/
public static final Country MX = of("MX");
/**
* The country 'US' - United States.
*/
public static final Country US = of("US");
// selected countries of the Rest of the World
/**
* The country 'AU' - Australia.
*/
public static final Country AU = of("AU");
/**
* The country 'CN' - China.
*/
public static final Country CN = of("CN");
/**
* The currency 'EG' - Egypt.
*/
public static final Country EG = of("EG");
/**
* The currency 'HK' - Hong Kong.
*/
public static final Country HK = of("HK");
/**
* The country 'ID' - Indonesia.
*/
public static final Country ID = of("ID");
/**
* The country 'IL' - Israel.
*/
public static final Country IL = of("IL");
/**
* The country 'IN' - India.
*/
public static final Country IN = of("IN");
/**
* The country 'JP' - Japan.
*/
public static final Country JP = of("JP");
/**
* The country 'KR' - South Korea.
*/
public static final Country KR = of("KR");
/**
* The country 'MY' - Malaysia.
*/
public static final Country MY = of("MY");
/**
* The country 'NZ' - New Zealand.
*/
public static final Country NZ = of("NZ");
/**
* The currency 'RU' = Russia.
*/
public static final Country RU = of("RU");
/**
* The country 'SA' - Saudi Arabia.
*/
public static final Country SA = of("SA");
/**
* The country 'SG' - Singapore.
*/
public static final Country SG = of("SG");
/**
* The country 'TH' - Thailand.
*/
public static final Country TH = of("TH");
/**
* The country 'ZA' - South Africa.
*/
public static final Country ZA = of("ZA");
/**
* The country code.
*/
private final String code;
//-------------------------------------------------------------------------
/**
* Obtains the set of available countries.
* <p>
* This contains all the countries that have been defined at the point
* that the method is called.
*
* @return an immutable set containing all registered countries
*/
public static Set<Country> getAvailableCountries() {
return ImmutableSet.copyOf(CACHE.values());
}
//-------------------------------------------------------------------------
/**
* Obtains an instance from the specified ISO-3166-1 alpha-2
* two letter country code dynamically creating a country if necessary.
* <p>
* A country is uniquely identified by ISO-3166-1 alpha-2 two letter code.
* This method creates the country if it is not known.
*
* @param countryCode the two letter country code, ASCII and upper case
* @return the singleton instance
* @throws IllegalArgumentException if the country code is invalid
*/
@FromString
public static Country of(String countryCode) {
ArgChecker.notNull(countryCode, "countryCode");
return CACHE.computeIfAbsent(countryCode, c -> addCode(c));
}
// add code
private static Country addCode(String countryCode) {
ArgChecker.matches(CODE_MATCHER, 2, 2, countryCode, "countryCode", "[A-Z][A-Z]");
return new Country(countryCode);
}
//-------------------------------------------------------------------------
/**
* Parses a string to obtain a {@code Country}.
* <p>
* The parse is identical to {@link #of(String)} except that it will convert
* letters to upper case first.
*
* @param countryCode the two letter country code, ASCII
* @return the singleton instance
* @throws IllegalArgumentException if the country code is invalid
*/
public static Country parse(String countryCode) {
ArgChecker.notNull(countryCode, "countryCode");
return of(countryCode.toUpperCase(Locale.ENGLISH));
}
//-------------------------------------------------------------------------
/**
* Restricted constructor.
*
* @param code the two letter country code
*/
private Country(String code) {
this.code = code;
}
/**
* Ensure singleton on deserialization.
*
* @return the singleton
*/
private Object readResolve() {
return Country.of(code);
}
//-------------------------------------------------------------------------
/**
* Gets the two letter ISO code.
*
* @return the two letter ISO code
*/
public String getCode() {
return code;
}
//-------------------------------------------------------------------------
/**
* Compares this country to another.
* <p>
* The comparison sorts alphabetically by the two letter country code.
*
* @param other the other country
* @return negative if less, zero if equal, positive if greater
*/
@Override
public int compareTo(Country other) {
return code.compareTo(other.code);
}
/**
* Checks if this country equals another country.
* <p>
* The comparison checks the two letter country code.
*
* @param obj the other country, null returns false
* @return true if equal
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Country other = (Country) obj;
return code.equals(other.code);
}
/**
* Returns a suitable hash code for the country.
*
* @return the hash code
*/
@Override
public int hashCode() {
return code.hashCode();
}
//-------------------------------------------------------------------------
/**
* Returns a string representation of the country, which is the two letter code.
*
* @return the two letter country code
*/
@Override
@ToString
public String toString() {
return code;
}
}